summaryrefslogtreecommitdiffstats
path: root/libdw
diff options
context:
space:
mode:
Diffstat (limited to 'libdw')
-rw-r--r--libdw/.cvsignore1
-rw-r--r--libdw/ChangeLog512
-rw-r--r--libdw/Makefile.am108
-rw-r--r--libdw/dwarf.h581
-rw-r--r--libdw/dwarf_abbrev_hash.c29
-rw-r--r--libdw/dwarf_abbrev_hash.h24
-rw-r--r--libdw/dwarf_abbrevhaschildren.c29
-rw-r--r--libdw/dwarf_addrdie.c39
-rw-r--r--libdw/dwarf_arrayorder.c33
-rw-r--r--libdw/dwarf_attr.c40
-rw-r--r--libdw/dwarf_attr_integrate.c43
-rw-r--r--libdw/dwarf_begin.c85
-rw-r--r--libdw/dwarf_begin_elf.c252
-rw-r--r--libdw/dwarf_bitoffset.c33
-rw-r--r--libdw/dwarf_bitsize.c33
-rw-r--r--libdw/dwarf_bytesize.c33
-rw-r--r--libdw/dwarf_child.c159
-rw-r--r--libdw/dwarf_cuoffset.c32
-rw-r--r--libdw/dwarf_diename.c31
-rw-r--r--libdw/dwarf_dieoffset.c32
-rw-r--r--libdw/dwarf_end.c75
-rw-r--r--libdw/dwarf_error.c180
-rw-r--r--libdw/dwarf_filesrc.c36
-rw-r--r--libdw/dwarf_formaddr.c44
-rw-r--r--libdw/dwarf_formblock.c72
-rw-r--r--libdw/dwarf_formflag.c40
-rw-r--r--libdw/dwarf_formref.c67
-rw-r--r--libdw/dwarf_formref_die.c28
-rw-r--r--libdw/dwarf_formsdata.c68
-rw-r--r--libdw/dwarf_formstring.c58
-rw-r--r--libdw/dwarf_formudata.c68
-rw-r--r--libdw/dwarf_func_col.c27
-rw-r--r--libdw/dwarf_func_entrypc.c33
-rw-r--r--libdw/dwarf_func_file.c72
-rw-r--r--libdw/dwarf_func_highpc.c26
-rw-r--r--libdw/dwarf_func_line.c47
-rw-r--r--libdw/dwarf_func_lowpc.c26
-rw-r--r--libdw/dwarf_func_name.c30
-rw-r--r--libdw/dwarf_getabbrev.c127
-rw-r--r--libdw/dwarf_getabbrevattr.c64
-rw-r--r--libdw/dwarf_getabbrevcode.c29
-rw-r--r--libdw/dwarf_getabbrevtag.c29
-rw-r--r--libdw/dwarf_getarange_addr.c47
-rw-r--r--libdw/dwarf_getarangeinfo.c38
-rw-r--r--libdw/dwarf_getaranges.c212
-rw-r--r--libdw/dwarf_getattrcnt.c33
-rw-r--r--libdw/dwarf_getattrs.c94
-rw-r--r--libdw/dwarf_getelf.c33
-rw-r--r--libdw/dwarf_getfuncs.c63
-rw-r--r--libdw/dwarf_getloclist.c454
-rw-r--r--libdw/dwarf_getmacros.c119
-rw-r--r--libdw/dwarf_getpubnames.c213
-rw-r--r--libdw/dwarf_getscopes.c334
-rw-r--r--libdw/dwarf_getscopevar.c147
-rw-r--r--libdw/dwarf_getsrc_die.c58
-rw-r--r--libdw/dwarf_getsrc_file.c158
-rw-r--r--libdw/dwarf_getsrcfiles.c60
-rw-r--r--libdw/dwarf_getsrclines.c652
-rw-r--r--libdw/dwarf_getstring.c51
-rw-r--r--libdw/dwarf_hasattr.c37
-rw-r--r--libdw/dwarf_hasattr_integrate.c42
-rw-r--r--libdw/dwarf_haschildren.c49
-rw-r--r--libdw/dwarf_hasform.c32
-rw-r--r--libdw/dwarf_haspc.c105
-rw-r--r--libdw/dwarf_highpc.c34
-rw-r--r--libdw/dwarf_lineaddr.c31
-rw-r--r--libdw/dwarf_linebeginstatement.c31
-rw-r--r--libdw/dwarf_lineblock.c31
-rw-r--r--libdw/dwarf_linecol.c31
-rw-r--r--libdw/dwarf_lineendsequence.c31
-rw-r--r--libdw/dwarf_lineepiloguebegin.c31
-rw-r--r--libdw/dwarf_lineno.c31
-rw-r--r--libdw/dwarf_lineprologueend.c31
-rw-r--r--libdw/dwarf_linesrc.c41
-rw-r--r--libdw/dwarf_lowpc.c34
-rw-r--r--libdw/dwarf_macro_opcode.c31
-rw-r--r--libdw/dwarf_macro_param1.c31
-rw-r--r--libdw/dwarf_macro_param2.c34
-rw-r--r--libdw/dwarf_nextcu.c132
-rw-r--r--libdw/dwarf_offabbrev.c36
-rw-r--r--libdw/dwarf_offdie.c55
-rw-r--r--libdw/dwarf_onearange.c35
-rw-r--r--libdw/dwarf_onesrcline.c35
-rw-r--r--libdw/dwarf_siblingof.c115
-rw-r--r--libdw/dwarf_srclang.c33
-rw-r--r--libdw/dwarf_tag.c82
-rw-r--r--libdw/dwarf_whatattr.c28
-rw-r--r--libdw/dwarf_whatform.c28
-rw-r--r--libdw/libdw.h564
-rw-r--r--libdw/libdw.map92
-rw-r--r--libdw/libdwP.h378
-rw-r--r--libdw/libdw_alloc.c59
-rw-r--r--libdw/libdw_findcu.c110
-rw-r--r--libdw/libdw_form.c112
-rw-r--r--libdw/memory-access.c35
-rw-r--r--libdw/memory-access.h240
96 files changed, 9028 insertions, 0 deletions
diff --git a/libdw/.cvsignore b/libdw/.cvsignore
new file mode 100644
index 00000000..70845e08
--- /dev/null
+++ b/libdw/.cvsignore
@@ -0,0 +1 @@
+Makefile.in
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
new file mode 100644
index 00000000..28c582ad
--- /dev/null
+++ b/libdw/ChangeLog
@@ -0,0 +1,512 @@
+2005-07-23 Ulrich Drepper <drepper@redhat.com>
+
+ * dwarf_error.c: Add internal alias for dwarf_errno.
+ * libdwP.h: Declare __dwarf_errno_internal.
+ * dwarf_getloclist.c: Use INTDEF for dwarf_errno.
+
+ * dwarf_error.c [USE_TLS]: Actually use __thread in definition of
+ global_error.
+
+2005-06-01 Roland McGrath <roland@redhat.com>
+
+ * dwarf_getaranges.c (dwarf_getaranges): Sort result array.
+ * dwarf_getarange_addr.c (dwarf_getarange_addr): Use binary search.
+
+2005-06-08 Roland McGrath <roland@redhat.com>
+
+ * memory-access.h (get_uleb128_step, get_uleb128): Remove casts.
+ (get_sleb128_step, get_sleb128): Likewise.
+ * dwarf_getattrs.c (dwarf_getattrs): Add consts.
+ * dwarf_getloclist.c (getloclist): Likewise.
+ * dwarf_formblock.c (dwarf_formblock): Likewise.
+ * dwarf_getsrclines.c (dwarf_getsrclines): Likewise.
+ * dwarf_getabbrevattr.c (dwarf_getabbrevattr): Likewise.
+ * dwarf_formref.c (dwarf_formref): Likewise.
+ * dwarf_formsdata.c (dwarf_formsdata): Likewise.
+ * dwarf_formudata.c (dwarf_formudata): Likewise.
+ * dwarf_haschildren.c (dwarf_haschildren): Likewise.
+ * dwarf_child.c (__libdw_find_attr, __libdw_find_attr): Likewise.
+ * dwarf_tag.c (dwarf_tag): Likewise.
+ * dwarf_getabbrev.c (__libdw_getabbrev): Likewise.
+ * memory-access.c (__libdw_get_uleb128, __libdw_get_sleb128): Likewise.
+ * libdw_form.c (__libdw_form_val_len): Likewise.
+ * libdwP.h: Update decl.
+
+2005-06-04 Roland McGrath <roland@redhat.com>
+
+ * memory-access.h (get_uleb128_rest_return): New macro.
+ [! IS_LIBDW] (__libdw_get_uleb128): New static, defined using it.
+ (get_sleb128_rest_return): New macro.
+ [! IS_LIBDW] (__libdw_get_sleb128): New static, defined using it.
+ * memory-access.c: New file.
+ * Makefile.am (libdw_a_SOURCES): Add it.
+ (DEFS): Add -DIS_LIBDW.
+
+2005-05-31 Roland McGrath <roland@redhat.com>
+
+ * dwarf_formref_die.c (dwarf_formref_die): Add CU header offset to
+ formref offset.
+
+2005-05-30 Roland McGrath <roland@redhat.com>
+
+ * dwarf_getloclist.c (dwarf_addrloclists): Use DW_AT_entry_pc for base
+ address if DW_AT_low_pc is missing. Not to spec, but GCC generates it.
+
+ * dwarf_getloclist.c (dwarf_addrloclists): Don't sign-extend 4-byte
+ BEGIN value. Instead, match base address entries separately for
+ 32/64 size cases.
+
+2005-05-28 Roland McGrath <roland@redhat.com>
+
+ * dwarf_getloclist.c (dwarf_addrloclists): Fix decoding to advance
+ past location expression contents.
+
+2005-05-23 Roland McGrath <roland@redhat.com>
+
+ * dwarf_getsrclines.c: Comment typo fix.
+
+ * dwarf_haspc.c (dwarf_haspc): Fix CU DIE address calculation.
+ * dwarf_getloclist.c (dwarf_addrloclists): Likewise.
+
+2005-05-22 Ulrich Drepper <drepper@redhat.com>
+
+ * libdwP.h: Only use INTDECL for alias prototypes.
+
+2005-05-19 Roland McGrath <roland@redhat.com>
+
+ * dwarf_getloclist.c (attr_ok): Permit DW_AT_static_link too.
+
+ * dwarf_getscopevar.c: New file.
+ * Makefile.am (libdw_a_SOURCES): Add it.
+ * libdw.h: Declare dwarf_getscopevar.
+
+ * dwarf_getsrcfiles.c: Add INTDEF.
+ * dwarf_haschildren.c: Likewise.
+ * libdwP.h (dwarf_getsrcfiles, dwarf_haschildren): Add INTDECL.
+
+ * dwarf_getscopes.c: New file.
+ * Makefile.am (libdw_a_SOURCES): Add it.
+ * libdw.h: Declare dwarf_getscopes.
+ * libdw.map: Add it.
+
+2005-05-18 Roland McGrath <roland@redhat.com>
+
+ * libdwP.h (IDX_debug_ranges): New enum constant.
+ * dwarf_begin_elf.c (dwarf_scnnames): Add it for ".debug_ranges".
+ * libdwP.h (DWARF_E_NO_DEBUG_RANGES): New enum constant.
+ * dwarf_error.c (errmsgs): Add it.
+ * dwarf_haspc.c: New file.
+ * libdw.h: Declare dwarf_haspc.
+ * libdw.map: Add it.
+ * libdwP.h: Add INTDECL.
+
+ * dwarf_attr_integrate.c: New file.
+ * dwarf_hasattr_integrate.c: New file.
+ * Makefile.am (libdw_a_SOURCES): Add them.
+ * libdw.h: Declare dwarf_attr_integrate, dwarf_hasattr_integrate.
+ * libdw.map: Add them.
+
+ * dwarf_hasattr.c: Add INTDEF.
+ * libdwP.h: Add INTDECL for it.
+
+ * dwarf_formref_die.c: New file.
+ * Makefile.am (libdw_a_SOURCES): Add it.
+ * libdw.h (dwarf_formref_die): Declare it.
+ * libdwP.h (dwarf_formref_die): Add INTDECL.
+ * libdw.map: Add it.
+
+ * dwarf_getloclist.c (attr_ok, getloclist): New functions, broken out
+ of ...
+ (dwarf_getloclist): ... here. Call them.
+ (dwarf_addrloclists): New function.
+ * libdw.h: Declare it.
+ * libdw.map: Add it.
+
+ * dwarf_getmacros.c (dwarf_getmacros): Don't bail at
+ DW_MACINFO_end_file. Recognize type 0 as terminator.
+
+2005-05-05 Roland McGrath <roland@redhat.com>
+
+ * dwarf_getsrc_die.c (dwarf_getsrc_die): Use binary search.
+
+ * dwarf_getsrclines.c (dwarf_getsrclines): Sort result array, since
+ the line program does not produce all entries in ascending order.
+
+2005-04-25 Ulrich Drepper <drepper@redhat.com>
+
+ * dwarf_getsrc_file.c (dwarf_getsrc_file): Handle multiple
+ occurences (e.g., inlines) better.
+
+2005-04-24 Ulrich Drepper <drepper@redhat.com>
+
+ * libdw.h (DWARF_END_ABBREV): Define.
+ * dwarf_getabbrev.c (__libdw_getabbrev): Return DWARF_END_ABBREV if
+ end is reached.
+ * dwarf_offabbrev.c (dwarf_offabbrev): Return -1 on error, 1 if end
+ of records reached.
+ * dwarf_tag.c (__libdw_findabbrev): Also recognize DWARF_END_ABBREV
+ as error of __libdw_getabbrev.
+
+2005-04-04 Ulrich Drepper <drepper@redhat.com>
+
+ * dwarf_getsrc_file.c (dwarf_getsrc_file): Minor optimization.
+
+ * dwarf_getsrc_file.c (dwarf_getsrc_file): Always pass number of
+ results back to caller.
+
+2005-04-04 Roland McGrath <roland@redhat.com>
+
+ * dwarf_getsrc_file.c (dwarf_getsrc_file): Use size_t for CUHL.
+
+ * dwarf_func_line.c (__libdw_func_intval): Use internal_function in
+ defn.
+
+2005-04-04 Ulrich Drepper <drepper@redhat.com>
+
+ * dwarf_getsrc_file.c (dwarf_getsrc_file): Use INTUSE.
+
+ * dwarf_getsrc_file.c: New file.
+ * Makefile.am (libdw_a_SOURCES): Add dwarf_getsrc_file.c.
+ * libdw.h: Declare dwarf_getsrc_file.
+ * libdw.map: Add dwarf_getsrc_file.
+
+2005-04-02 Ulrich Drepper <drepper@redhat.com>
+
+ * dwarf_func_entrypc.c: New file.
+ * dwarf_func_col.c: New file.
+ * dwarf_func_line.c: New file.
+ * dwarf_func_file.c: New file.
+ * libdw.h: Add prototypes for new functions.
+ * libdw.map: Add dwarf_func_entrypc, dwarf_func_col, dwarf_func_line,
+ dwarf_func_file.
+ * Makefile.am (libdw_a_SOURCES): Add dwarf_func_entrypc.c,
+ dwarf_func_col.c, dwarf_func_line.c, dwarf_func_file.c.
+ * libdwP.h (struct Dwarf_Func_s): Add cudie element.
+ Declare __libdw_func_intval and __dwarf_formsdata_internal.
+ * dwarf_getfuncs.c: Also fill in cudie in Dwarf_Func object.
+ * dwarf_formsdata.c: Use INTUSE and INTDEF to avoid PLTs.
+
+ * dwarf.h: Add some DWARF3 definitions.
+
+2005-04-01 Ulrich Drepper <drepper@redhat.com>
+
+ * dwarf_getfuncs.c: New file.
+ * dwarf_func_highpc.c: New file.
+ * dwarf_func_lowpc.c: New file.
+ * dwarf_func_name.c: New file.
+ * Makefile.am (libdw_a_SOURCES): Add dwarf_getfuncs.c,
+ dwarf_func_highpc.c, dwarf_func_lowpc.c, and dwarf_func_name.c.
+ * libdw.map: Add dwarf_getfuncs, dwarf_func_highpc, dwarf_func_lowpc,
+ and dwarf_func_name.
+ * libdw.h: Add prototypes for new functions.
+ * dwarf_child.c: Use INTUSE and INTDEF to avoid PLTs.
+ * dwarf_siblingof.c: Likewise.
+ * dwarf_dieoffset.c: Likewise.
+ * dwarf_highpc.c: Likewise.
+ * dwarf_lowpc.c: Likewise.
+ * libdwP.h: Add prototypes for internal functions.
+ Define Dwarf_Func_s structure.
+
+2005-03-29 Ulrich Drepper <drepper@redhat.com>
+
+ * libdw.h: Add padding in Dwarf_die.
+
+ * dwarf_arrayorder.c: Use INTUSE and INTDEF to avoid PLTs.
+ * dwarf_attr.c: Likewise.
+ * dwarf_begin.c: Likewise.
+ * dwarf_begin_elf.c: Likewise.
+ * dwarf_bitoffset.c: Likewise.
+ * dwarf_bitsize.c: Likewise.
+ * dwarf_bytesize.c: Likewise.
+ * dwarf_diename.c: Likewise.
+ * dwarf_formaddr.c: Likewise.
+ * dwarf_formblock.c: Likewise.
+ * dwarf_formref.c: Likewise.
+ * dwarf_formstring.c: Likewise.
+ * dwarf_formudata.c: Likewise.
+ * dwarf_getarange_addr.c: Likewise.
+ * dwarf_getarangeinfo.c: Likewise.
+ * dwarf_getaranges.c: Likewise.
+ * dwarf_getloclist.c: Likewise.
+ * dwarf_getmacros.c: Likewise.
+ * dwarf_getsrc_die.c: Likewise.
+ * dwarf_getsrcfiles.c: Likewise.
+ * dwarf_getsrclines.c: Likewise.
+ * dwarf_highpc.c: Likewise.
+ * dwarf_lowpc.c: Likewise.
+ * dwarf_nextcu.c: Likewise.
+ * dwarf_offdie.c: Likewise.
+ * dwarf_siblingof.c: Likewise.
+ * dwarf_srclang.c: Likewise.
+ * dwarf_tag.c: Likewise.
+ * libdw_findcu.c: Likewise.
+ * libdwP.h: Add prototypes for internal functions.
+
+ * dwarf_addrdie.c: New file.
+ * dwarf_macro_opcode.c: New file.
+ * dwarf_macro_param1.c: New file.
+ * dwarf_macro_param2.c: New file.
+ * libdw.h: Add declarations. Move Dwarf_Macro definition to libdwP.h.
+ * libdwP.h: Remove Dwarf_Macro definition.
+ * Makefile.am (libdw_a_SOURCES): Add dwarf_addrdie.c,
+ dwarf_macro_opcode.c, dwarf_macro_param1.c, and dwarf_macro_param2.c.
+ * libdw.map: Add entries for new functions.
+
+2005-03-21 Ulrich Drepper <drepper@redhat.com>
+
+ * libdw.h: Handle broken gcc < 4.
+
+2005-02-15 Ulrich Drepper <drepper@redhat.com>
+
+ * Makefile (AM_CFLAGS): Add -Wunused -Wextra -Wformat=2.
+
+ * dwarf_begin_elf.c: Fix warnings.
+ * dwarf_dieoffset.c: Likewise.
+ * dwarf_end.c: Likewise.
+ * dwarf_error.c: Likewise.
+ * dwarf_getpubnames.c: Likewise.
+
+ * libdwP.h: Add new error values.
+ * dwarf_error.c: Support new error values.
+ * dwarf_getpubnames.c: Check parameter value.
+
+2005-02-05 Ulrich Drepper <drepper@redhat.com>
+
+ * Makefile.am: Check for text relocations in constructed DSO.
+
+ * Makefile.am [MUDFLAP] (AM_CFLAGS): Add -fmudflap.
+
+2005-02-04 Ulrich Drepper <drepper@redhat.com>
+
+ * dwarf_siblingof.c (dwarf_siblingof): Add some buffer boundary
+ checks to not read over buffer boundaries for ill-formed DWARF data.
+
+2004-09-25 Ulrich Drepper <drepper@redhat.com>
+
+ * dwarf_child.c: Make compile with gcc 4.0.
+ * dwarf_error.c: Likewise.
+ * dwarf_formblock.c: Likewise.
+ * dwarf_getabbrev.c: Likewise.
+ * dwarf_getattrs.c: Likewise.
+ * dwarf_getsrclines.c: Likewise.
+ * dwarf_tag.c: Likewise.
+ * libdw_form.c: Likewise.
+
+2004-01-20 Ulrich Drepper <drepper@redhat.com>
+
+ * Makefile.am: Support building with mudflap.
+
+ * dwarf_getloclist.c: Fix warnings gcc 3.4 spits out.
+ * dwarf_getsrclines.c: Likewise.
+ * dwarf_memory-access.h: Likewise.
+
+2004-01-19 Ulrich Drepper <drepper@redhat.com>
+
+ * dwarf_getsrcfiles.c: Third parameter can be NULL.
+
+ * libdw.h: Define Dwarf_macro. Declare dwarf_getmacros.
+ Third parameter of dwarf_getsrcfiles can be NULL.
+
+ * libdw.map: Add dwarf_getmacros.
+ * Makefile.am (libdw_a_SOURCES): Add dwarf_getmacros.
+ * dwarf_getmacros.c: New file.
+
+2004-01-18 Ulrich Drepper <drepper@redhat.com>
+
+ * libdw.h: Second parameter of dwarf_getaranges can be NULL.
+
+ * dwarf_nextcu.c: Return -1 if dwarf parameter is NULL.
+
+ * dwarf_getsrclines.c:
+ Use read_2ubyte_unaligned_inc instead of _inc-less variant.
+
+ * dwarf_getaranges.c: Allow naranges parameter to be NULL.
+
+ * libdwP.h (_): Use elfutils domain.
+
+ * dwarf_getsrclines.c (dwarf_getsrclines): Add more branch prediction.
+
+ * dwarf_getsrclines.c: Fix typo in comment.
+
+2004-01-17 Ulrich Drepper <drepper@redhat.com>
+
+ * Makefile.am: Support building with mudflap.
+
+2004-01-16 Ulrich Drepper <drepper@redhat.com>
+
+ * memory-access.h: Add lots of const in case a pointer passed is const.
+
+ * dwarf_formflag.c: New file.
+ * dwarf_getattrs.c: New file.
+ * dwarf_error.c: Add new error value.
+ * libdw.h: Add prototypes for new functions. Adjust prototype for
+ dwarf_getpubnames.
+ * libdw.map: Add new functions.
+ * dwarf_getpubnames.c: Change type of return value and fourth parameter
+ to ptrdiff_t.
+ * libdwP.h: Add new error value.
+ * Makefile.am (libdw_a_SOURCES): Add dwarf_getattrs.c and
+ dwarf_formflag.c.
+
+ * dwarf_getpubnames.c (dwarf_getpubnames): Just fail if dbg is NULL.
+
+2004-01-12 Ulrich Drepper <drepper@redhat.com>
+
+ * dwarf_getarange_addr.c: New file
+ * dwarf_getarangeinfo.c: New file.
+ * dwarf_getaranges.c: New file.
+ * dwarf_onerange.c: New file.
+ * libdw.h: Declare new functions. Define Dwarf_Arange and
+ Dwarf_Aranges.
+ * libdw.map: Add new functions.
+ * libdwP.h: Add new errors. Add aranges member to struct Dwarf.
+ Define Dwarf_Aranges_s and Dwarf_Arange_s.
+ * Makefile.am (libdw_a_SOURCES): Add dwarf_getaranges.c,
+ dwarf_onearange.c, dwarf_getarangeinfo.c, dwarf_getarange_addr.c.
+ * dwarf_error.c: Add new message.
+
+2004-01-11 Ulrich Drepper <drepper@redhat.com>
+
+ * Makefile.am (libdw_a_SOURCES): Add dwarf_lineaddr.c, dwarf_linecol.c,
+ dwarf_linebeginstatement.c, dwarf_lineendsequence.c, dwarf_lineblock.c,
+ dwarf_lineprologueend.c, dwarf_lineepiloguebegin.c, dwarf_onesrcline.c.
+ * dwarf_error.c: Add another message.
+ * dwarf_getsrc_die.c: Adjust for Dwarf_Files and Dwarf_Lines
+ introduction.
+ * dwarf_filesrc.c: Likewise.
+ * dwarf_getsrcfiles.c: Likewise.
+ * dwarf_getsrclines.c: Likewise.
+ * dwarf_lineaddr.c: New file.
+ * dwarf_linebeginstatement.c: New file.
+ * dwarf_lineblock.c: New file.
+ * dwarf_linecol.c: New file.
+ * dwarf_lineendsequence.c: New file.
+ * dwarf_lineepiloguebegin.c: New file.
+ * dwarf_lineno.c: New file.
+ * dwarf_lineprologueend.c: New file.
+ * dwarf_onesrcline.c: New file.
+ * dwarf_lineno.c: Change interface to store result in object pointed
+ to by second parameter.
+ * libdw.h: Add prototypes for new functions. Change dwarf_lineno
+ prototype. Define Dwarf_Files and Dwarf_Lines.
+ * libdw.map: Add new functions.
+ * libdwP.h: Define Dwarf_Files_s and Dwarf_Lines_s.
+ * libdw_findcu.c: Don't initialize nlines field.
+
+ * dwarf_siblingof: Little optimization.
+
+ * dwarf_begin.c: Remember that the ELF descriptor must be closed.
+ * dwarf_end.c: Close ELF descriptor if free_elf is set.
+ * libdwP.h (struct Dwarf): Add free_elf field.
+
+ * Makefile.am (libdw_a_SOURCES): Add dwarf_getstring.c and
+ dwarf_offabbrev.c.
+ * dwarf_getstring.c: New file.
+ * dwarf_offabbrev.c: New file.
+ * libdw.map: Add dwarf_getstring and dwarf_offabbrev.
+ * dwarf_getabbrev.c (__libdw_getabbrev): Add new dbg and result
+ parameters. Don't allocate memory if not necessary and don't lookup
+ previous results if no CU given.
+ (dwarf_getabbrev): Adjust call to __libdw_getabbrev.
+ * dwarf_tag.c: Adjust call to __libdw_getabbrev.
+ * libdw.h: Declare dwarf_offabbrev and dwarf_getstring.
+ * libdwP.h: Change prototype for __libdw_getabbrev.
+
+ * dwarf_getabbrevattr.c: Add offsetp parameter. Fill in before
+ returning if this is wanted.
+
+2004-01-09 Ulrich Drepper <drepper@redhat.com>
+
+ * dwarf_nextcu.c: Add new parameter offset_sizep. Initialize it
+ with offset_size value.
+ * libdw.h: Adjust dwarf_nextcu prototype.
+ * libdwP.h (struct Dwarf_CU): Add offset_size member.
+ * libdw_findcu.c: Adjust dwarf_nextcu call. Initialize offset_size
+ member of new CU struct.
+ * dwarf_formstring.c: Depend on offset_size not address_size for
+ DW_FORM_strp handling.
+ * dwarf_form.c: Likewise for DW_FORM_strp and DW_FORM_ref_addr.
+
+ * dwarf_tag.c (__libdw_findabbrev): Return correct value for
+ failing lookup.
+ (dwarf_tag): Correctly recognize failed lookup.
+
+ * dwarf_end.c (cu_free): Call tdestroy for locs member. Use new
+ function noop_free.
+ * dwarf_error.c: Add message for DWARF_E_NO_BLOCK.
+ * dwarf_formblock.c: New file.
+ * dwarf_getloclist.c: Rewrite to handle a single block.
+ * libdw.h: Define Dwarf_Block. Rename Dwarf_Loc members. Remove
+ Dwarf_Locdesc definition. Declare dwarf_formblock. Remove
+ dwarf_getloclistent declaration.
+ * libdw.map: Add dwarf_formblock, remove dwarf_getloclistent.
+ * libdwP.h: Define struct loc_s and DWARF_E_NO_BLOCK.
+ Add locs member to struct Dwarf_CU.
+ * libdw_fundcu.c: Initialize locs member of new CU.
+ * Makefile.am (libdw_a_SOURCES): Add dwarf_formblock.c.
+ Remove dwarf_getloclistent.c.
+
+2004-01-07 Ulrich Drepper <drepper@redhat.com>
+
+ * libdw.h: Use __nonnull__ attribute only for gcc >= 3.3.
+ * libdwP.h: Likewise.
+
+ * dwarf_getloclist.c: New file.
+ * dwarf_getloclistent.c: New file.
+ * libdw.h: Define Dwarf_Loc and Dwarf_Locdesc.
+ Declare dwarf_getloclistent and dwarf_getloclist.
+ * libdw.map: Add dwarf_getloclistent and dwarf_getloclist.
+ * libdwP.h: Define DWARF_E_NO_LOCLIST.
+ * Makefile.am (libdw_a_SOURCES): Add dwarf_getloclistent.c and
+ dwarf_getloclist.c.
+
+ * dwarf_error.c: More error messages.
+
+2004-01-06 Ulrich Drepper <drepper@redhat.com>
+
+ * dwarf_getsrclines.c: Remove debugging support.
+
+ * dwarf_getsrcfiles.c: New file.
+ * dwarf_filesrc.c: New file.
+ * libdw.h: Declare these functions. Define Dwarf_File.
+ * libdwP.c: Adjust Dwarf_File_s definition.
+ * libdw.map: Add these functions.
+ * Makefile.am (libdw_a_SOURCES): Add dwarf_getsrcfiles.c and
+ dwarf_filesrc.c.
+ * dwarf_getsrclines.c: Initialize cu->files.
+
+2004-01-05 Ulrich Drepper <drepper@redhat.com>
+
+ * libdw.h: Add more nonnull function attributes.
+
+ * dwarf_begin_elf.c (dwarf_begin_elf): Don't initialize mem_tail->next.
+ * dwarf_end.c (cu_free): New function.
+ (dwarf_end): Also free CU tree. Correct freeing of memory blocks.
+ * dwarf_error.c (errmsgs): Add new messages.
+ * dwarf_getsrc_die.c: New file.
+ * dwarf_getsrclines.c: New file.
+ * dwarf_lineno.c: New file.
+ * dwarf_linesrc.c: New file.
+ * dwarf_nextcu.c (dwarf_nextcu): Use read_*byte_unaligned_inc
+ instead of the *_inc-less variants.
+ * libdw.h: Define Dwarf_Line. Add some function attributes. Declare
+ dwarf_getsrclines, dwarf_getsrc_die, dwarf_lineno, and dwarf_linesrc.
+ * libdw.map: Add dwarf_getsrclines, dwarf_getsrc_die, dwarf_lineno,
+ and dwarf_linesrc.
+ * libdwP.h: Add more error codes.
+ (struct Dwarf): Remove mem_tail.next member.
+ (Dwarf_File): Define type.
+ (struct Dwarf_Line_s): Define type.
+ (struct Dwarf_CU): Add lines and nlines members.
+ (libdw_alloc): Define local variable _tail and use it.
+ Add some function attributes.
+ * libdw_alloc.c (__libdw_allocate): Don't initialize next member.
+ * libdw_findcu.c (__libdw_findcu): Initialize lines and nlines members.
+ * memory-access.h: Add unlikely for the endian conversion paths.
+ * Makefile.am (AM_CFLAGS): Add -std parameter.
+ (libdw_a_SOURCES): Add dwarf_getsrclines, dwarf_getsrc_die,
+ dwarf_lineno, and dwarf_linesrc.
+
+2003-08-11 Ulrich Drepper <drepper@redhat.com>
+
+ * Moved to CVS archive.
diff --git a/libdw/Makefile.am b/libdw/Makefile.am
new file mode 100644
index 00000000..17be31dd
--- /dev/null
+++ b/libdw/Makefile.am
@@ -0,0 +1,108 @@
+## Process this file with automake to create Makefile.in
+##
+## Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc.
+##
+## This program is Open Source software; you can redistribute it and/or
+## modify it under the terms of the Open Software License version 1.0 as
+## published by the Open Source Initiative.
+##
+## You should have received a copy of the Open Software License along
+## with this program; if not, you may obtain a copy of the Open Software
+## License version 1.0 from http://www.opensource.org/licenses/osl.php or
+## by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+## 3001 King Ranch Road, Ukiah, CA 95482.
+##
+DEFS = -D_GNU_SOURCE -DHAVE_CONFIG_H -DIS_LIBDW
+if MUDFLAP
+AM_CFLAGS = -fmudflap
+else
+AM_CFLAGS =
+endif
+AM_CFLAGS += -Wall -Werror -Wshadow -Wunused -Wformat=2 -Wextra -std=gnu99
+INCLUDES = -I. -I$(srcdir) -I$(srcdir)/../libelf -I.. -I$(srcdir)/../lib
+VERSION = 1
+
+lib_LIBRARIES = libdw.a
+if !MUDFLAP
+noinst_LIBRARIES = libdw_pic.a
+noinst_PROGRAMS = $(noinst_LIBRARIES:_pic.a=.so)
+endif
+
+include_HEADERS = dwarf.h
+euincludedir = ${includedir}/elfutils
+euinclude_HEADERS = libdw.h
+
+libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \
+ dwarf_getpubnames.c dwarf_getabbrev.c dwarf_tag.c \
+ dwarf_error.c dwarf_nextcu.c dwarf_diename.c dwarf_offdie.c \
+ dwarf_attr.c dwarf_formstring.c dwarf_abbrev_hash.c \
+ dwarf_attr_integrate.c dwarf_hasattr_integrate.c \
+ dwarf_child.c dwarf_haschildren.c dwarf_formaddr.c \
+ dwarf_formudata.c dwarf_formsdata.c dwarf_lowpc.c \
+ dwarf_haspc.c dwarf_highpc.c \
+ dwarf_formref.c dwarf_formref_die.c dwarf_siblingof.c \
+ dwarf_dieoffset.c dwarf_cuoffset.c dwarf_hasattr.c \
+ dwarf_hasform.c dwarf_whatform.c dwarf_whatattr.c \
+ dwarf_bytesize.c dwarf_arrayorder.c dwarf_bitsize.c \
+ dwarf_bitoffset.c dwarf_srclang.c dwarf_getabbrevtag.c \
+ dwarf_getabbrevcode.c dwarf_abbrevhaschildren.c \
+ dwarf_getattrcnt.c dwarf_getabbrevattr.c \
+ dwarf_getsrclines.c dwarf_getsrc_die.c \
+ dwarf_getscopes.c dwarf_getscopevar.c \
+ dwarf_linesrc.c dwarf_lineno.c dwarf_lineaddr.c \
+ dwarf_linecol.c dwarf_linebeginstatement.c \
+ dwarf_lineendsequence.c dwarf_lineblock.c \
+ dwarf_lineprologueend.c dwarf_lineepiloguebegin.c \
+ dwarf_onesrcline.c dwarf_formblock.c \
+ dwarf_getsrcfiles.c dwarf_filesrc.c \
+ dwarf_getloclist.c dwarf_getstring.c dwarf_offabbrev.c \
+ dwarf_getaranges.c dwarf_onearange.c dwarf_getarangeinfo.c \
+ dwarf_getarange_addr.c dwarf_getattrs.c dwarf_formflag.c \
+ dwarf_getmacros.c dwarf_macro_opcode.c dwarf_macro_param1.c \
+ dwarf_macro_param2.c dwarf_addrdie.c \
+ dwarf_getfuncs.c dwarf_func_name.c dwarf_func_lowpc.c \
+ dwarf_func_highpc.c dwarf_func_entrypc.c dwarf_func_file.c \
+ dwarf_func_line.c dwarf_func_col.c dwarf_getsrc_file.c \
+ libdw_findcu.c libdw_form.c libdw_alloc.c memory-access.c
+
+
+if !MUDFLAP
+libdw_pic_a_SOURCES =
+am_libdw_pic_a_OBJECTS = $(libdw_a_SOURCES:.c=.os)
+
+libdw_so_SOURCES =
+libdw.so: libdw_pic.a $(srcdir)/libdw.map
+ $(CC) -shared -o $@ -Wl,--whole-archive,$<,--no-whole-archive \
+ -Wl,--version-script,$(srcdir)/libdw.map,--no-undefined \
+ -Wl,--soname,$@.$(VERSION),-z,defs \
+ ../libelf/libelf.so
+ if readelf -d $@ | fgrep -q TEXTREL; then exit 1; fi
+ ln -fs $@ $@.$(VERSION)
+
+
+%.os: %.c %.o
+ if $(COMPILE) -c -o $@ -fpic -DPIC -DSHARED -MT $@ -MD -MP \
+ -MF "$(DEPDIR)/$*.Tpo" `test -f '$<' || echo '$(srcdir)/'`$<; \
+ then cat "$(DEPDIR)/$*.Tpo" >> "$(DEPDIR)/$*.Po"; \
+ rm -f "$(DEPDIR)/$*.Tpo"; \
+ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
+ fi
+
+install: install-am libdw.so
+ $(mkinstalldirs) $(DESTDIR)$(libdir)
+ $(INSTALL_PROGRAM) libdw.so $(DESTDIR)$(libdir)/libdw-$(PACKAGE_VERSION).so
+ ln -fs libdw-$(PACKAGE_VERSION).so $(DESTDIR)$(libdir)/libdw.so.$(VERSION)
+ ln -fs libdw.so.$(VERSION) $(DESTDIR)$(libdir)/libdw.so
+
+uninstall: uninstall-am
+ rm -f $(DESTDIR)$(libdir)/libdw-$(PACKAGE_VERSION).so
+ rm -f $(DESTDIR)$(libdir)/libdw.so.$(VERSION)
+ rm -f $(DESTDIR)$(libdir)/libdw.so
+ rmdir --ignore-fail-on-non-empty $(DESTDIR)$(includedir)/elfutils
+endif
+
+noinst_HEADERS = libdwP.h memory-access.h dwarf_abbrev_hash.h
+
+EXTRA_DIST = libdw.map
+
+CLEANFILES = $(am_libdw_pic_a_OBJECTS)
diff --git a/libdw/dwarf.h b/libdw/dwarf.h
new file mode 100644
index 00000000..ce011aac
--- /dev/null
+++ b/libdw/dwarf.h
@@ -0,0 +1,581 @@
+/* This file defines standard DWARF types, structures, and macros.
+ Copyright (C) 2000, 2002, 2005 Red Hat, Inc.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifndef _DWARF_H
+#define _DWARF_H 1
+
+/* DWARF tags. */
+enum
+ {
+ DW_TAG_array_type = 0x01,
+ DW_TAG_class_type = 0x02,
+ DW_TAG_entry_point = 0x03,
+ DW_TAG_enumeration_type = 0x04,
+ DW_TAG_formal_parameter = 0x05,
+ DW_TAG_imported_declaration = 0x08,
+ DW_TAG_label = 0x0a,
+ DW_TAG_lexical_block = 0x0b,
+ DW_TAG_member = 0x0d,
+ DW_TAG_pointer_type = 0x0f,
+ DW_TAG_reference_type = 0x10,
+ DW_TAG_compile_unit = 0x11,
+ DW_TAG_string_type = 0x12,
+ DW_TAG_structure_type = 0x13,
+ DW_TAG_subroutine_type = 0x15,
+ DW_TAG_typedef = 0x16,
+ DW_TAG_union_type = 0x17,
+ DW_TAG_unspecified_parameters = 0x18,
+ DW_TAG_variant = 0x19,
+ DW_TAG_common_block = 0x1a,
+ DW_TAG_common_inclusion = 0x1b,
+ DW_TAG_inheritance = 0x1c,
+ DW_TAG_inlined_subroutine = 0x1d,
+ DW_TAG_module = 0x1e,
+ DW_TAG_ptr_to_member_type = 0x1f,
+ DW_TAG_set_type = 0x20,
+ DW_TAG_subrange_type = 0x21,
+ DW_TAG_with_stmt = 0x22,
+ DW_TAG_access_declaration = 0x23,
+ DW_TAG_base_type = 0x24,
+ DW_TAG_catch_block = 0x25,
+ DW_TAG_const_type = 0x26,
+ DW_TAG_constant = 0x27,
+ DW_TAG_enumerator = 0x28,
+ DW_TAG_file_type = 0x29,
+ DW_TAG_friend = 0x2a,
+ DW_TAG_namelist = 0x2b,
+ DW_TAG_namelist_item = 0x2c,
+ DW_TAG_packed_type = 0x2d,
+ DW_TAG_subprogram = 0x2e,
+ DW_TAG_template_type_param = 0x2f,
+ DW_TAG_template_value_param = 0x30,
+ DW_TAG_thrown_type = 0x31,
+ DW_TAG_try_block = 0x32,
+ DW_TAG_variant_part = 0x33,
+ DW_TAG_variable = 0x34,
+ DW_TAG_volatile_type = 0x35,
+ DW_TAG_dwarf_procedure = 0x36,
+ DW_TAG_restrict_type = 0x37,
+ DW_TAG_interface_type = 0x38,
+ DW_TAG_namespace = 0x39,
+ DW_TAG_imported_module = 0x3a,
+ DW_TAG_unspecified_type = 0x3b,
+ DW_TAG_partial_unit = 0x3c,
+ DW_TAG_imported_unit = 0x3d,
+ DW_TAG_mutable_type = 0x3e,
+ DW_TAG_lo_user = 0x4080,
+ DW_TAG_MIPS_loop = 0x4081,
+ DW_TAG_format_label = 0x4101,
+ DW_TAG_function_template = 0x4102,
+ DW_TAG_class_template = 0x4103,
+ DW_TAG_hi_user = 0xffff
+ };
+
+
+/* Children determination encodings. */
+enum
+ {
+ DW_CHILDREN_no = 0,
+ DW_CHILDREN_yes = 1
+ };
+
+
+/* DWARF attributes encodings. */
+enum
+ {
+ DW_AT_sibling = 0x01,
+ DW_AT_location = 0x02,
+ DW_AT_name = 0x03,
+ DW_AT_ordering = 0x09,
+ DW_AT_subscr_data = 0x0a,
+ DW_AT_byte_size = 0x0b,
+ DW_AT_bit_offset = 0x0c,
+ DW_AT_bit_size = 0x0d,
+ DW_AT_element_list = 0x0f,
+ DW_AT_stmt_list = 0x10,
+ DW_AT_low_pc = 0x11,
+ DW_AT_high_pc = 0x12,
+ DW_AT_language = 0x13,
+ DW_AT_member = 0x14,
+ DW_AT_discr = 0x15,
+ DW_AT_discr_value = 0x16,
+ DW_AT_visibility = 0x17,
+ DW_AT_import = 0x18,
+ DW_AT_string_length = 0x19,
+ DW_AT_common_reference = 0x1a,
+ DW_AT_comp_dir = 0x1b,
+ DW_AT_const_value = 0x1c,
+ DW_AT_containing_type = 0x1d,
+ DW_AT_default_value = 0x1e,
+ DW_AT_inline = 0x20,
+ DW_AT_is_optional = 0x21,
+ DW_AT_lower_bound = 0x22,
+ DW_AT_producer = 0x25,
+ DW_AT_prototyped = 0x27,
+ DW_AT_return_addr = 0x2a,
+ DW_AT_start_scope = 0x2c,
+ DW_AT_stride_size = 0x2e,
+ DW_AT_upper_bound = 0x2f,
+ DW_AT_abstract_origin = 0x31,
+ DW_AT_accessibility = 0x32,
+ DW_AT_address_class = 0x33,
+ DW_AT_artificial = 0x34,
+ DW_AT_base_types = 0x35,
+ DW_AT_calling_convention = 0x36,
+ DW_AT_count = 0x37,
+ DW_AT_data_member_location = 0x38,
+ DW_AT_decl_column = 0x39,
+ DW_AT_decl_file = 0x3a,
+ DW_AT_decl_line = 0x3b,
+ DW_AT_declaration = 0x3c,
+ DW_AT_discr_list = 0x3d,
+ DW_AT_encoding = 0x3e,
+ DW_AT_external = 0x3f,
+ DW_AT_frame_base = 0x40,
+ DW_AT_friend = 0x41,
+ DW_AT_identifier_case = 0x42,
+ DW_AT_macro_info = 0x43,
+ DW_AT_namelist_items = 0x44,
+ DW_AT_priority = 0x45,
+ DW_AT_segment = 0x46,
+ DW_AT_specification = 0x47,
+ DW_AT_static_link = 0x48,
+ DW_AT_type = 0x49,
+ DW_AT_use_location = 0x4a,
+ DW_AT_variable_parameter = 0x4b,
+ DW_AT_virtuality = 0x4c,
+ DW_AT_vtable_elem_location = 0x4d,
+ DW_AT_allocated = 0x4e,
+ DW_AT_associated = 0x4f,
+ DW_AT_data_location = 0x50,
+ DW_AT_stride = 0x51,
+ DW_AT_entry_pc = 0x52,
+ DW_AT_use_UTF8 = 0x53,
+ DW_AT_extension = 0x54,
+ DW_AT_ranges = 0x55,
+ DW_AT_trampoline = 0x56,
+ DW_AT_call_column = 0x57,
+ DW_AT_call_file = 0x58,
+ DW_AT_call_line = 0x59,
+ DW_AT_description = 0x5a,
+ DW_AT_lo_user = 0x2000,
+ DW_AT_MIPS_fde = 0x2001,
+ DW_AT_MIPS_loop_begin = 0x2002,
+ DW_AT_MIPS_tail_loop_begin = 0x2003,
+ DW_AT_MIPS_epilog_begin = 0x2004,
+ DW_AT_MIPS_loop_unroll_factor = 0x2005,
+ DW_AT_MIPS_software_pipeline_depth = 0x2006,
+ DW_AT_MIPS_linkage_name = 0x2007,
+ DW_AT_MIPS_stride = 0x2008,
+ DW_AT_MIPS_abstract_name = 0x2009,
+ DW_AT_MIPS_clone_origin = 0x200a,
+ DW_AT_MIPS_has_inlines = 0x200b,
+ DW_AT_MIPS_stride_byte = 0x200c,
+ DW_AT_MIPS_stride_elem = 0x200d,
+ DW_AT_MIPS_ptr_dopetype = 0x200e,
+ DW_AT_MIPS_allocatable_dopetype = 0x200f,
+ DW_AT_MIPS_assumed_shape_dopetype = 0x2010,
+ DW_AT_MIPS_assumed_size = 0x2011,
+ DW_AT_sf_names = 0x2101,
+ DW_AT_src_info = 0x2102,
+ DW_AT_mac_info = 0x2103,
+ DW_AT_src_coords = 0x2104,
+ DW_AT_body_begin = 0x2105,
+ DW_AT_body_end = 0x2106,
+ DW_AT_hi_user = 0x3fff
+ };
+
+
+/* DWARF form encodings. */
+enum
+ {
+ DW_FORM_addr = 0x01,
+ DW_FORM_block2 = 0x03,
+ DW_FORM_block4 = 0x04,
+ DW_FORM_data2 = 0x05,
+ DW_FORM_data4 = 0x06,
+ DW_FORM_data8 = 0x07,
+ DW_FORM_string = 0x08,
+ DW_FORM_block = 0x09,
+ DW_FORM_block1 = 0x0a,
+ DW_FORM_data1 = 0x0b,
+ DW_FORM_flag = 0x0c,
+ DW_FORM_sdata = 0x0d,
+ DW_FORM_strp = 0x0e,
+ DW_FORM_udata = 0x0f,
+ DW_FORM_ref_addr = 0x10,
+ DW_FORM_ref1 = 0x11,
+ DW_FORM_ref2 = 0x12,
+ DW_FORM_ref4 = 0x13,
+ DW_FORM_ref8 = 0x14,
+ DW_FORM_ref_udata = 0x15,
+ DW_FORM_indirect = 0x16
+ };
+
+
+/* DWARF location operation encodings. */
+enum
+ {
+ DW_OP_addr = 0x03, /* Constant address. */
+ DW_OP_deref = 0x06,
+ DW_OP_const1u = 0x08, /* Unsigned 1-byte constant. */
+ DW_OP_const1s = 0x09, /* Signed 1-byte constant. */
+ DW_OP_const2u = 0x0a, /* Unsigned 2-byte constant. */
+ DW_OP_const2s = 0x0b, /* Signed 2-byte constant. */
+ DW_OP_const4u = 0x0c, /* Unsigned 4-byte constant. */
+ DW_OP_const4s = 0x0d, /* Signed 4-byte constant. */
+ DW_OP_const8u = 0x0e, /* Unsigned 8-byte constant. */
+ DW_OP_const8s = 0x0f, /* Signed 8-byte constant. */
+ DW_OP_constu = 0x10, /* Unsigned LEB128 constant. */
+ DW_OP_consts = 0x11, /* Signed LEB128 constant. */
+ DW_OP_dup = 0x12,
+ DW_OP_drop = 0x13,
+ DW_OP_over = 0x14,
+ DW_OP_pick = 0x15, /* 1-byte stack index. */
+ DW_OP_swap = 0x16,
+ DW_OP_rot = 0x17,
+ DW_OP_xderef = 0x18,
+ DW_OP_abs = 0x19,
+ DW_OP_and = 0x1a,
+ DW_OP_div = 0x1b,
+ DW_OP_minus = 0x1c,
+ DW_OP_mod = 0x1d,
+ DW_OP_mul = 0x1e,
+ DW_OP_neg = 0x1f,
+ DW_OP_not = 0x20,
+ DW_OP_or = 0x21,
+ DW_OP_plus = 0x22,
+ DW_OP_plus_uconst = 0x23, /* Unsigned LEB128 addend. */
+ DW_OP_shl = 0x24,
+ DW_OP_shr = 0x25,
+ DW_OP_shra = 0x26,
+ DW_OP_xor = 0x27,
+ DW_OP_bra = 0x28, /* Signed 2-byte constant. */
+ DW_OP_eq = 0x29,
+ DW_OP_ge = 0x2a,
+ DW_OP_gt = 0x2b,
+ DW_OP_le = 0x2c,
+ DW_OP_lt = 0x2d,
+ DW_OP_ne = 0x2e,
+ DW_OP_skip = 0x2f, /* Signed 2-byte constant. */
+ DW_OP_lit0 = 0x30, /* Literal 0. */
+ DW_OP_lit1 = 0x31, /* Literal 1. */
+ DW_OP_lit2 = 0x32, /* Literal 2. */
+ DW_OP_lit3 = 0x33, /* Literal 3. */
+ DW_OP_lit4 = 0x34, /* Literal 4. */
+ DW_OP_lit5 = 0x35, /* Literal 5. */
+ DW_OP_lit6 = 0x36, /* Literal 6. */
+ DW_OP_lit7 = 0x37, /* Literal 7. */
+ DW_OP_lit8 = 0x38, /* Literal 8. */
+ DW_OP_lit9 = 0x39, /* Literal 9. */
+ DW_OP_lit10 = 0x3a, /* Literal 10. */
+ DW_OP_lit11 = 0x3b, /* Literal 11. */
+ DW_OP_lit12 = 0x3c, /* Literal 12. */
+ DW_OP_lit13 = 0x3d, /* Literal 13. */
+ DW_OP_lit14 = 0x3e, /* Literal 14. */
+ DW_OP_lit15 = 0x3f, /* Literal 15. */
+ DW_OP_lit16 = 0x40, /* Literal 16. */
+ DW_OP_lit17 = 0x41, /* Literal 17. */
+ DW_OP_lit18 = 0x42, /* Literal 18. */
+ DW_OP_lit19 = 0x43, /* Literal 19. */
+ DW_OP_lit20 = 0x44, /* Literal 20. */
+ DW_OP_lit21 = 0x45, /* Literal 21. */
+ DW_OP_lit22 = 0x46, /* Literal 22. */
+ DW_OP_lit23 = 0x47, /* Literal 23. */
+ DW_OP_lit24 = 0x48, /* Literal 24. */
+ DW_OP_lit25 = 0x49, /* Literal 25. */
+ DW_OP_lit26 = 0x4a, /* Literal 26. */
+ DW_OP_lit27 = 0x4b, /* Literal 27. */
+ DW_OP_lit28 = 0x4c, /* Literal 28. */
+ DW_OP_lit29 = 0x4d, /* Literal 29. */
+ DW_OP_lit30 = 0x4e, /* Literal 30. */
+ DW_OP_lit31 = 0x4f, /* Literal 31. */
+ DW_OP_reg0 = 0x50, /* Register 0. */
+ DW_OP_reg1 = 0x51, /* Register 1. */
+ DW_OP_reg2 = 0x52, /* Register 2. */
+ DW_OP_reg3 = 0x53, /* Register 3. */
+ DW_OP_reg4 = 0x54, /* Register 4. */
+ DW_OP_reg5 = 0x55, /* Register 5. */
+ DW_OP_reg6 = 0x56, /* Register 6. */
+ DW_OP_reg7 = 0x57, /* Register 7. */
+ DW_OP_reg8 = 0x58, /* Register 8. */
+ DW_OP_reg9 = 0x59, /* Register 9. */
+ DW_OP_reg10 = 0x5a, /* Register 10. */
+ DW_OP_reg11 = 0x5b, /* Register 11. */
+ DW_OP_reg12 = 0x5c, /* Register 12. */
+ DW_OP_reg13 = 0x5d, /* Register 13. */
+ DW_OP_reg14 = 0x5e, /* Register 14. */
+ DW_OP_reg15 = 0x5f, /* Register 15. */
+ DW_OP_reg16 = 0x60, /* Register 16. */
+ DW_OP_reg17 = 0x61, /* Register 17. */
+ DW_OP_reg18 = 0x62, /* Register 18. */
+ DW_OP_reg19 = 0x63, /* Register 19. */
+ DW_OP_reg20 = 0x64, /* Register 20. */
+ DW_OP_reg21 = 0x65, /* Register 21. */
+ DW_OP_reg22 = 0x66, /* Register 22. */
+ DW_OP_reg23 = 0x67, /* Register 24. */
+ DW_OP_reg24 = 0x68, /* Register 24. */
+ DW_OP_reg25 = 0x69, /* Register 25. */
+ DW_OP_reg26 = 0x6a, /* Register 26. */
+ DW_OP_reg27 = 0x6b, /* Register 27. */
+ DW_OP_reg28 = 0x6c, /* Register 28. */
+ DW_OP_reg29 = 0x6d, /* Register 29. */
+ DW_OP_reg30 = 0x6e, /* Register 30. */
+ DW_OP_reg31 = 0x6f, /* Register 31. */
+ DW_OP_breg0 = 0x70, /* Base register 0. */
+ DW_OP_breg1 = 0x71, /* Base register 1. */
+ DW_OP_breg2 = 0x72, /* Base register 2. */
+ DW_OP_breg3 = 0x73, /* Base register 3. */
+ DW_OP_breg4 = 0x74, /* Base register 4. */
+ DW_OP_breg5 = 0x75, /* Base register 5. */
+ DW_OP_breg6 = 0x76, /* Base register 6. */
+ DW_OP_breg7 = 0x77, /* Base register 7. */
+ DW_OP_breg8 = 0x78, /* Base register 8. */
+ DW_OP_breg9 = 0x79, /* Base register 9. */
+ DW_OP_breg10 = 0x7a, /* Base register 10. */
+ DW_OP_breg11 = 0x7b, /* Base register 11. */
+ DW_OP_breg12 = 0x7c, /* Base register 12. */
+ DW_OP_breg13 = 0x7d, /* Base register 13. */
+ DW_OP_breg14 = 0x7e, /* Base register 14. */
+ DW_OP_breg15 = 0x7f, /* Base register 15. */
+ DW_OP_breg16 = 0x80, /* Base register 16. */
+ DW_OP_breg17 = 0x81, /* Base register 17. */
+ DW_OP_breg18 = 0x82, /* Base register 18. */
+ DW_OP_breg19 = 0x83, /* Base register 19. */
+ DW_OP_breg20 = 0x84, /* Base register 20. */
+ DW_OP_breg21 = 0x85, /* Base register 21. */
+ DW_OP_breg22 = 0x86, /* Base register 22. */
+ DW_OP_breg23 = 0x87, /* Base register 23. */
+ DW_OP_breg24 = 0x88, /* Base register 24. */
+ DW_OP_breg25 = 0x89, /* Base register 25. */
+ DW_OP_breg26 = 0x8a, /* Base register 26. */
+ DW_OP_breg27 = 0x8b, /* Base register 27. */
+ DW_OP_breg28 = 0x8c, /* Base register 28. */
+ DW_OP_breg29 = 0x8d, /* Base register 29. */
+ DW_OP_breg30 = 0x8e, /* Base register 30. */
+ DW_OP_breg31 = 0x8f, /* Base register 31. */
+ DW_OP_regx = 0x90, /* Unsigned LEB128 register. */
+ DW_OP_fbreg = 0x91, /* Signed LEB128 register. */
+ DW_OP_bregx = 0x92, /* ULEB128 register followed by SLEB128 off. */
+ DW_OP_piece = 0x93, /* ULEB128 size of piece addressed. */
+ DW_OP_deref_size = 0x94, /* 1-byte size of data retrieved. */
+ DW_OP_xderef_size = 0x95, /* 1-byte size of data retrieved. */
+ DW_OP_nop = 0x96,
+ DW_OP_push_object_address = 0x97,
+ DW_OP_call2 = 0x98,
+ DW_OP_call4 = 0x99,
+ DW_OP_call_ref = 0x9a,
+
+ DW_OP_lo_user = 0xe0, /* Implementation-defined range start. */
+ DW_OP_hi_user = 0xff /* Implementation-defined range end. */
+ };
+
+
+/* DWARF base type encodings. */
+enum
+ {
+ DW_ATE_void = 0x0,
+ DW_ATE_address = 0x1,
+ DW_ATE_boolean = 0x2,
+ DW_ATE_complex_float = 0x3,
+ DW_ATE_float = 0x4,
+ DW_ATE_signed = 0x5,
+ DW_ATE_signed_char = 0x6,
+ DW_ATE_unsigned = 0x7,
+ DW_ATE_unsigned_char = 0x8,
+ DW_ATE_imaginary_float = 0x9,
+
+ DW_ATE_lo_user = 0x80,
+ DW_ATE_hi_user = 0xff
+ };
+
+
+/* DWARF accessibility encodings. */
+enum
+ {
+ DW_ACCESS_public = 1,
+ DW_ACCESS_protected = 2,
+ DW_ACCESS_private = 3
+ };
+
+
+/* DWARF visibility encodings. */
+enum
+ {
+ DW_VIS_local = 1,
+ DW_VIS_exported = 2,
+ DW_VIS_qualified = 3
+ };
+
+
+/* DWARF virtuality encodings. */
+enum
+ {
+ DW_VIRTUALITY_none = 0,
+ DW_VIRTUALITY_virtual = 1,
+ DW_VIRTUALITY_pure_virtual = 2
+ };
+
+
+/* DWARF language encodings. */
+enum
+ {
+ DW_LANG_C89 = 0x0001,
+ DW_LANG_C = 0x0002,
+ DW_LANG_Ada83 = 0x0003,
+ DW_LANG_C_plus_plus = 0x0004,
+ DW_LANG_Cobol74 = 0x0005,
+ DW_LANG_Cobol85 = 0x0006,
+ DW_LANG_Fortran77 = 0x0007,
+ DW_LANG_Fortran90 = 0x0008,
+ DW_LANG_Pascal83 = 0x0009,
+ DW_LANG_Modula2 = 0x000a,
+ DW_LANG_Java = 0x000b,
+ DW_LANG_C99 = 0x000c,
+ DW_LANG_Ada95 = 0x000d,
+ DW_LANG_Fortran95 = 0x000e,
+ DW_LANG_PL1 = 0x000f,
+ DW_LANG_lo_user = 0x8000,
+ DW_LANG_Mips_Assembler = 0x8001,
+ DW_LANG_hi_user = 0xffff
+ };
+
+
+/* DWARF identifier case encodings. */
+enum
+ {
+ DW_ID_case_sensitive = 0,
+ DW_ID_up_case = 1,
+ DW_ID_down_case = 2,
+ DW_ID_case_insensitive = 3
+ };
+
+
+/* DWARF calling conventions encodings. */
+enum
+ {
+ DW_CC_normal = 0x1,
+ DW_CC_program = 0x2,
+ DW_CC_nocall = 0x3,
+ DW_CC_lo_user = 0x40,
+ DW_CC_hi_user = 0xff
+ };
+
+
+/* DWARF inline encodings. */
+enum
+ {
+ DW_INL_not_inlined = 0,
+ DW_INL_inlined = 1,
+ DW_INL_declared_not_inlined = 2,
+ DW_INL_declared_inlined = 3
+ };
+
+
+/* DWARF ordering encodings. */
+enum
+ {
+ DW_ORD_row_major = 0,
+ DW_ORD_col_major = 1
+ };
+
+
+/* DWARF discriminant descriptor encodings. */
+enum
+ {
+ DW_DSC_label = 0,
+ DW_DSC_range = 1
+ };
+
+
+/* DWARF standard opcode encodings. */
+enum
+ {
+ DW_LNS_copy = 1,
+ DW_LNS_advance_pc = 2,
+ DW_LNS_advance_line = 3,
+ DW_LNS_set_file = 4,
+ DW_LNS_set_column = 5,
+ DW_LNS_negate_stmt = 6,
+ DW_LNS_set_basic_block = 7,
+ DW_LNS_const_add_pc = 8,
+ DW_LNS_fixed_advance_pc = 9,
+ DW_LNS_set_prologue_end = 10,
+ DW_LNS_set_epilog_begin = 11,
+ DW_LNS_set_isa = 12
+ };
+
+
+/* DWARF extended opcide encodings. */
+enum
+ {
+ DW_LNE_end_sequence = 1,
+ DW_LNE_set_address = 2,
+ DW_LNE_define_file = 3,
+
+ DW_LNE_lo_user = 128,
+ DW_LNE_hi_user = 255
+ };
+
+
+/* DWARF macinfo type encodings. */
+enum
+ {
+ DW_MACINFO_define = 1,
+ DW_MACINFO_undef = 2,
+ DW_MACINFO_start_file = 3,
+ DW_MACINFO_end_file = 4,
+ DW_MACINFO_vendor_ext = 255
+ };
+
+
+/* DWARF call frame instruction encodings. */
+enum
+ {
+ DW_CFA_advance_loc = 0x40,
+ DW_CFA_offset = 0x80,
+ DW_CFA_restore = 0xc0,
+ DW_CFA_extended = 0,
+
+ DW_CFA_nop = 0x00,
+ DW_CFA_set_loc = 0x01,
+ DW_CFA_advance_loc1 = 0x02,
+ DW_CFA_advance_loc2 = 0x03,
+ DW_CFA_advance_loc4 = 0x04,
+ DW_CFA_offset_extended = 0x05,
+ DW_CFA_restore_extended = 0x06,
+ DW_CFA_undefined = 0x07,
+ DW_CFA_same_value = 0x08,
+ DW_CFA_register = 0x09,
+ DW_CFA_remember_state = 0x0a,
+ DW_CFA_restore_state = 0x0b,
+ DW_CFA_def_cfa = 0x0c,
+ DW_CFA_def_cfa_register = 0x0d,
+ DW_CFA_def_cfa_offset = 0x0e,
+ DW_CFA_def_cfa_expression = 0x0f,
+ DW_CFA_expression = 0x10,
+ DW_CFA_offset_extended_sf = 0x11,
+ DW_CFA_def_cfa_sf = 0x12,
+ DW_CFA_def_cfa_offset_sf = 0x13,
+ DW_CFA_low_user = 0x1c,
+ DW_CFA_MIPS_advance_loc8 = 0x1d,
+ DW_CFA_GNU_window_save = 0x2d,
+ DW_CFA_GNU_args_size = 0x2e,
+ DW_CFA_high_user = 0x3f
+ };
+
+
+/* DWARF XXX. */
+#define DW_ADDR_none 0
+
+#endif /* dwarf.h */
diff --git a/libdw/dwarf_abbrev_hash.c b/libdw/dwarf_abbrev_hash.c
new file mode 100644
index 00000000..009e757f
--- /dev/null
+++ b/libdw/dwarf_abbrev_hash.c
@@ -0,0 +1,29 @@
+/* Implementation of hash table for DWARF .debug_abbrev section content.
+ Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define NO_UNDEF
+#include "libdwP.h"
+
+#define next_prime __libdwarf_next_prime
+extern size_t next_prime (size_t) attribute_hidden;
+
+#include <dynamicsizehash.c>
+
+#undef next_prime
+#define next_prime attribute_hidden __libdwarf_next_prime
+#include "../lib/next_prime.c"
diff --git a/libdw/dwarf_abbrev_hash.h b/libdw/dwarf_abbrev_hash.h
new file mode 100644
index 00000000..ef3cc48b
--- /dev/null
+++ b/libdw/dwarf_abbrev_hash.h
@@ -0,0 +1,24 @@
+/* Hash table for DWARF .debug_abbrev section content.
+ Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifndef _DWARF_ABBREV_HASH_H
+#define _DWARF_ABBREV_HASH_H 1
+
+#define NAME Dwarf_Abbrev_Hash
+#define TYPE Dwarf_Abbrev *
+#define COMPARE(a, b) (0)
+
+#include <dynamicsizehash.h>
+
+#endif /* dwarf_abbrev_hash.h */
diff --git a/libdw/dwarf_abbrevhaschildren.c b/libdw/dwarf_abbrevhaschildren.c
new file mode 100644
index 00000000..2261b2f3
--- /dev/null
+++ b/libdw/dwarf_abbrevhaschildren.c
@@ -0,0 +1,29 @@
+/* Return true if abbreviation is children flag set.
+ Copyright (C) 2003 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_abbrevhaschildren (abbrev)
+ Dwarf_Abbrev *abbrev;
+{
+ return abbrev == NULL ? -1 : abbrev->has_children;
+}
diff --git a/libdw/dwarf_addrdie.c b/libdw/dwarf_addrdie.c
new file mode 100644
index 00000000..c3fd4661
--- /dev/null
+++ b/libdw/dwarf_addrdie.c
@@ -0,0 +1,39 @@
+/* Return CU DIE containing given address.
+ Copyright (C) 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+Dwarf_Die *
+dwarf_addrdie (dbg, addr, result)
+ Dwarf *dbg;
+ Dwarf_Addr addr;
+ Dwarf_Die *result;
+{
+ Dwarf_Aranges *aranges;
+ size_t naranges;
+ Dwarf_Off off;
+
+ if (INTUSE(dwarf_getaranges) (dbg, &aranges, &naranges) != 0
+ || INTUSE(dwarf_getarangeinfo) (INTUSE(dwarf_getarange_addr) (aranges,
+ addr),
+ NULL, NULL, &off) != 0)
+ return NULL;
+
+ return INTUSE(dwarf_offdie) (dbg, off, result);
+}
diff --git a/libdw/dwarf_arrayorder.c b/libdw/dwarf_arrayorder.c
new file mode 100644
index 00000000..a1ea09fa
--- /dev/null
+++ b/libdw/dwarf_arrayorder.c
@@ -0,0 +1,33 @@
+/* Return array order attribute of DIE.
+ Copyright (C) 2003, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_arrayorder (die)
+ Dwarf_Die *die;
+{
+ Dwarf_Attribute attr_mem;
+ Dwarf_Word value;
+
+ return INTUSE(dwarf_formudata) (INTUSE(dwarf_attr) (die, DW_AT_ordering,
+ &attr_mem),
+ &value) == 0 ? (int) value : -1;
+}
diff --git a/libdw/dwarf_attr.c b/libdw/dwarf_attr.c
new file mode 100644
index 00000000..8ebbb8f5
--- /dev/null
+++ b/libdw/dwarf_attr.c
@@ -0,0 +1,40 @@
+/* Return specific DWARF attribute of a DIE.
+ Copyright (C) 2003, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+Dwarf_Attribute *
+dwarf_attr (die, search_name, result)
+ Dwarf_Die *die;
+ unsigned int search_name;
+ Dwarf_Attribute *result;
+{
+ if (die == NULL)
+ return NULL;
+
+ /* Search for the attribute with the given name. */
+ result->valp = __libdw_find_attr (die, search_name, &result->code,
+ &result->form);
+ /* Always fill in the CU information. */
+ result->cu = die->cu;
+
+ return result->code == search_name ? result : NULL;
+}
+INTDEF(dwarf_attr)
diff --git a/libdw/dwarf_attr_integrate.c b/libdw/dwarf_attr_integrate.c
new file mode 100644
index 00000000..4b27296a
--- /dev/null
+++ b/libdw/dwarf_attr_integrate.c
@@ -0,0 +1,43 @@
+/* Return specific DWARF attribute of a DIE, integrating DW_AT_abstract_origin.
+ Copyright (C) 2005 Red Hat, Inc.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+Dwarf_Attribute *
+dwarf_attr_integrate (Dwarf_Die *die, unsigned int search_name,
+ Dwarf_Attribute *result)
+{
+ Dwarf_Die die_mem;
+
+ do
+ {
+ Dwarf_Attribute *attr = INTUSE(dwarf_attr) (die, search_name, result);
+ if (attr != NULL)
+ return attr;
+
+ attr = INTUSE(dwarf_attr) (die, DW_AT_abstract_origin, result);
+ if (attr == NULL)
+ break;
+
+ die = INTUSE(dwarf_formref_die) (attr, &die_mem);
+ }
+ while (die != NULL);
+
+ return NULL;
+}
+INTDEF (dwarf_attr_integrate)
diff --git a/libdw/dwarf_begin.c b/libdw/dwarf_begin.c
new file mode 100644
index 00000000..70a1b07d
--- /dev/null
+++ b/libdw/dwarf_begin.c
@@ -0,0 +1,85 @@
+/* Create descriptor from file descriptor for processing file.
+ Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <stddef.h>
+#include <sys/stat.h>
+
+#include <libdwP.h>
+
+
+Dwarf *
+dwarf_begin (fd, cmd)
+ int fd;
+ Dwarf_Cmd cmd;
+{
+ Elf *elf;
+ Elf_Cmd elfcmd;
+ Dwarf *result = NULL;
+
+ switch (cmd)
+ {
+ case DWARF_C_READ:
+ elfcmd = ELF_C_READ_MMAP;
+ break;
+ case DWARF_C_WRITE:
+ elfcmd = ELF_C_WRITE;
+ break;
+ case DWARF_C_RDWR:
+ elfcmd = ELF_C_RDWR;
+ break;
+ default:
+ /* No valid mode. */
+ __libdw_seterrno (DWARF_E_INVALID_CMD);
+ return NULL;
+ }
+
+ /* We have to call `elf_version' here since the user might have not
+ done it or initialized libelf with a different version. This
+ would break libdwarf since we are using the ELF data structures
+ in a certain way. */
+ elf_version (EV_CURRENT);
+
+ /* Get an ELF descriptor. */
+ elf = elf_begin (fd, elfcmd, NULL);
+ if (elf == NULL)
+ {
+ /* Test why the `elf_begin" call failed. */
+ struct stat64 st;
+
+ if (fstat64 (fd, &st) == 0 && ! S_ISREG (st.st_mode))
+ __libdw_seterrno (DWARF_E_NO_REGFILE);
+ else if (errno == EBADF)
+ __libdw_seterrno (DWARF_E_INVALID_FILE);
+ else
+ __libdw_seterrno (DWARF_E_IO_ERROR);
+ }
+ else
+ {
+ /* Do the real work now that we have an ELF descriptor. */
+ result = INTUSE(dwarf_begin_elf) (elf, cmd, NULL);
+
+ /* If this failed, free the resources. */
+ if (result == NULL)
+ elf_end (elf);
+ else
+ result->free_elf = true;
+ }
+
+ return result;
+}
diff --git a/libdw/dwarf_begin_elf.c b/libdw/dwarf_begin_elf.c
new file mode 100644
index 00000000..427ffc39
--- /dev/null
+++ b/libdw/dwarf_begin_elf.c
@@ -0,0 +1,252 @@
+/* Create descriptor from ELF descriptor for processing file.
+ Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include "libdwP.h"
+
+
+/* Section names. */
+static const char dwarf_scnnames[IDX_last][17] =
+{
+ [IDX_debug_info] = ".debug_info",
+ [IDX_debug_abbrev] = ".debug_abbrev",
+ [IDX_debug_aranges] = ".debug_aranges",
+ [IDX_debug_line] = ".debug_line",
+ [IDX_debug_frame] = ".debug_frame",
+ [IDX_eh_frame] = ".eh_frame",
+ [IDX_debug_loc] = ".debug_loc",
+ [IDX_debug_pubnames] = ".debug_pubnames",
+ [IDX_debug_str] = ".debug_str",
+ [IDX_debug_funcnames] = ".debug_funcnames",
+ [IDX_debug_typenames] = ".debug_typenames",
+ [IDX_debug_varnames] = ".debug_varnames",
+ [IDX_debug_weaknames] = ".debug_weaknames",
+ [IDX_debug_macinfo] = ".debug_macinfo",
+ [IDX_debug_ranges] = ".debug_ranges"
+};
+#define ndwarf_scnnames (sizeof (dwarf_scnnames) / sizeof (dwarf_scnnames[0]))
+
+
+static void
+check_section (Dwarf *result, GElf_Ehdr *ehdr, Elf_Scn *scn, bool inscngrp)
+{
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *shdr;
+
+ /* Get the section header data. */
+ shdr = gelf_getshdr (scn, &shdr_mem);
+ if (shdr == NULL)
+ /* This should never happen. If it does something is
+ wrong in the libelf library. */
+ abort ();
+
+
+ /* Make sure the section is part of a section group only iff we
+ really need it. If we are looking for the global (= non-section
+ group debug info) we have to ignore all the info in section
+ groups. If we are looking into a section group we cannot look at
+ a section which isn't part of the section group. */
+ if (! inscngrp && (shdr->sh_flags & SHF_GROUP) != 0)
+ /* Ignore the section. */
+ return;
+
+
+ /* We recognize the DWARF section by their names. This is not very
+ safe and stable but the best we can do. */
+ const char *scnname = elf_strptr (result->elf, ehdr->e_shstrndx,
+ shdr->sh_name);
+ if (scnname == NULL)
+ {
+ /* The section name must be valid. Otherwise is the ELF file
+ invalid. */
+ __libdw_seterrno (DWARF_E_INVALID_ELF);
+ free (result);
+ return;
+ }
+
+
+ /* Recognize the various sections. Most names start with .debug_. */
+ size_t cnt;
+ for (cnt = 0; cnt < ndwarf_scnnames; ++cnt)
+ if (strcmp (scnname, dwarf_scnnames[cnt]) == 0)
+ {
+ /* Found it. Remember where the data is. */
+ if (unlikely (result->sectiondata[cnt] != NULL))
+ /* A section appears twice. That's bad. We ignore the section. */
+ break;
+
+ /* Get the section data. */
+ Elf_Data *data = elf_getdata (scn, NULL);
+ if (data != NULL && data->d_size != 0)
+ /* Yep, there is actually data available. */
+ result->sectiondata[cnt] = data;
+
+ break;
+ }
+}
+
+
+/* Check whether all the necessary DWARF information is available. */
+static Dwarf *
+valid_p (Dwarf *result)
+{
+ /* We looked at all the sections. Now determine whether all the
+ sections with debugging information we need are there.
+
+ XXX Which sections are absolutely necessary? Add tests if
+ necessary. For now we require only .debug_info. Hopefully this
+ is correct. */
+ if (unlikely (result->sectiondata[IDX_debug_info] == NULL))
+ {
+ __libdw_seterrno (DWARF_E_NO_DWARF);
+ result = NULL;
+ }
+
+ return result;
+}
+
+
+static Dwarf *
+global_read (Dwarf *result, Elf *elf, GElf_Ehdr *ehdr)
+{
+ Elf_Scn *scn = NULL;
+
+ while ((scn = elf_nextscn (elf, scn)) != NULL)
+ check_section (result, ehdr, scn, false);
+
+ return valid_p (result);
+}
+
+
+static Dwarf *
+scngrp_read (Dwarf *result, Elf *elf, GElf_Ehdr *ehdr, Elf_Scn *scngrp)
+{
+ /* SCNGRP is the section descriptor for a section group which might
+ contain debug sections. */
+ Elf_Data *data = elf_getdata (scngrp, NULL);
+ if (data == NULL)
+ {
+ /* We cannot read the section content. Fail! */
+ free (result);
+ return NULL;
+ }
+
+ /* The content of the section is a number of 32-bit words which
+ represent section indices. The first word is a flag word. */
+ Elf32_Word *scnidx = (Elf32_Word *) data->d_buf;
+ size_t cnt;
+ for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size; ++cnt)
+ {
+ Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]);
+ if (scn == NULL)
+ {
+ /* A section group refers to a non-existing section. Should
+ never happen. */
+ __libdw_seterrno (DWARF_E_INVALID_ELF);
+ free (result);
+ return NULL;
+ }
+
+ check_section (result, ehdr, scn, true);
+ }
+
+ return valid_p (result);
+}
+
+
+Dwarf *
+dwarf_begin_elf (elf, cmd, scngrp)
+ Elf *elf;
+ Dwarf_Cmd cmd;
+ Elf_Scn *scngrp;
+{
+ GElf_Ehdr *ehdr;
+ GElf_Ehdr ehdr_mem;
+
+ /* Get the ELF header of the file. We need various pieces of
+ information from it. */
+ ehdr = gelf_getehdr (elf, &ehdr_mem);
+ if (ehdr == NULL)
+ {
+ if (elf_kind (elf) != ELF_K_ELF)
+ __libdw_seterrno (DWARF_E_NOELF);
+ else
+ __libdw_seterrno (DWARF_E_GETEHDR_ERROR);
+
+ return NULL;
+ }
+
+
+ /* Default memory allocation size. */
+ size_t mem_default_size = sysconf (_SC_PAGESIZE) - 4 * sizeof (void *);
+
+ /* Allocate the data structure. */
+ Dwarf *result = (Dwarf *) calloc (1, sizeof (Dwarf) + mem_default_size);
+ if (result == NULL)
+ {
+ __libdw_seterrno (DWARF_E_NOMEM);
+ return NULL;
+ }
+
+ /* Fill in some values. */
+ if ((BYTE_ORDER == LITTLE_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
+ || (BYTE_ORDER == BIG_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
+ result->other_byte_order = true;
+
+ result->elf = elf;
+
+ /* Initialize the memory handling. */
+ result->mem_default_size = mem_default_size;
+ result->oom_handler = __libdw_oom;
+ result->mem_tail = (struct libdw_memblock *) (result + 1);
+ result->mem_tail->size = (result->mem_default_size
+ - offsetof (struct libdw_memblock, mem));
+ result->mem_tail->remaining = result->mem_tail->size;
+ result->mem_tail->prev = NULL;
+
+
+ if (cmd == DWARF_C_READ || cmd == DWARF_C_RDWR)
+ {
+ /* If the caller provides a section group we get the DWARF
+ sections only from this setion group. Otherwise we search
+ for the first section with the required name. Further
+ sections with the name are ignored. The DWARF specification
+ does not really say this is allowed. */
+ if (scngrp == NULL)
+ return global_read (result, elf, ehdr);
+ else
+ return scngrp_read (result, elf, ehdr, scngrp);
+ }
+ else if (cmd == DWARF_C_WRITE)
+ {
+ __libdw_seterrno (DWARF_E_UNIMPL);
+ free (result);
+ return NULL;
+ }
+
+ __libdw_seterrno (DWARF_E_INVALID_CMD);
+ free (result);
+ return NULL;
+}
+INTDEF(dwarf_begin_elf)
diff --git a/libdw/dwarf_bitoffset.c b/libdw/dwarf_bitoffset.c
new file mode 100644
index 00000000..52ab1759
--- /dev/null
+++ b/libdw/dwarf_bitoffset.c
@@ -0,0 +1,33 @@
+/* Return bit offset attribute of DIE.
+ Copyright (C) 2003, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_bitoffset (die)
+ Dwarf_Die *die;
+{
+ Dwarf_Attribute attr_mem;
+ Dwarf_Word value;
+
+ return INTUSE(dwarf_formudata) (INTUSE(dwarf_attr) (die, DW_AT_bit_offset,
+ &attr_mem),
+ &value) == 0 ? (int) value : -1;
+}
diff --git a/libdw/dwarf_bitsize.c b/libdw/dwarf_bitsize.c
new file mode 100644
index 00000000..c67b4ccf
--- /dev/null
+++ b/libdw/dwarf_bitsize.c
@@ -0,0 +1,33 @@
+/* Return bit size attribute of DIE.
+ Copyright (C) 2003, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_bitsize (die)
+ Dwarf_Die *die;
+{
+ Dwarf_Attribute attr_mem;
+ Dwarf_Word value;
+
+ return INTUSE(dwarf_formudata) (INTUSE(dwarf_attr) (die, DW_AT_bit_size,
+ &attr_mem),
+ &value) == 0 ? (int) value : -1;
+}
diff --git a/libdw/dwarf_bytesize.c b/libdw/dwarf_bytesize.c
new file mode 100644
index 00000000..3e0b05a8
--- /dev/null
+++ b/libdw/dwarf_bytesize.c
@@ -0,0 +1,33 @@
+/* Return byte size attribute of DIE.
+ Copyright (C) 2003, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_bytesize (die)
+ Dwarf_Die *die;
+{
+ Dwarf_Attribute attr_mem;
+ Dwarf_Word value;
+
+ return INTUSE(dwarf_formudata) (INTUSE(dwarf_attr) (die, DW_AT_byte_size,
+ &attr_mem),
+ &value) == 0 ? (int) value : -1;
+}
diff --git a/libdw/dwarf_child.c b/libdw/dwarf_child.c
new file mode 100644
index 00000000..8dbe9179
--- /dev/null
+++ b/libdw/dwarf_child.c
@@ -0,0 +1,159 @@
+/* Return vhild of current DIE.
+ Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+#include <string.h>
+
+/* Some arbitrary value not conflicting with any existing code. */
+#define INVALID 0xffffe444
+
+
+unsigned char *
+internal_function_def
+__libdw_find_attr (Dwarf_Die *die, unsigned int search_name,
+ unsigned int *codep, unsigned int *formp)
+{
+ Dwarf *dbg = die->cu->dbg;
+ const unsigned char *readp = (unsigned char *) die->addr;
+
+ /* First we have to get the abbreviation code so that we can decode
+ the data in the DIE. */
+ unsigned int abbrev_code;
+ get_uleb128 (abbrev_code, readp);
+
+ /* Find the abbreviation entry. */
+ Dwarf_Abbrev *abbrevp = die->abbrev;
+ if (abbrevp == NULL)
+ {
+ abbrevp = __libdw_findabbrev (die->cu, abbrev_code);
+ die->abbrev = abbrevp ?: (Dwarf_Abbrev *) -1l;
+ }
+ if (unlikely (die->abbrev == (Dwarf_Abbrev *) -1l))
+ {
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return NULL;
+ }
+
+ /* Search the name attribute. */
+ unsigned char *const endp
+ = ((unsigned char *) dbg->sectiondata[IDX_debug_abbrev]->d_buf
+ + dbg->sectiondata[IDX_debug_abbrev]->d_size);
+
+ const unsigned char *attrp = die->abbrev->attrp;
+ while (1)
+ {
+ /* Are we still in bounds? This test needs to be refined. */
+ if (unlikely (attrp + 1 >= endp))
+ {
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return NULL;
+ }
+
+ /* Get attribute name and form.
+
+ XXX We don't check whether this reads beyond the end of the
+ section. */
+ unsigned int attr_name;
+ get_uleb128 (attr_name, attrp);
+ unsigned int attr_form;
+ get_uleb128 (attr_form, attrp);
+
+ /* We can stop if we found the attribute with value zero. */
+ if (attr_name == 0 && attr_form == 0)
+ break;
+
+ /* Is this the name attribute? */
+ if (attr_name == search_name && search_name != INVALID)
+ {
+ if (codep != NULL)
+ *codep = attr_name;
+ if (formp != NULL)
+ *formp = attr_form;
+
+ return (unsigned char *) readp;
+ }
+
+ /* Skip over the rest of this attribute (if there is any). */
+ if (attr_form != 0)
+ {
+ size_t len = __libdw_form_val_len (dbg, die->cu, attr_form, readp);
+
+ if (unlikely (len == (size_t) -1l))
+ {
+ readp = NULL;
+ break;
+ }
+
+ // XXX We need better boundary checks.
+ readp += len;
+ }
+ }
+
+ // XXX Do we need other values?
+ if (codep != NULL)
+ *codep = INVALID;
+ if (formp != NULL)
+ *formp = INVALID;
+
+ return (unsigned char *) readp;
+}
+
+
+int
+dwarf_child (die, result)
+ Dwarf_Die *die;
+ Dwarf_Die *result;
+{
+ /* Ignore previous errors. */
+ if (die == NULL)
+ return -1;
+
+ /* Skip past the last attribute. */
+ void *addr = NULL;
+
+ /* If we already know there are no children do not search. */
+ if (die->abbrev != (Dwarf_Abbrev *) -1
+ && (die->abbrev == NULL || die->abbrev->has_children))
+ addr = __libdw_find_attr (die, INVALID, NULL, NULL);
+ if (die->abbrev == (Dwarf_Abbrev *) -1l)
+ return -1;
+
+ /* Make sure the DIE really has children. */
+ if (! die->abbrev->has_children)
+ /* There cannot be any children. */
+ return 1;
+
+ if (addr == NULL)
+ return -1;
+
+ /* RESULT can be the same as DIE. So preserve what we need. */
+ struct Dwarf_CU *cu = die->cu;
+
+ /* Clear the entire DIE structure. This signals we have not yet
+ determined any of the information. */
+ memset (result, '\0', sizeof (Dwarf_Die));
+
+ /* We have the address. */
+ result->addr = addr;
+
+ /* Same CU as the parent. */
+ result->cu = cu;
+
+ return 0;
+}
+INTDEF(dwarf_child)
diff --git a/libdw/dwarf_cuoffset.c b/libdw/dwarf_cuoffset.c
new file mode 100644
index 00000000..f3adfa83
--- /dev/null
+++ b/libdw/dwarf_cuoffset.c
@@ -0,0 +1,32 @@
+/* Return offset of DIE in CU.
+ Copyright (C) 2003 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+Dwarf_Off
+dwarf_cuoffset (die)
+ Dwarf_Die *die;
+{
+ return (die == NULL
+ ? (Dwarf_Off) -1l
+ : (die->addr
+ - die->cu->dbg->sectiondata[IDX_debug_info]->d_buf
+ - die->cu->start));
+}
diff --git a/libdw/dwarf_diename.c b/libdw/dwarf_diename.c
new file mode 100644
index 00000000..41d763c5
--- /dev/null
+++ b/libdw/dwarf_diename.c
@@ -0,0 +1,31 @@
+/* Return string in name attribute of DIE.
+ Copyright (C) 2002, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+const char *
+dwarf_diename (die)
+ Dwarf_Die *die;
+{
+ Dwarf_Attribute attr_mem;
+
+ return INTUSE(dwarf_formstring) (INTUSE(dwarf_attr) (die, DW_AT_name,
+ &attr_mem));
+}
diff --git a/libdw/dwarf_dieoffset.c b/libdw/dwarf_dieoffset.c
new file mode 100644
index 00000000..e678a404
--- /dev/null
+++ b/libdw/dwarf_dieoffset.c
@@ -0,0 +1,32 @@
+/* Return offset of DIE.
+ Copyright (C) 2003, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+Dwarf_Off
+dwarf_dieoffset (die)
+ Dwarf_Die *die;
+{
+ return (die == NULL
+ ? ~0ul
+ : (Dwarf_Off) (die->addr
+ - die->cu->dbg->sectiondata[IDX_debug_info]->d_buf));
+}
+INTDEF(dwarf_dieoffset)
diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c
new file mode 100644
index 00000000..935bd3d2
--- /dev/null
+++ b/libdw/dwarf_end.c
@@ -0,0 +1,75 @@
+/* Release debugging handling context.
+ Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <search.h>
+#include <stdlib.h>
+
+#include "libdwP.h"
+
+
+
+static void
+noop_free (void *arg __attribute__ ((unused)))
+{
+}
+
+
+static void
+cu_free (void *arg)
+{
+ struct Dwarf_CU *p = (struct Dwarf_CU *) arg;
+
+ Dwarf_Abbrev_Hash_free (&p->abbrev_hash);
+
+ tdestroy (p->locs, noop_free);
+}
+
+
+int
+dwarf_end (dwarf)
+ Dwarf *dwarf;
+{
+ if (dwarf != NULL)
+ {
+ /* The search tree for the CUs. NB: the CU data itself is
+ allocated separately, but the abbreviation hash tables need
+ to be handled. */
+ tdestroy (dwarf->cu_tree, cu_free);
+
+ struct libdw_memblock *memp = dwarf->mem_tail;
+ /* The first block is allocated together with the Dwarf object. */
+ while (memp->prev != NULL)
+ {
+ struct libdw_memblock *prevp = memp->prev;
+ free (memp);
+ memp = prevp;
+ }
+
+ /* Free the pubnames helper structure. */
+ free (dwarf->pubnames_sets);
+
+ /* Free the ELF descriptor if necessary. */
+ if (dwarf->free_elf)
+ elf_end (dwarf->elf);
+
+ /* Free the context descriptor. */
+ free (dwarf);
+ }
+
+ return 0;
+}
diff --git a/libdw/dwarf_error.c b/libdw/dwarf_error.c
new file mode 100644
index 00000000..85d928c9
--- /dev/null
+++ b/libdw/dwarf_error.c
@@ -0,0 +1,180 @@
+/* Retrieve ELF descriptor used for DWARF access.
+ Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <stddef.h>
+
+#include "libdwP.h"
+
+
+#ifdef USE_TLS
+/* The error number. */
+static __thread int global_error;
+#else
+/* This is the key for the thread specific memory. */
+static tls_key_t key;
+
+/* The error number. Used in non-threaded programs. */
+static int global_error;
+static bool threaded;
+/* We need to initialize the thread-specific data. */
+once_define (static, once);
+
+/* The initialization and destruction functions. */
+static void init (void);
+static void free_key_mem (void *mem);
+#endif /* TLS */
+
+
+int
+dwarf_errno (void)
+{
+ int result;
+
+#ifndef USE_TLS
+ /* If we have not yet initialized the buffer do it now. */
+ once_execute (once, init);
+
+ if (threaded)
+ {
+ /* We do not allocate memory for the data. It is only a word.
+ We can store it in place of the pointer. */
+ result = (intptr_t) getspecific (key);
+
+ setspecific (key, (void *) (intptr_t) DWARF_E_NOERROR);
+ return result;
+ }
+#endif /* TLS */
+
+ result = global_error;
+ global_error = DWARF_E_NOERROR;
+ return result;
+}
+INTDEF(dwarf_errno)
+
+
+/* XXX For now we use string pointers. Once the table stablelizes
+ make it more DSO-friendly. */
+static const char *errmsgs[] =
+ {
+ [DWARF_E_NOERROR] = N_("no error"),
+ [DWARF_E_UNKNOWN_ERROR] = N_("unknown error"),
+ [DWARF_E_INVALID_ACCESS] = N_("invalid access"),
+ [DWARF_E_NO_REGFILE] = N_("no regular file"),
+ [DWARF_E_IO_ERROR] = N_("I/O error"),
+ [DWARF_E_INVALID_ELF] = N_("invalid ELF file"),
+ [DWARF_E_NO_DWARF] = N_("no DWARF information"),
+ [DWARF_E_NOELF] = N_("no ELF file"),
+ [DWARF_E_GETEHDR_ERROR] = N_("cannot get ELF header"),
+ [DWARF_E_NOMEM] = N_("out of memory"),
+ [DWARF_E_UNIMPL] = N_("not implemented"),
+ [DWARF_E_INVALID_CMD] = N_("invalid command"),
+ [DWARF_E_INVALID_VERSION] = N_("invalid version"),
+ [DWARF_E_INVALID_FILE] = N_("invalid file"),
+ [DWARF_E_NO_ENTRY] = N_("no entries found"),
+ [DWARF_E_INVALID_DWARF] = N_("invalid DWARF"),
+ [DWARF_E_NO_STRING] = N_("no string data"),
+ [DWARF_E_NO_ADDR] = N_("no address value"),
+ [DWARF_E_NO_CONSTANT] = N_("no constant value"),
+ [DWARF_E_NO_REFERENCE] = N_("no reference value"),
+ [DWARF_E_INVALID_REFERENCE] = N_("invalid reference value"),
+ [DWARF_E_NO_DEBUG_LINE] = N_(".debug_line section missing"),
+ [DWARF_E_INVALID_DEBUG_LINE] = N_("invalid .debug_line section"),
+ [DWARF_E_TOO_BIG] = N_("debug information too big"),
+ [DWARF_E_VERSION] = N_("invalid DWARF version"),
+ [DWARF_E_INVALID_DIR_IDX] = N_("invalid directory index"),
+ [DWARF_E_ADDR_OUTOFRANGE] = N_("address out of range"),
+ [DWARF_E_NO_LOCLIST] = N_("no location list value"),
+ [DWARF_E_NO_BLOCK] = N_("no block data"),
+ [DWARF_E_INVALID_LINE_IDX] = N_("invalid line index"),
+ [DWARF_E_INVALID_ARANGE_IDX] = N_("invalid address range index"),
+ [DWARF_E_NO_MATCH] = N_("no matching address range"),
+ [DWARF_E_NO_FLAG] = N_("no flag value"),
+ [DWARF_E_INVALID_OFFSET] = N_("invalid offset"),
+ [DWARF_E_NO_DEBUG_RANGES] = N_(".debug_ranges section missing"),
+ };
+#define nerrmsgs (sizeof (errmsgs) / sizeof (errmsgs[0]))
+
+
+void
+__libdw_seterrno (value)
+ int value;
+{
+#ifndef USE_TLS
+ /* If we have not yet initialized the buffer do it now. */
+ once_execute (once, init);
+
+ if (threaded)
+ /* We do not allocate memory for the data. It is only a word.
+ We can store it in place of the pointer. */
+ setspecific (key, (void *) (intptr_t) value);
+#endif /* TLS */
+
+ global_error = (value >= 0 && value < (int) nerrmsgs
+ ? value : DWARF_E_UNKNOWN_ERROR);
+}
+
+
+const char *
+dwarf_errmsg (error)
+ int error;
+{
+ int last_error;
+
+#ifndef USE_TLS
+ /* If we have not yet initialized the buffer do it now. */
+ once_execute (once, init);
+
+ if ((error == 0 || error == -1) && threaded)
+ /* We do not allocate memory for the data. It is only a word.
+ We can store it in place of the pointer. */
+ last_error = (intptr_t) getspecific (key);
+ else
+#endif /* TLS */
+ last_error = global_error;
+
+ if (error == 0)
+ return last_error != 0 ? _(errmsgs[last_error]) : NULL;
+ else if (error < -1 || error >= (int) nerrmsgs)
+ return _(errmsgs[DWARF_E_UNKNOWN_ERROR]);
+
+ return _(errmsgs[error == -1 ? last_error : error]);
+}
+
+
+#ifndef USE_TLS
+/* Free the thread specific data, this is done if a thread terminates. */
+static void
+free_key_mem (void *mem __attribute__ ((unused)))
+{
+ setspecific (key, NULL);
+}
+
+
+/* Initialize the key for the global variable. */
+static void
+init (void)
+{
+ // XXX Screw you, gcc4, the unused function attribute does not work.
+ __asm ("" :: "r" (free_key_mem));
+
+ if (key_create (&key, free_key_mem) == 0)
+ /* Creating the key succeeded. */
+ threaded = true;
+}
+#endif /* TLS */
diff --git a/libdw/dwarf_filesrc.c b/libdw/dwarf_filesrc.c
new file mode 100644
index 00000000..770c004b
--- /dev/null
+++ b/libdw/dwarf_filesrc.c
@@ -0,0 +1,36 @@
+/* Find source file information.
+ Copyright (C) 2004 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+const char *
+dwarf_filesrc (Dwarf_Files *file, size_t idx, Dwarf_Word *mtime,
+ Dwarf_Word *length)
+{
+ if (file == NULL || idx >= file->nfiles)
+ return NULL;
+
+ if (mtime != NULL)
+ *mtime = file->info[idx].mtime;
+
+ if (length != NULL)
+ *length = file->info[idx].length;
+
+ return file->info[idx].name;
+}
diff --git a/libdw/dwarf_formaddr.c b/libdw/dwarf_formaddr.c
new file mode 100644
index 00000000..168eb89a
--- /dev/null
+++ b/libdw/dwarf_formaddr.c
@@ -0,0 +1,44 @@
+/* Return address represented by attribute.
+ Copyright (C) 2003, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_formaddr (attr, return_addr)
+ Dwarf_Attribute *attr;
+ Dwarf_Addr *return_addr;
+{
+ if (attr == NULL)
+ return -1;
+
+ if (unlikely (attr->form != DW_FORM_addr))
+ {
+ __libdw_seterrno (DWARF_E_NO_ADDR);
+ return -1;
+ }
+
+ if (attr->cu->address_size == 8)
+ *return_addr = read_8ubyte_unaligned (attr->cu->dbg, attr->valp);
+ else
+ *return_addr = read_4ubyte_unaligned (attr->cu->dbg, attr->valp);
+
+ return 0;
+}
+INTDEF(dwarf_formaddr)
diff --git a/libdw/dwarf_formblock.c b/libdw/dwarf_formblock.c
new file mode 100644
index 00000000..30c2ac93
--- /dev/null
+++ b/libdw/dwarf_formblock.c
@@ -0,0 +1,72 @@
+/* Return block represented by attribute.
+ Copyright (C) 2004, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_formblock (attr, return_block)
+ Dwarf_Attribute *attr;
+ Dwarf_Block *return_block;
+{
+ if (attr == NULL)
+ return -1;
+
+ const unsigned char *datap;
+
+ switch (attr->form)
+ {
+ case DW_FORM_block1:
+ return_block->length = *(uint8_t *) attr->valp;
+ return_block->data = attr->valp + 1;
+ break;
+
+ case DW_FORM_block2:
+ return_block->length = read_2ubyte_unaligned (attr->cu->dbg, attr->valp);
+ return_block->data = attr->valp + 2;
+ break;
+
+ case DW_FORM_block4:
+ return_block->length = read_4ubyte_unaligned (attr->cu->dbg, attr->valp);
+ return_block->data = attr->valp + 4;
+ break;
+
+ case DW_FORM_block:
+ datap = attr->valp;
+ get_uleb128 (return_block->length, datap);
+ return_block->data = (unsigned char *) datap;
+ break;
+
+ default:
+ __libdw_seterrno (DWARF_E_NO_BLOCK);
+ return -1;
+ }
+
+ if (return_block->data + return_block->length
+ > ((unsigned char *) attr->cu->dbg->sectiondata[IDX_debug_info]->d_buf
+ + attr->cu->dbg->sectiondata[IDX_debug_info]->d_size))
+ {
+ /* Block does not fit. */
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return -1;
+ }
+
+ return 0;
+}
+INTDEF(dwarf_formblock)
diff --git a/libdw/dwarf_formflag.c b/libdw/dwarf_formflag.c
new file mode 100644
index 00000000..ac344019
--- /dev/null
+++ b/libdw/dwarf_formflag.c
@@ -0,0 +1,40 @@
+/* Return flag represented by attribute.
+ Copyright (C) 2004 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_formflag (attr, return_bool)
+ Dwarf_Attribute *attr;
+ bool *return_bool;
+{
+ if (attr == NULL)
+ return -1;
+
+ if (unlikely (attr->form != DW_FORM_flag))
+ {
+ __libdw_seterrno (DWARF_E_NO_FLAG);
+ return -1;
+ }
+
+ *return_bool = *attr->valp != 0;
+
+ return 0;
+}
diff --git a/libdw/dwarf_formref.c b/libdw/dwarf_formref.c
new file mode 100644
index 00000000..ea569905
--- /dev/null
+++ b/libdw/dwarf_formref.c
@@ -0,0 +1,67 @@
+/* Return reference offset represented by attribute.
+ Copyright (C) 2003, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_formref (attr, return_offset)
+ Dwarf_Attribute *attr;
+ Dwarf_Off *return_offset;
+{
+ if (attr == NULL)
+ return -1;
+
+ const unsigned char *datap;
+
+ switch (attr->form)
+ {
+ case DW_FORM_ref1:
+ *return_offset = *attr->valp;
+ break;
+
+ case DW_FORM_ref2:
+ *return_offset = read_2ubyte_unaligned (attr->cu->dbg, attr->valp);
+ break;
+
+ case DW_FORM_ref4:
+ *return_offset = read_4ubyte_unaligned (attr->cu->dbg, attr->valp);
+ break;
+
+ case DW_FORM_ref8:
+ *return_offset = read_8ubyte_unaligned (attr->cu->dbg, attr->valp);
+ break;
+
+ case DW_FORM_ref_udata:
+ datap = attr->valp;
+ get_uleb128 (*return_offset, datap);
+ break;
+
+ case DW_FORM_ref_addr:
+ __libdw_seterrno (DWARF_E_INVALID_REFERENCE);
+ return -1;
+
+ default:
+ __libdw_seterrno (DWARF_E_NO_REFERENCE);
+ return -1;
+ }
+
+ return 0;
+}
+INTDEF(dwarf_formref)
diff --git a/libdw/dwarf_formref_die.c b/libdw/dwarf_formref_die.c
new file mode 100644
index 00000000..7f5b4f97
--- /dev/null
+++ b/libdw/dwarf_formref_die.c
@@ -0,0 +1,28 @@
+/* Look up the DIE in a reference-form attribute.
+ Copyright (C) 2005 Red Hat, Inc.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+Dwarf_Die *
+dwarf_formref_die (Dwarf_Attribute *attr, Dwarf_Die *die_mem)
+{
+ Dwarf_Off offset;
+ return (unlikely (INTUSE(dwarf_formref) (attr, &offset) != 0) ? NULL
+ : INTUSE(dwarf_offdie) (attr->cu->dbg, attr->cu->start + offset,
+ die_mem));
+}
+INTDEF (dwarf_formref_die)
diff --git a/libdw/dwarf_formsdata.c b/libdw/dwarf_formsdata.c
new file mode 100644
index 00000000..a5b6b88a
--- /dev/null
+++ b/libdw/dwarf_formsdata.c
@@ -0,0 +1,68 @@
+/* Return signed constant represented by attribute.
+ Copyright (C) 2003, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_formsdata (attr, return_sval)
+ Dwarf_Attribute *attr;
+ Dwarf_Sword *return_sval;
+{
+ if (attr == NULL)
+ return -1;
+
+ const unsigned char *datap;
+
+ switch (attr->form)
+ {
+ case DW_FORM_data1:
+ *return_sval = *attr->valp;
+ break;
+
+ case DW_FORM_data2:
+ *return_sval = read_2ubyte_unaligned (attr->cu->dbg, attr->valp);
+ break;
+
+ case DW_FORM_data4:
+ *return_sval = read_4ubyte_unaligned (attr->cu->dbg, attr->valp);
+ break;
+
+ case DW_FORM_data8:
+ *return_sval = read_8ubyte_unaligned (attr->cu->dbg, attr->valp);
+ break;
+
+ case DW_FORM_sdata:
+ datap = attr->valp;
+ get_sleb128 (*return_sval, datap);
+ break;
+
+ case DW_FORM_udata:
+ datap = attr->valp;
+ get_uleb128 (*return_sval, datap);
+ break;
+
+ default:
+ __libdw_seterrno (DWARF_E_NO_CONSTANT);
+ return -1;
+ }
+
+ return 0;
+}
+INTDEF(dwarf_formsdata)
diff --git a/libdw/dwarf_formstring.c b/libdw/dwarf_formstring.c
new file mode 100644
index 00000000..eac1cc05
--- /dev/null
+++ b/libdw/dwarf_formstring.c
@@ -0,0 +1,58 @@
+/* Return string associated with given attribute.
+ Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+const char *
+dwarf_formstring (attrp)
+ Dwarf_Attribute *attrp;
+{
+ /* Ignore earlier errors. */
+ if (attrp == NULL)
+ return NULL;
+
+ /* We found it. Now determine where the string is stored. */
+ if (attrp->form == DW_FORM_string)
+ /* A simple inlined string. */
+ return (const char *) attrp->valp;
+
+ Dwarf *dbg = attrp->cu->dbg;
+
+ if (unlikely (attrp->form != DW_FORM_strp)
+ || dbg->sectiondata[IDX_debug_str] == NULL)
+ {
+ invalid_error:
+ __libdw_seterrno (DWARF_E_NO_STRING);
+ return NULL;
+ }
+
+ uint64_t off;
+ // XXX We need better boundary checks.
+ if (attrp->cu->offset_size == 8)
+ off = read_8ubyte_unaligned (dbg, attrp->valp);
+ else
+ off = read_4ubyte_unaligned (dbg, attrp->valp);
+
+ if (off >= dbg->sectiondata[IDX_debug_str]->d_size)
+ goto invalid_error;
+
+ return (const char *) dbg->sectiondata[IDX_debug_str]->d_buf + off;
+}
+INTDEF(dwarf_formstring)
diff --git a/libdw/dwarf_formudata.c b/libdw/dwarf_formudata.c
new file mode 100644
index 00000000..67985621
--- /dev/null
+++ b/libdw/dwarf_formudata.c
@@ -0,0 +1,68 @@
+/* Return unsigned constant represented by attribute.
+ Copyright (C) 2003, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_formudata (attr, return_uval)
+ Dwarf_Attribute *attr;
+ Dwarf_Word *return_uval;
+{
+ if (attr == NULL)
+ return -1;
+
+ const unsigned char *datap;
+
+ switch (attr->form)
+ {
+ case DW_FORM_data1:
+ *return_uval = *attr->valp;
+ break;
+
+ case DW_FORM_data2:
+ *return_uval = read_2ubyte_unaligned (attr->cu->dbg, attr->valp);
+ break;
+
+ case DW_FORM_data4:
+ *return_uval = read_4ubyte_unaligned (attr->cu->dbg, attr->valp);
+ break;
+
+ case DW_FORM_data8:
+ *return_uval = read_8ubyte_unaligned (attr->cu->dbg, attr->valp);
+ break;
+
+ case DW_FORM_sdata:
+ datap = attr->valp;
+ get_sleb128 (*return_uval, datap);
+ break;
+
+ case DW_FORM_udata:
+ datap = attr->valp;
+ get_uleb128 (*return_uval, datap);
+ break;
+
+ default:
+ __libdw_seterrno (DWARF_E_NO_CONSTANT);
+ return -1;
+ }
+
+ return 0;
+}
+INTDEF(dwarf_formudata)
diff --git a/libdw/dwarf_func_col.c b/libdw/dwarf_func_col.c
new file mode 100644
index 00000000..feda1435
--- /dev/null
+++ b/libdw/dwarf_func_col.c
@@ -0,0 +1,27 @@
+/* Get line number of beginning of given function.
+ Copyright (C) 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_func_col (Dwarf_Func *func, int *colp)
+{
+ return __libdw_func_intval (func, colp, DW_AT_decl_column);
+}
diff --git a/libdw/dwarf_func_entrypc.c b/libdw/dwarf_func_entrypc.c
new file mode 100644
index 00000000..6b5103e0
--- /dev/null
+++ b/libdw/dwarf_func_entrypc.c
@@ -0,0 +1,33 @@
+/* Get entry address of function.
+ Copyright (C) 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_func_entrypc (Dwarf_Func *func, Dwarf_Addr *return_addr)
+{
+ Dwarf_Attribute attr_mem;
+ Dwarf_Attribute *attr = INTUSE(dwarf_attr) (func->die, DW_AT_entry_pc,
+ &attr_mem);
+ if (attr != NULL)
+ return INTUSE(dwarf_formaddr) (attr, return_addr);
+
+ return INTUSE(dwarf_lowpc) (func->die, return_addr);
+}
diff --git a/libdw/dwarf_func_file.c b/libdw/dwarf_func_file.c
new file mode 100644
index 00000000..d5302df0
--- /dev/null
+++ b/libdw/dwarf_func_file.c
@@ -0,0 +1,72 @@
+/* Return file name containing definition of the given function.
+ Copyright (C) 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+const char *
+dwarf_func_file (Dwarf_Func *func)
+{
+ Dwarf_Attribute attr_mem;
+ Dwarf_Sword idx = 0;
+ Dwarf_Die *die = func->die;
+
+ if (INTUSE(dwarf_formsdata) (INTUSE(dwarf_attr) (die, DW_AT_decl_file,
+ &attr_mem), &idx) != 0)
+ return NULL;
+
+ /* Zero means no source file information available. */
+ if (idx == 0)
+ {
+ __libdw_seterrno (DWARF_E_NO_ENTRY);
+ return NULL;
+ }
+
+ /* Get the array of source files for the CU. */
+ struct Dwarf_CU *cu = die->cu;
+ if (cu->lines == NULL)
+ {
+ Dwarf_Lines *lines;
+ size_t nlines;
+
+ /* Let the more generic function do the work. It'll create more
+ data but that will be needed in an real program anyway. */
+ (void) INTUSE(dwarf_getsrclines) (func->cudie, &lines, &nlines);
+ assert (cu->lines != NULL);
+ }
+
+ if (cu->lines == (void *) -1l)
+ {
+ /* If the file index is not zero, there must be file information
+ available. */
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return NULL;
+ }
+
+ assert (cu->files != NULL && cu->files != (void *) -1l);
+
+ if (idx >= cu->files->nfiles)
+ {
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return NULL;
+ }
+
+ return cu->files->info[idx].name;
+}
diff --git a/libdw/dwarf_func_highpc.c b/libdw/dwarf_func_highpc.c
new file mode 100644
index 00000000..c5d2eec3
--- /dev/null
+++ b/libdw/dwarf_func_highpc.c
@@ -0,0 +1,26 @@
+/* Get end address of function.
+ Copyright (C) 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_func_highpc (Dwarf_Func *func, Dwarf_Addr *return_addr)
+{
+ return INTUSE(dwarf_highpc) (func->die, return_addr);
+}
diff --git a/libdw/dwarf_func_line.c b/libdw/dwarf_func_line.c
new file mode 100644
index 00000000..6259b9f1
--- /dev/null
+++ b/libdw/dwarf_func_line.c
@@ -0,0 +1,47 @@
+/* Get line number of beginning of given function.
+ Copyright (C) 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+#include <limits.h>
+#include "libdwP.h"
+
+
+int
+dwarf_func_line (Dwarf_Func *func, int *linep)
+{
+ return __libdw_func_intval (func, linep, DW_AT_decl_line);
+}
+
+
+int internal_function
+__libdw_func_intval (Dwarf_Func *func, int *linep, int attval)
+{
+ Dwarf_Attribute attr_mem;
+ Dwarf_Sword line;
+
+ int res = INTUSE(dwarf_formsdata) (INTUSE(dwarf_attr) (func->die, attval,
+ &attr_mem), &line);
+ if (res == 0)
+ {
+ assert (line >= 0 && line <= INT_MAX);
+ *linep = line;
+ }
+
+ return res;
+}
diff --git a/libdw/dwarf_func_lowpc.c b/libdw/dwarf_func_lowpc.c
new file mode 100644
index 00000000..d364e6c6
--- /dev/null
+++ b/libdw/dwarf_func_lowpc.c
@@ -0,0 +1,26 @@
+/* Get start address of function.
+ Copyright (C) 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_func_lowpc (Dwarf_Func *func, Dwarf_Addr *return_addr)
+{
+ return INTUSE(dwarf_lowpc) (func->die, return_addr);
+}
diff --git a/libdw/dwarf_func_name.c b/libdw/dwarf_func_name.c
new file mode 100644
index 00000000..4151c359
--- /dev/null
+++ b/libdw/dwarf_func_name.c
@@ -0,0 +1,30 @@
+/* Get function name.
+ Copyright (C) 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+const char *
+dwarf_func_name (Dwarf_Func *func)
+{
+ Dwarf_Attribute attr_mem;
+
+ return INTUSE(dwarf_formstring) (INTUSE(dwarf_attr) (func->die, DW_AT_name,
+ &attr_mem));
+}
diff --git a/libdw/dwarf_getabbrev.c b/libdw/dwarf_getabbrev.c
new file mode 100644
index 00000000..a6968a83
--- /dev/null
+++ b/libdw/dwarf_getabbrev.c
@@ -0,0 +1,127 @@
+/* Get abbreviation at given offset.
+ Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+Dwarf_Abbrev *
+internal_function_def
+__libdw_getabbrev (dbg, cu, offset, lengthp, result)
+ Dwarf *dbg;
+ struct Dwarf_CU *cu;
+ Dwarf_Off offset;
+ size_t *lengthp;
+ Dwarf_Abbrev *result;
+{
+ /* Don't fail if there is not .debug_abbrev section. */
+ if (dbg->sectiondata[IDX_debug_abbrev] == NULL)
+ return NULL;
+
+ const unsigned char *abbrevp
+ = (unsigned char *) dbg->sectiondata[IDX_debug_abbrev]->d_buf + offset;
+ if (*abbrevp == '\0')
+ /* We are past the last entry. */
+ return DWARF_END_ABBREV;
+
+ /* 7.5.3 Abbreviations Tables
+
+ [...] Each declaration begins with an unsigned LEB128 number
+ representing the abbreviation code itself. [...] The
+ abbreviation code is followed by another unsigned LEB128
+ number that encodes the entry's tag. [...]
+
+ [...] Following the tag encoding is a 1-byte value that
+ determines whether a debugging information entry using this
+ abbreviation has child entries or not. [...]
+
+ [...] Finally, the child encoding is followed by a series of
+ attribute specifications. Each attribute specification
+ consists of two parts. The first part is an unsigned LEB128
+ number representing the attribute's name. The second part is
+ an unsigned LEB128 number representing the attribute's form. */
+ const unsigned char *start_abbrevp = abbrevp;
+ unsigned int code;
+ get_uleb128 (code, abbrevp);
+
+ /* Check whether this code is already in the hash table. */
+ bool foundit = false;
+ Dwarf_Abbrev *abb = NULL;
+ if (cu == NULL
+ || (abb = Dwarf_Abbrev_Hash_find (&cu->abbrev_hash, code, NULL)) == NULL)
+ {
+ if (result == NULL)
+ abb = libdw_typed_alloc (dbg, Dwarf_Abbrev);
+ else
+ abb = result;
+ }
+ else
+ {
+ foundit = true;
+
+ assert (abb->offset == offset);
+
+ /* If the caller doesn't need the length we are done. */
+ if (lengthp == NULL)
+ goto out;
+ }
+
+ /* If there is already a value in the hash table we are going to
+ overwrite its content. This must not be a problem, since the
+ content better be the same. */
+ abb->code = code;
+ get_uleb128 (abb->tag, abbrevp);
+ abb->has_children = *abbrevp++ == DW_CHILDREN_yes;
+ abb->attrp = (unsigned char *) abbrevp;
+ abb->offset = offset;
+
+ /* Skip over all the attributes and count them while doing so. */
+ abb->attrcnt = 0;
+ unsigned int attrname;
+ unsigned int attrform;
+ do
+ {
+ get_uleb128 (attrname, abbrevp);
+ get_uleb128 (attrform, abbrevp);
+ }
+ while (attrname != 0 && attrform != 0 && ++abb->attrcnt);
+
+ /* Return the length to the caller if she asked for it. */
+ if (lengthp != NULL)
+ *lengthp = abbrevp - start_abbrevp;
+
+ /* Add the entry to the hash table. */
+ if (cu != NULL && ! foundit)
+ (void) Dwarf_Abbrev_Hash_insert (&cu->abbrev_hash, abb->code, abb);
+
+ out:
+ return abb;
+}
+
+
+Dwarf_Abbrev *
+dwarf_getabbrev (die, offset, lengthp)
+ Dwarf_Die *die;
+ Dwarf_Off offset;
+ size_t *lengthp;
+{
+ return __libdw_getabbrev (die->cu->dbg, die->cu,
+ die->cu->orig_abbrev_offset + offset, lengthp,
+ NULL);
+}
diff --git a/libdw/dwarf_getabbrevattr.c b/libdw/dwarf_getabbrevattr.c
new file mode 100644
index 00000000..8cdf6a3d
--- /dev/null
+++ b/libdw/dwarf_getabbrevattr.c
@@ -0,0 +1,64 @@
+/* Get specific attribute of abbreviation.
+ Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_getabbrevattr (abbrev, idx, namep, formp, offsetp)
+ Dwarf_Abbrev *abbrev;
+ size_t idx;
+ unsigned int *namep;
+ unsigned int *formp;
+ Dwarf_Off *offsetp;
+{
+ if (abbrev == NULL)
+ return -1;
+
+ size_t cnt = 0;
+ const unsigned char *attrp = abbrev->attrp;
+ const unsigned char *start_attrp;
+ unsigned int name;
+ unsigned int form;
+
+ do
+ {
+ start_attrp = attrp;
+
+ /* Attribute code and form are encoded as ULEB128 values. */
+ get_uleb128 (name, attrp);
+ get_uleb128 (form, attrp);
+
+ /* If both values are zero the index is out of range. */
+ if (name == 0 && form == 0)
+ return -1;
+ }
+ while (cnt++ < idx);
+
+ /* Store the result if requested. */
+ if (namep != NULL)
+ *namep = name;
+ if (formp != NULL)
+ *formp = form;
+ if (offsetp != NULL)
+ *offsetp = (start_attrp - abbrev->attrp) + abbrev->offset;
+
+ return 0;
+}
diff --git a/libdw/dwarf_getabbrevcode.c b/libdw/dwarf_getabbrevcode.c
new file mode 100644
index 00000000..ef3dac46
--- /dev/null
+++ b/libdw/dwarf_getabbrevcode.c
@@ -0,0 +1,29 @@
+/* Get abbreviation code.
+ Copyright (C) 2003 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+unsigned int
+dwarf_getabbrevcode (abbrev)
+ Dwarf_Abbrev *abbrev;
+{
+ return abbrev == NULL ? 0 : abbrev->code;
+}
diff --git a/libdw/dwarf_getabbrevtag.c b/libdw/dwarf_getabbrevtag.c
new file mode 100644
index 00000000..4707fdd1
--- /dev/null
+++ b/libdw/dwarf_getabbrevtag.c
@@ -0,0 +1,29 @@
+/* Get abbreviation tag.
+ Copyright (C) 2003 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+unsigned int
+dwarf_getabbrevtag (abbrev)
+ Dwarf_Abbrev *abbrev;
+{
+ return abbrev == NULL ? 0 : abbrev->tag;
+}
diff --git a/libdw/dwarf_getarange_addr.c b/libdw/dwarf_getarange_addr.c
new file mode 100644
index 00000000..2d0408e4
--- /dev/null
+++ b/libdw/dwarf_getarange_addr.c
@@ -0,0 +1,47 @@
+/* Get address range which includes given address.
+ Copyright (C) 2004, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwP.h>
+
+
+Dwarf_Arange *
+dwarf_getarange_addr (aranges, addr)
+ Dwarf_Aranges *aranges;
+ Dwarf_Addr addr;
+{
+ if (aranges == NULL)
+ return NULL;
+
+ /* The ranges are sorted by address, so we can use binary search. */
+ size_t l = 0, u = aranges->naranges;
+ while (l < u)
+ {
+ size_t idx = (l + u) / 2;
+ if (addr < aranges->info[idx].addr)
+ u = idx;
+ else if (addr > aranges->info[idx].addr
+ && addr - aranges->info[idx].addr >= aranges->info[idx].length)
+ l = idx + 1;
+ else
+ return &aranges->info[idx];
+ }
+
+ __libdw_seterrno (DWARF_E_NO_MATCH);
+ return NULL;
+}
+INTDEF(dwarf_getarange_addr)
diff --git a/libdw/dwarf_getarangeinfo.c b/libdw/dwarf_getarangeinfo.c
new file mode 100644
index 00000000..eb1f539d
--- /dev/null
+++ b/libdw/dwarf_getarangeinfo.c
@@ -0,0 +1,38 @@
+/* Return list address ranges.
+ Copyright (C) 2000, 2001, 2002, 2004, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwP.h>
+
+
+int
+dwarf_getarangeinfo (Dwarf_Arange *arange, Dwarf_Addr *addrp,
+ Dwarf_Word *lengthp, Dwarf_Off *offsetp)
+{
+ if (arange == NULL)
+ return -1;
+
+ if (addrp != NULL)
+ *addrp = arange->addr;
+ if (lengthp != NULL)
+ *lengthp = arange->length;
+ if (offsetp != NULL)
+ *offsetp = arange->offset;
+
+ return 0;
+}
+INTDEF(dwarf_getarangeinfo)
diff --git a/libdw/dwarf_getaranges.c b/libdw/dwarf_getaranges.c
new file mode 100644
index 00000000..f7cf050f
--- /dev/null
+++ b/libdw/dwarf_getaranges.c
@@ -0,0 +1,212 @@
+/* Return list address ranges.
+ Copyright (C) 2000, 2001, 2002, 2004, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <assert.h>
+#include "libdwP.h"
+
+
+struct arangelist
+{
+ Dwarf_Arange arange;
+ struct arangelist *next;
+};
+
+/* Compare by Dwarf_Arange.addr, given pointers into an array of pointeers. */
+static int
+compare_aranges (const void *a, const void *b)
+{
+ Dwarf_Arange *const *p1 = a, *const *p2 = b;
+ Dwarf_Arange *l1 = *p1, *l2 = *p2;
+ return l1->addr - l2->addr;
+}
+
+int
+dwarf_getaranges (dbg, aranges, naranges)
+ Dwarf *dbg;
+ Dwarf_Aranges **aranges;
+ size_t *naranges;
+{
+ if (dbg == NULL)
+ return -1;
+
+ if (dbg->aranges != NULL)
+ {
+ *aranges = dbg->aranges;
+ if (naranges != NULL)
+ *naranges = dbg->aranges->naranges;
+ return 0;
+ }
+
+ if (dbg->sectiondata[IDX_debug_aranges]->d_buf == NULL)
+ return -1;
+
+ struct arangelist *arangelist = NULL;
+ unsigned int narangelist = 0;
+
+ const char *readp
+ = (const char *) dbg->sectiondata[IDX_debug_aranges]->d_buf;
+ const char *readendp = readp + dbg->sectiondata[IDX_debug_aranges]->d_size;
+
+ while (readp < readendp)
+ {
+ const char *hdrstart = readp;
+
+ /* Each entry starts with a header:
+
+ 1. A 4-byte or 12-byte length containing the length of the
+ set of entries for this compilation unit, not including the
+ length field itself. [...]
+
+ 2. A 2-byte version identifier containing the value 2 for
+ DWARF Version 2.1.
+
+ 3. A 4-byte or 8-byte offset into the .debug_info section. [...]
+
+ 4. A 1-byte unsigned integer containing the size in bytes of
+ an address (or the offset portion of an address for segmented
+ addressing) on the target system.
+
+ 5. A 1-byte unsigned integer containing the size in bytes of
+ a segment descriptor on the target system. */
+ Dwarf_Word length = read_4ubyte_unaligned_inc (dbg, readp);
+ unsigned int length_bytes = 4;
+ if (length == 0xffffffff)
+ {
+ length = read_8ubyte_unaligned_inc (dbg, readp);
+ length_bytes = 8;
+ }
+
+ unsigned int version = read_2ubyte_unaligned_inc (dbg, readp);
+ if (version != 2)
+ {
+ invalid:
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return -1;
+ }
+
+ Dwarf_Word offset;
+ if (length_bytes == 4)
+ offset = read_4ubyte_unaligned_inc (dbg, readp);
+ else
+ offset = read_8ubyte_unaligned_inc (dbg, readp);
+
+ unsigned int address_size = *readp++;
+ if (address_size != 4 && address_size != 8)
+ goto invalid;
+
+ /* Ignore the segment size value. */
+ // XXX Really?
+ (void) *readp++;
+
+ /* Round the address to the next multiple of 2*address_size. */
+ readp += ((2 * address_size - ((readp - hdrstart) % (2 * address_size)))
+ % (2 * address_size));
+
+ while (1)
+ {
+ Dwarf_Word range_address;
+ Dwarf_Word range_length;
+
+ if (address_size == 4)
+ {
+ range_address = read_4ubyte_unaligned_inc (dbg, readp);
+ range_length = read_4ubyte_unaligned_inc (dbg, readp);
+ }
+ else
+ {
+ range_address = read_8ubyte_unaligned_inc (dbg, readp);
+ range_length = read_8ubyte_unaligned_inc (dbg, readp);
+ }
+
+ /* Two zero values mark the end. */
+ if (range_address == 0 && range_length == 0)
+ break;
+
+ struct arangelist *new_arange =
+ (struct arangelist *) alloca (sizeof (struct arangelist));
+
+ new_arange->arange.addr = range_address;
+ new_arange->arange.length = range_length;
+
+ /* We store the actual CU DIE offset, not the CU header offset. */
+ const char *cu_header = (dbg->sectiondata[IDX_debug_info]->d_buf
+ + offset);
+ unsigned int offset_size;
+ if (read_4ubyte_unaligned_noncvt (cu_header) == 0xffffffff)
+ offset_size = 8;
+ else
+ offset_size = 4;
+ new_arange->arange.offset = offset + 3 * offset_size - 4 + 3;
+
+ new_arange->next = arangelist;
+ arangelist = new_arange;
+ ++narangelist;
+ }
+ }
+
+ if (narangelist == 0)
+ {
+ if (naranges != NULL)
+ *naranges = 0;
+ *aranges = NULL;
+ return 0;
+ }
+
+ /* Allocate the array for the result. */
+ void *buf = libdw_alloc (dbg, Dwarf_Aranges,
+ sizeof (Dwarf_Aranges)
+ + narangelist * sizeof (Dwarf_Arange), 1);
+
+ /* First use the buffer for the pointers, and sort the entries.
+ We'll write the pointers in the end of the buffer, and then
+ copy into the buffer from the beginning so the overlap works. */
+ assert (sizeof (Dwarf_Arange) >= sizeof (Dwarf_Arange *));
+ Dwarf_Arange **sortaranges = (buf + sizeof (Dwarf_Aranges)
+ + ((sizeof (Dwarf_Arange)
+ - sizeof (Dwarf_Arange *)) * narangelist));
+
+ /* The list is in LIFO order and usually they come in clumps with
+ ascending addresses. So fill from the back to probably start with
+ runs already in order before we sort. */
+ unsigned int i = narangelist;
+ while (i-- > 0)
+ {
+ sortaranges[i] = &arangelist->arange;
+ arangelist = arangelist->next;
+ }
+ assert (arangelist == NULL);
+
+ /* Sort by ascending address. */
+ qsort (sortaranges, narangelist, sizeof sortaranges[0], &compare_aranges);
+
+ /* Now that they are sorted, put them in the final array.
+ The buffers overlap, so we've clobbered the early elements
+ of SORTARANGES by the time we're reading the later ones. */
+ *aranges = buf;
+ (*aranges)->dbg = dbg;
+ (*aranges)->naranges = narangelist;
+ dbg->aranges = *aranges;
+ if (naranges != NULL)
+ *naranges = narangelist;
+ for (i = 0; i < narangelist; ++i)
+ (*aranges)->info[i] = *sortaranges[i];
+
+ return 0;
+}
+INTDEF(dwarf_getaranges)
diff --git a/libdw/dwarf_getattrcnt.c b/libdw/dwarf_getattrcnt.c
new file mode 100644
index 00000000..0758e030
--- /dev/null
+++ b/libdw/dwarf_getattrcnt.c
@@ -0,0 +1,33 @@
+/* Get number of attributes of abbreviation.
+ Copyright (C) 2003, 2004 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_getattrcnt (abbrev, attrcntp)
+ Dwarf_Abbrev *abbrev;
+ size_t *attrcntp;
+{
+ if (abbrev == NULL)
+ return -1;
+
+ *attrcntp = abbrev->attrcnt;
+
+ return 0;
+}
diff --git a/libdw/dwarf_getattrs.c b/libdw/dwarf_getattrs.c
new file mode 100644
index 00000000..8e6326d7
--- /dev/null
+++ b/libdw/dwarf_getattrs.c
@@ -0,0 +1,94 @@
+/* Get attributes of the DIE.
+ Copyright (C) 2004, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+ptrdiff_t
+dwarf_getattrs (Dwarf_Die *die, int (*callback) (Dwarf_Attribute *, void *),
+ void *arg, ptrdiff_t offset)
+{
+ if (die == NULL)
+ return -1l;
+
+ const unsigned char *die_addr = die->addr;
+
+ /* Get the abbreviation code. */
+ unsigned int u128;
+ get_uleb128 (u128, die_addr);
+
+ if (die->abbrev == NULL)
+ /* Find the abbreviation. */
+ die->abbrev = __libdw_findabbrev (die->cu, u128);
+
+ if (die->abbrev == (Dwarf_Abbrev *) -1l)
+ {
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return -1l;
+ }
+
+ /* This is where the attributes start. */
+ const unsigned char *attrp = die->abbrev->attrp + offset;
+
+ /* Go over the list of attributes. */
+ Dwarf *dbg = die->cu->dbg;
+ while (1)
+ {
+ /* Are we still in bounds? */
+ if (unlikely (attrp
+ >= ((unsigned char *) dbg->sectiondata[IDX_debug_abbrev]->d_buf
+ + dbg->sectiondata[IDX_debug_abbrev]->d_size)))
+ {
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return -1;
+ }
+
+ /* Get attribute name and form. */
+ Dwarf_Attribute attr;
+ // XXX Fix bound checks
+ get_uleb128 (attr.code, attrp);
+ get_uleb128 (attr.form, attrp);
+
+ /* We can stop if we found the attribute with value zero. */
+ if (attr.code == 0 && attr.form == 0)
+ return 0;
+
+ /* Fill in the rest. */
+ attr.valp = (unsigned char *) die_addr;
+ attr.cu = die->cu;
+
+ /* Now call the callback function. */
+ if (callback (&attr, arg) != DWARF_CB_OK)
+ return attrp - die->abbrev->attrp;
+
+ /* Skip over the rest of this attribute (if there is any). */
+ if (attr.form != 0)
+ {
+ size_t len = __libdw_form_val_len (dbg, die->cu, attr.form,
+ die_addr);
+
+ if (unlikely (len == (size_t) -1l))
+ /* Something wrong with the file. */
+ return -1l;
+
+ // XXX We need better boundary checks.
+ die_addr += len;
+ }
+ }
+ /* NOTREACHED */
+}
diff --git a/libdw/dwarf_getelf.c b/libdw/dwarf_getelf.c
new file mode 100644
index 00000000..1e2a06aa
--- /dev/null
+++ b/libdw/dwarf_getelf.c
@@ -0,0 +1,33 @@
+/* Retrieve ELF descriptor used for DWARF access.
+ Copyright (C) 2002, 2004 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+
+#include "libdwP.h"
+
+
+Elf *
+dwarf_get_elf (dwarf)
+ Dwarf *dwarf;
+{
+ if (dwarf == NULL)
+ /* Some error occurred before. */
+ return NULL;
+
+ return dwarf->elf;
+}
diff --git a/libdw/dwarf_getfuncs.c b/libdw/dwarf_getfuncs.c
new file mode 100644
index 00000000..149f1860
--- /dev/null
+++ b/libdw/dwarf_getfuncs.c
@@ -0,0 +1,63 @@
+/* Get function information.
+ Copyright (C) 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+ptrdiff_t
+dwarf_getfuncs (Dwarf_Die *cudie, int (*callback) (Dwarf_Func *, void *),
+ void *arg, ptrdiff_t offset)
+{
+ if (unlikely (cudie == NULL
+ || INTUSE(dwarf_tag) (cudie) != DW_TAG_compile_unit))
+ return -1;
+
+ Dwarf_Die die_mem;
+ Dwarf_Die *die;
+
+ int res;
+ if (offset == 0)
+ res = INTUSE(dwarf_child) (cudie, &die_mem);
+ else
+ {
+ die = INTUSE(dwarf_offdie) (cudie->cu->dbg, offset, &die_mem);
+ res = INTUSE(dwarf_siblingof) (die, &die_mem);
+ }
+ die = res != 0 ? NULL : &die_mem;
+
+ while (die != NULL)
+ {
+ if (INTUSE(dwarf_tag) (die) == DW_TAG_subprogram)
+ {
+ Dwarf_Func fct;
+
+ fct.die = die;
+ fct.cudie = cudie;
+
+ if (callback (&fct, arg) != DWARF_CB_OK)
+ return INTUSE(dwarf_dieoffset) (die);
+ }
+
+ if (INTUSE(dwarf_siblingof) (die, &die_mem) != 0)
+ break;
+ }
+
+ /* That's all. */
+ return 0;
+}
diff --git a/libdw/dwarf_getloclist.c b/libdw/dwarf_getloclist.c
new file mode 100644
index 00000000..ab7c3869
--- /dev/null
+++ b/libdw/dwarf_getloclist.c
@@ -0,0 +1,454 @@
+/* Return location expression list.
+ Copyright (C) 2000, 2001, 2002, 2004, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include <search.h>
+#include <stdlib.h>
+
+#include <libdwP.h>
+
+
+static bool
+attr_ok (Dwarf_Attribute *attr)
+{
+ if (attr == NULL)
+ return false;
+
+ /* Must be one of the attributes listed below. */
+ switch (attr->code)
+ {
+ case DW_AT_location:
+ case DW_AT_data_member_location:
+ case DW_AT_vtable_elem_location:
+ case DW_AT_string_length:
+ case DW_AT_use_location:
+ case DW_AT_frame_base:
+ case DW_AT_return_addr:
+ case DW_AT_static_link:
+ break;
+
+ default:
+ __libdw_seterrno (DWARF_E_NO_LOCLIST);
+ return false;
+ }
+
+ return true;
+}
+
+
+struct loclist
+{
+ uint8_t atom;
+ Dwarf_Word number;
+ Dwarf_Word number2;
+ Dwarf_Word offset;
+ struct loclist *next;
+};
+
+
+static int
+loc_compare (const void *p1, const void *p2)
+{
+ const struct loc_s *l1 = (const struct loc_s *) p1;
+ const struct loc_s *l2 = (const struct loc_s *) p2;
+
+ if ((uintptr_t) l1->addr < (uintptr_t) l2->addr)
+ return -1;
+ if ((uintptr_t) l1->addr > (uintptr_t) l2->addr)
+ return 1;
+
+ return 0;
+}
+
+static int
+getloclist (struct Dwarf_CU *cu, const Dwarf_Block *block,
+ Dwarf_Loc **llbuf, size_t *listlen)
+{
+ Dwarf *dbg = cu->dbg;
+
+ /* Check whether we already looked at this list. */
+ struct loc_s fake = { .addr = block->data };
+ struct loc_s **found = tfind (&fake, &cu->locs, loc_compare);
+ if (found != NULL)
+ {
+ /* We already saw it. */
+ *llbuf = (*found)->loc;
+ *listlen = (*found)->nloc;
+
+ return 0;
+ }
+
+ const unsigned char *data = block->data;
+ const unsigned char *const end_data = data + block->length;
+
+ struct loclist *loclist = NULL;
+ unsigned int n = 0;
+ /* Decode the opcodes. It is possible in some situations to have a
+ block of size zero. */
+ while (data < end_data)
+ {
+ struct loclist *newloc;
+ newloc = (struct loclist *) alloca (sizeof (struct loclist));
+ newloc->number = 0;
+ newloc->number2 = 0;
+ newloc->offset = data - block->data;
+ newloc->next = loclist;
+ loclist = newloc;
+ ++n;
+
+ switch ((newloc->atom = *data++))
+ {
+ case DW_OP_addr:
+ /* Address, depends on address size of CU. */
+ if (cu->address_size == 4)
+ {
+ if (unlikely (data + 4 > end_data))
+ {
+ invalid:
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return -1;
+ }
+
+ newloc->number = read_4ubyte_unaligned_inc (dbg, data);
+ }
+ else
+ {
+ if (unlikely (data + 8 > end_data))
+ goto invalid;
+
+ newloc->number = read_8ubyte_unaligned_inc (dbg, data);
+ }
+ break;
+
+ case DW_OP_deref:
+ case DW_OP_dup:
+ case DW_OP_drop:
+ case DW_OP_over:
+ case DW_OP_swap:
+ case DW_OP_rot:
+ case DW_OP_xderef:
+ case DW_OP_abs:
+ case DW_OP_and:
+ case DW_OP_div:
+ case DW_OP_minus:
+ case DW_OP_mod:
+ case DW_OP_mul:
+ case DW_OP_neg:
+ case DW_OP_not:
+ case DW_OP_or:
+ case DW_OP_plus:
+ case DW_OP_shl:
+ case DW_OP_shr:
+ case DW_OP_shra:
+ case DW_OP_xor:
+ case DW_OP_eq:
+ case DW_OP_ge:
+ case DW_OP_gt:
+ case DW_OP_le:
+ case DW_OP_lt:
+ case DW_OP_ne:
+ case DW_OP_lit0 ... DW_OP_lit31:
+ case DW_OP_reg0 ... DW_OP_reg31:
+ case DW_OP_nop:
+ case DW_OP_push_object_address:
+ case DW_OP_call_ref:
+ /* No operand. */
+ break;
+
+ case DW_OP_const1u:
+ case DW_OP_pick:
+ case DW_OP_deref_size:
+ case DW_OP_xderef_size:
+ if (unlikely (data >= end_data))
+ goto invalid;
+
+ newloc->number = *data++;
+ break;
+
+ case DW_OP_const1s:
+ if (unlikely (data >= end_data))
+ goto invalid;
+
+ newloc->number = *((int8_t *) data);
+ ++data;
+ break;
+
+ case DW_OP_const2u:
+ if (unlikely (data + 2 > end_data))
+ goto invalid;
+
+ newloc->number = read_2ubyte_unaligned_inc (dbg, data);
+ break;
+
+ case DW_OP_const2s:
+ case DW_OP_skip:
+ case DW_OP_bra:
+ case DW_OP_call2:
+ if (unlikely (data + 2 > end_data))
+ goto invalid;
+
+ newloc->number = read_2sbyte_unaligned_inc (dbg, data);
+ break;
+
+ case DW_OP_const4u:
+ if (unlikely (data + 4 > end_data))
+ goto invalid;
+
+ newloc->number = read_4ubyte_unaligned_inc (dbg, data);
+ break;
+
+ case DW_OP_const4s:
+ case DW_OP_call4:
+ if (unlikely (data + 4 > end_data))
+ goto invalid;
+
+ newloc->number = read_4sbyte_unaligned_inc (dbg, data);
+ break;
+
+ case DW_OP_const8u:
+ if (unlikely (data + 8 > end_data))
+ goto invalid;
+
+ newloc->number = read_8ubyte_unaligned_inc (dbg, data);
+ break;
+
+ case DW_OP_const8s:
+ if (unlikely (data + 8 > end_data))
+ goto invalid;
+
+ newloc->number = read_8sbyte_unaligned_inc (dbg, data);
+ break;
+
+ case DW_OP_constu:
+ case DW_OP_plus_uconst:
+ case DW_OP_regx:
+ case DW_OP_piece:
+ /* XXX Check size. */
+ get_uleb128 (newloc->number, data);
+ break;
+
+ case DW_OP_consts:
+ case DW_OP_breg0 ... DW_OP_breg31:
+ case DW_OP_fbreg:
+ /* XXX Check size. */
+ get_sleb128 (newloc->number, data);
+ break;
+
+ case DW_OP_bregx:
+ /* XXX Check size. */
+ get_uleb128 (newloc->number, data);
+ get_sleb128 (newloc->number2, data);
+ break;
+
+ default:
+ goto invalid;
+ }
+ }
+
+ if (unlikely (n == 0))
+ {
+ /* This is not allowed.
+
+ XXX Is it? */
+ goto invalid;
+ }
+
+ /* Allocate the array. */
+ Dwarf_Loc *result = libdw_alloc (dbg, Dwarf_Loc, sizeof (Dwarf_Loc), n);
+
+ /* Store the result. */
+ *llbuf = result;
+ *listlen = n;
+
+ do
+ {
+ /* We populate the array from the back since the list is
+ backwards. */
+ --n;
+ result[n].atom = loclist->atom;
+ result[n].number = loclist->number;
+ result[n].number2 = loclist->number2;
+ result[n].offset = loclist->offset;
+
+ loclist = loclist->next;
+ }
+ while (n > 0);
+
+ /* Insert a record in the search tree so that we can find it again
+ later. */
+ struct loc_s *newp = libdw_alloc (dbg, struct loc_s, sizeof (struct loc_s),
+ 1);
+ newp->addr = block->data;
+ newp->loc = result;
+ newp->nloc = *listlen;
+ (void) tsearch (newp, &cu->locs, loc_compare);
+
+ /* We did it. */
+ return 0;
+}
+
+int
+dwarf_getloclist (attr, llbuf, listlen)
+ Dwarf_Attribute *attr;
+ Dwarf_Loc **llbuf;
+ size_t *listlen;
+{
+ if (! attr_ok (attr))
+ return -1;
+
+ /* If it has a block form, it's a single location expression. */
+ Dwarf_Block block;
+ if (INTUSE(dwarf_formblock) (attr, &block) != 0)
+ return -1;
+
+ return getloclist (attr->cu, &block, llbuf, listlen);
+}
+
+int
+dwarf_addrloclists (attr, address, llbufs, listlens, maxlocs)
+ Dwarf_Attribute *attr;
+ Dwarf_Addr address;
+ Dwarf_Loc **llbufs;
+ size_t *listlens;
+ size_t maxlocs;
+{
+ if (! attr_ok (attr))
+ return -1;
+
+ if (llbufs == NULL)
+ maxlocs = SIZE_MAX;
+
+ /* If it has a block form, it's a single location expression. */
+ Dwarf_Block block;
+ if (INTUSE(dwarf_formblock) (attr, &block) == 0)
+ {
+ if (maxlocs == 0)
+ return 0;
+ if (llbufs != NULL &&
+ getloclist (attr->cu, &block, &llbufs[0], &listlens[0]) != 0)
+ return -1;
+ return listlens[0] == 0 ? 0 : 1;
+ }
+
+ int error = INTUSE(dwarf_errno) ();
+ if (error != DWARF_E_NO_BLOCK)
+ {
+ __libdw_seterrno (error);
+ return -1;
+ }
+
+ /* Must have the form data4 or data8 which act as an offset. */
+ Dwarf_Word offset;
+ if (INTUSE(dwarf_formudata) (attr, &offset) != 0)
+ return -1;
+
+ const Elf_Data *d = attr->cu->dbg->sectiondata[IDX_debug_loc];
+ if (d == NULL)
+ {
+ __libdw_seterrno (DWARF_E_NO_LOCLIST);
+ return -1;
+ }
+
+ /* Fetch the CU's base address. */
+ Dwarf_Addr base;
+ Dwarf_Die cudie =
+ {
+ .cu = attr->cu,
+ .addr = ((char *) attr->cu->dbg->sectiondata[IDX_debug_info]->d_buf
+ + attr->cu->start + 3 * attr->cu->offset_size - 4 + 3),
+ };
+
+
+ /* Find the base address of the compilation unit. It will
+ normally be specified by DW_AT_low_pc. In DWARF-3 draft 4,
+ the base address could be overridden by DW_AT_entry_pc. It's
+ been removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc
+ for compilation units with discontinuous ranges. */
+ Dwarf_Attribute attr_mem;
+ if (INTUSE(dwarf_lowpc) (&cudie, &base) != 0
+ && INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (&cudie, DW_AT_entry_pc,
+ &attr_mem),
+ &base) != 0)
+ return -1;
+
+ unsigned char *readp = d->d_buf + offset;
+ size_t got = 0;
+ while (got < maxlocs)
+ {
+ if ((unsigned char *) d->d_buf + d->d_size - readp
+ < attr->cu->address_size * 2)
+ {
+ invalid:
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return -1;
+ }
+
+ Dwarf_Addr begin;
+ Dwarf_Addr end;
+ if (attr->cu->address_size == 8)
+ {
+ begin = read_8ubyte_unaligned_inc (attr->cu->dbg, readp);
+ end = read_8ubyte_unaligned_inc (attr->cu->dbg, readp);
+
+ if (begin == (Elf64_Addr) -1l) /* Base address entry. */
+ {
+ base = end;
+ continue;
+ }
+ }
+ else
+ {
+ begin = read_4ubyte_unaligned_inc (attr->cu->dbg, readp);
+ end = read_4ubyte_unaligned_inc (attr->cu->dbg, readp);
+
+ if (begin == (Elf32_Addr) -1) /* Base address entry. */
+ {
+ base = end;
+ continue;
+ }
+ }
+
+ if (begin == 0 && end == 0) /* End of list entry. */
+ break;
+
+ if ((unsigned char *) d->d_buf + d->d_size - readp < 2)
+ {
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return -1;
+ }
+
+ /* We have a location expression. */
+ block.length = read_2ubyte_unaligned_inc (attr->cu->dbg, readp);
+ block.data = readp;
+ if ((unsigned char *) d->d_buf + d->d_size - readp
+ < (ptrdiff_t) block.length)
+ goto invalid;
+ readp += block.length;
+
+ if (address >= base + begin && address < base + end)
+ {
+ /* This one matches the address. */
+ if (llbufs != NULL && getloclist (attr->cu, &block,
+ &llbufs[got], &listlens[got]) != 0)
+ return -1;
+ ++got;
+ }
+ }
+
+ return got;
+}
diff --git a/libdw/dwarf_getmacros.c b/libdw/dwarf_getmacros.c
new file mode 100644
index 00000000..d3678c99
--- /dev/null
+++ b/libdw/dwarf_getmacros.c
@@ -0,0 +1,119 @@
+/* Get macro information.
+ Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include <string.h>
+
+#include <libdwP.h>
+
+
+ptrdiff_t
+dwarf_getmacros (die, callback, arg, offset)
+ Dwarf_Die *die;
+ int (*callback) (Dwarf_Macro *, void *);
+ void *arg;
+ ptrdiff_t offset;
+{
+ /* Get the appropriate attribute. */
+ Dwarf_Attribute attr;
+ if (INTUSE(dwarf_attr) (die, DW_AT_macro_info, &attr) == NULL)
+ return -1;
+
+ /* Offset into the .debug_macinfo section. */
+ Dwarf_Word macoff;
+ if (INTUSE(dwarf_formudata) (&attr, &macoff) != 0)
+ return -1;
+
+ const unsigned char *readp
+ = die->cu->dbg->sectiondata[IDX_debug_macinfo]->d_buf + offset;
+ const unsigned char *readendp
+ = readp + die->cu->dbg->sectiondata[IDX_debug_macinfo]->d_size;
+
+ if (readp == readendp)
+ return 0;
+
+ if (*readp != DW_MACINFO_start_file)
+ goto invalid;
+
+ while (readp < readendp)
+ {
+ unsigned int opcode = *readp++;
+ unsigned int u128;
+ unsigned int u128_2 = 0;
+ const char *str = NULL;
+ const unsigned char *endp;
+
+ switch (opcode)
+ {
+ case DW_MACINFO_define:
+ case DW_MACINFO_undef:
+ case DW_MACINFO_vendor_ext:
+ /* For the first two opcodes the parameters are
+ line, string
+ For the latter
+ number, string.
+ We can treat these cases together. */
+ get_uleb128 (u128, readp);
+
+ endp = memchr (readp, '\0', readendp - readp);
+ if (endp == NULL)
+ goto invalid;
+
+ str = (char *) readp;
+ readp = endp + 1;
+ break;
+
+ case DW_MACINFO_start_file:
+ /* The two parameters are line and file index. */
+ get_uleb128 (u128, readp);
+ get_uleb128 (u128_2, readp);
+ break;
+
+ case DW_MACINFO_end_file:
+ /* No parameters for this one. */
+ u128 = 0;
+ break;
+
+ case 0:
+ /* Nothing more to do. */
+ return 0;
+
+ default:
+ goto invalid;
+ }
+
+ Dwarf_Macro mac;
+ mac.opcode = opcode;
+ mac.param1 = u128;
+ if (str == NULL)
+ mac.param2.u = u128_2;
+ else
+ mac.param2.s = str;
+
+ if (callback (&mac, arg) != DWARF_CB_OK)
+ return (readp
+ - ((unsigned char *) die->cu->dbg->sectiondata[IDX_debug_macinfo]->d_buf
+ + offset));
+ }
+
+ /* If we come here the termination of the data for the CU is not
+ present. */
+ invalid:
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return -1;
+}
diff --git a/libdw/dwarf_getpubnames.c b/libdw/dwarf_getpubnames.c
new file mode 100644
index 00000000..5700cd77
--- /dev/null
+++ b/libdw/dwarf_getpubnames.c
@@ -0,0 +1,213 @@
+/* Get public symbol information.
+ Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+
+#include <libdwP.h>
+
+
+static int
+get_offsets (Dwarf *dbg)
+{
+ size_t allocated = 0;
+ size_t cnt = 0;
+ struct pubnames_s *mem = NULL;
+ const size_t entsize = sizeof (struct pubnames_s);
+ unsigned char *const startp = dbg->sectiondata[IDX_debug_pubnames]->d_buf;
+ unsigned char *readp = startp;
+ unsigned char *endp = readp + dbg->sectiondata[IDX_debug_pubnames]->d_size;
+
+ while (readp + 14 < endp)
+ {
+ /* If necessary, allocate more entries. */
+ if (cnt >= allocated)
+ {
+ allocated = MAX (10, 2 * allocated);
+ struct pubnames_s *newmem
+ = (struct pubnames_s *) realloc (mem, allocated * entsize);
+ if (newmem == NULL)
+ {
+ __libdw_seterrno (DWARF_E_NOMEM);
+ err_return:
+ free (mem);
+ return -1;
+ }
+
+ mem = newmem;
+ }
+
+ /* Read the set header. */
+ int len_bytes = 4;
+ Dwarf_Off len = read_4ubyte_unaligned_inc (dbg, readp);
+ if (len == 0xffffffff)
+ {
+ len = read_8ubyte_unaligned_inc (dbg, readp);
+ len_bytes = 8;
+ }
+
+ /* Now we know the offset of the first offset/name pair. */
+ mem[cnt].set_start = readp + 2 + 2 * len_bytes - startp;
+ mem[cnt].address_len = len_bytes;
+ if (mem[cnt].set_start >= dbg->sectiondata[IDX_debug_pubnames]->d_size)
+ /* Something wrong, the first entry is beyond the end of
+ the section. */
+ break;
+
+ /* Read the version. It better be two for now. */
+ uint16_t version = read_2ubyte_unaligned (dbg, readp);
+ if (version != 2)
+ {
+ __libdw_seterrno (DWARF_E_INVALID_VERSION);
+ goto err_return;
+ }
+
+ /* Get the CU offset. */
+ if (len_bytes == 4)
+ mem[cnt].cu_offset = read_4ubyte_unaligned (dbg, readp + 2);
+ else
+ mem[cnt].cu_offset = read_8ubyte_unaligned (dbg, readp + 2);
+
+ /* Determine the size of the CU header. */
+ assert (dbg->sectiondata[IDX_debug_info] != NULL);
+ assert (dbg->sectiondata[IDX_debug_info]->d_buf != NULL);
+ assert (mem[cnt].cu_offset + 3
+ < dbg->sectiondata[IDX_debug_info]->d_size);
+ unsigned char *infop
+ = ((unsigned char *) dbg->sectiondata[IDX_debug_info]->d_buf
+ + mem[cnt].cu_offset);
+ if (read_4ubyte_unaligned_noncvt (infop) == 0xffffffff)
+ mem[cnt].cu_header_size = 23;
+ else
+ mem[cnt].cu_header_size = 11;
+
+ ++cnt;
+
+ /* Advance to the next set. */
+ readp += len;
+ }
+
+ if (mem == NULL)
+ {
+ __libdw_seterrno (DWARF_E_NO_ENTRY);
+ return -1;
+ }
+
+ dbg->pubnames_sets = (struct pubnames_s *) realloc (mem, cnt * entsize);
+ dbg->pubnames_nsets = cnt;
+
+ return 0;
+}
+
+
+ptrdiff_t
+dwarf_getpubnames (dbg, callback, arg, offset)
+ Dwarf *dbg;
+ int (*callback) (Dwarf *, Dwarf_Global *, void *);
+ void *arg;
+ ptrdiff_t offset;
+{
+ if (dbg == NULL)
+ return -1l;
+
+ if (offset < 0)
+ {
+ __libdw_seterrno (DWARF_E_INVALID_OFFSET);
+ return -1l;
+ }
+
+ /* Make sure it is a valid offset. */
+ if (unlikely (dbg->sectiondata[IDX_debug_pubnames] == NULL
+ || ((size_t) offset
+ >= dbg->sectiondata[IDX_debug_pubnames]->d_size)))
+ /* No (more) entry. */
+ return 0;
+
+ /* If necessary read the set information. */
+ if (dbg->pubnames_nsets == 0 && get_offsets (dbg) != 0)
+ return -1l;
+
+ /* Find the place where to start. */
+ size_t cnt;
+ if (offset == 0)
+ {
+ cnt = 0;
+ offset = dbg->pubnames_sets[0].set_start;
+ }
+ else
+ {
+ for (cnt = 0; cnt + 1 < dbg->pubnames_nsets; ++cnt)
+ if ((Dwarf_Off) offset >= dbg->pubnames_sets[cnt].set_start)
+ {
+ assert ((Dwarf_Off) offset
+ < dbg->pubnames_sets[cnt + 1].set_start);
+ break;
+ }
+ assert (cnt + 1 < dbg->pubnames_nsets);
+ }
+
+ unsigned char *startp
+ = (unsigned char *) dbg->sectiondata[IDX_debug_pubnames]->d_buf;
+ unsigned char *readp = startp + offset;
+ while (1)
+ {
+ Dwarf_Global gl;
+
+ gl.cu_offset = (dbg->pubnames_sets[cnt].cu_offset
+ + dbg->pubnames_sets[cnt].cu_header_size);
+
+ while (1)
+ {
+ /* READP points to the next offset/name pair. */
+ if (dbg->pubnames_sets[cnt].address_len == 4)
+ gl.die_offset = read_4ubyte_unaligned_inc (dbg, readp);
+ else
+ gl.die_offset = read_8ubyte_unaligned_inc (dbg, readp);
+
+ /* If the offset is zero we reached the end of the set. */
+ if (gl.die_offset == 0)
+ break;
+
+ /* Add the CU offset. */
+ gl.die_offset += dbg->pubnames_sets[cnt].cu_offset;
+
+ gl.name = (char *) readp;
+ readp = (unsigned char *) rawmemchr (gl.name, '\0') + 1;
+
+ /* We found name and DIE offset. Report it. */
+ if (callback (dbg, &gl, arg) != DWARF_CB_OK)
+ {
+ /* The user wants us to stop. Return the offset of the
+ next entry. */
+ return readp - startp;
+ }
+ }
+
+ if (++cnt == dbg->pubnames_nsets)
+ /* This was the last set. */
+ break;
+
+ startp = (unsigned char *) dbg->sectiondata[IDX_debug_pubnames]->d_buf;
+ readp = startp + dbg->pubnames_sets[cnt].set_start;
+ }
+
+ /* We are done. No more entries. */
+ return 0;
+}
diff --git a/libdw/dwarf_getscopes.c b/libdw/dwarf_getscopes.c
new file mode 100644
index 00000000..21d6f20a
--- /dev/null
+++ b/libdw/dwarf_getscopes.c
@@ -0,0 +1,334 @@
+/* Return scope DIEs containing PC address.
+ Copyright (C) 2005 Red Hat, Inc.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include "libdwP.h"
+#include <dwarf.h>
+
+
+enum die_class { ignore, match, match_inline, walk, imported };
+
+static enum die_class
+classify_die (Dwarf_Die *die)
+{
+ switch (INTUSE(dwarf_tag) (die))
+ {
+ /* DIEs with addresses we can try to match. */
+ case DW_TAG_compile_unit:
+ case DW_TAG_module:
+ case DW_TAG_lexical_block:
+ case DW_TAG_with_stmt:
+ case DW_TAG_catch_block:
+ case DW_TAG_try_block:
+ case DW_TAG_entry_point:
+ return match;
+ case DW_TAG_inlined_subroutine:
+ return match_inline;
+ case DW_TAG_subprogram:
+ /* This might be a concrete out-of-line instance of an inline, in
+ which case it is not guaranteed to be owned by the right scope and
+ we will search for its origin as for DW_TAG_inlined_subroutine. */
+ return (INTUSE(dwarf_hasattr) (die, DW_AT_abstract_origin)
+ ? match_inline : match);
+
+ /* DIEs without addresses that can own DIEs with addresses. */
+ case DW_TAG_namespace:
+ return walk;
+
+ /* Special indirection required. */
+ case DW_TAG_imported_unit:
+ return imported;
+
+ /* Other DIEs we have no reason to descend. */
+ default:
+ break;
+ }
+ return ignore;
+}
+
+/* DIE contains PC. Find its child that contains PC. Returns -1 for
+ errors, 0 for no matches. On success, *SCOPES gets the malloc'd array
+ of containing scopes. A positive return value is the number of those
+ scopes. A return value < -1 is -1 - number of those scopes, when the
+ outermost scope is a concrete instance of an inline subroutine. */
+static int
+find_pc (unsigned int depth, Dwarf_Die *die, Dwarf_Addr pc, Dwarf_Die **scopes)
+{
+ Dwarf_Die child;
+ if (INTUSE(dwarf_child) (die, &child) != 0)
+ return -1;
+
+ /* Recurse on this DIE to search within its children.
+ Return nonzero if this gets an error or a final result. */
+ inline int search_child (void)
+ {
+ int n = find_pc (depth + 1, &child, pc, scopes);
+ if (n > 0)
+ /* That stored the N innermost scopes. Now store ours. */
+ (*scopes)[n++] = child;
+ return n;
+ }
+
+ /* Check each of our child DIEs. */
+ enum die_class got = ignore;
+ do
+ {
+ enum die_class child_class = classify_die (&child);
+ switch (child_class)
+ {
+ case match:
+ case match_inline:
+ if (INTUSE(dwarf_haspc) (&child, pc) > 0)
+ break;
+ continue;
+
+ case walk:
+ if (INTUSE(dwarf_haschildren) (&child))
+ got = walk;
+ continue;
+
+ case imported:
+ got = walk;
+ continue;
+
+ default:
+ case ignore:
+ continue;
+ }
+
+ /* We get here only when the PC has matched. */
+ got = child_class;
+ break;
+ }
+ while (INTUSE(dwarf_siblingof) (&child, &child) == 0);
+
+ switch (got)
+ {
+ case match:
+ case match_inline:
+ /* We have a DIE that matched the PC. */
+ if (INTUSE(dwarf_haschildren) (&child))
+ {
+ /* Recurse on this DIE to narrow within its children.
+ Return now if this gets an error or a final result. */
+ int result = search_child ();
+ if (result < 0 || (got == match && result > 0))
+ return result;
+ if (result > 0) /* got == match_inline */
+ /* We have a winner, but CHILD is a concrete inline instance
+ so DIE and its containing scopes do not actually apply.
+ DIE is the scope that inlined the function. Our root
+ caller must find the abstract scope that defines us. */
+ return -1 - result;
+ }
+
+ /* This DIE has no children containing the PC, so this is it. */
+ *scopes = malloc (depth * sizeof (*scopes)[0]);
+ if (*scopes == NULL)
+ {
+ __libdw_seterrno (DWARF_E_NOMEM);
+ return -1;
+ }
+ (*scopes)[0] = child;
+ return got == match ? 1 : -2;
+
+ case walk:
+ /* We don't have anything matching the PC, but we have some things
+ we might descend to find one. Recurse on each of those. */
+ if (INTUSE(dwarf_child) (die, &child) != 0)
+ return -1;
+ do
+ switch (classify_die (&child))
+ {
+ case walk:
+ if (INTUSE(dwarf_haschildren) (&child))
+ {
+ /* Recurse on this DIE to look for the PC within its children.
+ Return now if this gets an error or a final result. */
+ int result = search_child ();
+ if (result != 0)
+ return result;
+ }
+ break;
+
+ case imported:
+ {
+ /* This imports another compilation unit to appear
+ as part of this one, inside the current scope.
+ Recurse to search the referenced unit, but without
+ recording it as an inner scoping level. */
+
+ Dwarf_Attribute attr_mem;
+ Dwarf_Attribute *attr = INTUSE(dwarf_attr) (&child, DW_AT_import,
+ &attr_mem);
+ if (INTUSE(dwarf_formref_die) (attr, &child) != NULL)
+ {
+ int result = find_pc (depth, &child, pc, scopes);
+ if (result != 0)
+ return result;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ while (INTUSE(dwarf_siblingof) (&child, &child) == 0);
+ break;
+
+ default:
+ case ignore:
+ /* Nothing to see here. */
+ break;
+ }
+
+ /* No matches. */
+ return 0;
+}
+
+
+/* OWNER owns OWNED. Find intermediate scopes. *SCOPES was allocated by
+ find_pc and has SKIP elements. We realloc it, append more containing
+ scopes, and return 1 + the number appended. Returns -1 on errors,
+ or 0 when OWNED was not found within OWNER. */
+static int
+find_die (unsigned int depth, Dwarf_Die *owner, Dwarf_Die *owned,
+ Dwarf_Die **scopes, unsigned int skip)
+{
+ Dwarf_Die child;
+ if (INTUSE(dwarf_child) (owner, &child) != 0)
+ return -1;
+
+ do
+ {
+ if (child.addr == owned->addr)
+ /* This is the one. OWNER is the innermost owner. */
+ return 1;
+
+ /* Unfortunately we cannot short-circuit the dead-end paths just by
+ checking the physical layout to see if OWNED falls within CHILD.
+ If it doesn't, there may still be a DW_TAG_imported_unit that
+ refers to its true owner indirectly. */
+
+ switch (classify_die (&child))
+ {
+ case match:
+ case match_inline:
+ case walk:
+ if (INTUSE(dwarf_haschildren) (&child))
+ {
+ /* Recurse on this DIE to look for OWNED within its children.
+ Return now if this gets an error or a final result. */
+ int n = find_die (depth + 1, &child, owned, scopes, skip);
+ if (n < 0)
+ return n;
+ if (n > 1)
+ {
+ /* We have a winner. CHILD owns the owner of OWNED. */
+ (*scopes)[skip + n - 1] = child;
+ return n + 1;
+ }
+ if (n > 0) /* n == 1 */
+ {
+ /* CHILD is the direct owner of OWNED. */
+ Dwarf_Die *nscopes = realloc (*scopes,
+ (skip + depth)
+ * sizeof nscopes[0]);
+ if (nscopes == NULL)
+ {
+ free (*scopes);
+ *scopes = NULL;
+ __libdw_seterrno (DWARF_E_NOMEM);
+ return -1;
+ }
+ nscopes[skip] = child;
+ *scopes = nscopes;
+ return 2;
+ }
+ }
+ break;
+
+ case imported:
+ {
+ /* This is imports another compilation unit to appear
+ as part of this one, inside the current scope.
+ Recurse to search the referenced unit, but without
+ recording it as an inner scoping level. */
+
+ Dwarf_Attribute attr_mem;
+ Dwarf_Attribute *attr = INTUSE(dwarf_attr) (&child, DW_AT_import,
+ &attr_mem);
+ if (INTUSE(dwarf_formref_die) (attr, &child) != NULL)
+ {
+ int result = find_die (depth, &child, owner, scopes, skip);
+ if (result != 0)
+ return result;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ while (INTUSE(dwarf_siblingof) (&child, &child) == 0);
+
+ return 0;
+}
+
+
+int
+dwarf_getscopes (Dwarf_Die *cudie, Dwarf_Addr pc, Dwarf_Die **scopes)
+{
+ if (cudie == NULL)
+ return -1;
+
+ int n = find_pc (1, cudie, pc, scopes);
+ if (likely (n >= -1))
+ /* We have an error or a final result. */
+ return n;
+
+ /* We have the scopes out to one that is a concrete instance of an
+ inlined subroutine (usually DW_TAG_inlined_subroutine, but can
+ be DW_TAG_subprogram for a concrete out-of-line instance).
+ Now we must find the lexical scopes that contain the
+ corresponding abstract inline subroutine definition. */
+
+ n = -n - 1;
+
+ Dwarf_Attribute attr_mem;
+ Dwarf_Die die_mem;
+ Dwarf_Die *origin = INTUSE(dwarf_formref_die)
+ (INTUSE(dwarf_attr) (&(*scopes)[n - 1], DW_AT_abstract_origin, &attr_mem),
+ &die_mem);
+ if (unlikely (origin == NULL))
+ goto invalid;
+
+ int result = find_die (0, cudie, origin, scopes, n);
+ if (likely (result > 0))
+ return n + result - 1;
+
+ if (result == 0) /* No match, shouldn't happen. */
+ {
+ invalid:
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ }
+
+ free (*scopes);
+ *scopes = NULL;
+ return -1;
+}
diff --git a/libdw/dwarf_getscopevar.c b/libdw/dwarf_getscopevar.c
new file mode 100644
index 00000000..3ceb292d
--- /dev/null
+++ b/libdw/dwarf_getscopevar.c
@@ -0,0 +1,147 @@
+/* Find a named variable or parameter within given scopes.
+ Copyright (C) 2005 Red Hat, Inc.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdbool.h>
+#include <string.h>
+#include "libdwP.h"
+#include <dwarf.h>
+
+
+/* Find the containing CU's files. */
+static int
+getfiles (Dwarf_Die *die, Dwarf_Files **files)
+{
+ Dwarf_Die cudie =
+ {
+ .cu = die->cu,
+ .addr = ((char *) die->cu->dbg->sectiondata[IDX_debug_info]->d_buf
+ + 3 * die->cu->offset_size - 4 + 3),
+ };
+ return INTUSE(dwarf_getsrcfiles) (&cudie, files, NULL);
+}
+
+/* Fetch an attribute that should have a constant integer form. */
+static int
+getattr (Dwarf_Die *die, int search_name, Dwarf_Word *value)
+{
+ Dwarf_Attribute attr_mem;
+ return INTUSE(dwarf_formudata) (INTUSE(dwarf_attr) (die, search_name,
+ &attr_mem), value);
+}
+
+/* Search SCOPES[0..NSCOPES-1] for a variable called NAME.
+ Ignore the first SKIP_SHADOWS scopes that match the name.
+ If MATCH_FILE is not null, accept only declaration in that source file;
+ if MATCH_LINENO or MATCH_LINECOL are also nonzero, accept only declaration
+ at that line and column.
+
+ If successful, fill in *RESULT with the DIE of the variable found,
+ and return N where SCOPES[N] is the scope defining the variable.
+ Return -1 for errors or -2 for no matching variable found. */
+
+int
+dwarf_getscopevar (Dwarf_Die *scopes, int nscopes,
+ const char *name, int skip_shadows,
+ const char *match_file, int match_lineno, int match_linecol,
+ Dwarf_Die *result)
+{
+ /* Match against the given file name. */
+ size_t match_file_len = match_file == NULL ? 0 : strlen (match_file);
+ bool lastfile_matches = false;
+ const char *lastfile = NULL;
+ inline bool file_matches (Dwarf_Files *files, size_t idx)
+ {
+ if (idx >= files->nfiles)
+ return false;
+
+ const char *file = files->info[idx].name;
+ if (file != lastfile)
+ {
+ size_t len = strlen (file);
+ lastfile_matches = (len >= match_file_len
+ && !memcmp (match_file, file, match_file_len)
+ && (len == match_file_len
+ || file[len - match_file_len - 1] == '/'));
+ }
+ return lastfile_matches;
+ }
+
+ /* Start with the innermost scope and move out. */
+ for (int out = 0; out < nscopes; ++out)
+ if (INTUSE(dwarf_haschildren) (&scopes[out]))
+ {
+ if (INTUSE(dwarf_child) (&scopes[out], result) != 0)
+ return -1;
+ do
+ {
+ switch (INTUSE(dwarf_tag) (result))
+ {
+ case DW_TAG_variable:
+ case DW_TAG_formal_parameter:
+ break;
+
+ default:
+ continue;
+ }
+
+ /* Only get here for a variable or parameter. Check the name. */
+ Dwarf_Attribute attr_mem;
+ const char *diename = INTUSE(dwarf_formstring)
+ (INTUSE(dwarf_attr_integrate) (result, DW_AT_name, &attr_mem));
+ if (diename != NULL && !strcmp (name, diename))
+ {
+ /* We have a matching name. */
+
+ if (skip_shadows > 0)
+ {
+ /* Punt this scope for the one it shadows. */
+ --skip_shadows;
+ break;
+ }
+
+ if (match_file != NULL)
+ {
+ /* Check its decl_file. */
+
+ Dwarf_Word i;
+ Dwarf_Files *files;
+ if (getattr (result, DW_AT_decl_file, &i) != 0
+ || getfiles (&scopes[out], &files) != 0)
+ break;
+
+ if (!file_matches (files, i))
+ break;
+
+ if (match_lineno > 0
+ && (getattr (result, DW_AT_decl_line, &i) != 0
+ || (int) i != match_lineno))
+ break;
+ if (match_linecol > 0
+ && (getattr (result, DW_AT_decl_column, &i) != 0
+ || (int) i != match_linecol))
+ break;
+ }
+
+ /* We have a winner! */
+ return out;
+ }
+ }
+ while (INTUSE(dwarf_siblingof) (result, result) == 0);
+ }
+
+ return -2;
+}
diff --git a/libdw/dwarf_getsrc_die.c b/libdw/dwarf_getsrc_die.c
new file mode 100644
index 00000000..e3ce4f2a
--- /dev/null
+++ b/libdw/dwarf_getsrc_die.c
@@ -0,0 +1,58 @@
+/* Find line information for address.
+ Copyright (C) 2004, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+#include <assert.h>
+
+
+Dwarf_Line *
+dwarf_getsrc_die (Dwarf_Die *cudie, Dwarf_Addr addr)
+{
+ Dwarf_Lines *lines;
+ size_t nlines;
+
+ if (INTUSE(dwarf_getsrclines) (cudie, &lines, &nlines) != 0)
+ return NULL;
+
+ /* The lines are sorted by address, so we can use binary search. */
+ size_t l = 0, u = nlines;
+ while (l < u)
+ {
+ size_t idx = (l + u) / 2;
+ if (addr < lines->info[idx].addr)
+ u = idx;
+ else if (addr > lines->info[idx].addr)
+ l = idx + 1;
+ else
+ return &lines->info[idx];
+ }
+
+ if (nlines > 0)
+ assert (lines->info[nlines - 1].end_sequence);
+
+ /* If none were equal, the closest one below is what we want. We
+ never want the last one, because it's the end-sequence marker
+ with an address at the high bound of the CU's code. If the debug
+ information is faulty and no end-sequence marker is present, we
+ still ignore it. */
+ if (u > 0 && u < nlines && addr > lines->info[u - 1].addr)
+ return &lines->info[u - 1];
+
+ __libdw_seterrno (DWARF_E_ADDR_OUTOFRANGE);
+ return NULL;
+}
diff --git a/libdw/dwarf_getsrc_file.c b/libdw/dwarf_getsrc_file.c
new file mode 100644
index 00000000..a10581d4
--- /dev/null
+++ b/libdw/dwarf_getsrc_file.c
@@ -0,0 +1,158 @@
+/* Find line information for given file/line/column triple.
+ Copyright (C) 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libdwP.h"
+
+
+int
+dwarf_getsrc_file (Dwarf *dbg, const char *fname, int lineno, int column,
+ Dwarf_Line ***srcsp, size_t *nsrcs)
+{
+ if (dbg == NULL)
+ return -1;
+
+ bool is_basename = strchr (fname, '/') == NULL;
+
+ size_t max_match = *nsrcs ?: ~0u;
+ size_t act_match = *nsrcs;
+ size_t cur_match = 0;
+ Dwarf_Line **match = *nsrcs == 0 ? NULL : *srcsp;
+
+ Dwarf_Off off = 0;
+ size_t cuhl;
+ Dwarf_Off noff;
+
+ while (INTUSE(dwarf_nextcu) (dbg, off, &noff, &cuhl, NULL, NULL, NULL) == 0)
+ {
+ Dwarf_Die cudie_mem;
+ Dwarf_Die *cudie = INTUSE(dwarf_offdie) (dbg, off + cuhl, &cudie_mem);
+ if (cudie == NULL)
+ continue;
+
+ /* Get the line number information for this file. */
+ Dwarf_Lines *lines;
+ size_t nlines;
+ if (INTUSE(dwarf_getsrclines) (cudie, &lines, &nlines) != 0)
+ return -1;
+
+ /* Search through all the line number records for a matching
+ file and line/column number. If any of the numbers is zero,
+ no match is performed. */
+ unsigned int lastfile = UINT_MAX;
+ bool lastmatch = false;
+ for (size_t cnt = 0; cnt < nlines; ++cnt)
+ {
+ Dwarf_Line *line = &lines->info[cnt];
+
+ if (lastfile != line->file)
+ {
+ lastfile = line->file;
+ if (lastfile >= line->files->nfiles)
+ {
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return -1;
+ }
+
+ /* Match the name with the name the user provided. */
+ const char *fname2 = line->files->info[lastfile].name;
+ if (is_basename)
+ lastmatch = strcmp (basename (fname2), fname) == 0;
+ else
+ lastmatch = strcmp (fname2, fname) == 0;
+ }
+ if (!lastmatch)
+ continue;
+
+ /* See whether line and possibly column match. */
+ if (lineno != 0
+ && (lineno > line->line
+ || (column != 0 && column > line->column)))
+ /* Cannot match. */
+ continue;
+
+ /* Determine whether this is the best match so far. */
+ size_t inner;
+ for (inner = 0; inner < cur_match; ++inner)
+ if (match[inner]->files == line->files
+ && match[inner]->file == line->file)
+ break;
+ if (inner < cur_match
+ && (match[inner]->line != line->line
+ || match[inner]->line != lineno
+ || (column != 0
+ && (match[inner]->column != line->column
+ || match[inner]->column != column))))
+ {
+ /* We know about this file already. If this is a better
+ match for the line number, use it. */
+ if (match[inner]->line >= line->line
+ && (match[inner]->line != line->line
+ || match[inner]->column >= line->column))
+ /* Use the new line. Otherwise the old one. */
+ match[inner] = line;
+ continue;
+ }
+
+ if (cur_match < max_match)
+ {
+ if (cur_match == act_match)
+ {
+ /* Enlarge the array for the results. */
+ act_match += 10;
+ Dwarf_Line **newp = realloc (match,
+ act_match
+ * sizeof (Dwarf_Line *));
+ if (newp == NULL)
+ {
+ free (match);
+ __libdw_seterrno (DWARF_E_NOMEM);
+ return -1;
+ }
+ match = newp;
+ }
+
+ match[cur_match++] = line;
+ }
+ }
+
+ /* If we managed to find as many matches as the user requested
+ already, there is no need to go on to the next CU. */
+ if (cur_match == max_match)
+ break;
+
+ off = noff;
+ }
+
+ if (cur_match > 0)
+ {
+ assert (*nsrcs == 0 || *srcsp == match);
+
+ *nsrcs = cur_match;
+ *srcsp = match;
+
+ return 0;
+ }
+
+ __libdw_seterrno (DWARF_E_NO_MATCH);
+ return -1;
+}
diff --git a/libdw/dwarf_getsrcfiles.c b/libdw/dwarf_getsrcfiles.c
new file mode 100644
index 00000000..6472bf44
--- /dev/null
+++ b/libdw/dwarf_getsrcfiles.c
@@ -0,0 +1,60 @@
+/* Return source file information of CU.
+ Copyright (C) 2004, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_getsrcfiles (Dwarf_Die *cudie, Dwarf_Files **files, size_t *nfiles)
+{
+ if (unlikely (cudie == NULL
+ || INTUSE(dwarf_tag) (cudie) != DW_TAG_compile_unit))
+ return -1;
+
+ int res = -1;
+
+ /* Get the information if it is not already known. */
+ struct Dwarf_CU *const cu = cudie->cu;
+ if (cu->lines == NULL)
+ {
+ Dwarf_Lines *lines;
+ size_t nlines;
+
+ /* Let the more generic function do the work. It'll create more
+ data but that will be needed in an real program anyway. */
+ res = INTUSE(dwarf_getsrclines) (cudie, &lines, &nlines);
+ }
+ else if (cu->files != (void *) -1l)
+ /* We already have the information. */
+ res = 0;
+
+ if (likely (res == 0))
+ {
+ assert (cu->files != NULL && cu->files != (void *) -1l);
+ *files = cu->files;
+ if (nfiles != NULL)
+ *nfiles = cu->files->nfiles;
+ }
+
+ // XXX Eventually: unlocking here.
+
+ return res;
+}
+INTDEF (dwarf_getsrcfiles)
diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c
new file mode 100644
index 00000000..37e14aee
--- /dev/null
+++ b/libdw/dwarf_getsrclines.c
@@ -0,0 +1,652 @@
+/* Return line number information of CU.
+ Copyright (C) 2004, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "dwarf.h"
+#include "libdwP.h"
+
+
+struct filelist
+{
+ Dwarf_Fileinfo info;
+ struct filelist *next;
+};
+
+struct linelist
+{
+ Dwarf_Line line;
+ struct linelist *next;
+};
+
+
+/* Compare by Dwarf_Line.addr, given pointers into an array of pointers. */
+static int
+compare_lines (const void *a, const void *b)
+{
+ Dwarf_Line *const *p1 = a;
+ Dwarf_Line *const *p2 = b;
+
+ return (*p1)->addr - (*p2)->addr;
+}
+
+
+/* Adds a new line to the matrix. We cannot define a function because
+ we want to use alloca. */
+#define NEW_LINE(end_seq) \
+ do { \
+ /* Add the new line. */ \
+ new_line = (struct linelist *) alloca (sizeof (struct linelist)); \
+ \
+ /* Set the line information. */ \
+ new_line->line.addr = address; \
+ new_line->line.file = file; \
+ new_line->line.line = line; \
+ new_line->line.column = column; \
+ new_line->line.is_stmt = is_stmt; \
+ new_line->line.basic_block = basic_block; \
+ new_line->line.end_sequence = end_seq; \
+ new_line->line.prologue_end = prologue_end; \
+ new_line->line.epilogue_begin = epilogue_begin; \
+ \
+ new_line->next = linelist; \
+ linelist = new_line; \
+ ++nlinelist; \
+ } while (0)
+
+
+int
+dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines)
+{
+ if (unlikely (cudie == NULL
+ || INTUSE(dwarf_tag) (cudie) != DW_TAG_compile_unit))
+ return -1;
+
+ int res = -1;
+
+ /* Get the information if it is not already known. */
+ struct Dwarf_CU *const cu = cudie->cu;
+ if (cu->lines == NULL)
+ {
+ /* Failsafe mode: no data found. */
+ cu->lines = (void *) -1l;
+ cu->files = (void *) -1l;
+
+ /* The die must have a statement list associated. */
+ Dwarf_Attribute stmt_list_mem;
+ Dwarf_Attribute *stmt_list = INTUSE(dwarf_attr) (cudie, DW_AT_stmt_list,
+ &stmt_list_mem);
+
+ /* Get the offset into the .debug_line section. NB: this call
+ also checks whether the previous dwarf_attr call failed. */
+ Dwarf_Word offset;
+ if (INTUSE(dwarf_formudata) (stmt_list, &offset) != 0)
+ goto out;
+
+ Dwarf *dbg = cu->dbg;
+ if (dbg->sectiondata[IDX_debug_line] == NULL)
+ {
+ __libdw_seterrno (DWARF_E_NO_DEBUG_LINE);
+ goto out;
+ }
+ const uint8_t *linep = dbg->sectiondata[IDX_debug_line]->d_buf + offset;
+ const uint8_t *lineendp = (dbg->sectiondata[IDX_debug_line]->d_buf
+ + dbg->sectiondata[IDX_debug_line]->d_size);
+
+ /* Get the compilation directory. */
+ Dwarf_Attribute compdir_attr_mem;
+ Dwarf_Attribute *compdir_attr = INTUSE(dwarf_attr) (cudie,
+ DW_AT_comp_dir,
+ &compdir_attr_mem);
+ const char *comp_dir = INTUSE(dwarf_formstring) (compdir_attr);
+
+ if (unlikely (linep + 4 > lineendp))
+ {
+ invalid_data:
+ __libdw_seterrno (DWARF_E_INVALID_DEBUG_LINE);
+ goto out;
+ }
+ Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
+ unsigned int length = 4;
+ if (unlikely (unit_length == 0xffffffff))
+ {
+ if (unlikely (linep + 8 > lineendp))
+ goto invalid_data;
+ unit_length = read_8ubyte_unaligned_inc (dbg, linep);
+ length = 8;
+ }
+
+ /* Check whether we have enough room in the section. */
+ if (unit_length < 2 + length + 5 * 1
+ || unlikely (linep + unit_length > lineendp))
+ goto invalid_data;
+ lineendp = linep + unit_length;
+
+ /* The next element of the header is the version identifier. */
+ uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
+ if (unlikely (version != DWARF_VERSION))
+ {
+ __libdw_seterrno (DWARF_E_VERSION);
+ goto out;
+ }
+
+ /* Next comes the header length. */
+ Dwarf_Word header_length;
+ if (length == 4)
+ header_length = read_4ubyte_unaligned_inc (dbg, linep);
+ else
+ header_length = read_8ubyte_unaligned_inc (dbg, linep);
+ const unsigned char *header_start = linep;
+
+ /* Next the minimum instruction length. */
+ uint_fast8_t minimum_instr_len = *linep++;
+
+ /* Then the flag determining the default value of the is_stmt
+ register. */
+ uint_fast8_t default_is_stmt = *linep++;
+
+ /* Now the line base. */
+ int_fast8_t line_base = *((int_fast8_t *) linep);
+ ++linep;
+
+ /* And the line range. */
+ uint_fast8_t line_range = *linep++;
+
+ /* The opcode base. */
+ uint_fast8_t opcode_base = *linep++;
+
+ /* Remember array with the standard opcode length (-1 to account for
+ the opcode with value zero not being mentioned). */
+ const uint8_t *standard_opcode_lengths = linep - 1;
+ linep += opcode_base - 1;
+ if (unlikely (linep >= lineendp))
+ goto invalid_data;
+
+ /* First comes the list of directories. Add the compilation
+ directory first since the index zero is used for it. */
+ struct dirlist
+ {
+ const char *dir;
+ size_t len;
+ struct dirlist *next;
+ } comp_dir_elem =
+ {
+ .dir = comp_dir,
+ .len = comp_dir ? strlen (comp_dir) : 0,
+ .next = NULL
+ };
+ struct dirlist *dirlist = &comp_dir_elem;
+ unsigned int ndirlist = 1;
+
+ // XXX Directly construct array to conserve memory?
+ while (*linep != 0)
+ {
+ struct dirlist *new_dir =
+ (struct dirlist *) alloca (sizeof (*new_dir));
+
+ new_dir->dir = (char *) linep;
+ uint8_t *endp = memchr (linep, '\0', lineendp - linep);
+ if (endp == NULL)
+ goto invalid_data;
+ new_dir->len = endp - linep;
+ new_dir->next = dirlist;
+ dirlist = new_dir;
+ ++ndirlist;
+ linep = endp + 1;
+ }
+ /* Skip the final NUL byte. */
+ ++linep;
+
+ /* Rearrange the list in array form. */
+ struct dirlist **dirarray
+ = (struct dirlist **) alloca (ndirlist * sizeof (*dirarray));
+ while (ndirlist-- > 0)
+ {
+ dirarray[ndirlist] = dirlist;
+ dirlist = dirlist->next;
+ }
+
+ /* Now read the files. */
+ struct filelist null_file =
+ {
+ .info =
+ {
+ .name = "???",
+ .mtime = 0,
+ .length = 0
+ },
+ .next = NULL
+ };
+ struct filelist *filelist = &null_file;
+ unsigned int nfilelist = 1;
+
+ if (unlikely (linep >= lineendp))
+ goto invalid_data;
+ while (*linep != 0)
+ {
+ struct filelist *new_file =
+ (struct filelist *) alloca (sizeof (*new_file));
+
+ /* First comes the file name. */
+ char *fname = (char *) linep;
+ uint8_t *endp = memchr (fname, '\0', lineendp - linep);
+ if (endp == NULL)
+ goto invalid_data;
+ size_t fnamelen = endp - (uint8_t *) fname;
+ linep = endp + 1;
+
+ /* Then the index. */
+ Dwarf_Word diridx;
+ get_uleb128 (diridx, linep);
+ if (unlikely (diridx >= ndirlist))
+ {
+ __libdw_seterrno (DWARF_E_INVALID_DIR_IDX);
+ goto out;
+ }
+
+ if (*fname == '/')
+ /* It's an absolute path. */
+ new_file->info.name = fname;
+ else
+ {
+ new_file->info.name = libdw_alloc (dbg, char, 1,
+ dirarray[diridx]->len + 1
+ + fnamelen + 1);
+ char *cp = new_file->info.name;
+
+ if (dirarray[diridx]->dir != NULL)
+ {
+ /* This value could be NULL in case the DW_AT_comp_dir
+ was not present. We cannot do much in this case.
+ The easiest thing is to convert the path in an
+ absolute path. */
+ cp = stpcpy (cp, dirarray[diridx]->dir);
+ }
+ *cp++ = '/';
+ strcpy (cp, fname);
+ assert (strlen (new_file->info.name)
+ < dirarray[diridx]->len + 1 + fnamelen + 1);
+ }
+
+ /* Next comes the modification time. */
+ get_uleb128 (new_file->info.mtime, linep);
+
+ /* Finally the length of the file. */
+ get_uleb128 (new_file->info.length, linep);
+
+ new_file->next = filelist;
+ filelist = new_file;
+ ++nfilelist;
+ }
+ /* Skip the final NUL byte. */
+ ++linep;
+
+ /* Consistency check. */
+ if (unlikely (linep != header_start + header_length))
+ {
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ goto out;
+ }
+
+ /* We are about to process the statement program. Initialize the
+ state machine registers (see 6.2.2 in the v2.1 specification). */
+ Dwarf_Word address = 0;
+ size_t file = 1;
+ size_t line = 1;
+ size_t column = 0;
+ uint_fast8_t is_stmt = default_is_stmt;
+ int basic_block = 0;
+ int prologue_end = 0;
+ int epilogue_begin = 0;
+
+ /* Process the instructions. */
+ struct linelist *linelist = NULL;
+ unsigned int nlinelist = 0;
+ while (linep < lineendp)
+ {
+ struct linelist *new_line;
+ unsigned int opcode;
+ unsigned int u128;
+ int s128;
+
+ /* Read the opcode. */
+ opcode = *linep++;
+
+ /* Is this a special opcode? */
+ if (likely (opcode >= opcode_base))
+ {
+ /* Yes. Handling this is quite easy since the opcode value
+ is computed with
+
+ opcode = (desired line increment - line_base)
+ + (line_range * address advance) + opcode_base
+ */
+ int line_increment = (line_base
+ + (opcode - opcode_base) % line_range);
+ unsigned int address_increment = (minimum_instr_len
+ * ((opcode - opcode_base)
+ / line_range));
+
+ /* Perform the increments. */
+ line += line_increment;
+ address += address_increment;
+
+ /* Add a new line with the current state machine values. */
+ NEW_LINE (0);
+
+ /* Reset the flags. */
+ basic_block = 0;
+ prologue_end = 0;
+ epilogue_begin = 0;
+ }
+ else if (opcode == 0)
+ {
+ /* This an extended opcode. */
+ if (unlikely (linep + 2 > lineendp))
+ goto invalid_data;
+
+ /* The length. */
+ unsigned int len = *linep++;
+
+ if (unlikely (linep + len > lineendp))
+ goto invalid_data;
+
+ /* The sub-opcode. */
+ opcode = *linep++;
+
+ switch (opcode)
+ {
+ case DW_LNE_end_sequence:
+ /* Add a new line with the current state machine values.
+ The is the end of the sequence. */
+ NEW_LINE (1);
+
+ /* Reset the registers. */
+ address = 0;
+ file = 1;
+ line = 1;
+ column = 0;
+ is_stmt = default_is_stmt;
+ basic_block = 0;
+ prologue_end = 0;
+ epilogue_begin = 0;
+ break;
+
+ case DW_LNE_set_address:
+ /* The value is an address. The size is defined as
+ apporiate for the target machine. We use the
+ address size field from the CU header. */
+ if (cu->address_size == 4)
+ address = read_4ubyte_unaligned_inc (dbg, linep);
+ else
+ address = read_8ubyte_unaligned_inc (dbg, linep);
+ break;
+
+ case DW_LNE_define_file:
+ {
+ char *fname = (char *) linep;
+ uint8_t *endp = memchr (linep, '\0', lineendp - linep);
+ if (endp == NULL)
+ goto invalid_data;
+ size_t fnamelen = endp - linep;
+ linep = endp + 1;
+
+ unsigned int diridx;
+ get_uleb128 (diridx, linep);
+ Dwarf_Word mtime;
+ get_uleb128 (mtime, linep);
+ Dwarf_Word filelength;
+ get_uleb128 (filelength, linep);
+
+ struct filelist *new_file =
+ (struct filelist *) alloca (sizeof (*new_file));
+ if (fname[0] == '/')
+ new_file->info.name = fname;
+ else
+ {
+ new_file->info.name =
+ libdw_alloc (dbg, char, 1, (dirarray[diridx]->len + 1
+ + fnamelen + 1));
+ char *cp = new_file->info.name;
+
+ if (dirarray[diridx]->dir != NULL)
+ /* This value could be NULL in case the
+ DW_AT_comp_dir was not present. We
+ cannot do much in this case. The easiest
+ thing is to convert the path in an
+ absolute path. */
+ cp = stpcpy (cp, dirarray[diridx]->dir);
+ *cp++ = '/';
+ strcpy (cp, fname);
+ }
+
+ new_file->info.mtime = mtime;
+ new_file->info.length = filelength;
+ new_file->next = filelist;
+ filelist = new_file;
+ ++nfilelist;
+ }
+ break;
+
+ default:
+ /* Unknown, ignore it. */
+ linep += len - 1;
+ break;
+ }
+ }
+ else if (opcode <= DW_LNS_set_epilog_begin)
+ {
+ /* This is a known standard opcode. */
+ switch (opcode)
+ {
+ case DW_LNS_copy:
+ /* Takes no argument. */
+ if (unlikely (standard_opcode_lengths[opcode] != 0))
+ goto invalid_data;
+
+ /* Add a new line with the current state machine values. */
+ NEW_LINE (0);
+
+ /* Reset the flags. */
+ basic_block = 0;
+ /* XXX Whether the following two lines are necessary is
+ unclear. I guess the current v2.1 specification has
+ a bug in that it says clearing these two registers is
+ not necessary. */
+ prologue_end = 0;
+ epilogue_begin = 0;
+ break;
+
+ case DW_LNS_advance_pc:
+ /* Takes one uleb128 parameter which is added to the
+ address. */
+ if (unlikely (standard_opcode_lengths[opcode] != 1))
+ goto invalid_data;
+
+ get_uleb128 (u128, linep);
+ address += minimum_instr_len * u128;
+ break;
+
+ case DW_LNS_advance_line:
+ /* Takes one sleb128 parameter which is added to the
+ line. */
+ if (unlikely (standard_opcode_lengths[opcode] != 1))
+ goto invalid_data;
+
+ get_sleb128 (s128, linep);
+ line += s128;
+ break;
+
+ case DW_LNS_set_file:
+ /* Takes one uleb128 parameter which is stored in file. */
+ if (unlikely (standard_opcode_lengths[opcode] != 1))
+ goto invalid_data;
+
+ get_uleb128 (u128, linep);
+ file = u128;
+ break;
+
+ case DW_LNS_set_column:
+ /* Takes one uleb128 parameter which is stored in column. */
+ if (unlikely (standard_opcode_lengths[opcode] != 1))
+ goto invalid_data;
+
+ get_uleb128 (u128, linep);
+ column = u128;
+ break;
+
+ case DW_LNS_negate_stmt:
+ /* Takes no argument. */
+ if (unlikely (standard_opcode_lengths[opcode] != 0))
+ goto invalid_data;
+
+ is_stmt = 1 - is_stmt;
+ break;
+
+ case DW_LNS_set_basic_block:
+ /* Takes no argument. */
+ if (unlikely (standard_opcode_lengths[opcode] != 0))
+ goto invalid_data;
+
+ basic_block = 1;
+ break;
+
+ case DW_LNS_const_add_pc:
+ /* Takes no argument. */
+ if (unlikely (standard_opcode_lengths[opcode] != 0))
+ goto invalid_data;
+
+ address += (minimum_instr_len
+ * ((255 - opcode_base) / line_range));
+ break;
+
+ case DW_LNS_fixed_advance_pc:
+ /* Takes one 16 bit parameter which is added to the
+ address. */
+ if (unlikely (standard_opcode_lengths[opcode] != 1))
+ goto invalid_data;
+
+ address += read_2ubyte_unaligned_inc (dbg, linep);
+ break;
+
+ case DW_LNS_set_prologue_end:
+ /* Takes no argument. */
+ if (unlikely (standard_opcode_lengths[opcode] != 0))
+ goto invalid_data;
+
+ prologue_end = 1;
+ break;
+
+ case DW_LNS_set_epilog_begin:
+ /* Takes no argument. */
+ if (unlikely (standard_opcode_lengths[opcode] != 0))
+ goto invalid_data;
+
+ epilogue_begin = 1;
+ break;
+ }
+ }
+ else
+ {
+ /* This is a new opcode the generator but not we know about.
+ Read the parameters associated with it but then discard
+ everything. Read all the parameters for this opcode. */
+ for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
+ get_uleb128 (u128, linep);
+
+ /* Next round, ignore this opcode. */
+ continue;
+ }
+ }
+
+ /* Put all the files in an array. */
+ Dwarf_Files *files = libdw_alloc (dbg, Dwarf_Files,
+ sizeof (Dwarf_Files)
+ + nfilelist * sizeof (Dwarf_Fileinfo),
+ 1);
+ files->nfiles = nfilelist;
+ while (nfilelist-- > 0)
+ {
+ files->info[nfilelist] = filelist->info;
+ filelist = filelist->next;
+ }
+ assert (filelist == NULL);
+
+ /* Remember the debugging descriptor. */
+ files->dbg = dbg;
+
+ /* Make the file data structure available through the CU. */
+ cu->files = files;
+
+ void *buf = libdw_alloc (dbg, Dwarf_Lines, (sizeof (Dwarf_Lines)
+ + (sizeof (Dwarf_Line)
+ * nlinelist)), 1);
+
+ /* First use the buffer for the pointers, and sort the entries.
+ We'll write the pointers in the end of the buffer, and then
+ copy into the buffer from the beginning so the overlap works. */
+ assert (sizeof (Dwarf_Line) >= sizeof (Dwarf_Line *));
+ Dwarf_Line **sortlines = (buf + sizeof (Dwarf_Lines)
+ + ((sizeof (Dwarf_Line)
+ - sizeof (Dwarf_Line *)) * nlinelist));
+
+ /* The list is in LIFO order and usually they come in clumps with
+ ascending addresses. So fill from the back to probably start with
+ runs already in order before we sort. */
+ unsigned int i = nlinelist;
+ while (i-- > 0)
+ {
+ sortlines[i] = &linelist->line;
+ linelist = linelist->next;
+ }
+ assert (linelist == NULL);
+
+ /* Sort by ascending address. */
+ qsort (sortlines, nlinelist, sizeof sortlines[0], &compare_lines);
+
+ /* Now that they are sorted, put them in the final array.
+ The buffers overlap, so we've clobbered the early elements
+ of SORTLINES by the time we're reading the later ones. */
+ cu->lines = buf;
+ cu->lines->nlines = nlinelist;
+ for (i = 0; i < nlinelist; ++i)
+ {
+ cu->lines->info[i] = *sortlines[i];
+ cu->lines->info[i].files = files;
+ }
+
+ /* Success. */
+ res = 0;
+ }
+ else if (cu->lines != (void *) -1l)
+ /* We already have the information. */
+ res = 0;
+
+ if (likely (res == 0))
+ {
+ *lines = cu->lines;
+ *nlines = cu->lines->nlines;
+ }
+ out:
+
+ // XXX Eventually: unlocking here.
+
+ return res;
+}
+INTDEF(dwarf_getsrclines)
diff --git a/libdw/dwarf_getstring.c b/libdw/dwarf_getstring.c
new file mode 100644
index 00000000..e4abe8cb
--- /dev/null
+++ b/libdw/dwarf_getstring.c
@@ -0,0 +1,51 @@
+/* Get string.
+ Copyright (C) 2004 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include "libdwP.h"
+
+
+const char *
+dwarf_getstring (dbg, offset, lenp)
+ Dwarf *dbg;
+ Dwarf_Off offset;
+ size_t *lenp;
+{
+ if (dbg == NULL)
+ return NULL;
+
+ if (dbg->sectiondata[IDX_debug_str] == NULL
+ || offset >= dbg->sectiondata[IDX_debug_str]->d_size)
+ {
+ no_string:
+ __libdw_seterrno (DWARF_E_NO_STRING);
+ return NULL;
+ }
+
+ const char *result = ((const char *) dbg->sectiondata[IDX_debug_str]->d_buf
+ + offset);
+ const char *endp = memchr (result, '\0',
+ dbg->sectiondata[IDX_debug_str]->d_size - offset);
+ if (endp == NULL)
+ goto no_string;
+
+ if (lenp != NULL)
+ *lenp = endp - result;
+
+ return result;
+}
diff --git a/libdw/dwarf_hasattr.c b/libdw/dwarf_hasattr.c
new file mode 100644
index 00000000..88dbee49
--- /dev/null
+++ b/libdw/dwarf_hasattr.c
@@ -0,0 +1,37 @@
+/* Check whether given DIE has specific attribute.
+ Copyright (C) 2003, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_hasattr (die, search_name)
+ Dwarf_Die *die;
+ unsigned int search_name;
+{
+ if (die == NULL)
+ return 0;
+
+ /* Search for the attribute with the given name. */
+ unsigned int code;
+ (void) __libdw_find_attr (die, search_name, &code, NULL);
+
+ return code == search_name;
+}
+INTDEF (dwarf_hasattr)
diff --git a/libdw/dwarf_hasattr_integrate.c b/libdw/dwarf_hasattr_integrate.c
new file mode 100644
index 00000000..423aa2a2
--- /dev/null
+++ b/libdw/dwarf_hasattr_integrate.c
@@ -0,0 +1,42 @@
+/* Check whether DIE has specific attribute, integrating DW_AT_abstract_origin.
+ Copyright (C) 2005 Red Hat, Inc.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+int
+dwarf_hasattr_integrate (Dwarf_Die *die, unsigned int search_name)
+{
+ Dwarf_Die die_mem;
+
+ do
+ {
+ if (INTUSE(dwarf_hasattr) (die, search_name))
+ return 1;
+
+ Dwarf_Attribute attr_mem;
+ Dwarf_Attribute *attr = INTUSE(dwarf_attr) (die, DW_AT_abstract_origin,
+ &attr_mem);
+ if (attr == NULL)
+ break;
+
+ die = INTUSE(dwarf_formref_die) (attr, &die_mem);
+ }
+ while (die != NULL);
+
+ return 0;
+}
diff --git a/libdw/dwarf_haschildren.c b/libdw/dwarf_haschildren.c
new file mode 100644
index 00000000..05a5b526
--- /dev/null
+++ b/libdw/dwarf_haschildren.c
@@ -0,0 +1,49 @@
+/* Return string associated with given attribute.
+ Copyright (C) 2003, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+#include <string.h>
+
+
+int
+dwarf_haschildren (die)
+ Dwarf_Die *die;
+{
+ /* Find the abbreviation entry. */
+ Dwarf_Abbrev *abbrevp = die->abbrev;
+ if (abbrevp != (Dwarf_Abbrev *) -1l)
+ {
+ const unsigned char *readp = (unsigned char *) die->addr;
+
+ /* First we have to get the abbreviation code so that we can decode
+ the data in the DIE. */
+ unsigned int abbrev_code;
+ get_uleb128 (abbrev_code, readp);
+
+ abbrevp = __libdw_findabbrev (die->cu, abbrev_code);
+ die->abbrev = abbrevp ?: (Dwarf_Abbrev *) -1l;
+ }
+ if (unlikely (die->abbrev == (Dwarf_Abbrev *) -1l))
+ {
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return 0;
+ }
+
+ return die->abbrev->has_children;
+}
+INTDEF (dwarf_haschildren)
diff --git a/libdw/dwarf_hasform.c b/libdw/dwarf_hasform.c
new file mode 100644
index 00000000..392b1f13
--- /dev/null
+++ b/libdw/dwarf_hasform.c
@@ -0,0 +1,32 @@
+/* Check whether given attribute has specific form.
+ Copyright (C) 2003 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_hasform (attr, search_form)
+ Dwarf_Attribute *attr;
+ unsigned int search_form;
+{
+ if (attr == NULL)
+ return 0;
+
+ return attr->form == search_form;
+}
diff --git a/libdw/dwarf_haspc.c b/libdw/dwarf_haspc.c
new file mode 100644
index 00000000..7f29296d
--- /dev/null
+++ b/libdw/dwarf_haspc.c
@@ -0,0 +1,105 @@
+/* Determine whether a DIE covers a PC address.
+ Copyright (C) 2005 Red Hat, Inc.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+#include <dwarf.h>
+
+
+int
+dwarf_haspc (Dwarf_Die *die, Dwarf_Addr pc)
+{
+ if (die == NULL)
+ return -1;
+
+ /* Usually there is a single contiguous range. */
+ Dwarf_Addr lowpc, highpc;
+ if (INTUSE(dwarf_highpc) (die, &highpc) == 0
+ && INTUSE(dwarf_lowpc) (die, &lowpc) == 0)
+ return pc >= lowpc && pc < highpc;
+
+ /* We have to look for a noncontiguous range. */
+ Dwarf_Attribute attr_mem;
+ Dwarf_Attribute *attr = INTUSE(dwarf_attr) (die, DW_AT_ranges, &attr_mem);
+ if (attr == NULL)
+ return -1;
+
+ /* Must have the form data4 or data8 which act as an offset. */
+ Dwarf_Word offset;
+ if (INTUSE(dwarf_formudata) (attr, &offset) != 0)
+ return -1;
+
+ const Elf_Data *d = attr->cu->dbg->sectiondata[IDX_debug_ranges];
+ if (d == NULL)
+ {
+ __libdw_seterrno (DWARF_E_NO_DEBUG_RANGES);
+ return -1;
+ }
+
+ /* Fetch the CU's base address. */
+ Dwarf_Addr base;
+ Dwarf_Die cudie =
+ {
+ .cu = attr->cu,
+ .addr = ((char *) attr->cu->dbg->sectiondata[IDX_debug_info]->d_buf
+ + attr->cu->start + 3 * attr->cu->offset_size - 4 + 3),
+ };
+ if (INTUSE(dwarf_lowpc) (&cudie, &base) != 0)
+ return -1;
+
+ unsigned char *readp = d->d_buf + offset;
+ Dwarf_Addr begin;
+ Dwarf_Addr end;
+ do
+ {
+ next:
+ if ((unsigned char *) d->d_buf + d->d_size - readp
+ < attr->cu->address_size * 2)
+ {
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return -1;
+ }
+
+ if (attr->cu->address_size == 8)
+ {
+ begin = read_8ubyte_unaligned_inc (attr->cu->dbg, readp);
+ end = read_8ubyte_unaligned_inc (attr->cu->dbg, readp);
+ }
+ else
+ {
+ begin = (Dwarf_Sword) read_4sbyte_unaligned_inc (attr->cu->dbg,
+ readp);
+ end = read_4ubyte_unaligned_inc (attr->cu->dbg, readp);
+ }
+
+ if (begin == (Dwarf_Addr) -1l) /* Base address entry. */
+ {
+ base = end;
+ goto next;
+ }
+
+ if (begin == 0 && end == 0) /* End of list entry. */
+ /* This is not the droid you are looking for. */
+ return 0;
+
+ /* We have an address range entry. */
+ }
+ while (pc < base + begin || pc >= base + end);
+
+ /* This one matches the address. */
+ return 1;
+}
+INTDEF (dwarf_haspc)
diff --git a/libdw/dwarf_highpc.c b/libdw/dwarf_highpc.c
new file mode 100644
index 00000000..d842569a
--- /dev/null
+++ b/libdw/dwarf_highpc.c
@@ -0,0 +1,34 @@
+/* Return high PC attribute of DIE.
+ Copyright (C) 2003, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_highpc (die, return_addr)
+ Dwarf_Die *die;
+ Dwarf_Addr *return_addr;
+{
+ Dwarf_Attribute attr_mem;
+
+ return INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (die, DW_AT_high_pc,
+ &attr_mem),
+ return_addr);
+}
+INTDEF(dwarf_highpc)
diff --git a/libdw/dwarf_lineaddr.c b/libdw/dwarf_lineaddr.c
new file mode 100644
index 00000000..ddfc01ba
--- /dev/null
+++ b/libdw/dwarf_lineaddr.c
@@ -0,0 +1,31 @@
+/* Return line address.
+ Copyright (C) 2004 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_lineaddr (Dwarf_Line *line, Dwarf_Addr *addrp)
+{
+ if (line == NULL)
+ return -1;
+
+ *addrp = line->addr;
+
+ return 0;
+}
diff --git a/libdw/dwarf_linebeginstatement.c b/libdw/dwarf_linebeginstatement.c
new file mode 100644
index 00000000..d974d8f4
--- /dev/null
+++ b/libdw/dwarf_linebeginstatement.c
@@ -0,0 +1,31 @@
+/* Return true if record is for beginning of a statement.
+ Copyright (C) 2004 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_linebeginstatement (Dwarf_Line *line, bool *flagp)
+{
+ if (line == NULL)
+ return -1;
+
+ *flagp = line->is_stmt;
+
+ return 0;
+}
diff --git a/libdw/dwarf_lineblock.c b/libdw/dwarf_lineblock.c
new file mode 100644
index 00000000..a6b8e0c2
--- /dev/null
+++ b/libdw/dwarf_lineblock.c
@@ -0,0 +1,31 @@
+/* Return true if record is for beginning of a basic block.
+ Copyright (C) 2004 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_lineblock (Dwarf_Line *line, bool *flagp)
+{
+ if (line == NULL)
+ return -1;
+
+ *flagp = line->basic_block;
+
+ return 0;
+}
diff --git a/libdw/dwarf_linecol.c b/libdw/dwarf_linecol.c
new file mode 100644
index 00000000..2430d372
--- /dev/null
+++ b/libdw/dwarf_linecol.c
@@ -0,0 +1,31 @@
+/* Return column in line.
+ Copyright (C) 2004 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_linecol (Dwarf_Line *line, int *colp)
+{
+ if (line == NULL)
+ return -1;
+
+ *colp = line->column;
+
+ return 0;
+}
diff --git a/libdw/dwarf_lineendsequence.c b/libdw/dwarf_lineendsequence.c
new file mode 100644
index 00000000..c49fabe2
--- /dev/null
+++ b/libdw/dwarf_lineendsequence.c
@@ -0,0 +1,31 @@
+/* Return true if record is for end of sequence.
+ Copyright (C) 2004 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_lineendsequence (Dwarf_Line *line, bool *flagp)
+{
+ if (line == NULL)
+ return -1;
+
+ *flagp = line->end_sequence;
+
+ return 0;
+}
diff --git a/libdw/dwarf_lineepiloguebegin.c b/libdw/dwarf_lineepiloguebegin.c
new file mode 100644
index 00000000..ee4f5bb7
--- /dev/null
+++ b/libdw/dwarf_lineepiloguebegin.c
@@ -0,0 +1,31 @@
+/* Return true if record is for beginning of epilogue.
+ Copyright (C) 2004 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_lineepiloguebegin (Dwarf_Line *line, bool *flagp)
+{
+ if (line == NULL)
+ return -1;
+
+ *flagp = line->epilogue_begin;
+
+ return 0;
+}
diff --git a/libdw/dwarf_lineno.c b/libdw/dwarf_lineno.c
new file mode 100644
index 00000000..5ad24067
--- /dev/null
+++ b/libdw/dwarf_lineno.c
@@ -0,0 +1,31 @@
+/* Return line number.
+ Copyright (C) 2004 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_lineno (Dwarf_Line *line, int *linep)
+{
+ if (line == NULL)
+ return -1;
+
+ *linep = line->line;
+
+ return 0;
+}
diff --git a/libdw/dwarf_lineprologueend.c b/libdw/dwarf_lineprologueend.c
new file mode 100644
index 00000000..e869025c
--- /dev/null
+++ b/libdw/dwarf_lineprologueend.c
@@ -0,0 +1,31 @@
+/* Return true if record is for end of prologue.
+ Copyright (C) 2004 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_lineprologueend (Dwarf_Line *line, bool *flagp)
+{
+ if (line == NULL)
+ return -1;
+
+ *flagp = line->prologue_end;
+
+ return 0;
+}
diff --git a/libdw/dwarf_linesrc.c b/libdw/dwarf_linesrc.c
new file mode 100644
index 00000000..0aca1d6f
--- /dev/null
+++ b/libdw/dwarf_linesrc.c
@@ -0,0 +1,41 @@
+/* Find line information for address.
+ Copyright (C) 2004 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+const char *
+dwarf_linesrc (Dwarf_Line *line, Dwarf_Word *mtime, Dwarf_Word *length)
+{
+ if (line == NULL)
+ return NULL;
+
+ if (line->file >= line->files->nfiles)
+ {
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return NULL;
+ }
+
+ if (mtime != NULL)
+ *mtime = line->files->info[line->file].mtime;
+
+ if (length != NULL)
+ *length = line->files->info[line->file].length;
+
+ return line->files->info[line->file].name;
+}
diff --git a/libdw/dwarf_lowpc.c b/libdw/dwarf_lowpc.c
new file mode 100644
index 00000000..c8cec0c1
--- /dev/null
+++ b/libdw/dwarf_lowpc.c
@@ -0,0 +1,34 @@
+/* Return low PC attribute of DIE.
+ Copyright (C) 2003, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_lowpc (die, return_addr)
+ Dwarf_Die *die;
+ Dwarf_Addr *return_addr;
+{
+ Dwarf_Attribute attr_mem;
+
+ return INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (die, DW_AT_low_pc,
+ &attr_mem),
+ return_addr);
+}
+INTDEF(dwarf_lowpc)
diff --git a/libdw/dwarf_macro_opcode.c b/libdw/dwarf_macro_opcode.c
new file mode 100644
index 00000000..1401db2d
--- /dev/null
+++ b/libdw/dwarf_macro_opcode.c
@@ -0,0 +1,31 @@
+/* Return macro opcode.
+ Copyright (C) 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_macro_opcode (Dwarf_Macro *macro, unsigned int *opcodep)
+{
+ if (macro == NULL)
+ return -1;
+
+ *opcodep = macro->opcode;
+
+ return 0;
+}
diff --git a/libdw/dwarf_macro_param1.c b/libdw/dwarf_macro_param1.c
new file mode 100644
index 00000000..adac7613
--- /dev/null
+++ b/libdw/dwarf_macro_param1.c
@@ -0,0 +1,31 @@
+/* Return first macro parameter.
+ Copyright (C) 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_macro_param1 (Dwarf_Macro *macro, Dwarf_Word *paramp)
+{
+ if (macro == NULL)
+ return -1;
+
+ *paramp = macro->param1;
+
+ return 0;
+}
diff --git a/libdw/dwarf_macro_param2.c b/libdw/dwarf_macro_param2.c
new file mode 100644
index 00000000..1b49aa7f
--- /dev/null
+++ b/libdw/dwarf_macro_param2.c
@@ -0,0 +1,34 @@
+/* Return second macro parameter.
+ Copyright (C) 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_macro_param2 (Dwarf_Macro *macro, Dwarf_Word *paramp, const char **strp)
+{
+ if (macro == NULL)
+ return -1;
+
+ if (paramp != NULL)
+ *paramp = macro->param2.u;
+ if (strp != NULL)
+ *strp = macro->param2.s;
+
+ return 0;
+}
diff --git a/libdw/dwarf_nextcu.c b/libdw/dwarf_nextcu.c
new file mode 100644
index 00000000..9dc7633e
--- /dev/null
+++ b/libdw/dwarf_nextcu.c
@@ -0,0 +1,132 @@
+/* Advance to next CU header.
+ Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwP.h>
+
+
+int
+dwarf_nextcu (dwarf, off, next_off, header_sizep, abbrev_offsetp,
+ address_sizep, offset_sizep)
+ Dwarf *dwarf;
+ Dwarf_Off off;
+ Dwarf_Off *next_off;
+ size_t *header_sizep;
+ Dwarf_Off *abbrev_offsetp;
+ uint8_t *address_sizep;
+ uint8_t *offset_sizep;
+{
+ /* Maybe there has been an error before. */
+ if (dwarf == NULL)
+ return -1;
+
+ /* If we reached the end before don't do anything. */
+ if (off == (Dwarf_Off) -1l
+ /* Make sure there is enough space in the .debug_info section
+ for at least the initial word. We cannot test the rest since
+ we don't know yet whether this is a 64-bit object or not. */
+ || unlikely (off + 4 >= dwarf->sectiondata[IDX_debug_info]->d_size))
+ {
+ *next_off = (Dwarf_Off) -1l;
+ return 1;
+ }
+
+ /* This points into the .debug_info section to the beginning of the
+ CU entry. */
+ char *bytes = (char *) dwarf->sectiondata[IDX_debug_info]->d_buf + off;
+
+ /* The format of the CU header is described in dwarf2p1 7.5.1:
+
+ 1. A 4-byte or 12-byte unsigned integer representing the length
+ of the .debug_info contribution for that compilation unit, not
+ including the length field itself. In the 32-bit DWARF format,
+ this is a 4-byte unsigned integer (which must be less than
+ 0xffffff00); in the 64-bit DWARF format, this consists of the
+ 4-byte value 0xffffffff followed by an 8-byte unsigned integer
+ that gives the actual length (see Section 7.4).
+
+ 2. A 2-byte unsigned integer representing the version of the
+ DWARF information for that compilation unit. For DWARF Version
+ 2.1, the value in this field is 2.
+
+ 3. A 4-byte or 8-byte unsigned offset into the .debug_abbrev
+ section. This offset associates the compilation unit with a
+ particular set of debugging information entry abbreviations. In
+ the 32-bit DWARF format, this is a 4-byte unsigned length; in
+ the 64-bit DWARF format, this is an 8-byte unsigned length (see
+ Section 7.4).
+
+ 4. A 1-byte unsigned integer representing the size in bytes of
+ an address on the target architecture. If the system uses
+ segmented addressing, this value represents the size of the
+ offset portion of an address. */
+ uint64_t length = read_4ubyte_unaligned_inc (dwarf, bytes);
+ size_t offset_size = 4;
+ if (length == 0xffffffffu)
+ offset_size = 8;
+
+ /* Now we know how large the header is. Note the trick in the
+ computation. If the offset_size is 4 the '- 4' term undoes the
+ '2 *'. If offset_size is 8 this term computes the size of the
+ escape value plus the 8 byte offset. */
+ if (unlikely (off + 2 * offset_size - 4 + sizeof (uint16_t)
+ + offset_size + sizeof (uint8_t)
+ >= dwarf->sectiondata[IDX_debug_info]->d_size))
+ {
+ *next_off = -1;
+ return 1;
+ }
+
+ if (length == 0xffffffffu)
+ /* This is a 64-bit DWARF format. */
+ length = read_8ubyte_unaligned_inc (dwarf, bytes);
+
+ /* Read the version stamp. Always a 16-bit value.
+ XXX Do we need the value? */
+ read_2ubyte_unaligned_inc (dwarf, bytes);
+
+ /* Get offset in .debug_abbrev. Note that the size of the entry
+ depends on whether this is a 32-bit or 64-bit DWARF definition. */
+ uint64_t abbrev_offset;
+ if (offset_size == 4)
+ abbrev_offset = read_4ubyte_unaligned_inc (dwarf, bytes);
+ else
+ abbrev_offset = read_8ubyte_unaligned_inc (dwarf, bytes);
+ if (abbrev_offsetp != NULL)
+ *abbrev_offsetp = abbrev_offset;
+
+ /* The address size. Always an 8-bit value. */
+ uint8_t address_size = *bytes++;
+ if (address_sizep != NULL)
+ *address_sizep = address_size;
+
+ /* Store the offset size. */
+ if (offset_sizep != NULL)
+ *offset_sizep = offset_size;
+
+ /* Store the header length. */
+ if (header_sizep != NULL)
+ *header_sizep = (bytes
+ - ((char *) dwarf->sectiondata[IDX_debug_info]->d_buf
+ + off));
+
+ /* See above for an explanation of the trick in this formula. */
+ *next_off = off + 2 * offset_size - 4 + length;
+
+ return 0;
+}
+INTDEF(dwarf_nextcu)
diff --git a/libdw/dwarf_offabbrev.c b/libdw/dwarf_offabbrev.c
new file mode 100644
index 00000000..97370d60
--- /dev/null
+++ b/libdw/dwarf_offabbrev.c
@@ -0,0 +1,36 @@
+/* Get abbreviation at given offset.
+ Copyright (C) 2004, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_offabbrev (Dwarf *dbg, Dwarf_Off offset, size_t *lengthp,
+ Dwarf_Abbrev *abbrevp)
+{
+ if (dbg == NULL)
+ return -1;
+
+ Dwarf_Abbrev *abbrev = __libdw_getabbrev (dbg, NULL, offset, lengthp,
+ abbrevp);
+
+ if (abbrev == NULL)
+ return -1;
+
+ return abbrev == DWARF_END_ABBREV ? 1 : 0;
+}
diff --git a/libdw/dwarf_offdie.c b/libdw/dwarf_offdie.c
new file mode 100644
index 00000000..84300e1a
--- /dev/null
+++ b/libdw/dwarf_offdie.c
@@ -0,0 +1,55 @@
+/* Return DIE at given offset.
+ Copyright (C) 2002, 2003, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include "libdwP.h"
+
+
+Dwarf_Die *
+dwarf_offdie (dbg, offset, result)
+ Dwarf *dbg;
+ Dwarf_Off offset;
+ Dwarf_Die *result;
+{
+ if (dbg == NULL)
+ return NULL;
+
+ if (offset >= dbg->sectiondata[IDX_debug_info]->d_size)
+ {
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return NULL;
+ }
+
+ /* Clear the entire DIE structure. This signals we have not yet
+ determined any of the information. */
+ memset (result, '\0', sizeof (Dwarf_Die));
+
+ result->addr = (char *) dbg->sectiondata[IDX_debug_info]->d_buf + offset;
+
+ /* Get the CU. */
+ result->cu = __libdw_findcu (dbg, offset);
+ if (result->cu == NULL)
+ {
+ /* This should never happen. The input file is malformed. */
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ result = NULL;
+ }
+
+ return result;
+}
+INTDEF(dwarf_offdie)
diff --git a/libdw/dwarf_onearange.c b/libdw/dwarf_onearange.c
new file mode 100644
index 00000000..0c372526
--- /dev/null
+++ b/libdw/dwarf_onearange.c
@@ -0,0 +1,35 @@
+/* Return one of the address range entries.
+ Copyright (C) 2004 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+Dwarf_Arange *
+dwarf_onearange (Dwarf_Aranges *aranges, size_t idx)
+{
+ if (aranges == NULL)
+ return NULL;
+
+ if (idx >= aranges->naranges)
+ {
+ __libdw_seterrno (DWARF_E_INVALID_ARANGE_IDX);
+ return NULL;
+ }
+
+ return &aranges->info[idx];
+}
diff --git a/libdw/dwarf_onesrcline.c b/libdw/dwarf_onesrcline.c
new file mode 100644
index 00000000..9234ef9a
--- /dev/null
+++ b/libdw/dwarf_onesrcline.c
@@ -0,0 +1,35 @@
+/* Return one of the sources lines of a CU.
+ Copyright (C) 2004 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+Dwarf_Line *
+dwarf_onesrcline (Dwarf_Lines *lines, size_t idx)
+{
+ if (lines == NULL)
+ return NULL;
+
+ if (idx >= lines->nlines)
+ {
+ __libdw_seterrno (DWARF_E_INVALID_LINE_IDX);
+ return NULL;
+ }
+
+ return &lines->info[idx];
+}
diff --git a/libdw/dwarf_siblingof.c b/libdw/dwarf_siblingof.c
new file mode 100644
index 00000000..bd965ea8
--- /dev/null
+++ b/libdw/dwarf_siblingof.c
@@ -0,0 +1,115 @@
+/* Return sibling of given DIE.
+ Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+#include <dwarf.h>
+#include <string.h>
+
+
+int
+dwarf_siblingof (die, result)
+ Dwarf_Die *die;
+ Dwarf_Die *result;
+{
+ /* Ignore previous errors. */
+ if (die == NULL)
+ return -1;
+
+ unsigned int level = 0;
+
+ /* Copy of the current DIE. */
+ Dwarf_Die this_die = *die;
+ /* Temporary attributes we create. */
+ Dwarf_Attribute sibattr;
+ /* Copy of the CU in the request. */
+ sibattr.cu = this_die.cu;
+ /* That's the address we start looking. */
+ unsigned char *addr = this_die.addr;
+ /* End of the buffer. */
+ unsigned char *endp
+ = ((unsigned char *) sibattr.cu->dbg->sectiondata[IDX_debug_info]->d_buf
+ + sibattr.cu->end);
+
+ /* Search for the beginning of the next die on this level. We
+ must not return the dies for children of the given die. */
+ do
+ {
+ /* Find the end of the DIE or the sibling attribute. */
+ addr = __libdw_find_attr (&this_die, DW_AT_sibling, &sibattr.code,
+ &sibattr.form);
+ if (sibattr.code == DW_AT_sibling)
+ {
+ Dwarf_Off offset;
+ sibattr.valp = addr;
+ if (INTUSE(dwarf_formref) (&sibattr, &offset) != 0)
+ /* Something went wrong. */
+ return -1;
+
+ /* Compute the next address. */
+ addr = ((unsigned char *)
+ sibattr.cu->dbg->sectiondata[IDX_debug_info]->d_buf
+ + sibattr.cu->start + offset);
+ }
+ else if (unlikely (addr == NULL)
+ || unlikely (this_die.abbrev == (Dwarf_Abbrev *) -1l))
+ return -1;
+ else if (this_die.abbrev->has_children)
+ /* This abbreviation has children. */
+ ++level;
+
+
+ while (1)
+ {
+ /* Make sure we are still in range. Some producers might skip
+ the trailing NUL bytes. */
+ if (addr >= endp)
+ return 1;
+
+ if (*addr != '\0')
+ break;
+
+ if (level-- == 0)
+ /* No more sibling at all. */
+ return 1;
+
+ ++addr;
+ }
+
+ /* Initialize the 'current DIE'. */
+ this_die.addr = addr;
+ this_die.abbrev = NULL;
+ }
+ while (level > 0);
+
+ /* Maybe we reached the end of the CU. */
+ if (addr >= endp)
+ return 1;
+
+ /* Clear the entire DIE structure. This signals we have not yet
+ determined any of the information. */
+ memset (result, '\0', sizeof (Dwarf_Die));
+
+ /* We have the address. */
+ result->addr = addr;
+
+ /* Same CU as the parent. */
+ result->cu = sibattr.cu;
+
+ return 0;
+}
+INTDEF(dwarf_siblingof)
diff --git a/libdw/dwarf_srclang.c b/libdw/dwarf_srclang.c
new file mode 100644
index 00000000..3fb06a1e
--- /dev/null
+++ b/libdw/dwarf_srclang.c
@@ -0,0 +1,33 @@
+/* Return source language attribute of DIE.
+ Copyright (C) 2003, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_srclang (die)
+ Dwarf_Die *die;
+{
+ Dwarf_Attribute attr_mem;
+ Dwarf_Word value;
+
+ return INTUSE(dwarf_formudata) (INTUSE(dwarf_attr) (die, DW_AT_language,
+ &attr_mem),
+ &value) == 0 ? (int) value : -1;
+}
diff --git a/libdw/dwarf_tag.c b/libdw/dwarf_tag.c
new file mode 100644
index 00000000..939b6811
--- /dev/null
+++ b/libdw/dwarf_tag.c
@@ -0,0 +1,82 @@
+/* Return tag of given DIE.
+ Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+Dwarf_Abbrev *
+internal_function_def
+__libdw_findabbrev (struct Dwarf_CU *cu, unsigned int code)
+{
+ Dwarf_Abbrev *abb;
+
+ /* See whether the entry is already in the hash table. */
+ abb = Dwarf_Abbrev_Hash_find (&cu->abbrev_hash, code, NULL);
+ if (abb == NULL)
+ while (cu->last_abbrev_offset != (size_t) -1l)
+ {
+ size_t length;
+
+ /* Find the next entry. It gets automatically added to the
+ hash table. */
+ abb = __libdw_getabbrev (cu->dbg, cu, cu->last_abbrev_offset, &length,
+ NULL);
+ if (abb == NULL || abb == DWARF_END_ABBREV)
+ {
+ /* Make sure we do not try to search for it again. */
+ cu->last_abbrev_offset = (size_t) -1l;
+ abb = (void *) -1l;
+ break;
+ }
+
+ cu->last_abbrev_offset += length;
+
+ /* Is this the code we are looking for? */
+ if (abb->code == code)
+ break;
+ }
+
+ return abb;
+}
+
+
+int
+dwarf_tag (die)
+ Dwarf_Die *die;
+{
+ /* Do we already know the abbreviation? */
+ if (die->abbrev == NULL)
+ {
+ /* Get the abbreviation code. */
+ unsigned int u128;
+ const unsigned char *addr = die->addr;
+ get_uleb128 (u128, addr);
+
+ /* Find the abbreviation. */
+ die->abbrev = __libdw_findabbrev (die->cu, u128);
+ }
+
+ if (die->abbrev == (Dwarf_Abbrev *) -1l)
+ {
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return DW_TAG_invalid;
+ }
+
+ return die->abbrev->tag;
+}
+INTDEF(dwarf_tag)
diff --git a/libdw/dwarf_whatattr.c b/libdw/dwarf_whatattr.c
new file mode 100644
index 00000000..ad5d868f
--- /dev/null
+++ b/libdw/dwarf_whatattr.c
@@ -0,0 +1,28 @@
+/* Return attribute code of given attribute.
+ Copyright (C) 2003 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+unsigned int
+dwarf_whatattr (attr)
+ Dwarf_Attribute *attr;
+{
+ return attr == NULL ? 0 : attr->code;
+}
diff --git a/libdw/dwarf_whatform.c b/libdw/dwarf_whatform.c
new file mode 100644
index 00000000..99da1c97
--- /dev/null
+++ b/libdw/dwarf_whatform.c
@@ -0,0 +1,28 @@
+/* Return form code of given attribute.
+ Copyright (C) 2003 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+unsigned int
+dwarf_whatform (attr)
+ Dwarf_Attribute *attr;
+{
+ return attr == NULL ? 0 : attr->form;
+}
diff --git a/libdw/libdw.h b/libdw/libdw.h
new file mode 100644
index 00000000..786be22a
--- /dev/null
+++ b/libdw/libdw.h
@@ -0,0 +1,564 @@
+/* Interfaces for libdw.
+ Copyright (C) 2002, 2004, 2005 Red Hat, Inc.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifndef _LIBDW_H
+#define _LIBDW_H 1
+
+#include <gelf.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
+# define __nonnull_attribute__(...) __attribute__ ((__nonnull__ (__VA_ARGS__)))
+#else
+# define __nonnull_attribute__(args...)
+#endif
+
+
+/* Mode for the session. */
+typedef enum
+ {
+ DWARF_C_READ, /* Read .. */
+ DWARF_C_RDWR, /* Read and write .. */
+ DWARF_C_WRITE, /* Write .. */
+ }
+Dwarf_Cmd;
+
+
+/* Callback results. */
+enum
+{
+ DWARF_CB_OK = 0,
+ DWARF_CB_ABORT
+};
+
+
+/* Error values. */
+enum
+ {
+ DW_TAG_invalid = 0
+#define DW_TAG_invalid DW_TAG_invalid
+ };
+
+
+/* Type for offset in DWARF file. */
+typedef GElf_Off Dwarf_Off;
+
+/* Type for address in DWARF file. */
+typedef GElf_Addr Dwarf_Addr;
+
+/* Integer types. Big enough to hold any numeric value. */
+typedef GElf_Xword Dwarf_Word;
+typedef GElf_Sxword Dwarf_Sword;
+/* For the times we know we do not need that much. */
+typedef GElf_Half Dwarf_Half;
+
+
+/* DWARF abbreviation record. */
+typedef struct Dwarf_Abbrev Dwarf_Abbrev;
+
+/* Returned to show the last DIE has be returned. */
+#define DWARF_END_ABBREV ((Dwarf_Abbrev *) -1l)
+
+/* Source code line information for CU. */
+typedef struct Dwarf_Lines_s Dwarf_Lines;
+
+/* One source code line information. */
+typedef struct Dwarf_Line_s Dwarf_Line;
+
+/* Source file information. */
+typedef struct Dwarf_Files_s Dwarf_Files;
+
+/* One address range record. */
+typedef struct Dwarf_Arange_s Dwarf_Arange;
+
+/* Address ranges of a file. */
+typedef struct Dwarf_Aranges_s Dwarf_Aranges;
+
+/* CU representation. */
+struct Dwarf_CU;
+
+/* Function information. */
+typedef struct Dwarf_Func_s Dwarf_Func;
+
+/* Macro information. */
+typedef struct Dwarf_Macro_s Dwarf_Macro;
+
+/* Attribute representation. */
+typedef struct
+{
+ unsigned int code;
+ unsigned int form;
+ unsigned char *valp;
+ struct Dwarf_CU *cu;
+} Dwarf_Attribute;
+
+
+/* Data block representation. */
+typedef struct
+{
+ Dwarf_Word length;
+ unsigned char *data;
+} Dwarf_Block;
+
+
+/* DIE information. */
+typedef struct
+{
+ /* The offset can be computed from the address. */
+ void *addr;
+ struct Dwarf_CU *cu;
+ Dwarf_Abbrev *abbrev;
+ // XXX We'll see what other information will be needed.
+ long int padding__;
+} Dwarf_Die;
+
+/* Returned to show the last DIE has be returned. */
+#define DWARF_END_DIE ((Dwarf_Die *) -1l)
+
+
+/* Global symbol information. */
+typedef struct
+{
+ Dwarf_Off cu_offset;
+ Dwarf_Off die_offset;
+ const char *name;
+} Dwarf_Global;
+
+
+// XXX It remains to be seen whether the next two need to be exported.
+/* Location record. */
+typedef struct
+{
+ uint8_t atom; /* Operation */
+ Dwarf_Word number; /* Operand */
+ Dwarf_Word number2; /* Possible second operand */
+ Dwarf_Word offset; /* Offset in location expression */
+} Dwarf_Loc;
+
+
+/* Handle for debug sessions. */
+typedef struct Dwarf Dwarf;
+
+
+/* Out-Of-Memory handler. */
+#if __GNUC__ < 4
+typedef void (*Dwarf_OOM) (void);
+#else
+typedef void (*__attribute__ ((noreturn)) Dwarf_OOM) (void);
+#endif
+
+
+/* Create a handle for a new debug session. */
+extern Dwarf *dwarf_begin (int fildes, Dwarf_Cmd cmd);
+
+/* Create a handle for a new debug session for an ELF file. */
+extern Dwarf *dwarf_begin_elf (Elf *elf, Dwarf_Cmd cmd, Elf_Scn *scngrp);
+
+/* Retrieve ELF descriptor used for DWARF access. */
+extern Elf *dwarf_getelf (Dwarf *dwarf);
+
+/* Release debugging handling context. */
+extern int dwarf_end (Dwarf *dwarf);
+
+
+/* Get the data block for the .debug_info section. */
+extern Elf_Data *dwarf_getscn_info (Dwarf *dwarf);
+
+/* Read the header for the DWARF CU header. */
+extern int dwarf_nextcu (Dwarf *dwarf, Dwarf_Off off, Dwarf_Off *next_off,
+ size_t *header_sizep, Dwarf_Off *abbrev_offsetp,
+ uint8_t *address_sizep, uint8_t *offset_sizep)
+ __nonnull_attribute__ (3);
+
+
+/* Return DIE at given offset. */
+extern Dwarf_Die *dwarf_offdie (Dwarf *dbg, Dwarf_Off offset,
+ Dwarf_Die *result) __nonnull_attribute__ (3);
+
+/* Return offset of DIE. */
+extern Dwarf_Off dwarf_dieoffset (Dwarf_Die *die);
+
+/* Return offset of DIE in CU. */
+extern Dwarf_Off dwarf_cuoffset (Dwarf_Die *die);
+
+/* Return CU DIE containing given address. */
+extern Dwarf_Die *dwarf_addrdie (Dwarf *dbg, Dwarf_Addr addr,
+ Dwarf_Die *result) __nonnull_attribute__ (3);
+
+/* Return child of current DIE. */
+extern int dwarf_child (Dwarf_Die *die, Dwarf_Die *result)
+ __nonnull_attribute__ (2);
+
+/* Return sibling of given DIE. */
+extern int dwarf_siblingof (Dwarf_Die *die, Dwarf_Die *result)
+ __nonnull_attribute__ (2);
+
+/* Check whether the DIE has children. */
+extern int dwarf_haschildren (Dwarf_Die *die);
+
+/* Get attributes of the DIE. */
+extern ptrdiff_t dwarf_getattrs (Dwarf_Die *die,
+ int (*callback) (Dwarf_Attribute *, void *),
+ void *arg, ptrdiff_t offset);
+
+/* Return tag of given DIE. */
+extern int dwarf_tag (Dwarf_Die *die);
+
+
+/* Return specific attribute of DIE. */
+extern Dwarf_Attribute *dwarf_attr (Dwarf_Die *die, unsigned int search_name,
+ Dwarf_Attribute *result)
+ __nonnull_attribute__ (3);
+
+/* Check whether given DIE has specific attribute. */
+extern int dwarf_hasattr (Dwarf_Die *die, unsigned int search_name);
+
+/* These are the same as dwarf_attr and dwarf_hasattr, respectively,
+ but they resolve an indirect attribute through DW_AT_abstract_origin. */
+extern Dwarf_Attribute *dwarf_attr_integrate (Dwarf_Die *die,
+ unsigned int search_name,
+ Dwarf_Attribute *result)
+ __nonnull_attribute__ (3);
+extern int dwarf_hasattr_integrate (Dwarf_Die *die, unsigned int search_name);
+
+
+
+
+/* Check whether given attribute has specific form. */
+extern int dwarf_hasform (Dwarf_Attribute *attr, unsigned int search_form);
+
+/* Return attribute code of given attribute. */
+extern unsigned int dwarf_whatattr (Dwarf_Attribute *attr);
+
+/* Return form code of given attribute. */
+extern unsigned int dwarf_whatform (Dwarf_Attribute *attr);
+
+
+/* Return string associated with given attribute. */
+extern const char *dwarf_formstring (Dwarf_Attribute *attrp);
+
+/* Return unsigned constant represented by attribute. */
+extern int dwarf_formudata (Dwarf_Attribute *attr, Dwarf_Word *return_uval)
+ __nonnull_attribute__ (2);
+
+/* Return signed constant represented by attribute. */
+extern int dwarf_formsdata (Dwarf_Attribute *attr, Dwarf_Sword *return_uval)
+ __nonnull_attribute__ (2);
+
+/* Return address represented by attribute. */
+extern int dwarf_formaddr (Dwarf_Attribute *attr, Dwarf_Addr *return_addr)
+ __nonnull_attribute__ (2);
+
+/* Return reference offset represented by attribute. */
+extern int dwarf_formref (Dwarf_Attribute *attr, Dwarf_Off *return_offset)
+ __nonnull_attribute__ (2);
+
+/* Look up the DIE in a reference-form attribute. */
+extern Dwarf_Die *dwarf_formref_die (Dwarf_Attribute *attr, Dwarf_Die *die_mem)
+ __nonnull_attribute__ (2);
+
+/* Return block represented by attribute. */
+extern int dwarf_formblock (Dwarf_Attribute *attr, Dwarf_Block *return_block)
+ __nonnull_attribute__ (2);
+
+/* Return flag represented by attribute. */
+extern int dwarf_formflag (Dwarf_Attribute *attr, bool *return_bool)
+ __nonnull_attribute__ (2);
+
+
+/* Simplified attribute value access functions. */
+
+/* Return string in name attribute of DIE. */
+extern const char *dwarf_diename (Dwarf_Die *die);
+
+/* Return high PC attribute of DIE. */
+extern int dwarf_highpc (Dwarf_Die *die, Dwarf_Addr *return_addr)
+ __nonnull_attribute__ (2);
+
+/* Return low PC attribute of DIE. */
+extern int dwarf_lowpc (Dwarf_Die *die, Dwarf_Addr *return_addr)
+ __nonnull_attribute__ (2);
+
+/* Return 1 if DIE's lowpc/highpc or ranges attributes match the PC address,
+ 0 if not, or -1 for errors. */
+extern int dwarf_haspc (Dwarf_Die *die, Dwarf_Addr pc);
+
+/* Return byte size attribute of DIE. */
+extern int dwarf_bytesize (Dwarf_Die *die);
+
+/* Return bit size attribute of DIE. */
+extern int dwarf_bitsize (Dwarf_Die *die);
+
+/* Return bit offset attribute of DIE. */
+extern int dwarf_bitoffset (Dwarf_Die *die);
+
+/* Return array order attribute of DIE. */
+extern int dwarf_arrayorder (Dwarf_Die *die);
+
+/* Return source language attribute of DIE. */
+extern int dwarf_srclang (Dwarf_Die *die);
+
+
+/* Get abbreviation at given offset for given DIE. */
+extern Dwarf_Abbrev *dwarf_getabbrev (Dwarf_Die *die, Dwarf_Off offset,
+ size_t *lengthp);
+
+/* Get abbreviation at given offset in .debug_abbrev section. */
+extern int dwarf_offabbrev (Dwarf *dbg, Dwarf_Off offset, size_t *lengthp,
+ Dwarf_Abbrev *abbrevp)
+ __nonnull_attribute__ (4);
+
+/* Get abbreviation code. */
+extern unsigned int dwarf_getabbrevcode (Dwarf_Abbrev *abbrev);
+
+/* Get abbreviation tag. */
+extern unsigned int dwarf_getabbrevtag (Dwarf_Abbrev *abbrev);
+
+/* Return true if abbreviation is children flag set. */
+extern int dwarf_abbrevhaschildren (Dwarf_Abbrev *abbrev);
+
+/* Get number of attributes of abbreviation. */
+extern int dwarf_getattrcnt (Dwarf_Abbrev *abbrev, size_t *attrcntp)
+ __nonnull_attribute__ (2);
+
+/* Get specific attribute of abbreviation. */
+extern int dwarf_getabbrevattr (Dwarf_Abbrev *abbrev, size_t idx,
+ unsigned int *namep, unsigned int *formp,
+ Dwarf_Off *offset);
+
+
+/* Get string from-debug_str section. */
+extern const char *dwarf_getstring (Dwarf *dbg, Dwarf_Off offset,
+ size_t *lenp);
+
+
+/* Get public symbol information. */
+extern ptrdiff_t dwarf_getpubnames (Dwarf *dbg,
+ int (*callback) (Dwarf *, Dwarf_Global *,
+ void *),
+ void *arg, ptrdiff_t offset)
+ __nonnull_attribute__ (2);
+
+
+/* Get source file information for CU. */
+extern int dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines,
+ size_t *nlines) __nonnull_attribute__ (2, 3);
+
+/* Return one of the source lines of the CU. */
+extern Dwarf_Line *dwarf_onesrcline (Dwarf_Lines *lines, size_t idx);
+
+/* Get the file source files used in the CU. */
+extern int dwarf_getsrcfiles (Dwarf_Die *cudie, Dwarf_Files **files,
+ size_t *nfiles)
+ __nonnull_attribute__ (2);
+
+
+/* Get source for address in CU. */
+extern Dwarf_Line *dwarf_getsrc_die (Dwarf_Die *cudie, Dwarf_Addr addr);
+
+/* Get source for file and line number. */
+extern int dwarf_getsrc_file (Dwarf *dbg, const char *fname, int line, int col,
+ Dwarf_Line ***srcsp, size_t *nsrcs)
+ __nonnull_attribute__ (2, 5, 6);
+
+
+/* Return line address. */
+extern int dwarf_lineaddr (Dwarf_Line *line, Dwarf_Addr *addrp);
+
+/* Return line number. */
+extern int dwarf_lineno (Dwarf_Line *line, int *linep)
+ __nonnull_attribute__ (2);
+
+/* Return column in line. */
+extern int dwarf_linecol (Dwarf_Line *line, int *colp)
+ __nonnull_attribute__ (2);
+
+/* Return true if record is for beginning of a statement. */
+extern int dwarf_linebeginstatement (Dwarf_Line *line, bool *flagp)
+ __nonnull_attribute__ (2);
+
+/* Return true if record is for end of sequence. */
+extern int dwarf_lineendsequence (Dwarf_Line *line, bool *flagp)
+ __nonnull_attribute__ (2);
+
+/* Return true if record is for beginning of a basic block. */
+extern int dwarf_lineblock (Dwarf_Line *line, bool *flagp)
+ __nonnull_attribute__ (2);
+
+/* Return true if record is for end of prologue. */
+extern int dwarf_lineprologueend (Dwarf_Line *line, bool *flagp)
+ __nonnull_attribute__ (2);
+
+/* Return true if record is for beginning of epilogue. */
+extern int dwarf_lineepiloguebegin (Dwarf_Line *line, bool *flagp)
+ __nonnull_attribute__ (2);
+
+
+/* Find line information for address. */
+extern const char *dwarf_linesrc (Dwarf_Line *line,
+ Dwarf_Word *mtime, Dwarf_Word *length);
+
+/* Return file information. */
+extern const char *dwarf_filesrc (Dwarf_Files *file, size_t idx,
+ Dwarf_Word *mtime, Dwarf_Word *length);
+
+
+/* Return location expression list. */
+extern int dwarf_getloclist (Dwarf_Attribute *attr, Dwarf_Loc **llbuf,
+ size_t *listlen) __nonnull_attribute__ (2, 3);
+
+/* Return location expression lists. If the attribute uses a location
+ list, ADDRESS selects the relevant location expressions from the list.
+ There can be multiple matches, resulting in multiple expressions to
+ return. LLBUFS and LISTLENS are parallel arrays of NLOCS slots to fill
+ in. Returns the number of locations filled in, or -1 for errors. If
+ LLBUFS is a null pointer, stores nothing and returns the total number of
+ locations. A return value of zero means that the location list
+ indicated no value is accessible. */
+extern int dwarf_addrloclists (Dwarf_Attribute *attr, Dwarf_Addr address,
+ Dwarf_Loc **llbufs, size_t *listlens,
+ size_t nlocs);
+
+
+/* Return scope DIEs containing PC address.
+ Sets *SCOPES to a malloc'd array of Dwarf_Die structures,
+ and returns the number of elements in the array.
+ (*SCOPES)[0] is the DIE for the innermost scope containing PC,
+ (*SCOPES)[1] is the DIE for the scope containing that scope, and so on.
+ Returns -1 for errors or 0 if no scopes match PC. */
+extern int dwarf_getscopes (Dwarf_Die *cudie, Dwarf_Addr pc,
+ Dwarf_Die **scopes);
+
+/* Search SCOPES[0..NSCOPES-1] for a variable called NAME.
+ Ignore the first SKIP_SHADOWS scopes that match the name.
+ If MATCH_FILE is not null, accept only declaration in that source file;
+ if MATCH_LINENO or MATCH_LINECOL are also nonzero, accept only declaration
+ at that line and column.
+
+ If successful, fill in *RESULT with the DIE of the variable found,
+ and return N where SCOPES[N] is the scope defining the variable.
+ Return -1 for errors or -2 for no matching variable found. */
+extern int dwarf_getscopevar (Dwarf_Die *scopes, int nscopes,
+ const char *name, int skip_shadows,
+ const char *match_file,
+ int match_lineno, int match_linecol,
+ Dwarf_Die *result);
+
+
+
+/* Return list address ranges. */
+extern int dwarf_getaranges (Dwarf *dbg, Dwarf_Aranges **aranges,
+ size_t *naranges)
+ __nonnull_attribute__ (2);
+
+/* Return one of the address range entries. */
+extern Dwarf_Arange *dwarf_onearange (Dwarf_Aranges *aranges, size_t idx);
+
+/* Return information in address range record. */
+extern int dwarf_getarangeinfo (Dwarf_Arange *arange, Dwarf_Addr *addrp,
+ Dwarf_Word *lengthp, Dwarf_Off *offsetp);
+
+/* Get address range which includes given address. */
+extern Dwarf_Arange *dwarf_getarange_addr (Dwarf_Aranges *aranges,
+ Dwarf_Addr addr);
+
+
+
+/* Get functions in CUDIE. */
+extern ptrdiff_t dwarf_getfuncs (Dwarf_Die *cudie,
+ int (*callback) (Dwarf_Func *, void *),
+ void *arg, ptrdiff_t offset);
+
+/* Return name of function. */
+extern const char *dwarf_func_name (Dwarf_Func *func);
+
+/* Return start address of function. */
+extern int dwarf_func_lowpc (Dwarf_Func *func, Dwarf_Addr *return_addr)
+ __nonnull_attribute__ (2);
+
+/* Return end address of function. */
+extern int dwarf_func_highpc (Dwarf_Func *func, Dwarf_Addr *return_addr)
+ __nonnull_attribute__ (2);
+
+/* Return entry point address of function. */
+extern int dwarf_func_entrypc (Dwarf_Func *func, Dwarf_Addr *return_addr)
+ __nonnull_attribute__ (2);
+
+/* Return file name containing definition of the given function. */
+extern const char *dwarf_func_file (Dwarf_Func *func);
+
+/* Get line number of beginning of given function. */
+extern int dwarf_func_line (Dwarf_Func *func, int *linep)
+ __nonnull_attribute__ (2);
+
+/* Get column number of beginning of given function. */
+extern int dwarf_func_col (Dwarf_Func *func, int *colp)
+ __nonnull_attribute__ (2);
+
+
+/* Call callback function for each of the macro information entry for
+ the CU. */
+extern ptrdiff_t dwarf_getmacros (Dwarf_Die *cudie,
+ int (*callback) (Dwarf_Macro *, void *),
+ void *arg, ptrdiff_t offset)
+ __nonnull_attribute__ (2);
+
+/* Return macro opcode. */
+extern int dwarf_macro_opcode (Dwarf_Macro *macro, unsigned int *opcodep)
+ __nonnull_attribute__ (2);
+
+/* Return first macro parameter. */
+extern int dwarf_macro_param1 (Dwarf_Macro *macro, Dwarf_Word *paramp)
+ __nonnull_attribute__ (2);
+
+/* Return second macro parameter. */
+extern int dwarf_macro_param2 (Dwarf_Macro *macro, Dwarf_Word *paramp,
+ const char **strp);
+
+
+/* Return error code of last failing function call. This value is kept
+ separately for each thread. */
+extern int dwarf_errno (void);
+
+/* Return error string for ERROR. If ERROR is zero, return error string
+ for most recent error or NULL is none occurred. If ERROR is -1 the
+ behaviour is similar to the last case except that not NULL but a legal
+ string is returned. */
+extern const char *dwarf_errmsg (int err);
+
+
+/* Register new Out-Of-Memory handler. The old handler is returned. */
+extern Dwarf_OOM dwarf_new_oom_handler (Dwarf *dbg, Dwarf_OOM handler);
+
+
+/* Inline optimizations. */
+#ifdef __OPTIMIZE__
+/* Return attribute code of given attribute. */
+extern inline unsigned int
+dwarf_whatattr (Dwarf_Attribute *attr)
+{
+ return attr == NULL ? 0 : attr->code;
+}
+
+/* Return attribute code of given attribute. */
+extern inline unsigned int
+dwarf_whatform (Dwarf_Attribute *attr)
+{
+ return attr == NULL ? 0 : attr->form;
+}
+#endif /* Optimize. */
+
+#endif /* libdw.h */
diff --git a/libdw/libdw.map b/libdw/libdw.map
new file mode 100644
index 00000000..ed3c989a
--- /dev/null
+++ b/libdw/libdw.map
@@ -0,0 +1,92 @@
+ELFUTILS_1.0 {
+ global:
+ dwarf_abbrevhaschildren;
+ dwarf_addrdie;
+ dwarf_addrloclists;
+ dwarf_attr;
+ dwarf_attr_integrate;
+ dwarf_arrayorder;
+ dwarf_begin;
+ dwarf_begin_elf;
+ dwarf_bitoffset;
+ dwarf_bitsize;
+ dwarf_bytesize;
+ dwarf_child;
+ dwarf_cuoffset;
+ dwarf_diename;
+ dwarf_dieoffset;
+ dwarf_end;
+ dwarf_errmsg;
+ dwarf_errno;
+ dwarf_filesrc;
+ dwarf_formaddr;
+ dwarf_formblock;
+ dwarf_formflag;
+ dwarf_formref;
+ dwarf_formref_die;
+ dwarf_formsdata;
+ dwarf_formstring;
+ dwarf_formudata;
+ dwarf_func_col;
+ dwarf_func_entrypc;
+ dwarf_func_file;
+ dwarf_func_highpc;
+ dwarf_func_line;
+ dwarf_func_lowpc;
+ dwarf_func_name;
+ dwarf_getabbrev;
+ dwarf_getabbrevattr;
+ dwarf_getabbrevcode;
+ dwarf_getabbrevtag;
+ dwarf_getarange_addr;
+ dwarf_getarangeinfo;
+ dwarf_getaranges;
+ dwarf_getattrcnt;
+ dwarf_getattrs;
+ dwarf_getelf;
+ dwarf_getfuncs;
+ dwarf_getloclist;
+ dwarf_getmacros;
+ dwarf_getpubnames;
+ dwarf_getscopes;
+ dwarf_getscopevar;
+ dwarf_getscn_info;
+ dwarf_getsrc_die;
+ dwarf_getsrc_file;
+ dwarf_getsrcfiles;
+ dwarf_getsrclines;
+ dwarf_getstring;
+ dwarf_hasattr;
+ dwarf_hasattr_integrate;
+ dwarf_haspc;
+ dwarf_haschildren;
+ dwarf_hasform;
+ dwarf_highpc;
+ dwarf_lineaddr;
+ dwarf_linebeginstatement;
+ dwarf_lineblock;
+ dwarf_linecol;
+ dwarf_lineendsequence;
+ dwarf_lineepiloguebegin;
+ dwarf_lineno;
+ dwarf_lineprologueend;
+ dwarf_linesrc;
+ dwarf_lowpc;
+ dwarf_macro_opcode;
+ dwarf_macro_param1;
+ dwarf_macro_param2;
+ dwarf_offabbrev;
+ dwarf_offdie;
+ dwarf_onearange;
+ dwarf_onesrcline;
+ dwarf_nextcu;
+ dwarf_new_oom_handler;
+ dwarf_siblingof;
+ dwarf_srclang;
+ dwarf_tag;
+ dwarf_whatattr;
+ dwarf_whatform;
+
+ local:
+ *;
+};
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
new file mode 100644
index 00000000..05e02aa3
--- /dev/null
+++ b/libdw/libdwP.h
@@ -0,0 +1,378 @@
+/* Internal definitions for libdwarf.
+ Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifndef _LIBDWP_H
+#define _LIBDWP_H 1
+
+#include <libintl.h>
+#include <stdbool.h>
+
+#include <libdw.h>
+
+
+/* gettext helper macros. */
+#define _(Str) dgettext ("elfutils", Str)
+
+
+/* Version of the DWARF specification we support. */
+#define DWARF_VERSION 2
+
+/* Version of the CIE format. */
+#define CIE_VERSION 1
+
+
+/* Known location lists. */
+struct loc_s
+{
+ void *addr;
+ Dwarf_Loc *loc;
+ size_t nloc;
+};
+
+/* Valid indeces for the section data. */
+enum
+ {
+ IDX_debug_info = 0,
+ IDX_debug_abbrev,
+ IDX_debug_aranges,
+ IDX_debug_line,
+ IDX_debug_frame,
+ IDX_eh_frame,
+ IDX_debug_loc,
+ IDX_debug_pubnames,
+ IDX_debug_str,
+ IDX_debug_funcnames,
+ IDX_debug_typenames,
+ IDX_debug_varnames,
+ IDX_debug_weaknames,
+ IDX_debug_macinfo,
+ IDX_debug_ranges,
+ IDX_last
+ };
+
+
+/* Error values. */
+enum
+{
+ DWARF_E_NOERROR = 0,
+ DWARF_E_UNKNOWN_ERROR,
+ DWARF_E_INVALID_ACCESS,
+ DWARF_E_NO_REGFILE,
+ DWARF_E_IO_ERROR,
+ DWARF_E_INVALID_ELF,
+ DWARF_E_NO_DWARF,
+ DWARF_E_NOELF,
+ DWARF_E_GETEHDR_ERROR,
+ DWARF_E_NOMEM,
+ DWARF_E_UNIMPL,
+ DWARF_E_INVALID_CMD,
+ DWARF_E_INVALID_VERSION,
+ DWARF_E_INVALID_FILE,
+ DWARF_E_NO_ENTRY,
+ DWARF_E_INVALID_DWARF,
+ DWARF_E_NO_STRING,
+ DWARF_E_NO_ADDR,
+ DWARF_E_NO_CONSTANT,
+ DWARF_E_NO_REFERENCE,
+ DWARF_E_INVALID_REFERENCE,
+ DWARF_E_NO_DEBUG_LINE,
+ DWARF_E_INVALID_DEBUG_LINE,
+ DWARF_E_TOO_BIG,
+ DWARF_E_VERSION,
+ DWARF_E_INVALID_DIR_IDX,
+ DWARF_E_ADDR_OUTOFRANGE,
+ DWARF_E_NO_LOCLIST,
+ DWARF_E_NO_BLOCK,
+ DWARF_E_INVALID_LINE_IDX,
+ DWARF_E_INVALID_ARANGE_IDX,
+ DWARF_E_NO_MATCH,
+ DWARF_E_NO_FLAG,
+ DWARF_E_INVALID_OFFSET,
+ DWARF_E_NO_DEBUG_RANGES,
+};
+
+
+/* This is the structure representing the debugging state. */
+struct Dwarf
+{
+ /* The underlying ELF file. */
+ Elf *elf;
+
+ /* The section data. */
+ Elf_Data *sectiondata[IDX_last];
+
+ /* True if the file has a byte order different from the host. */
+ bool other_byte_order;
+
+ /* If true, we allocated the ELF descriptor ourselves. */
+ bool free_elf;
+
+ /* Information for traversing the .debug_pubnames section. This is
+ an array and separately allocated with malloc. */
+ struct pubnames_s
+ {
+ Dwarf_Off cu_offset;
+ Dwarf_Off set_start;
+ unsigned int cu_header_size;
+ int address_len;
+ } *pubnames_sets;
+ size_t pubnames_nsets;
+
+ /* Search tree for the CUs. */
+ void *cu_tree;
+ Dwarf_Off next_cu_offset;
+
+ /* Address ranges. */
+ Dwarf_Aranges *aranges;
+
+ /* Internal memory handling. This is basically a simplified
+ reimplementation of obstacks. Unfortunately the standard obstack
+ implementation is not usable in libraries. */
+ struct libdw_memblock
+ {
+ size_t size;
+ size_t remaining;
+ struct libdw_memblock *prev;
+ char mem[0];
+ } *mem_tail;
+
+ /* Default size of allocated memory blocks. */
+ size_t mem_default_size;
+
+ /* Registered OOM handler. */
+ Dwarf_OOM oom_handler;
+};
+
+
+/* Abbreviation representation. */
+struct Dwarf_Abbrev
+{
+ unsigned int code;
+ unsigned int tag;
+ int has_children;
+ unsigned int attrcnt;
+ unsigned char *attrp;
+ Dwarf_Off offset;
+};
+
+#include "dwarf_abbrev_hash.h"
+
+
+/* Files in line information records. */
+struct Dwarf_Files_s
+ {
+ Dwarf *dbg;
+ unsigned int nfiles;
+ struct Dwarf_Fileinfo_s
+ {
+ char *name;
+ Dwarf_Word mtime;
+ Dwarf_Word length;
+ } info[0];
+ };
+typedef struct Dwarf_Fileinfo_s Dwarf_Fileinfo;
+
+
+/* Representation of a row in the line table. */
+struct Dwarf_Lines_s
+ {
+ size_t nlines;
+
+ struct Dwarf_Line_s
+ {
+ Dwarf_Addr addr;
+ unsigned int file;
+ int line;
+ unsigned short int column;
+ unsigned int is_stmt:1;
+ unsigned int basic_block:1;
+ unsigned int end_sequence:1;
+ unsigned int prologue_end:1;
+ unsigned int epilogue_begin:1;
+
+ Dwarf_Files *files;
+ } info[0];
+ };
+
+
+/* Representation of address ranges. */
+struct Dwarf_Aranges_s
+{
+ Dwarf *dbg;
+ size_t naranges;
+
+ struct Dwarf_Arange_s
+ {
+ Dwarf_Addr addr;
+ Dwarf_Word length;
+ Dwarf_Off offset;
+ } info[0];
+};
+
+
+/* CU representation. */
+struct Dwarf_CU
+{
+ Dwarf *dbg;
+ Dwarf_Off start;
+ Dwarf_Off end;
+ uint8_t address_size;
+ uint8_t offset_size;
+
+ /* Hash table for the abbreviations. */
+ Dwarf_Abbrev_Hash abbrev_hash;
+ /* Offset of the first abbreviation. */
+ size_t orig_abbrev_offset;
+ /* Offset past last read abbreviation. */
+ size_t last_abbrev_offset;
+
+ /* The srcline information. */
+ Dwarf_Lines *lines;
+
+ /* The source file information. */
+ Dwarf_Files *files;
+
+ /* Known location lists. */
+ void *locs;
+};
+
+
+/* Function information. */
+struct Dwarf_Func_s
+{
+ // XXX If we want to cache functions, we need to change this struct.
+ Dwarf_Die *die;
+ Dwarf_Die *cudie;
+};
+
+
+/* Macro information. */
+struct Dwarf_Macro_s
+{
+ unsigned int opcode;
+ Dwarf_Word param1;
+ union
+ {
+ Dwarf_Word u;
+ const char *s;
+ } param2;
+};
+
+
+/* We have to include the file at this point because the inline
+ functions access internals of the Dwarf structure. */
+#include "memory-access.h"
+
+
+/* Set error value. */
+extern void __libdw_seterrno (int value) internal_function;
+
+
+/* Memory handling, the easy parts. This macro does not do any locking. */
+#define libdw_alloc(dbg, type, tsize, cnt) \
+ ({ struct libdw_memblock *_tail = (dbg)->mem_tail; \
+ size_t _required = (tsize) * (cnt); \
+ type *_result = (type *) (_tail->mem + (_tail->size - _tail->remaining));\
+ size_t _padding = ((__alignof (type) \
+ - ((uintptr_t) _result & (__alignof (type) - 1))) \
+ & (__alignof (type) - 1)); \
+ if (unlikely (_tail->remaining < _required + _padding)) \
+ { \
+ _result = (type *) __libdw_allocate (dbg, _required); \
+ _tail = (dbg)->mem_tail; \
+ } \
+ else \
+ { \
+ _required += _padding; \
+ _result = (type *) ((char *) _result + _padding); \
+ } \
+ _tail->remaining -= _required; \
+ _result; })
+
+#define libdw_typed_alloc(dbg, type) \
+ libdw_alloc (dbg, type, sizeof (type), 1)
+
+/* Callback to allocate more. */
+extern void *__libdw_allocate (Dwarf *dbg, size_t minsize)
+ __attribute__ ((__malloc__)) __nonnull_attribute__ (1);
+
+/* Default OOM handler. */
+extern void __libdw_oom (void) __attribute ((noreturn, visibility ("hidden")));
+
+/* Find CU for given offset. */
+extern struct Dwarf_CU *__libdw_findcu (Dwarf *dbg, Dwarf_Off offset)
+ __nonnull_attribute__ (1) internal_function;
+
+/* Return tag of given DIE. */
+extern Dwarf_Abbrev *__libdw_findabbrev (struct Dwarf_CU *cu,
+ unsigned int code)
+ __nonnull_attribute__ (1) internal_function;
+
+/* Get abbreviation at given offset. */
+extern Dwarf_Abbrev *__libdw_getabbrev (Dwarf *dbg, struct Dwarf_CU *cu,
+ Dwarf_Off offset, size_t *lengthp,
+ Dwarf_Abbrev *result)
+ __nonnull_attribute__ (1) internal_function;
+
+/* Helper functions for form handling. */
+extern size_t __libdw_form_val_len (Dwarf *dbg, struct Dwarf_CU *cu,
+ unsigned int form,
+ const unsigned char *valp)
+ __nonnull_attribute__ (1, 2, 4) internal_function;
+
+/* Helper function to locate attribute. */
+extern unsigned char *__libdw_find_attr (Dwarf_Die *die,
+ unsigned int search_name,
+ unsigned int *codep,
+ unsigned int *formp)
+ __nonnull_attribute__ (1) internal_function;
+
+/* Helper function to access integer attribute. */
+extern int __libdw_func_intval (Dwarf_Func *func, int *linep, int attval)
+ __nonnull_attribute__ (1, 2) internal_function;
+
+/* Return error code of last failing function call. This value is kept
+ separately for each thread. */
+extern int __dwarf_errno_internal (void);
+
+
+/* Aliases to avoid PLTs. */
+INTDECL (dwarf_attr)
+INTDECL (dwarf_attr_integrate)
+INTDECL (dwarf_begin_elf)
+INTDECL (dwarf_child)
+INTDECL (dwarf_dieoffset)
+INTDECL (dwarf_formaddr)
+INTDECL (dwarf_formblock)
+INTDECL (dwarf_formref)
+INTDECL (dwarf_formref_die)
+INTDECL (dwarf_formsdata)
+INTDECL (dwarf_formstring)
+INTDECL (dwarf_formudata)
+INTDECL (dwarf_getarange_addr)
+INTDECL (dwarf_getarangeinfo)
+INTDECL (dwarf_getaranges)
+INTDECL (dwarf_getsrcfiles)
+INTDECL (dwarf_getsrclines)
+INTDECL (dwarf_hasattr)
+INTDECL (dwarf_haschildren)
+INTDECL (dwarf_haspc)
+INTDECL (dwarf_highpc)
+INTDECL (dwarf_lowpc)
+INTDECL (dwarf_nextcu)
+INTDECL (dwarf_offdie)
+INTDECL (dwarf_siblingof)
+INTDECL (dwarf_tag)
+
+#endif /* libdwP.h */
diff --git a/libdw/libdw_alloc.c b/libdw/libdw_alloc.c
new file mode 100644
index 00000000..1c53d366
--- /dev/null
+++ b/libdw/libdw_alloc.c
@@ -0,0 +1,59 @@
+/* Memory handling for libdw.
+ Copyright (C) 2003, 2004 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <error.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include "libdwP.h"
+
+
+void *
+__libdw_allocate (Dwarf *dbg, size_t minsize)
+{
+ size_t size = MAX (dbg->mem_default_size,
+ 2 * minsize + offsetof (struct libdw_memblock, mem));
+ struct libdw_memblock *newp = malloc (size);
+ if (newp == NULL)
+ dbg->oom_handler ();
+
+ newp->size = newp->remaining = size - offsetof (struct libdw_memblock, mem);
+
+ newp->prev = dbg->mem_tail;
+ dbg->mem_tail = newp;
+
+ return newp->mem;
+}
+
+
+Dwarf_OOM
+dwarf_new_oom_handler (Dwarf *dbg, Dwarf_OOM handler)
+{
+ Dwarf_OOM old = dbg->oom_handler;
+ dbg->oom_handler = handler;
+ return old;
+}
+
+
+void
+__attribute ((noreturn, visibility ("hidden")))
+__libdw_oom (void)
+{
+ while (1)
+ error (EXIT_FAILURE, ENOMEM, "libdw");
+}
diff --git a/libdw/libdw_findcu.c b/libdw/libdw_findcu.c
new file mode 100644
index 00000000..c1d3a451
--- /dev/null
+++ b/libdw/libdw_findcu.c
@@ -0,0 +1,110 @@
+/* Find CU for given offset.
+ Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <search.h>
+#include "libdwP.h"
+
+
+static int
+findcu_cb (const void *arg1, const void *arg2)
+{
+ struct Dwarf_CU *cu1 = (struct Dwarf_CU *) arg1;
+ struct Dwarf_CU *cu2 = (struct Dwarf_CU *) arg2;
+
+ /* Find out which of the two arguments is the search value. It has
+ end offset 0. */
+ if (cu1->end == 0)
+ {
+ if (cu1->start < cu2->start)
+ return -1;
+ if (cu1->start >= cu2->end)
+ return 1;
+ }
+ else
+ {
+ if (cu2->start < cu1->start)
+ return 1;
+ if (cu2->start >= cu1->end)
+ return -1;
+ }
+
+ return 0;
+}
+
+
+struct Dwarf_CU *
+__libdw_findcu (dbg, start)
+ Dwarf *dbg;
+ Dwarf_Off start;
+{
+ /* Maybe we already know that CU. */
+ struct Dwarf_CU fake = { .start = start, .end = 0 };
+ struct Dwarf_CU **found = tfind (&fake, &dbg->cu_tree, findcu_cb);
+ if (found != NULL)
+ return *found;
+
+ if (start < dbg->next_cu_offset)
+ {
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return NULL;
+ }
+
+ /* No. Then read more CUs. */
+ while (1)
+ {
+ Dwarf_Off oldoff = dbg->next_cu_offset;
+ uint8_t address_size;
+ uint8_t offset_size;
+ Dwarf_Off abbrev_offset;
+
+ if (INTUSE(dwarf_nextcu) (dbg, oldoff, &dbg->next_cu_offset, NULL,
+ &abbrev_offset, &address_size, &offset_size)
+ != 0)
+ /* No more entries. */
+ return NULL;
+
+ /* Create an entry for this CU. */
+ struct Dwarf_CU *newp = libdw_typed_alloc (dbg, struct Dwarf_CU);
+
+ newp->dbg = dbg;
+ newp->start = oldoff;
+ newp->end = dbg->next_cu_offset;
+ newp->address_size = address_size;
+ newp->offset_size = offset_size;
+ Dwarf_Abbrev_Hash_init (&newp->abbrev_hash, 41);
+ newp->orig_abbrev_offset = newp->last_abbrev_offset = abbrev_offset;
+ newp->lines = NULL;
+ newp->locs = NULL;
+
+ /* Add the new entry to the search tree. */
+ if (tsearch (newp, &dbg->cu_tree, findcu_cb) == NULL)
+ {
+ /* Something went wrong. Unfo the operation. */
+ dbg->next_cu_offset = oldoff;
+ __libdw_seterrno (DWARF_E_NOMEM);
+ return NULL;
+ }
+
+ /* Is this the one we are looking for? */
+ if (start < dbg->next_cu_offset)
+ // XXX Match exact offset.
+ return newp;
+ }
+ /* NOTREACHED */
+}
diff --git a/libdw/libdw_form.c b/libdw/libdw_form.c
new file mode 100644
index 00000000..95d47140
--- /dev/null
+++ b/libdw/libdw_form.c
@@ -0,0 +1,112 @@
+/* Helper functions for form handling.
+ Copyright (C) 2003, 2004 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include <string.h>
+
+#include "libdwP.h"
+
+
+size_t
+internal_function_def
+__libdw_form_val_len (Dwarf *dbg, struct Dwarf_CU *cu, unsigned int form,
+ const unsigned char *valp)
+{
+ const unsigned char *saved;
+ Dwarf_Word u128;
+ size_t result;
+
+ switch (form)
+ {
+ case DW_FORM_addr:
+ result = cu->address_size;
+ break;
+
+ case DW_FORM_strp:
+ case DW_FORM_ref_addr:
+ result = cu->offset_size;
+ break;
+
+ case DW_FORM_block1:
+ result = *valp + 1;
+ break;
+
+ case DW_FORM_block2:
+ result = read_2ubyte_unaligned (dbg, valp) + 2;
+ break;
+
+ case DW_FORM_block4:
+ result = read_4ubyte_unaligned (dbg, valp) + 4;
+ break;
+
+ case DW_FORM_block:
+ saved = valp;
+ get_uleb128 (u128, valp);
+ result = u128 + (valp - saved);
+ break;
+
+ case DW_FORM_ref1:
+ case DW_FORM_data1:
+ case DW_FORM_flag:
+ result = 1;
+ break;
+
+ case DW_FORM_data2:
+ case DW_FORM_ref2:
+ result = 2;
+ break;
+
+ case DW_FORM_data4:
+ case DW_FORM_ref4:
+ result = 4;
+ break;
+
+ case DW_FORM_data8:
+ case DW_FORM_ref8:
+ result = 8;
+ break;
+
+ case DW_FORM_string:
+ result = strlen ((char *) valp) + 1;
+ break;
+
+ case DW_FORM_sdata:
+ case DW_FORM_udata:
+ case DW_FORM_ref_udata:
+ saved = valp;
+ get_uleb128 (u128, valp);
+ result = valp - saved;
+ break;
+
+ case DW_FORM_indirect:
+ saved = valp;
+ get_uleb128 (u128, valp);
+ // XXX Is this really correct?
+ result = __libdw_form_val_len (dbg, cu, u128, valp);
+ if (result != (size_t) -1)
+ result += valp - saved;
+ break;
+
+ default:
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ result = (size_t) -1l;
+ break;
+ }
+
+ return result;
+}
diff --git a/libdw/memory-access.c b/libdw/memory-access.c
new file mode 100644
index 00000000..04899a81
--- /dev/null
+++ b/libdw/memory-access.c
@@ -0,0 +1,35 @@
+/* Out of line functions for memory-access.h macros.
+ Copyright (C) 2005 Red Hat, Inc.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include "libdwP.h"
+#include "memory-access.h"
+
+uint64_t
+internal_function_def
+__libdw_get_uleb128 (uint64_t acc, unsigned int i, const unsigned char **addrp)
+{
+ unsigned char __b;
+ get_uleb128_rest_return (acc, i, addrp);
+}
+
+int64_t
+internal_function_def
+__libdw_get_sleb128 (int64_t acc, unsigned int i, const unsigned char **addrp)
+{
+ unsigned char __b;
+ int64_t _v = acc;
+ get_sleb128_rest_return (acc, i, addrp);
+}
diff --git a/libdw/memory-access.h b/libdw/memory-access.h
new file mode 100644
index 00000000..8efd8993
--- /dev/null
+++ b/libdw/memory-access.h
@@ -0,0 +1,240 @@
+/* Unaligned memory access functionality.
+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifndef _MEMORY_ACCESS_H
+#define _MEMORY_ACCESS_H 1
+
+#include <byteswap.h>
+#include <limits.h>
+#include <stdint.h>
+
+
+/* Number decoding macros. See 7.6 Variable Length Data. */
+
+#define get_uleb128_step(var, addr, nth, break) \
+ __b = *(addr)++; \
+ var |= (uintmax_t) (__b & 0x7f) << (nth * 7); \
+ if (likely ((__b & 0x80) == 0)) \
+ break
+
+#define get_uleb128(var, addr) \
+ do { \
+ unsigned char __b; \
+ var = 0; \
+ get_uleb128_step (var, addr, 0, break); \
+ var = __libdw_get_uleb128 (var, 1, &(addr)); \
+ } while (0)
+
+#define get_uleb128_rest_return(var, i, addrp) \
+ do { \
+ for (; i < 10; ++i) \
+ { \
+ get_uleb128_step (var, *addrp, i, return var); \
+ } \
+ /* Other implementations set VALUE to UINT_MAX in this \
+ case. So we better do this as well. */ \
+ return UINT64_MAX; \
+ } while (0)
+
+/* The signed case is similar, but we sign-extend the result. */
+
+#define get_sleb128_step(var, addr, nth, break) \
+ __b = *(addr)++; \
+ _v |= (uint64_t) (__b & 0x7f) << (nth * 7); \
+ if (likely ((__b & 0x80) == 0)) \
+ { \
+ var = (_v << (64 - (nth * 7) - 7) >> (64 - (nth * 7) - 7)); \
+ break; \
+ } \
+ else do {} while (0)
+
+#define get_sleb128(var, addr) \
+ do { \
+ unsigned char __b; \
+ int64_t _v = 0; \
+ get_sleb128_step (var, addr, 0, break); \
+ var = __libdw_get_sleb128 (_v, 1, &(addr)); \
+ } while (0)
+
+#define get_sleb128_rest_return(var, i, addrp) \
+ do { \
+ for (; i < 9; ++i) \
+ { \
+ get_sleb128_step (var, *addrp, i, return var); \
+ } \
+ /* Other implementations set VALUE to INT_MAX in this \
+ case. So we better do this as well. */ \
+ return INT64_MAX; \
+ } while (0)
+
+#ifdef IS_LIBDW
+extern uint64_t __libdw_get_uleb128 (uint64_t acc, unsigned int i,
+ const unsigned char **addrp)
+ internal_function attribute_hidden;
+extern int64_t __libdw_get_sleb128 (int64_t acc, unsigned int i,
+ const unsigned char **addrp)
+ internal_function attribute_hidden;
+#else
+static uint64_t
+__attribute__ ((unused))
+__libdw_get_uleb128 (uint64_t acc, unsigned int i, const unsigned char **addrp)
+{
+ unsigned char __b;
+ get_uleb128_rest_return (acc, i, addrp);
+}
+static int64_t
+__attribute__ ((unused))
+__libdw_get_sleb128 (int64_t acc, unsigned int i, const unsigned char **addrp)
+{
+ unsigned char __b;
+ int64_t _v = acc;
+ get_sleb128_rest_return (acc, i, addrp);
+}
+#endif
+
+
+/* We use simple memory access functions in case the hardware allows it.
+ The caller has to make sure we don't have alias problems. */
+#if ALLOW_UNALIGNED
+
+# define read_2ubyte_unaligned(Dbg, Addr) \
+ (unlikely ((Dbg)->other_byte_order) \
+ ? bswap_16 (*((const uint16_t *) (Addr))) \
+ : *((const uint16_t *) (Addr)))
+# define read_2sbyte_unaligned(Dbg, Addr) \
+ (unlikely ((Dbg)->other_byte_order) \
+ ? (int16_t) bswap_16 (*((const int16_t *) (Addr))) \
+ : *((const int16_t *) (Addr)))
+
+# define read_4ubyte_unaligned_noncvt(Addr) \
+ *((const uint32_t *) (Addr))
+# define read_4ubyte_unaligned(Dbg, Addr) \
+ (unlikely ((Dbg)->other_byte_order) \
+ ? bswap_32 (*((const uint32_t *) (Addr))) \
+ : *((const uint32_t *) (Addr)))
+# define read_4sbyte_unaligned(Dbg, Addr) \
+ (unlikely ((Dbg)->other_byte_order) \
+ ? (int32_t) bswap_32 (*((const int32_t *) (Addr))) \
+ : *((const int32_t *) (Addr)))
+
+# define read_8ubyte_unaligned(Dbg, Addr) \
+ (unlikely ((Dbg)->other_byte_order) \
+ ? bswap_64 (*((const uint64_t *) (Addr))) \
+ : *((const uint64_t *) (Addr)))
+# define read_8sbyte_unaligned(Dbg, Addr) \
+ (unlikely ((Dbg)->other_byte_order) \
+ ? (int64_t) bswap_64 (*((const int64_t *) (Addr))) \
+ : *((const int64_t *) (Addr)))
+
+#else
+
+union unaligned
+ {
+ void *p;
+ uint16_t u2;
+ uint32_t u4;
+ uint64_t u8;
+ int16_t s2;
+ int32_t s4;
+ int64_t s8;
+ } __attribute__ ((packed));
+
+static inline uint16_t
+read_2ubyte_unaligned (Dwarf *dbg, const void *p)
+{
+ const union unaligned *up = p;
+ if (dbg->other_byte_order)
+ return bswap_16 (up->u2);
+ return up->u2;
+}
+static inline int16_t
+read_2sbyte_unaligned (Dwarf *dbg, const void *p)
+{
+ const union unaligned *up = p;
+ if (dbg->other_byte_order)
+ return (int16_t) bswap_16 (up->u2);
+ return up->s2;
+}
+
+static inline uint32_t
+read_4ubyte_unaligned_noncvt (const void *p)
+{
+ const union unaligned *up = p;
+ return up->u4;
+}
+static inline uint32_t
+read_4ubyte_unaligned (Dwarf *dbg, const void *p)
+{
+ const union unaligned *up = p;
+ if (dbg->other_byte_order)
+ return bswap_32 (up->u4);
+ return up->u4;
+}
+static inline int32_t
+read_4sbyte_unaligned (Dwarf *dbg, const void *p)
+{
+ const union unaligned *up = p;
+ if (dbg->other_byte_order)
+ return (int32_t) bswap_32 (up->u4);
+ return up->s4;
+}
+
+static inline uint64_t
+read_8ubyte_unaligned (Dwarf *dbg, const void *p)
+{
+ const union unaligned *up = p;
+ if (dbg->other_byte_order)
+ return bswap_64 (up->u8);
+ return up->u8;
+}
+static inline int64_t
+read_8sbyte_unaligned (Dwarf *dbg, const void *p)
+{
+ const union unaligned *up = p;
+ if (dbg->other_byte_order)
+ return (int64_t) bswap_64 (up->u8);
+ return up->s8;
+}
+
+#endif /* allow unaligned */
+
+
+#define read_2ubyte_unaligned_inc(Dbg, Addr) \
+ ({ uint16_t t_ = read_2ubyte_unaligned (Dbg, Addr); \
+ Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2); \
+ t_; })
+#define read_2sbyte_unaligned_inc(Dbg, Addr) \
+ ({ int16_t t_ = read_2sbyte_unaligned (Dbg, Addr); \
+ Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2); \
+ t_; })
+
+#define read_4ubyte_unaligned_inc(Dbg, Addr) \
+ ({ uint32_t t_ = read_4ubyte_unaligned (Dbg, Addr); \
+ Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4); \
+ t_; })
+#define read_4sbyte_unaligned_inc(Dbg, Addr) \
+ ({ int32_t t_ = read_4sbyte_unaligned (Dbg, Addr); \
+ Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4); \
+ t_; })
+
+#define read_8ubyte_unaligned_inc(Dbg, Addr) \
+ ({ uint64_t t_ = read_8ubyte_unaligned (Dbg, Addr); \
+ Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8); \
+ t_; })
+#define read_8sbyte_unaligned_inc(Dbg, Addr) \
+ ({ int64_t t_ = read_8sbyte_unaligned (Dbg, Addr); \
+ Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8); \
+ t_; })
+
+#endif /* memory-access.h */