summaryrefslogtreecommitdiff
path: root/usr/src/tools/ctf/dwarf/common/dwarf_global.c
diff options
context:
space:
mode:
authorRichard Lowe <richlowe@richlowe.net>2011-05-22 03:13:22 +0100
committerRichard Lowe <richlowe@richlowe.net>2011-06-29 19:12:22 -0400
commit77b6d4a80fc05587b08370de690c979abe2667d5 (patch)
treef00c511c215afecbbe09aac179e10839099358a6 /usr/src/tools/ctf/dwarf/common/dwarf_global.c
parent9ecc7612020c1993e4dbadd3422a74b210279739 (diff)
downloadillumos-joyent-77b6d4a80fc05587b08370de690c979abe2667d5.tar.gz
dwarf: Upgrade to libdwarf-20110113
Diffstat (limited to 'usr/src/tools/ctf/dwarf/common/dwarf_global.c')
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_global.c645
1 files changed, 394 insertions, 251 deletions
diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_global.c b/usr/src/tools/ctf/dwarf/common/dwarf_global.c
index 6ba561ef5b..d1c090fa43 100644
--- a/usr/src/tools/ctf/dwarf/common/dwarf_global.c
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_global.c
@@ -1,6 +1,7 @@
/*
- Copyright (C) 2000, 2002 Silicon Graphics, Inc. All Rights Reserved.
+ Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2010 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
@@ -19,10 +20,10 @@
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., 59 Temple Place - Suite 330, Boston MA 02111-1307,
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
USA.
- Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky,
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
Mountain View, CA 94043, or:
http://www.sgi.com
@@ -32,6 +33,12 @@
http://oss.sgi.com/projects/GenInfo/NoticeExplan
*/
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
@@ -40,35 +47,106 @@
#include <stdio.h>
#include "dwarf_global.h"
+
+#ifdef __sgi /* __sgi should only be defined for IRIX/MIPS. */
+/* The 'fixup' here intended for IRIX targets only.
+ With a 2+GB Elf64 IRIX executable (under 4GB in size),
+ some DIE offsets wrongly
+ got the 32bit upper bit sign extended. For the cu-header
+ offset in the .debug_pubnames section and in the
+ .debug_aranges section.
+ the 'varp' here is a pointer to an offset into .debug_info.
+ We fix up the offset here if it seems advisable..
+
+ As of June 2005 we have identified a series of mistakes
+ in ldx64 that can cause this (64 bit values getting passed
+ thru 32-bit signed knothole).
+*/
+void
+_dwarf_fix_up_offset_irix(Dwarf_Debug dbg,
+ Dwarf_Unsigned * varp, char *caller_site_name)
+{
+
+ Dwarf_Unsigned var = *varp;
+
+#define UPPER33 0xffffffff80000000LL
+#define LOWER32 0xffffffffLL
+ /* Restrict the hack to the known case. Upper 32 bits erroneously
+ sign extended from lower 32 upper bit. */
+ if ((var & UPPER33) == UPPER33) {
+ var &= LOWER32;
+ /* Apply the fix. Dreadful hack. */
+ *varp = var;
+ }
+#undef UPPER33
+#undef LOWER32
+ return;
+}
+#endif
+
+
int
dwarf_get_globals(Dwarf_Debug dbg,
- Dwarf_Global ** globals,
- Dwarf_Signed * return_count, Dwarf_Error * error)
+ Dwarf_Global ** globals,
+ Dwarf_Signed * return_count, Dwarf_Error * error)
{
- int res;
-
- res =
- _dwarf_load_section(dbg,
- dbg->de_debug_pubnames_index,
- &dbg->de_debug_pubnames,
- error);
+ int res = _dwarf_load_section(dbg, &dbg->de_debug_pubnames,error);
if (res != DW_DLV_OK) {
return res;
}
+ return _dwarf_internal_get_pubnames_like_data(dbg,
+ dbg->de_debug_pubnames.dss_data,
+ dbg->de_debug_pubnames.dss_size,
+ globals,
+ return_count,
+ error,
+ DW_DLA_GLOBAL_CONTEXT,
+ DW_DLA_GLOBAL,
+ DW_DLE_PUBNAMES_LENGTH_BAD,
+ DW_DLE_PUBNAMES_VERSION_ERROR);
+}
- return _dwarf_internal_get_pubnames_like_data(dbg,
- dbg->
- de_debug_pubnames,
- dbg->
- de_debug_pubnames_size,
- globals, return_count,
- error,
- DW_DLA_GLOBAL_CONTEXT,
- DW_DLE_PUBNAMES_LENGTH_BAD,
- DW_DLE_PUBNAMES_VERSION_ERROR);
+/* Deallocating fully requires deallocating the list
+ and all entries. But some internal data is
+ not exposed, so we need a function with internal knowledge.
+*/
+
+void
+dwarf_globals_dealloc(Dwarf_Debug dbg, Dwarf_Global * dwgl,
+ Dwarf_Signed count)
+{
+ _dwarf_internal_globals_dealloc(dbg, dwgl,
+ count,
+ DW_DLA_GLOBAL_CONTEXT,
+ DW_DLA_GLOBAL, DW_DLA_LIST);
+ return;
+}
+
+void
+_dwarf_internal_globals_dealloc(Dwarf_Debug dbg, Dwarf_Global * dwgl,
+ Dwarf_Signed count,
+ int context_code,
+ int global_code, int list_code)
+{
+ Dwarf_Signed i;
+ struct Dwarf_Global_Context_s *gcp = 0;
+ struct Dwarf_Global_Context_s *lastgcp = 0;
+
+ for (i = 0; i < count; i++) {
+ Dwarf_Global dgb = dwgl[i];
+ gcp = dgb->gl_context;
+
+ if (lastgcp != gcp) {
+ lastgcp = gcp;
+ dwarf_dealloc(dbg, gcp, context_code);
+ }
+ dwarf_dealloc(dbg, dgb, global_code);
+ }
+ dwarf_dealloc(dbg, dwgl, list_code);
+ return;
}
@@ -76,212 +154,221 @@ dwarf_get_globals(Dwarf_Debug dbg,
*/
int
_dwarf_internal_get_pubnames_like_data(Dwarf_Debug dbg,
- Dwarf_Small * section_data_ptr,
- Dwarf_Unsigned section_length,
- Dwarf_Global ** globals,
- Dwarf_Signed * return_count,
- Dwarf_Error * error,
- int allocation_code,
- int length_err_num,
- int version_err_num)
+ Dwarf_Small * section_data_ptr,
+ Dwarf_Unsigned section_length,
+ Dwarf_Global ** globals,
+ Dwarf_Signed * return_count,
+ Dwarf_Error * error,
+ int context_code,
+ int global_code,
+ int length_err_num,
+ int version_err_num)
{
- Dwarf_Small *pubnames_like_ptr;
+ Dwarf_Small *pubnames_like_ptr = 0;
- /*
- Points to the context for the current set of global names, and
+ /* Points to the context for the current set of global names, and
contains information to identify the compilation-unit that the
set refers to. */
- Dwarf_Global_Context pubnames_context;
+ Dwarf_Global_Context pubnames_context = 0;
- Dwarf_Half version;
+ Dwarf_Half version = 0;
/*
Offset from the start of compilation-unit for the current
global. */
- Dwarf_Off die_offset_in_cu;
+ Dwarf_Off die_offset_in_cu = 0;
Dwarf_Unsigned global_count = 0;
/* Points to the current global read. */
- Dwarf_Global global;
+ Dwarf_Global global = 0;
- /*
- Used to chain the Dwarf_Global_s structs for creating contiguous
+ /* Used to chain the Dwarf_Global_s structs for creating contiguous
list of pointers to the structs. */
- Dwarf_Chain curr_chain, prev_chain, head_chain = NULL;
+ Dwarf_Chain curr_chain = 0;
+ Dwarf_Chain prev_chain = 0;
+ Dwarf_Chain head_chain = 0;
/* Points to contiguous block of Dwarf_Global's to be returned. */
- Dwarf_Global *ret_globals;
+ Dwarf_Global *ret_globals = 0;
/* Temporary counter. */
- Dwarf_Unsigned i;
+ Dwarf_Unsigned i = 0;
if (dbg == NULL) {
- _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
- return (DW_DLV_ERROR);
+ _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_ERROR);
}
/* We will eventually need the .debug_info data. Load it now. */
- if(!dbg->de_debug_info) {
- int res = _dwarf_load_debug_info(dbg,error);
- if(res != DW_DLV_OK) {
- return res;
+ if (!dbg->de_debug_info.dss_data) {
+ int res = _dwarf_load_debug_info(dbg, error);
+
+ if (res != DW_DLV_OK) {
+ return res;
}
}
if (section_data_ptr == NULL) {
- return (DW_DLV_NO_ENTRY);
+ return (DW_DLV_NO_ENTRY);
}
pubnames_like_ptr = section_data_ptr;
do {
- Dwarf_Unsigned length;
- int local_extension_size;
- int local_length_size;
-
- /* Some compilers emit padding at the end of each cu's
- area. pubnames_ptr_past_end_cu records the true
- area end for this cu's data. Essentially the
- length in the header and the 0 terminator of the
- data are redundant information. The dwarf2/3
- spec does not mention what to do if the length
- is past the 0 terminator. So we take any bytes
- left after the 0 as padding and ignore them. */
+ Dwarf_Unsigned length = 0;
+ int local_extension_size = 0;
+ int local_length_size = 0;
+
+ /* Some compilers emit padding at the end of each cu's area.
+ pubnames_ptr_past_end_cu records the true area end for this
+ cu's data. Essentially the length in the header and the 0
+ terminator of the data are redundant information. The
+ dwarf2/3 spec does not mention what to do if the length is
+ past the 0 terminator. So we take any bytes left after the 0
+ as padding and ignore them. */
Dwarf_Small *pubnames_ptr_past_end_cu = 0;
-
-
- pubnames_context = (Dwarf_Global_Context)
- _dwarf_get_alloc(dbg, allocation_code, 1);
- if (pubnames_context == NULL) {
- _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
- return (DW_DLV_ERROR);
- }
- /* READ_AREA_LENGTH updates pubnames_like_ptr for consumed
- bytes */
- READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
- pubnames_like_ptr, local_length_size,
- local_extension_size);
- pubnames_context->pu_length_size = local_length_size;
- pubnames_context->pu_extension_size = local_extension_size;
- pubnames_context->pu_dbg = dbg;
-
- pubnames_ptr_past_end_cu = pubnames_like_ptr + length;
-
- READ_UNALIGNED(dbg, version, Dwarf_Half,
- pubnames_like_ptr, sizeof(Dwarf_Half));
- pubnames_like_ptr += sizeof(Dwarf_Half);
- if (version != CURRENT_VERSION_STAMP) {
- _dwarf_error(dbg, error, version_err_num);
- return (DW_DLV_ERROR);
- }
-
- /* offset of CU header in debug section */
- READ_UNALIGNED(dbg, pubnames_context->pu_offset_of_cu_header,
- Dwarf_Off, pubnames_like_ptr,
- pubnames_context->pu_length_size);
- pubnames_like_ptr += pubnames_context->pu_length_size;
-
-
- READ_UNALIGNED(dbg, pubnames_context->pu_info_length,
- Dwarf_Unsigned, pubnames_like_ptr,
- pubnames_context->pu_length_size);
- pubnames_like_ptr += pubnames_context->pu_length_size;
-
- if (pubnames_like_ptr > (section_data_ptr + section_length)) {
- _dwarf_error(dbg, error, length_err_num);
- return (DW_DLV_ERROR);
- }
-
- /* read initial offset (of DIE within CU) of a pubname, final
- entry is not a pair, just a zero offset */
- READ_UNALIGNED(dbg, die_offset_in_cu, Dwarf_Off,
- pubnames_like_ptr,
- pubnames_context->pu_length_size);
- pubnames_like_ptr += pubnames_context->pu_length_size;
-
- /* loop thru pairs. DIE off with CU followed by string */
- while (die_offset_in_cu != 0) {
-
- /* Already read offset, pubnames_like_ptr now points to the
- string */
- global =
- (Dwarf_Global) _dwarf_get_alloc(dbg, DW_DLA_GLOBAL, 1);
- if (global == NULL) {
- _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
- return (DW_DLV_ERROR);
- }
- global_count++;
-
- global->gl_context = pubnames_context;
-
- global->gl_named_die_offset_within_cu = die_offset_in_cu;
-
- global->gl_name = pubnames_like_ptr;
-
- pubnames_like_ptr = pubnames_like_ptr +
- strlen((char *) pubnames_like_ptr) + 1;
-
-
- /* finish off current entry chain */
- curr_chain =
- (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
- if (curr_chain == NULL) {
- _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
- return (DW_DLV_ERROR);
- }
-
- /* Put current global on singly_linked list. */
- curr_chain->ch_item = (Dwarf_Global) global;
-
- if (head_chain == NULL)
- head_chain = prev_chain = curr_chain;
- else {
- prev_chain->ch_next = curr_chain;
- prev_chain = curr_chain;
- }
-
- /* read offset for the *next* entry */
- READ_UNALIGNED(dbg, die_offset_in_cu, Dwarf_Off,
- pubnames_like_ptr,
- pubnames_context->pu_length_size);
-
- pubnames_like_ptr += pubnames_context->pu_length_size;
- if (pubnames_like_ptr > (section_data_ptr + section_length)) {
- _dwarf_error(dbg, error, length_err_num);
- return (DW_DLV_ERROR);
- }
- }
- /* ASSERT: die_offset_in_cu == 0 */
- if(pubnames_like_ptr > pubnames_ptr_past_end_cu) {
- /* This is some kind of error. This simply cannot happen.
- The encoding is wrong or the length in the header
- for this cu's contribution is wrong. */
- _dwarf_error(dbg, error, length_err_num);
- return (DW_DLV_ERROR);
-
+
+
+ pubnames_context = (Dwarf_Global_Context)
+ _dwarf_get_alloc(dbg, context_code, 1);
+ if (pubnames_context == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ /* READ_AREA_LENGTH updates pubnames_like_ptr for consumed
+ bytes. */
+ READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
+ pubnames_like_ptr, local_length_size,
+ local_extension_size);
+ pubnames_context->pu_length_size = local_length_size;
+ pubnames_context->pu_extension_size = local_extension_size;
+ pubnames_context->pu_dbg = dbg;
+
+ pubnames_ptr_past_end_cu = pubnames_like_ptr + length;
+
+ READ_UNALIGNED(dbg, version, Dwarf_Half,
+ pubnames_like_ptr, sizeof(Dwarf_Half));
+ pubnames_like_ptr += sizeof(Dwarf_Half);
+ if (version != CURRENT_VERSION_STAMP) {
+ _dwarf_error(dbg, error, version_err_num);
+ return (DW_DLV_ERROR);
+ }
+
+ /* Offset of CU header in debug section. */
+ READ_UNALIGNED(dbg, pubnames_context->pu_offset_of_cu_header,
+ Dwarf_Off, pubnames_like_ptr,
+ pubnames_context->pu_length_size);
+ pubnames_like_ptr += pubnames_context->pu_length_size;
+
+ FIX_UP_OFFSET_IRIX_BUG(dbg,
+ pubnames_context->pu_offset_of_cu_header,
+ "pubnames cu header offset");
+
+
+ READ_UNALIGNED(dbg, pubnames_context->pu_info_length,
+ Dwarf_Unsigned, pubnames_like_ptr,
+ pubnames_context->pu_length_size);
+ pubnames_like_ptr += pubnames_context->pu_length_size;
+
+ if (pubnames_like_ptr > (section_data_ptr + section_length)) {
+ _dwarf_error(dbg, error, length_err_num);
+ return (DW_DLV_ERROR);
}
- /* If there is some kind of padding at the end of
- the section, as emitted by some compilers,
- skip over that padding and simply ignore the bytes
- thus passed-over. With most compilers,
- pubnames_like_ptr == pubnames_ptr_past_end_cu
- at this point */
- pubnames_like_ptr = pubnames_ptr_past_end_cu;
+
+ /* Read initial offset (of DIE within CU) of a pubname, final
+ entry is not a pair, just a zero offset. */
+ READ_UNALIGNED(dbg, die_offset_in_cu, Dwarf_Off,
+ pubnames_like_ptr,
+ pubnames_context->pu_length_size);
+ pubnames_like_ptr += pubnames_context->pu_length_size;
+ FIX_UP_OFFSET_IRIX_BUG(dbg,
+ die_offset_in_cu, "offset of die in cu");
+
+ /* Loop thru pairs. DIE off with CU followed by string. */
+ while (die_offset_in_cu != 0) {
+
+ /* Already read offset, pubnames_like_ptr now points to the
+ string. */
+ global =
+ (Dwarf_Global) _dwarf_get_alloc(dbg, global_code, 1);
+ if (global == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ global_count++;
+
+ global->gl_context = pubnames_context;
+
+ global->gl_named_die_offset_within_cu = die_offset_in_cu;
+
+ global->gl_name = pubnames_like_ptr;
+
+ pubnames_like_ptr = pubnames_like_ptr +
+ strlen((char *) pubnames_like_ptr) + 1;
+
+
+ /* finish off current entry chain */
+ curr_chain =
+ (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (curr_chain == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ /* Put current global on singly_linked list. */
+ curr_chain->ch_item = (Dwarf_Global) global;
+
+ if (head_chain == NULL)
+ head_chain = prev_chain = curr_chain;
+ else {
+ prev_chain->ch_next = curr_chain;
+ prev_chain = curr_chain;
+ }
+
+ /* read offset for the *next* entry */
+ READ_UNALIGNED(dbg, die_offset_in_cu, Dwarf_Off,
+ pubnames_like_ptr,
+ pubnames_context->pu_length_size);
+
+ pubnames_like_ptr += pubnames_context->pu_length_size;
+ FIX_UP_OFFSET_IRIX_BUG(dbg,
+ die_offset_in_cu,
+ "offset of next die in cu");
+
+ if (pubnames_like_ptr > (section_data_ptr + section_length)) {
+ _dwarf_error(dbg, error, length_err_num);
+ return (DW_DLV_ERROR);
+ }
+ }
+ /* ASSERT: die_offset_in_cu == 0 */
+ if (pubnames_like_ptr > pubnames_ptr_past_end_cu) {
+ /* This is some kind of error. This simply cannot happen.
+ The encoding is wrong or the length in the header for
+ this cu's contribution is wrong. */
+ _dwarf_error(dbg, error, length_err_num);
+ return (DW_DLV_ERROR);
+ }
+ /* If there is some kind of padding at the end of the section,
+ as emitted by some compilers, skip over that padding and
+ simply ignore the bytes thus passed-over. With most
+ compilers, pubnames_like_ptr == pubnames_ptr_past_end_cu at
+ this point */
+ pubnames_like_ptr = pubnames_ptr_past_end_cu;
} while (pubnames_like_ptr < (section_data_ptr + section_length));
/* Points to contiguous block of Dwarf_Global's. */
ret_globals = (Dwarf_Global *)
- _dwarf_get_alloc(dbg, DW_DLA_LIST, global_count);
+ _dwarf_get_alloc(dbg, DW_DLA_LIST, global_count);
if (ret_globals == NULL) {
- _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
- return (DW_DLV_ERROR);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
}
/*
@@ -289,29 +376,30 @@ _dwarf_internal_get_pubnames_like_data(Dwarf_Debug dbg,
and deallocate the chain. */
curr_chain = head_chain;
for (i = 0; i < global_count; i++) {
- *(ret_globals + i) = curr_chain->ch_item;
- prev_chain = curr_chain;
- curr_chain = curr_chain->ch_next;
- dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
+ *(ret_globals + i) = curr_chain->ch_item;
+ prev_chain = curr_chain;
+ curr_chain = curr_chain->ch_next;
+ dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
}
*globals = ret_globals;
- *return_count = (global_count);
+ *return_count = (Dwarf_Signed) global_count;
return DW_DLV_OK;
}
+
/*
- Given a pubnames entry (or other like section entry)
- return thru the ret_name pointer
- a pointer to the string which is the entry name.
-
+ Given a pubnames entry (or other like section entry)
+ return thru the ret_name pointer
+ a pointer to the string which is the entry name.
+
*/
int
dwarf_globname(Dwarf_Global glob, char **ret_name, Dwarf_Error * error)
{
if (glob == NULL) {
- _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
- return (DW_DLV_ERROR);
+ _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
+ return (DW_DLV_ERROR);
}
*ret_name = (char *) (glob->gl_name);
@@ -320,40 +408,40 @@ dwarf_globname(Dwarf_Global glob, char **ret_name, Dwarf_Error * error)
/*
- Given a pubnames entry (or other like section entry)
- return thru the ret_off pointer the
- global offset of the DIE for this entry.
- The global offset is the offset within the .debug_info
- section as a whole.
+ Given a pubnames entry (or other like section entry)
+ return thru the ret_off pointer the
+ global offset of the DIE for this entry.
+ The global offset is the offset within the .debug_info
+ section as a whole.
*/
int
dwarf_global_die_offset(Dwarf_Global global,
- Dwarf_Off * ret_off, Dwarf_Error * error)
+ Dwarf_Off * ret_off, Dwarf_Error * error)
{
if (global == NULL) {
- _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
- return (DW_DLV_ERROR);
+ _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
+ return (DW_DLV_ERROR);
}
if (global->gl_context == NULL) {
- _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
- return (DW_DLV_ERROR);
+ _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
+ return (DW_DLV_ERROR);
}
*ret_off = (global->gl_named_die_offset_within_cu +
- global->gl_context->pu_offset_of_cu_header);
+ global->gl_context->pu_offset_of_cu_header);
return DW_DLV_OK;
}
/*
- Given a pubnames entry (or other like section entry)
- return thru the ret_off pointer the
- offset of the compilation unit header of the
+ Given a pubnames entry (or other like section entry)
+ return thru the ret_off pointer the
+ offset of the compilation unit header of the
compilation unit the global is part of.
- In early versions of this, the value returned was
+ In early versions of this, the value returned was
the offset of the compilation unit die, and
- other cu-local die offsets were faked so adding this to
+ other cu-local die offsets were faked so adding this to
such a cu-local offset got a true section offset.
Now things do as they say (adding *cu_header_offset to
a cu-local offset gets the section offset).
@@ -361,21 +449,21 @@ dwarf_global_die_offset(Dwarf_Global global,
*/
int
dwarf_global_cu_offset(Dwarf_Global global,
- Dwarf_Off * cu_header_offset,
- Dwarf_Error * error)
+ Dwarf_Off * cu_header_offset,
+ Dwarf_Error * error)
{
- Dwarf_Global_Context con;
+ Dwarf_Global_Context con = 0;
if (global == NULL) {
- _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
- return (DW_DLV_ERROR);
+ _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
+ return (DW_DLV_ERROR);
}
con = global->gl_context;
if (con == NULL) {
- _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
- return (DW_DLV_ERROR);
+ _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
+ return (DW_DLV_ERROR);
}
/* In early libdwarf, this incorrectly returned the offset of the
@@ -388,77 +476,132 @@ dwarf_global_cu_offset(Dwarf_Global global,
/*
Give back the pubnames entry (or any other like section)
name, symbol DIE offset, and the cu-DIE offset.
+
+ Various errors are possible.
+
+ The string pointer returned thru ret_name is not
+ dwarf_get_alloc()ed, so no dwarf_dealloc()
+ DW_DLA_STRING should be applied to it.
+
*/
int
dwarf_global_name_offsets(Dwarf_Global global,
- char **ret_name,
- Dwarf_Off * die_offset,
- Dwarf_Off * cu_die_offset,
- Dwarf_Error * error)
+ char **ret_name,
+ Dwarf_Off * die_offset,
+ Dwarf_Off * cu_die_offset,
+ Dwarf_Error * error)
{
- Dwarf_Global_Context con;
- Dwarf_Debug dbg;
- Dwarf_Off off;
+ Dwarf_Global_Context con = 0;
+ Dwarf_Debug dbg = 0;
+ Dwarf_Off off = 0;
if (global == NULL) {
- _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
- return (DW_DLV_ERROR);
+ _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
+ return (DW_DLV_ERROR);
}
con = global->gl_context;
if (con == NULL) {
- _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
- return (DW_DLV_ERROR);
+ _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
+ return (DW_DLV_ERROR);
}
off = con->pu_offset_of_cu_header;
- if (die_offset != NULL) {
- *die_offset = global->gl_named_die_offset_within_cu + off;
- }
-
+ /* The offset had better not be too close to the end. If it is,
+ _dwarf_length_of_cu_header() will step off the end and therefore
+ must not be used. 10 is a meaningless heuristic, but no CU
+ header is that small so it is safe. An erroneous offset is due
+ to a bug in the tool chain. A bug like this has been seen on
+ IRIX with MIPSpro 7.3.1.3 and an executable > 2GB in size and
+ with 2 million pubnames entries. */
+#define MIN_CU_HDR_SIZE 10
dbg = con->pu_dbg;
if (dbg == NULL) {
- _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
- return (DW_DLV_ERROR);
+ _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+ if (dbg->de_debug_info.dss_size &&
+ ((off + MIN_CU_HDR_SIZE) >= dbg->de_debug_info.dss_size)) {
+ _dwarf_error(NULL, error, DW_DLE_OFFSET_BAD);
+ return (DW_DLV_ERROR);
}
+#undef MIN_CU_HDR_SIZE
+ if (die_offset != NULL) {
+ *die_offset = global->gl_named_die_offset_within_cu + off;
+ }
+
+ *ret_name = (char *) global->gl_name;
if (cu_die_offset != NULL) {
- int res = _dwarf_load_debug_info(dbg,error);
- if(res != DW_DLV_OK) {
- return res;
- }
- *cu_die_offset = off + _dwarf_length_of_cu_header(dbg, off);
+ int res = _dwarf_load_debug_info(dbg, error);
+
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ /* The offset had better not be too close to the end. If it is,
+ _dwarf_length_of_cu_header() will step off the end and
+ therefore must not be used. 10 is a meaningless heuristic,
+ but no CU header is that small so it is safe. */
+ if ((off + 10) >= dbg->de_debug_info.dss_size) {
+ _dwarf_error(NULL, error, DW_DLE_OFFSET_BAD);
+ return (DW_DLV_ERROR);
+ }
+ *cu_die_offset = off + _dwarf_length_of_cu_header(dbg, off);
}
- *ret_name = (char *) global->gl_name;
return DW_DLV_OK;
}
/*
- We have the offset to a CU header.
- Return thru outFileOffset the offset of the CU DIE.
-
- New June, 2001.
- Used by SGI debuggers.
- No error is possible.
+ We have the offset to a CU header.
+ Return thru outFileOffset the offset of the CU DIE.
+
+ New June, 2001.
+ Used by SGI debuggers.
+ No error is possible.
+
+ See also dwarf_CU_dieoffset_given_die().
*/
/* ARGSUSED */
int
dwarf_get_cu_die_offset_given_cu_header_offset(Dwarf_Debug dbg,
- Dwarf_Off
- in_cu_header_offset,
- Dwarf_Off *
- out_cu_die_offset,
- Dwarf_Error * err)
+ Dwarf_Off in_cu_header_offset,
+ Dwarf_Off * out_cu_die_offset,
+ Dwarf_Error * err)
{
Dwarf_Off len =
- _dwarf_length_of_cu_header(dbg, in_cu_header_offset);
+ _dwarf_length_of_cu_header(dbg, in_cu_header_offset);
Dwarf_Off newoff = in_cu_header_offset + len;
*out_cu_die_offset = newoff;
return DW_DLV_OK;
}
+/* dwarf_CU_dieoffset_given_die returns
+ the global debug_info section offset of the CU die
+ that is the CU containing the given (passed-in) die.
+ This information makes it possible for a consumer to
+ find and print context information for any die.
+
+ Use dwarf_offdie() passing in the offset this returns
+ to get a die pointer to the CU die.
+ */
+int
+dwarf_CU_dieoffset_given_die(Dwarf_Die die,
+ Dwarf_Off* return_offset,
+ Dwarf_Error* error)
+{
+ Dwarf_Off dieoff = 0;
+ Dwarf_CU_Context cucontext = 0;
+
+ CHECK_DIE(die, DW_DLV_ERROR);
+ cucontext = die->di_cu_context;
+ dieoff = cucontext->cc_debug_info_offset;
+ /* The following call cannot fail, so no error check. */
+ dwarf_get_cu_die_offset_given_cu_header_offset(
+ cucontext->cc_dbg, dieoff, return_offset,error);
+ return DW_DLV_OK;
+}