149d3bc9Richard Lowe/*
249d3bc9Richard Lowe
307dc194Richard Lowe  Copyright (C) 2000,2004,2006 Silicon Graphics, Inc.  All Rights Reserved.
407dc194Richard Lowe  Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved.
507dc194Richard Lowe  Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved.
649d3bc9Richard Lowe
749d3bc9Richard Lowe  This program is free software; you can redistribute it and/or modify it
849d3bc9Richard Lowe  under the terms of version 2.1 of the GNU Lesser General Public License
949d3bc9Richard Lowe  as published by the Free Software Foundation.
1049d3bc9Richard Lowe
1149d3bc9Richard Lowe  This program is distributed in the hope that it would be useful, but
1249d3bc9Richard Lowe  WITHOUT ANY WARRANTY; without even the implied warranty of
1349d3bc9Richard Lowe  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1449d3bc9Richard Lowe
1549d3bc9Richard Lowe  Further, this software is distributed without any warranty that it is
1649d3bc9Richard Lowe  free of the rightful claim of any third person regarding infringement
1749d3bc9Richard Lowe  or the like.  Any license provided herein, whether implied or
1849d3bc9Richard Lowe  otherwise, applies only to this software file.  Patent licenses, if
1949d3bc9Richard Lowe  any, provided herein do not apply to combinations of this program with
2049d3bc9Richard Lowe  other software, or any other product whatsoever.
2149d3bc9Richard Lowe
2249d3bc9Richard Lowe  You should have received a copy of the GNU Lesser General Public
2349d3bc9Richard Lowe  License along with this program; if not, write the Free Software
2407dc194Richard Lowe  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
2549d3bc9Richard Lowe  USA.
2649d3bc9Richard Lowe
2707dc194Richard Lowe  Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
2849d3bc9Richard Lowe  Mountain View, CA 94043, or:
2949d3bc9Richard Lowe
3049d3bc9Richard Lowe  http://www.sgi.com
3149d3bc9Richard Lowe
3249d3bc9Richard Lowe  For further information regarding this notice, see:
3349d3bc9Richard Lowe
3449d3bc9Richard Lowe  http://oss.sgi.com/projects/GenInfo/NoticeExplan
3549d3bc9Richard Lowe
3649d3bc9Richard Lowe*/
3707dc194Richard Lowe/*
3807dc194Richard Lowe   SGI has moved from the Crittenden Lane address.
3907dc194Richard Lowe*/
4007dc194Richard Lowe
4107dc194Richard Lowe
4249d3bc9Richard Lowe
4349d3bc9Richard Lowe
4449d3bc9Richard Lowe
4549d3bc9Richard Lowe#include "config.h"
4649d3bc9Richard Lowe#include "libdwarfdefs.h"
4749d3bc9Richard Lowe#include <stdio.h>
4849d3bc9Richard Lowe#include <string.h>
4949d3bc9Richard Lowe#ifdef   HAVE_ELFACCESS_H
5049d3bc9Richard Lowe#include <elfaccess.h>
5149d3bc9Richard Lowe#endif
5249d3bc9Richard Lowe#include "pro_incl.h"
5349d3bc9Richard Lowe#include "pro_section.h"
5449d3bc9Richard Lowe#include "pro_line.h"
5549d3bc9Richard Lowe#include "pro_frame.h"
5649d3bc9Richard Lowe#include "pro_die.h"
5749d3bc9Richard Lowe#include "pro_macinfo.h"
5849d3bc9Richard Lowe#include "pro_types.h"
5949d3bc9Richard Lowe
6049d3bc9Richard Lowe#ifndef SHF_MIPS_NOSTRIP
6149d3bc9Richard Lowe/* if this is not defined, we probably don't need it: just use 0 */
6249d3bc9Richard Lowe#define SHF_MIPS_NOSTRIP 0
6349d3bc9Richard Lowe#endif
6449d3bc9Richard Lowe#ifndef R_MIPS_NONE
6549d3bc9Richard Lowe#define R_MIPS_NONE 0
6649d3bc9Richard Lowe#endif
6749d3bc9Richard Lowe
6849d3bc9Richard Lowe#ifndef TRUE
6949d3bc9Richard Lowe#define TRUE 1
7049d3bc9Richard Lowe#endif
7149d3bc9Richard Lowe#ifndef FALSE
7249d3bc9Richard Lowe#define FALSE 0
7349d3bc9Richard Lowe#endif
7449d3bc9Richard Lowe
7549d3bc9Richard Lowe/* must match up with pro_section.h defines of DEBUG_INFO etc
7607dc194Richard Loweand sectnames (below).  REL_SEC_PREFIX is either ".rel" or ".rela"
7707dc194Richard Lowesee pro_incl.h
7849d3bc9Richard Lowe*/
7949d3bc9Richard Lowechar *_dwarf_rel_section_names[] = {
8007dc194Richard Lowe    REL_SEC_PREFIX ".debug_info",
8107dc194Richard Lowe    REL_SEC_PREFIX ".debug_line",
8207dc194Richard Lowe    REL_SEC_PREFIX ".debug_abbrev",     /* no relocations on this, really */
8307dc194Richard Lowe    REL_SEC_PREFIX ".debug_frame",
8407dc194Richard Lowe    REL_SEC_PREFIX ".debug_aranges",
8507dc194Richard Lowe    REL_SEC_PREFIX ".debug_pubnames",
8607dc194Richard Lowe    REL_SEC_PREFIX ".debug_str",
8707dc194Richard Lowe    REL_SEC_PREFIX ".debug_funcnames",  /* sgi extension */
8807dc194Richard Lowe    REL_SEC_PREFIX ".debug_typenames",  /* sgi extension */
8907dc194Richard Lowe    REL_SEC_PREFIX ".debug_varnames",   /* sgi extension */
9007dc194Richard Lowe    REL_SEC_PREFIX ".debug_weaknames",  /* sgi extension */
9107dc194Richard Lowe    REL_SEC_PREFIX ".debug_macinfo",
9207dc194Richard Lowe    REL_SEC_PREFIX ".debug_loc"
9349d3bc9Richard Lowe};
9449d3bc9Richard Lowe
9549d3bc9Richard Lowe/* names of sections. Ensure that it matches the defines
9649d3bc9Richard Lowe   in pro_section.h, in the same order
9749d3bc9Richard Lowe   Must match also _dwarf_rel_section_names above
9849d3bc9Richard Lowe*/
9949d3bc9Richard Lowechar *_dwarf_sectnames[] = {
10049d3bc9Richard Lowe    ".debug_info",
10149d3bc9Richard Lowe    ".debug_line",
10249d3bc9Richard Lowe    ".debug_abbrev",
10349d3bc9Richard Lowe    ".debug_frame",
10449d3bc9Richard Lowe    ".debug_aranges",
10549d3bc9Richard Lowe    ".debug_pubnames",
10649d3bc9Richard Lowe    ".debug_str",
10707dc194Richard Lowe    ".debug_funcnames",         /* sgi extension */
10807dc194Richard Lowe    ".debug_typenames",         /* sgi extension */
10907dc194Richard Lowe    ".debug_varnames",          /* sgi extension */
11007dc194Richard Lowe    ".debug_weaknames",         /* sgi extension */
11149d3bc9Richard Lowe    ".debug_macinfo",
11249d3bc9Richard Lowe    ".debug_loc"
11349d3bc9Richard Lowe};
11449d3bc9Richard Lowe
11549d3bc9Richard Lowe
11649d3bc9Richard Lowe
11749d3bc9Richard Lowe
11807dc194Richard Lowestatic Dwarf_Ubyte std_opcode_len[] = { 0,      /* DW_LNS_copy */
11907dc194Richard Lowe    1,                          /* DW_LNS_advance_pc */
12007dc194Richard Lowe    1,                          /* DW_LNS_advance_line */
12107dc194Richard Lowe    1,                          /* DW_LNS_set_file */
12207dc194Richard Lowe    1,                          /* DW_LNS_set_column */
12307dc194Richard Lowe    0,                          /* DW_LNS_negate_stmt */
12407dc194Richard Lowe    0,                          /* DW_LNS_set_basic_block */
12507dc194Richard Lowe    0,                          /* DW_LNS_const_add_pc */
12607dc194Richard Lowe    1,                          /* DW_LNS_fixed_advance_pc */
12749d3bc9Richard Lowe};
12849d3bc9Richard Lowe
12949d3bc9Richard Lowe/* struct to hold relocation entries. Its mantained as a linked
13049d3bc9Richard Lowe   list of relocation structs, and will then be written at as a
13149d3bc9Richard Lowe   whole into the relocation section. Whether its 32 bit or
13249d3bc9Richard Lowe   64 bit will be obtained from Dwarf_Debug pointer.
13349d3bc9Richard Lowe*/
13449d3bc9Richard Lowe
13549d3bc9Richard Lowetypedef struct Dwarf_P_Rel_s *Dwarf_P_Rel;
13649d3bc9Richard Lowestruct Dwarf_P_Rel_s {
13749d3bc9Richard Lowe    Dwarf_P_Rel dr_next;
13849d3bc9Richard Lowe    void *dr_rel_datap;
13949d3bc9Richard Lowe};
14049d3bc9Richard Lowetypedef struct Dwarf_P_Rel_Head_s *Dwarf_P_Rel_Head;
14149d3bc9Richard Lowestruct Dwarf_P_Rel_Head_s {
14249d3bc9Richard Lowe    struct Dwarf_P_Rel_s *drh_head;
14349d3bc9Richard Lowe    struct Dwarf_P_Rel_s *drh_tail;
14449d3bc9Richard Lowe};
14549d3bc9Richard Lowe
14649d3bc9Richard Lowestatic int _dwarf_pro_generate_debugline(Dwarf_P_Debug dbg,
14707dc194Richard Lowe                                         Dwarf_Error * error);
14849d3bc9Richard Lowestatic int _dwarf_pro_generate_debugframe(Dwarf_P_Debug dbg,
14907dc194Richard Lowe                                          Dwarf_Error * error);
15049d3bc9Richard Lowestatic int _dwarf_pro_generate_debuginfo(Dwarf_P_Debug dbg,
15107dc194Richard Lowe                                         Dwarf_Error * error);
15249d3bc9Richard Lowestatic Dwarf_P_Abbrev _dwarf_pro_getabbrev(Dwarf_P_Die, Dwarf_P_Abbrev);
15349d3bc9Richard Lowestatic int _dwarf_pro_match_attr
15449d3bc9Richard Lowe    (Dwarf_P_Attribute, Dwarf_P_Abbrev, int no_attr);
15549d3bc9Richard Lowe
15649d3bc9Richard Lowe/* these macros used as return value for below functions */
15707dc194Richard Lowe#define         OPC_INCS_ZERO           -1
15807dc194Richard Lowe#define         OPC_OUT_OF_RANGE        -2
15907dc194Richard Lowe#define         LINE_OUT_OF_RANGE       -3
16049d3bc9Richard Lowestatic int _dwarf_pro_get_opc(Dwarf_Unsigned addr_adv, int line_adv);
16149d3bc9Richard Lowe
16249d3bc9Richard Lowe
16307dc194Richard Lowe/* BEGIN_LEN_SIZE is the size of the 'length' field in total.
16407dc194Richard Lowe   Which may be 4,8, or 12 bytes!
16507dc194Richard Lowe   4 is standard DWARF2.
16607dc194Richard Lowe   8 is non-standard MIPS-IRIX 64-bit.
16707dc194Richard Lowe   12 is standard DWARF3 for 64 bit offsets.
16807dc194Richard Lowe   Used in various routines: local variable names
16907dc194Richard Lowe   must match the names here.
17007dc194Richard Lowe*/
17107dc194Richard Lowe#define BEGIN_LEN_SIZE (uwordb_size + extension_size)
17249d3bc9Richard Lowe
17349d3bc9Richard Lowe/*
17407dc194Richard Lowe        Return TRUE if we need the section, FALSE otherwise
17549d3bc9Richard Lowe
17649d3bc9Richard Lowe        If any of the 'line-data-related' calls were made
17749d3bc9Richard Lowe        including file or directory entries,
17849d3bc9Richard Lowe        produce .debug_line .
17949d3bc9Richard Lowe
18049d3bc9Richard Lowe*/
18149d3bc9Richard Lowestatic int
18249d3bc9Richard Lowedwarf_need_debug_line_section(Dwarf_P_Debug dbg)
18349d3bc9Richard Lowe{
18449d3bc9Richard Lowe    if (dbg->de_lines == NULL && dbg->de_file_entries == NULL
18507dc194Richard Lowe        && dbg->de_inc_dirs == NULL) {
18607dc194Richard Lowe        return FALSE;
18749d3bc9Richard Lowe    }
18849d3bc9Richard Lowe    return TRUE;
18949d3bc9Richard Lowe}
19049d3bc9Richard Lowe
19149d3bc9Richard Lowe/*
19249d3bc9Richard Lowe    Convert debug information to  a format such that
19349d3bc9Richard Lowe    it can be written on disk.
19449d3bc9Richard Lowe    Called exactly once per execution.
19549d3bc9Richard Lowe*/
19649d3bc9Richard LoweDwarf_Signed
19749d3bc9Richard Lowedwarf_transform_to_disk_form(Dwarf_P_Debug dbg, Dwarf_Error * error)
19849d3bc9Richard Lowe{
19949d3bc9Richard Lowe    /*
20049d3bc9Richard Lowe       Section data in written out in a number of buffers. Each
20149d3bc9Richard Lowe       _generate_*() function returns a cumulative count of buffers for
20207dc194Richard Lowe       all the sections. get_section_bytes() returns pointers to these
20349d3bc9Richard Lowe       buffers one at a time. */
20407dc194Richard Lowe    int nbufs = 0;
20507dc194Richard Lowe    int sect = 0;
20607dc194Richard Lowe    int err = 0;
20707dc194Richard Lowe    Dwarf_Unsigned du = 0;
20849d3bc9Richard Lowe
20949d3bc9Richard Lowe    if (dbg->de_version_magic_number != PRO_VERSION_MAGIC) {
21007dc194Richard Lowe        DWARF_P_DBG_ERROR(dbg, DW_DLE_IA, DW_DLV_NOCOUNT);
21149d3bc9Richard Lowe    }
21249d3bc9Richard Lowe
21349d3bc9Richard Lowe    /* Create dwarf section headers */
21449d3bc9Richard Lowe    for (sect = 0; sect < NUM_DEBUG_SECTIONS; sect++) {
21507dc194Richard Lowe        long flags = 0;
21607dc194Richard Lowe
21707dc194Richard Lowe        switch (sect) {
21807dc194Richard Lowe
21907dc194Richard Lowe        case DEBUG_INFO:
22007dc194Richard Lowe            if (dbg->de_dies == NULL)
22107dc194Richard Lowe                continue;
22207dc194Richard Lowe            break;
22307dc194Richard Lowe
22407dc194Richard Lowe        case DEBUG_LINE:
22507dc194Richard Lowe            if (dwarf_need_debug_line_section(dbg) == FALSE) {
22607dc194Richard Lowe                continue;
22707dc194Richard Lowe            }
22807dc194Richard Lowe            break;
22907dc194Richard Lowe
23007dc194Richard Lowe        case DEBUG_ABBREV:
23107dc194Richard Lowe            if (dbg->de_dies == NULL)
23207dc194Richard Lowe                continue;
23307dc194Richard Lowe            break;
23407dc194Richard Lowe
23507dc194Richard Lowe        case DEBUG_FRAME:
23607dc194Richard Lowe            if (dbg->de_frame_cies == NULL)
23707dc194Richard Lowe                continue;
23807dc194Richard Lowe            flags = SHF_MIPS_NOSTRIP;
23907dc194Richard Lowe            break;
24007dc194Richard Lowe
24107dc194Richard Lowe        case DEBUG_ARANGES:
24207dc194Richard Lowe            if (dbg->de_arange == NULL)
24307dc194Richard Lowe                continue;
24407dc194Richard Lowe            break;
24507dc194Richard Lowe
24607dc194Richard Lowe        case DEBUG_PUBNAMES:
24707dc194Richard Lowe            if (dbg->de_simple_name_headers[dwarf_snk_pubname].
24807dc194Richard Lowe                sn_head == NULL)
24907dc194Richard Lowe                continue;
25007dc194Richard Lowe            break;
25107dc194Richard Lowe
25207dc194Richard Lowe        case DEBUG_STR:
25307dc194Richard Lowe            if (dbg->de_strings == NULL)
25407dc194Richard Lowe                continue;
25507dc194Richard Lowe            break;
25607dc194Richard Lowe
25707dc194Richard Lowe        case DEBUG_FUNCNAMES:
25807dc194Richard Lowe            if (dbg->de_simple_name_headers[dwarf_snk_funcname].
25907dc194Richard Lowe                sn_head == NULL)
26007dc194Richard Lowe                continue;
26107dc194Richard Lowe            break;
26207dc194Richard Lowe
26307dc194Richard Lowe        case DEBUG_TYPENAMES:
26407dc194Richard Lowe            if (dbg->de_simple_name_headers[dwarf_snk_typename].
26507dc194Richard Lowe                sn_head == NULL)
26607dc194Richard Lowe                continue;
26707dc194Richard Lowe            break;
26807dc194Richard Lowe
26907dc194Richard Lowe        case DEBUG_VARNAMES:
27007dc194Richard Lowe            if (dbg->de_simple_name_headers[dwarf_snk_varname].
27107dc194Richard Lowe                sn_head == NULL)
27207dc194Richard Lowe                continue;
27307dc194Richard Lowe            break;
27407dc194Richard Lowe
27507dc194Richard Lowe        case DEBUG_WEAKNAMES:
27607dc194Richard Lowe            if (dbg->de_simple_name_headers[dwarf_snk_weakname].
27707dc194Richard Lowe                sn_head == NULL)
27807dc194Richard Lowe                continue;
27907dc194Richard Lowe            break;
28007dc194Richard Lowe
28107dc194Richard Lowe        case DEBUG_MACINFO:
28207dc194Richard Lowe            if (dbg->de_first_macinfo == NULL)
28307dc194Richard Lowe                continue;
28407dc194Richard Lowe            break;
28507dc194Richard Lowe        case DEBUG_LOC:
28607dc194Richard Lowe            /* not handled yet */
28707dc194Richard Lowe            continue;
28807dc194Richard Lowe        default:
28907dc194Richard Lowe            /* logic error: missing a case */
29007dc194Richard Lowe            DWARF_P_DBG_ERROR(dbg, DW_DLE_ELF_SECT_ERR, DW_DLV_NOCOUNT);
29107dc194Richard Lowe        }
29207dc194Richard Lowe        {
29307dc194Richard Lowe            int new_base_elf_sect;
29407dc194Richard Lowe
29507dc194Richard Lowe            if (dbg->de_callback_func_b) {
29607dc194Richard Lowe                new_base_elf_sect =
29707dc194Richard Lowe                    dbg->de_callback_func_b(_dwarf_sectnames[sect],
29807dc194Richard Lowe                        /* rec size */ 1,
29907dc194Richard Lowe                        SECTION_TYPE,
30007dc194Richard Lowe                        flags, SHN_UNDEF, 0, &du, &err);
30107dc194Richard Lowe
30207dc194Richard Lowe            } else {
30307dc194Richard Lowe                int name_idx = 0;
30407dc194Richard Lowe                new_base_elf_sect = dbg->de_callback_func(
30507dc194Richard Lowe                    _dwarf_sectnames[sect],
30607dc194Richard Lowe                    dbg->de_relocation_record_size,
30707dc194Richard Lowe                    SECTION_TYPE, flags,
30807dc194Richard Lowe                    SHN_UNDEF, 0,
30907dc194Richard Lowe                    &name_idx, &err);
31007dc194Richard Lowe                du = name_idx;
31107dc194Richard Lowe            }
31207dc194Richard Lowe            if (new_base_elf_sect == -1) {
31307dc194Richard Lowe                DWARF_P_DBG_ERROR(dbg, DW_DLE_ELF_SECT_ERR,
31407dc194Richard Lowe                                  DW_DLV_NOCOUNT);
31507dc194Richard Lowe            }
31607dc194Richard Lowe            dbg->de_elf_sects[sect] = new_base_elf_sect;
31707dc194Richard Lowe
31807dc194Richard Lowe            dbg->de_sect_name_idx[sect] = du;
31907dc194Richard Lowe        }
32049d3bc9Richard Lowe    }
32149d3bc9Richard Lowe
32249d3bc9Richard Lowe    nbufs = 0;
32349d3bc9Richard Lowe
32449d3bc9Richard Lowe    /*
32507dc194Richard Lowe       Changing the order in which the sections are generated may cause
32607dc194Richard Lowe       problems because of relocations. */
32749d3bc9Richard Lowe
32849d3bc9Richard Lowe    if (dwarf_need_debug_line_section(dbg) == TRUE) {
32907dc194Richard Lowe        nbufs = _dwarf_pro_generate_debugline(dbg, error);
33007dc194Richard Lowe        if (nbufs < 0) {
33107dc194Richard Lowe            DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGLINE_ERROR,
33207dc194Richard Lowe                              DW_DLV_NOCOUNT);
33307dc194Richard Lowe        }
33449d3bc9Richard Lowe    }
33549d3bc9Richard Lowe
33649d3bc9Richard Lowe    if (dbg->de_frame_cies) {
33707dc194Richard Lowe        nbufs = _dwarf_pro_generate_debugframe(dbg, error);
33807dc194Richard Lowe        if (nbufs < 0) {
33907dc194Richard Lowe            DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGFRAME_ERROR,
34007dc194Richard Lowe                              DW_DLV_NOCOUNT);
34107dc194Richard Lowe        }
34249d3bc9Richard Lowe    }
34349d3bc9Richard Lowe    if (dbg->de_first_macinfo) {
34407dc194Richard Lowe        nbufs = _dwarf_pro_transform_macro_info_to_disk(dbg, error);
34507dc194Richard Lowe        if (nbufs < 0) {
34607dc194Richard Lowe            DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGMACINFO_ERROR,
34707dc194Richard Lowe                              DW_DLV_NOCOUNT);
34807dc194Richard Lowe        }
34949d3bc9Richard Lowe    }
35049d3bc9Richard Lowe
35149d3bc9Richard Lowe    if (dbg->de_dies) {
35207dc194Richard Lowe        nbufs = _dwarf_pro_generate_debuginfo(dbg, error);
35307dc194Richard Lowe        if (nbufs < 0) {
35407dc194Richard Lowe            DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
35507dc194Richard Lowe                              DW_DLV_NOCOUNT);
35607dc194Richard Lowe        }
35749d3bc9Richard Lowe    }
35849d3bc9Richard Lowe
35949d3bc9Richard Lowe    if (dbg->de_arange) {
36007dc194Richard Lowe        nbufs = _dwarf_transform_arange_to_disk(dbg, error);
36107dc194Richard Lowe        if (nbufs < 0) {
36207dc194Richard Lowe            DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
36307dc194Richard Lowe                              DW_DLV_NOCOUNT);
36407dc194Richard Lowe        }
36549d3bc9Richard Lowe    }
36649d3bc9Richard Lowe
36749d3bc9Richard Lowe    if (dbg->de_simple_name_headers[dwarf_snk_pubname].sn_head) {
36807dc194Richard Lowe        nbufs = _dwarf_transform_simplename_to_disk(dbg,
36907dc194Richard Lowe                                                    dwarf_snk_pubname,
37007dc194Richard Lowe                                                    DEBUG_PUBNAMES,
37107dc194Richard Lowe                                                    error);
37249d3bc9Richard Lowe
37349d3bc9Richard Lowe
37407dc194Richard Lowe        if (nbufs < 0) {
37507dc194Richard Lowe            DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
37607dc194Richard Lowe                              DW_DLV_NOCOUNT);
37707dc194Richard Lowe        }
37849d3bc9Richard Lowe    }
37949d3bc9Richard Lowe
38049d3bc9Richard Lowe    if (dbg->de_simple_name_headers[dwarf_snk_funcname].sn_head) {
38107dc194Richard Lowe        nbufs = _dwarf_transform_simplename_to_disk(dbg,
38207dc194Richard Lowe                                                    dwarf_snk_funcname,
38307dc194Richard Lowe                                                    DEBUG_FUNCNAMES,
38407dc194Richard Lowe                                                    error);
38507dc194Richard Lowe        if (nbufs < 0) {
38607dc194Richard Lowe            DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
38707dc194Richard Lowe                              DW_DLV_NOCOUNT);
38807dc194Richard Lowe        }
38949d3bc9Richard Lowe    }
39049d3bc9Richard Lowe
39149d3bc9Richard Lowe    if (dbg->de_simple_name_headers[dwarf_snk_typename].sn_head) {
39207dc194Richard Lowe        nbufs = _dwarf_transform_simplename_to_disk(dbg,
39307dc194Richard Lowe                                                    dwarf_snk_typename,
39407dc194Richard Lowe                                                    DEBUG_TYPENAMES,
39507dc194Richard Lowe                                                    error);
39607dc194Richard Lowe        if (nbufs < 0) {
39707dc194Richard Lowe            DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
39807dc194Richard Lowe                              DW_DLV_NOCOUNT);
39907dc194Richard Lowe        }
40049d3bc9Richard Lowe    }
40149d3bc9Richard Lowe
40249d3bc9Richard Lowe    if (dbg->de_simple_name_headers[dwarf_snk_varname].sn_head) {
40307dc194Richard Lowe        nbufs = _dwarf_transform_simplename_to_disk(dbg,
40407dc194Richard Lowe                                                    dwarf_snk_varname,
40507dc194Richard Lowe                                                    DEBUG_VARNAMES,
40607dc194Richard Lowe                                                    error);
40707dc194Richard Lowe
40807dc194Richard Lowe        if (nbufs < 0) {
40907dc194Richard Lowe            DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
41007dc194Richard Lowe                              DW_DLV_NOCOUNT);
41107dc194Richard Lowe        }
41249d3bc9Richard Lowe    }
41349d3bc9Richard Lowe
41449d3bc9Richard Lowe    if (dbg->de_simple_name_headers[dwarf_snk_weakname].sn_head) {
41507dc194Richard Lowe        nbufs = _dwarf_transform_simplename_to_disk(dbg,
41607dc194Richard Lowe            dwarf_snk_weakname, DEBUG_WEAKNAMES, error);
41707dc194Richard Lowe        if (nbufs < 0) {
41807dc194Richard Lowe            DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
41907dc194Richard Lowe                              DW_DLV_NOCOUNT);
42007dc194Richard Lowe        }
42149d3bc9Richard Lowe    }
42249d3bc9Richard Lowe
42349d3bc9Richard Lowe    {
42407dc194Richard Lowe        Dwarf_Signed new_secs = 0;
42507dc194Richard Lowe        int res = 0;
42607dc194Richard Lowe
42707dc194Richard Lowe        res = dbg->de_transform_relocs_to_disk(dbg, &new_secs);
42807dc194Richard Lowe        if (res != DW_DLV_OK) {
42907dc194Richard Lowe            DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
43007dc194Richard Lowe                              DW_DLV_NOCOUNT);
43107dc194Richard Lowe        }
43207dc194Richard Lowe        nbufs += new_secs;
43349d3bc9Richard Lowe    }
43449d3bc9Richard Lowe    return nbufs;
43549d3bc9Richard Lowe}
43649d3bc9Richard Lowe
43749d3bc9Richard Lowe
43849d3bc9Richard Lowe/*---------------------------------------------------------------
43907dc194Richard Lowe        Generate debug_line section
44049d3bc9Richard Lowe---------------------------------------------------------------*/
44149d3bc9Richard Lowestatic int
44249d3bc9Richard Lowe_dwarf_pro_generate_debugline(Dwarf_P_Debug dbg, Dwarf_Error * error)
44349d3bc9Richard Lowe{
44407dc194Richard Lowe    Dwarf_P_Inc_Dir curdir = 0;
44507dc194Richard Lowe    Dwarf_P_F_Entry curentry = 0;
44607dc194Richard Lowe    Dwarf_P_Line curline = 0;
44707dc194Richard Lowe    Dwarf_P_Line prevline = 0;
44849d3bc9Richard Lowe
44949d3bc9Richard Lowe    /* all data named cur* are used to loop thru linked lists */
45049d3bc9Richard Lowe
45107dc194Richard Lowe    int sum_bytes = 0;
45207dc194Richard Lowe    int prolog_size = 0;
45307dc194Richard Lowe    unsigned char *data = 0;    /* holds disk form data */
45407dc194Richard Lowe    int elfsectno = 0;
45507dc194Richard Lowe    unsigned char *start_line_sec = 0;  /* pointer to the buffer at
45607dc194Richard Lowe                                           section start */
45749d3bc9Richard Lowe    /* temps for memcpy */
45807dc194Richard Lowe    Dwarf_Unsigned du = 0;
45907dc194Richard Lowe    Dwarf_Ubyte db = 0;
46007dc194Richard Lowe    Dwarf_Half dh = 0;
46107dc194Richard Lowe    int res = 0;
46249d3bc9Richard Lowe    int uwordb_size = dbg->de_offset_size;
46349d3bc9Richard Lowe    int extension_size = dbg->de_64bit_extension ? 4 : 0;
46449d3bc9Richard Lowe    int upointer_size = dbg->de_pointer_size;
46549d3bc9Richard Lowe    char buff1[ENCODE_SPACE_NEEDED];
46649d3bc9Richard Lowe
46749d3bc9Richard Lowe
46807dc194Richard Lowe
46949d3bc9Richard Lowe    sum_bytes = 0;
47049d3bc9Richard Lowe
47149d3bc9Richard Lowe    elfsectno = dbg->de_elf_sects[DEBUG_LINE];
47249d3bc9Richard Lowe
47349d3bc9Richard Lowe    /* include directories */
47449d3bc9Richard Lowe    curdir = dbg->de_inc_dirs;
47549d3bc9Richard Lowe    while (curdir) {
47607dc194Richard Lowe        prolog_size += strlen(curdir->did_name) + 1;
47707dc194Richard Lowe        curdir = curdir->did_next;
47849d3bc9Richard Lowe    }
47907dc194Richard Lowe    prolog_size++;              /* last null following last directory
48007dc194Richard Lowe                                   entry. */
48149d3bc9Richard Lowe
48249d3bc9Richard Lowe    /* file entries */
48349d3bc9Richard Lowe    curentry = dbg->de_file_entries;
48449d3bc9Richard Lowe    while (curentry) {
48507dc194Richard Lowe        prolog_size +=
48607dc194Richard Lowe            strlen(curentry->dfe_name) + 1 + curentry->dfe_nbytes;
48707dc194Richard Lowe        curentry = curentry->dfe_next;
48849d3bc9Richard Lowe    }
48907dc194Richard Lowe    prolog_size++;              /* last null byte */
49049d3bc9Richard Lowe
49149d3bc9Richard Lowe
49207dc194Richard Lowe    prolog_size += BEGIN_LEN_SIZE + sizeof_uhalf(dbg) + /* version # */
49307dc194Richard Lowe        uwordb_size +           /* header length */
49407dc194Richard Lowe        sizeof_ubyte(dbg) +     /* min_instr length */
49507dc194Richard Lowe        sizeof_ubyte(dbg) +     /* default is_stmt */
49607dc194Richard Lowe        sizeof_ubyte(dbg) +     /* linebase */
49707dc194Richard Lowe        sizeof_ubyte(dbg) +     /* linerange */
49807dc194Richard Lowe        sizeof_ubyte(dbg);      /* opcode base */
49949d3bc9Richard Lowe
50049d3bc9Richard Lowe    /* length of table specifying # of opnds */
50149d3bc9Richard Lowe    prolog_size += sizeof(std_opcode_len);
50249d3bc9Richard Lowe
50349d3bc9Richard Lowe    GET_CHUNK(dbg, elfsectno, data, prolog_size, error);
50449d3bc9Richard Lowe    start_line_sec = data;
50549d3bc9Richard Lowe
50649d3bc9Richard Lowe    /* copy over the data */
50749d3bc9Richard Lowe    /* total_length */
50849d3bc9Richard Lowe    du = 0;
50949d3bc9Richard Lowe    if (extension_size) {
51007dc194Richard Lowe        Dwarf_Word x = DISTINGUISHED_VALUE;
51149d3bc9Richard Lowe
51207dc194Richard Lowe        WRITE_UNALIGNED(dbg, (void *) data, (const void *) &x,
51307dc194Richard Lowe                        sizeof(x), extension_size);
51407dc194Richard Lowe        data += extension_size;
51549d3bc9Richard Lowe    }
51649d3bc9Richard Lowe
51749d3bc9Richard Lowe    WRITE_UNALIGNED(dbg, (void *) data, (const void *) &du,
51807dc194Richard Lowe                    sizeof(du), uwordb_size);
51949d3bc9Richard Lowe    data += uwordb_size;
52049d3bc9Richard Lowe
52149d3bc9Richard Lowe    dh = VERSION;
52249d3bc9Richard Lowe    WRITE_UNALIGNED(dbg, (void *) data, (const void *) &dh,
52307dc194Richard Lowe                    sizeof(dh), sizeof(Dwarf_Half));
52449d3bc9Richard Lowe    data += sizeof(Dwarf_Half);
52549d3bc9Richard Lowe
52607dc194Richard Lowe    /* header length */
52707dc194Richard Lowe    du = prolog_size - (BEGIN_LEN_SIZE + sizeof(Dwarf_Half) +
52807dc194Richard Lowe                        uwordb_size);
52949d3bc9Richard Lowe    {
53007dc194Richard Lowe        WRITE_UNALIGNED(dbg, (void *) data, (const void *) &du,
53107dc194Richard Lowe                        sizeof(du), uwordb_size);
53207dc194Richard Lowe        data += uwordb_size;
53349d3bc9Richard Lowe    }
53449d3bc9Richard Lowe    db = MIN_INST_LENGTH;
53549d3bc9Richard Lowe    WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
53607dc194Richard Lowe                    sizeof(db), sizeof(Dwarf_Ubyte));
53749d3bc9Richard Lowe    data += sizeof(Dwarf_Ubyte);
53849d3bc9Richard Lowe    db = DEFAULT_IS_STMT;
53949d3bc9Richard Lowe    WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
54007dc194Richard Lowe                    sizeof(db), sizeof(Dwarf_Ubyte));
54149d3bc9Richard Lowe    data += sizeof(Dwarf_Ubyte);
54249d3bc9Richard Lowe    db = (Dwarf_Ubyte) LINE_BASE;
54349d3bc9Richard Lowe    WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
54407dc194Richard Lowe                    sizeof(db), sizeof(Dwarf_Ubyte));
54549d3bc9Richard Lowe    data += sizeof(Dwarf_Ubyte);
54649d3bc9Richard Lowe    db = LINE_RANGE;
54749d3bc9Richard Lowe    WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
54807dc194Richard Lowe                    sizeof(db), sizeof(Dwarf_Ubyte));
54949d3bc9Richard Lowe    data += sizeof(Dwarf_Ubyte);
55049d3bc9Richard Lowe    db = OPCODE_BASE;
55149d3bc9Richard Lowe    WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
55207dc194Richard Lowe                    sizeof(db), sizeof(Dwarf_Ubyte));
55349d3bc9Richard Lowe    data += sizeof(Dwarf_Ubyte);
55449d3bc9Richard Lowe    WRITE_UNALIGNED(dbg, (void *) data, (const void *) std_opcode_len,
55507dc194Richard Lowe                    sizeof(std_opcode_len), sizeof(std_opcode_len));
55649d3bc9Richard Lowe    data += sizeof(std_opcode_len);
55749d3bc9Richard Lowe
55849d3bc9Richard Lowe    /* copy over include directories */
55949d3bc9Richard Lowe    curdir = dbg->de_inc_dirs;
56049d3bc9Richard Lowe    while (curdir) {
56107dc194Richard Lowe        strcpy((char *) data, curdir->did_name);
56207dc194Richard Lowe        data += strlen(curdir->did_name) + 1;
56307dc194Richard Lowe        curdir = curdir->did_next;
56449d3bc9Richard Lowe    }
56507dc194Richard Lowe    *data = '\0';               /* last null */
56649d3bc9Richard Lowe    data++;
56749d3bc9Richard Lowe
56849d3bc9Richard Lowe    /* copy file entries */
56949d3bc9Richard Lowe    curentry = dbg->de_file_entries;
57049d3bc9Richard Lowe    while (curentry) {
57107dc194Richard Lowe        strcpy((char *) data, curentry->dfe_name);
57207dc194Richard Lowe        data += strlen(curentry->dfe_name) + 1;
57307dc194Richard Lowe        /* copies of leb numbers, no endian issues */
57407dc194Richard Lowe        memcpy((void *) data,
57507dc194Richard Lowe               (const void *) curentry->dfe_args, curentry->dfe_nbytes);
57607dc194Richard Lowe        data += curentry->dfe_nbytes;
57707dc194Richard Lowe        curentry = curentry->dfe_next;
57849d3bc9Richard Lowe    }
57949d3bc9Richard Lowe    *data = '\0';
58049d3bc9Richard Lowe    data++;
58149d3bc9Richard Lowe
58249d3bc9Richard Lowe    sum_bytes += prolog_size;
58349d3bc9Richard Lowe
58449d3bc9Richard Lowe    curline = dbg->de_lines;
58549d3bc9Richard Lowe    prevline = (Dwarf_P_Line)
58607dc194Richard Lowe        _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Line_s));
58749d3bc9Richard Lowe    if (prevline == NULL) {
58807dc194Richard Lowe        DWARF_P_DBG_ERROR(dbg, DW_DLE_LINE_ALLOC, -1);
58949d3bc9Richard Lowe    }
59049d3bc9Richard Lowe    _dwarf_pro_reg_init(prevline);
59149d3bc9Richard Lowe    /* generate opcodes for line numbers */
59249d3bc9Richard Lowe    while (curline) {
59307dc194Richard Lowe        int nbytes;
59407dc194Richard Lowe        char *arg;
59507dc194Richard Lowe        int opc;
59607dc194Richard Lowe        int no_lns_copy;        /* if lns copy opcode doesnt need to be
59707dc194Richard Lowe                                   generated, if special opcode or end
59807dc194Richard Lowe                                   sequence */
59907dc194Richard Lowe        Dwarf_Unsigned addr_adv;
60007dc194Richard Lowe        int line_adv;           /* supposed to be a reasonably small
60107dc194Richard Lowe                                   number, so the size should not be a
60207dc194Richard Lowe                                   problem. ? */
60307dc194Richard Lowe
60407dc194Richard Lowe        no_lns_copy = 0;
60507dc194Richard Lowe        if (curline->dpl_opc != 0) {
60607dc194Richard Lowe            int inst_bytes;     /* no of bytes in extended opcode */
60707dc194Richard Lowe            char *str;          /* hold leb encoded inst_bytes */
60807dc194Richard Lowe            int str_nbytes;     /* no of bytes in str */
60907dc194Richard Lowe
61007dc194Richard Lowe            switch (curline->dpl_opc) {
61107dc194Richard Lowe            case DW_LNE_end_sequence:
61207dc194Richard Lowe
61307dc194Richard Lowe                /* Advance pc to end of text section. */
61407dc194Richard Lowe                addr_adv = curline->dpl_address - prevline->dpl_address;
61507dc194Richard Lowe                if (addr_adv > 0) {
61607dc194Richard Lowe                    db = DW_LNS_advance_pc;
61707dc194Richard Lowe                    res =
61807dc194Richard Lowe                        _dwarf_pro_encode_leb128_nm(addr_adv /
61907dc194Richard Lowe                                                    MIN_INST_LENGTH,
62007dc194Richard Lowe                                                    &nbytes, buff1,
62107dc194Richard Lowe                                                    sizeof(buff1));
62207dc194Richard Lowe                    if (res != DW_DLV_OK) {
62307dc194Richard Lowe                        DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
62407dc194Richard Lowe                    }
62507dc194Richard Lowe                    GET_CHUNK(dbg, elfsectno, data,
62607dc194Richard Lowe                              nbytes + sizeof(Dwarf_Ubyte), error);
62707dc194Richard Lowe                    WRITE_UNALIGNED(dbg, (void *) data,
62807dc194Richard Lowe                                    (const void *) &db, sizeof(db),
62907dc194Richard Lowe                                    sizeof(Dwarf_Ubyte));
63007dc194Richard Lowe                    data += sizeof(Dwarf_Ubyte);
63107dc194Richard Lowe                    /* leb, no endianness issue */
63207dc194Richard Lowe                    memcpy((void *) data, (const void *) buff1, nbytes);
63307dc194Richard Lowe                    data += nbytes + sizeof(Dwarf_Ubyte);
63407dc194Richard Lowe                    sum_bytes += nbytes + sizeof(Dwarf_Ubyte);
63507dc194Richard Lowe                    prevline->dpl_address = curline->dpl_address;
63607dc194Richard Lowe                }
63707dc194Richard Lowe
63807dc194Richard Lowe                /* first null byte */
63907dc194Richard Lowe                db = 0;
64007dc194Richard Lowe                GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte),
64107dc194Richard Lowe                          error);
64207dc194Richard Lowe                WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
64307dc194Richard Lowe                                sizeof(db), sizeof(Dwarf_Ubyte));
64407dc194Richard Lowe                data += sizeof(Dwarf_Ubyte);
64507dc194Richard Lowe                sum_bytes += sizeof(Dwarf_Ubyte);
64607dc194Richard Lowe
64707dc194Richard Lowe                /* write length of extended opcode */
64807dc194Richard Lowe                inst_bytes = sizeof(Dwarf_Ubyte);
64907dc194Richard Lowe                res =
65007dc194Richard Lowe                    _dwarf_pro_encode_leb128_nm(inst_bytes, &str_nbytes,
65107dc194Richard Lowe                                                buff1, sizeof(buff1));
65207dc194Richard Lowe                if (res != DW_DLV_OK) {
65307dc194Richard Lowe                    DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
65407dc194Richard Lowe                }
65507dc194Richard Lowe                GET_CHUNK(dbg, elfsectno, data, str_nbytes, error);
65607dc194Richard Lowe                memcpy((void *) data, (const void *) buff1, str_nbytes);
65707dc194Richard Lowe                data += str_nbytes;
65807dc194Richard Lowe                sum_bytes += str_nbytes;
65907dc194Richard Lowe
66007dc194Richard Lowe                /* write extended opcode */
66107dc194Richard Lowe                db = DW_LNE_end_sequence;
66207dc194Richard Lowe                GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte),
66307dc194Richard Lowe                          error);
66407dc194Richard Lowe                WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
66507dc194Richard Lowe                                sizeof(db), sizeof(Dwarf_Ubyte));
66607dc194Richard Lowe                data += sizeof(Dwarf_Ubyte);
66707dc194Richard Lowe                sum_bytes += sizeof(Dwarf_Ubyte);
66807dc194Richard Lowe                /* reset value to original values */
66907dc194Richard Lowe                _dwarf_pro_reg_init(prevline);
67007dc194Richard Lowe                no_lns_copy = 1;
67107dc194Richard Lowe                /* this is set only for end_sequence, so that a
67207dc194Richard Lowe                   dw_lns_copy is not generated */
67307dc194Richard Lowe                break;
67407dc194Richard Lowe
67507dc194Richard Lowe            case DW_LNE_set_address:
67607dc194Richard Lowe
67707dc194Richard Lowe                /* first null byte */
67807dc194Richard Lowe                db = 0;
67907dc194Richard Lowe                GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte),
68007dc194Richard Lowe                          error);
68107dc194Richard Lowe                WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
68207dc194Richard Lowe                                sizeof(db), sizeof(Dwarf_Ubyte));
68307dc194Richard Lowe                data += sizeof(Dwarf_Ubyte);
68407dc194Richard Lowe                sum_bytes += sizeof(Dwarf_Ubyte);
68507dc194Richard Lowe
68607dc194Richard Lowe                /* write length of extended opcode */
68707dc194Richard Lowe                inst_bytes = sizeof(Dwarf_Ubyte) + upointer_size;
68807dc194Richard Lowe                res =
68907dc194Richard Lowe                    _dwarf_pro_encode_leb128_nm(inst_bytes, &str_nbytes,
69007dc194Richard Lowe                                                buff1, sizeof(buff1));
69107dc194Richard Lowe                if (res != DW_DLV_OK) {
69207dc194Richard Lowe                    DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
69307dc194Richard Lowe                }
69407dc194Richard Lowe                GET_CHUNK(dbg, elfsectno, data, str_nbytes, error);
69507dc194Richard Lowe                str = buff1;
69607dc194Richard Lowe                /* leb number, no endian issue */
69707dc194Richard Lowe                memcpy((void *) data, (const void *) str, str_nbytes);
69807dc194Richard Lowe                data += str_nbytes;
69907dc194Richard Lowe                sum_bytes += str_nbytes;
70007dc194Richard Lowe
70107dc194Richard Lowe                /* write extended opcode */
70207dc194Richard Lowe                db = DW_LNE_set_address;
70307dc194Richard Lowe                GET_CHUNK(dbg, elfsectno, data, upointer_size +
70407dc194Richard Lowe                          sizeof(Dwarf_Ubyte), error);
70507dc194Richard Lowe                WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
70607dc194Richard Lowe                                sizeof(db), sizeof(Dwarf_Ubyte));
70707dc194Richard Lowe                data += sizeof(Dwarf_Ubyte);
70807dc194Richard Lowe                sum_bytes += sizeof(Dwarf_Ubyte);
70907dc194Richard Lowe
71007dc194Richard Lowe                /* reloc for address */
71107dc194Richard Lowe                res = dbg->de_reloc_name(dbg, DEBUG_LINE,
71207dc194Richard Lowe                    sum_bytes,  /* r_offset  */
71307dc194Richard Lowe                    curline->dpl_r_symidx,
71407dc194Richard Lowe                    dwarf_drt_data_reloc,
71507dc194Richard Lowe                    uwordb_size);
71607dc194Richard Lowe                if (res != DW_DLV_OK) {
71707dc194Richard Lowe                    DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
71807dc194Richard Lowe                }
71907dc194Richard Lowe
72007dc194Richard Lowe                /* write offset (address) */
72107dc194Richard Lowe                du = curline->dpl_address;
72207dc194Richard Lowe                WRITE_UNALIGNED(dbg, (void *) data, (const void *) &du,
72307dc194Richard Lowe                                sizeof(du), upointer_size);
72407dc194Richard Lowe                data += upointer_size;
72507dc194Richard Lowe                sum_bytes += upointer_size;
72607dc194Richard Lowe                prevline->dpl_address = curline->dpl_address;
72707dc194Richard Lowe                no_lns_copy = 1;
72807dc194Richard Lowe                break;
72907dc194Richard Lowe            }
73007dc194Richard Lowe        } else {
73107dc194Richard Lowe            if (curline->dpl_file != prevline->dpl_file) {
73207dc194Richard Lowe                db = DW_LNS_set_file;
73307dc194Richard Lowe                res =
73407dc194Richard Lowe                    _dwarf_pro_encode_leb128_nm(curline->dpl_file,
73507dc194Richard Lowe                                                &nbytes, buff1,
73607dc194Richard Lowe                                                sizeof(buff1));
73707dc194Richard Lowe                if (res != DW_DLV_OK) {
73807dc194Richard Lowe                    DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
73907dc194Richard Lowe                }
74007dc194Richard Lowe                arg = buff1;
74107dc194Richard Lowe                GET_CHUNK(dbg, elfsectno, data,
74207dc194Richard Lowe                          nbytes + sizeof(Dwarf_Ubyte), error);
74307dc194Richard Lowe                WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
74407dc194Richard Lowe                                sizeof(db), sizeof(Dwarf_Ubyte));
74507dc194Richard Lowe                data += sizeof(Dwarf_Ubyte);
74607dc194Richard Lowe                memcpy((void *) data, (const void *) arg, nbytes);
74707dc194Richard Lowe                data += nbytes;
74807dc194Richard Lowe                sum_bytes += nbytes + sizeof(Dwarf_Ubyte);
74907dc194Richard Lowe                prevline->dpl_file = curline->dpl_file;
75007dc194Richard Lowe            }
75107dc194Richard Lowe            if (curline->dpl_column != prevline->dpl_column) {
75207dc194Richard Lowe                db = DW_LNS_set_column;
75307dc194Richard Lowe                res = _dwarf_pro_encode_leb128_nm(curline->dpl_column,
75407dc194Richard Lowe                                                  &nbytes,
75507dc194Richard Lowe                                                  buff1, sizeof(buff1));
75607dc194Richard Lowe                if (res != DW_DLV_OK) {
75707dc194Richard Lowe                    DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
75807dc194Richard Lowe                }
75907dc194Richard Lowe
76007dc194Richard Lowe                arg = buff1;
76107dc194Richard Lowe                GET_CHUNK(dbg, elfsectno, data,
76207dc194Richard Lowe                          nbytes + sizeof(Dwarf_Ubyte), error);
76307dc194Richard Lowe                WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
76407dc194Richard Lowe                                sizeof(db), sizeof(Dwarf_Ubyte));
76507dc194Richard Lowe                data += sizeof(Dwarf_Ubyte);
76607dc194Richard Lowe                memcpy((void *) data, (const void *) arg, nbytes);
76707dc194Richard Lowe                data += nbytes;
76807dc194Richard Lowe                sum_bytes += nbytes + sizeof(Dwarf_Ubyte);
76907dc194Richard Lowe                prevline->dpl_column = curline->dpl_column;
77007dc194Richard Lowe            }
77107dc194Richard Lowe            if (curline->dpl_is_stmt != prevline->dpl_is_stmt) {
77207dc194Richard Lowe                db = DW_LNS_negate_stmt;
77307dc194Richard Lowe                GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte),
77407dc194Richard Lowe                          error);
77507dc194Richard Lowe                WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
77607dc194Richard Lowe                                sizeof(db), sizeof(Dwarf_Ubyte));
77707dc194Richard Lowe                data += sizeof(Dwarf_Ubyte);
77807dc194Richard Lowe                sum_bytes += sizeof(Dwarf_Ubyte);
77907dc194Richard Lowe                prevline->dpl_is_stmt = curline->dpl_is_stmt;
78007dc194Richard Lowe            }
78107dc194Richard Lowe            if (curline->dpl_basic_block == true &&
78207dc194Richard Lowe                prevline->dpl_basic_block == false) {
78307dc194Richard Lowe                db = DW_LNS_set_basic_block;
78407dc194Richard Lowe                GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte),
78507dc194Richard Lowe                          error);
78607dc194Richard Lowe                WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
78707dc194Richard Lowe                                sizeof(db), sizeof(Dwarf_Ubyte));
78807dc194Richard Lowe                data += sizeof(Dwarf_Ubyte);
78907dc194Richard Lowe                sum_bytes += sizeof(Dwarf_Ubyte);
79007dc194Richard Lowe                prevline->dpl_basic_block = curline->dpl_basic_block;
79107dc194Richard Lowe            }
79207dc194Richard Lowe            addr_adv = curline->dpl_address - prevline->dpl_address;
79307dc194Richard Lowe
79407dc194Richard Lowe            line_adv = (int) (curline->dpl_line - prevline->dpl_line);
79507dc194Richard Lowe            if ((addr_adv % MIN_INST_LENGTH) != 0) {
79607dc194Richard Lowe                DWARF_P_DBG_ERROR(dbg, DW_DLE_WRONG_ADDRESS, -1);
79707dc194Richard Lowe            }
79807dc194Richard Lowe            if ((opc = _dwarf_pro_get_opc(addr_adv, line_adv)) > 0) {
79907dc194Richard Lowe                no_lns_copy = 1;
80007dc194Richard Lowe                db = opc;
80107dc194Richard Lowe                GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte),
80207dc194Richard Lowe                          error);
80307dc194Richard Lowe                WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
80407dc194Richard Lowe                                sizeof(db), sizeof(Dwarf_Ubyte));
80507dc194Richard Lowe                data += sizeof(Dwarf_Ubyte);
80607dc194Richard Lowe                sum_bytes += sizeof(Dwarf_Ubyte);
80707dc194Richard Lowe                prevline->dpl_basic_block = false;
80807dc194Richard Lowe                prevline->dpl_address = curline->dpl_address;
80907dc194Richard Lowe                prevline->dpl_line = curline->dpl_line;
81007dc194Richard Lowe            } else {
81107dc194Richard Lowe                if (addr_adv > 0) {
81207dc194Richard Lowe                    db = DW_LNS_advance_pc;
81307dc194Richard Lowe                    res =
81407dc194Richard Lowe                        _dwarf_pro_encode_leb128_nm(addr_adv /
81507dc194Richard Lowe                                                    MIN_INST_LENGTH,
81607dc194Richard Lowe                                                    &nbytes, buff1,
81707dc194Richard Lowe                                                    sizeof(buff1));
81807dc194Richard Lowe                    if (res != DW_DLV_OK) {
81907dc194Richard Lowe                        DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
82007dc194Richard Lowe                    }
82107dc194Richard Lowe
82207dc194Richard Lowe                    arg = buff1;
82307dc194Richard Lowe                    GET_CHUNK(dbg, elfsectno, data,
82407dc194Richard Lowe                              nbytes + sizeof(Dwarf_Ubyte), error);
82507dc194Richard Lowe                    WRITE_UNALIGNED(dbg, (void *) data,
82607dc194Richard Lowe                                    (const void *) &db,
82707dc194Richard Lowe                                    sizeof(db), sizeof(Dwarf_Ubyte));
82807dc194Richard Lowe                    data += sizeof(Dwarf_Ubyte);
82907dc194Richard Lowe                    memcpy((void *) data, (const void *) arg, nbytes);
83007dc194Richard Lowe                    data += nbytes + sizeof(Dwarf_Ubyte);
83107dc194Richard Lowe                    sum_bytes += nbytes + sizeof(Dwarf_Ubyte);
83207dc194Richard Lowe                    prevline->dpl_basic_block = false;
83307dc194Richard Lowe                    prevline->dpl_address = curline->dpl_address;
83407dc194Richard Lowe                }
83507dc194Richard Lowe                if (line_adv != 0) {
83607dc194Richard Lowe                    db = DW_LNS_advance_line;
83707dc194Richard Lowe                    res = _dwarf_pro_encode_signed_leb128_nm(line_adv,
83807dc194Richard Lowe                                                             &nbytes,
83907dc194Richard Lowe                                                             buff1,
84007dc194Richard Lowe                                                             sizeof
84107dc194Richard Lowe                                                             (buff1));
84207dc194Richard Lowe                    if (res != DW_DLV_OK) {
84307dc194Richard Lowe                        DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
84407dc194Richard Lowe                    }
84507dc194Richard Lowe
84607dc194Richard Lowe                    arg = buff1;
84707dc194Richard Lowe                    GET_CHUNK(dbg, elfsectno, data,
84807dc194Richard Lowe                              nbytes + sizeof(Dwarf_Ubyte), error);
84907dc194Richard Lowe                    WRITE_UNALIGNED(dbg, (void *) data,
85007dc194Richard Lowe                                    (const void *) &db, sizeof(db),
85107dc194Richard Lowe                                    sizeof(Dwarf_Ubyte));
85207dc194Richard Lowe                    data += sizeof(Dwarf_Ubyte);
85307dc194Richard Lowe                    memcpy((void *) data, (const void *) arg, nbytes);
85407dc194Richard Lowe                    data += nbytes + sizeof(Dwarf_Ubyte);
85507dc194Richard Lowe                    sum_bytes += nbytes + sizeof(Dwarf_Ubyte);
85607dc194Richard Lowe                    prevline->dpl_basic_block = false;
85707dc194Richard Lowe                    prevline->dpl_line = curline->dpl_line;
85807dc194Richard Lowe                }
85907dc194Richard Lowe            }
86007dc194Richard Lowe        }                       /* ends else for opc != 0 */
86107dc194Richard Lowe        if (no_lns_copy == 0) { /* if not a special or dw_lne_end_seq
86207dc194Richard Lowe                                   generate a matrix line */
86307dc194Richard Lowe            db = DW_LNS_copy;
86407dc194Richard Lowe            GET_CHUNK(dbg, elfsectno, data, sizeof(Dwarf_Ubyte), error);
86507dc194Richard Lowe            WRITE_UNALIGNED(dbg, (void *) data,
86607dc194Richard Lowe                            (const void *) &db,
86707dc194Richard Lowe                            sizeof(db), sizeof(Dwarf_Ubyte));
86807dc194Richard Lowe            data += sizeof(Dwarf_Ubyte);
86907dc194Richard Lowe            sum_bytes += sizeof(Dwarf_Ubyte);
87007dc194Richard Lowe            prevline->dpl_basic_block = false;
87107dc194Richard Lowe        }
87207dc194Richard Lowe        curline = curline->dpl_next;
87349d3bc9Richard Lowe    }
87449d3bc9Richard Lowe
87549d3bc9Richard Lowe    /* write total length field */
87607dc194Richard Lowe    du = sum_bytes - BEGIN_LEN_SIZE;
87749d3bc9Richard Lowe    {
87807dc194Richard Lowe        start_line_sec += extension_size;
87907dc194Richard Lowe        WRITE_UNALIGNED(dbg, (void *) start_line_sec,
88007dc194Richard Lowe                        (const void *) &du, sizeof(du), uwordb_size);
88149d3bc9Richard Lowe    }
88249d3bc9Richard Lowe
88349d3bc9Richard Lowe    return (int) dbg->de_n_debug_sect;
88449d3bc9Richard Lowe}
88549d3bc9Richard Lowe
88649d3bc9Richard Lowe/*---------------------------------------------------------------
88707dc194Richard Lowe        Generate debug_frame section
88849d3bc9Richard Lowe---------------------------------------------------------------*/
88949d3bc9Richard Lowestatic int
89049d3bc9Richard Lowe_dwarf_pro_generate_debugframe(Dwarf_P_Debug dbg, Dwarf_Error * error)
89149d3bc9Richard Lowe{
89207dc194Richard Lowe    int elfsectno = 0;
89307dc194Richard Lowe    int i = 0;
89449d3bc9Richard Lowe    int firsttime = 1;
89507dc194Richard Lowe    int pad = 0;     /* Pad for padding to align cies and fdes */
89607dc194Richard Lowe    Dwarf_P_Cie curcie = 0;
89707dc194Richard Lowe    Dwarf_P_Fde curfde = 0;
89807dc194Richard Lowe    unsigned char *data = 0;
89907dc194Richard Lowe    Dwarf_sfixed dsw = 0;
90007dc194Richard Lowe    Dwarf_Unsigned du = 0;
90107dc194Richard Lowe    Dwarf_Ubyte db = 0;
90207dc194Richard Lowe    long *cie_offs = 0;   /* Holds byte offsets for links to fde's */
90307dc194Richard Lowe    unsigned long cie_length = 0;
90407dc194Richard Lowe    int cie_no = 0;
90549d3bc9Richard Lowe    int uwordb_size = dbg->de_offset_size;
90649d3bc9Richard Lowe    int extension_size = dbg->de_64bit_extension ? 4 : 0;
90749d3bc9Richard Lowe    int upointer_size = dbg->de_pointer_size;
90807dc194Richard Lowe    Dwarf_Unsigned cur_off = 0; /* current offset of written data, held
90907dc194Richard Lowe                                   for relocation info */
91049d3bc9Richard Lowe
91149d3bc9Richard Lowe    elfsectno = dbg->de_elf_sects[DEBUG_FRAME];
91249d3bc9Richard Lowe
91349d3bc9Richard Lowe    curcie = dbg->de_frame_cies;
91449d3bc9Richard Lowe    cie_length = 0;
91549d3bc9Richard Lowe    cur_off = 0;
91649d3bc9Richard Lowe    cie_offs = (long *)
91707dc194Richard Lowe        _dwarf_p_get_alloc(dbg, sizeof(long) * dbg->de_n_cie);
91849d3bc9Richard Lowe    if (cie_offs == NULL) {
91907dc194Richard Lowe        DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1);
92049d3bc9Richard Lowe    }
92107dc194Richard Lowe    /* Generate cie number as we go along.  This writes
92207dc194Richard Lowe       all CIEs first before any FDEs, which is rather
92307dc194Richard Lowe       different from the order a compiler might like (which
92407dc194Richard Lowe       might be each CIE followed by its FDEs then the next CIE, and
92507dc194Richard Lowe       so on). */
92649d3bc9Richard Lowe    cie_no = 1;
92749d3bc9Richard Lowe    while (curcie) {
92807dc194Richard Lowe        char *code_al = 0;
92907dc194Richard Lowe        int c_bytes = 0;
93007dc194Richard Lowe        char *data_al = 0;
93107dc194Richard Lowe        int d_bytes = 0;
93207dc194Richard Lowe        int res = 0;
93307dc194Richard Lowe        char buff1[ENCODE_SPACE_NEEDED];
93407dc194Richard Lowe        char buff2[ENCODE_SPACE_NEEDED];
93507dc194Richard Lowe        char buff3[ENCODE_SPACE_NEEDED];
93607dc194Richard Lowe        char *augmentation = 0;
93707dc194Richard Lowe        char *augmented_al = 0;
93807dc194Richard Lowe        long augmented_fields_length = 0;
93907dc194Richard Lowe        int a_bytes = 0;
94007dc194Richard Lowe
94107dc194Richard Lowe        res = _dwarf_pro_encode_leb128_nm(curcie->cie_code_align,
94207dc194Richard Lowe                                          &c_bytes,
94307dc194Richard Lowe                                          buff1, sizeof(buff1));
94407dc194Richard Lowe        if (res != DW_DLV_OK) {
94507dc194Richard Lowe            DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1);
94607dc194Richard Lowe        }
94707dc194Richard Lowe        /* Before April 1999, the following was using an unsigned
94807dc194Richard Lowe           encode. That worked ok even though the decoder used the
94907dc194Richard Lowe           correct signed leb read, but doing the encode correctly
95007dc194Richard Lowe           (according to the dwarf spec) saves space in the output file
95107dc194Richard Lowe           and is completely compatible.
95207dc194Richard Lowe
95307dc194Richard Lowe           Note the actual stored amount on MIPS was 10 bytes (!) to
95407dc194Richard Lowe           store the value -4. (hex)fc ffffffff ffffffff 01 The
95507dc194Richard Lowe           libdwarf consumer consumed all 10 bytes too!
95607dc194Richard Lowe
95707dc194Richard Lowe           old version res =
95807dc194Richard Lowe           _dwarf_pro_encode_leb128_nm(curcie->cie_data_align,
95907dc194Richard Lowe
96007dc194Richard Lowe           below is corrected signed version. */
96107dc194Richard Lowe        res = _dwarf_pro_encode_signed_leb128_nm(curcie->cie_data_align,
96207dc194Richard Lowe                                                 &d_bytes,
96307dc194Richard Lowe                                                 buff2, sizeof(buff2));
96407dc194Richard Lowe        if (res != DW_DLV_OK) {
96507dc194Richard Lowe            DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1);
96607dc194Richard Lowe        }
96707dc194Richard Lowe        code_al = buff1;
96807dc194Richard Lowe        data_al = buff2;
96907dc194Richard Lowe
97007dc194Richard Lowe        /* get the correct offset */
97107dc194Richard Lowe        if (firsttime) {
97207dc194Richard Lowe            cie_offs[cie_no - 1] = 0;
97307dc194Richard Lowe            firsttime = 0;
97407dc194Richard Lowe        } else {
97507dc194Richard Lowe            cie_offs[cie_no - 1] = cie_offs[cie_no - 2] +
97607dc194Richard Lowe                (long) cie_length + BEGIN_LEN_SIZE;
97707dc194Richard Lowe        }
97807dc194Richard Lowe        cie_no++;
97907dc194Richard Lowe        augmentation = curcie->cie_aug;
98007dc194Richard Lowe        if (strcmp(augmentation, DW_CIE_AUGMENTER_STRING_V0) == 0) {
98107dc194Richard Lowe            augmented_fields_length = 0;
98207dc194Richard Lowe            res = _dwarf_pro_encode_leb128_nm(augmented_fields_length,
98307dc194Richard Lowe                                              &a_bytes, buff3,
98407dc194Richard Lowe                                              sizeof(buff3));
98507dc194Richard Lowe            augmented_al = buff3;
98607dc194Richard Lowe            if (res != DW_DLV_OK) {
98707dc194Richard Lowe                DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1);
98807dc194Richard Lowe            }
98907dc194Richard Lowe            cie_length = uwordb_size +  /* cie_id */
99007dc194Richard Lowe                sizeof(Dwarf_Ubyte) +   /* cie version */
99107dc194Richard Lowe                strlen(curcie->cie_aug) + 1 +   /* augmentation */
99207dc194Richard Lowe                c_bytes +       /* code alignment factor */
99307dc194Richard Lowe                d_bytes +       /* data alignment factor */
99407dc194Richard Lowe                sizeof(Dwarf_Ubyte) +   /* return reg address */
99507dc194Richard Lowe                a_bytes +       /* augmentation length */
99607dc194Richard Lowe                curcie->cie_inst_bytes;
99707dc194Richard Lowe        } else {
99807dc194Richard Lowe            cie_length = uwordb_size +  /* cie_id */
99907dc194Richard Lowe                sizeof(Dwarf_Ubyte) +   /* cie version */
100007dc194Richard Lowe                strlen(curcie->cie_aug) + 1 +   /* augmentation */
100107dc194Richard Lowe                c_bytes + d_bytes + sizeof(Dwarf_Ubyte) +       /* return
100207dc194Richard Lowe                                                                   reg
100307dc194Richard Lowe                                                                   address
100407dc194Richard Lowe                                                                 */
100507dc194Richard Lowe                curcie->cie_inst_bytes;
100607dc194Richard Lowe        }
100707dc194Richard Lowe        pad = (int) PADDING(cie_length, upointer_size);
100807dc194Richard Lowe        cie_length += pad;
100907dc194Richard Lowe        GET_CHUNK(dbg, elfsectno, data, cie_length +
101007dc194Richard Lowe                  BEGIN_LEN_SIZE, error);
101107dc194Richard Lowe        if (extension_size) {
101207dc194Richard Lowe            Dwarf_Unsigned x = DISTINGUISHED_VALUE;
101307dc194Richard Lowe
101407dc194Richard Lowe            WRITE_UNALIGNED(dbg, (void *) data,
101507dc194Richard Lowe                            (const void *) &x,
101607dc194Richard Lowe                            sizeof(x), extension_size);
101707dc194Richard Lowe            data += extension_size;
101807dc194Richard Lowe
101907dc194Richard Lowe        }
102007dc194Richard Lowe        du = cie_length;
102107dc194Richard Lowe        /* total length of cie */
102207dc194Richard Lowe        WRITE_UNALIGNED(dbg, (void *) data,
102307dc194Richard Lowe                        (const void *) &du, sizeof(du), uwordb_size);
102407dc194Richard Lowe        data += uwordb_size;
102507dc194Richard Lowe
102607dc194Richard Lowe        /* cie-id is a special value. */
102707dc194Richard Lowe        du = DW_CIE_ID;
102807dc194Richard Lowe        WRITE_UNALIGNED(dbg, (void *) data, (const void *) &du,
102907dc194Richard Lowe                        sizeof(du), uwordb_size);
103007dc194Richard Lowe        data += uwordb_size;
103107dc194Richard Lowe
103207dc194Richard Lowe        db = curcie->cie_version;
103307dc194Richard Lowe        WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
103407dc194Richard Lowe                        sizeof(db), sizeof(Dwarf_Ubyte));
103507dc194Richard Lowe        data += sizeof(Dwarf_Ubyte);
103607dc194Richard Lowe        strcpy((char *) data, curcie->cie_aug);
103707dc194Richard Lowe        data += strlen(curcie->cie_aug) + 1;
103807dc194Richard Lowe        memcpy((void *) data, (const void *) code_al, c_bytes);
103907dc194Richard Lowe        data += c_bytes;
104007dc194Richard Lowe        memcpy((void *) data, (const void *) data_al, d_bytes);
104107dc194Richard Lowe        data += d_bytes;
104207dc194Richard Lowe        db = curcie->cie_ret_reg;
104307dc194Richard Lowe        WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
104407dc194Richard Lowe                        sizeof(db), sizeof(Dwarf_Ubyte));
104507dc194Richard Lowe        data += sizeof(Dwarf_Ubyte);
104607dc194Richard Lowe
104707dc194Richard Lowe        if (strcmp(augmentation, DW_CIE_AUGMENTER_STRING_V0) == 0) {
104807dc194Richard Lowe            memcpy((void *) data, (const void *) augmented_al, a_bytes);
104907dc194Richard Lowe            data += a_bytes;
105007dc194Richard Lowe        }
105107dc194Richard Lowe        memcpy((void *) data, (const void *) curcie->cie_inst,
105207dc194Richard Lowe               curcie->cie_inst_bytes);
105307dc194Richard Lowe        data += curcie->cie_inst_bytes;
105407dc194Richard Lowe        for (i = 0; i < pad; i++) {
105507dc194Richard Lowe            *data = DW_CFA_nop;
105607dc194Richard Lowe            data++;
105707dc194Richard Lowe        }
105807dc194Richard Lowe        curcie = curcie->cie_next;
105949d3bc9Richard Lowe    }
106049d3bc9Richard Lowe    /* calculate current offset */
106107dc194Richard Lowe    cur_off = cie_offs[cie_no - 2] + cie_length + BEGIN_LEN_SIZE;
106249d3bc9Richard Lowe
106349d3bc9Richard Lowe    /* write out fde's */
106449d3bc9Richard Lowe    curfde = dbg->de_frame_fdes;
106549d3bc9Richard Lowe    while (curfde) {
106607dc194Richard Lowe        Dwarf_P_Frame_Pgm curinst = 0;
106707dc194Richard Lowe        long fde_length = 0;
106807dc194Richard Lowe        int pad = 0;
106907dc194Richard Lowe        Dwarf_P_Cie cie_ptr = 0;
107007dc194Richard Lowe        Dwarf_Word cie_index = 0;
107107dc194Richard Lowe        Dwarf_Word index = 0;
107207dc194Richard Lowe        int oet_length = 0;
107307dc194Richard Lowe        int afl_length = 0;
107407dc194Richard Lowe        int res = 0;
107507dc194Richard Lowe        int v0_augmentation = 0;
107649d3bc9Richard Lowe#if 0
107707dc194Richard Lowe        unsigned char *fde_start_point = 0;
107849d3bc9Richard Lowe#endif
107907dc194Richard Lowe        char afl_buff[ENCODE_SPACE_NEEDED];
108007dc194Richard Lowe
108107dc194Richard Lowe        /* Find the CIE associated with this fde. */
108207dc194Richard Lowe        cie_ptr = dbg->de_frame_cies;
108307dc194Richard Lowe        cie_index = curfde->fde_cie;
108407dc194Richard Lowe        index = 1;              /* The cie_index of the first cie is 1,
108507dc194Richard Lowe                                   not 0. */
108607dc194Richard Lowe        while (cie_ptr && index < cie_index) {
108707dc194Richard Lowe            cie_ptr = cie_ptr->cie_next;
108807dc194Richard Lowe            index++;
108907dc194Richard Lowe        }
109007dc194Richard Lowe        if (cie_ptr == NULL) {
109107dc194Richard Lowe            DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_NULL, -1);
109207dc194Richard Lowe        }
109307dc194Richard Lowe
109407dc194Richard Lowe        if (strcmp(cie_ptr->cie_aug, DW_CIE_AUGMENTER_STRING_V0) == 0) {
109507dc194Richard Lowe            v0_augmentation = 1;
109607dc194Richard Lowe            oet_length = sizeof(Dwarf_sfixed);
109707dc194Richard Lowe            /* encode the length of augmented fields. */
109807dc194Richard Lowe            res = _dwarf_pro_encode_leb128_nm(oet_length,
109907dc194Richard Lowe                                              &afl_length, afl_buff,
110007dc194Richard Lowe                                              sizeof(afl_buff));
110107dc194Richard Lowe            if (res != DW_DLV_OK) {
110207dc194Richard Lowe                DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1);
110307dc194Richard Lowe            }
110407dc194Richard Lowe
110507dc194Richard Lowe            fde_length = curfde->fde_n_bytes + BEGIN_LEN_SIZE + /* cie
110607dc194Richard Lowe                                                                   pointer
110707dc194Richard Lowe                                                                 */
110807dc194Richard Lowe                upointer_size + /* initial loc */
110907dc194Richard Lowe                upointer_size + /* address range */
111007dc194Richard Lowe                afl_length +    /* augmented field length */
111107dc194Richard Lowe                oet_length;     /* exception_table offset */
111207dc194Richard Lowe        } else {
111307dc194Richard Lowe            fde_length = curfde->fde_n_bytes + BEGIN_LEN_SIZE + /* cie
111407dc194Richard Lowe                                                                   pointer
111507dc194Richard Lowe                                                                 */
111607dc194Richard Lowe                upointer_size + /* initial loc */
111707dc194Richard Lowe                upointer_size;  /* address range */
111807dc194Richard Lowe        }
111907dc194Richard Lowe
112007dc194Richard Lowe
112107dc194Richard Lowe        if (curfde->fde_die) {
112207dc194Richard Lowe            /* IRIX/MIPS extension:
112307dc194Richard Lowe               Using fde offset, generate DW_AT_MIPS_fde attribute for the
112407dc194Richard Lowe               die corresponding to this fde.  */
112507dc194Richard Lowe            if(_dwarf_pro_add_AT_fde(dbg, curfde->fde_die, cur_off,
112607dc194Richard Lowe                error) < 0) {
112707dc194Richard Lowe                return -1;
112807dc194Richard Lowe            }
112907dc194Richard Lowe        }
113007dc194Richard Lowe
113107dc194Richard Lowe        /* store relocation for cie pointer */
113207dc194Richard Lowe        res = dbg->de_reloc_name(dbg, DEBUG_FRAME, cur_off +
113307dc194Richard Lowe                                     BEGIN_LEN_SIZE /* r_offset */,
113407dc194Richard Lowe                                 dbg->de_sect_name_idx[DEBUG_FRAME],
113507dc194Richard Lowe                                 dwarf_drt_data_reloc, uwordb_size);
113607dc194Richard Lowe        if (res != DW_DLV_OK) {
113707dc194Richard Lowe            DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
113807dc194Richard Lowe        }
113907dc194Richard Lowe
114007dc194Richard Lowe        /* store relocation information for initial location */
114107dc194Richard Lowe        res = dbg->de_reloc_name(dbg, DEBUG_FRAME,
114207dc194Richard Lowe                                 cur_off + BEGIN_LEN_SIZE +
114307dc194Richard Lowe                                     upointer_size /* r_offset */,
114407dc194Richard Lowe                                 curfde->fde_r_symidx,
114507dc194Richard Lowe                                 dwarf_drt_data_reloc, upointer_size);
114607dc194Richard Lowe        if (res != DW_DLV_OK) {
114707dc194Richard Lowe            DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
114807dc194Richard Lowe        }
114907dc194Richard Lowe        /* Store the relocation information for the
115007dc194Richard Lowe           offset_into_exception_info field, if the offset is valid (0
115107dc194Richard Lowe           is a valid offset). */
115207dc194Richard Lowe        if (v0_augmentation &&
115307dc194Richard Lowe            curfde->fde_offset_into_exception_tables >= 0) {
115407dc194Richard Lowe
115507dc194Richard Lowe            res = dbg->de_reloc_name(dbg, DEBUG_FRAME,
115607dc194Richard Lowe                                     /* r_offset, where in cie this
115707dc194Richard Lowe                                        field starts */
115807dc194Richard Lowe                                     cur_off + BEGIN_LEN_SIZE +
115907dc194Richard Lowe                                         uwordb_size + 2 * upointer_size +
116007dc194Richard Lowe                                         afl_length,
116107dc194Richard Lowe                                     curfde->fde_exception_table_symbol,
116207dc194Richard Lowe                                     dwarf_drt_segment_rel,
116307dc194Richard Lowe                                     sizeof(Dwarf_sfixed));
116407dc194Richard Lowe            if (res != DW_DLV_OK) {
116507dc194Richard Lowe                DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
116607dc194Richard Lowe            }
116707dc194Richard Lowe        }
116807dc194Richard Lowe
116907dc194Richard Lowe        /* adjust for padding */
117007dc194Richard Lowe        pad = (int) PADDING(fde_length, upointer_size);
117107dc194Richard Lowe        fde_length += pad;
117207dc194Richard Lowe
117307dc194Richard Lowe
117407dc194Richard Lowe        /* write out fde */
117507dc194Richard Lowe        GET_CHUNK(dbg, elfsectno, data, fde_length + BEGIN_LEN_SIZE,
117607dc194Richard Lowe                  error);
117749d3bc9Richard Lowe#if 0
117807dc194Richard Lowe        fde_start_point = data;
117949d3bc9Richard Lowe#endif
118007dc194Richard Lowe        du = fde_length;
118107dc194Richard Lowe        {
118207dc194Richard Lowe            if (extension_size) {
118307dc194Richard Lowe                Dwarf_Word x = DISTINGUISHED_VALUE;
118407dc194Richard Lowe
118507dc194Richard Lowe                WRITE_UNALIGNED(dbg, (void *) data,
118607dc194Richard Lowe                                (const void *) &x,
118707dc194Richard Lowe                                sizeof(x), extension_size);
118807dc194Richard Lowe                data += extension_size;
118907dc194Richard Lowe            }
119007dc194Richard Lowe            /* length */
119107dc194Richard Lowe            WRITE_UNALIGNED(dbg, (void *) data,
119207dc194Richard Lowe                            (const void *) &du,
119307dc194Richard Lowe                            sizeof(du), uwordb_size);
119407dc194Richard Lowe            data += uwordb_size;
119507dc194Richard Lowe
119607dc194Richard Lowe            /* offset to cie */
119707dc194Richard Lowe            du = cie_offs[curfde->fde_cie - 1];
119807dc194Richard Lowe            WRITE_UNALIGNED(dbg, (void *) data,
119907dc194Richard Lowe                            (const void *) &du,
120007dc194Richard Lowe                            sizeof(du), uwordb_size);
120107dc194Richard Lowe            data += uwordb_size;
120207dc194Richard Lowe
120307dc194Richard Lowe            du = curfde->fde_initloc;
120407dc194Richard Lowe            WRITE_UNALIGNED(dbg, (void *) data,
120507dc194Richard Lowe                            (const void *) &du,
120607dc194Richard Lowe                            sizeof(du), upointer_size);
120707dc194Richard Lowe            data += upointer_size;
120807dc194Richard Lowe
120907dc194Richard Lowe            if (dbg->de_reloc_pair &&
121007dc194Richard Lowe                curfde->fde_end_symbol != 0 &&
121107dc194Richard Lowe                curfde->fde_addr_range == 0) {
121207dc194Richard Lowe                /* symbolic reloc, need reloc for length What if we
121307dc194Richard Lowe                   really know the length? If so, should use the other
121407dc194Richard Lowe                   part of 'if'. */
121507dc194Richard Lowe                Dwarf_Unsigned val;
121607dc194Richard Lowe
121707dc194Richard Lowe                res = dbg->de_reloc_pair(dbg,
121807dc194Richard Lowe                                         /* DEBUG_ARANGES, */
121907dc194Richard Lowe                                         DEBUG_FRAME, cur_off + 2 * uwordb_size + upointer_size,        /* r_offset
122007dc194Richard Lowe                                                                                                         */
122107dc194Richard Lowe                                         curfde->fde_r_symidx,
122207dc194Richard Lowe                                         curfde->fde_end_symbol,
122307dc194Richard Lowe                                         dwarf_drt_first_of_length_pair,
122407dc194Richard Lowe                                         upointer_size);
122507dc194Richard Lowe                if (res != DW_DLV_OK) {
122607dc194Richard Lowe                    {
122707dc194Richard Lowe                        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
122807dc194Richard Lowe                        return (0);
122907dc194Richard Lowe                    }
123007dc194Richard Lowe                }
123107dc194Richard Lowe
123207dc194Richard Lowe                /* arrange pre-calc so assem text can do .word end -
123307dc194Richard Lowe                   begin + val (gets val from stream) */
123407dc194Richard Lowe                val = curfde->fde_end_symbol_offset -
123507dc194Richard Lowe                    curfde->fde_initloc;
123607dc194Richard Lowe                WRITE_UNALIGNED(dbg, data,
123707dc194Richard Lowe                                (const void *) &val,
123807dc194Richard Lowe                                sizeof(val), upointer_size);
123907dc194Richard Lowe                data += upointer_size;
124007dc194Richard Lowe            } else {
124107dc194Richard Lowe
124207dc194Richard Lowe                du = curfde->fde_addr_range;
124307dc194Richard Lowe                WRITE_UNALIGNED(dbg, (void *) data,
124407dc194Richard Lowe                                (const void *) &du,
124507dc194Richard Lowe                                sizeof(du), upointer_size);
124607dc194Richard Lowe                data += upointer_size;
124707dc194Richard Lowe            }
124807dc194Richard Lowe        }
124907dc194Richard Lowe
125007dc194Richard Lowe        if (v0_augmentation) {
125107dc194Richard Lowe            /* write the encoded augmented field length. */
125207dc194Richard Lowe            memcpy((void *) data, (const void *) afl_buff, afl_length);
125307dc194Richard Lowe            data += afl_length;
125407dc194Richard Lowe            /* write the offset_into_exception_tables field. */
125507dc194Richard Lowe            dsw =
125607dc194Richard Lowe                (Dwarf_sfixed) curfde->fde_offset_into_exception_tables;
125707dc194Richard Lowe            WRITE_UNALIGNED(dbg, (void *) data, (const void *) &dsw,
125807dc194Richard Lowe                            sizeof(dsw), sizeof(Dwarf_sfixed));
125907dc194Richard Lowe            data += sizeof(Dwarf_sfixed);
126007dc194Richard Lowe        }
126107dc194Richard Lowe
126207dc194Richard Lowe        curinst = curfde->fde_inst;
126307dc194Richard Lowe        if(curfde->fde_block) {
126407dc194Richard Lowe            unsigned long size = curfde->fde_inst_block_size;
126507dc194Richard Lowe            memcpy((void *) data, (const void *) curfde->fde_block, size);
126607dc194Richard Lowe            data += size;
126707dc194Richard Lowe        } else {
126807dc194Richard Lowe            while (curinst) {
126907dc194Richard Lowe                db = curinst->dfp_opcode;
127007dc194Richard Lowe                WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
127107dc194Richard Lowe                     sizeof(db), sizeof(Dwarf_Ubyte));
127207dc194Richard Lowe                data += sizeof(Dwarf_Ubyte);
127349d3bc9Richard Lowe#if 0
127407dc194Richard Lowe                if (curinst->dfp_sym_index) {
127507dc194Richard Lowe                    int res = dbg->de_reloc_name(dbg,
127607dc194Richard Lowe                        DEBUG_FRAME,
127707dc194Richard Lowe                        /* r_offset = */
127807dc194Richard Lowe                        (data - fde_start_point) + cur_off + uwordb_size,
127907dc194Richard Lowe                        curinst->dfp_sym_index,
128007dc194Richard Lowe                        dwarf_drt_data_reloc,
128107dc194Richard Lowe                        upointer_size);
128207dc194Richard Lowe                    if (res != DW_DLV_OK) {
128307dc194Richard Lowe                        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
128407dc194Richard Lowe                        return (0);
128507dc194Richard Lowe                    }
128607dc194Richard Lowe                }
128749d3bc9Richard Lowe#endif
128807dc194Richard Lowe                memcpy((void *) data,
128907dc194Richard Lowe                   (const void *) curinst->dfp_args,
129007dc194Richard Lowe                   curinst->dfp_nbytes);
129107dc194Richard Lowe                data += curinst->dfp_nbytes;
129207dc194Richard Lowe                curinst = curinst->dfp_next;
129307dc194Richard Lowe            }
129407dc194Richard Lowe        }
129507dc194Richard Lowe        /* padding */
129607dc194Richard Lowe        for (i = 0; i < pad; i++) {
129707dc194Richard Lowe            *data = DW_CFA_nop;
129807dc194Richard Lowe            data++;
129907dc194Richard Lowe        }
130007dc194Richard Lowe        cur_off += fde_length + uwordb_size;
130107dc194Richard Lowe        curfde = curfde->fde_next;
130249d3bc9Richard Lowe    }
130349d3bc9Richard Lowe
130449d3bc9Richard Lowe
130549d3bc9Richard Lowe    return (int) dbg->de_n_debug_sect;
130649d3bc9Richard Lowe}
130749d3bc9Richard Lowe
130807dc194Richard Lowe/*
130907dc194Richard Lowe  These functions remember all the markers we see along
131007dc194Richard Lowe  with the right offset in the .debug_info section so that
131107dc194Richard Lowe  we can dump them all back to the user with the section info.
131207dc194Richard Lowe*/
131307dc194Richard Lowe
131407dc194Richard Lowestatic int
131507dc194Richard Lowemarker_init(Dwarf_P_Debug dbg,
131607dc194Richard Lowe            unsigned count)
131707dc194Richard Lowe{
131807dc194Richard Lowe    dbg->de_marker_n_alloc = count;
131907dc194Richard Lowe    dbg->de_markers = NULL;
132007dc194Richard Lowe    if (count > 0) {
132107dc194Richard Lowe        dbg->de_markers = _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Marker_s) *
132207dc194Richard Lowe                                             dbg->de_marker_n_alloc);
132307dc194Richard Lowe        if (dbg->de_markers == NULL) {
132407dc194Richard Lowe            dbg->de_marker_n_alloc = 0;
132507dc194Richard Lowe            return -1;
132607dc194Richard Lowe        }
132707dc194Richard Lowe    }
132807dc194Richard Lowe    return 0;
132907dc194Richard Lowe}
133007dc194Richard Lowe
133107dc194Richard Lowestatic int
133207dc194Richard Lowemarker_add(Dwarf_P_Debug dbg,
133307dc194Richard Lowe           Dwarf_Unsigned offset,
133407dc194Richard Lowe           Dwarf_Unsigned marker)
133507dc194Richard Lowe{
133607dc194Richard Lowe    if (dbg->de_marker_n_alloc >= (dbg->de_marker_n_used + 1)) {
133707dc194Richard Lowe        unsigned n = dbg->de_marker_n_used++;
133807dc194Richard Lowe        dbg->de_markers[n].ma_offset = offset;
133907dc194Richard Lowe        dbg->de_markers[n].ma_marker = marker;
134007dc194Richard Lowe        return 0;
134107dc194Richard Lowe    }
134207dc194Richard Lowe
134307dc194Richard Lowe    return -1;
134407dc194Richard Lowe}
134507dc194Richard Lowe
134607dc194Richard LoweDwarf_Signed
134707dc194Richard Lowedwarf_get_die_markers(Dwarf_P_Debug dbg,
134807dc194Richard Lowe                      Dwarf_P_Marker * marker_list, /* pointer to a pointer */
134907dc194Richard Lowe                      Dwarf_Unsigned * marker_count,
135007dc194Richard Lowe                      Dwarf_Error * error)
135107dc194Richard Lowe{
135207dc194Richard Lowe    if (marker_list == NULL || marker_count == NULL) {
135307dc194Richard Lowe        DWARF_P_DBG_ERROR(dbg, DW_DLE_IA, DW_DLV_BADADDR);
135407dc194Richard Lowe    }
135507dc194Richard Lowe    if (dbg->de_marker_n_used != dbg->de_marker_n_alloc) {
135607dc194Richard Lowe        DWARF_P_DBG_ERROR(dbg, DW_DLE_MAF, DW_DLV_BADADDR);
135707dc194Richard Lowe    }
135807dc194Richard Lowe
135907dc194Richard Lowe    *marker_list = dbg->de_markers;
136007dc194Richard Lowe    *marker_count = dbg->de_marker_n_used;
136107dc194Richard Lowe    return DW_DLV_OK;
136207dc194Richard Lowe}
136307dc194Richard Lowe
136407dc194Richard Lowe/* These functions provide the offsets of DW_FORM_string
136507dc194Richard Lowe   attributes in the section section_index. These information
136607dc194Richard Lowe   will enable a producer app that is generating assembly
136707dc194Richard Lowe   text output to easily emit those attributes in ascii form
136807dc194Richard Lowe   without having to decode the byte stream.
136907dc194Richard Lowe */
137007dc194Richard Lowestatic int
137107dc194Richard Lowestring_attr_init (Dwarf_P_Debug dbg,
137207dc194Richard Lowe                  Dwarf_Signed section_index,
137307dc194Richard Lowe                  unsigned count)
137407dc194Richard Lowe{
137507dc194Richard Lowe    Dwarf_P_Per_Sect_String_Attrs sect_sa = &dbg->de_sect_string_attr[section_index];
137607dc194Richard Lowe
137707dc194Richard Lowe    sect_sa->sect_sa_n_alloc = count;
137807dc194Richard Lowe    sect_sa->sect_sa_list = NULL;
137907dc194Richard Lowe    if (count > 0) {
138007dc194Richard Lowe        sect_sa->sect_sa_section_number = section_index;
138107dc194Richard Lowe        sect_sa->sect_sa_list = _dwarf_p_get_alloc(dbg,
138207dc194Richard Lowe                                                   sizeof(struct Dwarf_P_String_Attr_s)
138307dc194Richard Lowe                                                   * sect_sa->sect_sa_n_alloc);
138407dc194Richard Lowe        if (sect_sa->sect_sa_list == NULL) {
138507dc194Richard Lowe            sect_sa->sect_sa_n_alloc = 0;
138607dc194Richard Lowe            return -1;
138707dc194Richard Lowe        }
138807dc194Richard Lowe    }
138907dc194Richard Lowe    return 0;
139007dc194Richard Lowe}
139107dc194Richard Lowe
139207dc194Richard Lowestatic int
139307dc194Richard Lowestring_attr_add (Dwarf_P_Debug dbg,
139407dc194Richard Lowe                 Dwarf_Signed section_index,
139507dc194Richard Lowe                 Dwarf_Unsigned offset,
139607dc194Richard Lowe                 Dwarf_P_Attribute attr)
139707dc194Richard Lowe{
139807dc194Richard Lowe    Dwarf_P_Per_Sect_String_Attrs sect_sa = &dbg->de_sect_string_attr[section_index];
139907dc194Richard Lowe    if (sect_sa->sect_sa_n_alloc >= (sect_sa->sect_sa_n_used + 1)) {
140007dc194Richard Lowe        unsigned n = sect_sa->sect_sa_n_used++;
140107dc194Richard Lowe        sect_sa->sect_sa_list[n].sa_offset = offset;
140207dc194Richard Lowe        sect_sa->sect_sa_list[n].sa_nbytes = attr->ar_nbytes;
140307dc194Richard Lowe        return 0;
140407dc194Richard Lowe    }
140507dc194Richard Lowe
140607dc194Richard Lowe    return -1;
140707dc194Richard Lowe}
140807dc194Richard Lowe
140907dc194Richard Loweint
141007dc194Richard Lowedwarf_get_string_attributes_count(Dwarf_P_Debug dbg,
141107dc194Richard Lowe                                  Dwarf_Unsigned *
141207dc194Richard Lowe                                  count_of_sa_sections,
141307dc194Richard Lowe                                  int *drd_buffer_version,
141407dc194Richard Lowe                                  Dwarf_Error *error)
141507dc194Richard Lowe{
141607dc194Richard Lowe    int i;
141707dc194Richard Lowe    unsigned int count = 0;
141807dc194Richard Lowe
141907dc194Richard Lowe    for (i = 0; i < NUM_DEBUG_SECTIONS; ++i) {
142007dc194Richard Lowe        if (dbg->de_sect_string_attr[i].sect_sa_n_used > 0) {
142107dc194Richard Lowe            ++count;
142207dc194Richard Lowe        }
142307dc194Richard Lowe    }
142407dc194Richard Lowe    *count_of_sa_sections = (Dwarf_Unsigned) count;
142507dc194Richard Lowe    *drd_buffer_version = DWARF_DRD_BUFFER_VERSION;
142607dc194Richard Lowe
142707dc194Richard Lowe    return DW_DLV_OK;
142807dc194Richard Lowe}
142907dc194Richard Lowe
143007dc194Richard Loweint
143107dc194Richard Lowedwarf_get_string_attributes_info(Dwarf_P_Debug dbg,
143207dc194Richard Lowe                                 Dwarf_Signed *elf_section_index,
143307dc194Richard Lowe                                 Dwarf_Unsigned *sect_sa_buffer_count,
143407dc194Richard Lowe                                 Dwarf_P_String_Attr *sect_sa_buffer,
143507dc194Richard Lowe                                 Dwarf_Error *error)
143607dc194Richard Lowe{
143707dc194Richard Lowe    int i;
143807dc194Richard Lowe    int next = dbg->de_sect_sa_next_to_return;
143907dc194Richard Lowe
144007dc194Richard Lowe    for (i = next; i < NUM_DEBUG_SECTIONS; ++i) {
144107dc194Richard Lowe        Dwarf_P_Per_Sect_String_Attrs sect_sa = &dbg->de_sect_string_attr[i];
144207dc194Richard Lowe        if (sect_sa->sect_sa_n_used > 0) {
144307dc194Richard Lowe            dbg->de_sect_sa_next_to_return = i + 1;
144407dc194Richard Lowe            *elf_section_index = sect_sa->sect_sa_section_number;
144507dc194Richard Lowe            *sect_sa_buffer_count = sect_sa->sect_sa_n_used;
144607dc194Richard Lowe            *sect_sa_buffer = sect_sa->sect_sa_list;
144707dc194Richard Lowe            return DW_DLV_OK;
144807dc194Richard Lowe        }
144907dc194Richard Lowe    }
145007dc194Richard Lowe    return DW_DLV_NO_ENTRY;
145107dc194Richard Lowe}
145207dc194Richard Lowe
145349d3bc9Richard Lowe
145449d3bc9Richard Lowe
145549d3bc9Richard Lowe/*---------------------------------------------------------------
145607dc194Richard Lowe        Generate debug_info and debug_abbrev sections
145749d3bc9Richard Lowe---------------------------------------------------------------*/
145849d3bc9Richard Lowestatic int
145949d3bc9Richard Lowe_dwarf_pro_generate_debuginfo(Dwarf_P_Debug dbg, Dwarf_Error * error)
146049d3bc9Richard Lowe{
146107dc194Richard Lowe    int elfsectno_of_debug_info = 0;
146207dc194Richard Lowe    int abbrevsectno = 0;
146307dc194Richard Lowe    unsigned char *data = 0;
146407dc194Richard Lowe    int cu_header_size = 0;
146507dc194Richard Lowe    Dwarf_P_Abbrev curabbrev = 0;
146607dc194Richard Lowe    Dwarf_P_Abbrev abbrev_head = 0;
146707dc194Richard Lowe    Dwarf_P_Abbrev abbrev_tail = 0;
146807dc194Richard Lowe    Dwarf_P_Die curdie = 0;
146907dc194Richard Lowe    Dwarf_P_Die first_child = 0;
147007dc194Richard Lowe    Dwarf_Word dw = 0;
147107dc194Richard Lowe    Dwarf_Unsigned du = 0;
147207dc194Richard Lowe    Dwarf_Half dh = 0;
147307dc194Richard Lowe    Dwarf_Ubyte db = 0;
147407dc194Richard Lowe    Dwarf_Half version = 0;     /* Need 2 byte quantity. */
147507dc194Richard Lowe    Dwarf_Unsigned die_off = 0; /* Offset of die in debug_info. */
147607dc194Richard Lowe    int n_abbrevs = 0;
147707dc194Richard Lowe    int res = 0;
147807dc194Richard Lowe    unsigned marker_count = 0;
147907dc194Richard Lowe    unsigned string_attr_count = 0;
148007dc194Richard Lowe    unsigned string_attr_offset = 0;
148107dc194Richard Lowe
148207dc194Richard Lowe    Dwarf_Small *start_info_sec = 0;
148307dc194Richard Lowe
148407dc194Richard Lowe    int uwordb_size = dbg->de_offset_size;
148549d3bc9Richard Lowe    int extension_size = dbg->de_64bit_extension ? 4 : 0;
148649d3bc9Richard Lowe
148749d3bc9Richard Lowe    abbrev_head = abbrev_tail = NULL;
148849d3bc9Richard Lowe    elfsectno_of_debug_info = dbg->de_elf_sects[DEBUG_INFO];
148949d3bc9Richard Lowe
149049d3bc9Richard Lowe    /* write cu header */
149107dc194Richard Lowe    cu_header_size = BEGIN_LEN_SIZE + sizeof(Dwarf_Half) +      /* version
149207dc194Richard Lowe                                                                   stamp
149307dc194Richard Lowe                                                                 */
149407dc194Richard Lowe        uwordb_size +           /* offset into abbrev table */
149507dc194Richard Lowe        sizeof(Dwarf_Ubyte);    /* size of target address */
149649d3bc9Richard Lowe    GET_CHUNK(dbg, elfsectno_of_debug_info, data, cu_header_size,
149707dc194Richard Lowe              error);
149849d3bc9Richard Lowe    start_info_sec = data;
149949d3bc9Richard Lowe    if (extension_size) {
150007dc194Richard Lowe        du = DISTINGUISHED_VALUE;
150107dc194Richard Lowe        WRITE_UNALIGNED(dbg, (void *) data,
150207dc194Richard Lowe                        (const void *) &du, sizeof(du), extension_size);
150307dc194Richard Lowe        data += extension_size;
150449d3bc9Richard Lowe    }
150507dc194Richard Lowe    du = 0;                     /* length of debug_info, not counting
150607dc194Richard Lowe                                   this field itself (unknown at this
150707dc194Richard Lowe                                   point). */
150849d3bc9Richard Lowe    WRITE_UNALIGNED(dbg, (void *) data,
150907dc194Richard Lowe                    (const void *) &du, sizeof(du), uwordb_size);
151007dc194Richard Lowe    data += uwordb_size;
151149d3bc9Richard Lowe
151207dc194Richard Lowe    version = CURRENT_VERSION_STAMP;    /* assume this length will not
151307dc194Richard Lowe                                           change */
151449d3bc9Richard Lowe    WRITE_UNALIGNED(dbg, (void *) data, (const void *) &version,
151507dc194Richard Lowe                    sizeof(version), sizeof(Dwarf_Half));
151649d3bc9Richard Lowe    data += sizeof(Dwarf_Half);
151749d3bc9Richard Lowe
151807dc194Richard Lowe    du = 0;                     /* offset into abbrev table, not yet
151907dc194Richard Lowe                                   known. */
152049d3bc9Richard Lowe    WRITE_UNALIGNED(dbg, (void *) data,
152107dc194Richard Lowe                    (const void *) &du, sizeof(du), uwordb_size);
152207dc194Richard Lowe    data += uwordb_size;
152349d3bc9Richard Lowe
152449d3bc9Richard Lowe
152549d3bc9Richard Lowe    db = dbg->de_pointer_size;
152649d3bc9Richard Lowe
152749d3bc9Richard Lowe    WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
152807dc194Richard Lowe                    sizeof(db), 1);
152949d3bc9Richard Lowe
153049d3bc9Richard Lowe    /* We have filled the chunk we got with GET_CHUNK. At this point we
153149d3bc9Richard Lowe       no longer dare use "data" or "start_info_sec" as a pointer any
153249d3bc9Richard Lowe       longer except to refer to that first small chunk for the cu
153349d3bc9Richard Lowe       header. */
153449d3bc9Richard Lowe
153549d3bc9Richard Lowe    curdie = dbg->de_dies;
153649d3bc9Richard Lowe
153749d3bc9Richard Lowe    /* create AT_macro_info if appropriate */
153849d3bc9Richard Lowe    if (dbg->de_first_macinfo != NULL) {
153907dc194Richard Lowe        if (_dwarf_pro_add_AT_macro_info(dbg, curdie, 0, error) < 0)
154007dc194Richard Lowe            return -1;
154149d3bc9Richard Lowe    }
154249d3bc9Richard Lowe
154349d3bc9Richard Lowe    /* create AT_stmt_list attribute if necessary */
154449d3bc9Richard Lowe    if (dwarf_need_debug_line_section(dbg) == TRUE)
154507dc194Richard Lowe        if (_dwarf_pro_add_AT_stmt_list(dbg, curdie, error) < 0)
154607dc194Richard Lowe            return -1;
154749d3bc9Richard Lowe
154849d3bc9Richard Lowe    die_off = cu_header_size;
154949d3bc9Richard Lowe
155049d3bc9Richard Lowe    /*
155149d3bc9Richard Lowe       Relocation for abbrev offset in cu header store relocation
155249d3bc9Richard Lowe       record in linked list */
155307dc194Richard Lowe    res = dbg->de_reloc_name(dbg, DEBUG_INFO, BEGIN_LEN_SIZE +
155407dc194Richard Lowe                             sizeof(Dwarf_Half),
155507dc194Richard Lowe                             /* r_offset */
155607dc194Richard Lowe                             dbg->de_sect_name_idx[DEBUG_ABBREV],
155707dc194Richard Lowe                             dwarf_drt_data_reloc, uwordb_size);
155849d3bc9Richard Lowe    if (res != DW_DLV_OK) {
155907dc194Richard Lowe        DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, -1);
156049d3bc9Richard Lowe    }
156149d3bc9Richard Lowe
156249d3bc9Richard Lowe    /* pass 0: only top level dies, add at_sibling attribute to those
156349d3bc9Richard Lowe       dies with children */
156449d3bc9Richard Lowe    first_child = curdie->di_child;
156549d3bc9Richard Lowe    while (first_child && first_child->di_right) {
156607dc194Richard Lowe        if (first_child->di_child)
156707dc194Richard Lowe            dwarf_add_AT_reference(dbg,
156807dc194Richard Lowe                                   first_child,
156907dc194Richard Lowe                                   DW_AT_sibling,
157007dc194Richard Lowe                                   first_child->di_right, error);
157107dc194Richard Lowe        first_child = first_child->di_right;
157249d3bc9Richard Lowe    }
157349d3bc9Richard Lowe
157449d3bc9Richard Lowe    /* pass 1: create abbrev info, get die offsets, calc relocations */
157507dc194Richard Lowe    marker_count = 0;
157607dc194Richard Lowe    string_attr_count = 0;
157749d3bc9Richard Lowe    while (curdie != NULL) {
157807dc194Richard Lowe        int nbytes = 0;
157907dc194Richard Lowe        Dwarf_P_Attribute curattr;
158007dc194Richard Lowe        Dwarf_P_Attribute new_first_attr;
158107dc194Richard Lowe        Dwarf_P_Attribute new_last_attr;
158207dc194Richard Lowe        char *space = 0;
158307dc194Richard Lowe        int res = 0;
158407dc194Richard Lowe        char buff1[ENCODE_SPACE_NEEDED];
158507dc194Richard Lowe        int i = 0;
158607dc194Richard Lowe
158707dc194Richard Lowe        curdie->di_offset = die_off;
158807dc194Richard Lowe
158907dc194Richard Lowe        if (curdie->di_marker != 0)
159007dc194Richard Lowe            marker_count++;
159107dc194Richard Lowe
159207dc194Richard Lowe        curabbrev = _dwarf_pro_getabbrev(curdie, abbrev_head);
159307dc194Richard Lowe        if (curabbrev == NULL) {
159407dc194Richard Lowe            DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
159507dc194Richard Lowe        }
159607dc194Richard Lowe        if (abbrev_head == NULL) {
159707dc194Richard Lowe            n_abbrevs = 1;
159807dc194Richard Lowe            curabbrev->abb_idx = n_abbrevs;
159907dc194Richard Lowe            abbrev_tail = abbrev_head = curabbrev;
160007dc194Richard Lowe        } else {
160107dc194Richard Lowe            /* check if its a new abbreviation, if yes, add to tail */
160207dc194Richard Lowe            if (curabbrev->abb_idx == 0) {
160307dc194Richard Lowe                n_abbrevs++;
160407dc194Richard Lowe                curabbrev->abb_idx = n_abbrevs;
160507dc194Richard Lowe                abbrev_tail->abb_next = curabbrev;
160607dc194Richard Lowe                abbrev_tail = curabbrev;
160707dc194Richard Lowe            }
160807dc194Richard Lowe        }
160907dc194Richard Lowe        res = _dwarf_pro_encode_leb128_nm(curabbrev->abb_idx,
161007dc194Richard Lowe                                          &nbytes,
161107dc194Richard Lowe                                          buff1, sizeof(buff1));
161207dc194Richard Lowe        if (res != DW_DLV_OK) {
161307dc194Richard Lowe            DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
161407dc194Richard Lowe        }
161507dc194Richard Lowe        space = _dwarf_p_get_alloc(dbg, nbytes);
161607dc194Richard Lowe        if (space == NULL) {
161707dc194Richard Lowe            DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
161807dc194Richard Lowe        }
161907dc194Richard Lowe        memcpy(space, buff1, nbytes);
162007dc194Richard Lowe        curdie->di_abbrev = space;
162107dc194Richard Lowe        curdie->di_abbrev_nbytes = nbytes;
162207dc194Richard Lowe        die_off += nbytes;
162307dc194Richard Lowe
162407dc194Richard Lowe        /* Resorting the attributes!! */
162507dc194Richard Lowe        new_first_attr = new_last_attr = NULL;
162607dc194Richard Lowe        curattr = curdie->di_attrs;
162707dc194Richard Lowe        for (i = 0; i < (int)curabbrev->abb_n_attr; i++) {
162807dc194Richard Lowe            Dwarf_P_Attribute ca;
162907dc194Richard Lowe            Dwarf_P_Attribute cl;
163007dc194Richard Lowe
163107dc194Richard Lowe            /* The following should always find an attribute! */
163207dc194Richard Lowe            for (ca = cl = curattr;
163307dc194Richard Lowe                 ca && curabbrev->abb_attrs[i] != ca->ar_attribute;
163407dc194Richard Lowe                 cl = ca, ca = ca->ar_next)
163507dc194Richard Lowe            {
163607dc194Richard Lowe            }
163707dc194Richard Lowe
163807dc194Richard Lowe            if (!ca) {
163907dc194Richard Lowe                DWARF_P_DBG_ERROR(dbg,DW_DLE_ABBREV_ALLOC, -1);
164007dc194Richard Lowe            }
164107dc194Richard Lowe
164207dc194Richard Lowe            /* Remove the attribute from the old list. */
164307dc194Richard Lowe            if (ca == curattr) {
164407dc194Richard Lowe                curattr = ca->ar_next;
164507dc194Richard Lowe            } else {
164607dc194Richard Lowe                cl->ar_next = ca->ar_next;
164707dc194Richard Lowe            }
164807dc194Richard Lowe
164907dc194Richard Lowe            ca->ar_next = NULL;
165007dc194Richard Lowe
165107dc194Richard Lowe            /* Add the attribute to the new list. */
165207dc194Richard Lowe            if (new_first_attr == NULL) {
165307dc194Richard Lowe                new_first_attr = new_last_attr = ca;
165407dc194Richard Lowe            } else {
165507dc194Richard Lowe                new_last_attr->ar_next = ca;
165607dc194Richard Lowe                new_last_attr = ca;
165707dc194Richard Lowe            }
165807dc194Richard Lowe        }
165907dc194Richard Lowe
166007dc194Richard Lowe        curdie->di_attrs = new_first_attr;
166107dc194Richard Lowe
166207dc194Richard Lowe        curattr = curdie->di_attrs;
166307dc194Richard Lowe
166407dc194Richard Lowe        while (curattr) {
166507dc194Richard Lowe            if (curattr->ar_rel_type != R_MIPS_NONE) {
166607dc194Richard Lowe                switch (curattr->ar_attribute) {
166707dc194Richard Lowe                case DW_AT_stmt_list:
166807dc194Richard Lowe                    curattr->ar_rel_symidx =
166907dc194Richard Lowe                        dbg->de_sect_name_idx[DEBUG_LINE];
167007dc194Richard Lowe                    break;
167107dc194Richard Lowe                case DW_AT_MIPS_fde:
167207dc194Richard Lowe                    curattr->ar_rel_symidx =
167307dc194Richard Lowe                        dbg->de_sect_name_idx[DEBUG_FRAME];
167407dc194Richard Lowe                    break;
167507dc194Richard Lowe                case DW_AT_macro_info:
167607dc194Richard Lowe                    curattr->ar_rel_symidx =
167707dc194Richard Lowe                        dbg->de_sect_name_idx[DEBUG_MACINFO];
167807dc194Richard Lowe                    break;
167907dc194Richard Lowe                default:
168007dc194Richard Lowe                    break;
168107dc194Richard Lowe                }
168207dc194Richard Lowe                res = dbg->de_reloc_name(dbg, DEBUG_INFO, die_off + curattr->ar_rel_offset,     /* r_offset
168307dc194Richard Lowe                                                                                                 */
168407dc194Richard Lowe                                         curattr->ar_rel_symidx,
168507dc194Richard Lowe                                         dwarf_drt_data_reloc,
168607dc194Richard Lowe                                         curattr->ar_reloc_len);
168707dc194Richard Lowe
168807dc194Richard Lowe                if (res != DW_DLV_OK) {
168907dc194Richard Lowe                    DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, -1);
169007dc194Richard Lowe                }
169107dc194Richard Lowe
169207dc194Richard Lowe            }
169307dc194Richard Lowe            if (curattr->ar_attribute_form == DW_FORM_string) {
169407dc194Richard Lowe                string_attr_count++;
169507dc194Richard Lowe            }
169607dc194Richard Lowe            die_off += curattr->ar_nbytes;
169707dc194Richard Lowe            curattr = curattr->ar_next;
169807dc194Richard Lowe        }
169907dc194Richard Lowe
170007dc194Richard Lowe        /* depth first search */
170107dc194Richard Lowe        if (curdie->di_child)
170207dc194Richard Lowe            curdie = curdie->di_child;
170307dc194Richard Lowe        else {
170407dc194Richard Lowe            while (curdie != NULL && curdie->di_right == NULL) {
170507dc194Richard Lowe                curdie = curdie->di_parent;
170607dc194Richard Lowe                die_off++;      /* since we are writing a null die at
170707dc194Richard Lowe                                   the end of each sibling chain */
170807dc194Richard Lowe            }
170907dc194Richard Lowe            if (curdie != NULL)
171007dc194Richard Lowe                curdie = curdie->di_right;
171107dc194Richard Lowe        }
171207dc194Richard Lowe
171307dc194Richard Lowe    } /* end while (curdie != NULL) */
171407dc194Richard Lowe
171507dc194Richard Lowe    res = marker_init(dbg, marker_count);
171607dc194Richard Lowe    if (res == -1) {
171707dc194Richard Lowe        DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, -1);
171849d3bc9Richard Lowe    }
171907dc194Richard Lowe    res = string_attr_init(dbg, DEBUG_INFO, string_attr_count);
172007dc194Richard Lowe    if (res == -1) {
172107dc194Richard Lowe        DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, -1);
172207dc194Richard Lowe    }
172307dc194Richard Lowe
172449d3bc9Richard Lowe    /* Pass 2: Write out the die information Here 'data' is a
172549d3bc9Richard Lowe       temporary, one block for each GET_CHUNK.  'data' is overused. */
172649d3bc9Richard Lowe    curdie = dbg->de_dies;
172749d3bc9Richard Lowe    while (curdie != NULL) {
172807dc194Richard Lowe        Dwarf_P_Attribute curattr;
172907dc194Richard Lowe
173007dc194Richard Lowe        if (curdie->di_marker != 0) {
173107dc194Richard Lowe            res = marker_add(dbg, curdie->di_offset, curdie->di_marker);
173207dc194Richard Lowe            if (res == -1) {
173307dc194Richard Lowe                DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, -1);
173407dc194Richard Lowe            }
173507dc194Richard Lowe        }
173607dc194Richard Lowe
173707dc194Richard Lowe        /* index to abbreviation table */
173807dc194Richard Lowe        GET_CHUNK(dbg, elfsectno_of_debug_info,
173907dc194Richard Lowe                  data, curdie->di_abbrev_nbytes, error);
174007dc194Richard Lowe
174107dc194Richard Lowe        memcpy((void *) data,
174207dc194Richard Lowe               (const void *) curdie->di_abbrev,
174307dc194Richard Lowe               curdie->di_abbrev_nbytes);
174407dc194Richard Lowe
174507dc194Richard Lowe        /* Attribute values - need to fill in all form attributes */
174607dc194Richard Lowe        curattr = curdie->di_attrs;
174707dc194Richard Lowe        string_attr_offset = curdie->di_offset + curdie->di_abbrev_nbytes;
174807dc194Richard Lowe
174907dc194Richard Lowe        while (curattr) {
175007dc194Richard Lowe            GET_CHUNK(dbg, elfsectno_of_debug_info, data,
175107dc194Richard Lowe                      (unsigned long) curattr->ar_nbytes, error);
175207dc194Richard Lowe            switch (curattr->ar_attribute_form) {
175307dc194Richard Lowe            case DW_FORM_ref1:
175407dc194Richard Lowe                {
175507dc194Richard Lowe                    if (curattr->ar_ref_die->di_offset >
175607dc194Richard Lowe                        (unsigned) 0xff) {
175707dc194Richard Lowe                        DWARF_P_DBG_ERROR(dbg, DW_DLE_OFFSET_UFLW, -1);
175807dc194Richard Lowe                    }
175907dc194Richard Lowe                    db = curattr->ar_ref_die->di_offset;
176007dc194Richard Lowe                    WRITE_UNALIGNED(dbg, (void *) data,
176107dc194Richard Lowe                                    (const void *) &db,
176207dc194Richard Lowe                                    sizeof(db), sizeof(Dwarf_Ubyte));
176307dc194Richard Lowe                    break;
176407dc194Richard Lowe                }
176507dc194Richard Lowe            case DW_FORM_ref2:
176607dc194Richard Lowe                {
176707dc194Richard Lowe                    if (curattr->ar_ref_die->di_offset >
176807dc194Richard Lowe                        (unsigned) 0xffff) {
176907dc194Richard Lowe                        DWARF_P_DBG_ERROR(dbg, DW_DLE_OFFSET_UFLW, -1);
177007dc194Richard Lowe                    }
177107dc194Richard Lowe                    dh = curattr->ar_ref_die->di_offset;
177207dc194Richard Lowe                    WRITE_UNALIGNED(dbg, (void *) data,
177307dc194Richard Lowe                                    (const void *) &dh,
177407dc194Richard Lowe                                    sizeof(dh), sizeof(Dwarf_Half));
177507dc194Richard Lowe                    break;
177607dc194Richard Lowe                }
177707dc194Richard Lowe            case DW_FORM_ref_addr:
177807dc194Richard Lowe                {
177907dc194Richard Lowe                    /* curattr->ar_ref_die == NULL!
178007dc194Richard Lowe                     *
178107dc194Richard Lowe                     * ref_addr doesn't take a CU-offset.
178207dc194Richard Lowe                     * This is different than other refs.
178307dc194Richard Lowe                     * This value will be set by the user of the
178407dc194Richard Lowe                     * producer library using a relocation.
178507dc194Richard Lowe                     * No need to set a value here.
178607dc194Richard Lowe                     */
178707dc194Richard Lowe#if 0
178807dc194Richard Lowe                    du = curattr->ar_ref_die->di_offset;
178907dc194Richard Lowe                    {
179007dc194Richard Lowe                        /* ref to offset of die */
179107dc194Richard Lowe                        WRITE_UNALIGNED(dbg, (void *) data,
179207dc194Richard Lowe                                        (const void *) &du,
179307dc194Richard Lowe                                        sizeof(du), uwordb_size);
179407dc194Richard Lowe                    }
179507dc194Richard Lowe#endif
179607dc194Richard Lowe                    break;
179707dc194Richard Lowe
179807dc194Richard Lowe                }
179907dc194Richard Lowe            case DW_FORM_ref4:
180007dc194Richard Lowe                {
180107dc194Richard Lowe                    if (curattr->ar_ref_die->di_offset >
180207dc194Richard Lowe                        (unsigned) 0xffffffff) {
180307dc194Richard Lowe                        DWARF_P_DBG_ERROR(dbg, DW_DLE_OFFSET_UFLW, -1);
180407dc194Richard Lowe                    }
180507dc194Richard Lowe                    dw = (Dwarf_Word) curattr->ar_ref_die->di_offset;
180607dc194Richard Lowe                    WRITE_UNALIGNED(dbg, (void *) data,
180707dc194Richard Lowe                                    (const void *) &dw,
180807dc194Richard Lowe                                    sizeof(dw), sizeof(Dwarf_ufixed));
180907dc194Richard Lowe                    break;
181007dc194Richard Lowe                }
181107dc194Richard Lowe            case DW_FORM_ref8:
181207dc194Richard Lowe                du = curattr->ar_ref_die->di_offset;
181307dc194Richard Lowe                WRITE_UNALIGNED(dbg, (void *) data,
181407dc194Richard Lowe                                (const void *) &du,
181507dc194Richard Lowe                                sizeof(du), sizeof(Dwarf_Unsigned));
181607dc194Richard Lowe                break;
181707dc194Richard Lowe            case DW_FORM_ref_udata:
181807dc194Richard Lowe                {               /* unsigned leb128 offset */
181907dc194Richard Lowe
182007dc194Richard Lowe                    int nbytes;
182107dc194Richard Lowe                    char buff1[ENCODE_SPACE_NEEDED];
182207dc194Richard Lowe
182307dc194Richard Lowe                    res =
182407dc194Richard Lowe                        _dwarf_pro_encode_leb128_nm(curattr->
182507dc194Richard Lowe                                                    ar_ref_die->
182607dc194Richard Lowe                                                    di_offset, &nbytes,
182707dc194Richard Lowe                                                    buff1,
182807dc194Richard Lowe                                                    sizeof(buff1));
182907dc194Richard Lowe                    if (res != DW_DLV_OK) {
183007dc194Richard Lowe                        DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
183107dc194Richard Lowe                    }
183207dc194Richard Lowe
183307dc194Richard Lowe                    memcpy(data, buff1, nbytes);
183407dc194Richard Lowe                    break;
183507dc194Richard Lowe                }
183607dc194Richard Lowe            default:
183707dc194Richard Lowe                memcpy((void *) data,
183807dc194Richard Lowe                       (const void *) curattr->ar_data,
183907dc194Richard Lowe                       curattr->ar_nbytes);
184007dc194Richard Lowe                break;
184107dc194Richard Lowe            }
184207dc194Richard Lowe            if (curattr->ar_attribute_form == DW_FORM_string) {
184307dc194Richard Lowe                string_attr_add(dbg, DEBUG_INFO, string_attr_offset, curattr);
184407dc194Richard Lowe            }
184507dc194Richard Lowe            string_attr_offset += curattr->ar_nbytes;
184607dc194Richard Lowe            curattr = curattr->ar_next;
184707dc194Richard Lowe        }
184807dc194Richard Lowe
184907dc194Richard Lowe        /* depth first search */
185007dc194Richard Lowe        if (curdie->di_child)
185107dc194Richard Lowe            curdie = curdie->di_child;
185207dc194Richard Lowe        else {
185307dc194Richard Lowe            while (curdie != NULL && curdie->di_right == NULL) {
185407dc194Richard Lowe                GET_CHUNK(dbg, elfsectno_of_debug_info, data, 1, error);
185507dc194Richard Lowe                *data = '\0';
185607dc194Richard Lowe                curdie = curdie->di_parent;
185707dc194Richard Lowe            }
185807dc194Richard Lowe            if (curdie != NULL)
185907dc194Richard Lowe                curdie = curdie->di_right;
186007dc194Richard Lowe        }
186107dc194Richard Lowe    } /* end while (curdir != NULL) */
186249d3bc9Richard Lowe
186349d3bc9Richard Lowe    /* Write out debug_info size */
186449d3bc9Richard Lowe    /* Dont include length field or extension bytes */
186507dc194Richard Lowe    du = die_off - BEGIN_LEN_SIZE;
186649d3bc9Richard Lowe    WRITE_UNALIGNED(dbg, (void *) (start_info_sec + extension_size),
186707dc194Richard Lowe                    (const void *) &du, sizeof(du), uwordb_size);
186849d3bc9Richard Lowe
186949d3bc9Richard Lowe
187007dc194Richard Lowe    data = 0;                   /* Emphasise not usable now */
187149d3bc9Richard Lowe
187249d3bc9Richard Lowe    /* Write out debug_abbrev section */
187349d3bc9Richard Lowe    abbrevsectno = dbg->de_elf_sects[DEBUG_ABBREV];
187449d3bc9Richard Lowe
187549d3bc9Richard Lowe    curabbrev = abbrev_head;
187649d3bc9Richard Lowe    while (curabbrev) {
187707dc194Richard Lowe        char *val;
187807dc194Richard Lowe        int nbytes;
187907dc194Richard Lowe        int idx;
188007dc194Richard Lowe        int res;
188107dc194Richard Lowe        char buff1[ENCODE_SPACE_NEEDED];
188207dc194Richard Lowe
188307dc194Richard Lowe        res = _dwarf_pro_encode_leb128_nm(curabbrev->abb_idx, &nbytes,
188407dc194Richard Lowe                                          buff1, sizeof(buff1));
188507dc194Richard Lowe        if (res != DW_DLV_OK) {
188607dc194Richard Lowe            DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
188707dc194Richard Lowe        }
188807dc194Richard Lowe
188907dc194Richard Lowe        GET_CHUNK(dbg, abbrevsectno, data, nbytes, error);
189007dc194Richard Lowe        val = buff1;
189107dc194Richard Lowe        memcpy((void *) data, (const void *) val, nbytes);
189207dc194Richard Lowe        res = _dwarf_pro_encode_leb128_nm(curabbrev->abb_tag, &nbytes,
189307dc194Richard Lowe                                          buff1, sizeof(buff1));
189407dc194Richard Lowe        if (res != DW_DLV_OK) {
189507dc194Richard Lowe            DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
189607dc194Richard Lowe        }
189707dc194Richard Lowe        val = buff1;
189807dc194Richard Lowe        GET_CHUNK(dbg, abbrevsectno, data, nbytes, error);
189907dc194Richard Lowe        memcpy((void *) data, (const void *) val, nbytes);
190007dc194Richard Lowe        db = curabbrev->abb_children;
190107dc194Richard Lowe        GET_CHUNK(dbg, abbrevsectno, data, sizeof(Dwarf_Ubyte), error);
190207dc194Richard Lowe        WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
190307dc194Richard Lowe                        sizeof(db), sizeof(Dwarf_Ubyte));
190407dc194Richard Lowe
190507dc194Richard Lowe        /* add attributes and forms */
190607dc194Richard Lowe        for (idx = 0; idx < curabbrev->abb_n_attr; idx++) {
190707dc194Richard Lowe            res = _dwarf_pro_encode_leb128_nm(curabbrev->abb_attrs[idx],
190807dc194Richard Lowe                                              &nbytes,
190907dc194Richard Lowe                                              buff1, sizeof(buff1));
191007dc194Richard Lowe            if (res != DW_DLV_OK) {
191107dc194Richard Lowe                DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
191207dc194Richard Lowe            }
191307dc194Richard Lowe            val = buff1;
191407dc194Richard Lowe            GET_CHUNK(dbg, abbrevsectno, data, nbytes, error);
191507dc194Richard Lowe            memcpy((void *) data, (const void *) val, nbytes);
191607dc194Richard Lowe            res = _dwarf_pro_encode_leb128_nm(curabbrev->abb_forms[idx],
191707dc194Richard Lowe                                              &nbytes,
191807dc194Richard Lowe                                              buff1, sizeof(buff1));
191907dc194Richard Lowe            if (res != DW_DLV_OK) {
192007dc194Richard Lowe                DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
192107dc194Richard Lowe            }
192207dc194Richard Lowe            val = buff1;
192307dc194Richard Lowe            GET_CHUNK(dbg, abbrevsectno, data, nbytes, error);
192407dc194Richard Lowe            memcpy((void *) data, (const void *) val, nbytes);
192507dc194Richard Lowe        }
192607dc194Richard Lowe        GET_CHUNK(dbg, abbrevsectno, data, 2, error);   /* two zeros,
192707dc194Richard Lowe                                                           for last
192807dc194Richard Lowe                                                           entry, see
192907dc194Richard Lowe                                                           dwarf2 sec
193007dc194Richard Lowe                                                           7.5.3 */
193107dc194Richard Lowe        *data = 0;
193207dc194Richard Lowe        data++;
193307dc194Richard Lowe        *data = 0;
193407dc194Richard Lowe
193507dc194Richard Lowe        curabbrev = curabbrev->abb_next;
193649d3bc9Richard Lowe    }
193749d3bc9Richard Lowe
193807dc194Richard Lowe    GET_CHUNK(dbg, abbrevsectno, data, 1, error);       /* one zero,
193907dc194Richard Lowe                                                           for end of
194007dc194Richard Lowe                                                           cu, see
194107dc194Richard Lowe                                                           dwarf2 sec
194207dc194Richard Lowe                                                           7.5.3 */
194349d3bc9Richard Lowe    *data = 0;
194407dc194Richard Lowe
194549d3bc9Richard Lowe
194649d3bc9Richard Lowe    return (int) dbg->de_n_debug_sect;
194749d3bc9Richard Lowe}
194849d3bc9Richard Lowe
194949d3bc9Richard Lowe
195049d3bc9Richard Lowe/*---------------------------------------------------------------------
195107dc194Richard Lowe        Get a buffer of section data.
195207dc194Richard Lowe        section_idx is the elf-section number that this data applies to.
195307dc194Richard Lowe        length shows length of returned data
195449d3bc9Richard Lowe----------------------------------------------------------------------*/
195507dc194Richard Lowe /*ARGSUSED*/                   /* pretend all args used */
195649d3bc9Richard Lowe    Dwarf_Ptr
195749d3bc9Richard Lowedwarf_get_section_bytes(Dwarf_P_Debug dbg,
195807dc194Richard Lowe                        Dwarf_Signed dwarf_section,
195907dc194Richard Lowe                        Dwarf_Signed * section_idx,
196007dc194Richard Lowe                        Dwarf_Unsigned * length, Dwarf_Error * error)
196149d3bc9Richard Lowe{
196249d3bc9Richard Lowe    Dwarf_Ptr buf;
196349d3bc9Richard Lowe
196449d3bc9Richard Lowe    if (dbg->de_version_magic_number != PRO_VERSION_MAGIC) {
196507dc194Richard Lowe        DWARF_P_DBG_ERROR(dbg, DW_DLE_IA, NULL);
196649d3bc9Richard Lowe    }
196749d3bc9Richard Lowe
196849d3bc9Richard Lowe    if (dbg->de_debug_sects == 0) {
196907dc194Richard Lowe        /* no more data !! */
197007dc194Richard Lowe        return NULL;
197149d3bc9Richard Lowe    }
197249d3bc9Richard Lowe    if (dbg->de_debug_sects->ds_elf_sect_no == MAGIC_SECT_NO) {
197307dc194Richard Lowe        /* no data ever entered !! */
197407dc194Richard Lowe        return NULL;
197549d3bc9Richard Lowe    }
197649d3bc9Richard Lowe    *section_idx = dbg->de_debug_sects->ds_elf_sect_no;
197749d3bc9Richard Lowe    *length = dbg->de_debug_sects->ds_nbytes;
197849d3bc9Richard Lowe
197949d3bc9Richard Lowe    buf = (Dwarf_Ptr *) dbg->de_debug_sects->ds_data;
198049d3bc9Richard Lowe
198149d3bc9Richard Lowe    dbg->de_debug_sects = dbg->de_debug_sects->ds_next;
198249d3bc9Richard Lowe
198349d3bc9Richard Lowe    /* We may want to call the section stuff more than once: see
198449d3bc9Richard Lowe       dwarf_reset_section_bytes() do not do: dbg->de_n_debug_sect--; */
198549d3bc9Richard Lowe
198649d3bc9Richard Lowe    return buf;
198749d3bc9Richard Lowe}
198849d3bc9Richard Lowe
198949d3bc9Richard Lowe/*
199007dc194Richard Lowe        No errors possible.
199149d3bc9Richard Lowe*/
199249d3bc9Richard Lowevoid
199349d3bc9Richard Lowedwarf_reset_section_bytes(Dwarf_P_Debug dbg)
199449d3bc9Richard Lowe{
199549d3bc9Richard Lowe    dbg->de_debug_sects = dbg->de_first_debug_sect;
199649d3bc9Richard Lowe    /* No need to reset; commented out decrement. dbg->de_n_debug_sect
199749d3bc9Richard Lowe       = ???; */
199849d3bc9Richard Lowe    dbg->de_reloc_next_to_return = 0;
199907dc194Richard Lowe    dbg->de_sect_sa_next_to_return = 0;
200049d3bc9Richard Lowe}
200149d3bc9Richard Lowe
200249d3bc9Richard Lowe/*
200349d3bc9Richard Lowe    Storage handler. Gets either a new chunk of memory, or
200449d3bc9Richard Lowe    a pointer in existing memory, from the linked list attached
200549d3bc9Richard Lowe    to dbg at de_debug_sects, depending on size of nbytes
200649d3bc9Richard Lowe
200749d3bc9Richard Lowe    Assume dbg not null, checked in top level routine
200849d3bc9Richard Lowe
200949d3bc9Richard Lowe    Returns a pointer to the allocated buffer space for the
201049d3bc9Richard Lowe    lib to fill in,  predincrements next-to-use count so the
201149d3bc9Richard Lowe    space requested is already counted 'used'
201249d3bc9Richard Lowe    when this returns (ie, reserved).
201349d3bc9Richard Lowe
201449d3bc9Richard Lowe*/
201549d3bc9Richard LoweDwarf_Small *
201649d3bc9Richard Lowe_dwarf_pro_buffer(Dwarf_P_Debug dbg,
201707dc194Richard Lowe                  int elfsectno, unsigned long nbytes)
201849d3bc9Richard Lowe{
201949d3bc9Richard Lowe    Dwarf_P_Section_Data cursect;
202049d3bc9Richard Lowe
202149d3bc9Richard Lowe
202249d3bc9Richard Lowe    cursect = dbg->de_current_active_section;
202349d3bc9Richard Lowe    /* By using MAGIC_SECT_NO we allow the following MAGIC_SECT_NO must
202449d3bc9Richard Lowe       not match any legit section number. test to have just two
202549d3bc9Richard Lowe       clauses (no NULL pointer test) See dwarf_producer_init(). */
202649d3bc9Richard Lowe    if ((cursect->ds_elf_sect_no != elfsectno) ||
202707dc194Richard Lowe        ((cursect->ds_nbytes + nbytes) > cursect->ds_orig_alloc)
202807dc194Richard Lowe        ) {
202907dc194Richard Lowe
203007dc194Richard Lowe        /* Either the elf section has changed or there is not enough
203107dc194Richard Lowe           space in the current section.
203207dc194Richard Lowe
203307dc194Richard Lowe           Create a new Dwarf_P_Section_Data_s for the chunk. and have
203407dc194Richard Lowe           space 'on the end' for the buffer itself so we just do one
203507dc194Richard Lowe           malloc (not two).
203607dc194Richard Lowe
203707dc194Richard Lowe         */
203807dc194Richard Lowe        unsigned long space = nbytes;
203907dc194Richard Lowe
204007dc194Richard Lowe        if (nbytes < CHUNK_SIZE)
204107dc194Richard Lowe            space = CHUNK_SIZE;
204207dc194Richard Lowe
204307dc194Richard Lowe        cursect = (Dwarf_P_Section_Data)
204407dc194Richard Lowe            _dwarf_p_get_alloc(dbg,
204507dc194Richard Lowe                               sizeof(struct Dwarf_P_Section_Data_s)
204607dc194Richard Lowe                               + space);
204707dc194Richard Lowe
204807dc194Richard Lowe
204907dc194Richard Lowe        if (cursect == NULL)
205007dc194Richard Lowe            return (NULL);
205107dc194Richard Lowe
205207dc194Richard Lowe        /* _dwarf_p_get_alloc zeroes the space... */
205307dc194Richard Lowe
205407dc194Richard Lowe        cursect->ds_data = (char *) cursect +
205507dc194Richard Lowe            sizeof(struct Dwarf_P_Section_Data_s);
205607dc194Richard Lowe        cursect->ds_orig_alloc = space;
205707dc194Richard Lowe        cursect->ds_elf_sect_no = elfsectno;
205807dc194Richard Lowe        cursect->ds_nbytes = nbytes;    /* reserve this number of bytes
205907dc194Richard Lowe                                           of space for caller to fill
206007dc194Richard Lowe                                           in */
206107dc194Richard Lowe
206207dc194Richard Lowe        /* Now link on the end of the list, and mark this one as the
206307dc194Richard Lowe           current one */
206407dc194Richard Lowe
206507dc194Richard Lowe        if (dbg->de_debug_sects->ds_elf_sect_no == MAGIC_SECT_NO) {
206607dc194Richard Lowe            /* the only entry is the special one for 'no entry' so
206707dc194Richard Lowe               delete that phony one while adding this initial real
206807dc194Richard Lowe               one. */
206907dc194Richard Lowe            dbg->de_debug_sects = cursect;
207007dc194Richard Lowe            dbg->de_current_active_section = cursect;
207107dc194Richard Lowe            dbg->de_first_debug_sect = cursect;
207207dc194Richard Lowe        } else {
207307dc194Richard Lowe            dbg->de_current_active_section->ds_next = cursect;
207407dc194Richard Lowe            dbg->de_current_active_section = cursect;
207507dc194Richard Lowe        }
207607dc194Richard Lowe        dbg->de_n_debug_sect++;
207707dc194Richard Lowe
207807dc194Richard Lowe        return ((Dwarf_Small *) cursect->ds_data);
207949d3bc9Richard Lowe    }
208049d3bc9Richard Lowe
208149d3bc9Richard Lowe    /* There is enough space in the current buffer */
208249d3bc9Richard Lowe    {
208307dc194Richard Lowe        Dwarf_Small *space_for_caller = (Dwarf_Small *)
208407dc194Richard Lowe            (cursect->ds_data + cursect->ds_nbytes);
208549d3bc9Richard Lowe
208607dc194Richard Lowe        cursect->ds_nbytes += nbytes;
208707dc194Richard Lowe        return space_for_caller;
208849d3bc9Richard Lowe    }
208949d3bc9Richard Lowe}
209049d3bc9Richard Lowe
209149d3bc9Richard Lowe
209249d3bc9Richard Lowe/*------------------------------------------------------------
209307dc194Richard Lowe        Given address advance and line advance, it gives
209407dc194Richard Lowe        either special opcode, or a number < 0
209549d3bc9Richard Lowe------------------------------------------------------------*/
209649d3bc9Richard Lowestatic int
209749d3bc9Richard Lowe_dwarf_pro_get_opc(Dwarf_Unsigned addr_adv, int line_adv)
209849d3bc9Richard Lowe{
209949d3bc9Richard Lowe    int opc;
210049d3bc9Richard Lowe
210149d3bc9Richard Lowe    addr_adv = addr_adv / MIN_INST_LENGTH;
210249d3bc9Richard Lowe    if (line_adv == 0 && addr_adv == 0)
210307dc194Richard Lowe        return OPC_INCS_ZERO;
210449d3bc9Richard Lowe    if (line_adv >= LINE_BASE && line_adv < LINE_BASE + LINE_RANGE) {
210507dc194Richard Lowe        opc =
210607dc194Richard Lowe            (line_adv - LINE_BASE) + (addr_adv * LINE_RANGE) +
210707dc194Richard Lowe            OPCODE_BASE;
210807dc194Richard Lowe        if (opc > 255)
210907dc194Richard Lowe            return OPC_OUT_OF_RANGE;
211007dc194Richard Lowe        return opc;
211149d3bc9Richard Lowe    } else
211207dc194Richard Lowe        return LINE_OUT_OF_RANGE;
211349d3bc9Richard Lowe}
211449d3bc9Richard Lowe
211549d3bc9Richard Lowe/*-----------------------------------------------------------------------
211607dc194Richard Lowe        Handles abbreviations. It takes a die, searches through
211707dc194Richard Lowe        current list of abbreviations for matching one. If it
211807dc194Richard Lowe        finds one, it returns a pointer to it, and if it doesnt,
211907dc194Richard Lowe        it returns a new one. Upto the user of this function to
212007dc194Richard Lowe        link it up to the abbreviation head. If its a new one,
212107dc194Richard Lowe        abb_idx has 0.
212249d3bc9Richard Lowe-----------------------------------------------------------------------*/
212349d3bc9Richard Lowestatic Dwarf_P_Abbrev
212449d3bc9Richard Lowe_dwarf_pro_getabbrev(Dwarf_P_Die die, Dwarf_P_Abbrev head)
212549d3bc9Richard Lowe{
212649d3bc9Richard Lowe    Dwarf_P_Abbrev curabbrev;
212749d3bc9Richard Lowe    Dwarf_P_Attribute curattr;
212849d3bc9Richard Lowe    int res1;
212949d3bc9Richard Lowe    int nattrs;
213049d3bc9Richard Lowe    int match;
213149d3bc9Richard Lowe    Dwarf_ufixed *forms = 0;
213249d3bc9Richard Lowe    Dwarf_ufixed *attrs = 0;
213349d3bc9Richard Lowe
213449d3bc9Richard Lowe    curabbrev = head;
213549d3bc9Richard Lowe    while (curabbrev) {
213607dc194Richard Lowe        if ((die->di_tag == curabbrev->abb_tag) &&
213707dc194Richard Lowe            ((die->di_child != NULL &&
213807dc194Richard Lowe              curabbrev->abb_children == DW_CHILDREN_yes) ||
213907dc194Richard Lowe             (die->di_child == NULL &&
214007dc194Richard Lowe              curabbrev->abb_children == DW_CHILDREN_no)) &&
214107dc194Richard Lowe            (die->di_n_attr == curabbrev->abb_n_attr)) {
214207dc194Richard Lowe
214307dc194Richard Lowe            /* There is a chance of a match. */
214407dc194Richard Lowe            curattr = die->di_attrs;
214507dc194Richard Lowe            match = 1;          /* Assume match found. */
214607dc194Richard Lowe            while (match && curattr) {
214707dc194Richard Lowe                res1 = _dwarf_pro_match_attr(curattr,
214807dc194Richard Lowe                                             curabbrev,
214907dc194Richard Lowe                                             (int) curabbrev->
215007dc194Richard Lowe                                             abb_n_attr);
215107dc194Richard Lowe                if (res1 == 0)
215207dc194Richard Lowe                    match = 0;
215307dc194Richard Lowe                curattr = curattr->ar_next;
215407dc194Richard Lowe            }
215507dc194Richard Lowe            if (match == 1)
215607dc194Richard Lowe                return curabbrev;
215707dc194Richard Lowe        }
215807dc194Richard Lowe        curabbrev = curabbrev->abb_next;
215949d3bc9Richard Lowe    }
216049d3bc9Richard Lowe
216149d3bc9Richard Lowe    /* no match, create new abbreviation */
216249d3bc9Richard Lowe    if (die->di_n_attr != 0) {
216307dc194Richard Lowe        forms = (Dwarf_ufixed *)
216407dc194Richard Lowe            _dwarf_p_get_alloc(die->di_dbg,
216507dc194Richard Lowe                               sizeof(Dwarf_ufixed) * die->di_n_attr);
216607dc194Richard Lowe        if (forms == NULL)
216707dc194Richard Lowe            return NULL;
216807dc194Richard Lowe        attrs = (Dwarf_ufixed *)
216907dc194Richard Lowe            _dwarf_p_get_alloc(die->di_dbg,
217007dc194Richard Lowe                               sizeof(Dwarf_ufixed) * die->di_n_attr);
217107dc194Richard Lowe        if (attrs == NULL)
217207dc194Richard Lowe            return NULL;
217349d3bc9Richard Lowe    }
217449d3bc9Richard Lowe    nattrs = 0;
217549d3bc9Richard Lowe    curattr = die->di_attrs;
217649d3bc9Richard Lowe    while (curattr) {
217707dc194Richard Lowe        attrs[nattrs] = curattr->ar_attribute;
217807dc194Richard Lowe        forms[nattrs] = curattr->ar_attribute_form;
217907dc194Richard Lowe        nattrs++;
218007dc194Richard Lowe        curattr = curattr->ar_next;
218149d3bc9Richard Lowe    }
218249d3bc9Richard Lowe
218349d3bc9Richard Lowe    curabbrev = (Dwarf_P_Abbrev)
218407dc194Richard Lowe        _dwarf_p_get_alloc(die->di_dbg, sizeof(struct Dwarf_P_Abbrev_s));
218549d3bc9Richard Lowe    if (curabbrev == NULL)
218607dc194Richard Lowe        return NULL;
218749d3bc9Richard Lowe
218849d3bc9Richard Lowe    if (die->di_child == NULL)
218907dc194Richard Lowe        curabbrev->abb_children = DW_CHILDREN_no;
219049d3bc9Richard Lowe    else
219107dc194Richard Lowe        curabbrev->abb_children = DW_CHILDREN_yes;
219249d3bc9Richard Lowe    curabbrev->abb_tag = die->di_tag;
219349d3bc9Richard Lowe    curabbrev->abb_attrs = attrs;
219449d3bc9Richard Lowe    curabbrev->abb_forms = forms;
219549d3bc9Richard Lowe    curabbrev->abb_n_attr = die->di_n_attr;
219649d3bc9Richard Lowe    curabbrev->abb_idx = 0;
219749d3bc9Richard Lowe    curabbrev->abb_next = NULL;
219849d3bc9Richard Lowe
219949d3bc9Richard Lowe    return curabbrev;
220049d3bc9Richard Lowe}
220149d3bc9Richard Lowe
220249d3bc9Richard Lowe/*------------------------------------------------------------------
220307dc194Richard Lowe        Tries to see if given attribute and form combination
220407dc194Richard Lowe        exists in the given abbreviation
220549d3bc9Richard Lowe-------------------------------------------------------------------*/
220649d3bc9Richard Lowestatic int
220749d3bc9Richard Lowe_dwarf_pro_match_attr(Dwarf_P_Attribute attr,
220807dc194Richard Lowe                      Dwarf_P_Abbrev abbrev, int no_attr)
220949d3bc9Richard Lowe{
221049d3bc9Richard Lowe    int i;
221149d3bc9Richard Lowe    int found = 0;
221249d3bc9Richard Lowe
221349d3bc9Richard Lowe    for (i = 0; i < no_attr; i++) {
221407dc194Richard Lowe        if (attr->ar_attribute == abbrev->abb_attrs[i] &&
221507dc194Richard Lowe            attr->ar_attribute_form == abbrev->abb_forms[i]) {
221607dc194Richard Lowe            found = 1;
221707dc194Richard Lowe            break;
221807dc194Richard Lowe        }
221949d3bc9Richard Lowe    }
222049d3bc9Richard Lowe    return found;
222149d3bc9Richard Lowe}
2222