149d3bc9Richard Lowe/*
249d3bc9Richard Lowe
307dc194Richard Lowe  Copyright (C) 2000,2004 Silicon Graphics, Inc.  All Rights Reserved.
407dc194Richard Lowe  Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved.
54d9fdb4Robert Mustacchi  Portions Copyright 2011-2017 David Anderson.  All Rights Reserved.
64d9fdb4Robert Mustacchi
74d9fdb4Robert Mustacchi  This program is free software; you can redistribute it
84d9fdb4Robert Mustacchi  and/or modify it under the terms of version 2.1 of the
94d9fdb4Robert Mustacchi  GNU Lesser General Public License as published by the Free
104d9fdb4Robert Mustacchi  Software Foundation.
114d9fdb4Robert Mustacchi
124d9fdb4Robert Mustacchi  This program is distributed in the hope that it would be
134d9fdb4Robert Mustacchi  useful, but WITHOUT ANY WARRANTY; without even the implied
144d9fdb4Robert Mustacchi  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
154d9fdb4Robert Mustacchi  PURPOSE.
164d9fdb4Robert Mustacchi
174d9fdb4Robert Mustacchi  Further, this software is distributed without any warranty
184d9fdb4Robert Mustacchi  that it is free of the rightful claim of any third person
194d9fdb4Robert Mustacchi  regarding infringement or the like.  Any license provided
204d9fdb4Robert Mustacchi  herein, whether implied or otherwise, applies only to this
214d9fdb4Robert Mustacchi  software file.  Patent licenses, if any, provided herein
224d9fdb4Robert Mustacchi  do not apply to combinations of this program with other
234d9fdb4Robert Mustacchi  software, or any other product whatsoever.
244d9fdb4Robert Mustacchi
254d9fdb4Robert Mustacchi  You should have received a copy of the GNU Lesser General
264d9fdb4Robert Mustacchi  Public License along with this program; if not, write the
274d9fdb4Robert Mustacchi  Free Software Foundation, Inc., 51 Franklin Street - Fifth
284d9fdb4Robert Mustacchi  Floor, Boston MA 02110-1301, USA.
2949d3bc9Richard Lowe
3049d3bc9Richard Lowe*/
3149d3bc9Richard Lowe
3249d3bc9Richard Lowe#include "config.h"
3349d3bc9Richard Lowe#include "libdwarfdefs.h"
3449d3bc9Richard Lowe#include <stdio.h>
354d9fdb4Robert Mustacchi#ifdef HAVE_STDLIB_H
364d9fdb4Robert Mustacchi#include <stdlib.h> /* for exit(), C89 malloc */
374d9fdb4Robert Mustacchi#endif /* HAVE_STDLIB_H */
384d9fdb4Robert Mustacchi#ifdef HAVE_MALLOC_H
394d9fdb4Robert Mustacchi/* Useful include for some Windows compilers. */
404d9fdb4Robert Mustacchi#include <malloc.h>
414d9fdb4Robert Mustacchi#endif /* HAVE_MALLOC_H */
424d9fdb4Robert Mustacchi#ifdef HAVE_STDINT_H
434d9fdb4Robert Mustacchi#include <stdint.h> /* For uintptr_t */
444d9fdb4Robert Mustacchi#endif /* HAVE_STDINT_H */
4549d3bc9Richard Lowe#include <string.h>
464d9fdb4Robert Mustacchi#include <stddef.h>
4749d3bc9Richard Lowe#include "pro_incl.h"
484d9fdb4Robert Mustacchi#include "dwarf.h"
494d9fdb4Robert Mustacchi#include "libdwarf.h"
504d9fdb4Robert Mustacchi#include "pro_opaque.h"
514d9fdb4Robert Mustacchi#include "pro_error.h"
524d9fdb4Robert Mustacchi#include "pro_util.h"
534d9fdb4Robert Mustacchi#include "pro_alloc.h"
5449d3bc9Richard Lowe#include "pro_die.h"
554d9fdb4Robert Mustacchi#include "pro_section.h"
564d9fdb4Robert Mustacchi#include "dwarf_tsearch.h"
5749d3bc9Richard Lowe
5849d3bc9Richard Lowe#ifndef R_MIPS_NONE
5949d3bc9Richard Lowe#define R_MIPS_NONE 0
6049d3bc9Richard Lowe#endif
6149d3bc9Richard Lowe
624d9fdb4Robert Mustacchi#define TRUE 1
634d9fdb4Robert Mustacchi#define FALSE 0
6449d3bc9Richard Lowe
654d9fdb4Robert Mustacchi/*  This function creates a new die.
6607dc194Richard Lowe    tag: tag of the new die to be created
6707dc194Richard Lowe    parent,child,left,right: specify neighbors of the new die. Only
684d9fdb4Robert Mustacchi    one of these may be non-null */
6949d3bc9Richard LoweDwarf_P_Die
7049d3bc9Richard Lowedwarf_new_die(Dwarf_P_Debug dbg,
714d9fdb4Robert Mustacchi    Dwarf_Tag tag,
724d9fdb4Robert Mustacchi    Dwarf_P_Die parent,
734d9fdb4Robert Mustacchi    Dwarf_P_Die child,
744d9fdb4Robert Mustacchi    Dwarf_P_Die left, Dwarf_P_Die right,
754d9fdb4Robert Mustacchi    Dwarf_Error * error)
764d9fdb4Robert Mustacchi{
774d9fdb4Robert Mustacchi    Dwarf_P_Die created = 0;
784d9fdb4Robert Mustacchi    int res = 0;
794d9fdb4Robert Mustacchi
804d9fdb4Robert Mustacchi    res = dwarf_new_die_a(dbg,tag,parent,child,
814d9fdb4Robert Mustacchi        left,right,&created,error);
824d9fdb4Robert Mustacchi    if (res != DW_DLV_OK) {
834d9fdb4Robert Mustacchi        return (Dwarf_P_Die)DW_DLV_BADADDR;
844d9fdb4Robert Mustacchi    }
854d9fdb4Robert Mustacchi    return created;
864d9fdb4Robert Mustacchi}
874d9fdb4Robert Mustacchi
884d9fdb4Robert Mustacchi/* New September 2016. Preferred as error checking
894d9fdb4Robert Mustacchi   is easier, no need for ugly cast. */
904d9fdb4Robert Mustacchiint
914d9fdb4Robert Mustacchidwarf_new_die_a(Dwarf_P_Debug dbg,
924d9fdb4Robert Mustacchi    Dwarf_Tag tag,
934d9fdb4Robert Mustacchi    Dwarf_P_Die parent,
944d9fdb4Robert Mustacchi    Dwarf_P_Die child,
954d9fdb4Robert Mustacchi    Dwarf_P_Die left, Dwarf_P_Die right,
964d9fdb4Robert Mustacchi    Dwarf_P_Die *die_out,
974d9fdb4Robert Mustacchi    Dwarf_Error *error)
9849d3bc9Richard Lowe{
9907dc194Richard Lowe    Dwarf_P_Die ret_die = 0;
1004d9fdb4Robert Mustacchi    int res = 0;
10149d3bc9Richard Lowe
1024d9fdb4Robert Mustacchi    ret_die = (Dwarf_P_Die)
10307dc194Richard Lowe        _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Die_s));
1044d9fdb4Robert Mustacchi    if (ret_die == NULL) {
10507dc194Richard Lowe        DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_ALLOC,
1064d9fdb4Robert Mustacchi            DW_DLV_ERROR);
1074d9fdb4Robert Mustacchi    }
1084d9fdb4Robert Mustacchi    ret_die->di_parent = NULL;
1094d9fdb4Robert Mustacchi    ret_die->di_left = NULL;
1104d9fdb4Robert Mustacchi    ret_die->di_right = NULL;
1114d9fdb4Robert Mustacchi    ret_die->di_child = NULL;
1124d9fdb4Robert Mustacchi    ret_die->di_last_child = NULL;
1134d9fdb4Robert Mustacchi    ret_die->di_tag = tag;
1144d9fdb4Robert Mustacchi    ret_die->di_dbg = dbg;
1154d9fdb4Robert Mustacchi    ret_die->di_marker = 0;
1164d9fdb4Robert Mustacchi    res = dwarf_die_link_a(ret_die, parent, child, left, right,
1174d9fdb4Robert Mustacchi        error);
1184d9fdb4Robert Mustacchi    if (res != DW_DLV_OK) {
1194d9fdb4Robert Mustacchi        _dwarf_p_dealloc(dbg,(Dwarf_Small *)ret_die);
1204d9fdb4Robert Mustacchi        ret_die = 0;
1214d9fdb4Robert Mustacchi    } else {
1224d9fdb4Robert Mustacchi        *die_out = ret_die;
1234d9fdb4Robert Mustacchi    }
1244d9fdb4Robert Mustacchi    return res;
12549d3bc9Richard Lowe}
12649d3bc9Richard Lowe
1274d9fdb4Robert Mustacchi/*  This function links up a die to specified neighbors
12807dc194Richard Lowe    parent,child,left,right: specify neighbors of the new die. Only
12907dc194Richard Lowe    one of these may be non-null
1304d9fdb4Robert Mustacchi    This is the original version. Use dwarf_die_link_a()
1314d9fdb4Robert Mustacchi    instead as that function is easier to use (in checking for error).
1324d9fdb4Robert Mustacchi    */
13349d3bc9Richard LoweDwarf_P_Die
13449d3bc9Richard Lowedwarf_die_link(Dwarf_P_Die new_die,
1354d9fdb4Robert Mustacchi    Dwarf_P_Die parent,
1364d9fdb4Robert Mustacchi    Dwarf_P_Die child,
1374d9fdb4Robert Mustacchi    Dwarf_P_Die left, Dwarf_P_Die right, Dwarf_Error * error)
1384d9fdb4Robert Mustacchi{
1394d9fdb4Robert Mustacchi    int res = 0;
1404d9fdb4Robert Mustacchi
1414d9fdb4Robert Mustacchi    res = dwarf_die_link_a(new_die,parent,child,left,right,error);
1424d9fdb4Robert Mustacchi    if (res != DW_DLV_OK) {
1434d9fdb4Robert Mustacchi        return (Dwarf_P_Die)DW_DLV_BADADDR;
1444d9fdb4Robert Mustacchi    }
1454d9fdb4Robert Mustacchi    return new_die;
1464d9fdb4Robert Mustacchi}
1474d9fdb4Robert Mustacchi
1484d9fdb4Robert Mustacchi/*  New September 2016.
1494d9fdb4Robert Mustacchi    Error return easier to deal with
1504d9fdb4Robert Mustacchi    than dwarf_die_link(). */
1514d9fdb4Robert Mustacchiint
1524d9fdb4Robert Mustacchidwarf_die_link_a(Dwarf_P_Die new_die,
1534d9fdb4Robert Mustacchi    Dwarf_P_Die parent,
1544d9fdb4Robert Mustacchi    Dwarf_P_Die child,
1554d9fdb4Robert Mustacchi    Dwarf_P_Die left, Dwarf_P_Die right, Dwarf_Error * error)
15649d3bc9Richard Lowe{
15707dc194Richard Lowe    /* Count the # of non null neighbors. */
1584d9fdb4Robert Mustacchi    int n_nulls = 0;
15949d3bc9Richard Lowe
16049d3bc9Richard Lowe    if (parent != NULL) {
16107dc194Richard Lowe        n_nulls++;
16207dc194Richard Lowe        if (new_die->di_parent != NULL) {
1634d9fdb4Robert Mustacchi            DWARF_P_DBG_ERROR(NULL, DW_DLE_LINK_LOOP,
1644d9fdb4Robert Mustacchi                DW_DLV_ERROR);
16507dc194Richard Lowe        }
16607dc194Richard Lowe        new_die->di_parent = parent;
16707dc194Richard Lowe        if (parent->di_child) {
16807dc194Richard Lowe
1694d9fdb4Robert Mustacchi            /*  di_last_child identifies the last sibling, the
1704d9fdb4Robert Mustacchi                die we want to attach new_die to. */
1714d9fdb4Robert Mustacchi            /*  ASSERT: if di_child is set so is di_last_child. */
17207dc194Richard Lowe            Dwarf_P_Die former_lastchild = parent->di_last_child;
17307dc194Richard Lowe            parent->di_last_child = new_die;
17407dc194Richard Lowe            /* Attach to  the new die to end of the sibling list. */
17507dc194Richard Lowe            former_lastchild->di_right = new_die;
17607dc194Richard Lowe            new_die->di_left = former_lastchild;
17707dc194Richard Lowe        } else {
17807dc194Richard Lowe            parent->di_child = new_die;
17907dc194Richard Lowe            parent->di_last_child = new_die;
18007dc194Richard Lowe        }
18149d3bc9Richard Lowe    }
18249d3bc9Richard Lowe    if (child != NULL) {
18307dc194Richard Lowe        n_nulls++;
18407dc194Richard Lowe        new_die->di_child = child;
18507dc194Richard Lowe        new_die->di_last_child = child;
18607dc194Richard Lowe        if (child->di_parent) {
18707dc194Richard Lowe            DWARF_P_DBG_ERROR(NULL, DW_DLE_PARENT_EXISTS,
1884d9fdb4Robert Mustacchi                DW_DLV_ERROR);
18907dc194Richard Lowe        } else {
19007dc194Richard Lowe            child->di_parent = new_die;
19107dc194Richard Lowe        }
19249d3bc9Richard Lowe    }
19349d3bc9Richard Lowe    if (left != NULL) {
19407dc194Richard Lowe        n_nulls++;
19507dc194Richard Lowe        new_die->di_left = left;
1964d9fdb4Robert Mustacchi        if (left->di_right) {
1974d9fdb4Robert Mustacchi            /*  There's already a right sibling of left,
1984d9fdb4Robert Mustacchi                insert the new die in the list. */
19907dc194Richard Lowe            new_die->di_right = left->di_right;
20007dc194Richard Lowe            left->di_right->di_left = new_die;
20107dc194Richard Lowe        }
20207dc194Richard Lowe        left->di_right = new_die;
20307dc194Richard Lowe        if (new_die->di_parent) {
20407dc194Richard Lowe            DWARF_P_DBG_ERROR(NULL, DW_DLE_PARENT_EXISTS,
2054d9fdb4Robert Mustacchi                DW_DLV_ERROR);
20607dc194Richard Lowe        } else {
20707dc194Richard Lowe            new_die->di_parent = left->di_parent;
20807dc194Richard Lowe        }
20949d3bc9Richard Lowe    }
21049d3bc9Richard Lowe    if (right != NULL) {
21107dc194Richard Lowe        n_nulls++;
21207dc194Richard Lowe        new_die->di_right = right;
21307dc194Richard Lowe        if (right->di_left) {
2144d9fdb4Robert Mustacchi            /*  There is already a left sibling of the right die,
2154d9fdb4Robert Mustacchi                insert the new die in the list.  */
21607dc194Richard Lowe            new_die->di_left = right->di_left;
21707dc194Richard Lowe            right->di_left->di_right = new_die;
21807dc194Richard Lowe        }
21907dc194Richard Lowe        right->di_left = new_die;
22007dc194Richard Lowe        if (new_die->di_parent) {
2214d9fdb4Robert Mustacchi            DWARF_P_DBG_ERROR(NULL, DW_DLE_PARENT_EXISTS,
2224d9fdb4Robert Mustacchi                DW_DLV_ERROR);
2234d9fdb4Robert Mustacchi        } else {
2244d9fdb4Robert Mustacchi            new_die->di_parent = right->di_parent;
22507dc194Richard Lowe        }
22649d3bc9Richard Lowe    }
2274d9fdb4Robert Mustacchi    if (n_nulls > 1) {
2284d9fdb4Robert Mustacchi        /* Multiple neighbors! error! */
2294d9fdb4Robert Mustacchi        DWARF_P_DBG_ERROR(NULL, DW_DLE_EXTRA_NEIGHBORS,
2304d9fdb4Robert Mustacchi            DW_DLV_ERROR);
23149d3bc9Richard Lowe    }
2324d9fdb4Robert Mustacchi    return DW_DLV_OK;
23349d3bc9Richard Lowe}
23449d3bc9Richard Lowe
23507dc194Richard LoweDwarf_Unsigned
23607dc194Richard Lowedwarf_add_die_marker(Dwarf_P_Debug dbg,
23707dc194Richard Lowe    Dwarf_P_Die die,
23807dc194Richard Lowe    Dwarf_Unsigned marker,
2394d9fdb4Robert Mustacchi    Dwarf_Error * error) {
24007dc194Richard Lowe    if (die == NULL) {
24107dc194Richard Lowe        DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL, DW_DLV_NOCOUNT);
24207dc194Richard Lowe    }
24307dc194Richard Lowe    die->di_marker = marker;
24407dc194Richard Lowe    return 0;
24507dc194Richard Lowe}
2464d9fdb4Robert Mustacchiint
2474d9fdb4Robert Mustacchidwarf_add_die_marker_a(Dwarf_P_Debug dbg,
2484d9fdb4Robert Mustacchi    Dwarf_P_Die die,
2494d9fdb4Robert Mustacchi    Dwarf_Unsigned marker,
2504d9fdb4Robert Mustacchi    Dwarf_Error * error)
2514d9fdb4Robert Mustacchi{
2524d9fdb4Robert Mustacchi    if (die == NULL) {
2534d9fdb4Robert Mustacchi        DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL,
2544d9fdb4Robert Mustacchi            DW_DLV_ERROR);
2554d9fdb4Robert Mustacchi    }
2564d9fdb4Robert Mustacchi    die->di_marker = marker;
2574d9fdb4Robert Mustacchi    return DW_DLV_OK;
2584d9fdb4Robert Mustacchi}
25907dc194Richard Lowe
26007dc194Richard Lowe
26107dc194Richard LoweDwarf_Unsigned
26207dc194Richard Lowedwarf_get_die_marker(Dwarf_P_Debug dbg,
2634d9fdb4Robert Mustacchi    Dwarf_P_Die die,
2644d9fdb4Robert Mustacchi    Dwarf_Unsigned * marker,
2654d9fdb4Robert Mustacchi    Dwarf_Error * error)
26607dc194Richard Lowe{
26707dc194Richard Lowe    if (die == NULL) {
2684d9fdb4Robert Mustacchi        DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL,
2694d9fdb4Robert Mustacchi            DW_DLV_NOCOUNT);
27007dc194Richard Lowe    }
27107dc194Richard Lowe    *marker = die->di_marker;
27207dc194Richard Lowe    return 0;
27307dc194Richard Lowe}
2744d9fdb4Robert Mustacchiint
2754d9fdb4Robert Mustacchidwarf_get_die_marker_a(Dwarf_P_Debug dbg,
2764d9fdb4Robert Mustacchi    Dwarf_P_Die die,
2774d9fdb4Robert Mustacchi    Dwarf_Unsigned * marker,
2784d9fdb4Robert Mustacchi    Dwarf_Error * error)
2794d9fdb4Robert Mustacchi{
2804d9fdb4Robert Mustacchi    if (die == NULL) {
2814d9fdb4Robert Mustacchi        DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL,
2824d9fdb4Robert Mustacchi            DW_DLV_ERROR);
2834d9fdb4Robert Mustacchi    }
2844d9fdb4Robert Mustacchi    *marker = die->di_marker;
2854d9fdb4Robert Mustacchi    return DW_DLV_ERROR;
2864d9fdb4Robert Mustacchi}
28707dc194Richard Lowe
28807dc194Richard Lowe
2894d9fdb4Robert Mustacchi/*---------------------------------------------------------
2904d9fdb4Robert Mustacchi    This function adds a die to dbg struct. It should
2914d9fdb4Robert Mustacchi    be called using the root of all the dies.
2924d9fdb4Robert Mustacchi---------------------------------------------------------*/
2934d9fdb4Robert Mustacchi/*  Original form of this call..
2944d9fdb4Robert Mustacchi    dwarf_add_die_to_debug_a() is preferred now. */
29549d3bc9Richard LoweDwarf_Unsigned
29649d3bc9Richard Lowedwarf_add_die_to_debug(Dwarf_P_Debug dbg,
2974d9fdb4Robert Mustacchi    Dwarf_P_Die first_die, Dwarf_Error * error)
2984d9fdb4Robert Mustacchi{
2994d9fdb4Robert Mustacchi    int res = dwarf_add_die_to_debug_a(dbg,first_die,error);
3004d9fdb4Robert Mustacchi    if (res == DW_DLV_ERROR) {
3014d9fdb4Robert Mustacchi        return DW_DLV_NOCOUNT;
3024d9fdb4Robert Mustacchi    }
3034d9fdb4Robert Mustacchi    return 0;
3044d9fdb4Robert Mustacchi}
3054d9fdb4Robert Mustacchi
3064d9fdb4Robert Mustacchi/*  New September 2016. The new and preferred form. */
3074d9fdb4Robert Mustacchiint
3084d9fdb4Robert Mustacchidwarf_add_die_to_debug_a(Dwarf_P_Debug dbg,
3094d9fdb4Robert Mustacchi    Dwarf_P_Die first_die, Dwarf_Error * error)
31049d3bc9Richard Lowe{
31149d3bc9Richard Lowe    if (first_die == NULL) {
3124d9fdb4Robert Mustacchi        DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL,
3134d9fdb4Robert Mustacchi            DW_DLV_ERROR);
31449d3bc9Richard Lowe    }
31549d3bc9Richard Lowe    if (first_die->di_tag != DW_TAG_compile_unit) {
3164d9fdb4Robert Mustacchi        DWARF_P_DBG_ERROR(dbg, DW_DLE_WRONG_TAG,
3174d9fdb4Robert Mustacchi            DW_DLV_ERROR);
31849d3bc9Richard Lowe    }
31949d3bc9Richard Lowe    dbg->de_dies = first_die;
3204d9fdb4Robert Mustacchi    return DW_DLV_OK;
32149d3bc9Richard Lowe}
32249d3bc9Richard Lowe
32349d3bc9Richard Loweint
32449d3bc9Richard Lowe_dwarf_pro_add_AT_stmt_list(Dwarf_P_Debug dbg,
32507dc194Richard Lowe    Dwarf_P_Die first_die, Dwarf_Error * error)
32649d3bc9Richard Lowe{
32749d3bc9Richard Lowe    Dwarf_P_Attribute new_attr;
3284d9fdb4Robert Mustacchi    int uwordb_size = dbg->de_dwarf_offset_size;
32949d3bc9Richard Lowe
33049d3bc9Richard Lowe    /* Add AT_stmt_list attribute */
33149d3bc9Richard Lowe    new_attr = (Dwarf_P_Attribute)
3324d9fdb4Robert Mustacchi        _dwarf_p_get_alloc(dbg,
3334d9fdb4Robert Mustacchi            sizeof(struct Dwarf_P_Attribute_s));
33449d3bc9Richard Lowe    if (new_attr == NULL) {
3354d9fdb4Robert Mustacchi        DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC,
3364d9fdb4Robert Mustacchi            DW_DLV_ERROR);
33749d3bc9Richard Lowe    }
33849d3bc9Richard Lowe
33949d3bc9Richard Lowe    new_attr->ar_attribute = DW_AT_stmt_list;
3404d9fdb4Robert Mustacchi    new_attr->ar_attribute_form =
3414d9fdb4Robert Mustacchi        dbg->de_ar_data_attribute_form;
34249d3bc9Richard Lowe    new_attr->ar_rel_type = dbg->de_offset_reloc;
34349d3bc9Richard Lowe
34449d3bc9Richard Lowe    new_attr->ar_nbytes = uwordb_size;
34549d3bc9Richard Lowe    new_attr->ar_next = NULL;
34649d3bc9Richard Lowe    new_attr->ar_reloc_len = uwordb_size;
34749d3bc9Richard Lowe    new_attr->ar_data = (char *)
34807dc194Richard Lowe        _dwarf_p_get_alloc(dbg, uwordb_size);
34949d3bc9Richard Lowe    if (new_attr->ar_data == NULL) {
3504d9fdb4Robert Mustacchi        DWARF_P_DBG_ERROR(NULL,DW_DLE_ADDR_ALLOC,
3514d9fdb4Robert Mustacchi            DW_DLV_ERROR);
35249d3bc9Richard Lowe    }
35349d3bc9Richard Lowe    {
3544d9fdb4Robert Mustacchi        Dwarf_Unsigned du = 0;
35549d3bc9Richard Lowe
3564d9fdb4Robert Mustacchi        WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data,
3574d9fdb4Robert Mustacchi            (const void *) &du, sizeof(du), uwordb_size);
35849d3bc9Richard Lowe    }
35949d3bc9Richard Lowe
36049d3bc9Richard Lowe    _dwarf_pro_add_at_to_die(first_die, new_attr);
3614d9fdb4Robert Mustacchi    return DW_DLV_OK;
3624d9fdb4Robert Mustacchi}
3634d9fdb4Robert Mustacchi
3644d9fdb4Robert Mustacchistatic int
3654d9fdb4Robert Mustacchi_dwarf_debug_str_compare_func(const void *l,const void *r)
3664d9fdb4Robert Mustacchi{
3674d9fdb4Robert Mustacchi    const struct Dwarf_P_debug_str_entry_s*el = l;
3684d9fdb4Robert Mustacchi    const struct Dwarf_P_debug_str_entry_s*er = r;
3694d9fdb4Robert Mustacchi    char *lname =  0;
3704d9fdb4Robert Mustacchi    char *rname =  0;
3714d9fdb4Robert Mustacchi    int ir = 0;
3724d9fdb4Robert Mustacchi
3734d9fdb4Robert Mustacchi    if (el->dse_has_table_offset) {
3744d9fdb4Robert Mustacchi        /*  When set the name is in the debug_str table. */
3754d9fdb4Robert Mustacchi        /*  ASSERT: dse_dbg->de_debug_str->ds_data
3764d9fdb4Robert Mustacchi            is non-zero.
3774d9fdb4Robert Mustacchi            ASSERT: dse_name NULL. */
3784d9fdb4Robert Mustacchi        lname = el->dse_dbg->de_debug_str->ds_data +
3794d9fdb4Robert Mustacchi            el->dse_table_offset;
3804d9fdb4Robert Mustacchi    } else {
3814d9fdb4Robert Mustacchi        /*  ASSERT: dse_name non-null */
3824d9fdb4Robert Mustacchi        lname = el->dse_name;
3834d9fdb4Robert Mustacchi    }
3844d9fdb4Robert Mustacchi    if (er->dse_has_table_offset) {
3854d9fdb4Robert Mustacchi        /*  When set the name is in the debug_str table. */
3864d9fdb4Robert Mustacchi        /*  ASSERT: dse_dbg->de_debug_str->ds_data
3874d9fdb4Robert Mustacchi            is non-zero.
3884d9fdb4Robert Mustacchi            ASSERT: dse_name NULL. */
3894d9fdb4Robert Mustacchi        rname = er->dse_dbg->de_debug_str->ds_data +
3904d9fdb4Robert Mustacchi            er->dse_table_offset;
3914d9fdb4Robert Mustacchi    } else {
3924d9fdb4Robert Mustacchi        /*  ASSERT: dse_name non-null */
3934d9fdb4Robert Mustacchi        rname = er->dse_name;
3944d9fdb4Robert Mustacchi    }
3954d9fdb4Robert Mustacchi    ir = strcmp(lname,rname);
3964d9fdb4Robert Mustacchi    return ir;
3974d9fdb4Robert Mustacchi}
3984d9fdb4Robert Mustacchi
3994d9fdb4Robert Mustacchistatic  void
4004d9fdb4Robert Mustacchidebug_str_entry_free_func(void *m)
4014d9fdb4Robert Mustacchi{
4024d9fdb4Robert Mustacchi    free(m);
40349d3bc9Richard Lowe}
40449d3bc9Richard Lowe
4054d9fdb4Robert Mustacchistatic int
4064d9fdb4Robert Mustacchimake_debug_str_entry(Dwarf_P_Debug dbg,
4074d9fdb4Robert Mustacchi    struct Dwarf_P_debug_str_entry_s **mt_out,
4084d9fdb4Robert Mustacchi    char *name,
4094d9fdb4Robert Mustacchi    unsigned slen,
4104d9fdb4Robert Mustacchi    unsigned char has_offset,
4114d9fdb4Robert Mustacchi    Dwarf_Unsigned offset_in_table,
4124d9fdb4Robert Mustacchi    Dwarf_Error *error)
4134d9fdb4Robert Mustacchi{
4144d9fdb4Robert Mustacchi    struct Dwarf_P_debug_str_entry_s *mt =
4154d9fdb4Robert Mustacchi        (struct  Dwarf_P_debug_str_entry_s *)calloc(
4164d9fdb4Robert Mustacchi        sizeof(struct Dwarf_P_debug_str_entry_s),1);
4174d9fdb4Robert Mustacchi    if (!mt) {
4184d9fdb4Robert Mustacchi        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
4194d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
4204d9fdb4Robert Mustacchi    }
4214d9fdb4Robert Mustacchi
4224d9fdb4Robert Mustacchi    mt->dse_slen = slen;
4234d9fdb4Robert Mustacchi    mt->dse_table_offset = 0;
4244d9fdb4Robert Mustacchi    mt->dse_dbg = dbg;
4254d9fdb4Robert Mustacchi    if (has_offset) {
4264d9fdb4Robert Mustacchi        mt->dse_has_table_offset = TRUE;
4274d9fdb4Robert Mustacchi        mt->dse_table_offset = offset_in_table;
4284d9fdb4Robert Mustacchi        mt->dse_name = 0;
4294d9fdb4Robert Mustacchi    } else {
4304d9fdb4Robert Mustacchi        /* ASSERT: name != NULL */
4314d9fdb4Robert Mustacchi        mt->dse_has_table_offset = FALSE;
4324d9fdb4Robert Mustacchi        /* We just set dse_table_offset so it has
4334d9fdb4Robert Mustacchi            a known value, though nothing should refer
4344d9fdb4Robert Mustacchi            to dse_table_offset because
4354d9fdb4Robert Mustacchi            dse_has_table_offset is FALSE.*/
4364d9fdb4Robert Mustacchi        mt->dse_table_offset = 0;
4374d9fdb4Robert Mustacchi        mt->dse_name = name;
4384d9fdb4Robert Mustacchi    }
4394d9fdb4Robert Mustacchi    *mt_out = mt;
4404d9fdb4Robert Mustacchi    return DW_DLV_OK;
4414d9fdb4Robert Mustacchi}
4424d9fdb4Robert Mustacchi#define STRTAB_BASE_ALLOC_SIZE 2048
4434d9fdb4Robert Mustacchistatic int
4444d9fdb4Robert Mustacchiinsert_debug_str_data_string(Dwarf_P_Debug dbg,
4454d9fdb4Robert Mustacchi    char *name,
4464d9fdb4Robert Mustacchi    unsigned slen,
4474d9fdb4Robert Mustacchi    Dwarf_P_Section_Data sd,
4484d9fdb4Robert Mustacchi    Dwarf_Unsigned*adding_at_offset,
4494d9fdb4Robert Mustacchi    Dwarf_Error *  error)
4504d9fdb4Robert Mustacchi{
4514d9fdb4Robert Mustacchi    Dwarf_Unsigned current_offset = 0;
4524d9fdb4Robert Mustacchi
4534d9fdb4Robert Mustacchi    if (!sd->ds_data) {
4544d9fdb4Robert Mustacchi        Dwarf_Unsigned initial_alloc = STRTAB_BASE_ALLOC_SIZE;
4554d9fdb4Robert Mustacchi        Dwarf_Unsigned base_insert_offset = 0;
4564d9fdb4Robert Mustacchi
4574d9fdb4Robert Mustacchi        /*  Inserting our first string.
4584d9fdb4Robert Mustacchi            The GNU linker refuses to commonize strings
4594d9fdb4Robert Mustacchi            if the section starts with a NUL byte,
4604d9fdb4Robert Mustacchi            so start with real string, using a
4614d9fdb4Robert Mustacchi            base_insert_offset of 0. */
4624d9fdb4Robert Mustacchi        if ( (slen + base_insert_offset) >= STRTAB_BASE_ALLOC_SIZE) {
4634d9fdb4Robert Mustacchi            initial_alloc = slen *2+ base_insert_offset;
4644d9fdb4Robert Mustacchi        }
4654d9fdb4Robert Mustacchi        if (initial_alloc < slen) {
4664d9fdb4Robert Mustacchi            _dwarf_p_error(dbg, error, DW_DLE_SIZE_WRAPAROUND);
4674d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
4684d9fdb4Robert Mustacchi        }
4694d9fdb4Robert Mustacchi        sd->ds_data = calloc(1,initial_alloc);
4704d9fdb4Robert Mustacchi        if (!sd->ds_data) {
4714d9fdb4Robert Mustacchi            _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
4724d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
4734d9fdb4Robert Mustacchi        }
4744d9fdb4Robert Mustacchi        sd->ds_orig_alloc = initial_alloc;
4754d9fdb4Robert Mustacchi        *adding_at_offset = base_insert_offset;
4764d9fdb4Robert Mustacchi        sd->ds_nbytes = slen + base_insert_offset;
4774d9fdb4Robert Mustacchi        strcpy(sd->ds_data+base_insert_offset,name);
4784d9fdb4Robert Mustacchi        return DW_DLV_OK;
4794d9fdb4Robert Mustacchi    }
4804d9fdb4Robert Mustacchi    current_offset = sd->ds_nbytes;
4814d9fdb4Robert Mustacchi    if ( (current_offset + slen) >= sd->ds_orig_alloc) {
4824d9fdb4Robert Mustacchi        unsigned updated_length = sd->ds_orig_alloc;
4834d9fdb4Robert Mustacchi        char *newbuf = 0;
4844d9fdb4Robert Mustacchi        if (slen > updated_length) {
4854d9fdb4Robert Mustacchi            /*  Very long string passed in. */
4864d9fdb4Robert Mustacchi            updated_length = slen *2;
4874d9fdb4Robert Mustacchi        } else {
4884d9fdb4Robert Mustacchi            updated_length = updated_length *2;
4894d9fdb4Robert Mustacchi        }
4904d9fdb4Robert Mustacchi        if (updated_length < sd->ds_orig_alloc) {
4914d9fdb4Robert Mustacchi            _dwarf_p_error(dbg, error, DW_DLE_SIZE_WRAPAROUND);
4924d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
4934d9fdb4Robert Mustacchi        }
4944d9fdb4Robert Mustacchi        newbuf = calloc(1,updated_length);
4954d9fdb4Robert Mustacchi        if (!newbuf) {
4964d9fdb4Robert Mustacchi            _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
4974d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
4984d9fdb4Robert Mustacchi        }
4994d9fdb4Robert Mustacchi        memcpy(newbuf,sd->ds_data,sd->ds_nbytes);
5004d9fdb4Robert Mustacchi        free(sd->ds_data);
5014d9fdb4Robert Mustacchi        sd->ds_data = newbuf;
5024d9fdb4Robert Mustacchi        sd->ds_orig_alloc = updated_length;
5034d9fdb4Robert Mustacchi        newbuf = 0;
5044d9fdb4Robert Mustacchi    }
5054d9fdb4Robert Mustacchi    strcpy(sd->ds_data + current_offset,name);
5064d9fdb4Robert Mustacchi    sd->ds_nbytes += slen;
5074d9fdb4Robert Mustacchi    *adding_at_offset = current_offset;
5084d9fdb4Robert Mustacchi    return DW_DLV_OK;
5094d9fdb4Robert Mustacchi}
5104d9fdb4Robert Mustacchi
5114d9fdb4Robert Mustacchi/*  Find the string offset using the hash table,
5124d9fdb4Robert Mustacchi    and if not known, insert the new string. */
5134d9fdb4Robert Mustacchiint
5144d9fdb4Robert Mustacchi_dwarf_insert_or_find_in_debug_str(Dwarf_P_Debug dbg,
5154d9fdb4Robert Mustacchi    char *name,
5164d9fdb4Robert Mustacchi    enum dwarf_which_hash whash,
5174d9fdb4Robert Mustacchi    unsigned slen, /* includes space for trailing NUL */
5184d9fdb4Robert Mustacchi    Dwarf_Unsigned *offset_in_debug_str,
5194d9fdb4Robert Mustacchi    Dwarf_Error *error)
5204d9fdb4Robert Mustacchi{
5214d9fdb4Robert Mustacchi    struct Dwarf_P_debug_str_entry_s *mt = 0;
5224d9fdb4Robert Mustacchi    struct Dwarf_P_debug_str_entry_s *mt2 = 0;
5234d9fdb4Robert Mustacchi    struct Dwarf_P_debug_str_entry_s *retval = 0;
5244d9fdb4Robert Mustacchi    struct Dwarf_P_debug_str_entry_s *re = 0;
5254d9fdb4Robert Mustacchi    int res = 0;
5264d9fdb4Robert Mustacchi    Dwarf_Unsigned adding_at_offset = 0;
5274d9fdb4Robert Mustacchi    void **hashtab = 0;
5284d9fdb4Robert Mustacchi    Dwarf_P_Section_Data sd = 0;
5294d9fdb4Robert Mustacchi    struct Dwarf_P_Str_stats_s * stats =  0;
5304d9fdb4Robert Mustacchi
5314d9fdb4Robert Mustacchi    switch (whash) {
5324d9fdb4Robert Mustacchi    case _dwarf_hash_debug_str:
5334d9fdb4Robert Mustacchi        hashtab =  &dbg->de_debug_str_hashtab;
5344d9fdb4Robert Mustacchi        sd =  dbg->de_debug_str;
5354d9fdb4Robert Mustacchi        stats = &dbg->de_stats.ps_strp;
5364d9fdb4Robert Mustacchi        break;
5374d9fdb4Robert Mustacchi    case _dwarf_hash_debug_line_str:
5384d9fdb4Robert Mustacchi        hashtab =  &dbg->de_debug_line_str_hashtab;
5394d9fdb4Robert Mustacchi        sd =  dbg->de_debug_line_str;
5404d9fdb4Robert Mustacchi        stats = &dbg->de_stats.ps_line_strp;
5414d9fdb4Robert Mustacchi        break;
5424d9fdb4Robert Mustacchi    case _dwarf_hash_debug_str_sup:
5434d9fdb4Robert Mustacchi    default:
5444d9fdb4Robert Mustacchi        /* Not supported or unknown. */
5454d9fdb4Robert Mustacchi        _dwarf_p_error(dbg, error, DW_DLE_STRING_HASHTAB_IDENTITY_ERROR);
5464d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
5474d9fdb4Robert Mustacchi    }
5484d9fdb4Robert Mustacchi    res = make_debug_str_entry(dbg,&mt,name,
5494d9fdb4Robert Mustacchi        slen,FALSE, 0, error);
5504d9fdb4Robert Mustacchi    if (res != DW_DLV_OK) {
5514d9fdb4Robert Mustacchi        return res;
5524d9fdb4Robert Mustacchi    }
5534d9fdb4Robert Mustacchi    /*  We do a find as we do not want the string pointer passed in
5544d9fdb4Robert Mustacchi        to be in the hash table, we want a pointer into the
5554d9fdb4Robert Mustacchi        debug_str table in the hash table. */
5564d9fdb4Robert Mustacchi    retval = dwarf_tfind(mt,(void *const*)hashtab,
5574d9fdb4Robert Mustacchi        _dwarf_debug_str_compare_func);
5584d9fdb4Robert Mustacchi    if (retval) {
5594d9fdb4Robert Mustacchi
5604d9fdb4Robert Mustacchi        stats->ps_strp_reused_count++;
5614d9fdb4Robert Mustacchi        stats->ps_strp_reused_len += slen;
5624d9fdb4Robert Mustacchi
5634d9fdb4Robert Mustacchi        re = *(struct Dwarf_P_debug_str_entry_s **)retval;
5644d9fdb4Robert Mustacchi        *offset_in_debug_str = re->dse_table_offset;
5654d9fdb4Robert Mustacchi        debug_str_entry_free_func(mt);
5664d9fdb4Robert Mustacchi        return DW_DLV_OK;
5674d9fdb4Robert Mustacchi    }
5684d9fdb4Robert Mustacchi
5694d9fdb4Robert Mustacchi    /*  We know the string is not in .debug_str data yet.
5704d9fdb4Robert Mustacchi        Insert it into the big string table and get that
5714d9fdb4Robert Mustacchi        offset. */
5724d9fdb4Robert Mustacchi
5734d9fdb4Robert Mustacchi    debug_str_entry_free_func(mt);
5744d9fdb4Robert Mustacchi    mt = 0;
5754d9fdb4Robert Mustacchi    res = insert_debug_str_data_string(dbg,name,slen,sd,
5764d9fdb4Robert Mustacchi        &adding_at_offset, error);
5774d9fdb4Robert Mustacchi    if (res != DW_DLV_OK) {
5784d9fdb4Robert Mustacchi        return res;
5794d9fdb4Robert Mustacchi    }
5804d9fdb4Robert Mustacchi
5814d9fdb4Robert Mustacchi    /*  The name is in the string table itself, so use that pointer
5824d9fdb4Robert Mustacchi        and offset for the string. */
5834d9fdb4Robert Mustacchi    res = make_debug_str_entry(dbg,&mt2, 0,
5844d9fdb4Robert Mustacchi        slen,TRUE,adding_at_offset,error);
5854d9fdb4Robert Mustacchi    if (res != DW_DLV_OK) {
5864d9fdb4Robert Mustacchi        return res;
5874d9fdb4Robert Mustacchi    }
5884d9fdb4Robert Mustacchi    retval = dwarf_tsearch(mt2,
5894d9fdb4Robert Mustacchi        (void *)hashtab,
5904d9fdb4Robert Mustacchi        _dwarf_debug_str_compare_func);
5914d9fdb4Robert Mustacchi    if (!retval) {
5924d9fdb4Robert Mustacchi        debug_str_entry_free_func(mt2);
5934d9fdb4Robert Mustacchi        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
5944d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
5954d9fdb4Robert Mustacchi    }
5964d9fdb4Robert Mustacchi
5974d9fdb4Robert Mustacchi    /* This indirection is one of the surprises in using tsearch... */
5984d9fdb4Robert Mustacchi    re = *(struct Dwarf_P_debug_str_entry_s **)retval;
5994d9fdb4Robert Mustacchi    if (re != mt2) {
6004d9fdb4Robert Mustacchi        debug_str_entry_free_func(mt2);
6014d9fdb4Robert Mustacchi        /*  Found it in hash tab: illogical as the tsearch_find should
6024d9fdb4Robert Mustacchi            have found it. */
6034d9fdb4Robert Mustacchi        _dwarf_p_error(dbg, error, DW_DLE_ILLOGICAL_TSEARCH);
6044d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
6054d9fdb4Robert Mustacchi    }
6064d9fdb4Robert Mustacchi    stats->ps_strp_count_debug_str++;
6074d9fdb4Robert Mustacchi    stats->ps_strp_len_debug_str += slen;
6084d9fdb4Robert Mustacchi    /* we added it to hash, do not free mt2 (which == re). */
6094d9fdb4Robert Mustacchi    *offset_in_debug_str = re->dse_table_offset;
6104d9fdb4Robert Mustacchi    return DW_DLV_OK;
6114d9fdb4Robert Mustacchi}
6124d9fdb4Robert Mustacchi
6134d9fdb4Robert Mustacchi/*  Returns DW_DLV_OK or DW_DLV_ERROR. */
6144d9fdb4Robert Mustacchiint _dwarf_pro_set_string_attr(Dwarf_P_Attribute new_attr,
6154d9fdb4Robert Mustacchi    Dwarf_P_Debug dbg,
6164d9fdb4Robert Mustacchi    char *name,
6174d9fdb4Robert Mustacchi    Dwarf_Error *error)
6184d9fdb4Robert Mustacchi{
6194d9fdb4Robert Mustacchi    int form = dbg->de_debug_default_str_form;
6204d9fdb4Robert Mustacchi    unsigned slen = strlen(name)+1;
6214d9fdb4Robert Mustacchi
6224d9fdb4Robert Mustacchi    if (form == DW_FORM_string ||
6234d9fdb4Robert Mustacchi        slen <= dbg->de_dwarf_offset_size) {
6244d9fdb4Robert Mustacchi        new_attr->ar_nbytes = slen;
6254d9fdb4Robert Mustacchi        new_attr->ar_next = 0;
6264d9fdb4Robert Mustacchi
6274d9fdb4Robert Mustacchi        new_attr->ar_data =
6284d9fdb4Robert Mustacchi            (char *) _dwarf_p_get_alloc(dbg, slen);
6294d9fdb4Robert Mustacchi        if (new_attr->ar_data == NULL) {
6304d9fdb4Robert Mustacchi            _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
6314d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
6324d9fdb4Robert Mustacchi        }
6334d9fdb4Robert Mustacchi        dbg->de_stats.ps_str_count++;
6344d9fdb4Robert Mustacchi        dbg->de_stats.ps_str_total_length += slen;
6354d9fdb4Robert Mustacchi
6364d9fdb4Robert Mustacchi        strcpy(new_attr->ar_data, name);
6374d9fdb4Robert Mustacchi        new_attr->ar_attribute_form = DW_FORM_string;
6384d9fdb4Robert Mustacchi        new_attr->ar_rel_type = R_MIPS_NONE;
6394d9fdb4Robert Mustacchi        new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */
6404d9fdb4Robert Mustacchi        return DW_DLV_OK;
6414d9fdb4Robert Mustacchi    }
6424d9fdb4Robert Mustacchi    if (form == DW_FORM_strp) {
6434d9fdb4Robert Mustacchi        int uwordb_size = dbg->de_dwarf_offset_size;
6444d9fdb4Robert Mustacchi        Dwarf_Unsigned offset_in_debug_str = 0;
6454d9fdb4Robert Mustacchi        int res = 0;
6464d9fdb4Robert Mustacchi
6474d9fdb4Robert Mustacchi        res = _dwarf_insert_or_find_in_debug_str(dbg,name,
6484d9fdb4Robert Mustacchi            _dwarf_hash_debug_str,slen,
6494d9fdb4Robert Mustacchi            &offset_in_debug_str,error);
6504d9fdb4Robert Mustacchi        if(res != DW_DLV_OK) {
6514d9fdb4Robert Mustacchi            return res;
6524d9fdb4Robert Mustacchi        }
6534d9fdb4Robert Mustacchi        new_attr->ar_attribute_form = form;
6544d9fdb4Robert Mustacchi        new_attr->ar_rel_type = dbg->de_offset_reloc;
6554d9fdb4Robert Mustacchi        new_attr->ar_nbytes = uwordb_size;
6564d9fdb4Robert Mustacchi        new_attr->ar_next = NULL;
6574d9fdb4Robert Mustacchi        new_attr->ar_reloc_len = uwordb_size;
6584d9fdb4Robert Mustacchi        /*  During transform to disk
6594d9fdb4Robert Mustacchi            a symbol index will be applied. */
6604d9fdb4Robert Mustacchi        new_attr->ar_data = (char *)
6614d9fdb4Robert Mustacchi            _dwarf_p_get_alloc(dbg, uwordb_size);
6624d9fdb4Robert Mustacchi        if (new_attr->ar_data == NULL) {
6634d9fdb4Robert Mustacchi            _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
6644d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
6654d9fdb4Robert Mustacchi        }
6664d9fdb4Robert Mustacchi        {
6674d9fdb4Robert Mustacchi            Dwarf_Unsigned du = offset_in_debug_str;
6684d9fdb4Robert Mustacchi
6694d9fdb4Robert Mustacchi            WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data,
6704d9fdb4Robert Mustacchi                (const void *) &du, sizeof(du), uwordb_size);
6714d9fdb4Robert Mustacchi        }
6724d9fdb4Robert Mustacchi
6734d9fdb4Robert Mustacchi        return DW_DLV_OK;
6744d9fdb4Robert Mustacchi    }
6754d9fdb4Robert Mustacchi    _dwarf_p_error(dbg, error, DW_DLE_BAD_STRING_FORM);
6764d9fdb4Robert Mustacchi    return DW_DLV_ERROR;
6774d9fdb4Robert Mustacchi
6784d9fdb4Robert Mustacchi}
6794d9fdb4Robert Mustacchi
6804d9fdb4Robert Mustacchi
6814d9fdb4Robert Mustacchi/*-------------------------------------------------------------------
68207dc194Richard Lowe    Add AT_name attribute to die
6834d9fdb4Robert Mustacchi---------------------------------------------------------------------*/
6844d9fdb4Robert Mustacchi/*  Original function. dwarf_add_AT_name_a() is the
6854d9fdb4Robert Mustacchi    suggested alternative. */
68649d3bc9Richard LoweDwarf_P_Attribute
6874d9fdb4Robert Mustacchidwarf_add_AT_name(Dwarf_P_Die die,
6884d9fdb4Robert Mustacchi    char *name,
6894d9fdb4Robert Mustacchi    Dwarf_Error * error)
69049d3bc9Richard Lowe{
6914d9fdb4Robert Mustacchi    Dwarf_P_Attribute a = 0;
6924d9fdb4Robert Mustacchi    int res = 0;
6934d9fdb4Robert Mustacchi
6944d9fdb4Robert Mustacchi    res = dwarf_add_AT_name_a(die, name,
6954d9fdb4Robert Mustacchi        &a, error);
6964d9fdb4Robert Mustacchi    if (res == DW_DLV_ERROR) {
6974d9fdb4Robert Mustacchi        return (Dwarf_P_Attribute)(DW_DLV_BADADDR);
6984d9fdb4Robert Mustacchi    }
6994d9fdb4Robert Mustacchi    return a;
7004d9fdb4Robert Mustacchi}
7014d9fdb4Robert Mustacchi
7024d9fdb4Robert Mustacchi/*   New December 2018.  */
7034d9fdb4Robert Mustacchiint
7044d9fdb4Robert Mustacchidwarf_add_AT_name_a(Dwarf_P_Die die, char *name,
7054d9fdb4Robert Mustacchi    Dwarf_P_Attribute *newattr_out,
7064d9fdb4Robert Mustacchi    Dwarf_Error * error)
7074d9fdb4Robert Mustacchi{
7084d9fdb4Robert Mustacchi    Dwarf_P_Attribute new_attr = 0;
7094d9fdb4Robert Mustacchi    int res = 0;
71049d3bc9Richard Lowe
71149d3bc9Richard Lowe    if (die == NULL) {
71207dc194Richard Lowe        DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL,
7134d9fdb4Robert Mustacchi            DW_DLV_ERROR);
71449d3bc9Richard Lowe    }
71549d3bc9Richard Lowe    new_attr = (Dwarf_P_Attribute)
7164d9fdb4Robert Mustacchi        _dwarf_p_get_alloc(die->di_dbg,
7174d9fdb4Robert Mustacchi            sizeof(struct Dwarf_P_Attribute_s));
71849d3bc9Richard Lowe    if (new_attr == NULL) {
71907dc194Richard Lowe        DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC,
7204d9fdb4Robert Mustacchi            DW_DLV_ERROR);
72149d3bc9Richard Lowe    }
72249d3bc9Richard Lowe
72349d3bc9Richard Lowe    /* fill in the information */
72449d3bc9Richard Lowe    new_attr->ar_attribute = DW_AT_name;
7254d9fdb4Robert Mustacchi    res = _dwarf_pro_set_string_attr(new_attr,die->di_dbg,name,error);
7264d9fdb4Robert Mustacchi    if (res != DW_DLV_OK) {
7274d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
72849d3bc9Richard Lowe    }
72949d3bc9Richard Lowe
73049d3bc9Richard Lowe    /* add attribute to the die */
73149d3bc9Richard Lowe    _dwarf_pro_add_at_to_die(die, new_attr);
7324d9fdb4Robert Mustacchi    *newattr_out = new_attr;
7334d9fdb4Robert Mustacchi    return DW_DLV_OK;
73449d3bc9Richard Lowe}
73549d3bc9Richard Lowe
73649d3bc9Richard Lowe
7374d9fdb4Robert Mustacchi/*--------------------------------------------------------------------
73807dc194Richard Lowe    Add AT_comp_dir attribute to die
7394d9fdb4Robert Mustacchi--------------------------------------------------------------------*/
74049d3bc9Richard LoweDwarf_P_Attribute
74149d3bc9Richard Lowedwarf_add_AT_comp_dir(Dwarf_P_Die ownerdie,
74207dc194Richard Lowe    char *current_working_directory,
74307dc194Richard Lowe    Dwarf_Error * error)
74449d3bc9Richard Lowe{
7454d9fdb4Robert Mustacchi    Dwarf_P_Attribute a = 0;
7464d9fdb4Robert Mustacchi    int res = 0;
7474d9fdb4Robert Mustacchi
7484d9fdb4Robert Mustacchi    res = dwarf_add_AT_comp_dir_a(ownerdie,
7494d9fdb4Robert Mustacchi        current_working_directory,
7504d9fdb4Robert Mustacchi        &a, error);
7514d9fdb4Robert Mustacchi    if (res != DW_DLV_OK) {
7524d9fdb4Robert Mustacchi        return (Dwarf_P_Attribute)(DW_DLV_BADADDR);
7534d9fdb4Robert Mustacchi    }
7544d9fdb4Robert Mustacchi    return a;
7554d9fdb4Robert Mustacchi}
7564d9fdb4Robert Mustacchi
7574d9fdb4Robert Mustacchiint
7584d9fdb4Robert Mustacchidwarf_add_AT_comp_dir_a(Dwarf_P_Die ownerdie,
7594d9fdb4Robert Mustacchi    char *current_working_directory,
7604d9fdb4Robert Mustacchi    Dwarf_P_Attribute *attr_out,
7614d9fdb4Robert Mustacchi    Dwarf_Error * error)
7624d9fdb4Robert Mustacchi{
7634d9fdb4Robert Mustacchi    Dwarf_P_Attribute new_attr = 0;
7644d9fdb4Robert Mustacchi    int res = 0;
76549d3bc9Richard Lowe
76649d3bc9Richard Lowe    if (ownerdie == NULL) {
76707dc194Richard Lowe        DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL,
7684d9fdb4Robert Mustacchi            DW_DLV_ERROR);
76949d3bc9Richard Lowe    }
77049d3bc9Richard Lowe    new_attr = (Dwarf_P_Attribute)
77107dc194Richard Lowe        _dwarf_p_get_alloc(ownerdie->di_dbg,
77207dc194Richard Lowe        sizeof(struct Dwarf_P_Attribute_s));
77349d3bc9Richard Lowe    if (new_attr == NULL) {
77407dc194Richard Lowe        DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC,
7754d9fdb4Robert Mustacchi            DW_DLV_ERROR);
77649d3bc9Richard Lowe    }
77749d3bc9Richard Lowe
77849d3bc9Richard Lowe    /* fill in the information */
77949d3bc9Richard Lowe    new_attr->ar_attribute = DW_AT_comp_dir;
7804d9fdb4Robert Mustacchi    res = _dwarf_pro_set_string_attr(new_attr,ownerdie->di_dbg,
7814d9fdb4Robert Mustacchi        current_working_directory,error);
7824d9fdb4Robert Mustacchi    if (res != DW_DLV_OK) {
7834d9fdb4Robert Mustacchi        return res;
78449d3bc9Richard Lowe    }
78549d3bc9Richard Lowe
78649d3bc9Richard Lowe    /* add attribute to the die */
78749d3bc9Richard Lowe    _dwarf_pro_add_at_to_die(ownerdie, new_attr);
7884d9fdb4Robert Mustacchi    *attr_out = new_attr;
7894d9fdb4Robert Mustacchi    return DW_DLV_OK;
79049d3bc9Richard Lowe}
79149d3bc9Richard Lowe
7924d9fdb4Robert Mustacchi
79349d3bc9Richard Loweint
79449d3bc9Richard Lowe_dwarf_pro_add_AT_fde(Dwarf_P_Debug dbg,
79507dc194Richard Lowe    Dwarf_P_Die die,
79607dc194Richard Lowe    Dwarf_Unsigned offset, Dwarf_Error * error)
79749d3bc9Richard Lowe{
79849d3bc9Richard Lowe    Dwarf_P_Attribute new_attr;
7994d9fdb4Robert Mustacchi    int uwordb_size = dbg->de_dwarf_offset_size;
80049d3bc9Richard Lowe
80149d3bc9Richard Lowe    if (die == NULL) {
8024d9fdb4Robert Mustacchi        DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, DW_DLV_ERROR);
80349d3bc9Richard Lowe    }
80449d3bc9Richard Lowe    new_attr = (Dwarf_P_Attribute)
80507dc194Richard Lowe        _dwarf_p_get_alloc(dbg,sizeof(struct Dwarf_P_Attribute_s));
80649d3bc9Richard Lowe    if (new_attr == NULL) {
8074d9fdb4Robert Mustacchi        DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, DW_DLV_ERROR);
80849d3bc9Richard Lowe    }
80949d3bc9Richard Lowe
81049d3bc9Richard Lowe    /* fill in the information */
81149d3bc9Richard Lowe    new_attr->ar_attribute = DW_AT_MIPS_fde;
8124d9fdb4Robert Mustacchi    new_attr->ar_attribute_form = dbg->de_ar_data_attribute_form;
81349d3bc9Richard Lowe    new_attr->ar_rel_type = dbg->de_offset_reloc;
81449d3bc9Richard Lowe    new_attr->ar_nbytes = uwordb_size;
81549d3bc9Richard Lowe    new_attr->ar_next = NULL;
81649d3bc9Richard Lowe    new_attr->ar_reloc_len = uwordb_size;
81749d3bc9Richard Lowe    new_attr->ar_data = (char *)
81807dc194Richard Lowe        _dwarf_p_get_alloc(dbg, uwordb_size);
81949d3bc9Richard Lowe    if (new_attr->ar_data == NULL) {
8204d9fdb4Robert Mustacchi        DWARF_P_DBG_ERROR(NULL, DW_DLE_ADDR_ALLOC, DW_DLV_ERROR);
82149d3bc9Richard Lowe    }
82249d3bc9Richard Lowe    {
82307dc194Richard Lowe        Dwarf_Unsigned du = offset;
82449d3bc9Richard Lowe
82507dc194Richard Lowe        WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data,
82607dc194Richard Lowe            (const void *) &du, sizeof(du), uwordb_size);
82749d3bc9Richard Lowe    }
82849d3bc9Richard Lowe    _dwarf_pro_add_at_to_die(die, new_attr);
8294d9fdb4Robert Mustacchi    return DW_DLV_OK;
83049d3bc9Richard Lowe}
83149d3bc9Richard Lowe
8324d9fdb4Robert Mustacchi/* Sept 2016: returns DW_DLV_OK or DW_DLV_ERROR */
83349d3bc9Richard Loweint
83449d3bc9Richard Lowe_dwarf_pro_add_AT_macro_info(Dwarf_P_Debug dbg,
83507dc194Richard Lowe    Dwarf_P_Die die,
83607dc194Richard Lowe    Dwarf_Unsigned offset, Dwarf_Error * error)
83749d3bc9Richard Lowe{
83849d3bc9Richard Lowe    Dwarf_P_Attribute new_attr;
8394d9fdb4Robert Mustacchi    int uwordb_size = dbg->de_dwarf_offset_size;
84049d3bc9Richard Lowe
84149d3bc9Richard Lowe    if (die == NULL) {
8424d9fdb4Robert Mustacchi        DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, DW_DLV_ERROR);
84349d3bc9Richard Lowe    }
84449d3bc9Richard Lowe    new_attr = (Dwarf_P_Attribute)
84507dc194Richard Lowe        _dwarf_p_get_alloc(dbg,sizeof(struct Dwarf_P_Attribute_s));
84649d3bc9Richard Lowe    if (new_attr == NULL) {
8474d9fdb4Robert Mustacchi        DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, DW_DLV_ERROR);
84849d3bc9Richard Lowe    }
84949d3bc9Richard Lowe
85049d3bc9Richard Lowe    /* fill in the information */
85149d3bc9Richard Lowe    new_attr->ar_attribute = DW_AT_macro_info;
85249d3bc9Richard Lowe    new_attr->ar_attribute_form = dbg->de_ar_data_attribute_form;
85349d3bc9Richard Lowe    new_attr->ar_rel_type = dbg->de_offset_reloc;
85449d3bc9Richard Lowe
85549d3bc9Richard Lowe    new_attr->ar_nbytes = uwordb_size;
85649d3bc9Richard Lowe    new_attr->ar_next = NULL;
85749d3bc9Richard Lowe    new_attr->ar_reloc_len = uwordb_size;
85849d3bc9Richard Lowe    new_attr->ar_data = (char *)
85907dc194Richard Lowe        _dwarf_p_get_alloc(dbg, uwordb_size);
86049d3bc9Richard Lowe    if (new_attr->ar_data == NULL) {
8614d9fdb4Robert Mustacchi        DWARF_P_DBG_ERROR(NULL, DW_DLE_ADDR_ALLOC, DW_DLV_ERROR);
86249d3bc9Richard Lowe    }
86349d3bc9Richard Lowe    {
86407dc194Richard Lowe        Dwarf_Unsigned du = offset;
86549d3bc9Richard Lowe
86607dc194Richard Lowe        WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data,
86707dc194Richard Lowe            (const void *) &du, sizeof(du), uwordb_size);
86849d3bc9Richard Lowe    }
86949d3bc9Richard Lowe
87049d3bc9Richard Lowe    _dwarf_pro_add_at_to_die(die, new_attr);
87149d3bc9Richard Lowe
8724d9fdb4Robert Mustacchi    return DW_DLV_OK;
87349d3bc9Richard Lowe}
87449d3bc9Richard Lowe
87549d3bc9Richard Lowe
8764d9fdb4Robert Mustacchi/*  Updates the list of attributes on this Dwarf_P_Die
8774d9fdb4Robert Mustacchi*/
87849d3bc9Richard Lowevoid
87949d3bc9Richard Lowe_dwarf_pro_add_at_to_die(Dwarf_P_Die die, Dwarf_P_Attribute attr)
88049d3bc9Richard Lowe{
88149d3bc9Richard Lowe    if (die->di_last_attr) {
8824d9fdb4Robert Mustacchi        /* Inserts new attr at the end */
88307dc194Richard Lowe        die->di_last_attr->ar_next = attr;
88407dc194Richard Lowe        die->di_last_attr = attr;
88507dc194Richard Lowe        die->di_n_attr++;
88649d3bc9Richard Lowe    } else {
88707dc194Richard Lowe        die->di_n_attr = 1;
88807dc194Richard Lowe        die->di_attrs = die->di_last_attr = attr;
88949d3bc9Richard Lowe    }
89049d3bc9Richard Lowe}