149d3bc9Richard Lowe/*
207dc194Richard Lowe  Copyright (C) 2000,2004 Silicon Graphics, Inc.  All Rights Reserved.
307dc194Richard Lowe  Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved.
44d9fdb4Robert Mustacchi  Portions Copyright 2007-2013 David Anderson. All rights reserved.
54d9fdb4Robert Mustacchi  Portions Copyright 2012 SN Systems Ltd. All rights reserved.
649d3bc9Richard Lowe
749d3bc9Richard Lowe  This program is free software; you can redistribute it and/or modify it
84d9fdb4Robert Mustacchi  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
134d9fdb4Robert Mustacchi  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1449d3bc9Richard Lowe
1549d3bc9Richard Lowe  Further, this software is distributed without any warranty that it is
164d9fdb4Robert Mustacchi  free of the rightful claim of any third person regarding infringement
174d9fdb4Robert Mustacchi  or the like.  Any license provided herein, whether implied or
1849d3bc9Richard Lowe  otherwise, applies only to this software file.  Patent licenses, if
194d9fdb4Robert Mustacchi  any, provided herein do not apply to combinations of this program with
204d9fdb4Robert Mustacchi  other software, or any other product whatsoever.
2149d3bc9Richard Lowe
224d9fdb4Robert Mustacchi  You should have received a copy of the GNU Lesser General Public
234d9fdb4Robert Mustacchi  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
2749d3bc9Richard Lowe*/
2849d3bc9Richard Lowe
2949d3bc9Richard Lowe#include "config.h"
3049d3bc9Richard Lowe#include "libdwarfdefs.h"
3149d3bc9Richard Lowe#include <stdio.h>
3249d3bc9Richard Lowe#include <string.h>
3349d3bc9Richard Lowe#include <limits.h>
3449d3bc9Richard Lowe#include "pro_incl.h"
354d9fdb4Robert Mustacchi#include <stddef.h>
364d9fdb4Robert Mustacchi#include "dwarf.h"
374d9fdb4Robert Mustacchi#include "libdwarf.h"
384d9fdb4Robert Mustacchi#include "pro_opaque.h"
394d9fdb4Robert Mustacchi#include "pro_error.h"
404d9fdb4Robert Mustacchi#include "pro_encode_nm.h"
414d9fdb4Robert Mustacchi#include "pro_alloc.h"
424d9fdb4Robert Mustacchi#include "pro_die.h"
4349d3bc9Richard Lowe#include "pro_expr.h"
4449d3bc9Richard Lowe
4549d3bc9Richard Lowe#ifndef R_MIPS_NONE
4649d3bc9Richard Lowe#define R_MIPS_NONE 0
4749d3bc9Richard Lowe#endif
4849d3bc9Richard Lowe
4949d3bc9Richard Lowe
504d9fdb4Robert Mustacchi/* Indicates no relocation needed. */
5107dc194Richard Lowe#define NO_ELF_SYM_INDEX        0
5249d3bc9Richard Lowe
5349d3bc9Richard Lowe
544d9fdb4Robert Mustacchi#ifdef WORDS_BIGENDIAN
554d9fdb4Robert Mustacchi#define ASNAR(t,s,l)                   \
564d9fdb4Robert Mustacchi    do {                                    \
574d9fdb4Robert Mustacchi        unsigned tbyte = sizeof(t) - l;     \
584d9fdb4Robert Mustacchi        t = 0;                              \
594d9fdb4Robert Mustacchi        dbg->de_copy_word(((char *)&t)+tbyte ,&s[0],l);\
604d9fdb4Robert Mustacchi    } while (0)
614d9fdb4Robert Mustacchi#else /* LITTLE ENDIAN */
624d9fdb4Robert Mustacchi#define ASNAR(t,s,l)                 \
634d9fdb4Robert Mustacchi    do {                                \
644d9fdb4Robert Mustacchi        t = 0;                          \
654d9fdb4Robert Mustacchi        dbg->de_copy_word(&t,&s[0],l);             \
664d9fdb4Robert Mustacchi    } while (0)
674d9fdb4Robert Mustacchi#endif /* end LITTLE- BIG-ENDIAN */
684d9fdb4Robert Mustacchi
694d9fdb4Robert Mustacchi
704d9fdb4Robert Mustacchi#ifdef WORDS_BIGENDIAN
714d9fdb4Robert Mustacchi#define ASNOUT(t,s,l)                       \
724d9fdb4Robert Mustacchi    do {                                    \
734d9fdb4Robert Mustacchi        unsigned sbyte = 0;                 \
744d9fdb4Robert Mustacchi        char *p = 0;                        \
754d9fdb4Robert Mustacchi        if (l > sizeof(s)) {                \
764d9fdb4Robert Mustacchi            _dwarf_p_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);\
774d9fdb4Robert Mustacchi            return DW_DLV_ERROR;            \
784d9fdb4Robert Mustacchi        }                                   \
794d9fdb4Robert Mustacchi        sbyte = sizeof(s) - l;              \
804d9fdb4Robert Mustacchi        p = (const char *)(&s);             \
814d9fdb4Robert Mustacchi        dbg->de_copy_word(t,(const void *)(p+sbyte),l);\
824d9fdb4Robert Mustacchi    } while (0)
834d9fdb4Robert Mustacchi#else /* LITTLEENDIAN */
844d9fdb4Robert Mustacchi#define ASNOUT(t,s,l)                       \
854d9fdb4Robert Mustacchi    do {                                    \
864d9fdb4Robert Mustacchi        const char *p = 0;                  \
874d9fdb4Robert Mustacchi        if (l > sizeof(s)) {                \
884d9fdb4Robert Mustacchi            _dwarf_p_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);\
894d9fdb4Robert Mustacchi            return DW_DLV_ERROR;            \
904d9fdb4Robert Mustacchi        }                                   \
914d9fdb4Robert Mustacchi        p = (const char *)(&s);             \
924d9fdb4Robert Mustacchi        memcpy(t,(const void *)p,l);        \
934d9fdb4Robert Mustacchi        dbg->de_copy_word(t,(const void *)p,l); \
944d9fdb4Robert Mustacchi    } while (0)
954d9fdb4Robert Mustacchi#endif /* ENDIANNESS */
964d9fdb4Robert Mustacchi
974d9fdb4Robert Mustacchi#ifdef WORDS_BIGENDIAN
984d9fdb4Robert Mustacchi#define SIGN_EXTEND(dest, length)                                 \
994d9fdb4Robert Mustacchi    do {                                                          \
1004d9fdb4Robert Mustacchi        if (*(Dwarf_Sbyte *)((char *)&dest +                      \
1014d9fdb4Robert Mustacchi            sizeof(dest) - length) < 0) {                         \
1024d9fdb4Robert Mustacchi            memcpy((char *)&dest, "\xff\xff\xff\xff\xff\xff\xff\xff",\
1034d9fdb4Robert Mustacchi                sizeof(dest) - length);                           \
1044d9fdb4Robert Mustacchi        }                                                         \
1054d9fdb4Robert Mustacchi    } while (0)
1064d9fdb4Robert Mustacchi#else /* LITTLE ENDIAN */
1074d9fdb4Robert Mustacchi#define SIGN_EXTEND(dest, length)                               \
1084d9fdb4Robert Mustacchi    do {                                                        \
1094d9fdb4Robert Mustacchi        if (*(Dwarf_Sbyte *)((char *)&dest + (length-1)) < 0) { \
1104d9fdb4Robert Mustacchi            memcpy((char *)&dest+length,                        \
1114d9fdb4Robert Mustacchi                "\xff\xff\xff\xff\xff\xff\xff\xff",             \
1124d9fdb4Robert Mustacchi                sizeof(dest) - length);                         \
1134d9fdb4Robert Mustacchi        }                                                       \
1144d9fdb4Robert Mustacchi    } while (0)
1154d9fdb4Robert Mustacchi
1164d9fdb4Robert Mustacchi#endif /* ! LITTLE_ENDIAN */
1174d9fdb4Robert Mustacchi
1184d9fdb4Robert Mustacchi
1194d9fdb4Robert Mustacchi/*  This function adds an attribute whose value is
12049d3bc9Richard Lowe    a target address to the given die.  The attribute
12149d3bc9Richard Lowe    is given the name provided by attr.  The address
1224d9fdb4Robert Mustacchi    is given in pc_value.  */
1234d9fdb4Robert Mustacchi
1244d9fdb4Robert Mustacchistatic int
1254d9fdb4Robert Mustacchilocal_add_AT_address_a(Dwarf_P_Debug dbg,
1264d9fdb4Robert Mustacchi    Dwarf_P_Die ownerdie,
1274d9fdb4Robert Mustacchi    Dwarf_Half attr,
1284d9fdb4Robert Mustacchi    Dwarf_Signed form,
1294d9fdb4Robert Mustacchi    Dwarf_Unsigned pc_value,
1304d9fdb4Robert Mustacchi    Dwarf_Unsigned sym_index,
1314d9fdb4Robert Mustacchi    Dwarf_P_Attribute *attr_out,
1324d9fdb4Robert Mustacchi    Dwarf_Error * error);
13307dc194Richard Lowe
13449d3bc9Richard Lowe/* old interface */
13549d3bc9Richard LoweDwarf_P_Attribute
13649d3bc9Richard Lowedwarf_add_AT_targ_address(Dwarf_P_Debug dbg,
1374d9fdb4Robert Mustacchi    Dwarf_P_Die ownerdie,
1384d9fdb4Robert Mustacchi    Dwarf_Half attr,
1394d9fdb4Robert Mustacchi    Dwarf_Unsigned pc_value,
1404d9fdb4Robert Mustacchi    Dwarf_Signed sym_index, Dwarf_Error * error)
14149d3bc9Richard Lowe{
1424d9fdb4Robert Mustacchi    Dwarf_P_Attribute a = 0;
1434d9fdb4Robert Mustacchi    int res = 0;
1444d9fdb4Robert Mustacchi
1454d9fdb4Robert Mustacchi    if (sym_index < 0) {
1464d9fdb4Robert Mustacchi        return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
1474d9fdb4Robert Mustacchi    }
1484d9fdb4Robert Mustacchi    res =   dwarf_add_AT_targ_address_c(dbg,
1494d9fdb4Robert Mustacchi        ownerdie, attr, pc_value,
1504d9fdb4Robert Mustacchi        (Dwarf_Unsigned) sym_index,
1514d9fdb4Robert Mustacchi        &a,
1524d9fdb4Robert Mustacchi        error);
1534d9fdb4Robert Mustacchi    if (res != DW_DLV_OK) {
1544d9fdb4Robert Mustacchi        return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
1554d9fdb4Robert Mustacchi    }
1564d9fdb4Robert Mustacchi    return a;
1574d9fdb4Robert Mustacchi
15849d3bc9Richard Lowe}
15949d3bc9Richard Lowe
1604d9fdb4Robert Mustacchi/*  New interface, replacing dwarf_add_AT_targ_address.
1614d9fdb4Robert Mustacchi    Essentially just makes sym_index a Dwarf_Unsigned
1624d9fdb4Robert Mustacchi    so for symbolic relocations it can be a full address.  */
16349d3bc9Richard LoweDwarf_P_Attribute
16449d3bc9Richard Lowedwarf_add_AT_targ_address_b(Dwarf_P_Debug dbg,
1654d9fdb4Robert Mustacchi    Dwarf_P_Die ownerdie,
1664d9fdb4Robert Mustacchi    Dwarf_Half attr,
1674d9fdb4Robert Mustacchi    Dwarf_Unsigned pc_value,
1684d9fdb4Robert Mustacchi    Dwarf_Unsigned sym_index,
1694d9fdb4Robert Mustacchi    Dwarf_Error * error)
1704d9fdb4Robert Mustacchi{
1714d9fdb4Robert Mustacchi    Dwarf_P_Attribute a = 0;
1724d9fdb4Robert Mustacchi    int res = 0;
1734d9fdb4Robert Mustacchi
1744d9fdb4Robert Mustacchi    res = dwarf_add_AT_targ_address_c(dbg,
1754d9fdb4Robert Mustacchi        ownerdie,attr,pc_value,sym_index,
1764d9fdb4Robert Mustacchi        &a, error);
1774d9fdb4Robert Mustacchi    if (res != DW_DLV_OK) {
1784d9fdb4Robert Mustacchi        return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
1794d9fdb4Robert Mustacchi    }
1804d9fdb4Robert Mustacchi    return a;
1814d9fdb4Robert Mustacchi
1824d9fdb4Robert Mustacchi}
1834d9fdb4Robert Mustacchiint
1844d9fdb4Robert Mustacchidwarf_add_AT_targ_address_c(Dwarf_P_Debug dbg,
1854d9fdb4Robert Mustacchi    Dwarf_P_Die ownerdie,
1864d9fdb4Robert Mustacchi    Dwarf_Half attr,
1874d9fdb4Robert Mustacchi    Dwarf_Unsigned pc_value,
1884d9fdb4Robert Mustacchi    Dwarf_Unsigned sym_index,
1894d9fdb4Robert Mustacchi    Dwarf_P_Attribute *attr_out,
1904d9fdb4Robert Mustacchi    Dwarf_Error * error)
19107dc194Richard Lowe{
1924d9fdb4Robert Mustacchi    int res = 0;
1934d9fdb4Robert Mustacchi
19407dc194Richard Lowe    switch (attr) {
19507dc194Richard Lowe    case DW_AT_low_pc:
19607dc194Richard Lowe    case DW_AT_high_pc:
19707dc194Richard Lowe
19807dc194Richard Lowe    /* added to support location lists */
19907dc194Richard Lowe    /* no way to check that this is a loclist-style address though */
20007dc194Richard Lowe    case DW_AT_location:
20107dc194Richard Lowe    case DW_AT_string_length:
20207dc194Richard Lowe    case DW_AT_return_addr:
20307dc194Richard Lowe    case DW_AT_frame_base:
20407dc194Richard Lowe    case DW_AT_segment:
20507dc194Richard Lowe    case DW_AT_static_link:
20607dc194Richard Lowe    case DW_AT_use_location:
20707dc194Richard Lowe    case DW_AT_vtable_elem_location:
20807dc194Richard Lowe    case DW_AT_const_value: /* Gcc can generate this as address. */
20907dc194Richard Lowe    case DW_AT_entry_pc:
21007dc194Richard Lowe        break;
2114d9fdb4Robert Mustacchi    default:
2124d9fdb4Robert Mustacchi        if (attr < DW_AT_lo_user || attr > DW_AT_hi_user ) {
21307dc194Richard Lowe            _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
2144d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
21507dc194Richard Lowe        }
21607dc194Richard Lowe        break;
21707dc194Richard Lowe    }
2184d9fdb4Robert Mustacchi
2194d9fdb4Robert Mustacchi    res = local_add_AT_address_a(dbg, ownerdie, attr, DW_FORM_addr,
2204d9fdb4Robert Mustacchi        pc_value, sym_index,attr_out, error);
2214d9fdb4Robert Mustacchi    return res;
22207dc194Richard Lowe}
22307dc194Richard Lowe
22407dc194Richard LoweDwarf_P_Attribute
22507dc194Richard Lowedwarf_add_AT_ref_address(Dwarf_P_Debug dbg,
2264d9fdb4Robert Mustacchi    Dwarf_P_Die ownerdie,
2274d9fdb4Robert Mustacchi    Dwarf_Half attr,
2284d9fdb4Robert Mustacchi    Dwarf_Unsigned pc_value,
2294d9fdb4Robert Mustacchi    Dwarf_Unsigned sym_index,
2304d9fdb4Robert Mustacchi    Dwarf_Error * error)
2314d9fdb4Robert Mustacchi{
2324d9fdb4Robert Mustacchi    Dwarf_P_Attribute a = 0;
2334d9fdb4Robert Mustacchi    int res = 0;
2344d9fdb4Robert Mustacchi
2354d9fdb4Robert Mustacchi    res = dwarf_add_AT_ref_address_a(dbg,ownerdie,
2364d9fdb4Robert Mustacchi        attr,pc_value,sym_index,&a,error);
2374d9fdb4Robert Mustacchi    if (res != DW_DLV_OK) {
2384d9fdb4Robert Mustacchi        return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
2394d9fdb4Robert Mustacchi    }
2404d9fdb4Robert Mustacchi    return a;
2414d9fdb4Robert Mustacchi}
2424d9fdb4Robert Mustacchi
2434d9fdb4Robert Mustacchiint
2444d9fdb4Robert Mustacchidwarf_add_AT_ref_address_a(Dwarf_P_Debug dbg,
2454d9fdb4Robert Mustacchi    Dwarf_P_Die ownerdie,
2464d9fdb4Robert Mustacchi    Dwarf_Half attr,
2474d9fdb4Robert Mustacchi    Dwarf_Unsigned pc_value,
2484d9fdb4Robert Mustacchi    Dwarf_Unsigned sym_index,
2494d9fdb4Robert Mustacchi    Dwarf_P_Attribute *attr_out,
2504d9fdb4Robert Mustacchi    Dwarf_Error * error)
25107dc194Richard Lowe{
2524d9fdb4Robert Mustacchi    int res = 0;
2534d9fdb4Robert Mustacchi
25407dc194Richard Lowe    switch (attr) {
25507dc194Richard Lowe    case DW_AT_type:
25607dc194Richard Lowe    case DW_AT_import:
25707dc194Richard Lowe        break;
25807dc194Richard Lowe
2594d9fdb4Robert Mustacchi    default:
2604d9fdb4Robert Mustacchi        if (attr < DW_AT_lo_user || attr > DW_AT_hi_user ) {
26107dc194Richard Lowe            _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
2624d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
26307dc194Richard Lowe        }
26407dc194Richard Lowe        break;
26507dc194Richard Lowe    }
2664d9fdb4Robert Mustacchi
2674d9fdb4Robert Mustacchi    /*  FIXME: For DWARF3 and later this call is problematic as
2684d9fdb4Robert Mustacchi        DW_FORM_ref_addr is really an offset in
2694d9fdb4Robert Mustacchi        .debug_info , not an address.  */
2704d9fdb4Robert Mustacchi    res = local_add_AT_address_a(dbg, ownerdie,
2714d9fdb4Robert Mustacchi        attr, DW_FORM_ref_addr,
2724d9fdb4Robert Mustacchi        pc_value, sym_index,attr_out, error);
2734d9fdb4Robert Mustacchi    return res;
27407dc194Richard Lowe}
27507dc194Richard Lowe
27607dc194Richard Lowe
27707dc194Richard Lowe/* Make sure attribute types are checked before entering here. */
2784d9fdb4Robert Mustacchistatic int
2794d9fdb4Robert Mustacchilocal_add_AT_address_a(Dwarf_P_Debug dbg,
2804d9fdb4Robert Mustacchi    Dwarf_P_Die ownerdie,
2814d9fdb4Robert Mustacchi    Dwarf_Half attr,
2824d9fdb4Robert Mustacchi    Dwarf_Signed form,
2834d9fdb4Robert Mustacchi    Dwarf_Unsigned pc_value,
2844d9fdb4Robert Mustacchi    Dwarf_Unsigned sym_index,
2854d9fdb4Robert Mustacchi    Dwarf_P_Attribute *attr_out,
2864d9fdb4Robert Mustacchi    Dwarf_Error * error)
28749d3bc9Richard Lowe{
28849d3bc9Richard Lowe    Dwarf_P_Attribute new_attr;
2894d9fdb4Robert Mustacchi    int upointer_size = 0;
29049d3bc9Richard Lowe
29149d3bc9Richard Lowe    if (dbg == NULL) {
29207dc194Richard Lowe        _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
2934d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
29449d3bc9Richard Lowe    }
2954d9fdb4Robert Mustacchi    upointer_size = dbg->de_pointer_size;
29649d3bc9Richard Lowe
29749d3bc9Richard Lowe    if (ownerdie == NULL) {
29807dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
2994d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
30049d3bc9Richard Lowe    }
30149d3bc9Richard Lowe
30207dc194Richard Lowe    /* attribute types have already been checked */
30307dc194Richard Lowe    /* switch (attr) { ... } */
30449d3bc9Richard Lowe
30549d3bc9Richard Lowe    new_attr = (Dwarf_P_Attribute)
30607dc194Richard Lowe        _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
30749d3bc9Richard Lowe    if (new_attr == NULL) {
30807dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
3094d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
31049d3bc9Richard Lowe    }
31149d3bc9Richard Lowe
31249d3bc9Richard Lowe    new_attr->ar_attribute = attr;
31307dc194Richard Lowe    new_attr->ar_attribute_form = form;
31449d3bc9Richard Lowe    new_attr->ar_nbytes = upointer_size;
31549d3bc9Richard Lowe    new_attr->ar_rel_symidx = sym_index;
31649d3bc9Richard Lowe    new_attr->ar_reloc_len = upointer_size;
31749d3bc9Richard Lowe    new_attr->ar_next = 0;
3184d9fdb4Robert Mustacchi    if (sym_index != NO_ELF_SYM_INDEX) {
31907dc194Richard Lowe        new_attr->ar_rel_type = dbg->de_ptr_reloc;
3204d9fdb4Robert Mustacchi    } else {
32107dc194Richard Lowe        new_attr->ar_rel_type = R_MIPS_NONE;
3224d9fdb4Robert Mustacchi    }
32349d3bc9Richard Lowe
32449d3bc9Richard Lowe    new_attr->ar_data = (char *)
32507dc194Richard Lowe        _dwarf_p_get_alloc(dbg, upointer_size);
32649d3bc9Richard Lowe    if (new_attr->ar_data == NULL) {
32707dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
3284d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
32949d3bc9Richard Lowe    }
33049d3bc9Richard Lowe    WRITE_UNALIGNED(dbg, new_attr->ar_data,
3314d9fdb4Robert Mustacchi        (const void *) &pc_value,
3324d9fdb4Robert Mustacchi        sizeof(pc_value), upointer_size);
33307dc194Richard Lowe
33407dc194Richard Lowe    /* add attribute to the die */
33507dc194Richard Lowe    _dwarf_pro_add_at_to_die(ownerdie, new_attr);
3364d9fdb4Robert Mustacchi    *attr_out = new_attr;
3374d9fdb4Robert Mustacchi    return DW_DLV_OK;
33807dc194Richard Lowe}
33907dc194Richard Lowe
3404d9fdb4Robert Mustacchi/*  Pass in array (ie a pointer to) of Dwarf_Signed
3414d9fdb4Robert Mustacchi    with input_array_length elements.
3424d9fdb4Robert Mustacchi
3434d9fdb4Robert Mustacchi    A block of bytes is created
3444d9fdb4Robert Mustacchi    with the sleb data in it.
3454d9fdb4Robert Mustacchi
3464d9fdb4Robert Mustacchi    A pointer to the glob of bytes is returned
3474d9fdb4Robert Mustacchi    through the output_block pointer and its length
3484d9fdb4Robert Mustacchi    through output_block_len pointer. */
3494d9fdb4Robert Mustacchiint
3504d9fdb4Robert Mustacchidwarf_compress_integer_block_a(
3514d9fdb4Robert Mustacchi    Dwarf_P_Debug    dbg,
3524d9fdb4Robert Mustacchi    Dwarf_Unsigned  input_array_length,
3534d9fdb4Robert Mustacchi    Dwarf_Signed *  input_array,
3544d9fdb4Robert Mustacchi    Dwarf_Unsigned *output_block_len,
3554d9fdb4Robert Mustacchi    void         ** output_block_returned,
3564d9fdb4Robert Mustacchi    Dwarf_Error*     error
3574d9fdb4Robert Mustacchi)
3584d9fdb4Robert Mustacchi{
3594d9fdb4Robert Mustacchi    Dwarf_Unsigned output_length_in_bytes = 0;
3604d9fdb4Robert Mustacchi    char * output_block = 0;
3614d9fdb4Robert Mustacchi    char encode_buffer[ENCODE_SPACE_NEEDED];
3624d9fdb4Robert Mustacchi    unsigned u = 0;
3634d9fdb4Robert Mustacchi    char * ptr = 0;
3644d9fdb4Robert Mustacchi    int remain = 0;
3654d9fdb4Robert Mustacchi    int result = 0;
3664d9fdb4Robert Mustacchi
3674d9fdb4Robert Mustacchi    if (dbg == NULL) {
3684d9fdb4Robert Mustacchi        _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
3694d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
3704d9fdb4Robert Mustacchi    }
3714d9fdb4Robert Mustacchi    /* First compress everything to find the total size. */
3724d9fdb4Robert Mustacchi
3734d9fdb4Robert Mustacchi    output_length_in_bytes = 0;
3744d9fdb4Robert Mustacchi    for (u=0; u<input_array_length; u++) {
3754d9fdb4Robert Mustacchi        int unit_encoded_size;
3764d9fdb4Robert Mustacchi        Dwarf_Signed unit = 0;
3774d9fdb4Robert Mustacchi
3784d9fdb4Robert Mustacchi        unit = input_array[u];
3794d9fdb4Robert Mustacchi        result = _dwarf_pro_encode_signed_leb128_nm(
3804d9fdb4Robert Mustacchi            unit, &unit_encoded_size,
3814d9fdb4Robert Mustacchi            encode_buffer,sizeof(encode_buffer));
3824d9fdb4Robert Mustacchi        if (result !=  DW_DLV_OK) {
3834d9fdb4Robert Mustacchi            _dwarf_p_error(NULL, error, DW_DLE_LEB_IMPROPER);
3844d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
3854d9fdb4Robert Mustacchi        }
3864d9fdb4Robert Mustacchi        output_length_in_bytes += unit_encoded_size;
3874d9fdb4Robert Mustacchi    }
3884d9fdb4Robert Mustacchi    output_block = (void *)
3894d9fdb4Robert Mustacchi        _dwarf_p_get_alloc(dbg, output_length_in_bytes);
3904d9fdb4Robert Mustacchi    if (output_block == NULL) {
3914d9fdb4Robert Mustacchi        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
3924d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
3934d9fdb4Robert Mustacchi    }
3944d9fdb4Robert Mustacchi
3954d9fdb4Robert Mustacchi    /* Then compress again and copy into new buffer */
3964d9fdb4Robert Mustacchi    ptr = output_block;
3974d9fdb4Robert Mustacchi    remain = output_length_in_bytes;
3984d9fdb4Robert Mustacchi    for (u=0; u<input_array_length; u++) {
3994d9fdb4Robert Mustacchi        int unit_encoded_size;
4004d9fdb4Robert Mustacchi        Dwarf_Signed unit = 0;
4014d9fdb4Robert Mustacchi
4024d9fdb4Robert Mustacchi        unit = input_array[u];
4034d9fdb4Robert Mustacchi        result = _dwarf_pro_encode_signed_leb128_nm(unit,
4044d9fdb4Robert Mustacchi            &unit_encoded_size,
4054d9fdb4Robert Mustacchi            ptr, remain);
4064d9fdb4Robert Mustacchi        if (result !=  DW_DLV_OK) {
4074d9fdb4Robert Mustacchi            _dwarf_p_error(NULL, error, DW_DLE_LEB_IMPROPER);
4084d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
4094d9fdb4Robert Mustacchi        }
4104d9fdb4Robert Mustacchi        remain -= unit_encoded_size;
4114d9fdb4Robert Mustacchi        ptr += unit_encoded_size;
4124d9fdb4Robert Mustacchi    }
4134d9fdb4Robert Mustacchi
4144d9fdb4Robert Mustacchi    *output_block_len = output_length_in_bytes;
4154d9fdb4Robert Mustacchi    *output_block_returned = output_block;
4164d9fdb4Robert Mustacchi    return DW_DLV_OK;
4174d9fdb4Robert Mustacchi}
4184d9fdb4Robert Mustacchi/*  Functions to compress and uncompress data from normal
4194d9fdb4Robert Mustacchi    arrays of integral types into arrays of LEB128 numbers.
4204d9fdb4Robert Mustacchi    Extend these functions as needed to handle wider input
4214d9fdb4Robert Mustacchi    variety.  Return values should be freed with _dwarf_p_dealloc
4224d9fdb4Robert Mustacchi    after they aren't needed any more.
4234d9fdb4Robert Mustacchi
4244d9fdb4Robert Mustacchi    It is not clear there is any use to this function
4254d9fdb4Robert Mustacchi    as it was contributed by SUN but may not have ever
4264d9fdb4Robert Mustacchi    been needed in any released SUN compiler. */
42707dc194Richard Lowe
4284d9fdb4Robert Mustacchi/* return value points to an array of LEB numbers */
42907dc194Richard Lowe
43007dc194Richard Lowevoid *
43107dc194Richard Lowedwarf_compress_integer_block(
43207dc194Richard Lowe    Dwarf_P_Debug    dbg,
43307dc194Richard Lowe    Dwarf_Bool       unit_is_signed,
43407dc194Richard Lowe    Dwarf_Small      unit_length_in_bits,
43507dc194Richard Lowe    void*            input_block,
43607dc194Richard Lowe    Dwarf_Unsigned   input_length_in_units,
43707dc194Richard Lowe    Dwarf_Unsigned*  output_length_in_bytes_ptr,
43807dc194Richard Lowe    Dwarf_Error*     error
43907dc194Richard Lowe)
44007dc194Richard Lowe{
44107dc194Richard Lowe    Dwarf_Unsigned output_length_in_bytes = 0;
44207dc194Richard Lowe    char * output_block = 0;
44307dc194Richard Lowe    char encode_buffer[ENCODE_SPACE_NEEDED];
4444d9fdb4Robert Mustacchi    unsigned u = 0;
44507dc194Richard Lowe    char * ptr = 0;
44607dc194Richard Lowe    int remain = 0;
44707dc194Richard Lowe    int result = 0;
4484d9fdb4Robert Mustacchi    char *inptr = 0;
44907dc194Richard Lowe
45007dc194Richard Lowe    if (dbg == NULL) {
45107dc194Richard Lowe        _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
45207dc194Richard Lowe        return((void *)DW_DLV_BADADDR);
45307dc194Richard Lowe    }
4544d9fdb4Robert Mustacchi
45507dc194Richard Lowe    if (unit_is_signed == false ||
45607dc194Richard Lowe        unit_length_in_bits != 32 ||
45707dc194Richard Lowe        input_block == NULL ||
45807dc194Richard Lowe        input_length_in_units == 0 ||
45907dc194Richard Lowe        output_length_in_bytes_ptr == NULL) {
46007dc194Richard Lowe        _dwarf_p_error(NULL, error, DW_DLE_BADBITC);
46107dc194Richard Lowe        return ((void *) DW_DLV_BADADDR);
46207dc194Richard Lowe    }
46307dc194Richard Lowe
46407dc194Richard Lowe    /* At this point we assume the format is: signed 32 bit */
46507dc194Richard Lowe
4664d9fdb4Robert Mustacchi    /* First compress everything to find the total size. */
46707dc194Richard Lowe
46807dc194Richard Lowe    output_length_in_bytes = 0;
4694d9fdb4Robert Mustacchi    inptr = input_block;
4704d9fdb4Robert Mustacchi    for (u=0; u<input_length_in_units; u++) {
47107dc194Richard Lowe        int unit_encoded_size;
4724d9fdb4Robert Mustacchi        Dwarf_Signed unit = 0;
4734d9fdb4Robert Mustacchi
4744d9fdb4Robert Mustacchi        ASNAR(unit,inptr,DWARF_32BIT_SIZE);
4754d9fdb4Robert Mustacchi        SIGN_EXTEND(unit,DWARF_32BIT_SIZE);
4764d9fdb4Robert Mustacchi        result = _dwarf_pro_encode_signed_leb128_nm(
4774d9fdb4Robert Mustacchi            unit, &unit_encoded_size,
4784d9fdb4Robert Mustacchi            encode_buffer,sizeof(encode_buffer));
47907dc194Richard Lowe        if (result !=  DW_DLV_OK) {
48007dc194Richard Lowe            _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
48107dc194Richard Lowe            return((Dwarf_P_Attribute)DW_DLV_BADADDR);
48207dc194Richard Lowe        }
48307dc194Richard Lowe        output_length_in_bytes += unit_encoded_size;
4844d9fdb4Robert Mustacchi        inptr += DWARF_32BIT_SIZE;
48507dc194Richard Lowe    }
48607dc194Richard Lowe
4874d9fdb4Robert Mustacchi    /* Then alloc */
48807dc194Richard Lowe    output_block = (void *)
48907dc194Richard Lowe        _dwarf_p_get_alloc(dbg, output_length_in_bytes);
49007dc194Richard Lowe    if (output_block == NULL) {
49107dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
49207dc194Richard Lowe        return((void*)DW_DLV_BADADDR);
49307dc194Richard Lowe    }
49407dc194Richard Lowe
4954d9fdb4Robert Mustacchi    /* Then compress again and copy into new buffer */
49607dc194Richard Lowe    ptr = output_block;
4974d9fdb4Robert Mustacchi    inptr = input_block;
49807dc194Richard Lowe    remain = output_length_in_bytes;
4994d9fdb4Robert Mustacchi    for (u=0; u<input_length_in_units; u++) {
50007dc194Richard Lowe        int unit_encoded_size;
5014d9fdb4Robert Mustacchi        Dwarf_Signed unit = 0;
5024d9fdb4Robert Mustacchi
5034d9fdb4Robert Mustacchi        ASNAR(unit,inptr,DWARF_32BIT_SIZE);
5044d9fdb4Robert Mustacchi        SIGN_EXTEND(unit,DWARF_32BIT_SIZE);
5054d9fdb4Robert Mustacchi        result = _dwarf_pro_encode_signed_leb128_nm(unit,
5064d9fdb4Robert Mustacchi            &unit_encoded_size,
5074d9fdb4Robert Mustacchi            ptr, remain);
50807dc194Richard Lowe        if (result !=  DW_DLV_OK) {
50907dc194Richard Lowe            _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
51007dc194Richard Lowe            return((Dwarf_P_Attribute)DW_DLV_BADADDR);
51107dc194Richard Lowe        }
51207dc194Richard Lowe        remain -= unit_encoded_size;
51307dc194Richard Lowe        ptr += unit_encoded_size;
5144d9fdb4Robert Mustacchi        inptr += DWARF_32BIT_SIZE;
51507dc194Richard Lowe    }
51607dc194Richard Lowe
51707dc194Richard Lowe    if (remain != 0) {
51807dc194Richard Lowe        _dwarf_p_dealloc(dbg, (unsigned char *)output_block);
51907dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
52007dc194Richard Lowe        return((Dwarf_P_Attribute)DW_DLV_BADADDR);
52107dc194Richard Lowe    }
52207dc194Richard Lowe
52307dc194Richard Lowe    *output_length_in_bytes_ptr = output_length_in_bytes;
52407dc194Richard Lowe    return (void*) output_block;
52507dc194Richard Lowe}
52607dc194Richard Lowe
52707dc194Richard Lowevoid
52807dc194Richard Lowedwarf_dealloc_compressed_block(Dwarf_P_Debug dbg, void * space)
52907dc194Richard Lowe{
53007dc194Richard Lowe    _dwarf_p_dealloc(dbg, space);
53107dc194Richard Lowe}
53207dc194Richard Lowe
5334d9fdb4Robert Mustacchi/*  This is very similar to targ_address but results in a different FORM */
5344d9fdb4Robert Mustacchi/*  dbg->de_ar_data_attribute_form is data4 or data8
5354d9fdb4Robert Mustacchi    and dwarf4 changes the definition for such on DW_AT_high_pc.
5364d9fdb4Robert Mustacchi    DWARF 3: the FORM here has no defined meaning for dwarf3.
5374d9fdb4Robert Mustacchi    DWARF 4: the FORM here means that for DW_AT_high_pc the value
5384d9fdb4Robert Mustacchi        is not a high address but is instead an offset
5394d9fdb4Robert Mustacchi        from a (separate) DW_AT_low_pc.
5404d9fdb4Robert Mustacchi    The intent for DWARF4 is that this is not a relocated
5414d9fdb4Robert Mustacchi    address at all.  Instead a simple offset.
5424d9fdb4Robert Mustacchi    But this should NOT be called for a simple non-relocated offset.
5434d9fdb4Robert Mustacchi    So do not call this with an attr of DW_AT_high_pc.
5444d9fdb4Robert Mustacchi    Use dwarf_add_AT_unsigned_const() (for example) instead of
5454d9fdb4Robert Mustacchi    dwarf_add_AT_dataref when the value is a simple offset .  */
5464d9fdb4Robert Mustacchi
5474d9fdb4Robert Mustacchiint
5484d9fdb4Robert Mustacchidwarf_add_AT_dataref_a(
54907dc194Richard Lowe    Dwarf_P_Debug dbg,
55007dc194Richard Lowe    Dwarf_P_Die ownerdie,
55107dc194Richard Lowe    Dwarf_Half attr,
55207dc194Richard Lowe    Dwarf_Unsigned pc_value,
55307dc194Richard Lowe    Dwarf_Unsigned sym_index,
5544d9fdb4Robert Mustacchi    Dwarf_P_Attribute *attr_out,
55507dc194Richard Lowe    Dwarf_Error * error)
55607dc194Richard Lowe{
5574d9fdb4Robert Mustacchi    int res = 0;
5584d9fdb4Robert Mustacchi
55907dc194Richard Lowe    /* TODO: Add checking here */
5604d9fdb4Robert Mustacchi    res = local_add_AT_address_a(dbg, ownerdie, attr,
5614d9fdb4Robert Mustacchi        dbg->de_ar_data_attribute_form,
5624d9fdb4Robert Mustacchi        pc_value,
5634d9fdb4Robert Mustacchi        sym_index,
5644d9fdb4Robert Mustacchi        attr_out,
5654d9fdb4Robert Mustacchi        error);
5664d9fdb4Robert Mustacchi    return res;
56707dc194Richard Lowe}
56807dc194Richard Lowe
56907dc194Richard Lowe
5704d9fdb4Robert MustacchiDwarf_P_Attribute
5714d9fdb4Robert Mustacchidwarf_add_AT_dataref(
5724d9fdb4Robert Mustacchi    Dwarf_P_Debug dbg,
5734d9fdb4Robert Mustacchi    Dwarf_P_Die ownerdie,
5744d9fdb4Robert Mustacchi    Dwarf_Half attr,
5754d9fdb4Robert Mustacchi    Dwarf_Unsigned pc_value,
5764d9fdb4Robert Mustacchi    Dwarf_Unsigned sym_index,
5774d9fdb4Robert Mustacchi    Dwarf_Error * error)
5784d9fdb4Robert Mustacchi{
5794d9fdb4Robert Mustacchi    Dwarf_P_Attribute a = 0;
5804d9fdb4Robert Mustacchi    int res = 0;
5814d9fdb4Robert Mustacchi
5824d9fdb4Robert Mustacchi    /* TODO: Add checking here */
5834d9fdb4Robert Mustacchi    res = local_add_AT_address_a(dbg, ownerdie, attr,
5844d9fdb4Robert Mustacchi        dbg->de_ar_data_attribute_form,
5854d9fdb4Robert Mustacchi        pc_value,
5864d9fdb4Robert Mustacchi        sym_index,
5874d9fdb4Robert Mustacchi        &a,
5884d9fdb4Robert Mustacchi        error);
5894d9fdb4Robert Mustacchi    if (res != DW_DLV_OK) {
5904d9fdb4Robert Mustacchi        return((Dwarf_P_Attribute)DW_DLV_BADADDR);
5914d9fdb4Robert Mustacchi    }
5924d9fdb4Robert Mustacchi    return a;
5934d9fdb4Robert Mustacchi}
59407dc194Richard Lowe
5954d9fdb4Robert MustacchiDwarf_P_Attribute
59607dc194Richard Lowedwarf_add_AT_block(
59707dc194Richard Lowe    Dwarf_P_Debug       dbg,
59807dc194Richard Lowe    Dwarf_P_Die         ownerdie,
59907dc194Richard Lowe    Dwarf_Half          attr,
60007dc194Richard Lowe    Dwarf_Small         *block_data,
60107dc194Richard Lowe    Dwarf_Unsigned      block_size,
6024d9fdb4Robert Mustacchi    Dwarf_Error         *error)
6034d9fdb4Robert Mustacchi{
6044d9fdb4Robert Mustacchi    int res = 0;
6054d9fdb4Robert Mustacchi    Dwarf_P_Attribute   new_attr = 0;
6064d9fdb4Robert Mustacchi
6074d9fdb4Robert Mustacchi    res = dwarf_add_AT_block_a(dbg,ownerdie,attr,
6084d9fdb4Robert Mustacchi        block_data,block_size,&new_attr,error);
6094d9fdb4Robert Mustacchi    if (res != DW_DLV_OK) {
6104d9fdb4Robert Mustacchi        return((Dwarf_P_Attribute)DW_DLV_BADADDR);
6114d9fdb4Robert Mustacchi    }
6124d9fdb4Robert Mustacchi    return new_attr;
6134d9fdb4Robert Mustacchi}
6144d9fdb4Robert Mustacchiint
6154d9fdb4Robert Mustacchidwarf_add_AT_block_a(
6164d9fdb4Robert Mustacchi    Dwarf_P_Debug       dbg,
6174d9fdb4Robert Mustacchi    Dwarf_P_Die         ownerdie,
6184d9fdb4Robert Mustacchi    Dwarf_Half          attr,
6194d9fdb4Robert Mustacchi    Dwarf_Small         *block_data,
6204d9fdb4Robert Mustacchi    Dwarf_Unsigned      block_size,
6214d9fdb4Robert Mustacchi    Dwarf_P_Attribute*  attr_out,
6224d9fdb4Robert Mustacchi    Dwarf_Error         *error)
62307dc194Richard Lowe{
6244d9fdb4Robert Mustacchi    Dwarf_P_Attribute   new_attr = 0;
6254d9fdb4Robert Mustacchi    int result = 0;
62607dc194Richard Lowe    char encode_buffer[ENCODE_SPACE_NEEDED];
6274d9fdb4Robert Mustacchi    int len_size = 0;
6284d9fdb4Robert Mustacchi    char * attrdata = 0;
62907dc194Richard Lowe
63007dc194Richard Lowe    if (dbg == NULL) {
63107dc194Richard Lowe        _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
6324d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
63307dc194Richard Lowe    }
63407dc194Richard Lowe
63507dc194Richard Lowe    if (ownerdie == NULL) {
63607dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
6374d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
63807dc194Richard Lowe    }
63907dc194Richard Lowe
64007dc194Richard Lowe    /* I don't mess with block1, block2, block4, not worth the effort */
64107dc194Richard Lowe
64207dc194Richard Lowe    /* So, encode the length into LEB128 */
64307dc194Richard Lowe    result = _dwarf_pro_encode_leb128_nm(block_size, &len_size,
6444d9fdb4Robert Mustacchi        encode_buffer,sizeof(encode_buffer));
64507dc194Richard Lowe    if (result !=  DW_DLV_OK) {
64607dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
6474d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
64807dc194Richard Lowe    }
64907dc194Richard Lowe
65007dc194Richard Lowe    /* Allocate the new attribute */
65107dc194Richard Lowe    new_attr = (Dwarf_P_Attribute)
65207dc194Richard Lowe        _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
65307dc194Richard Lowe    if (new_attr == NULL) {
65407dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
6554d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
65607dc194Richard Lowe    }
65707dc194Richard Lowe
65807dc194Richard Lowe    /* Fill in the attribute */
65907dc194Richard Lowe    new_attr->ar_attribute = attr;
66007dc194Richard Lowe    new_attr->ar_attribute_form = DW_FORM_block;
66107dc194Richard Lowe    new_attr->ar_nbytes = len_size + block_size;
66207dc194Richard Lowe    new_attr->ar_next = 0;
66307dc194Richard Lowe
66407dc194Richard Lowe    new_attr->ar_data = attrdata = (char *)
66507dc194Richard Lowe        _dwarf_p_get_alloc(dbg, len_size + block_size);
66607dc194Richard Lowe    if (new_attr->ar_data == NULL) {
66707dc194Richard Lowe        /* free the block we got earlier */
66807dc194Richard Lowe        _dwarf_p_dealloc(dbg, (unsigned char *) new_attr);
66907dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
6704d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
67107dc194Richard Lowe    }
67249d3bc9Richard Lowe
67307dc194Richard Lowe    /* write length and data to attribute data buffer */
67407dc194Richard Lowe    memcpy(attrdata, encode_buffer, len_size);
67507dc194Richard Lowe    attrdata += len_size;
67607dc194Richard Lowe    memcpy(attrdata, block_data, block_size);
6774d9fdb4Robert Mustacchi
67849d3bc9Richard Lowe    /* add attribute to the die */
67949d3bc9Richard Lowe    _dwarf_pro_add_at_to_die(ownerdie, new_attr);
6804d9fdb4Robert Mustacchi    *attr_out = new_attr;
6814d9fdb4Robert Mustacchi    return DW_DLV_OK;
68249d3bc9Richard Lowe}
68349d3bc9Richard Lowe
68449d3bc9Richard Lowe
68549d3bc9Richard Lowe/*
68649d3bc9Richard Lowe    This function adds attributes whose value
6874d9fdb4Robert Mustacchi    is an unsigned constant.  It determines the
6884d9fdb4Robert Mustacchi    size of the value field from the value of
68949d3bc9Richard Lowe    the constant.
69049d3bc9Richard Lowe*/
69149d3bc9Richard LoweDwarf_P_Attribute
69249d3bc9Richard Lowedwarf_add_AT_unsigned_const(Dwarf_P_Debug dbg,
6934d9fdb4Robert Mustacchi   Dwarf_P_Die ownerdie,
6944d9fdb4Robert Mustacchi   Dwarf_Half attr,
6954d9fdb4Robert Mustacchi   Dwarf_Unsigned value, Dwarf_Error * error)
69649d3bc9Richard Lowe{
6974d9fdb4Robert Mustacchi    Dwarf_P_Attribute a = 0;
6984d9fdb4Robert Mustacchi    int res = 0;
6994d9fdb4Robert Mustacchi
7004d9fdb4Robert Mustacchi    res = dwarf_add_AT_unsigned_const_a(dbg,
7014d9fdb4Robert Mustacchi        ownerdie,attr,value,
7024d9fdb4Robert Mustacchi        &a,error);
7034d9fdb4Robert Mustacchi    if (res != DW_DLV_OK) {
7044d9fdb4Robert Mustacchi        return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
7054d9fdb4Robert Mustacchi    }
7064d9fdb4Robert Mustacchi    return a;
7074d9fdb4Robert Mustacchi}
7084d9fdb4Robert Mustacchi
7094d9fdb4Robert Mustacchi
7104d9fdb4Robert Mustacchiint
7114d9fdb4Robert Mustacchidwarf_add_AT_unsigned_const_a(Dwarf_P_Debug dbg,
7124d9fdb4Robert Mustacchi   Dwarf_P_Die ownerdie,
7134d9fdb4Robert Mustacchi   Dwarf_Half attr,
7144d9fdb4Robert Mustacchi   Dwarf_Unsigned value,
7154d9fdb4Robert Mustacchi   Dwarf_P_Attribute *attr_out,
7164d9fdb4Robert Mustacchi   Dwarf_Error * error)
7174d9fdb4Robert Mustacchi{
7184d9fdb4Robert Mustacchi    Dwarf_P_Attribute new_attr = 0;
7194d9fdb4Robert Mustacchi    Dwarf_Half attr_form = 0;
7204d9fdb4Robert Mustacchi    Dwarf_Small size = 0;
72149d3bc9Richard Lowe
72249d3bc9Richard Lowe    if (dbg == NULL) {
72307dc194Richard Lowe        _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
7244d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
72549d3bc9Richard Lowe    }
72649d3bc9Richard Lowe
72749d3bc9Richard Lowe    if (ownerdie == NULL) {
72807dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
7294d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
73049d3bc9Richard Lowe    }
73149d3bc9Richard Lowe
73249d3bc9Richard Lowe    switch (attr) {
73349d3bc9Richard Lowe    case DW_AT_ordering:
73449d3bc9Richard Lowe    case DW_AT_byte_size:
73549d3bc9Richard Lowe    case DW_AT_bit_offset:
73649d3bc9Richard Lowe    case DW_AT_bit_size:
73749d3bc9Richard Lowe    case DW_AT_inline:
73849d3bc9Richard Lowe    case DW_AT_language:
73949d3bc9Richard Lowe    case DW_AT_visibility:
74049d3bc9Richard Lowe    case DW_AT_virtuality:
74149d3bc9Richard Lowe    case DW_AT_accessibility:
74249d3bc9Richard Lowe    case DW_AT_address_class:
74349d3bc9Richard Lowe    case DW_AT_calling_convention:
74449d3bc9Richard Lowe    case DW_AT_encoding:
74549d3bc9Richard Lowe    case DW_AT_identifier_case:
74649d3bc9Richard Lowe    case DW_AT_MIPS_loop_unroll_factor:
74749d3bc9Richard Lowe    case DW_AT_MIPS_software_pipeline_depth:
74807dc194Richard Lowe        break;
74949d3bc9Richard Lowe
75049d3bc9Richard Lowe    case DW_AT_decl_column:
75149d3bc9Richard Lowe    case DW_AT_decl_file:
75249d3bc9Richard Lowe    case DW_AT_decl_line:
75349d3bc9Richard Lowe    case DW_AT_const_value:
75449d3bc9Richard Lowe    case DW_AT_start_scope:
7554d9fdb4Robert Mustacchi    case DW_AT_stride_size: /* DW_AT_bit_stride  is DWARF3 name */
75649d3bc9Richard Lowe    case DW_AT_count:
7574d9fdb4Robert Mustacchi    case DW_AT_high_pc:     /* DWARF5: allowing const udata high_pc */
75807dc194Richard Lowe    case DW_AT_associated:
75907dc194Richard Lowe    case DW_AT_allocated:
76007dc194Richard Lowe    case DW_AT_upper_bound:
76107dc194Richard Lowe    case DW_AT_lower_bound:
76207dc194Richard Lowe    case DW_AT_call_file:
76307dc194Richard Lowe    case DW_AT_call_line:
7644d9fdb4Robert Mustacchi    case DW_AT_data_member_location:
7654d9fdb4Robert Mustacchi    case DW_AT_trampoline:
76607dc194Richard Lowe        break;
76707dc194Richard Lowe
7684d9fdb4Robert Mustacchi    default:
7694d9fdb4Robert Mustacchi        if (attr < DW_AT_lo_user || attr > DW_AT_hi_user ) {
7704d9fdb4Robert Mustacchi            _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
7714d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
77207dc194Richard Lowe        }
7734d9fdb4Robert Mustacchi        break;
7744d9fdb4Robert Mustacchi    }
77549d3bc9Richard Lowe
7764d9fdb4Robert Mustacchi    /* Compute the number of bytes needed to hold constant. */
77749d3bc9Richard Lowe    if (value <= UCHAR_MAX) {
77807dc194Richard Lowe        attr_form = DW_FORM_data1;
77907dc194Richard Lowe        size = 1;
78049d3bc9Richard Lowe    } else if (value <= USHRT_MAX) {
78107dc194Richard Lowe        attr_form = DW_FORM_data2;
78207dc194Richard Lowe        size = 2;
78349d3bc9Richard Lowe    } else if (value <= UINT_MAX) {
78407dc194Richard Lowe        attr_form = DW_FORM_data4;
78507dc194Richard Lowe        size = 4;
78649d3bc9Richard Lowe    } else {
78707dc194Richard Lowe        attr_form = DW_FORM_data8;
78807dc194Richard Lowe        size = 8;
78949d3bc9Richard Lowe    }
79049d3bc9Richard Lowe
79149d3bc9Richard Lowe    new_attr = (Dwarf_P_Attribute)
79207dc194Richard Lowe        _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
79349d3bc9Richard Lowe    if (new_attr == NULL) {
79407dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
7954d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
79649d3bc9Richard Lowe    }
79749d3bc9Richard Lowe
79849d3bc9Richard Lowe    new_attr->ar_attribute = attr;
79949d3bc9Richard Lowe    new_attr->ar_attribute_form = attr_form;
80049d3bc9Richard Lowe    new_attr->ar_rel_type = R_MIPS_NONE;
80107dc194Richard Lowe    new_attr->ar_reloc_len = 0; /* irrelevant: unused with R_MIPS_NONE */
80249d3bc9Richard Lowe    new_attr->ar_nbytes = size;
80349d3bc9Richard Lowe    new_attr->ar_next = 0;
80449d3bc9Richard Lowe
80549d3bc9Richard Lowe    new_attr->ar_data = (char *)
80607dc194Richard Lowe        _dwarf_p_get_alloc(dbg, size);
80749d3bc9Richard Lowe    if (new_attr->ar_data == NULL) {
80807dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
8094d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
81049d3bc9Richard Lowe    }
81149d3bc9Richard Lowe    WRITE_UNALIGNED(dbg, new_attr->ar_data,
8124d9fdb4Robert Mustacchi        (const void *) &value, sizeof(value), size);
81349d3bc9Richard Lowe
81449d3bc9Richard Lowe    /* add attribute to the die */
81549d3bc9Richard Lowe    _dwarf_pro_add_at_to_die(ownerdie, new_attr);
8164d9fdb4Robert Mustacchi    *attr_out = new_attr;
8174d9fdb4Robert Mustacchi    return DW_DLV_OK;
81849d3bc9Richard Lowe}
81949d3bc9Richard Lowe
82049d3bc9Richard Lowe
8214d9fdb4Robert Mustacchi/*  This function adds attributes whose value
8224d9fdb4Robert Mustacchi    is an signed constant.  It determines the
8234d9fdb4Robert Mustacchi    size of the value field from the value of
8244d9fdb4Robert Mustacchi    the constant.  */
82549d3bc9Richard LoweDwarf_P_Attribute
82649d3bc9Richard Lowedwarf_add_AT_signed_const(Dwarf_P_Debug dbg,
8274d9fdb4Robert Mustacchi    Dwarf_P_Die ownerdie,
8284d9fdb4Robert Mustacchi    Dwarf_Half attr,
8294d9fdb4Robert Mustacchi    Dwarf_Signed value,
8304d9fdb4Robert Mustacchi    Dwarf_Error * error)
83149d3bc9Richard Lowe{
8324d9fdb4Robert Mustacchi    Dwarf_P_Attribute a = 0;
8334d9fdb4Robert Mustacchi    int res = 0;
8344d9fdb4Robert Mustacchi
8354d9fdb4Robert Mustacchi    res = dwarf_add_AT_signed_const_a(dbg,
8364d9fdb4Robert Mustacchi        ownerdie,attr,value,&a,error);
8374d9fdb4Robert Mustacchi    if(res != DW_DLV_OK) {
8384d9fdb4Robert Mustacchi        return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
8394d9fdb4Robert Mustacchi    }
8404d9fdb4Robert Mustacchi    return a;
8414d9fdb4Robert Mustacchi}
8424d9fdb4Robert Mustacchi
8434d9fdb4Robert Mustacchiint
8444d9fdb4Robert Mustacchidwarf_add_AT_signed_const_a(Dwarf_P_Debug dbg,
8454d9fdb4Robert Mustacchi    Dwarf_P_Die ownerdie,
8464d9fdb4Robert Mustacchi    Dwarf_Half attr,
8474d9fdb4Robert Mustacchi    Dwarf_Signed value,
8484d9fdb4Robert Mustacchi    Dwarf_P_Attribute *attr_out,
8494d9fdb4Robert Mustacchi    Dwarf_Error * error)
8504d9fdb4Robert Mustacchi{
8514d9fdb4Robert Mustacchi    Dwarf_P_Attribute new_attr = 0;
8524d9fdb4Robert Mustacchi    Dwarf_Half attr_form = 0;
8534d9fdb4Robert Mustacchi    Dwarf_Small size = 0;
85449d3bc9Richard Lowe
85549d3bc9Richard Lowe    if (dbg == NULL) {
85607dc194Richard Lowe        _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
8574d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
85849d3bc9Richard Lowe    }
85949d3bc9Richard Lowe
86049d3bc9Richard Lowe    if (ownerdie == NULL) {
86107dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
8624d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
86349d3bc9Richard Lowe    }
86449d3bc9Richard Lowe
86549d3bc9Richard Lowe    switch (attr) {
86649d3bc9Richard Lowe    case DW_AT_lower_bound:
86707dc194Richard Lowe    case DW_AT_upper_bound:
86807dc194Richard Lowe    case DW_AT_const_value:
86907dc194Richard Lowe    case DW_AT_bit_offset:
87007dc194Richard Lowe    case DW_AT_bit_size:
87107dc194Richard Lowe    case DW_AT_byte_size:
87207dc194Richard Lowe    case DW_AT_count:
87307dc194Richard Lowe    case DW_AT_byte_stride:
87407dc194Richard Lowe    case DW_AT_bit_stride:
87507dc194Richard Lowe    case DW_AT_allocated:
87607dc194Richard Lowe    case DW_AT_associated:
87707dc194Richard Lowe        break;
87807dc194Richard Lowe
8794d9fdb4Robert Mustacchi    default:
8804d9fdb4Robert Mustacchi        if (attr < DW_AT_lo_user || attr > DW_AT_hi_user ) {
8814d9fdb4Robert Mustacchi            _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
8824d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
88307dc194Richard Lowe        }
88407dc194Richard Lowe        break;
88549d3bc9Richard Lowe    }
88649d3bc9Richard Lowe
8874d9fdb4Robert Mustacchi    /* Compute the number of bytes needed to hold constant. */
88849d3bc9Richard Lowe    if (value >= SCHAR_MIN && value <= SCHAR_MAX) {
88907dc194Richard Lowe        attr_form = DW_FORM_data1;
89007dc194Richard Lowe        size = 1;
89149d3bc9Richard Lowe    } else if (value >= SHRT_MIN && value <= SHRT_MAX) {
89207dc194Richard Lowe        attr_form = DW_FORM_data2;
89307dc194Richard Lowe        size = 2;
89449d3bc9Richard Lowe    } else if (value >= INT_MIN && value <= INT_MAX) {
89507dc194Richard Lowe        attr_form = DW_FORM_data4;
89607dc194Richard Lowe        size = 4;
89749d3bc9Richard Lowe    } else {
89807dc194Richard Lowe        attr_form = DW_FORM_data8;
89907dc194Richard Lowe        size = 8;
90049d3bc9Richard Lowe    }
90149d3bc9Richard Lowe
90249d3bc9Richard Lowe    new_attr = (Dwarf_P_Attribute)
90307dc194Richard Lowe        _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
90449d3bc9Richard Lowe    if (new_attr == NULL) {
90507dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
9064d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
90749d3bc9Richard Lowe    }
90849d3bc9Richard Lowe
90949d3bc9Richard Lowe    new_attr->ar_attribute = attr;
91049d3bc9Richard Lowe    new_attr->ar_attribute_form = attr_form;
91149d3bc9Richard Lowe    new_attr->ar_rel_type = R_MIPS_NONE;
91207dc194Richard Lowe    new_attr->ar_reloc_len = 0; /* irrelevant: unused with R_MIPS_NONE */
91349d3bc9Richard Lowe    new_attr->ar_nbytes = size;
91449d3bc9Richard Lowe    new_attr->ar_next = 0;
91549d3bc9Richard Lowe
91649d3bc9Richard Lowe    new_attr->ar_data = (char *)
91707dc194Richard Lowe        _dwarf_p_get_alloc(dbg, size);
91849d3bc9Richard Lowe    if (new_attr->ar_data == NULL) {
91907dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
9204d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
92149d3bc9Richard Lowe    }
92249d3bc9Richard Lowe    WRITE_UNALIGNED(dbg, new_attr->ar_data,
9234d9fdb4Robert Mustacchi        (const void *) &value, sizeof(value), size);
92449d3bc9Richard Lowe
92549d3bc9Richard Lowe    /* add attribute to the die */
92649d3bc9Richard Lowe    _dwarf_pro_add_at_to_die(ownerdie, new_attr);
9274d9fdb4Robert Mustacchi    *attr_out = new_attr;
9284d9fdb4Robert Mustacchi    return DW_DLV_OK;
92949d3bc9Richard Lowe}
93049d3bc9Richard Lowe
93149d3bc9Richard Lowe
9324d9fdb4Robert Mustacchi/*  This function adds attributes whose value
9334d9fdb4Robert Mustacchi    is a location expression.  */
93449d3bc9Richard LoweDwarf_P_Attribute
93549d3bc9Richard Lowedwarf_add_AT_location_expr(Dwarf_P_Debug dbg,
9364d9fdb4Robert Mustacchi    Dwarf_P_Die ownerdie,
9374d9fdb4Robert Mustacchi    Dwarf_Half attr,
9384d9fdb4Robert Mustacchi    Dwarf_P_Expr loc_expr, Dwarf_Error * error)
9394d9fdb4Robert Mustacchi{
9404d9fdb4Robert Mustacchi    int res = 0;
9414d9fdb4Robert Mustacchi    Dwarf_P_Attribute a = 0;
9424d9fdb4Robert Mustacchi
9434d9fdb4Robert Mustacchi    res = dwarf_add_AT_location_expr_a(dbg,ownerdie,attr,
9444d9fdb4Robert Mustacchi        loc_expr,&a,error);
9454d9fdb4Robert Mustacchi    if (res != DW_DLV_OK) {
9464d9fdb4Robert Mustacchi        return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
9474d9fdb4Robert Mustacchi    }
9484d9fdb4Robert Mustacchi    return a;
9494d9fdb4Robert Mustacchi}
9504d9fdb4Robert Mustacchi
9514d9fdb4Robert Mustacchi/* Preferred interface as of December 2018 */
9524d9fdb4Robert Mustacchiint
9534d9fdb4Robert Mustacchidwarf_add_AT_location_expr_a(Dwarf_P_Debug dbg,
9544d9fdb4Robert Mustacchi    Dwarf_P_Die ownerdie,
9554d9fdb4Robert Mustacchi    Dwarf_Half attr,
9564d9fdb4Robert Mustacchi    Dwarf_P_Expr loc_expr,
9574d9fdb4Robert Mustacchi    Dwarf_P_Attribute *attr_out,
9584d9fdb4Robert Mustacchi    Dwarf_Error * error)
95949d3bc9Richard Lowe{
96049d3bc9Richard Lowe    char encode_buffer[ENCODE_SPACE_NEEDED];
9614d9fdb4Robert Mustacchi    int res = 0;
9624d9fdb4Robert Mustacchi    Dwarf_P_Attribute new_attr = 0;
9634d9fdb4Robert Mustacchi    Dwarf_Half attr_form = 0;
96407dc194Richard Lowe    char *len_str = 0;
9654d9fdb4Robert Mustacchi    int len_size = 0;
9664d9fdb4Robert Mustacchi    Dwarf_Unsigned block_size = 0;
9674d9fdb4Robert Mustacchi    char *block_dest_ptr = 0;
96849d3bc9Richard Lowe    int do_len_as_int = 0;
96949d3bc9Richard Lowe
97049d3bc9Richard Lowe    if (dbg == NULL) {
97107dc194Richard Lowe        _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
9724d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
97349d3bc9Richard Lowe    }
97449d3bc9Richard Lowe
97549d3bc9Richard Lowe    if (ownerdie == NULL) {
97607dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
9774d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
97849d3bc9Richard Lowe    }
97949d3bc9Richard Lowe
98049d3bc9Richard Lowe    if (loc_expr == NULL) {
98107dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_EXPR_NULL);
9824d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
98349d3bc9Richard Lowe    }
98449d3bc9Richard Lowe
98549d3bc9Richard Lowe    if (loc_expr->ex_dbg != dbg) {
98607dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_LOC_EXPR_BAD);
9874d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
98849d3bc9Richard Lowe    }
98949d3bc9Richard Lowe    block_size = loc_expr->ex_next_byte_offset;
99049d3bc9Richard Lowe
99149d3bc9Richard Lowe    switch (attr) {
99249d3bc9Richard Lowe    case DW_AT_location:
99349d3bc9Richard Lowe    case DW_AT_string_length:
99449d3bc9Richard Lowe    case DW_AT_const_value:
99549d3bc9Richard Lowe    case DW_AT_use_location:
99649d3bc9Richard Lowe    case DW_AT_return_addr:
99749d3bc9Richard Lowe    case DW_AT_data_member_location:
99849d3bc9Richard Lowe    case DW_AT_frame_base:
99949d3bc9Richard Lowe    case DW_AT_static_link:
100049d3bc9Richard Lowe    case DW_AT_vtable_elem_location:
100107dc194Richard Lowe    case DW_AT_lower_bound:
100207dc194Richard Lowe    case DW_AT_upper_bound:
100307dc194Richard Lowe    case DW_AT_count:
100407dc194Richard Lowe    case DW_AT_associated:
100507dc194Richard Lowe    case DW_AT_allocated:
100607dc194Richard Lowe    case DW_AT_data_location:
100707dc194Richard Lowe    case DW_AT_byte_stride:
100807dc194Richard Lowe    case DW_AT_bit_stride:
100907dc194Richard Lowe    case DW_AT_byte_size:
101007dc194Richard Lowe    case DW_AT_bit_size:
101107dc194Richard Lowe    break;
101207dc194Richard Lowe
101307dc194Richard Lowe    default:
10144d9fdb4Robert Mustacchi        if (attr < DW_AT_lo_user || attr > DW_AT_hi_user ) {
101507dc194Richard Lowe            _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
10164d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
101707dc194Richard Lowe        }
101807dc194Richard Lowe    break;
101949d3bc9Richard Lowe    }
102049d3bc9Richard Lowe
10214d9fdb4Robert Mustacchi    /*  Compute the number of bytes needed to hold constant.
10224d9fdb4Robert Mustacchi        This is a bit fake in that the size will never
10234d9fdb4Robert Mustacchi        be particularly large and always < UINT_MAX. */
102449d3bc9Richard Lowe    if (block_size <= UCHAR_MAX) {
102507dc194Richard Lowe        attr_form = DW_FORM_block1;
102607dc194Richard Lowe        len_size = 1;
102707dc194Richard Lowe        do_len_as_int = 1;
102849d3bc9Richard Lowe    } else if (block_size <= USHRT_MAX) {
102907dc194Richard Lowe        attr_form = DW_FORM_block2;
103007dc194Richard Lowe        len_size = 2;
103107dc194Richard Lowe        do_len_as_int = 1;
103249d3bc9Richard Lowe    } else if (block_size <= UINT_MAX) {
103307dc194Richard Lowe        attr_form = DW_FORM_block4;
103407dc194Richard Lowe        len_size = 4;
103507dc194Richard Lowe        do_len_as_int = 1;
103649d3bc9Richard Lowe    } else {
103707dc194Richard Lowe        attr_form = DW_FORM_block;
103807dc194Richard Lowe        res = _dwarf_pro_encode_leb128_nm(block_size, &len_size,
10394d9fdb4Robert Mustacchi            encode_buffer,
10404d9fdb4Robert Mustacchi            sizeof(encode_buffer));
104107dc194Richard Lowe        if (res != DW_DLV_OK) {
104207dc194Richard Lowe            _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
10434d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
104407dc194Richard Lowe        }
104507dc194Richard Lowe        len_str = (char *) encode_buffer;
104649d3bc9Richard Lowe    }
104749d3bc9Richard Lowe
104849d3bc9Richard Lowe    new_attr = (Dwarf_P_Attribute)
104907dc194Richard Lowe        _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
105049d3bc9Richard Lowe    if (new_attr == NULL) {
105107dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
10524d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
105349d3bc9Richard Lowe    }
105449d3bc9Richard Lowe
105549d3bc9Richard Lowe    new_attr->ar_attribute = attr;
105649d3bc9Richard Lowe    new_attr->ar_attribute_form = attr_form;
105749d3bc9Richard Lowe    new_attr->ar_reloc_len = dbg->de_pointer_size;
105849d3bc9Richard Lowe    if (loc_expr->ex_reloc_sym_index != NO_ELF_SYM_INDEX) {
105907dc194Richard Lowe        new_attr->ar_rel_type = dbg->de_ptr_reloc;
106049d3bc9Richard Lowe    } else {
106107dc194Richard Lowe        new_attr->ar_rel_type = R_MIPS_NONE;
106249d3bc9Richard Lowe    }
106349d3bc9Richard Lowe    new_attr->ar_rel_symidx = loc_expr->ex_reloc_sym_index;
106449d3bc9Richard Lowe    new_attr->ar_rel_offset =
10654d9fdb4Robert Mustacchi        loc_expr->ex_reloc_offset + len_size;
106649d3bc9Richard Lowe
106749d3bc9Richard Lowe    new_attr->ar_nbytes = block_size + len_size;
106849d3bc9Richard Lowe
106949d3bc9Richard Lowe    new_attr->ar_next = 0;
107049d3bc9Richard Lowe    new_attr->ar_data = block_dest_ptr =
107107dc194Richard Lowe        (char *) _dwarf_p_get_alloc(dbg, block_size + len_size);
107249d3bc9Richard Lowe    if (new_attr->ar_data == NULL) {
107307dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
10744d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
107549d3bc9Richard Lowe    }
107649d3bc9Richard Lowe
107749d3bc9Richard Lowe    if (do_len_as_int) {
107807dc194Richard Lowe        WRITE_UNALIGNED(dbg, block_dest_ptr, (const void *) &block_size,
10794d9fdb4Robert Mustacchi            sizeof(block_size), len_size);
108049d3bc9Richard Lowe    } else {
108107dc194Richard Lowe        /* Is uleb number form, DW_FORM_block. See above. */
108207dc194Richard Lowe        memcpy(block_dest_ptr, len_str, len_size);
108349d3bc9Richard Lowe    }
108449d3bc9Richard Lowe    block_dest_ptr += len_size;
10854d9fdb4Robert Mustacchi    if (block_size > sizeof(loc_expr->ex_byte_stream)) {
10864d9fdb4Robert Mustacchi        /* ex_byte_stream has a fixed max value. */
10874d9fdb4Robert Mustacchi        _dwarf_p_error(dbg, error, DW_DLE_EXPR_LENGTH_BAD);
10884d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
10894d9fdb4Robert Mustacchi    }
109049d3bc9Richard Lowe    memcpy(block_dest_ptr, &(loc_expr->ex_byte_stream[0]), block_size);
109149d3bc9Richard Lowe
109249d3bc9Richard Lowe    /* add attribute to the die */
109349d3bc9Richard Lowe    _dwarf_pro_add_at_to_die(ownerdie, new_attr);
10944d9fdb4Robert Mustacchi    *attr_out = new_attr;
10954d9fdb4Robert Mustacchi    return DW_DLV_OK;
109649d3bc9Richard Lowe}
109749d3bc9Richard Lowe
109849d3bc9Richard Lowe
10994d9fdb4Robert Mustacchi/*  This function adds attributes of reference class.
11004d9fdb4Robert Mustacchi    The references here are local CU references,
110149d3bc9Richard Lowe    not DW_FORM_ref_addr.
110249d3bc9Richard Lowe    The offset field is 4 bytes for 32-bit objects,
110349d3bc9Richard Lowe    and 8-bytes for 64-bit objects.  Otherdie is the
110449d3bc9Richard Lowe    that is referenced by ownerdie.
110549d3bc9Richard Lowe
110649d3bc9Richard Lowe    For reference attributes, the ar_data and ar_nbytes
110749d3bc9Richard Lowe    are not needed.  Instead, the ar_ref_die points to
110849d3bc9Richard Lowe    the other die, and its di_offset value is used as
11094d9fdb4Robert Mustacchi    the reference value.  */
11104d9fdb4Robert Mustacchi
11114d9fdb4Robert Mustacchistatic int
11124d9fdb4Robert Mustacchi_dwarf_add_AT_reference_internal_a(Dwarf_P_Debug dbg,
11134d9fdb4Robert Mustacchi    Dwarf_P_Die ownerdie,
11144d9fdb4Robert Mustacchi    Dwarf_Half attr,
11154d9fdb4Robert Mustacchi    Dwarf_P_Die otherdie,
11164d9fdb4Robert Mustacchi    int check_otherdie,
11174d9fdb4Robert Mustacchi    Dwarf_P_Attribute *attr_out,
11184d9fdb4Robert Mustacchi    Dwarf_Error * error)
111949d3bc9Richard Lowe{
11204d9fdb4Robert Mustacchi    Dwarf_P_Attribute new_attr = 0;
112149d3bc9Richard Lowe
112249d3bc9Richard Lowe    if (dbg == NULL) {
112307dc194Richard Lowe        _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
11244d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
112549d3bc9Richard Lowe    }
112649d3bc9Richard Lowe
112749d3bc9Richard Lowe    if (ownerdie == NULL) {
112807dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
11294d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
113049d3bc9Richard Lowe    }
113149d3bc9Richard Lowe
11324d9fdb4Robert Mustacchi    if (check_otherdie && (otherdie == NULL)) {
113307dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
11344d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
113549d3bc9Richard Lowe    }
113649d3bc9Richard Lowe
113749d3bc9Richard Lowe    switch (attr) {
11384d9fdb4Robert Mustacchi    case DW_AT_count:
11394d9fdb4Robert Mustacchi    case DW_AT_sibling:
11404d9fdb4Robert Mustacchi    case DW_AT_byte_size:
11414d9fdb4Robert Mustacchi    case DW_AT_bit_offset:
11424d9fdb4Robert Mustacchi    case DW_AT_bit_size:
114349d3bc9Richard Lowe    case DW_AT_discr:
114449d3bc9Richard Lowe    case DW_AT_import:
11454d9fdb4Robert Mustacchi    case DW_AT_common_reference:
114649d3bc9Richard Lowe    case DW_AT_containing_type:
114749d3bc9Richard Lowe    case DW_AT_default_value:
11484d9fdb4Robert Mustacchi    case DW_AT_lower_bound:
11494d9fdb4Robert Mustacchi    case DW_AT_bit_stride: /* Early name is DW_AT_stride_size */
11504d9fdb4Robert Mustacchi    case DW_AT_upper_bound:
11514d9fdb4Robert Mustacchi    case DW_AT_abstract_origin:
11524d9fdb4Robert Mustacchi    case DW_AT_base_types:
115349d3bc9Richard Lowe    case DW_AT_friend:
11544d9fdb4Robert Mustacchi    case DW_AT_namelist_item:
115549d3bc9Richard Lowe    case DW_AT_priority:
11564d9fdb4Robert Mustacchi    case DW_AT_specification:
115749d3bc9Richard Lowe    case DW_AT_type:
115807dc194Richard Lowe    case DW_AT_allocated:
11594d9fdb4Robert Mustacchi    case DW_AT_associated:
116007dc194Richard Lowe    case DW_AT_byte_stride:
11614d9fdb4Robert Mustacchi    case DW_AT_extension:
11624d9fdb4Robert Mustacchi    case DW_AT_trampoline:
11634d9fdb4Robert Mustacchi    case DW_AT_small:
11644d9fdb4Robert Mustacchi    case DW_AT_object_pointer:
11654d9fdb4Robert Mustacchi    case DW_AT_signature:
116607dc194Richard Lowe        break;
116707dc194Richard Lowe
116807dc194Richard Lowe    default:
11694d9fdb4Robert Mustacchi        if (attr < DW_AT_lo_user || attr > DW_AT_hi_user ) {
117007dc194Richard Lowe            _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
11714d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
117207dc194Richard Lowe        }
117307dc194Richard Lowe        break;
117449d3bc9Richard Lowe    }
117549d3bc9Richard Lowe
117649d3bc9Richard Lowe    new_attr = (Dwarf_P_Attribute)
117707dc194Richard Lowe        _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
117849d3bc9Richard Lowe    if (new_attr == NULL) {
117907dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
11804d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
118149d3bc9Richard Lowe    }
118249d3bc9Richard Lowe
118349d3bc9Richard Lowe    new_attr->ar_attribute = attr;
118449d3bc9Richard Lowe    new_attr->ar_attribute_form = dbg->de_ar_ref_attr_form;
11854d9fdb4Robert Mustacchi    new_attr->ar_nbytes = dbg->de_dwarf_offset_size;
11864d9fdb4Robert Mustacchi    new_attr->ar_reloc_len = dbg->de_dwarf_offset_size;
118749d3bc9Richard Lowe    new_attr->ar_ref_die = otherdie;
118849d3bc9Richard Lowe    new_attr->ar_rel_type = R_MIPS_NONE;
118949d3bc9Richard Lowe    new_attr->ar_next = 0;
119049d3bc9Richard Lowe
11914d9fdb4Robert Mustacchi    /* Add attribute to the die */
119249d3bc9Richard Lowe    _dwarf_pro_add_at_to_die(ownerdie, new_attr);
11934d9fdb4Robert Mustacchi    *attr_out = new_attr;
11944d9fdb4Robert Mustacchi    return DW_DLV_OK;
119549d3bc9Richard Lowe}
119649d3bc9Richard Lowe
11974d9fdb4Robert Mustacchi/*  Allowing the target die to be identified later.
11984d9fdb4Robert Mustacchi    */
11994d9fdb4Robert Mustacchiint
12004d9fdb4Robert Mustacchidwarf_add_AT_reference_c(Dwarf_P_Debug dbg,
12014d9fdb4Robert Mustacchi    Dwarf_P_Die ownerdie,
12024d9fdb4Robert Mustacchi    Dwarf_Half attr,
12034d9fdb4Robert Mustacchi    Dwarf_P_Die otherdie,
12044d9fdb4Robert Mustacchi    Dwarf_P_Attribute *attr_out,
12054d9fdb4Robert Mustacchi    Dwarf_Error * error)
12064d9fdb4Robert Mustacchi{
12074d9fdb4Robert Mustacchi    int res = 0;
12084d9fdb4Robert Mustacchi
12094d9fdb4Robert Mustacchi    res = _dwarf_add_AT_reference_internal_a(dbg,
12104d9fdb4Robert Mustacchi        ownerdie,
12114d9fdb4Robert Mustacchi        attr,
12124d9fdb4Robert Mustacchi        otherdie,
12134d9fdb4Robert Mustacchi        /* check otherdie */ 0,
12144d9fdb4Robert Mustacchi        attr_out,
12154d9fdb4Robert Mustacchi        error);
12164d9fdb4Robert Mustacchi    return res;
12174d9fdb4Robert Mustacchi}
12184d9fdb4Robert Mustacchi
12194d9fdb4Robert Mustacchi
122049d3bc9Richard Lowe
122149d3bc9Richard LoweDwarf_P_Attribute
12224d9fdb4Robert Mustacchidwarf_add_AT_reference(Dwarf_P_Debug dbg,
12234d9fdb4Robert Mustacchi    Dwarf_P_Die ownerdie,
12244d9fdb4Robert Mustacchi    Dwarf_Half attr,
12254d9fdb4Robert Mustacchi    Dwarf_P_Die otherdie, Dwarf_Error * error)
122649d3bc9Richard Lowe{
12274d9fdb4Robert Mustacchi    Dwarf_P_Attribute a = 0;
12284d9fdb4Robert Mustacchi    int res = 0;
12294d9fdb4Robert Mustacchi
12304d9fdb4Robert Mustacchi    res = _dwarf_add_AT_reference_internal_a(dbg,
12314d9fdb4Robert Mustacchi        ownerdie,
12324d9fdb4Robert Mustacchi        attr,
12334d9fdb4Robert Mustacchi        otherdie,
12344d9fdb4Robert Mustacchi        /* check otherdie */ 1,
12354d9fdb4Robert Mustacchi        &a,
12364d9fdb4Robert Mustacchi        error);
12374d9fdb4Robert Mustacchi    if (res != DW_DLV_OK) {
12384d9fdb4Robert Mustacchi        return (Dwarf_P_Attribute)DW_DLV_BADADDR;
12394d9fdb4Robert Mustacchi    }
12404d9fdb4Robert Mustacchi    return a;
12414d9fdb4Robert Mustacchi}
12424d9fdb4Robert Mustacchi
12434d9fdb4Robert Mustacchi/*  Allowing the target die to be identified later.
12444d9fdb4Robert Mustacchi    */
12454d9fdb4Robert MustacchiDwarf_P_Attribute
12464d9fdb4Robert Mustacchidwarf_add_AT_reference_b(Dwarf_P_Debug dbg,
12474d9fdb4Robert Mustacchi    Dwarf_P_Die ownerdie,
12484d9fdb4Robert Mustacchi    Dwarf_Half attr,
12494d9fdb4Robert Mustacchi    Dwarf_P_Die otherdie,
12504d9fdb4Robert Mustacchi    Dwarf_Error * error)
12514d9fdb4Robert Mustacchi{
12524d9fdb4Robert Mustacchi    Dwarf_P_Attribute a = 0;
12534d9fdb4Robert Mustacchi    int res = 0;
12544d9fdb4Robert Mustacchi
12554d9fdb4Robert Mustacchi    res = _dwarf_add_AT_reference_internal_a(dbg,
12564d9fdb4Robert Mustacchi        ownerdie,
12574d9fdb4Robert Mustacchi        attr,
12584d9fdb4Robert Mustacchi        otherdie,
12594d9fdb4Robert Mustacchi        /* check otherdie */ 0,
12604d9fdb4Robert Mustacchi        &a,
12614d9fdb4Robert Mustacchi        error);
12624d9fdb4Robert Mustacchi    if (res != DW_DLV_OK) {
12634d9fdb4Robert Mustacchi        return (Dwarf_P_Attribute)DW_DLV_BADADDR;
12644d9fdb4Robert Mustacchi    }
12654d9fdb4Robert Mustacchi    return a;
12664d9fdb4Robert Mustacchi}
12674d9fdb4Robert Mustacchi
12684d9fdb4Robert Mustacchi
126949d3bc9Richard Lowe
12704d9fdb4Robert Mustacchi
12714d9fdb4Robert Mustacchiint
12724d9fdb4Robert Mustacchidwarf_fixup_AT_reference_die(Dwarf_P_Debug dbg,
12734d9fdb4Robert Mustacchi   Dwarf_Half attrnum,
12744d9fdb4Robert Mustacchi   Dwarf_P_Die sourcedie,
12754d9fdb4Robert Mustacchi   Dwarf_P_Die targetdie,
12764d9fdb4Robert Mustacchi   Dwarf_Error *error)
12774d9fdb4Robert Mustacchi{
12784d9fdb4Robert Mustacchi    Dwarf_P_Attribute a = 0;
12794d9fdb4Robert Mustacchi    Dwarf_P_Attribute cur = 0;
128049d3bc9Richard Lowe    if (dbg == NULL) {
128107dc194Richard Lowe        _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
12824d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
12834d9fdb4Robert Mustacchi    }
12844d9fdb4Robert Mustacchi    for(cur = sourcedie->di_attrs; cur; cur = cur->ar_next) {
12854d9fdb4Robert Mustacchi        if (attrnum == cur->ar_attribute) {
12864d9fdb4Robert Mustacchi            a = cur;
12874d9fdb4Robert Mustacchi            break;
12884d9fdb4Robert Mustacchi        }
12894d9fdb4Robert Mustacchi    }
12904d9fdb4Robert Mustacchi    if(!a) {
12914d9fdb4Robert Mustacchi        _dwarf_p_error(dbg, error, DW_DLE_AT_FIXUP_NULL);
12924d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
129349d3bc9Richard Lowe    }
12944d9fdb4Robert Mustacchi    if(a->ar_ref_die) {
12954d9fdb4Robert Mustacchi        _dwarf_p_error(dbg, error, DW_DLE_AT_FIXUP_DUP);
12964d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
12974d9fdb4Robert Mustacchi    }
12984d9fdb4Robert Mustacchi    a->ar_ref_die = targetdie;
12994d9fdb4Robert Mustacchi    return DW_DLV_OK;
13004d9fdb4Robert Mustacchi}
130149d3bc9Richard Lowe
13024d9fdb4Robert Mustacchi
13034d9fdb4Robert Mustacchi/* This function adds attributes of the flag class.  */
13044d9fdb4Robert MustacchiDwarf_P_Attribute
13054d9fdb4Robert Mustacchidwarf_add_AT_flag(Dwarf_P_Debug dbg,
13064d9fdb4Robert Mustacchi    Dwarf_P_Die ownerdie,
13074d9fdb4Robert Mustacchi    Dwarf_Half attr,
13084d9fdb4Robert Mustacchi    Dwarf_Small flag,
13094d9fdb4Robert Mustacchi    Dwarf_Error * error)
13104d9fdb4Robert Mustacchi{
13114d9fdb4Robert Mustacchi    Dwarf_P_Attribute a = 0;
13124d9fdb4Robert Mustacchi    int res = 0;
13134d9fdb4Robert Mustacchi
13144d9fdb4Robert Mustacchi    res = dwarf_add_AT_flag_a(dbg,ownerdie,attr,flag,
13154d9fdb4Robert Mustacchi        &a,error);
13164d9fdb4Robert Mustacchi    if (res != DW_DLV_OK) {
131707dc194Richard Lowe        return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
131849d3bc9Richard Lowe    }
13194d9fdb4Robert Mustacchi    return a;
13204d9fdb4Robert Mustacchi}
13214d9fdb4Robert Mustacchiint
13224d9fdb4Robert Mustacchidwarf_add_AT_flag_a(Dwarf_P_Debug dbg,
13234d9fdb4Robert Mustacchi    Dwarf_P_Die ownerdie,
13244d9fdb4Robert Mustacchi    Dwarf_Half attr,
13254d9fdb4Robert Mustacchi    Dwarf_Small flag,
13264d9fdb4Robert Mustacchi    Dwarf_P_Attribute * attr_out,
13274d9fdb4Robert Mustacchi    Dwarf_Error * error)
13284d9fdb4Robert Mustacchi{
13294d9fdb4Robert Mustacchi    Dwarf_P_Attribute new_attr = 0;
133049d3bc9Richard Lowe
13314d9fdb4Robert Mustacchi    if (dbg == NULL) {
13324d9fdb4Robert Mustacchi        _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
13334d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
13344d9fdb4Robert Mustacchi    }
13354d9fdb4Robert Mustacchi    if (ownerdie == NULL) {
13364d9fdb4Robert Mustacchi        _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
13374d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
133849d3bc9Richard Lowe    }
133949d3bc9Richard Lowe
134049d3bc9Richard Lowe    new_attr = (Dwarf_P_Attribute)
134107dc194Richard Lowe        _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
134249d3bc9Richard Lowe    if (new_attr == NULL) {
134307dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
13444d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
134549d3bc9Richard Lowe    }
134649d3bc9Richard Lowe
134749d3bc9Richard Lowe    new_attr->ar_attribute = attr;
134849d3bc9Richard Lowe    new_attr->ar_attribute_form = DW_FORM_flag;
134949d3bc9Richard Lowe    new_attr->ar_nbytes = 1;
135007dc194Richard Lowe    new_attr->ar_reloc_len = 0; /* not used */
135149d3bc9Richard Lowe    new_attr->ar_rel_type = R_MIPS_NONE;
135249d3bc9Richard Lowe    new_attr->ar_next = 0;
135349d3bc9Richard Lowe
135449d3bc9Richard Lowe    new_attr->ar_data = (char *)
135507dc194Richard Lowe        _dwarf_p_get_alloc(dbg, 1);
135649d3bc9Richard Lowe    if (new_attr->ar_data == NULL) {
135707dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
13584d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
135949d3bc9Richard Lowe    }
136049d3bc9Richard Lowe    memcpy(new_attr->ar_data, &flag, 1);
136149d3bc9Richard Lowe
13624d9fdb4Robert Mustacchi    /* Add attribute to the die */
136349d3bc9Richard Lowe    _dwarf_pro_add_at_to_die(ownerdie, new_attr);
13644d9fdb4Robert Mustacchi    *attr_out = new_attr;
13654d9fdb4Robert Mustacchi    return DW_DLV_OK;
136649d3bc9Richard Lowe}
136749d3bc9Richard Lowe
136849d3bc9Richard Lowe
13694d9fdb4Robert Mustacchi/*  This function adds values of attributes
13704d9fdb4Robert Mustacchi    belonging to the string class. */
137149d3bc9Richard LoweDwarf_P_Attribute
137249d3bc9Richard Lowedwarf_add_AT_string(Dwarf_P_Debug dbg,
13734d9fdb4Robert Mustacchi    Dwarf_P_Die ownerdie,
13744d9fdb4Robert Mustacchi    Dwarf_Half attr, char *string, Dwarf_Error * error)
137549d3bc9Richard Lowe{
13764d9fdb4Robert Mustacchi    Dwarf_P_Attribute a = 0;
13774d9fdb4Robert Mustacchi    int res = 0;
13784d9fdb4Robert Mustacchi
13794d9fdb4Robert Mustacchi    res = dwarf_add_AT_string_a(dbg,
13804d9fdb4Robert Mustacchi        ownerdie,attr,string,&a,error);
13814d9fdb4Robert Mustacchi    if (res != DW_DLV_OK) {
13824d9fdb4Robert Mustacchi        return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
13834d9fdb4Robert Mustacchi    }
13844d9fdb4Robert Mustacchi    return a;
13854d9fdb4Robert Mustacchi}
13864d9fdb4Robert Mustacchi
13874d9fdb4Robert Mustacchiint
13884d9fdb4Robert Mustacchidwarf_add_AT_string_a(Dwarf_P_Debug dbg,
13894d9fdb4Robert Mustacchi    Dwarf_P_Die ownerdie,
13904d9fdb4Robert Mustacchi    Dwarf_Half attr,
13914d9fdb4Robert Mustacchi    char *string,
13924d9fdb4Robert Mustacchi    Dwarf_P_Attribute *attr_out,
13934d9fdb4Robert Mustacchi    Dwarf_Error * error)
13944d9fdb4Robert Mustacchi{
13954d9fdb4Robert Mustacchi    Dwarf_P_Attribute new_attr = 0;
13964d9fdb4Robert Mustacchi    int res = 0;
139749d3bc9Richard Lowe
139849d3bc9Richard Lowe    if (dbg == NULL) {
139907dc194Richard Lowe        _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
14004d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
140149d3bc9Richard Lowe    }
140249d3bc9Richard Lowe
140349d3bc9Richard Lowe    if (ownerdie == NULL) {
140407dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
14054d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
140649d3bc9Richard Lowe    }
140749d3bc9Richard Lowe
140849d3bc9Richard Lowe    new_attr = (Dwarf_P_Attribute)
140907dc194Richard Lowe        _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
141049d3bc9Richard Lowe    if (new_attr == NULL) {
141107dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
14124d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
141349d3bc9Richard Lowe    }
141449d3bc9Richard Lowe
141549d3bc9Richard Lowe    switch (attr) {
14164d9fdb4Robert Mustacchi    /* See also: pro_section.c for same strings attribute list. */
141749d3bc9Richard Lowe    case DW_AT_comp_dir:
141849d3bc9Richard Lowe    case DW_AT_const_value:
14194d9fdb4Robert Mustacchi    case DW_AT_linkage_name:/* DWARF5, but ok for any version really.*/
14204d9fdb4Robert Mustacchi    case DW_AT_MIPS_abstract_name:
14214d9fdb4Robert Mustacchi    case DW_AT_MIPS_linkage_name:
14224d9fdb4Robert Mustacchi    case DW_AT_name:
142349d3bc9Richard Lowe    case DW_AT_producer:
142407dc194Richard Lowe        break;
142507dc194Richard Lowe
142607dc194Richard Lowe        default:
14274d9fdb4Robert Mustacchi            if (attr < DW_AT_lo_user || attr > DW_AT_hi_user ) {
142807dc194Richard Lowe            _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
14294d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
143007dc194Richard Lowe        }
143107dc194Richard Lowe            break;
143249d3bc9Richard Lowe    }
143349d3bc9Richard Lowe    new_attr->ar_attribute = attr;
14344d9fdb4Robert Mustacchi    res = _dwarf_pro_set_string_attr(new_attr,ownerdie->di_dbg,
14354d9fdb4Robert Mustacchi        string,error);
14364d9fdb4Robert Mustacchi    if (res != DW_DLV_OK) {
14374d9fdb4Robert Mustacchi        return res;
143849d3bc9Richard Lowe    }
143949d3bc9Richard Lowe
144049d3bc9Richard Lowe    /* add attribute to the die */
144149d3bc9Richard Lowe    _dwarf_pro_add_at_to_die(ownerdie, new_attr);
14424d9fdb4Robert Mustacchi    *attr_out = new_attr;
14434d9fdb4Robert Mustacchi    return DW_DLV_OK;
144449d3bc9Richard Lowe}
144549d3bc9Richard Lowe
144649d3bc9Richard LoweDwarf_P_Attribute
144749d3bc9Richard Lowedwarf_add_AT_const_value_string(Dwarf_P_Die ownerdie,
14484d9fdb4Robert Mustacchi    char *string_value, Dwarf_Error * error)
144949d3bc9Richard Lowe{
14504d9fdb4Robert Mustacchi    Dwarf_P_Attribute a = 0;
14514d9fdb4Robert Mustacchi    int res = 0;
14524d9fdb4Robert Mustacchi
14534d9fdb4Robert Mustacchi    res = dwarf_add_AT_const_value_string_a(ownerdie,
14544d9fdb4Robert Mustacchi        string_value,&a,error);
14554d9fdb4Robert Mustacchi    if (res != DW_DLV_OK) {
14564d9fdb4Robert Mustacchi        return (Dwarf_P_Attribute) DW_DLV_BADADDR;
14574d9fdb4Robert Mustacchi    }
14584d9fdb4Robert Mustacchi    return a;
14594d9fdb4Robert Mustacchi}
14604d9fdb4Robert Mustacchi
14614d9fdb4Robert Mustacchiint
14624d9fdb4Robert Mustacchidwarf_add_AT_const_value_string_a(Dwarf_P_Die ownerdie,
14634d9fdb4Robert Mustacchi    char *string_value,
14644d9fdb4Robert Mustacchi    Dwarf_P_Attribute *attr_out,
14654d9fdb4Robert Mustacchi    Dwarf_Error * error)
14664d9fdb4Robert Mustacchi{
14674d9fdb4Robert Mustacchi    Dwarf_P_Attribute new_attr = 0;
14684d9fdb4Robert Mustacchi    Dwarf_P_Debug dbg = 0;
14694d9fdb4Robert Mustacchi    int res = 0;
147049d3bc9Richard Lowe
147149d3bc9Richard Lowe    if (ownerdie == NULL) {
14724d9fdb4Robert Mustacchi        _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
14734d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
147449d3bc9Richard Lowe    }
14754d9fdb4Robert Mustacchi    dbg = ownerdie->di_dbg;
147649d3bc9Richard Lowe
147749d3bc9Richard Lowe    new_attr = (Dwarf_P_Attribute)
14784d9fdb4Robert Mustacchi        _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
147949d3bc9Richard Lowe    if (new_attr == NULL) {
14804d9fdb4Robert Mustacchi        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
14814d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
148249d3bc9Richard Lowe    }
148349d3bc9Richard Lowe
148449d3bc9Richard Lowe    new_attr->ar_attribute = DW_AT_const_value;
14854d9fdb4Robert Mustacchi    res = _dwarf_pro_set_string_attr(new_attr,dbg,
14864d9fdb4Robert Mustacchi        string_value,error);
14874d9fdb4Robert Mustacchi    if (res != DW_DLV_OK) {
14884d9fdb4Robert Mustacchi        return res;
14894d9fdb4Robert Mustacchi    }
14904d9fdb4Robert Mustacchi
14914d9fdb4Robert Mustacchi    /* add attribute to the die */
14924d9fdb4Robert Mustacchi    _dwarf_pro_add_at_to_die(ownerdie, new_attr);
14934d9fdb4Robert Mustacchi    *attr_out = new_attr;
14944d9fdb4Robert Mustacchi    return DW_DLV_OK;
14954d9fdb4Robert Mustacchi}
14964d9fdb4Robert Mustacchi
14974d9fdb4Robert MustacchiDwarf_P_Attribute
14984d9fdb4Robert Mustacchidwarf_add_AT_with_ref_sig8(Dwarf_P_Die ownerdie,
14994d9fdb4Robert Mustacchi    Dwarf_Half attrnum,
15004d9fdb4Robert Mustacchi    const Dwarf_Sig8 *sig8_in,
15014d9fdb4Robert Mustacchi    Dwarf_Error * error)
15024d9fdb4Robert Mustacchi{
15034d9fdb4Robert Mustacchi    Dwarf_P_Attribute a = 0;
15044d9fdb4Robert Mustacchi    int res = 0;
15054d9fdb4Robert Mustacchi
15064d9fdb4Robert Mustacchi    res = dwarf_add_AT_with_ref_sig8_a(ownerdie,
15074d9fdb4Robert Mustacchi        attrnum,sig8_in,&a,error);
15084d9fdb4Robert Mustacchi    if (res != DW_DLV_OK) {
15094d9fdb4Robert Mustacchi        return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
15104d9fdb4Robert Mustacchi    }
15114d9fdb4Robert Mustacchi    return a;
15124d9fdb4Robert Mustacchi}
15134d9fdb4Robert Mustacchi
15144d9fdb4Robert Mustacchiint
15154d9fdb4Robert Mustacchidwarf_add_AT_with_ref_sig8_a(Dwarf_P_Die ownerdie,
15164d9fdb4Robert Mustacchi    Dwarf_Half attrnum,
15174d9fdb4Robert Mustacchi    const Dwarf_Sig8 *sig8_in,
15184d9fdb4Robert Mustacchi    Dwarf_P_Attribute * attr_out,
15194d9fdb4Robert Mustacchi    Dwarf_Error * error)
15204d9fdb4Robert Mustacchi{
15214d9fdb4Robert Mustacchi    Dwarf_P_Attribute new_attr = 0;
15224d9fdb4Robert Mustacchi    Dwarf_P_Debug dbg = 0;
15234d9fdb4Robert Mustacchi
15244d9fdb4Robert Mustacchi    if (ownerdie == NULL) {
15254d9fdb4Robert Mustacchi        _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
15264d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
15274d9fdb4Robert Mustacchi    }
15284d9fdb4Robert Mustacchi    dbg = ownerdie->di_dbg;
15294d9fdb4Robert Mustacchi
15304d9fdb4Robert Mustacchi    new_attr = (Dwarf_P_Attribute)
15314d9fdb4Robert Mustacchi        _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
15324d9fdb4Robert Mustacchi    if (new_attr == NULL) {
15334d9fdb4Robert Mustacchi        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
15344d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
15354d9fdb4Robert Mustacchi    }
15364d9fdb4Robert Mustacchi    new_attr->ar_attribute<