diff options
Diffstat (limited to 'usr/src/lib/libdwarf/common/pro_die.c')
-rw-r--r-- | usr/src/lib/libdwarf/common/pro_die.c | 772 |
1 files changed, 610 insertions, 162 deletions
diff --git a/usr/src/lib/libdwarf/common/pro_die.c b/usr/src/lib/libdwarf/common/pro_die.c index 948b641146..53e15ad8ac 100644 --- a/usr/src/lib/libdwarf/common/pro_die.c +++ b/usr/src/lib/libdwarf/common/pro_die.c @@ -2,114 +2,173 @@ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan + Portions Copyright 2011-2017 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it + and/or modify it under the terms of version 2.1 of the + GNU Lesser General Public License as published by the Free + Software Foundation. + + This program is distributed in the hope that it would be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. + + Further, this software is distributed without any warranty + that it is free of the rightful claim of any third person + regarding infringement or the like. Any license provided + herein, whether implied or otherwise, applies only to this + software file. Patent licenses, if any, provided herein + do not apply to combinations of this program with other + software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General + Public License along with this program; if not, write the + Free Software Foundation, Inc., 51 Franklin Street - Fifth + Floor, Boston MA 02110-1301, USA. */ - - #include "config.h" #include "libdwarfdefs.h" #include <stdio.h> +#ifdef HAVE_STDLIB_H +#include <stdlib.h> /* for exit(), C89 malloc */ +#endif /* HAVE_STDLIB_H */ +#ifdef HAVE_MALLOC_H +/* Useful include for some Windows compilers. */ +#include <malloc.h> +#endif /* HAVE_MALLOC_H */ +#ifdef HAVE_STDINT_H +#include <stdint.h> /* For uintptr_t */ +#endif /* HAVE_STDINT_H */ #include <string.h> +#include <stddef.h> #include "pro_incl.h" +#include "dwarf.h" +#include "libdwarf.h" +#include "pro_opaque.h" +#include "pro_error.h" +#include "pro_util.h" +#include "pro_alloc.h" #include "pro_die.h" +#include "pro_section.h" +#include "dwarf_tsearch.h" #ifndef R_MIPS_NONE #define R_MIPS_NONE 0 #endif -/* adds an attribute to a die */ -void _dwarf_pro_add_at_to_die(Dwarf_P_Die die, Dwarf_P_Attribute attr); +#define TRUE 1 +#define FALSE 0 -/*---------------------------------------------------------------------------- - This function creates a new die. +/* This function creates a new die. tag: tag of the new die to be created parent,child,left,right: specify neighbors of the new die. Only - one of these may be non-null ------------------------------------------------------------------------------*/ + one of these may be non-null */ Dwarf_P_Die dwarf_new_die(Dwarf_P_Debug dbg, - Dwarf_Tag tag, - Dwarf_P_Die parent, - Dwarf_P_Die child, - Dwarf_P_Die left, Dwarf_P_Die right, Dwarf_Error * error) + Dwarf_Tag tag, + Dwarf_P_Die parent, + Dwarf_P_Die child, + Dwarf_P_Die left, Dwarf_P_Die right, + Dwarf_Error * error) +{ + Dwarf_P_Die created = 0; + int res = 0; + + res = dwarf_new_die_a(dbg,tag,parent,child, + left,right,&created,error); + if (res != DW_DLV_OK) { + return (Dwarf_P_Die)DW_DLV_BADADDR; + } + return created; +} + +/* New September 2016. Preferred as error checking + is easier, no need for ugly cast. */ +int +dwarf_new_die_a(Dwarf_P_Debug dbg, + Dwarf_Tag tag, + Dwarf_P_Die parent, + Dwarf_P_Die child, + Dwarf_P_Die left, Dwarf_P_Die right, + Dwarf_P_Die *die_out, + Dwarf_Error *error) { Dwarf_P_Die ret_die = 0; + int res = 0; - Dwarf_P_Die new_die = (Dwarf_P_Die) + ret_die = (Dwarf_P_Die) _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Die_s)); - if (new_die == NULL) { + if (ret_die == NULL) { DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_ALLOC, - (Dwarf_P_Die) DW_DLV_BADADDR); - } - new_die->di_parent = NULL; - new_die->di_left = NULL; - new_die->di_right = NULL; - new_die->di_child = NULL; - new_die->di_last_child = NULL; - new_die->di_tag = tag; - new_die->di_dbg = dbg; - new_die->di_marker = 0; - ret_die = - dwarf_die_link(new_die, parent, child, left, right, error); - return ret_die; + DW_DLV_ERROR); + } + ret_die->di_parent = NULL; + ret_die->di_left = NULL; + ret_die->di_right = NULL; + ret_die->di_child = NULL; + ret_die->di_last_child = NULL; + ret_die->di_tag = tag; + ret_die->di_dbg = dbg; + ret_die->di_marker = 0; + res = dwarf_die_link_a(ret_die, parent, child, left, right, + error); + if (res != DW_DLV_OK) { + _dwarf_p_dealloc(dbg,(Dwarf_Small *)ret_die); + ret_die = 0; + } else { + *die_out = ret_die; + } + return res; } -/*---------------------------------------------------------------------------- - This function links up a die to specified neighbors +/* This function links up a die to specified neighbors parent,child,left,right: specify neighbors of the new die. Only one of these may be non-null ------------------------------------------------------------------------------*/ + This is the original version. Use dwarf_die_link_a() + instead as that function is easier to use (in checking for error). + */ Dwarf_P_Die dwarf_die_link(Dwarf_P_Die new_die, - Dwarf_P_Die parent, - Dwarf_P_Die child, - Dwarf_P_Die left, Dwarf_P_Die right, Dwarf_Error * error) + Dwarf_P_Die parent, + Dwarf_P_Die child, + Dwarf_P_Die left, Dwarf_P_Die right, Dwarf_Error * error) +{ + int res = 0; + + res = dwarf_die_link_a(new_die,parent,child,left,right,error); + if (res != DW_DLV_OK) { + return (Dwarf_P_Die)DW_DLV_BADADDR; + } + return new_die; +} + +/* New September 2016. + Error return easier to deal with + than dwarf_die_link(). */ +int +dwarf_die_link_a(Dwarf_P_Die new_die, + Dwarf_P_Die parent, + Dwarf_P_Die child, + Dwarf_P_Die left, Dwarf_P_Die right, Dwarf_Error * error) { /* Count the # of non null neighbors. */ - int n_nulls = 0; + int n_nulls = 0; if (parent != NULL) { n_nulls++; if (new_die->di_parent != NULL) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_LINK_LOOP, - (Dwarf_P_Die) DW_DLV_BADADDR); + DWARF_P_DBG_ERROR(NULL, DW_DLE_LINK_LOOP, + DW_DLV_ERROR); } new_die->di_parent = parent; if (parent->di_child) { - /* di_last_child identifies the last sibling, the - die we want to attach new_die to. */ - /* ASSERT: if di_child is set so is di_last_child. */ + /* di_last_child identifies the last sibling, the + die we want to attach new_die to. */ + /* ASSERT: if di_child is set so is di_last_child. */ Dwarf_P_Die former_lastchild = parent->di_last_child; parent->di_last_child = new_die; /* Attach to the new die to end of the sibling list. */ @@ -126,7 +185,7 @@ dwarf_die_link(Dwarf_P_Die new_die, new_die->di_last_child = child; if (child->di_parent) { DWARF_P_DBG_ERROR(NULL, DW_DLE_PARENT_EXISTS, - (Dwarf_P_Die) DW_DLV_BADADDR); + DW_DLV_ERROR); } else { child->di_parent = new_die; } @@ -134,16 +193,16 @@ dwarf_die_link(Dwarf_P_Die new_die, if (left != NULL) { n_nulls++; new_die->di_left = left; - if (left->di_right) { - /* There's already a right sibling of left, - insert the new die in the list. */ + if (left->di_right) { + /* There's already a right sibling of left, + insert the new die in the list. */ new_die->di_right = left->di_right; left->di_right->di_left = new_die; } left->di_right = new_die; if (new_die->di_parent) { DWARF_P_DBG_ERROR(NULL, DW_DLE_PARENT_EXISTS, - (Dwarf_P_Die) DW_DLV_BADADDR); + DW_DLV_ERROR); } else { new_die->di_parent = left->di_parent; } @@ -152,72 +211,113 @@ dwarf_die_link(Dwarf_P_Die new_die, n_nulls++; new_die->di_right = right; if (right->di_left) { - /* There is already a left sibling of the right die, - insert the new die in the list. */ + /* There is already a left sibling of the right die, + insert the new die in the list. */ new_die->di_left = right->di_left; right->di_left->di_right = new_die; } right->di_left = new_die; if (new_die->di_parent) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_PARENT_EXISTS, - (Dwarf_P_Die) DW_DLV_BADADDR); - } else { - new_die->di_parent = right->di_parent; + DWARF_P_DBG_ERROR(NULL, DW_DLE_PARENT_EXISTS, + DW_DLV_ERROR); + } else { + new_die->di_parent = right->di_parent; } } - if (n_nulls > 1) { - /* Multiple neighbors! error! */ - DWARF_P_DBG_ERROR(NULL, DW_DLE_EXTRA_NEIGHBORS, - (Dwarf_P_Die) DW_DLV_BADADDR); + if (n_nulls > 1) { + /* Multiple neighbors! error! */ + DWARF_P_DBG_ERROR(NULL, DW_DLE_EXTRA_NEIGHBORS, + DW_DLV_ERROR); } - return new_die; - + return DW_DLV_OK; } Dwarf_Unsigned dwarf_add_die_marker(Dwarf_P_Debug dbg, Dwarf_P_Die die, Dwarf_Unsigned marker, - Dwarf_Error * error) -{ + Dwarf_Error * error) { if (die == NULL) { DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL, DW_DLV_NOCOUNT); } die->di_marker = marker; return 0; } +int +dwarf_add_die_marker_a(Dwarf_P_Debug dbg, + Dwarf_P_Die die, + Dwarf_Unsigned marker, + Dwarf_Error * error) +{ + if (die == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL, + DW_DLV_ERROR); + } + die->di_marker = marker; + return DW_DLV_OK; +} Dwarf_Unsigned dwarf_get_die_marker(Dwarf_P_Debug dbg, - Dwarf_P_Die die, - Dwarf_Unsigned * marker, - Dwarf_Error * error) + Dwarf_P_Die die, + Dwarf_Unsigned * marker, + Dwarf_Error * error) { if (die == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL, DW_DLV_NOCOUNT); + DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL, + DW_DLV_NOCOUNT); } *marker = die->di_marker; return 0; } +int +dwarf_get_die_marker_a(Dwarf_P_Debug dbg, + Dwarf_P_Die die, + Dwarf_Unsigned * marker, + Dwarf_Error * error) +{ + if (die == NULL) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL, + DW_DLV_ERROR); + } + *marker = die->di_marker; + return DW_DLV_ERROR; +} -/*---------------------------------------------------------------------------- - This function adds a die to dbg struct. It should be called using - the root of all the dies. ------------------------------------------------------------------------------*/ +/*--------------------------------------------------------- + This function adds a die to dbg struct. It should + be called using the root of all the dies. +---------------------------------------------------------*/ +/* Original form of this call.. + dwarf_add_die_to_debug_a() is preferred now. */ Dwarf_Unsigned dwarf_add_die_to_debug(Dwarf_P_Debug dbg, - Dwarf_P_Die first_die, Dwarf_Error * error) + Dwarf_P_Die first_die, Dwarf_Error * error) +{ + int res = dwarf_add_die_to_debug_a(dbg,first_die,error); + if (res == DW_DLV_ERROR) { + return DW_DLV_NOCOUNT; + } + return 0; +} + +/* New September 2016. The new and preferred form. */ +int +dwarf_add_die_to_debug_a(Dwarf_P_Debug dbg, + Dwarf_P_Die first_die, Dwarf_Error * error) { if (first_die == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL, DW_DLV_NOCOUNT); + DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL, + DW_DLV_ERROR); } if (first_die->di_tag != DW_TAG_compile_unit) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_WRONG_TAG, DW_DLV_NOCOUNT); + DWARF_P_DBG_ERROR(dbg, DW_DLE_WRONG_TAG, + DW_DLV_ERROR); } dbg->de_dies = first_die; - return 0; + return DW_DLV_OK; } int @@ -225,17 +325,20 @@ _dwarf_pro_add_AT_stmt_list(Dwarf_P_Debug dbg, Dwarf_P_Die first_die, Dwarf_Error * error) { Dwarf_P_Attribute new_attr; - int uwordb_size = dbg->de_offset_size; + int uwordb_size = dbg->de_dwarf_offset_size; /* Add AT_stmt_list attribute */ new_attr = (Dwarf_P_Attribute) - _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s)); + _dwarf_p_get_alloc(dbg, + sizeof(struct Dwarf_P_Attribute_s)); if (new_attr == NULL) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, DW_DLV_NOCOUNT); + DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, + DW_DLV_ERROR); } new_attr->ar_attribute = DW_AT_stmt_list; - new_attr->ar_attribute_form = dbg->de_ar_data_attribute_form; + new_attr->ar_attribute_form = + dbg->de_ar_data_attribute_form; new_attr->ar_rel_type = dbg->de_offset_reloc; new_attr->ar_nbytes = uwordb_size; @@ -244,126 +347,469 @@ _dwarf_pro_add_AT_stmt_list(Dwarf_P_Debug dbg, new_attr->ar_data = (char *) _dwarf_p_get_alloc(dbg, uwordb_size); if (new_attr->ar_data == NULL) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_ADDR_ALLOC, DW_DLV_NOCOUNT); + DWARF_P_DBG_ERROR(NULL,DW_DLE_ADDR_ALLOC, + DW_DLV_ERROR); } { - Dwarf_Unsigned du = 0; + Dwarf_Unsigned du = 0; - WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data, - (const void *) &du, sizeof(du), uwordb_size); + WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data, + (const void *) &du, sizeof(du), uwordb_size); } _dwarf_pro_add_at_to_die(first_die, new_attr); - return 0; + return DW_DLV_OK; +} + +static int +_dwarf_debug_str_compare_func(const void *l,const void *r) +{ + const struct Dwarf_P_debug_str_entry_s*el = l; + const struct Dwarf_P_debug_str_entry_s*er = r; + char *lname = 0; + char *rname = 0; + int ir = 0; + + if (el->dse_has_table_offset) { + /* When set the name is in the debug_str table. */ + /* ASSERT: dse_dbg->de_debug_str->ds_data + is non-zero. + ASSERT: dse_name NULL. */ + lname = el->dse_dbg->de_debug_str->ds_data + + el->dse_table_offset; + } else { + /* ASSERT: dse_name non-null */ + lname = el->dse_name; + } + if (er->dse_has_table_offset) { + /* When set the name is in the debug_str table. */ + /* ASSERT: dse_dbg->de_debug_str->ds_data + is non-zero. + ASSERT: dse_name NULL. */ + rname = er->dse_dbg->de_debug_str->ds_data + + er->dse_table_offset; + } else { + /* ASSERT: dse_name non-null */ + rname = er->dse_name; + } + ir = strcmp(lname,rname); + return ir; +} + +static void +debug_str_entry_free_func(void *m) +{ + free(m); } -/*----------------------------------------------------------------------------- +static int +make_debug_str_entry(Dwarf_P_Debug dbg, + struct Dwarf_P_debug_str_entry_s **mt_out, + char *name, + unsigned slen, + unsigned char has_offset, + Dwarf_Unsigned offset_in_table, + Dwarf_Error *error) +{ + struct Dwarf_P_debug_str_entry_s *mt = + (struct Dwarf_P_debug_str_entry_s *)calloc( + sizeof(struct Dwarf_P_debug_str_entry_s),1); + if (!mt) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return DW_DLV_ERROR; + } + + mt->dse_slen = slen; + mt->dse_table_offset = 0; + mt->dse_dbg = dbg; + if (has_offset) { + mt->dse_has_table_offset = TRUE; + mt->dse_table_offset = offset_in_table; + mt->dse_name = 0; + } else { + /* ASSERT: name != NULL */ + mt->dse_has_table_offset = FALSE; + /* We just set dse_table_offset so it has + a known value, though nothing should refer + to dse_table_offset because + dse_has_table_offset is FALSE.*/ + mt->dse_table_offset = 0; + mt->dse_name = name; + } + *mt_out = mt; + return DW_DLV_OK; +} +#define STRTAB_BASE_ALLOC_SIZE 2048 +static int +insert_debug_str_data_string(Dwarf_P_Debug dbg, + char *name, + unsigned slen, + Dwarf_P_Section_Data sd, + Dwarf_Unsigned*adding_at_offset, + Dwarf_Error * error) +{ + Dwarf_Unsigned current_offset = 0; + + if (!sd->ds_data) { + Dwarf_Unsigned initial_alloc = STRTAB_BASE_ALLOC_SIZE; + Dwarf_Unsigned base_insert_offset = 0; + + /* Inserting our first string. + The GNU linker refuses to commonize strings + if the section starts with a NUL byte, + so start with real string, using a + base_insert_offset of 0. */ + if ( (slen + base_insert_offset) >= STRTAB_BASE_ALLOC_SIZE) { + initial_alloc = slen *2+ base_insert_offset; + } + if (initial_alloc < slen) { + _dwarf_p_error(dbg, error, DW_DLE_SIZE_WRAPAROUND); + return DW_DLV_ERROR; + } + sd->ds_data = calloc(1,initial_alloc); + if (!sd->ds_data) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return DW_DLV_ERROR; + } + sd->ds_orig_alloc = initial_alloc; + *adding_at_offset = base_insert_offset; + sd->ds_nbytes = slen + base_insert_offset; + strcpy(sd->ds_data+base_insert_offset,name); + return DW_DLV_OK; + } + current_offset = sd->ds_nbytes; + if ( (current_offset + slen) >= sd->ds_orig_alloc) { + unsigned updated_length = sd->ds_orig_alloc; + char *newbuf = 0; + if (slen > updated_length) { + /* Very long string passed in. */ + updated_length = slen *2; + } else { + updated_length = updated_length *2; + } + if (updated_length < sd->ds_orig_alloc) { + _dwarf_p_error(dbg, error, DW_DLE_SIZE_WRAPAROUND); + return DW_DLV_ERROR; + } + newbuf = calloc(1,updated_length); + if (!newbuf) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return DW_DLV_ERROR; + } + memcpy(newbuf,sd->ds_data,sd->ds_nbytes); + free(sd->ds_data); + sd->ds_data = newbuf; + sd->ds_orig_alloc = updated_length; + newbuf = 0; + } + strcpy(sd->ds_data + current_offset,name); + sd->ds_nbytes += slen; + *adding_at_offset = current_offset; + return DW_DLV_OK; +} + +/* Find the string offset using the hash table, + and if not known, insert the new string. */ +int +_dwarf_insert_or_find_in_debug_str(Dwarf_P_Debug dbg, + char *name, + enum dwarf_which_hash whash, + unsigned slen, /* includes space for trailing NUL */ + Dwarf_Unsigned *offset_in_debug_str, + Dwarf_Error *error) +{ + struct Dwarf_P_debug_str_entry_s *mt = 0; + struct Dwarf_P_debug_str_entry_s *mt2 = 0; + struct Dwarf_P_debug_str_entry_s *retval = 0; + struct Dwarf_P_debug_str_entry_s *re = 0; + int res = 0; + Dwarf_Unsigned adding_at_offset = 0; + void **hashtab = 0; + Dwarf_P_Section_Data sd = 0; + struct Dwarf_P_Str_stats_s * stats = 0; + + switch (whash) { + case _dwarf_hash_debug_str: + hashtab = &dbg->de_debug_str_hashtab; + sd = dbg->de_debug_str; + stats = &dbg->de_stats.ps_strp; + break; + case _dwarf_hash_debug_line_str: + hashtab = &dbg->de_debug_line_str_hashtab; + sd = dbg->de_debug_line_str; + stats = &dbg->de_stats.ps_line_strp; + break; + case _dwarf_hash_debug_str_sup: + default: + /* Not supported or unknown. */ + _dwarf_p_error(dbg, error, DW_DLE_STRING_HASHTAB_IDENTITY_ERROR); + return DW_DLV_ERROR; + } + res = make_debug_str_entry(dbg,&mt,name, + slen,FALSE, 0, error); + if (res != DW_DLV_OK) { + return res; + } + /* We do a find as we do not want the string pointer passed in + to be in the hash table, we want a pointer into the + debug_str table in the hash table. */ + retval = dwarf_tfind(mt,(void *const*)hashtab, + _dwarf_debug_str_compare_func); + if (retval) { + + stats->ps_strp_reused_count++; + stats->ps_strp_reused_len += slen; + + re = *(struct Dwarf_P_debug_str_entry_s **)retval; + *offset_in_debug_str = re->dse_table_offset; + debug_str_entry_free_func(mt); + return DW_DLV_OK; + } + + /* We know the string is not in .debug_str data yet. + Insert it into the big string table and get that + offset. */ + + debug_str_entry_free_func(mt); + mt = 0; + res = insert_debug_str_data_string(dbg,name,slen,sd, + &adding_at_offset, error); + if (res != DW_DLV_OK) { + return res; + } + + /* The name is in the string table itself, so use that pointer + and offset for the string. */ + res = make_debug_str_entry(dbg,&mt2, 0, + slen,TRUE,adding_at_offset,error); + if (res != DW_DLV_OK) { + return res; + } + retval = dwarf_tsearch(mt2, + (void *)hashtab, + _dwarf_debug_str_compare_func); + if (!retval) { + debug_str_entry_free_func(mt2); + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return DW_DLV_ERROR; + } + + /* This indirection is one of the surprises in using tsearch... */ + re = *(struct Dwarf_P_debug_str_entry_s **)retval; + if (re != mt2) { + debug_str_entry_free_func(mt2); + /* Found it in hash tab: illogical as the tsearch_find should + have found it. */ + _dwarf_p_error(dbg, error, DW_DLE_ILLOGICAL_TSEARCH); + return DW_DLV_ERROR; + } + stats->ps_strp_count_debug_str++; + stats->ps_strp_len_debug_str += slen; + /* we added it to hash, do not free mt2 (which == re). */ + *offset_in_debug_str = re->dse_table_offset; + return DW_DLV_OK; +} + +/* Returns DW_DLV_OK or DW_DLV_ERROR. */ +int _dwarf_pro_set_string_attr(Dwarf_P_Attribute new_attr, + Dwarf_P_Debug dbg, + char *name, + Dwarf_Error *error) +{ + int form = dbg->de_debug_default_str_form; + unsigned slen = strlen(name)+1; + + if (form == DW_FORM_string || + slen <= dbg->de_dwarf_offset_size) { + new_attr->ar_nbytes = slen; + new_attr->ar_next = 0; + + new_attr->ar_data = + (char *) _dwarf_p_get_alloc(dbg, slen); + if (new_attr->ar_data == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return DW_DLV_ERROR; + } + dbg->de_stats.ps_str_count++; + dbg->de_stats.ps_str_total_length += slen; + + strcpy(new_attr->ar_data, name); + new_attr->ar_attribute_form = DW_FORM_string; + new_attr->ar_rel_type = R_MIPS_NONE; + new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */ + return DW_DLV_OK; + } + if (form == DW_FORM_strp) { + int uwordb_size = dbg->de_dwarf_offset_size; + Dwarf_Unsigned offset_in_debug_str = 0; + int res = 0; + + res = _dwarf_insert_or_find_in_debug_str(dbg,name, + _dwarf_hash_debug_str,slen, + &offset_in_debug_str,error); + if(res != DW_DLV_OK) { + return res; + } + new_attr->ar_attribute_form = form; + new_attr->ar_rel_type = dbg->de_offset_reloc; + new_attr->ar_nbytes = uwordb_size; + new_attr->ar_next = NULL; + new_attr->ar_reloc_len = uwordb_size; + /* During transform to disk + a symbol index will be applied. */ + new_attr->ar_data = (char *) + _dwarf_p_get_alloc(dbg, uwordb_size); + if (new_attr->ar_data == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return DW_DLV_ERROR; + } + { + Dwarf_Unsigned du = offset_in_debug_str; + + WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data, + (const void *) &du, sizeof(du), uwordb_size); + } + + return DW_DLV_OK; + } + _dwarf_p_error(dbg, error, DW_DLE_BAD_STRING_FORM); + return DW_DLV_ERROR; + +} + + +/*------------------------------------------------------------------- Add AT_name attribute to die -------------------------------------------------------------------------------*/ +---------------------------------------------------------------------*/ +/* Original function. dwarf_add_AT_name_a() is the + suggested alternative. */ Dwarf_P_Attribute -dwarf_add_AT_name(Dwarf_P_Die die, char *name, Dwarf_Error * error) +dwarf_add_AT_name(Dwarf_P_Die die, + char *name, + Dwarf_Error * error) { - Dwarf_P_Attribute new_attr; + Dwarf_P_Attribute a = 0; + int res = 0; + + res = dwarf_add_AT_name_a(die, name, + &a, error); + if (res == DW_DLV_ERROR) { + return (Dwarf_P_Attribute)(DW_DLV_BADADDR); + } + return a; +} + +/* New December 2018. */ +int +dwarf_add_AT_name_a(Dwarf_P_Die die, char *name, + Dwarf_P_Attribute *newattr_out, + Dwarf_Error * error) +{ + Dwarf_P_Attribute new_attr = 0; + int res = 0; if (die == NULL) { DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, - (Dwarf_P_Attribute) DW_DLV_BADADDR); + DW_DLV_ERROR); } new_attr = (Dwarf_P_Attribute) - _dwarf_p_get_alloc(die->di_dbg,sizeof(struct Dwarf_P_Attribute_s)); + _dwarf_p_get_alloc(die->di_dbg, + sizeof(struct Dwarf_P_Attribute_s)); if (new_attr == NULL) { DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, - (Dwarf_P_Attribute) DW_DLV_BADADDR); + DW_DLV_ERROR); } /* fill in the information */ new_attr->ar_attribute = DW_AT_name; - /* assume that form is string, no debug_str yet */ - new_attr->ar_attribute_form = DW_FORM_string; - new_attr->ar_nbytes = strlen(name) + 1; - new_attr->ar_next = NULL; - new_attr->ar_reloc_len = 0; - new_attr->ar_data = (char *) - _dwarf_p_get_alloc(die->di_dbg, strlen(name)+1); - if (new_attr->ar_data == NULL) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_STRING_ALLOC, - (Dwarf_P_Attribute) DW_DLV_BADADDR); + res = _dwarf_pro_set_string_attr(new_attr,die->di_dbg,name,error); + if (res != DW_DLV_OK) { + return DW_DLV_ERROR; } - strcpy(new_attr->ar_data, name); - - new_attr->ar_rel_type = R_MIPS_NONE; /* add attribute to the die */ _dwarf_pro_add_at_to_die(die, new_attr); - return new_attr; + *newattr_out = new_attr; + return DW_DLV_OK; } -/*----------------------------------------------------------------------------- +/*-------------------------------------------------------------------- Add AT_comp_dir attribute to die -------------------------------------------------------------------------------*/ +--------------------------------------------------------------------*/ Dwarf_P_Attribute dwarf_add_AT_comp_dir(Dwarf_P_Die ownerdie, char *current_working_directory, Dwarf_Error * error) { - Dwarf_P_Attribute new_attr; + Dwarf_P_Attribute a = 0; + int res = 0; + + res = dwarf_add_AT_comp_dir_a(ownerdie, + current_working_directory, + &a, error); + if (res != DW_DLV_OK) { + return (Dwarf_P_Attribute)(DW_DLV_BADADDR); + } + return a; +} + +int +dwarf_add_AT_comp_dir_a(Dwarf_P_Die ownerdie, + char *current_working_directory, + Dwarf_P_Attribute *attr_out, + Dwarf_Error * error) +{ + Dwarf_P_Attribute new_attr = 0; + int res = 0; if (ownerdie == NULL) { DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, - (Dwarf_P_Attribute) DW_DLV_BADADDR); + DW_DLV_ERROR); } new_attr = (Dwarf_P_Attribute) _dwarf_p_get_alloc(ownerdie->di_dbg, sizeof(struct Dwarf_P_Attribute_s)); if (new_attr == NULL) { DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, - (Dwarf_P_Attribute) DW_DLV_BADADDR); + DW_DLV_ERROR); } /* fill in the information */ new_attr->ar_attribute = DW_AT_comp_dir; - /* assume that form is string, no debug_str yet */ - new_attr->ar_attribute_form = DW_FORM_string; - new_attr->ar_nbytes = strlen(current_working_directory) + 1; - new_attr->ar_next = NULL; - new_attr->ar_reloc_len = 0; - new_attr->ar_data = (char *) - _dwarf_p_get_alloc(ownerdie->di_dbg, - strlen(current_working_directory)+1); - if (new_attr->ar_data == NULL) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_STRING_ALLOC, - (Dwarf_P_Attribute) DW_DLV_BADADDR); + res = _dwarf_pro_set_string_attr(new_attr,ownerdie->di_dbg, + current_working_directory,error); + if (res != DW_DLV_OK) { + return res; } - strcpy(new_attr->ar_data, current_working_directory); - - new_attr->ar_rel_type = R_MIPS_NONE; /* add attribute to the die */ _dwarf_pro_add_at_to_die(ownerdie, new_attr); - return new_attr; + *attr_out = new_attr; + return DW_DLV_OK; } + int _dwarf_pro_add_AT_fde(Dwarf_P_Debug dbg, Dwarf_P_Die die, Dwarf_Unsigned offset, Dwarf_Error * error) { Dwarf_P_Attribute new_attr; - int uwordb_size = dbg->de_offset_size; + int uwordb_size = dbg->de_dwarf_offset_size; if (die == NULL) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, -1); + DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, DW_DLV_ERROR); } new_attr = (Dwarf_P_Attribute) _dwarf_p_get_alloc(dbg,sizeof(struct Dwarf_P_Attribute_s)); if (new_attr == NULL) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, -1); + DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, DW_DLV_ERROR); } /* fill in the information */ new_attr->ar_attribute = DW_AT_MIPS_fde; - new_attr->ar_attribute_form = dbg->de_ar_data_attribute_form;; + new_attr->ar_attribute_form = dbg->de_ar_data_attribute_form; new_attr->ar_rel_type = dbg->de_offset_reloc; new_attr->ar_nbytes = uwordb_size; new_attr->ar_next = NULL; @@ -371,7 +817,7 @@ _dwarf_pro_add_AT_fde(Dwarf_P_Debug dbg, new_attr->ar_data = (char *) _dwarf_p_get_alloc(dbg, uwordb_size); if (new_attr->ar_data == NULL) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_ADDR_ALLOC, DW_DLV_NOCOUNT); + DWARF_P_DBG_ERROR(NULL, DW_DLE_ADDR_ALLOC, DW_DLV_ERROR); } { Dwarf_Unsigned du = offset; @@ -379,27 +825,26 @@ _dwarf_pro_add_AT_fde(Dwarf_P_Debug dbg, WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data, (const void *) &du, sizeof(du), uwordb_size); } - _dwarf_pro_add_at_to_die(die, new_attr); - - return 0; + return DW_DLV_OK; } +/* Sept 2016: returns DW_DLV_OK or DW_DLV_ERROR */ int _dwarf_pro_add_AT_macro_info(Dwarf_P_Debug dbg, Dwarf_P_Die die, Dwarf_Unsigned offset, Dwarf_Error * error) { Dwarf_P_Attribute new_attr; - int uwordb_size = dbg->de_offset_size; + int uwordb_size = dbg->de_dwarf_offset_size; if (die == NULL) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, -1); + DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, DW_DLV_ERROR); } new_attr = (Dwarf_P_Attribute) _dwarf_p_get_alloc(dbg,sizeof(struct Dwarf_P_Attribute_s)); if (new_attr == NULL) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, -1); + DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, DW_DLV_ERROR); } /* fill in the information */ @@ -413,7 +858,7 @@ _dwarf_pro_add_AT_macro_info(Dwarf_P_Debug dbg, new_attr->ar_data = (char *) _dwarf_p_get_alloc(dbg, uwordb_size); if (new_attr->ar_data == NULL) { - DWARF_P_DBG_ERROR(NULL, DW_DLE_ADDR_ALLOC, DW_DLV_NOCOUNT); + DWARF_P_DBG_ERROR(NULL, DW_DLE_ADDR_ALLOC, DW_DLV_ERROR); } { Dwarf_Unsigned du = offset; @@ -424,14 +869,17 @@ _dwarf_pro_add_AT_macro_info(Dwarf_P_Debug dbg, _dwarf_pro_add_at_to_die(die, new_attr); - return 0; + return DW_DLV_OK; } +/* Updates the list of attributes on this Dwarf_P_Die +*/ void _dwarf_pro_add_at_to_die(Dwarf_P_Die die, Dwarf_P_Attribute attr) { if (die->di_last_attr) { + /* Inserts new attr at the end */ die->di_last_attr->ar_next = attr; die->di_last_attr = attr; die->di_n_attr++; |