summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2012-10-20 14:42:03 +0400
committerIgor Pashev <pashev.igor@gmail.com>2012-10-20 14:42:03 +0400
commitbb1c3da3c12651f1c408d96dd6d33ae157bdadd6 (patch)
tree4a535b35500684ac6a928bf0fd661325b5a04697
downloaddwarfutils-upstream.tar.gz
Imported Upstream version 20120410upstream/20120410upstream
-rwxr-xr-xBLDLIBDWARF30
-rw-r--r--dwarfdump/CODINGSTYLE44
-rw-r--r--dwarfdump/COPYING31
-rw-r--r--dwarfdump/ChangeLog2
-rw-r--r--dwarfdump/ChangeLog2006332
-rw-r--r--dwarfdump/ChangeLog2007108
-rw-r--r--dwarfdump/ChangeLog200896
-rw-r--r--dwarfdump/ChangeLog2009280
-rw-r--r--dwarfdump/ChangeLog2010105
-rw-r--r--dwarfdump/DWARFDUMPCOPYRIGHT85
-rw-r--r--dwarfdump/GPL.txt339
-rw-r--r--dwarfdump/Makefile.in191
-rw-r--r--dwarfdump/NEWS206
-rw-r--r--dwarfdump/README82
-rw-r--r--dwarfdump/addrmap.c149
-rw-r--r--dwarfdump/addrmap.h33
-rw-r--r--dwarfdump/checkutil.c565
-rw-r--r--dwarfdump/checkutil.h98
-rw-r--r--dwarfdump/common.c88
-rw-r--r--dwarfdump/common.h42
-rw-r--r--dwarfdump/config.h.in100
-rwxr-xr-xdwarfdump/configure5109
-rw-r--r--dwarfdump/configure.in98
-rw-r--r--dwarfdump/dwarfdump.1523
-rw-r--r--dwarfdump/dwarfdump.c2357
-rw-r--r--dwarfdump/dwarfdump.conf810
-rw-r--r--dwarfdump/dwconf.c1424
-rw-r--r--dwarfdump/dwconf.h106
-rw-r--r--dwarfdump/esb.c242
-rw-r--r--dwarfdump/esb.h86
-rw-r--r--dwarfdump/globals.h459
-rwxr-xr-xdwarfdump/install.sh119
-rw-r--r--dwarfdump/makename.c68
-rw-r--r--dwarfdump/makename.h53
-rw-r--r--dwarfdump/naming.c261
-rw-r--r--dwarfdump/naming.h73
-rw-r--r--dwarfdump/print_abbrevs.c304
-rw-r--r--dwarfdump/print_aranges.c267
-rw-r--r--dwarfdump/print_die.c3540
-rw-r--r--dwarfdump/print_frames.c1823
-rw-r--r--dwarfdump/print_frames.h47
-rw-r--r--dwarfdump/print_lines.c433
-rw-r--r--dwarfdump/print_locs.c128
-rw-r--r--dwarfdump/print_macros.c216
-rw-r--r--dwarfdump/print_pubnames.c300
-rw-r--r--dwarfdump/print_ranges.c106
-rw-r--r--dwarfdump/print_reloc.c1150
-rw-r--r--dwarfdump/print_reloc.h307
-rw-r--r--dwarfdump/print_sections.c206
-rw-r--r--dwarfdump/print_sections.h54
-rw-r--r--dwarfdump/print_static_funcs.c137
-rw-r--r--dwarfdump/print_static_vars.c104
-rw-r--r--dwarfdump/print_strings.c80
-rw-r--r--dwarfdump/print_types.c141
-rw-r--r--dwarfdump/print_weaknames.c104
-rwxr-xr-xdwarfdump/strstrnocase.c118
-rw-r--r--dwarfdump/tag_attr.c286
-rw-r--r--dwarfdump/tag_attr.list880
-rw-r--r--dwarfdump/tag_attr_ext.list78
-rw-r--r--dwarfdump/tag_common.c145
-rw-r--r--dwarfdump/tag_common.h123
-rw-r--r--dwarfdump/tag_tree.c290
-rw-r--r--dwarfdump/tag_tree.list486
-rw-r--r--dwarfdump/tag_tree_ext.list63
-rw-r--r--dwarfdump/testesb.c78
-rw-r--r--dwarfdump/uri.c493
-rw-r--r--dwarfdump/uri.h37
-rw-r--r--dwarfdump/uritablebuild.c146
-rw-r--r--dwarfdump2/COPYING31
-rw-r--r--dwarfdump2/ChangeLog2
-rw-r--r--dwarfdump2/ChangeLog2009156
-rw-r--r--dwarfdump2/ChangeLog201077
-rw-r--r--dwarfdump2/DWARFDUMPCOPYRIGHT85
-rw-r--r--dwarfdump2/GPL.txt339
-rw-r--r--dwarfdump2/Makefile.in175
-rw-r--r--dwarfdump2/NEWS52
-rw-r--r--dwarfdump2/README86
-rw-r--r--dwarfdump2/checkutil.cc156
-rw-r--r--dwarfdump2/checkutil.h158
-rw-r--r--dwarfdump2/common.cc88
-rw-r--r--dwarfdump2/common.h46
-rw-r--r--dwarfdump2/config.h.in94
-rwxr-xr-xdwarfdump2/configure5354
-rw-r--r--dwarfdump2/configure.in70
-rw-r--r--dwarfdump2/dieholder.h80
-rw-r--r--dwarfdump2/dwarfdump.1523
-rw-r--r--dwarfdump2/dwarfdump.cc2258
-rw-r--r--dwarfdump2/dwarfdump.conf810
-rw-r--r--dwarfdump2/dwconf.cc1291
-rw-r--r--dwarfdump2/dwconf.h109
-rw-r--r--dwarfdump2/fderegs.h136
-rw-r--r--dwarfdump2/globals.h587
-rwxr-xr-xdwarfdump2/install.sh119
-rw-r--r--dwarfdump2/naming.cc264
-rw-r--r--dwarfdump2/naming.h71
-rw-r--r--dwarfdump2/print_abbrevs.cc307
-rw-r--r--dwarfdump2/print_aranges.cc266
-rw-r--r--dwarfdump2/print_die.cc3281
-rw-r--r--dwarfdump2/print_frames.cc1621
-rw-r--r--dwarfdump2/print_frames.h59
-rw-r--r--dwarfdump2/print_lines.cc435
-rw-r--r--dwarfdump2/print_locs.cc131
-rw-r--r--dwarfdump2/print_macros.cc208
-rw-r--r--dwarfdump2/print_pubnames.cc277
-rw-r--r--dwarfdump2/print_ranges.cc121
-rw-r--r--dwarfdump2/print_reloc.cc1146
-rw-r--r--dwarfdump2/print_sections.cc216
-rw-r--r--dwarfdump2/print_sections.h55
-rw-r--r--dwarfdump2/print_static_funcs.cc135
-rw-r--r--dwarfdump2/print_static_vars.cc106
-rw-r--r--dwarfdump2/print_strings.cc88
-rw-r--r--dwarfdump2/print_types.cc142
-rw-r--r--dwarfdump2/print_weaknames.cc113
-rw-r--r--dwarfdump2/srcfilesholder.h89
-rwxr-xr-xdwarfdump2/strstrnocase.cc115
-rw-r--r--dwarfdump2/tag_attr.cc278
-rw-r--r--dwarfdump2/tag_attr.list880
-rw-r--r--dwarfdump2/tag_attr_ext.list78
-rw-r--r--dwarfdump2/tag_common.cc150
-rw-r--r--dwarfdump2/tag_common.h125
-rw-r--r--dwarfdump2/tag_tree.cc282
-rw-r--r--dwarfdump2/tag_tree.list486
-rw-r--r--dwarfdump2/tag_tree_ext.list63
-rw-r--r--dwarfdump2/uri.cc477
-rw-r--r--dwarfdump2/uri.h37
-rw-r--r--dwarfexample/ChangeLog5
-rw-r--r--dwarfexample/ChangeLog20098
-rw-r--r--dwarfexample/ChangeLog201011
-rw-r--r--dwarfexample/Makefile18
-rw-r--r--dwarfexample/NEWS6
-rw-r--r--dwarfexample/frame1.c408
-rw-r--r--dwarfexample/simplereader.c384
-rw-r--r--dwarfgen/COPYING30
-rw-r--r--dwarfgen/ChangeLog6
-rw-r--r--dwarfgen/GPL.txt339
-rw-r--r--dwarfgen/Makefile.in89
-rw-r--r--dwarfgen/README20
-rw-r--r--dwarfgen/config.h.in85
-rwxr-xr-xdwarfgen/configure5445
-rw-r--r--dwarfgen/configure.in41
-rw-r--r--dwarfgen/createirepformfrombinary.cc357
-rw-r--r--dwarfgen/createirepfrombinary.cc608
-rw-r--r--dwarfgen/createirepfrombinary.h22
-rw-r--r--dwarfgen/dwarfgen.110
-rwxr-xr-xdwarfgen/dwarfgen.cc666
-rw-r--r--dwarfgen/general.h55
-rwxr-xr-xdwarfgen/install.sh119
-rw-r--r--dwarfgen/irepattrtodbg.cc221
-rw-r--r--dwarfgen/irepattrtodbg.h26
-rw-r--r--dwarfgen/irepdie.h228
-rw-r--r--dwarfgen/irepform.h592
-rw-r--r--dwarfgen/irepframe.h154
-rw-r--r--dwarfgen/irepline.h101
-rw-r--r--dwarfgen/irepmacro.h47
-rw-r--r--dwarfgen/irepresentation.h135
-rw-r--r--dwarfgen/ireptodbg.cc371
-rw-r--r--dwarfgen/ireptodbg.h24
-rwxr-xr-xdwarfgen/strtabdata.h65
-rw-r--r--libdwarf/CHANGES102
-rw-r--r--libdwarf/CODINGSTYLE61
-rw-r--r--libdwarf/COPYING37
-rw-r--r--libdwarf/ChangeLog9
-rw-r--r--libdwarf/ChangeLog2006835
-rw-r--r--libdwarf/ChangeLog2007217
-rw-r--r--libdwarf/ChangeLog2008263
-rw-r--r--libdwarf/ChangeLog2009348
-rw-r--r--libdwarf/ChangeLog2010175
-rw-r--r--libdwarf/LGPL.txt504
-rw-r--r--libdwarf/LIBDWARFCOPYRIGHT30
-rw-r--r--libdwarf/Makefile.in227
-rw-r--r--libdwarf/NEWS406
-rw-r--r--libdwarf/README199
-rw-r--r--libdwarf/bldDWindex.sh24
-rw-r--r--libdwarf/cmplrs/dwarf_addr_finder.h55
-rw-r--r--libdwarf/common.c71
-rw-r--r--libdwarf/common.h47
-rw-r--r--libdwarf/config.h.in143
-rwxr-xr-xlibdwarf/configure5480
-rw-r--r--libdwarf/configure.in134
-rw-r--r--libdwarf/dwarf.h1182
-rw-r--r--libdwarf/dwarf.v2.mm7699
-rw-r--r--libdwarf/dwarf.v2.pdfbin0 -> 251991 bytes
-rw-r--r--libdwarf/dwarf_abbrev.c289
-rw-r--r--libdwarf/dwarf_abbrev.h54
-rw-r--r--libdwarf/dwarf_addr_finder.c680
-rw-r--r--libdwarf/dwarf_alloc.c1270
-rw-r--r--libdwarf/dwarf_alloc.h168
-rw-r--r--libdwarf/dwarf_arange.c616
-rw-r--r--libdwarf/dwarf_arange.h71
-rw-r--r--libdwarf/dwarf_base_types.h118
-rw-r--r--libdwarf/dwarf_die_deliv.c1214
-rw-r--r--libdwarf/dwarf_die_deliv.h55
-rw-r--r--libdwarf/dwarf_elf_access.c1027
-rw-r--r--libdwarf/dwarf_elf_access.h55
-rw-r--r--libdwarf/dwarf_error.c418
-rw-r--r--libdwarf/dwarf_error.h44
-rw-r--r--libdwarf/dwarf_form.c931
-rw-r--r--libdwarf/dwarf_frame.c2431
-rw-r--r--libdwarf/dwarf_frame.h419
-rw-r--r--libdwarf/dwarf_frame2.c1531
-rw-r--r--libdwarf/dwarf_frame3.c292
-rw-r--r--libdwarf/dwarf_funcs.c134
-rw-r--r--libdwarf/dwarf_funcs.h42
-rw-r--r--libdwarf/dwarf_global.c614
-rw-r--r--libdwarf/dwarf_global.h126
-rw-r--r--libdwarf/dwarf_harmless.c226
-rw-r--r--libdwarf/dwarf_harmless.h31
-rw-r--r--libdwarf/dwarf_incl.h69
-rw-r--r--libdwarf/dwarf_init_finish.c732
-rw-r--r--libdwarf/dwarf_leb.c146
-rw-r--r--libdwarf/dwarf_line.c2059
-rw-r--r--libdwarf/dwarf_line.h326
-rw-r--r--libdwarf/dwarf_line2.c107
-rw-r--r--libdwarf/dwarf_loc.c1197
-rw-r--r--libdwarf/dwarf_loc.h46
-rw-r--r--libdwarf/dwarf_macro.c470
-rw-r--r--libdwarf/dwarf_macro.h44
-rw-r--r--libdwarf/dwarf_opaque.h364
-rw-r--r--libdwarf/dwarf_original_elf_init.c194
-rw-r--r--libdwarf/dwarf_print_lines.c736
-rw-r--r--libdwarf/dwarf_pubtypes.c142
-rw-r--r--libdwarf/dwarf_query.c856
-rw-r--r--libdwarf/dwarf_ranges.c172
-rw-r--r--libdwarf/dwarf_sort_line.c676
-rw-r--r--libdwarf/dwarf_string.c83
-rw-r--r--libdwarf/dwarf_stubs.c51
-rw-r--r--libdwarf/dwarf_types.c132
-rw-r--r--libdwarf/dwarf_types.h41
-rw-r--r--libdwarf/dwarf_util.c584
-rw-r--r--libdwarf/dwarf_util.h324
-rw-r--r--libdwarf/dwarf_vars.c136
-rw-r--r--libdwarf/dwarf_vars.h41
-rw-r--r--libdwarf/dwarf_weaks.c134
-rw-r--r--libdwarf/dwarf_weaks.h41
-rw-r--r--libdwarf/gennames.c541
-rw-r--r--libdwarf/index.v2.mm266
-rw-r--r--libdwarf/index.v2.pdfbin0 -> 7139 bytes
-rwxr-xr-xlibdwarf/install.sh119
-rw-r--r--libdwarf/libdwarf.h2964
-rw-r--r--libdwarf/libdwarf2.1.mm6626
-rw-r--r--libdwarf/libdwarf2.1.pdfbin0 -> 249383 bytes
-rw-r--r--libdwarf/libdwarf2p.1.mm2748
-rw-r--r--libdwarf/libdwarf2p.1.pdfbin0 -> 25580 bytes
-rw-r--r--libdwarf/libdwarfdefs.h91
-rw-r--r--libdwarf/malloc_check.c339
-rw-r--r--libdwarf/malloc_check.h62
-rw-r--r--libdwarf/mips_extensions.mm1266
-rw-r--r--libdwarf/mips_extensions.pdfbin0 -> 57910 bytes
-rw-r--r--libdwarf/pro_alloc.c188
-rw-r--r--libdwarf/pro_alloc.h42
-rw-r--r--libdwarf/pro_arange.c321
-rw-r--r--libdwarf/pro_arange.h60
-rw-r--r--libdwarf/pro_die.c439
-rw-r--r--libdwarf/pro_die.h68
-rw-r--r--libdwarf/pro_encode_nm.c119
-rw-r--r--libdwarf/pro_encode_nm.h48
-rw-r--r--libdwarf/pro_error.c107
-rw-r--r--libdwarf/pro_error.h52
-rw-r--r--libdwarf/pro_expr.c585
-rw-r--r--libdwarf/pro_expr.h45
-rw-r--r--libdwarf/pro_finish.c56
-rw-r--r--libdwarf/pro_forms.c1161
-rw-r--r--libdwarf/pro_frame.c582
-rw-r--r--libdwarf/pro_frame.h129
-rw-r--r--libdwarf/pro_funcs.c61
-rw-r--r--libdwarf/pro_incl.h95
-rw-r--r--libdwarf/pro_init.c291
-rw-r--r--libdwarf/pro_line.c384
-rw-r--r--libdwarf/pro_line.h121
-rw-r--r--libdwarf/pro_macinfo.c468
-rw-r--r--libdwarf/pro_macinfo.h40
-rw-r--r--libdwarf/pro_opaque.h516
-rw-r--r--libdwarf/pro_pubnames.c62
-rw-r--r--libdwarf/pro_reloc.c263
-rw-r--r--libdwarf/pro_reloc.h47
-rw-r--r--libdwarf/pro_reloc_stream.c291
-rw-r--r--libdwarf/pro_reloc_stream.h61
-rw-r--r--libdwarf/pro_reloc_symbolic.c279
-rw-r--r--libdwarf/pro_reloc_symbolic.h54
-rw-r--r--libdwarf/pro_section.c2263
-rw-r--r--libdwarf/pro_section.h109
-rw-r--r--libdwarf/pro_types.c284
-rw-r--r--libdwarf/pro_types.h43
-rw-r--r--libdwarf/pro_util.h146
-rw-r--r--libdwarf/pro_vars.c63
-rw-r--r--libdwarf/pro_weaks.c62
286 files changed, 129178 insertions, 0 deletions
diff --git a/BLDLIBDWARF b/BLDLIBDWARF
new file mode 100755
index 0000000..8309961
--- /dev/null
+++ b/BLDLIBDWARF
@@ -0,0 +1,30 @@
+#!/bin/sh
+#
+bldone () {
+ t=$1
+ cd $t
+ # The following distclean will fail on a clean directory
+ # Ignore the failure
+ make distclean
+ ./configure
+ if [ $? != 0 ]
+ then
+ echo build failed
+ exit
+ fi
+ make
+ if [ $? != 0 ]
+ then
+ echo build failed
+ exit
+ fi
+ cd ..
+}
+
+bldone libdwarf
+bldone dwarfdump
+bldone dwarfdump2
+
+
+
+
diff --git a/dwarfdump/CODINGSTYLE b/dwarfdump/CODINGSTYLE
new file mode 100644
index 0000000..64bbb48
--- /dev/null
+++ b/dwarfdump/CODINGSTYLE
@@ -0,0 +1,44 @@
+This document is a brief description of the main
+coding style conventions in dwarfdump. Many of them
+will be obvious from the code, but over time some
+accidental diffences crept in.
+
+
+Code should be indented in multiples of 4 spaces, and
+tabs should not be used to indent the source code.
+Use the dicheck program to check indenting.
+
+The struct naming convention is 'struct my_struct_s' for the
+struct defined here (meaning the name should end with _s).
+It is better to not do struct typedefs of local structs.
+Coders should type 'struct mystruct_s'. Readability
+is much more important than brevity.
+
+Any data or function not referenced outside the
+defining source file should be declared 'static'.
+
+Any duplicated code is a candidate for refactoring
+into a subprogram.
+
+Function names should be all lower case with underbars
+with the goal that statements and comments 'read well'.
+
+Variables should be lower-case with
+underbars for readability. It's ok for a small loop
+with counters to use single letter names like i or k or m.
+
+Structure members should have a struct-specific
+2-character prefix to the name (followed by
+an underbar). That makes it much
+easier to grep for uses of members.
+
+Try to keep lines under 80 characters in length.
+
+Ensure every if() has {} to enclose the actions.
+
+Use libdwarf.h types for all the data objects you define,
+though sometimes an 'unsigned' or 'int' or 'size_t' is
+ok in restricted circumstances. Dwarf_Unsigned and
+Dwarf_Signed are the preferred integer types for general use.
+
+------------
diff --git a/dwarfdump/COPYING b/dwarfdump/COPYING
new file mode 100644
index 0000000..355bd60
--- /dev/null
+++ b/dwarfdump/COPYING
@@ -0,0 +1,31 @@
+
+David Anderson: December 2006
+The code in the dwarfdump directory is (if you look
+in each file) covered by the GPL (not the LGPL). The
+DWARFDUMPCOPYRIGHT file, though, said (before December 24,
+2006) the copyright is LGPL. There is no doubt in my (David
+Anderson) mind that the intent was always that dwarfdump be
+GPL and the copyright markings in each file are correct.
+
+There are three files marked with the LGPL: tag_tree.list
+tag_attr.list acconfig.h. These markings are left as is and
+these are are therefore LGPL files.
+
+The DWARFDUMPCOPYRIGHT file now (Dec 24 2006) has both
+copyrights and an explanation of where each applies.
+
+
+
+-------------------------------------------
+The text present for years, thru Dec 23, 2006:
+The files:
+ dwarfdump.c
+ and all the .h and .c files in this implementation of
+ dwarfdump are copyrighted according to the file
+ DWARFDUMPCOPYRIGHT.
+
+
+
+$Source: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/COPYING,v $
+$Revision: 1.1 $
+$Date: 2001/01/16 17:47:55 $
diff --git a/dwarfdump/ChangeLog b/dwarfdump/ChangeLog
new file mode 100644
index 0000000..03bb4a1
--- /dev/null
+++ b/dwarfdump/ChangeLog
@@ -0,0 +1,2 @@
+2012-04-10 DavidAnderson <davea42@earthlink.net>
+ * dwarfdump.c, common.c: Updated version string.
diff --git a/dwarfdump/ChangeLog2006 b/dwarfdump/ChangeLog2006
new file mode 100644
index 0000000..dbedb67
--- /dev/null
+++ b/dwarfdump/ChangeLog2006
@@ -0,0 +1,332 @@
+2006-12-24 David Anderson <davea@sgi.com>
+ * DWARFDUMPCOPYRIGHT: Added GPL copyright text with
+ explanation of the intended content.
+ * COPYING: added text explaining confusion of GPL vs LGPL.
+ Thanks to Chris Quenelle for pointing out the disconnect
+ between DWARFDUMPCOPYRIGHT and the source files in dwarfdump.
+2006-12-21 David Anderson <davea@sgi.com>
+ * tag_tree.list: add tags to make allowed list more complete.
+ Omission noticed by Marcel Mettes.
+2006-06-14 David Anderson <davea@sgi.com>
+ * print_frames.c: Clean up printing of augmentation data by
+ eliminating dangling 0x (for eh_frame).
+2006-04-28 David Anderson <davea@sgi.com>
+ * dwarfdump.conf: Now has x86_64 register names.
+ x86_64 with help from Tom Hughes (verified
+ from independent sources).
+ Added m68k register names and refined x86 list
+ by looking at various information-sources.
+2006-04-18 David Anderson <davea@sgi.com>
+ * *.c: Ran indent so all now follow a standard look.
+ * dwconf.c: Added fclose(conf_stream).
+2006-04-18 David Anderson <davea@sgi.com>
+ * dwarfdump.c: Forgot to call key new functions for
+ handling variable-size frame data and different
+ frame rule initialization value.
+ * dwconf.c: Add a default print for CFA in case of
+ an omission in dwarfdump.conf.
+ * dwarfdump.conf: Move setup and rename the ABIs slightly.
+2006-04-17 David Anderson <davea@sgi.com>
+ * dwarfdump.conf: Correct typos. Remove some register names.
+ * dwarfdump.c: Fix compiler warnings, fix -x option usage message.
+ * dwconf.h: Fix compiler warnings by changing types.
+ * dwconf.c: Change error checking so we check all errors, do
+ not stop at first error. Ran indent. Added code to check
+ for extra junk after operand(s).
+ * print_frames.c: Fix compiler warnings.
+ * Makefile.in: get <prefix> used in install rule and creating
+ places to search for dwarfdump.conf
+2006-04-16 David Anderson <davea@sgi.com>
+ * dwarfdump.conf: New dwarfdump configuration file. Makes using frame
+ information easy to read and correct for any ABI/ISA
+ without rebuilding dwarfdump.
+ * Makefile.in: Added new files dwconf.h dwconf.c
+ * dwconf.h dwconf.c: New files implement reading dwarfdump.conf
+ and help print_frames.c print frame information correctly
+ for ABIs specified at runtime.
+ * dwarfdump.1: document -x commands.
+ * globals.h: Minor changes to support dwarfdump.conf
+ * print_frames.c: Major changes to support a run-time description of
+ the frames info and dwarfdump.conf.
+ * print_frames.h: Changes to support a run-time description of
+ the frames info and dwarfdump.conf.
+ * print_sections.c: Minor tweaks to support a run-time
+ description of the frames info and dwarfdump.conf.
+
+2006-03-31 David Anderson <davea@sgi.com>
+ * Makefile.in globals.h print_sections.c: Refer to new
+ print_frames.h print_frames.c.
+ * print_frames.h print_frames.c: Extract cie, fde printing
+ to separate file, separating loop logic from the printing
+ of an entry from the loop.
+2006-03-31 David Anderson <davea@sgi.com>
+ * dwarfdump.c global.h print_sections.c: Preparing for
+ dwarf3 frame interface.
+ * print_die.c: Corrects handling of DW_AT_encoding (etc) value.
+2006-03-29 David Anderson <davea@sgi.com>
+ * print_sections.c: define DWARFDUMP_TURN_OFF_MIPS_REG_NAMES
+ at compile time
+ to turn off the MIPS register names printing. Instead
+ (aside from cfa) use a name like r4 (where the DWARF
+ register number follows the letter 'r').
+ Indent. Initialize some local variables at declarations.
+2006-03-13 David Anderson <davea@sgi.com>
+ * print_sections.c: Now gets gnu eh_augmentation data by calling
+ dwarf_get_cie_augmentation_data() or dwarf_get_fde_augmentation_data()
+ and prints it (use -v to see cie data).
+ Now prints DWARF3 frame information.
+2006-03-08 David Anderson <davea@sgi.com>
+ * print_sections.c: Add 'break;' at line 710.
+ Thanks to Richard Stuckey for noticing.
+2005-12-01 David Anderson <davea@sgi.com>
+ * dwarf_names.awk: use snprintf instead of sprintf for safety.
+2005-12-01 David Anderson <davea@sgi.com>
+ * Makefile.in: Build attr/tag trees with
+ individual commands to catch build errors.
+ * tag_attr.c,tag_tree.c: Verify that
+ tables fit in the generated C code and check for
+ format errors in the *.list files.
+ * tag_attr.list, tag_tree.list: Added some valid entries.
+ * globals.h: add DWARF_ERROR3 macro for better diagnostics.
+ * print_die.c: Show both sides of questionable tag relation
+ in CHECK -k diagnostic output.
+
+2005-11-25 David Anderson <davea@sgi.com>
+ * print_die.c: DW_AT_stride_size changed to DW_AT_bit_stride,
+ added DW_AT_byte_stride.
+ * tag_attr.c,tag_tree.c: fixed array size now a #define for
+ readability.
+ * tag_attr.list: Added DWARF3 attributes, also new TAGs.
+ * tag_tree.list: Added DWARF3 TAGs.
+
+2005-11-08 David Anderson <davea@sgi.com>
+ * makename.c: remove non-standard malloc.h include,
+ stdlib.h suffices and is already included.
+
+2005-10-24 David Anderson <davea@sgi.com>
+ * tag_attr.c tag_tree.c: added DWARF3 TAGs to string array.
+
+2005-08-01 David Anderson <davea@sgi.com>
+ * Makefile.in: Add esb.o and test rule (test code for esb.c).
+ * dwarfdump.c: Remove old static buffer initialization.
+ * print_die.c: Use esb now, avoid crash due to long loclist
+ overrunning static buffer. Uses snprintf now, not sprintf.
+ snprintf is for safety.
+ * esb.h esb.c: Adding extensible string buffer (esb) code.
+ * testesb.c: Test code for esb.c.
+ * print_reloc.c: size field is now Elf64_Xword for
+ Elf64 as Elf64_Word is only 32 bits.
+
+2005-07-15 David Anderson <davea@sgi.com>
+ * dwarfdump.c: Add print of .debug_pubtypes, remove
+ erroneous dealloc after dwarf_formstring() call.
+ * globals.h: Add declarations for .debug_pubtypes print. Add
+ declaration for full dealloc.
+ * print_die.c: Remove erroneous dealloc after dwarf_formstring() call.
+ * print_exception_tables.c: Call dwarf_fde_cie_list_dealloc()
+ for complete dealloc.
+ * print_sections.c: Remove incorrect dealloc() call.
+ Add calls to new dealloc routines. Add support of .debug_pubtypes
+ print.
+2005-07-14 David Anderson <davea@sgi.com>
+ * print_sections.c (print_line_numbers_this_cu): Use new
+ dwarf_srclines_dealloc() for deallocation after
+ dwarf_srclines() called.
+
+2005-04-13 David Anderson <davea@sgi.com>
+ * print_sections.c: Factors out common print code into
+ a new routine. Avoid indexing past end of register names
+ array. Adds checks and prints so that certain errors
+ in pubnames-like sections are printed usefully (and dwarfdump
+ then stops if libdwarf gave an error).
+
+2005-03-21 David Anderson <davea@sgi.com>
+ * dwarfdump.c: Add -F flag to
+ request .eh_frame section print. Changed -f flag meaning
+ to print .debug_frame only. -a flag no longer
+ prints .debug_frame by default.
+ * print_sections.c: avoid printing an eh_frame we don't understand.
+ Add new information per CU when printing line info: specifically
+ the line section offset.
+ * globals.h: Added arguments to print_frames() for -F flag.
+
+2005-03-18 David Anderson <davea@sgi.com>
+ * print_sections.c: Correct macro section printing.
+
+2004-10-28 David Anderson <davea@sgi.com>
+ * DWARFDUMPCOPYRIGHT config.h defs.h dwarfdump.c globals.h
+ makename.c makename.h print_die.c print_exception_tables.c
+ print_reloc.c print_sections.c tag_attr.c tag_attr.list
+ tag_tree.c tag_tree.list: Copyright update, SGI
+ corporate address change.
+
+2004-10-26 David Anderson <davea@sgi.com>
+ * acconfig.h: removed. Was old style autoconf usage.
+ * configure.in: Updated AC_DEFINE usage, adding args 2 & 3.
+ * config.guess: Updated. timestamp='2004-06-11'.
+ * config.sub: Updated. timestamp='2004-03-12'.
+ * configure config.h.in: regenerated with autoconf 2.58.
+
+2004-05-14 David Anderson <davea@sgi.com>
+
+ * print_die.c (print_die_and_children): Change to iteration
+ on siblings (still recursing on children).
+
+
+2004-03-30 David Anderson <davea@sgi.com>
+ * dwarfdump.c (main): getopt() string should contain k:g
+ not kg: Thanks to Peter Seiderer for pointing this out.
+
+2003-12-31 David Anderson <davea@sgi.com>
+ * README: Added configure example.
+ * Makefile.in: Removed bogus LIBS line, updated copyright date.
+ * acconfig.h: Added LGPL copyright to match libdwarf
+ Silly, but it matches libdwarf version boilerplate.
+ * config.guess config.sub: new versions from automake-1.6.
+ * config.h.in configure: Regenerated.
+
+
+2003-10-06 David Anderson <davea@sgi.com>
+ * dwarfdump.c print_sections.c: applied indent(1).
+ * print_die.c: applied indent and added ; after
+ invocations of macros PUSH_DIE_STACK POP_DIE_STACK SPACE
+ as these were confusing indent a bit.
+ The indent control file .indent.pro contained:
+ -bad -bap -nbbo -br -ce -brs
+ -l72 -lc72 -hnl -nprs
+ -fca -i4 -lp -psl -npcs
+
+
+
+2003-10-02 David Anderson <davea@sgi.com>
+ * dwarfdump.c: Add -g to indicate use of older
+ location entry code in libdwarf. So dwarf_loclist
+ and dwarf_loclist_n are testable.
+ * globals.h: Added use_old_dwarf_loclist flag so one
+ can choose the old dwarf_loclist() interface.
+ For testing.
+ * print_die.c: Rearranged to avoid code duplication.
+ Now supports .debug_loc fully.
+ * print_sections.c: Prints .debug_loc now.
+
+2003-09-29 David Anderson <davea@sgi.com>
+
+ * print_die.c: with -v, print 'loclist' start and
+ end addr and also a hint that DW_FORM_indirect is used.
+ No change for normal output (for now).
+
+2003-05-19 David Anderson <davea@sgi.com>
+ * dwarfdump.c call dwarf_srcfiles() to get file names
+ per cu and pass down to die print routines.
+ Removed incorrect tests for when to print ".debug_info",
+ leaving simpler test.
+ * print_die.c globals.h: print file name (from line info)
+ with DW_AT_decl_file, adding data from dwarf_srcfiles
+ to argument list of a few routines to make that possible.
+ * print_sections.c: moved "line number info" string print so
+ it prints for -v as well as normal line ouput.
+
+2002-10-23 Amaury Le Leyzour amaury@sgi.com
+ * print_sections.c (print_weaknames): Changed
+ DW_DLA_TYPENAME to DW_DLA_WEAK at dwarf_dealloc().
+
+2002-10-22 Tom Hughes <thh@cyberscience.com>
+ * print_sections.c: macro printing now supported.
+ * dwarfdump.c: removed erroneous dwarf_dealloc()
+ of string returned by dwarf_errmsg().
+
+2002-11-22 David Anderson <davea@sgi.com>
+ * dwarf_names.awk at_list.awk: Allow an name to have two
+ spellings so the historical name preserved yet the dwarf3
+ version is supported. First name seen is used/reported
+ by dwarfdump.
+ * dwarf.h: DW_TAG_template_type_param(eter)
+ DW_TAG_template_value_param(eter) DW_AT_namelist_itm(s)
+ are the ones with alternate spellings now.
+ Added Universal Parallel C TAGs/Attributes in
+ user namespace.
+ * tag_attr.c tag_attr.list tag_tree.c tag_tree.list:
+ Use the DW_TAG_template_* dwarf3 spellings.
+
+
+2002-05-08 David Anderson <davea@sgi.com>
+ * tag_attr.list dwarf.h: DW_AT_namelist_items is
+ wrong, changed to DW_AT_namelist_item
+
+2002-04-29 Stephen Clarke <stephen.clarke@superh.com>
+ * dwarfdump.c (main): #ifdef for __CYGWIN__ on open().
+
+2001-06-14 David Anderson <davea@sgi.com>
+
+ * print_sections.c: Calling the new libdwarf function
+ dwarf_get_arange_cu_header_offset() so we can print
+ the cu header offset for aranges.
+
+
+2000-07-14 Fred Fish <fnf@ninemoons.com>
+
+ * configure.in (LOCATION_OF_LIBELFHEADER): Fix typo for configure
+ variable to be tested and enclose libelf/libelf.h in <>.
+ * configure: Regenerated.
+
+2000-07-10 Fred Fish <fnf@ninemoons.com>
+
+ * Makefile.in (install): Install dwarfdump.1 from $(srcdir).
+
+2000 June 12 davea@sgi.com
+ print_sections.c the DW_CFA_offset_extended print
+ did not multiply by data-alignment factor in the
+ -v -v detailed output.
+ And the offsets used %2d when the values were
+ unsigned int, so now %2u.
+
+ And not all cfa prints of values had
+ necessarily a type to match
+ %llu or %lld where required. Depended on the size of Dwarf_Signed
+ and Dwarf_Unsigned.
+ So now explicitly use cast to the
+ right type to match the % format.
+2000 April 13 davea@sgi.com
+ print_sections.c - 1.56
+ - A single byte of zero is a perfectly legitmate null
+ abbreviation entry (in .debug_abbrev)
+ now we print those directly and avoid a warning
+ from dwarfdump
+
+ print_die.c - 1.42
+ - Explain what combo checker is doing and make it
+ more maintainable (and fix bug which would
+ not be hit, but was real enough (in combo checker),
+ using too large a number as highest tag number).
+
+ tag_tree.list - 1.2
+ - Add valid parent/child relationships so checker
+ does not report valid entries as bogus.
+
+
+
+
+2000 Feb 24
+ Jason Merrill <jason@cygnus.com> noticed that gcc did
+ not like gcc -E foo.list, so incorporated his fix so
+ now the Makefile.in makes a link and does gcc -E _tmp.c
+
+2000 Jan 26
+ elena.demikhovsky@intel.com noticed that 3 statements in
+ print_sections.c got warnings from the compiler
+ she was using. Simple casts (provided by her) fixed these.
+
+1999 July 21
+ davea@sgi.com
+ print_sections changed to allow printing
+ of dwarf-ish egcs c++ .eh_frame data
+
+
+1999 June 14
+ Fred Fish fnf@ninemoons.com contributed
+ autoconf'ing of the libdwarf and dwarfdump source.
+
+
+
+1999 June 10
+ ChangeLog started. davea@sgi.com David Anderson
diff --git a/dwarfdump/ChangeLog2007 b/dwarfdump/ChangeLog2007
new file mode 100644
index 0000000..d1230b5
--- /dev/null
+++ b/dwarfdump/ChangeLog2007
@@ -0,0 +1,108 @@
+2007-12-09 DavidAnderson <davea42@earthlink.net>
+ * print_sections.c print_frames.c: Forgot to commit yesterday.
+ yesterday's commit includes renaming _dwarf_fde_section_offset
+ _dwarf_cie_section_offset, _dwarf_print_lines, _dwarf_ld_sort_lines
+ to dwarf_* form while retaining support for the now obsolete
+ _dwarf_* form.
+2007-12-08 DavidAnderson <davea42@earthlink.net>
+ * config.h.in, configure.in: Latest linux libelf.h requires
+ _GNU_SOURCE to get off64_t defined so dwarfdump compiles.
+ Only define _GNU_SOURCE if libelf.h defines off64_t.
+ Regenerated configure.
+ * config.guess, config.sub: Updated to 2.61
+ * acconfig.h: Deleted, removing autoconf complaint.
+2007-10-15 DavidAnderson <davea42@earthlink.net>
+ * print_die.c (clean_up_die_esb): New function
+ cleans up malloc space.
+ * print_reloc.c (clean_up_syms_malloc_data): New function
+ cleans up malloc space.
+ * dwarfdump.c (main): Call new cleanup functions at end.
+ * globals.h: Declare new cleanup functions.
+
+2007-09-04 DavidAnderson <davea42@earthlink.net>
+ * print_die.c (print_attribute): For DWARF4: DW_AT_high_pc:
+ add qualifier to value when the value is an offset from
+ DW_AT_low_pc (thus not itself a address).
+ Update the address of the FSF.
+ * print_frames.h DWARFDUMPCOPYRIGHT print_sections.c
+ print_reloc.c dwarfdump.c tag_tree.c tag_attr.c
+ esb.c esb.h makename.c acconfig.h dwconf.c makename.h
+ dwconf.h globals.h print_frames.c:
+ Update the address of the FSF.
+
+2007-07-03 DavidAnderson <davea42@earthlink.net>
+ * print_sections.c (dump_block): Removed superfluous return byte from
+ printed characters. Removed unused variables.
+ * print_die.c: A little refactoring for clarity.
+ * globals.h: dwarfdump_print_one_locdesc() is now a
+ global-to-dwarfdump function.
+ * print_frames.c: Now (with -v) prints dwarf expression bytes
+ in frame expressions readably.
+2007-07-02 DavidAnderson <davea42@earthlink.net>
+ * dwarfdump.c: Add new -R option for 'generic' register sets.
+ * dwarfdump.1: document -R, add new -x documentation.
+ * dwconf.c: Set up -R configuration. Slight revision of
+ register printing code.
+ * dwconf.h: Interface to register name printing simplified.
+ * print_frames.c: Use the simpler register name interface.
+ * dwarfdump.conf: Add new 'generic' abi for up to 1000 registers.
+
+2007-07-01 DavidAnderson <davea42@earthlink.net>
+ * print_frames.c: For DW_CFA_def_cfa_sf & DW_CFA_def_cfa_offset_sf
+ print a computed data alignment factor.
+2007-06-29 DavidAnderson <davea42@earthlink.net>
+ * dwarfdump.1: Corrected spelling error.
+2007-05-25 DavidAnderson <davea42@earthlink.net>
+ * dwconf.h dwconf.c: Changed field name to
+ cf_named_regs_table_size as old name was less than clear.
+ * dwarfdump.c: Call frame table setup with
+ cf_table_entry_count not cf_named_regs_table_size. The newly
+ renamed field makes it clearer the call was wrong.
+2007-05-04 DavidAnderson <davea42@earthlink.net>
+ * print_die.c: printing of global offset of DIEs
+ with -G is now more in the style of previous output.
+2007-04-18 Chris Quenelle <chris.quenelle@sun.com>
+ * Makefile.in:
+ - use $(srcdir) for files in source directory
+ - support running rules in parallel by
+ - use different tmp file names in different rules.
+ - use more accurate target for dwarf_names.{c,h}
+ * dwarf_names.awk: Enhance script to be able to generate either
+ #define-style headers or enum-style headers
+ * dwarfdump.c: dump most everything by default if no arguments
+ are given to dwarfdump. This seems to be a more useful default
+ than showing nothing at all. Also add a -G option to show
+ the (G)lobal section offset for each die within an a.out. If you
+ think you're seeing data corruption inside a .debug_info
+ section, this is a useful option to have.
+ * print_die.c: Support compressed integer blocks. This is an
+ array (DW_FORM_block) of LEB numbers used as part of a Sun
+ extension, DW_AT_SUN_func_offsets. Also add support for
+ a new dwarf enum DW_ATCF_xxxx. This is used in DW_AT_SUN_cf_kind.
+ Also, fix DW_AT_upper_bound so it can be a constant or a location
+ list. DW_AT_count and DW_AT_data_member_location should also be
+ fixed eventually.
+ * print_sections.c: Changes to support zero-padding in the middle of
+ section data. Change offset labels to be a little more clear.
+ Not sure about the get_str failure.
+ * tag_tree.list: DW_TAG_compile_unit can contain a DW_TAG_namespace
+2007-04-10 David Anderson <davea42@earthlink.net>
+ * print_reloc.c dwarfdump.c print_frames.c: Unified
+ copyright to the SGI form. No copyright change.
+
+2007-04-06 David Anderson <davea42@earthlink.net>
+ * print_die.c (print_die_and_children): Increase static
+ depth of die stack. Notice if it overflows and
+ print error.
+2007-02-23 David Anderson <davea42@earthlink.net>
+ * print_reloc.c: 2 lines added (long) cast in printf
+ and made %3ld instead of %3d to fix compiler warning.
+ * print_frames.c: newline was missing from the output.
+ Thanks to Chris Quenelle for noticing.
+2007-02-20 David Anderson <davea42@earthlink.net>
+ * print_frame.c (print_frame_inst_bytes): Fixed
+ an off by one error (several places)
+ when printing dwarf expressions and added commentary about it.
+ Thanks to Julian Seward for pointing out it was off by one.
+ * dwarfdump.c (print_error): added fflush of stdout, stderr
+ where we are going to exit right away anyway.
diff --git a/dwarfdump/ChangeLog2008 b/dwarfdump/ChangeLog2008
new file mode 100644
index 0000000..24a1ffa
--- /dev/null
+++ b/dwarfdump/ChangeLog2008
@@ -0,0 +1,96 @@
+2008-12-30 David Anderson <davea42@earthlink.net>
+ * tag_attr.list: Mark DW_AT_artificial as sensible on
+ DW_TAG_variable.
+ * dwarfdump.1: Document -N option to print .debug_ranges.
+ * Makefile.in: add new source header files
+ * dwarfdump.c: Implement -N to print .debug_ranges.
+ * print_sections.c: Allow more flexible printing
+ of function names for .debug_frame section.
+ With -N, print .debug_ranges.
+ * print_die.c: Print .debug_ranges details.
+ * print_frames.c: Delete useless comment.
+ * globals.h: Allow re-use of debug_ranges formatting code.
+ * Makefile.in: Make the header dependency list more complete.
+ * makename.h: Comment tweaked.
+2008-12-08 David Anderson <davea42@earthlink.net>
+ * print_die.c: the -M option now also prints the form
+ number (after the form name). And -v prints the DIE
+ abbreviation code, the index into the relevant abbreviation
+ table.
+ * globals.h: Removed unused global variable.
+ * dwarfdump.c: Removed unused global variable.
+ * dwarfdump.1: document -M and the new -v features.
+2008-12-07 David Anderson <davea42@earthlink.net>
+ * print_reloc.c (print_relocinfo): Removed unused local variable.
+2008-11-19 David Anderson <davea42@earthlink.net>
+ * globals.h: Added new boolean to support -M.
+ * dwarfdump.1: Mentioning the -M option.
+ * dwarfdump.c: Implementing -M, which has each attribute line
+ show the name of the form.
+ * print_die.c: Implementing -M option.
+2008-10-12 David Anderson <davea42@earthlink.net>
+ * dwarfdump.conf: Adding power pc register names and table
+ size for use with -x abi=ppc .
+2008-08-13 David Anderson <davea42@earthlink.net>
+ * dwarfdump.1: When no options (just object files) present
+ all sections print, now we say that. Renamed fields
+ in synopsis for readability.
+2008-06-23 David Anderson <davea42@earthlink.net>
+ * print_reloc.c (print_reloc_information_64): Was testing
+ sym_data_entry_count one place where sym_data_64_entry_count
+ should have been tested. Thanks to Carlos Alberto Enciso
+ for noticing.
+2008-06-17 David Anderson <davea42@earthlink.net>
+ * print_die.c: Add to dwarf_formstring failure message.
+ * README: Correct email: the old sgi.com address is no
+ longer correct.
+2008-06-13 David Anderson <davea42@earthlink.net>
+ * dwconf.c: Fix an off-by-one condition where
+ we could index off the end of the cf_regs array in printing
+ a register name.
+2008-04-12 David Anderson <davea42@earthlink.net>
+ * print_reloc.c: Verify stringtab exists and is
+ large enough before indexing into it to get a string
+ in printing relocations.
+ (Providing default name "<no name>" so it's evident from
+ the output that we used a default name string).
+2008-04-09 David Anderson <davea42@earthlink.net>
+ * print_sections.c (get_fde_proc_name): Initialize some
+ local variables at declaration. The function is very slow
+ and needs a replacement.
+ * print_die.c: Fixes a typo in a comment.
+ * dwarfdump.c: Added -n option to suppress function name search
+ when printing FDEs. Current dwarfdump is n-squared at least
+ getting those names, this is a bandage-type-workaround when
+ there are so many FDEs the slowness is painful.
+ * globals.h: Support for -n option.
+ * print_frames.c: Support for -n option.
+2008-04-08 David Anderson <davea42@earthlink.net>
+ * dwarfdump.c: Added -H option for testing
+ (it limits the run length).
+ And the support for -H in printing DIEs.
+ * globals.h: Added extern for -H option declaration.
+ * print_sections.c: Added -H option support to limit frames printing.
+
+2008-04-04 David Anderson <davea42@earthlink.net>
+ * print_die.c (tag_tree_combination, tag_attr_combination):
+ Ensure we do not index off the end of the -k checking arrays.
+ * print_sections.c: Increase the size of a local variable,.
+2008-03-03 David Anderson <davea42@earthlink.net>
+ * dwarfdump.1: Add description of -ka option.
+ * print_frames.h print_sections.c testesb.c print_die.c print_reloc.c
+ dwarfdump.c tag_tree.c tag_attr.c esb.c esb.h makename.c dwconf.c
+ makename.h dwconf.h globals.h print_frames.c: Change tabs
+ to spaces with expand(1).
+2008-03-03 David Anderson <davea42@earthlink.net>
+ * print_die.c: Now check that DW_AT_decl_file
+ and DW_AT_call_file indexes are valid and count instances of the
+ attribute and errors found in it.
+ * dwarfdump.c: With -ka and -ky now check that DW_AT_decl_file
+ and DW_AT_call_file indexes are valid and warn if bad.
+ Thanks to Carlos Alberto Enciso for the suggestion.
+ * globals.h: Declare new fields for the DW_AT_decl_file
+ DW_AT_call_file checks.
+2008-02-26 David Anderson <davea42@earthlink.net>
+ * print_die.c (get_attr_value): Print DW_AT_call_file,
+ DW_AT_call_line, DW_AT_call_column nicely.
diff --git a/dwarfdump/ChangeLog2009 b/dwarfdump/ChangeLog2009
new file mode 100644
index 0000000..9d9a2d5
--- /dev/null
+++ b/dwarfdump/ChangeLog2009
@@ -0,0 +1,280 @@
+2009-12-30 DavidAnderson <davea42@earthlink.net>
+ * configure: Regenerated with autoconf 2.64.
+ * config.guess, config.sub: Delete these, best not
+ to have them.
+2009-11-24 DavidAnderson <davea42@earthlink.net>
+ * tag_common.h: Updated 'standard tag table row' and
+ tag table column maximums now the DWARF4 entries are
+ in the .list files. Removed dos 'CR' characters at line ends.
+ * tag_tree.list, tag_attr.list: Added various
+ DWARF4 entries and added DW_TAG_enumeration_type
+ under DW_TAG_union_type.
+2009-11-17 DavidAnderson <davea42@earthlink.net>
+ * dwarfdump.1: Document the -u option more fully.
+ * print_die.c: Check for both info_flag and
+ cu_name_flag to decide when to print DIEs.
+2009-10-12 DavidAnderson <davea42@earthlink.net>
+ * dwarfdump.c: Updated dwarfdump version string to today.
+2009-09-30 DavidAnderson <davea42@earthlink.net>
+ * dwarfdump.c: Added globals for aranges checking and
+ to print the resulting error count.
+ * print_aranges.c: Added checking that all 3 ways
+ of computing a cu_die_offset from an arange get
+ the same offset (checked with -r -ka).
+ * print_frames.c: DW_CFA_cfa_offset_extended_sf
+ corrected to DW_CFA_offset_extended_sf.
+2009-09-01 DavidAnderson <davea42@earthlink.net>
+ * tag_tree.list: We add
+ DW_TAG_class_type as a valid child of a DW_TAG_union_type.
+2009-08-05 DavidAnderson <davea42@earthlink.net>
+ * gennames.c: Change include from getopt.h to unistd.h
+ so the code is more universally compilable.
+2009-07-24: David Anderson <davea42@earthlink.net>
+ * tag_attr.c: Remove duplicate include of naming.h.
+2009-06-23: David Anderson <davea42@earthlink.net>
+ * strstrnocase.c: Corrected typo in TEST code and
+ added a new test.
+2009-06-22: David Anderson <davea42@earthlink.net>
+ * Makefile.in: switched to personally written
+ string comparison, strstrnocase.c.
+ * stristr.c: deleted.
+ * strstrnocase.c: New code, written by me so no
+ license issues.
+ * print_die.c: Call is_strstrnocase(), the new function.
+ * dwarfdump.1: More fully document -S.
+ * globals.h: Create extern for is_strstrnocase().
+2009-06-18: David Anderson <davea42@earthlink.net>
+ * configure: Regenerated.
+ * Makefile.in: Add stristr.o
+ * stristr.c: public domain source added to dwarfdump
+ * print_die.c: Add code and arguments to support -S.
+ * print_lines.c: print_one_die argument list changed, added
+ the require argument..
+ * dwarfdump.c: Added the -S option.
+
+ * configure.in: Add test to set HAVE_REGEX for the -S option.
+ * dwarfdump.1: Document the -S options.
+ * config.h.in: Set the default HAVE_REGEX
+ * globals.h: Add -S globals, change the print_one_die()
+ prototype to support -S.
+ * print_aranges.c: Alter the print_one_die calls added
+ to support -S.
+2009-06-06: David Anderson <davea42@earthlink.net>
+ * naming.c,naming.h: New files that implement the
+ ellipsis functionality of dwarfdump and defer to
+ libdwarf to get the names of the TAGs, attributes, FORMs, etc.
+ * gennames.c: This file has moved to libdwarf, no longer
+ present in dwarfdump.
+ * esb.h, esb.c: Change certain char* arguments to const char*
+ to avoid compiler warnings.
+ * print_static_vars.c,print_static_funcs.c,
+ print_sections.c,print_strings.c, print_locs.c,
+ print_lines.c, print_pubnames.c,print_ranges.c,
+ print_macros.c,print_types.c,tag_common.c,
+ print_weaknames.c, print_aranges.c: Include
+ changed from dwarf_names.h to naming.h
+ * tag_common.h: Removed the tag_name array, libdwarf
+ provides the TAG, ATTR, etc name strings now.
+ * dwarfdump.c: Updated DWARFDUMP_VERSION string.
+ * tag_tree.c,tag_attr.c: Include changed from dwarf_names.h to
+ naming.h. simplified long complicated lines, remove dbg argument
+ to get_TAG_name.
+ * print_die.c,print_abbrevs.c: Include changed from dwarf_names.h
+ to naming.h.
+ Calls to get_TAG_name (etc) no longer have a dbg argument.
+ * Makefile.in: We no longer build generated file names.c,
+ we build naming.c (hand coded, not generated).
+2009-05-07: David Anderson <davea42@earthlink.net>
+ * dwarfdump.cc: updated DWARF_VERSION string.
+ * Makefile.in: dwarf_names* are now generated by C,
+ so 'clean' now cleans them out.
+2009-05-04: David Anderson <davea42@earthlink.net>
+ * common.h, common.c: Extracted simple utility routines
+ into their own files.
+ * dwarf_names.awk, at_list.awk: deleted. gennames.c replaces these.
+ * tag_common.c, tag_common.h: Removed the simple utility
+ routines from these files to simplify dependencies.
+ * tag_attr.c, tag_tree.c: Include new common.h.
+ * print_frames.c: Adding address_size argument to call.
+ * print_frames.h: Adding new address_size argument to
+ get_string_from_locs() declaration.
+ * print_locs.c: Gets and uses CU-specific address_size.
+ * print_ranges.c: Adding commentary.
+ * print_die.c: adding DIE argument to ensure correct
+ address size used for the CU in question.
+ * Makefile.in: Now handles common.* and gennames.c changes.
+ * gennames.c: New code emitting string 'get name' source.
+ Replaces awk source.
+2009-04-04: David Anderson <davea42@earthlink.net>
+ * Makefile.in: clean up 'clean' and 'distclean'
+ so that distributed files are not cleaned out by 'clean'
+ and all generated files (even those shipped in
+ distribution) are cleaned out by distclean.
+ * dwarfdump.c: Now calls the new
+ libdwarf function dwarf_set_frame_cfa_value() and other
+ such functions to specify all the values libdwarf needs.
+ * dwarfdump.conf: Sets the cfa_reg: value to
+ a new higher value (1436) to avoid conflict with largest
+ known register count.
+ * dwconf.h: Corrected commentary on DW_FRAME_CFA_COL3.
+ * dwconf.c: Now uses DW_FRAME_CFA_COL3 as default for
+ interface 3, rather than a directly typed number.
+ Sets undefined-value and same-value pseudo-register numbers.
+2009-04-03: David Anderson <davea42@earthlink.net>
+ * dwarfdump.1: Amplified -R and -x abi= documentation.
+ * dwarfdump.conf: Added generic500 generic100 abis.
+2009-03-29: David Anderson <davea42@earthlink.net>
+ * print_die.c: Moved print_infos() to here.
+ * dwarfdump.c: Moved print_infos() out of here.
+ * globals.h: Declarations changed to allow moving
+ print_infos().
+ * dwarf_names.awk: Eliminate a pointless space before
+ a newline in the generated code.
+ * print_locs.c: Add -v section offset output to loclist printing
+ of the debug_loc section so the entries can be matched to
+ loclist printing initiated from .debug_info.
+2009-03-24: David Anderson <davea42@earthlink.net>
+ * README: Would be nice if all could use dwarfdump2,
+ not this C dwarfdump.
+ * dwconf.c: Initialize new frame regs configure data and
+ parse it in the .conf file. Fixed old formatting mistakes.
+ * dwconf.h: Add new fields to frame regs configure struct. Make -R
+ be 1200 regs so that -R covers all the currently popular ABIs.
+ * print_die.c, print_lines.c, print_frames.c: Change %# to
+ 0x% so that zero prints with leading 0x consistently.
+ * dwarfdump.c: -R is now 1200 registers. So config function
+ changed and usage message needed update.
+ * dwarfdump.1: Change -R to 1200 and document -C.
+ * dwarfdump.conf: Add same_val_reg: and undefined_val_reg:
+ initial values where needed or interesting.
+ * print_macros.c: Fix old formatting mistake.
+2009-03-23: David Anderson <davea42@earthlink.net>
+ * print_sections.h: New file for print_*.c
+ sources.
+ * dwarfdump.1: Added -C documentation.
+ * Makefile.in: updated 'mandir' so it works with
+ current configure (so now make install properly installs
+ the man page).
+ * print_sections.c: Moved get_fde_proc_name() and related
+ code to print_frames.c, where it is referenced.
+ * dwarfdump.c: No longer turn on info_flag with -f or -F.
+ Moved the Usage strings into a string table and loop through
+ to print them.
+ * globals.h: Removed get_fde_proc_name() declaration.
+ * print_frames.c: Added get_fde_proc_name() here
+ and removed the 'inlined:' from the abstract origin
+ name.
+2009-03-20: David Anderson <davea42@earthlink.net>
+ * print_static_vars.c, print_static_funcs.c, print_strings.c,
+ print_locs.c, print_pubnames.c, print_lines.c, print_ranges.c,
+ print_abbrevs.c, print_macros.c, print_types.c, print_weaknames.c,
+ print_aranges.c: Moved the print_* functions from print_sections.c
+ into individual sourcefiles.
+ * Makefile.in: Now lists the new sourcefiles.
+ * print_sections.c: Deleted code moved to individual sourcefiles.
+ Added code to try to find the name from a DW_AT_abstract_origin
+ DIE when a subprogram DIE itself has no DW_AT_name;
+ * dwarfdump.c: Remove unused local variables. Use DWARFDUMP_VERSION
+ #define to set version string.
+ * tag_tree.c: Fix && || problem with parentheses.
+ * tag_attr.c: Fix && || problem with parentheses.
+ * print_frames.c: Moved the 'print_frames' function itself from
+ print_sections.c to here.
+2009-03-17: David Anderson <davea42@earthlink.net>
+ * globals.h: Created predicate function
+ should_skip_this_cu() predicate function. Eliminating
+ code duplication.
+ * print_frames.c: Fix a hex value output to have a leading
+ 0x as all hex values should (when printed).
+ * print_sections.c: Call should_skip_this_cu(), which
+ replaces duplicate code.
+ Fix the arange print: now the hex value has a leading 0x
+ as all hex values should. get_proc_name() had local
+ variable funcnamefound initialized incorrectly, now is
+ set to 0 as it should be. get_nested_proc_name()
+ now initializes string buffers. get_fde_proc_name()
+ now initializes its string buffer. Surprisingly
+ things worked adequately before in spite of the errors.
+ * dwarfdump.c: Call should_skip_this_cu(). Implementation
+ of that new function is in this source file.
+2009-03-16: David Anderson <davea42@earthlink.net>
+ * print_frames.c:DW_CFA_restore output had a spurious newline.
+ Removed 2 pointless blank lines an initialized 2 local variables.
+ * print_sections.c: Removed a pointless redeclaration of a function
+ in libdwarf.h. check_info_offset_sanity() was missing a
+ return statement in one place, which could lead to spurious
+ extra (and silly) error text.
+2009-03-09: David Anderson <davea42@earthlink.net>
+ * print_die.c: Make a comment easier to understand.
+2009-02-28: David Anderson <davea42@earthlink.net>
+ * Makefile.in: add tmp-*.tmp to the 'clean' rule.
+2009-02-17: David Anderson <davea42@earthlink.net>
+ * print_sections.c,print_die.c,tag_common.c,print_frames.c: C99
+ in-line declarations and // comments are not intended here,
+ this removes a few that were introduced accidentally.
+2009-02-16: David Anderson <davea42@earthlink.net>
+ * Makefile.in: Removed some use of awk and
+ simplified some shell scripting here.
+ renamed temp files, no longer named with
+ underbars, they uniformly start with 'tmp-'.
+ * print_sections.c: Added the new argument required
+ by the updated dwarf_names.c functions argument lists.
+ * tag_tree_ext.list: List 'common extensions'
+ of tag->tag relationships.
+ * tag_attr_ext.list: List 'common extensions'
+ of tag->attr relationships.
+ * print_die.c: New 'common extension' tables used
+ for checking tag->tag and tag->attr relationships
+ unless turned off with -C.
+ * dwarf_names.awk: Removed tabs so generated names.c not so
+ spread out. Added argument to the generated functions so
+ tag_tree.c, tag_attr.c can use these generated functions nicely.
+ * dwarfdump.c: Adding -C option, which exposes
+ some 'common extensions' of dwarf uses as DWARF CHECK
+ (-ka) warnings. By default these extensions not reported
+ as warnings.
+ * tag_tree.c: Now generates base and extensions tables.
+ Code in common with tag_attr.c is in tag_common* files.
+ * tag_attr.c: Now generates base and extensions tables.
+ Code in common with tag_tree.c is in tag_common* files.
+ * tag_common.c, tag_common.h: New files with the common
+ data extracted from tag_tree.c and tag_attr.c
+ * globals.h: global flag added for -C.
+
+2009-02-14: David Anderson <davea42@earthlink.net>
+ * configure.in: Define --enable-nonstandardprintf
+ * config.h.in: new #undef HAVE_NONSTANDARD_PRINTF_64_FORMAT
+ * configure: Regenerated.
+ * config.guess, config.sub: Latest version from GNU.
+ * Makefile.in: Referenced configure variable to avoid
+ irritating message at configure time.
+ * README: document --enable-nonstandardprintf
+ * print_sections.c, print_die.c, print_reloc.c, dwarfdump.c,
+ dwconf.c, print_frames.c: Use libdwarf.h DW_PR_ printf macros
+ for for better portability.
+2009-02-13: David Anderson <davea42@earthlink.net>
+ * print_sections.c: Ensure we are checking line table header
+ correctness whichever line-table-print code is being used.
+ Allow ARM line header table (which has a bug) to be used.
+ * dwarfdump.c: Print lines_result total with checking on.
+ * globals.h: Add lines_result global to count line botches.
+2009-02-11: David Anderson <davea42@earthlink.net>
+ * print_sections.c, print_die.c: DWARF_CHECK_ERROR*
+ macros now get the count struct passed in.
+ * tag_tree.c, tag_attr.c: Add a comment in the output
+ identifying the output as generated code and
+ with the generation date/time inserted.
+ * globals.h: Accept the struct in DWARF_CHECK_ERROR*
+ macros so we can update the error count in the macro.
+2009-01-31: David Anderson <davea42@earthlink.net>
+ * Makefile.in: Remove compilation of _tag_attr_table.c
+ and _tag_tree_table.c as those are #included in
+ print_die.c, not separately compiled.
+ * print_frames.c: A formerly-static function now called
+ from another file, so declare it here.
+ * print_sections.c: Improve the printing of the .debug_loc
+ section.
+ * print_die.c: A couple of errors were missing their error
+ count increment.
+ * tag_attr.list tag_tree.list: Some normal relationships
+ were left out of the tables: fixed now.
diff --git a/dwarfdump/ChangeLog2010 b/dwarfdump/ChangeLog2010
new file mode 100644
index 0000000..e281cae
--- /dev/null
+++ b/dwarfdump/ChangeLog2010
@@ -0,0 +1,105 @@
+2010-09-30 DavidAnderson <davea42@earthlink.net>
+ * dwarfdump.c: Now -a no longer implies -c because
+ the -c option is not guaranteed to work by the DWARF spec,
+ nor is -c really necessary.
+ * README: More tweaks on the 'install' issue.
+2010-09-29 DavidAnderson <davea42@earthlink.net>
+ * README, Makefile.in: Amplified make install instructions.
+2010-09-20 DavidAnderson <da
+ * dwarfdump.1: The -c option is not guaranteed to work.
+ Because .debug_loc can have garbage bytes in areas
+ not referenced by .debug_info.
+2010-06-29 DavidAnderson <davea42@earthlink.net>
+ * print_die.c: If a location form is wrong report
+ an error but continue operating.
+ * dwarfdump.c: Implement print_error_and_continue().
+ Fix mistakes in usage message.
+ * globals.h: Declare print_error_and_continue().
+2010-04-04 DavidAnderson
+ * dwarfdump.c: New version date.
+ * configure: regenerated.
+ * addrmap.c: Added a comment to mention that tdestroy is
+ GNU only, POSIX does not mention a way to delete the
+ tsearch tree. Hence the code does #define USE_GNU 1
+ to expose the tdestroy function prototype.
+2010-04-03 DavidAnderson <davea42@earthlink.net>
+ * print_frames.h: Added new arguments to a function to get better
+ function names printing.
+ * configure.in: Added test for tsearch functions so dwarfdump
+ will still compile if they are not present.
+ See HAVE_TSEARCH macro.
+ * configure: regenerated.
+ * Makefile.in: Now names object for addrmap.c
+ * addrmap.c: New file to map pc address to function names
+ so fde printing gets functions named properly (using tsearch).
+ * addrmap.h: New file to map pc address to function names
+ so fde printing gets functions named properly (using tsearch).
+ * print_lines.c: Correct the calculation of the number
+ of error checks.
+ * dwarfdump.c: Added fdes error check print.
+ * config.h.in: Now handles the HAVE_TSEARCH macro.
+ * globals.h: Added declarations for the fde error check
+ globals.
+ * print_frames.c: Now uses addrmap.h functions to do a
+ better job of printing function names in the frame output.
+2010-03-31 DavidAnderson <davea42@earthlink.net>
+ * dwarfdump.1: Added some text about 'harmless'
+ errors.
+ * dwarfdump.c: Change the size of the harmless error list
+ to 50. Change harmless error reporting to be associated
+ with -k flags.
+ * dwconf.c: Initialize uninitialized fields to satisfy
+ a compiler warning.
+ * globals.h: Declarations added for 'harmless' error
+ reporting.
+ * print_die.c: Added commentary.
+ * print_frames.cc: Change harmless error reporting to be
+ associated with -k flags.
+ * print_aranges.c: Now calls dwarf_get_arange_info_b()
+ allowing proper printing of DWARF4 segment-sensitive
+ aranges. Change harmless error reporting to be
+ associated with -k flags.
+2010-03-28 DavidAnderson <davea42@earthlink.net>
+ * dwarf_globals.h: Added interface to print_any_harmless_errors().
+ * dwarfdump.c: Added print_any_harmless_errors() implementation
+ and we call it just before closing libdwarf.
+ * print_frames.c: Call print_any_harmless_errors after
+ getting cie/fde list.
+ * dwarfdump.conf: Add abi named 'arm' for Arm users.
+ * print_die.c: Initialize a local string pointer to NULL at
+ the point of definition.
+2010-02-14 DavidAnderson <davea42@earthlink.net>
+ * print_die.c: Add newer DW_OP operators, remove
+ bogus test of DW_OP_nop as the highest valid operator.
+ Add table of DW_OPs to simplify testing for zero-operand
+ operators.
+ Revise so that the FORM of all attributes print with -M.
+ Move a local variable declaration to the front of a block
+ to match C 1990 rules.
+ String searches now also match on attribute name.
+ * tag_attr.list: Updated copyright.
+ * dwarfdump.c: Remove a switch FALL THROUGH in the 'g' case.
+ * tag_tree_ext.list, tag_attr_ext.list: Added GNU template
+ parameter tags, attributes. Updated copyright.
+ * tag_tree.list: Added template parameter tags. Added
+ entry for nested classes. Updated copyright.
+ * tag_common.h: Increased STD_TAG_TABLE_COLUMNS and
+ EXT_ATTR_TABLE_COLS.
+2010-01-30 DavidAnderson <davea42@earthlink.net>
+ * print_die.c: Changed the spelling of one
+ 'DW_AT_type offset does not point to type info' error message so
+ one can distinguish which check lead to the message.
+2010-01-26 DavidAnderson <davea42@earthlink.net>
+ * dwarfdump.1, dwconf.c, dwconf.h, dwarfdump.conf: The default
+ frame values in frame
+ output are now generic registers like r0 to r99
+ instead of MIPS register names.
+ For the MIPS register names use '-x abi=mips'.
+ * print_frames.c: Added commentary.
+2010-01-17 DavidAnderson <davea42@earthlink.net>
+ * print_die.c: The special case DW_AT_SUN_func_offsets
+ now prints identically in dwarfdump and dwarfdump2.
+2010-01-03 DavidAnderson <davea42@earthlink.net>
+ * tag_common.c, common.h, common.c: Remove <cr> line
+ terminator characters. Update copyright year.
+ * All other files: Update copyright year.
diff --git a/dwarfdump/DWARFDUMPCOPYRIGHT b/dwarfdump/DWARFDUMPCOPYRIGHT
new file mode 100644
index 0000000..cf465e2
--- /dev/null
+++ b/dwarfdump/DWARFDUMPCOPYRIGHT
@@ -0,0 +1,85 @@
+
+========The dwarfdump copyright=======
+
+The full text of the GPL version 2 is provided in the file GPL.txt.
+
+Nearly all the files in this directory have contained a GPL
+copyright, not an LGPL copyright, for years. The following
+is an example of that copyright as used in the dwarfdump
+source, and is what SGI always intended (in David
+Anderson's opinion) to have present in
+the DWARFDUMPCOPYRIGHT file. (tag_tree.list tag_attr.list
+acconfig.h have long been marked LGPL and therefore the LGPL
+copyright, not GPL, applies to those three files.) This GPL
+copyright text added here to DWARFDUMPCOPYRIGHT Dec 4, 2006
+
+ Copyright (C) 2000,2002,2004,2005 Silicon Graphics, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+The following was the entire content of this file before
+December 24 2006, Being the LGPL text this is in conflict
+with the individual source files and I (David Anderson)
+believe the source file copyright was intended for dwarfdump
+not the LGPL source directly following this note. However the
+3 files tag_tree.list tag_attr.list acconfig.h have long been
+marked LGPL and the following copyright applies to those three.
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
diff --git a/dwarfdump/GPL.txt b/dwarfdump/GPL.txt
new file mode 100644
index 0000000..d511905
--- /dev/null
+++ b/dwarfdump/GPL.txt
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/dwarfdump/Makefile.in b/dwarfdump/Makefile.in
new file mode 100644
index 0000000..19278f3
--- /dev/null
+++ b/dwarfdump/Makefile.in
@@ -0,0 +1,191 @@
+#
+# Makefile for dwarfdump
+# This is made very simple so it should work with
+# any 'make'.
+# The Makefile does assume that libdwarf is at ../libdwarf
+# from the dwarfdump2 source directory.
+#
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = $(exec_prefix)/bin
+libdir = $(exec_prefix)/lib
+mandir = $(exec_prefix)/share/man
+man1dir = $(mandir)/man1
+
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+DATAROOT = @datarootdir@
+SHELL = /bin/sh
+CC = @CC@
+AR = @AR@
+ARFLAGS = @ARFLAGS@
+RM = rm
+RANLIB = @RANLIB@
+DEFS = @DEFS@
+# ../libdwarf gets us to local headers and a libdwarf
+# archive, usually, so we assume it.
+DIRINC = $(srcdir)/../libdwarf
+LIBS = @LIBS@ -L../libdwarf -ldwarf -lelf
+INCLUDES = -I. -I$(srcdir) -I$(srcdir)/../libdwarf
+CFLAGS = $(PREINCS) @CFLAGS@ $(INCLUDES) -DCONFPREFIX=${libdir} $(POSTINCS)
+LDFLAGS = $(PRELIBS) @LDFLAGS@ $(LIBS) $(POSTLIBS)
+
+
+INSTALL = cp
+
+binprefix =
+
+FINALOBJECTS = \
+ addrmap.o \
+ checkutil.o \
+ dwarfdump.o \
+ dwconf.o \
+ esb.o \
+ print_abbrevs.o \
+ print_aranges.o \
+ print_die.o \
+ print_frames.o \
+ print_lines.o \
+ print_locs.o \
+ print_macros.o \
+ print_pubnames.o \
+ print_ranges.o \
+ print_reloc.o \
+ print_sections.o \
+ print_static_funcs.o \
+ print_static_vars.o \
+ print_strings.o \
+ print_types.o \
+ print_weaknames.o \
+ strstrnocase.o \
+ uri.o
+GEN_HFILES = common.o \
+ tmp-tt-table.c \
+ tmp-ta-table.c \
+ tmp-ta-ext-table.c \
+ tmp-tt-ext-table.c
+
+all: dwarfdump
+
+HEADERS = $(srcdir)/checkutil.h \
+ $(srcdir)/common.h \
+ $(srcdir)/dwconf.h \
+ $(srcdir)/esb.h \
+ $(srcdir)/globals.h \
+ $(srcdir)/makename.h \
+ $(srcdir)/print_frames.h \
+ $(srcdir)/uri.h
+
+$(FINALOBJECTS): $(GEN_HFILES) $(HEADERS) $(srcdir)/naming.c
+
+default: $(TARGETS)
+
+dwarfdump: $(FINALOBJECTS) makename.o naming.o common.o
+ $(CC) $(CFLAGS) -o $@ $(FINALOBJECTS) common.o makename.o naming.o $(LDFLAGS)
+
+#tag_common.o: $(srcdir)/tag_common.c $(HEADERS) dwarf_names.h
+# $(CC) $(CFLAGS) -c $(srcdir)/tag_common.c
+makename.o: $(srcdir)/makename.h $(srcdir)/makename.c
+ $(CC) $(CFLAGS) -c $(srcdir)/makename.c
+common.o: $(srcdir)/common.c $(srcdir)/common.h
+ $(CC) $(CFLAGS) -c $(srcdir)/common.c
+gennames: $(srcdir)/gennames.c $(DIRINC)/dwarf.h $(HEADERS) common.o
+ $(CC) $(CFLAGS) $(srcdir)/gennames.c common.o $(LDFLAGS) -o gennames
+naming.o: $(srcdir)/naming.c $(srcdir)/naming.h
+ $(CC) $(CFLAGS) -c $(srcdir)/naming.c
+
+# We need this as naming.o has external references we cannot have
+# in the tree builds.
+trivial_naming.o: $(srcdir)/naming.c
+ $(CC) $(CFLAGS) -DTRIVIAL_NAMING -c $(srcdir)/naming.c -o trivial_naming.o
+
+tag_tree_build: $(srcdir)/tag_tree.c $(DIRINC)/dwarf.h $(HEADERS) tag_common.o makename.o common.o trivial_naming.o
+ $(CC) $(CFLAGS) $(srcdir)/tag_tree.c tag_common.o common.o makename.o trivial_naming.o $(LDFLAGS) -o tag_tree_build
+
+tag_attr_build: $(srcdir)/tag_attr.c $(DIRINC)/dwarf.h $(HEADERS) tag_common.o makename.o common.o trivial_naming.o
+ $(CC) $(CFLAGS) $(srcdir)/tag_attr.c tag_common.o common.o makename.o trivial_naming.o $(LDFLAGS) -o tag_attr_build
+
+tmp-tt-table.c tmp-tt-ext-table.c: $(srcdir)/tag_tree_ext.list $(srcdir)/tag_tree.list tag_tree_build
+ # gcc -E tag_tree.list does not work, so use a .c name
+ -rm -f tmp-t1.c
+ cp $(srcdir)/tag_tree.list tmp-t1.c
+ $(CC) $(CFLAGS) -E tmp-t1.c > ./tmp-tag-tree-build1.tmp
+ ./tag_tree_build -s -i tmp-tag-tree-build1.tmp -o tmp-tt-table.c
+ -rm -f tmp-t4.c
+ cp $(srcdir)/tag_tree_ext.list tmp-t4.c
+ $(CC) $(CFLAGS) -E tmp-t4.c > ./tmp-tag-tree-build4.tmp
+ ./tag_tree_build -e -i tmp-tag-tree-build4.tmp -o tmp-tt-ext-table.c
+
+tmp-ta-table.c tmp-ta-ext-table.c: $(srcdir)/tag_attr_ext.list $(srcdir)/tag_attr.list tag_attr_build
+ # gcc -E tag_attr.list does not work, so use a .c name
+ -rm -f tmp-t2.c
+ cp $(srcdir)/tag_attr.list tmp-t2.c
+ $(CC) $(CFLAGS) -E tmp-t2.c > ./tmp-tag-attr-build2.tmp
+ ./tag_attr_build -s -i tmp-tag-attr-build2.tmp -o tmp-ta-table.c
+ -rm -f tmp-t3.c
+ cp $(srcdir)/tag_attr_ext.list tmp-t3.c
+ $(CC) $(CFLAGS) -E tmp-t3.c > ./tmp-tag-attr-build3.tmp
+ ./tag_attr_build -e -i tmp-tag-attr-build3.tmp -o tmp-ta-ext-table.c
+
+
+# The file dwarf_names.awk generates BOTH dwarf_names.h and dwarf_names.c
+# be careful of the make dependencies here
+dwarf_names.h: gennames $(DIRINC)/dwarf.h
+ rm -f dwarf_names.h dwarf_names.c
+ ./gennames -s -i ../libdwarf -o .
+dwarf_names.c: dwarf_names.h
+
+test: esb.o $(srcdir)/testesb.c
+ $(CC) -o test $(srcdir)/testesb.c esb.o
+ ./test
+ -rm -f ./test
+
+
+# This simply assumes that a default INSTALL (cp) command
+# will work and leave sensible permissions on the resulting files.
+# Some adjustment might be required, see README.
+install: all
+ $(INSTALL) dwarfdump $(bindir)/dwarfdump
+ $(INSTALL) $(srcdir)/dwarfdump.conf $(libdir)/dwarfdump.conf
+ $(INSTALL) $(srcdir)/dwarfdump.1 $(man1dir)/dwarfdump.1
+
+uninstall:
+ -rm -f $(bindir)/dwarfdump
+ -rm -f $(man1dir)/dwarfdump.1
+ -rm -f $(libdir)/dwarfdump.conf
+
+clean:
+ rm -f *.o dwarfdump
+ rm -f _tag_attr_table.c
+ rm -f _tag_attr_ext_table.c
+ rm -f _tag_tree_table.c
+ rm -f _tag_tree_ext_table.c
+ -rm -f tag_attr_build*.tmp
+ -rm -f tag_tree_build*.tmp
+ rm -f tag_tree_build
+ rm -f tag_attr_build
+ -rm -f _*.c _*.h
+ -rm -f tmp-*.c tmp-*.h tmp-*.tmp
+ rm -f gennames
+ rm -f dwarf_names_new.c
+ rm -f dwarf_names_new.h
+ rm -f dwarf_names_enum.h
+ rm -f dwarf_names.h
+ rm -f dwarf_names.c
+
+
+distclean: clean
+ rm -f config.log config.h config.cache config.status
+ rm -rf autom4te.cache
+ rm -rf Makefile
+
+shar:
+ @echo "shar not set up yet"
+dist:
+ @echo "dist not set up yet"
diff --git a/dwarfdump/NEWS b/dwarfdump/NEWS
new file mode 100644
index 0000000..ed4428b
--- /dev/null
+++ b/dwarfdump/NEWS
@@ -0,0 +1,206 @@
+December 13, 2011
+ Now prints missing line table column number as 0 (now
+ matching the DWARF spec), the previous
+ practice of printing -1 was always wrong.
+ And prints the DWARF3/4 new line table fields (when present).
+October 29, 2011
+ Added support for printing .debug_types (type unit) data.
+October 26, 2011
+ Added new features to Makefile.in and documented in README
+ how to build dwarfdump with headers or libraries in
+ non-standard places.
+October 23, 2011
+ By default the various places with string option values
+ and file paths all use URI transformation on input and
+ if the transformation does anything at all dwarfdump reports
+ the input and transformed strings. This makes it easy
+ to deal with strings and expressions and file paths
+ that are difficult to express in a shell (or that getopt
+ mangles). Options -q and -U give you control over this process.
+October 07, 2011
+ The -x abi=mips frame register abi in dwarfdump.conf is now
+ usable with modern MIPS objects as well as old IRIX objects.
+ There are other mips-* frame register setups described
+ in dwarfdump.conf for anyone testing that nothing new has
+ been added that conflicts with old IRIX/MIPS frame generation.
+June 04, 2011
+ Error checking is now distinct from section printing, making
+ error checking (the -k options) much easier to work with on
+ large objects.
+ So compiler-created errors can be found, the error reporting
+ now prints context information.
+March 29, 2011
+ Added many new correctness tests. Changed the format of
+ various items (line data prints in a more compact form, numbers
+ are more uniformly hexadecimal fixed length where that makes sense).
+ All the source files are uniformly indented to a multiple of 4
+ characters and all intent-tabs in the source have been removed.
+ Major logic changes involved changing error-reporting to be
+ more detailed and adding new tests for incorrect DWARF.
+ Now reports error summary by the compiler name, not just overall.
+January 26, 2010
+ Changed the default frame-data register names from MIPS to
+ a generic set of registers.
+ Try '-x abi=mips' to get the traditional old MIPS register
+ naming.
+June 22, 2009
+ Added the -S option to dwarfdump.
+June 10, 2009
+ Moved the gennames.c code to libdwarf.
+May 4, 2009
+ Replaced awk source-generation of certain functions
+ with new gennames.c code.
+ Now we can print an object with an address_size that
+ varies by compilation unit.
+April 4, 2009
+ Corrected aspects of the frame-printing by ensuring we pass
+ all the information libdwarf needs for fully consistent behavior.
+ Three newly defined libdwarf calls calls made to ensure
+ that better behavior (specifically having dwarfdump consistently
+ recognize when registers are the cfa, undefined-value or same-value
+ pseudo registers). Updated dwarfdump.conf to set these same
+ things consistently.
+Mar 22, 2009
+ The -f and -F flags no longer also imply -i (it just
+ did not make sense to tie them (cannot recall why
+ it might have been tied before).
+Mar 20, 2009
+ Moved print_* functions from print_sections.c to individual
+ source files. Hopefully making the code a bit easier
+ to read.
+Feb 16, 2009
+ Added the -C option. It is a sort of 'pedantic' option
+ as it turns on warnings about certain commonly used
+ non-standard tag->tag and tag->attr relationships.
+ Added the tag_attr_ext.list tag_tree_ext.list files which
+ define the 'common use' extensions.
+Feb 14, 2009
+ Added configure option --enable-nonstandardprintf
+ which makes it easy to get printf of Dwarf_Unsigned (etc)
+ types correct even for non-standard compilers.
+December 30, 2008
+ Now we print the .debug_ranges section (with -N)
+ and the data for DW_AT_ranges (with -i).
+December 8, 2008
+ The -M option now causes printing of FORM details.
+ And -v adds details about abbreviation 'indexes' into
+ an abbreviation table (.debug_abbrev)
+ providing more detail for folks debugging or
+ improving their understanding of DWARF data.
+April 9, 2008
+ Added -H <num> to limit the number of compilation-units/FDEs
+ dwarfdump prints in one run. Added -n to eliminate function-name
+ printing in .debug_frame output (with a large-enough debug_info
+ section function-name printing is too slow). The function name
+ printing will be fixed in another release.
+December 8, 2007
+ Had to add an ugly configure conditional as libelf has
+ unconditional use of off64_t in recent libelf.h
+July 3, 2007
+ Now with -v dwarf expression blocks in frame operations
+ are printed expanded out.
+July 2, 2007
+ Added a new abi -x abi=general usable for any cpu with
+ up to 1000 registers.
+May 7, 2007
+ Sun Microsystems contributes new dwarf.h extensions and a new -G option
+ to dwarfdump -i (so one can see the 'global' offset to DIEs).
+ Thanks to Chris Quenelle of Sun.
+April 17, 2006
+ New -x name=<conf file> -x abi=<abiname> and configuration file
+ enable sensible printing of a wide range of .debug_frame eh_frame
+ correctly without recompiling dwarfdump or touching libdwarf.h or
+ dwarf.h.
+March 29, 2005
+ Now handles DWARF3. For non-MIPS objects, the list of register
+ names in print_sections.c is not appropriate, #define
+ DWARFDUMP_TURN_OFF_MIPS_REG_NAMES to turn off the MIPS names.
+December 1, 2005
+ Added new DWARF3 TAGs and ATtributes to the -k lists,
+ clarified the -k reporting, and made the build more robust
+ in the face of errors in the *.list relationship-spec-files.
+
+August 1, 2005
+ Now print_die.c deals with long loclists without a coredump.
+ Added esb.h esb.c (and testesb.c for testing) to encapsulate
+ getting space for possibly-long strings.
+ Now print_die.c uses snprintf() not sprintf (hopefully this
+ will not inconvenience anyone, snprintf() has been available
+ on most systems for years now).
+ Altered print of location lists a little bit - for better appearance.
+
+July 15, 2005
+ Now completely frees all allocated memory. Various
+ routines were not calling dealloc() code and
+ new libdwarf dealloc routines are now used where those
+ are needed.
+
+ Now prints DWARF3 .debug_pubtypes section (with -a or -y).
+ The .debug_pubtypes section and SGI-specific .debug_typenames
+ are equvalent so they are treated alike.
+
+Mar 21, 2005
+ The -f flag now prints only .debug_frame data. The .eh_frame section
+ (GNU exceptions data) now prints with -F (not -a).
+ Printing gcc 3.3 or 3.4 .eh_frame with zR augmentation
+ does not work at this time, so do not use -F
+ to print such an object.
+ The line section print now prints a CU-DIE offset for each such DIEs
+ line information. This makes it much easier to correctly associate
+ -l (or -v -l) output with -v -v -l when debugging a faulty
+ linetable in an executable.
+ With -v -v -l (two -v) the output of line info continues to be a
+ completely different format than zero or one -v, the two-v
+ form showing the detailed line table opcodes.
+ With g++ 3.3.3 one sees bad line addresses at times as the
+ DW_LNE_set_address address for header files do not always
+ get their relocations applied. I am told this is fixed in 3.4.x.
+
+
+Mar 18, 2005
+ In correcting printing of macro information the format
+ of the macro (-m) output has changed substantially.
+ Much more complete now. Still could use enhancement.
+
+Oct 28, 2004
+ Updated contact address in copyright: SGI moved 1/4 mile
+ to a new address: 1500 Crittenden Lane.
+
+Oct 02, 2003
+ Now fully supports .debug_loc section.
+
+June 14, 2001
+ Now calling a new function dwarf_get_arange_cu_header_offset()
+ in libdwarf and printing the returned cu header offset for
+ aranges entries. Making it easier to track down internal
+ errors in the dwarf2 data. Also added small other
+ consistency checks, printing a message and exit()ing on
+ error.
+
+April 14, 2000
+ The libdwarf copyright has changed to
+ version 2.1 of the GNU Lesser General Public License.
+ Anyone holding a version of libdwarf that was published
+ before this new copyright
+ is allowed to use
+ the copyright published in that earlier libdwarf source
+ on the earlier source
+ or to use
+ this new copyright on the earlier source,
+ at their option.
+
+July 21, 1999
+ Added gnu extensions to the frame information printer
+ and handling for egcs eh_frame printing.
+ libdwarf changes mean this now can print little-endian
+ object dwarf on a big-endian system and vice-versa.
+
+December, 1998
+ added dwarfdump to the dwarf public source distribution.
+
+June, 1994
+ libdwarf consumer interface changed completely so updated to match.
+
+May, 1993
+ Initial version of dwarfdump for dwarf version 2
+ written at sgi.
diff --git a/dwarfdump/README b/dwarfdump/README
new file mode 100644
index 0000000..515e2b6
--- /dev/null
+++ b/dwarfdump/README
@@ -0,0 +1,82 @@
+I would prefer you try using ../dwarfdump2, not this source.
+If you must use this for some reason, could you let me know why?
+Thanks.
+
+To build dwarfdump, first build libdwarf in the neighboring
+directory then type
+ ./configure
+ make
+
+Installation is a bit primitive.
+ sudo make install
+may or may not work.
+Some or all of the following might be required on Unix or Linux or MacOS:
+ sudo mkdir -p /usr/local/share/man/man1/
+ sudo mkdir -p /usr/local/lib
+ sudo mkdir -p /usr/local/bin
+Then retry the 'sudo make install' and (if necessary) try
+ sudo chmod a+x /usr/local/bin/dwarfdump
+ sudo chmod a+r /usr/local/share/man/man1/dwarfdump.1
+ sudo chmod a+r /usr/local/lib/dwarfdump.conf
+You don't really need the dwarfdump.1 man page,
+but you might as well have it. If the man page is not visible
+with 'man dwarfdump' try 'man manpath' for hints.
+
+If you don't need others using dwarfdump on your computer,
+just
+ cp dwarfdump $HOME/bin/dwarfdump
+(by convention many people put personal executables in $HOME/bin
+and fix up $PATH to refer there) which suffices as 'installation'.
+Also
+ cp dwarfdump.conf $HOME
+
+To use dwarf or libdwarf, you may want to install dwarf.h
+and libdwarf.h somewhere convenient.
+You can just copy those two headers to /usr/local/include by hand
+(or anywhere, really, that you have permission to copy to)
+(you may need to use -I/usr/local/include on compile lines
+to reference them there, but see below on configure and make).
+
+Notice that dwarf_names.c and dwarf_names.h are supplied by
+the release though the Makefile can and may rebuild them.
+Some users find it difficult to get a reliable awk(1) program,
+so for them these prebuilt versions may be useful.
+
+If your headers or libelf/libdwarf are not in the expected places,
+use the make command line to add flags and include directories.
+For example
+ ./configure
+ PREINCS="-I /usr/local/include" POSTINCS="-I /home/x/include" make
+PREINCS content is inserted before CFLAGS as make(1) is running.
+POSTINCS content is added after the CFLAGS value.
+
+To set LDFLAGS,
+do so at configure time, for example:
+ ./configure LDFLAGS="-L /some/dir"
+And/or use PRELIBS and/or POSTLIBS at 'make' time similar to the use
+of PREINCS and POSTINCS.
+
+If the libdwarf directory
+has both libdwarf.so and libdwarf.a, the libdwarf.so
+will be picked up and
+ "./tag_tree_build: error while loading shared libraries:
+ libdwarf.so: cannot open shared object file:
+ No such file or directory"
+will probably result.
+Either: remove libdwarf.so and rebuild or set
+the environment variable LD_LIBRARY_PATH to the directory
+containing the .so or use LDFLAGS to set rpath (see just below).
+It is perhaps simpler to ensure that the libdwarf directory
+only has an archive, not a shared-library.
+But sometimes one wants a shared library.
+In that case
+one can set ld's -rpath on the gcc command line like this:
+ LDFLAGS="-Wl,-rpath=/some/path/libdir"
+so the shared library can be found at run time automatically.
+
+The same problem may arise with libelf, and the same approach
+will solve the problem.
+
+
+
+David Anderson. davea42 at earthlink dot net.
diff --git a/dwarfdump/addrmap.c b/dwarfdump/addrmap.c
new file mode 100644
index 0000000..fb7ba79
--- /dev/null
+++ b/dwarfdump/addrmap.c
@@ -0,0 +1,149 @@
+/*
+ Copyright 2010-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+*/
+
+/* If memory full we do not exit, we just keep going as if
+ all were well. */
+
+#include "globals.h"
+#include <stdio.h>
+#include "addrmap.h"
+#ifndef HAVE_TSEARCH
+struct Addr_Map_Entry * addr_map_insert( Dwarf_Unsigned addr,
+ char *name,void **tree1)
+{ return 0; }
+struct Addr_Map_Entry * addr_map_find(Dwarf_Unsigned addr,void **tree1)
+{ return 0; }
+void addr_map_destroy(void *map)
+{ return;}
+
+
+
+#else /* HAVE_TSEARCH */
+#define __USE_GNU 1
+#include <search.h>
+
+char firststringcontent[100];
+char *firststring = 0;
+struct Addr_Map_Entry *firstaddr = 0;
+
+static struct Addr_Map_Entry *
+addr_map_create_entry(Dwarf_Unsigned k,char *name)
+{
+ struct Addr_Map_Entry *mp =
+ (struct Addr_Map_Entry *)malloc(sizeof(struct Addr_Map_Entry));
+ if(!mp) {
+ return 0;
+ }
+ mp->mp_key = k;
+ if(name) {
+ mp->mp_name = strdup(name);
+ } else {
+ mp->mp_name = 0;
+ }
+ return mp;
+}
+static void
+addr_map_free_func(void *mx)
+{
+ struct Addr_Map_Entry *m = mx;
+ if(!m) {
+ return;
+ }
+ free(m->mp_name);
+ m->mp_name = 0;
+ free(m);
+ return;
+}
+
+static void
+DUMPFIRST(int line)
+{
+ if(!firststring) {
+ return;
+ }
+}
+
+static int
+addr_map_compare_func(const void *l, const void *r)
+{
+ const struct Addr_Map_Entry *ml = l;
+ const struct Addr_Map_Entry *mr = r;
+ if(ml->mp_key < mr->mp_key) {
+ return -1;
+ }
+ if(ml->mp_key > mr->mp_key) {
+ return 1;
+ }
+ return 0;
+}
+struct Addr_Map_Entry *
+addr_map_insert( Dwarf_Unsigned addr,char *name,void **tree1)
+{
+ void *retval = 0;
+ struct Addr_Map_Entry *re = 0;
+ struct Addr_Map_Entry *e;
+ e = addr_map_create_entry(addr,name);
+ DUMPFIRST(__LINE__);
+ /* tsearch records e's contents unless e
+ is already present . We must not free it till
+ destroy time if it got added to tree1. */
+ retval = tsearch(e,tree1, addr_map_compare_func);
+ if(retval) {
+ re = *(struct Addr_Map_Entry **)retval;
+ if ( re != e) {
+ /* We returned an existing record, e not needed. */
+ addr_map_free_func(e);
+ } else {
+ /* Record e got added to tree1, do not free record e. */
+ }
+ }
+ return re;
+}
+struct Addr_Map_Entry *
+addr_map_find(Dwarf_Unsigned addr,void **tree1)
+{
+ void *retval = 0;
+ struct Addr_Map_Entry *re = 0;
+ struct Addr_Map_Entry *e = 0;
+
+ e = addr_map_create_entry(addr,NULL);
+ DUMPFIRST(__LINE__);
+ retval = tfind(e,tree1, addr_map_compare_func);
+ if(retval) {
+ re = *(struct Addr_Map_Entry **)retval;
+ }
+ /* The one we created here must be deleted, it is dead.
+ We look at the returned one instead. */
+ addr_map_free_func(e);
+ return re;
+}
+
+void
+addr_map_destroy(void *map)
+{
+ /* tdestroy is not part of Posix, it is a GNU libc function. */
+ tdestroy(map,addr_map_free_func);
+}
+
+#endif /* HAVE_TSEARCH */
diff --git a/dwarfdump/addrmap.h b/dwarfdump/addrmap.h
new file mode 100644
index 0000000..a7b26df
--- /dev/null
+++ b/dwarfdump/addrmap.h
@@ -0,0 +1,33 @@
+/*
+ Copyright 2010 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+*/
+
+struct Addr_Map_Entry {
+ Dwarf_Unsigned mp_key;
+ char * mp_name;
+};
+
+struct Addr_Map_Entry * addr_map_insert(Dwarf_Unsigned addr,
+ char *name, void **map);
+struct Addr_Map_Entry * addr_map_find(Dwarf_Unsigned addr, void **map);
+void addr_map_destroy(void *map);
diff --git a/dwarfdump/checkutil.c b/dwarfdump/checkutil.c
new file mode 100644
index 0000000..6ba756c
--- /dev/null
+++ b/dwarfdump/checkutil.c
@@ -0,0 +1,565 @@
+/*
+ Copyright (C) 2011 SN Systems Ltd. All Rights Reserved.
+ Portions Copyright (C) 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+*/
+/*
+
+ These simple list-processing functions are in support
+ of checking DWARF for compiler-errors of various sorts.
+
+
+*/
+
+#include "globals.h"
+#include <assert.h>
+
+/* Private function */
+static void DumpFullBucketGroup(Bucket_Group *pBucketGroup);
+static int FindDataIndexInBucket(Bucket_Group *pBucketGroup,
+ Bucket_Data *pBucketData);
+static void PrintBucketData(Bucket_Group *pBucketGroup,
+ Bucket_Data *pBucketData);
+static void ProcessBucketGroup(Bucket_Group *pBucketGroup,
+ void (*pFunction)(Bucket_Group *pBucketGroup,Bucket_Data *pBucketData));
+
+Bucket_Group *
+AllocateBucketGroup(int kind)
+{
+ Bucket_Group *pBucketGroup = (Bucket_Group *)calloc(1,sizeof(Bucket_Group));
+ pBucketGroup->kind = kind;
+ return pBucketGroup;
+}
+
+void
+ReleaseBucketGroup(Bucket_Group *pBucketGroup)
+{
+ Bucket *pBucket = 0;
+ Bucket *pNext = 0;
+
+ assert(pBucketGroup);
+ for (pBucket = pBucketGroup->pHead; pBucket; /*pBucket = pBucket->pNext*/) {
+ pNext = pBucket->pNext;
+ free(pBucket);
+ pBucket = pNext;
+ }
+ pBucketGroup->pHead = NULL;
+ pBucketGroup->pTail = NULL;
+ free(pBucketGroup);
+}
+
+void
+ResetBucketGroup(Bucket_Group *pBucketGroup)
+{
+ Bucket *pBucket = 0;
+
+ assert(pBucketGroup);
+ for (pBucket = pBucketGroup->pHead; pBucket; pBucket = pBucket->pNext) {
+ pBucket->nEntries = 0;
+ }
+ ResetSentinelBucketGroup(pBucketGroup);
+}
+
+/* Reset sentinels in a Bucket Group. */
+void
+ResetSentinelBucketGroup(Bucket_Group *pBucketGroup)
+{
+ /* Sanity checks */
+ assert(pBucketGroup);
+ pBucketGroup->pFirst = NULL;
+ pBucketGroup->pLast = NULL;
+}
+
+void PrintBucketGroup(Bucket_Group *pBucketGroup,Dwarf_Bool bFull)
+{
+ assert(pBucketGroup);
+ if (bFull) {
+ DumpFullBucketGroup(pBucketGroup);
+ } else {
+ if (pBucketGroup->pFirst && pBucketGroup->pLast) {
+ printf("\nBegin Traversing, First = 0x%08" DW_PR_DUx
+ ", Last = 0x%08" DW_PR_DUx "\n",
+ pBucketGroup->pFirst->key,pBucketGroup->pLast->key);
+ ProcessBucketGroup(pBucketGroup,PrintBucketData);
+ }
+ }
+}
+
+static void
+PrintBucketData(Bucket_Group *pBucketGroup,Bucket_Data *pBucketData)
+{
+ int nCount = 0;
+ assert(pBucketGroup);
+ assert(pBucketData);
+
+ nCount = FindDataIndexInBucket(pBucketGroup,pBucketData);
+ printf("[%06d] Key = 0x%08" DW_PR_DUx ", Base = 0x%08" DW_PR_DUx
+ ", Low = 0x%08" DW_PR_DUx ", High = 0x%08" DW_PR_DUx
+ ", Flag = %d, Name = '%s'\n",
+ ++nCount,
+ pBucketData->key,
+ pBucketData->base,
+ pBucketData->low,
+ pBucketData->high,
+ pBucketData->bFlag,
+ pBucketData->name);
+}
+
+static void
+DumpFullBucketGroup(Bucket_Group *pBucketGroup)
+{
+ int nBucketNo = 1;
+ int nIndex = 0;
+ int nCount = 0;
+ Bucket *pBucket = 0;
+ Bucket_Data *pBucketData = 0;
+
+ assert(pBucketGroup);
+ for (pBucket = pBucketGroup->pHead; pBucket && pBucket->nEntries;
+ pBucket = pBucket->pNext) {
+
+ printf("\nLowPC & HighPC records for bucket %d, at 0x%08lx\n",
+ nBucketNo++,(unsigned long)pBucket);
+ for (nIndex = 0; nIndex < pBucket->nEntries; ++nIndex) {
+ pBucketData = &pBucket->Entries[nIndex];
+ printf("[%06d] Key = 0x%08" DW_PR_DUx ", Base = 0x%08" DW_PR_DUx
+ ", Low = 0x%08" DW_PR_DUx ", High = 0x%08" DW_PR_DUx
+ ", Flag = %d, Name = '%s'\n",
+ ++nCount,
+ pBucketData->key,
+ pBucketData->base,
+ pBucketData->low,
+ pBucketData->high,
+ pBucketData->bFlag,
+ pBucketData->name);
+ }
+ }
+}
+
+/* Insert entry into Bucket Group.
+ We make no check for duplicate information. */
+void
+AddEntryIntoBucketGroup(Bucket_Group *pBucketGroup,
+ Dwarf_Addr key,Dwarf_Addr base,
+ Dwarf_Addr low,Dwarf_Addr high,
+ const char *name,
+ Dwarf_Bool bFlag)
+{
+ Bucket *pBucket = 0;
+ Bucket_Data data;
+
+ data.bFlag = bFlag;
+ data.name = name;
+ data.key = key;
+ data.base = base;
+ data.low = low;
+ data.high = high;
+
+ assert(pBucketGroup);
+ if (!pBucketGroup->pHead) {
+ /* Allocate first bucket */
+ pBucket = (Bucket *)calloc(1,sizeof(Bucket));
+ pBucketGroup->pHead = pBucket;
+ pBucketGroup->pTail = pBucket;
+ pBucket->nEntries = 1;
+ pBucket->Entries[0] = data;
+ return;
+ }
+
+ pBucket = pBucketGroup->pTail;
+
+ /* Check if we have a previous allocated set of
+ buckets (have been cleared */
+ if (pBucket->nEntries) {
+ if (pBucket->nEntries < BUCKET_SIZE) {
+ pBucket->Entries[pBucket->nEntries++] = data;
+ } else {
+ /* Allocate new bucket */
+ pBucket = (Bucket *)calloc(1,sizeof(Bucket));
+ pBucketGroup->pTail->pNext = pBucket;
+ pBucketGroup->pTail = pBucket;
+ pBucket->nEntries = 1;
+ pBucket->Entries[0] = data;
+ }
+ } else {
+ /* We have an allocated bucket with zero entries; search for the
+ first available bucket to be used as the current
+ insertion point */
+ for (pBucket = pBucketGroup->pHead; pBucket;
+ pBucket = pBucket->pNext) {
+
+ if (pBucket->nEntries < BUCKET_SIZE) {
+ pBucket->Entries[pBucket->nEntries++] = data;
+ break;
+ }
+ }
+ }
+}
+
+/* For Groups where entries are individually deleted, this does
+ that work. */
+Dwarf_Bool
+DeleteKeyInBucketGroup(Bucket_Group *pBucketGroup,Dwarf_Addr key)
+{
+ int nIndex = 0;
+ Bucket *pBucket = 0;
+ Bucket_Data *pBucketData = 0;
+
+ /* Sanity checks */
+ assert(pBucketGroup);
+
+ /* For now do a linear search */
+ for (pBucket = pBucketGroup->pHead; pBucket && pBucket->nEntries;
+ pBucket = pBucket->pNext) {
+
+ for (nIndex = 0; nIndex < pBucket->nEntries; ++nIndex) {
+ pBucketData = &pBucket->Entries[nIndex];
+ if (pBucketData->key == key) {
+ Bucket_Data data = {FALSE,NULL,0,0,0,0};
+ int nStart;
+ for (nStart = nIndex + 1; nStart < pBucket->nEntries;
+ ++nStart) {
+
+ pBucket->Entries[nIndex] = pBucket->Entries[nStart];
+ ++nIndex;
+ }
+ pBucket->Entries[nIndex] = data;
+ --pBucket->nEntries;
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/* Search to see if the address is in the range between
+ low and high addresses in some Bucked Data record.
+ This matches == if high is exact match (which usually means
+ one-past-true-high). */
+Dwarf_Bool
+FindAddressInBucketGroup(Bucket_Group *pBucketGroup,Dwarf_Addr address)
+{
+ int nIndex = 0;
+ Bucket *pBucket = 0;
+ Bucket_Data *pBucketData = 0;
+
+ assert(pBucketGroup);
+ /* For now do a linear search */
+ for (pBucket = pBucketGroup->pHead; pBucket && pBucket->nEntries;
+ pBucket = pBucket->pNext) {
+
+ for (nIndex = 0; nIndex < pBucket->nEntries; ++nIndex) {
+ pBucketData = &pBucket->Entries[nIndex];
+ if (address >= pBucketData->low &&
+ address <= pBucketData->high) {
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/* Search an entry (Bucket Data) in the Bucket Set */
+Bucket_Data *FindDataInBucketGroup(Bucket_Group *pBucketGroup,Dwarf_Addr key)
+{
+ int mid = 0;
+ int low = 0;
+ int high = 0;
+ Bucket *pBucket = 0;
+ Bucket_Data *pBucketData = 0;
+
+ assert(pBucketGroup);
+
+ for (pBucket = pBucketGroup->pHead; pBucket; pBucket = pBucket->pNext) {
+ /* Get lower and upper references */
+ if (pBucket->nEntries) {
+ low = 0;
+ high = pBucket->nEntries;
+ while (low < high) {
+ mid = low + (high - low) / 2;
+ if (pBucket->Entries[mid].key < key) {
+ low = mid + 1;
+ } else {
+ high = mid;
+ }
+ }
+ if ((low < pBucket->nEntries) &&
+ (pBucket->Entries[low].key == key)) {
+
+ pBucketData = &pBucket->Entries[low];
+ /* Update sentinels to allow traversing the table */
+ if (!pBucketGroup->pFirst) {
+ pBucketGroup->pFirst = pBucketData;
+ }
+ pBucketGroup->pLast = pBucketData;
+ return pBucketData;
+ }
+ }
+ }
+ return (Bucket_Data *)NULL;
+}
+
+/* Find the Bucket that contains a given Bucket Data
+ and return its local index. Else return -1. */
+static int
+FindDataIndexInBucket(Bucket_Group *pBucketGroup,Bucket_Data *pBucketData)
+{
+ Bucket *pBucket = 0;
+ Bucket_Data *pLower = 0;
+ Bucket_Data *pUpper = 0;
+
+ /* Sanity checks */
+ assert(pBucketGroup);
+ assert(pBucketData);
+
+ /* Use sentinels if any. */
+ if (pBucketGroup->pFirst && pBucketGroup->pLast &&
+ pBucketData >= pBucketGroup->pFirst &&
+ pBucketData <= pBucketGroup->pLast) {
+
+ /* Find bucket that contains the first sentinel */
+ for (pBucket = pBucketGroup->pHead; pBucket && pBucket->nEntries;
+ pBucket = pBucket->pNext) {
+
+ pLower = &pBucket->Entries[0];
+ pUpper = &pBucket->Entries[pBucket->nEntries - 1];
+
+ /* Check if the first sentinel is in this bucket. */
+ if (pBucketGroup->pFirst >= pLower &&
+ pBucketGroup->pFirst <= pUpper) {
+ /* We have found the bucket, return the index. */
+ return pBucketData - pBucketGroup->pFirst;
+ }
+ }
+ } else {
+ /* Find bucket that contains the entry */
+ for (pBucket = pBucketGroup->pHead; pBucket && pBucket->nEntries;
+ pBucket = pBucket->pNext) {
+
+ pLower = &pBucket->Entries[0];
+ pUpper = &pBucket->Entries[pBucket->nEntries - 1];
+
+ /* Check if the first sentinel is in this bucket */
+ if (pBucketData >= pLower && pBucketData <= pUpper) {
+ /* We have found the bucket, return the index */
+ return pBucketData - pLower;
+ }
+ }
+ }
+ /* Invalid data; just return index indicating not-found */
+ return -1;
+}
+
+/* Search an entry (Bucket Data) in the Bucket Group.
+ The key is an offset, a DIE offset
+ within Visited info. */
+Bucket_Data *FindKeyInBucketGroup(Bucket_Group *pBucketGroup,Dwarf_Addr key)
+{
+ int nIndex = 0;
+ Bucket *pBucket = 0;
+ Bucket_Data *pBucketData = 0;
+
+ /* Sanity checks */
+ assert(pBucketGroup);
+
+ /* For now do a linear search */
+ for (pBucket = pBucketGroup->pHead; pBucket && pBucket->nEntries;
+ pBucket = pBucket->pNext) {
+ for (nIndex = 0; nIndex < pBucket->nEntries; ++nIndex) {
+ pBucketData = &pBucket->Entries[nIndex];
+ if (pBucketData->key == key) {
+ return pBucketData;
+ }
+ }
+ }
+ return (Bucket_Data *)NULL;
+}
+
+/* Search an entry (Bucket Data) in the Bucket Set by name.
+ Used to find link-once section names. */
+Bucket_Data *
+FindNameInBucketGroup(Bucket_Group *pBucketGroup,char *name)
+{
+ int nIndex = 0;
+ Bucket *pBucket = 0;
+ Bucket_Data *pBucketData = 0;
+
+ assert(pBucketGroup);
+ /* For now do a linear search. */
+ for (pBucket = pBucketGroup->pHead; pBucket && pBucket->nEntries;
+ pBucket = pBucket->pNext) {
+ for (nIndex = 0; nIndex < pBucket->nEntries; ++nIndex) {
+ pBucketData = &pBucket->Entries[nIndex];
+ if (!strcmp(pBucketData->name,name)) {
+ return pBucketData;
+ }
+ }
+ }
+ return (Bucket_Data *)NULL;
+}
+
+/* Check if an address valid or not. That is,
+ check if it is in the lower -> upper range of a bucket.
+ It checks <= and >= so the lower end
+ and one-past on the upper end matches.
+*/
+Dwarf_Bool
+IsValidInBucketGroup(Bucket_Group *pBucketGroup,Dwarf_Addr address)
+{
+ Bucket *pBucket = 0;
+ Bucket_Data *pBucketData = 0;
+ int nIndex = 0;
+
+ assert(pBucketGroup);
+ /* Check the address is within the allowed limits */
+ if (address >= pBucketGroup->lower && address <= pBucketGroup->upper) {
+ for (pBucket = pBucketGroup->pHead; pBucket && pBucket->nEntries;
+ pBucket = pBucket->pNext) {
+
+ for (nIndex = 0; nIndex < pBucket->nEntries; ++nIndex) {
+ pBucketData = &pBucket->Entries[nIndex];
+ if (address >= pBucketData->low &&
+ address <= pBucketData->high) {
+ return TRUE;
+ }
+ }
+ }
+ }
+ return FALSE;
+}
+
+/* Reset limits for values in the Bucket Set */
+void
+ResetLimitsBucketSet(Bucket_Group *pBucketGroup)
+{
+ assert(pBucketGroup);
+ pBucketGroup->lower = 0;
+ pBucketGroup->upper = 0;
+}
+
+/* Limits are set only for ranges, so only in pRangesInfo. */
+void
+SetLimitsBucketGroup(Bucket_Group *pBucketGroup,
+ Dwarf_Addr lower,Dwarf_Addr upper)
+{
+ assert(pBucketGroup);
+ if (lower < upper) {
+ pBucketGroup->lower = lower;
+ pBucketGroup->upper = upper;
+ }
+}
+
+/* Traverse Bucket Set and execute a supplied function */
+static void
+ProcessBucketGroup(Bucket_Group *pBucketGroup,
+ void (*pFunction)(Bucket_Group *pBucketGroup,Bucket_Data *pBucketData))
+{
+ int nIndex = 0;
+ int nStart = 0;
+ Bucket *pBucket = 0;
+ Bucket_Data *pBucketData = 0;
+ Bucket_Data *pLower = 0;
+ Bucket_Data *pUpper = 0;
+ Dwarf_Bool bFound = FALSE;
+
+ /* Sanity checks */
+ assert(pBucketGroup);
+
+ /* No sentinels present; do nothing */
+ if (!pBucketGroup->pFirst || !pBucketGroup->pLast) {
+ return;
+ }
+
+ /* Find bucket that contains the first sentinel */
+ for (pBucket = pBucketGroup->pHead; pBucket && pBucket->nEntries;
+ pBucket = pBucket->pNext) {
+
+ pLower = &pBucket->Entries[0];
+ pUpper = &pBucket->Entries[pBucket->nEntries - 1];
+
+ /* Check if the first sentinel is in this bucket */
+ if (pBucketGroup->pFirst >= pLower && pBucketGroup->pFirst <= pUpper) {
+ /* Low sentinel is in this bucket */
+ bFound = TRUE;
+ break;
+ }
+ }
+
+ /* Invalid sentinel; do nothing */
+ if (!bFound) {
+ return;
+ }
+
+ /* Calculate index for first sentinel */
+ nStart = pBucketGroup->pFirst - pLower;
+
+ /* Start traversing from found bucket */
+ for (; pBucket && pBucket->nEntries; pBucket = pBucket->pNext) {
+ for (nIndex = nStart; nIndex < pBucket->nEntries; ++nIndex) {
+ pBucketData = &pBucket->Entries[nIndex];
+ if (pBucketData > pBucketGroup->pLast) {
+ return;
+ }
+ /* Call the user supplied function */
+ if (pFunction) {
+ pFunction(pBucketGroup,pBucketData);
+ }
+ }
+ /* For next bucket start with first entry */
+ nStart = 0;
+ }
+}
+
+/* Check if a given (lopc,hipc) are valid for a linkonce.
+ We pass in the linkonce (instead of
+ referencing the global pLinkonceInfo) as that means
+ searches for pLinkonceInfo find all the uses,
+ making understanding of the code a tiny bit easier.
+ The section name created is supposed to be the appropriate
+ linkonce section name.
+*/
+Dwarf_Bool IsValidInLinkonce(Bucket_Group *pLo,
+ const char *name,Dwarf_Addr lopc,Dwarf_Addr hipc)
+{
+#define SECTION_NAME_LEN 2048 /* Guessing a sensible length */
+ static char section_name[SECTION_NAME_LEN];
+ Bucket_Data *pBucketData = 0;
+ /* Since text is quite uniformly just this name, no need to get it
+ from elsewhere, though it will not work for non-elf. */
+ const char *lo_text = ".text";
+
+ /* Build the name that represents the linkonce section (.text).
+ This is not defined in DWARF so not correct for all
+ compilers. */
+ snprintf(section_name,sizeof(section_name),"%s%s",lo_text,name);
+
+ pBucketData = FindNameInBucketGroup(pLo,section_name);
+ if (pBucketData) {
+ if (lopc >= pBucketData->low && lopc <= pBucketData->high) {
+ if (hipc >= pBucketData->low && hipc <= pBucketData->high) {
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
diff --git a/dwarfdump/checkutil.h b/dwarfdump/checkutil.h
new file mode 100644
index 0000000..d922b98
--- /dev/null
+++ b/dwarfdump/checkutil.h
@@ -0,0 +1,98 @@
+/*
+ Copyright (C) 2011 SN Systems Ltd. All Rights Reserved.
+ Portions Copyright (C) 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+*/
+
+#ifndef CHECKUTIL_H
+#define CHECKUTIL_H
+
+/* Map information.
+ Depending on the specific functions used various
+ fields here are either used or ignored.
+
+*/
+typedef struct {
+ Dwarf_Bool bFlag; /* General flag */
+ const char *name; /* Generic name */
+ Dwarf_Addr key; /* Used for binary search, the key
+ is either a pc address or a DIE offset
+ depending on which bucket table is in use. */
+ Dwarf_Addr base; /* Used for base address */
+ Dwarf_Addr low; /* Used for Low PC */
+ Dwarf_Addr high; /* Used for High PC */
+} Bucket_Data;
+
+/* This groups Bucket_Data records into
+ a 'bucket' so that a single malloc creates
+ BUCKET_SIZE entries. The intent is to reduce
+ overhead (as compared to having next/previous
+ pointers in each Bucket_Data and mallocing
+ each Bucket_Data individually.
+*/
+
+#define BUCKET_SIZE 2040
+typedef struct bucket {
+ int nEntries;
+ Bucket_Data Entries[BUCKET_SIZE];
+ struct bucket *pNext;
+} Bucket;
+
+/* This Forms the head record of a list of Buckets.
+*/
+typedef struct {
+ int kind; /* Kind of bucket */
+ Dwarf_Addr lower; /* Lower value for data */
+ Dwarf_Addr upper; /* Upper value for data */
+ Bucket_Data *pFirst; /* First sentinel */
+ Bucket_Data *pLast; /* Last sentinel */
+ Bucket *pHead; /* First bucket in set */
+ Bucket *pTail; /* Last bucket in set */
+} Bucket_Group;
+
+Bucket_Group *AllocateBucketGroup(int kind);
+void ReleaseBucketGroup(Bucket_Group *pBucketGroup);
+void ResetBucketGroup(Bucket_Group *pBucketGroup);
+void ResetSentinelBucketGroup(Bucket_Group *pBucketGroup);
+
+void PrintBucketGroup(Bucket_Group *pBucketGroup,Dwarf_Bool bFull);
+
+void AddEntryIntoBucketGroup(Bucket_Group *pBucketGroup,
+ Dwarf_Addr key,Dwarf_Addr base,Dwarf_Addr low,Dwarf_Addr high,
+ const char *name, Dwarf_Bool bFlag);
+
+Dwarf_Bool DeleteKeyInBucketGroup(Bucket_Group *pBucketGroup,Dwarf_Addr key);
+
+Dwarf_Bool FindAddressInBucketGroup(Bucket_Group *pBucketGroup,Dwarf_Addr address);
+Bucket_Data *FindDataInBucketGroup(Bucket_Group *pBucketGroup,Dwarf_Addr key);
+Bucket_Data *FindKeyInBucketGroup(Bucket_Group *pBucketGroup,Dwarf_Addr key);
+Bucket_Data *FindNameInBucketGroup(Bucket_Group *pBucketGroup,char *name);
+
+Dwarf_Bool IsValidInBucketGroup(Bucket_Group *pBucketGroup,Dwarf_Addr pc);
+
+void ResetLimitsBucketSet(Bucket_Group *pBucketGroup);
+void SetLimitsBucketGroup(Bucket_Group *pBucketGroup,Dwarf_Addr lower,Dwarf_Addr upper);
+Dwarf_Bool IsValidInLinkonce(Bucket_Group *pLo,
+ const char *name,Dwarf_Addr lopc,Dwarf_Addr hipc);
+
+
+#endif /* CHECKUTIL_H */
diff --git a/dwarfdump/common.c b/dwarfdump/common.c
new file mode 100644
index 0000000..2788578
--- /dev/null
+++ b/dwarfdump/common.c
@@ -0,0 +1,88 @@
+/*
+ Copyright (C) 2008-2010 SN Systems. All Rights Reserved.
+ Portions Copyright (C) 2008-2011 David Anderson. All Rights Reserved.
+ Portions Copyright (C) 2011 SN Systems Ltd. . All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+/* These do little except on Windows */
+
+#include "common.h"
+#include <stdio.h>
+#define DWARFDUMP_VERSION " Tue Apr 10 11:43:32 PDT 2012 "
+
+/* The Linux/Unix version does not want a version string to print
+ unless -V is on the command line. */
+void
+print_version_details(const char * name,int alwaysprint)
+{
+#ifdef WIN32
+# ifdef _DEBUG
+ char *acType = "Debug";
+# else
+ char *acType = "Release";
+# endif /* _DEBUG */
+ static char acVersion[32];
+ snprintf(acVersion,sizeof(acVersion),
+ "[%s %s %s]",__DATE__,__TIME__,acType);
+ printf("%s %s\n",name,acVersion);
+#else /* !WIN32 */
+ if(alwaysprint) {
+ printf("%s\n",DWARFDUMP_VERSION);
+ }
+#endif /* WIN32 */
+}
+
+
+void
+print_args(int argc, char *argv[])
+{
+#ifdef WIN32
+ int index = 1;
+ printf("Arguments: ");
+ for (index = 1; index < argc; ++index) {
+ printf("%s ",argv[index]);
+ }
+ printf("\n");
+#endif /* WIN32 */
+}
+
+void
+print_usage_message(const char *program_name, const char **text)
+{
+ unsigned i = 0;
+#ifndef WIN32
+ fprintf(stderr,"Usage: %s <options> <object file>\n", program_name);
+#endif
+ for (i = 0; *text[i]; ++i) {
+ fprintf(stderr,"%s\n", text[i]);
+ }
+}
diff --git a/dwarfdump/common.h b/dwarfdump/common.h
new file mode 100644
index 0000000..f1a598e
--- /dev/null
+++ b/dwarfdump/common.h
@@ -0,0 +1,42 @@
+/*
+ Copyright (C) 2009-2010 SN Systems. All Rights Reserved.
+ Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+#ifndef COMMON_INCLUDED_H
+#define COMMON_INCLUDED_H
+
+void print_args(int argc, char *argv[]);
+void print_version_details(const char *name, int alwaysprint);
+void print_usage_message(const char *program_name, const char **text);
+
+#endif /* COMMON_INCLUDED_H */
diff --git a/dwarfdump/config.h.in b/dwarfdump/config.h.in
new file mode 100644
index 0000000..a1a11db
--- /dev/null
+++ b/dwarfdump/config.h.in
@@ -0,0 +1,100 @@
+/* config.h.in. Generated from configure.in by autoheader. */
+
+/* Define to 1 if the elf64_getehdr function is in libelf.a. */
+#undef HAVE_ELF64_GETEHDR
+
+/* Define to 1 if the Elf64_Rel structure has r_info field. */
+#undef HAVE_ELF64_R_INFO
+
+/* Define to 1 if you have the <elf.h> header file. */
+#undef HAVE_ELF_H
+
+/* Define to 1 if you have the <getopt.h> header file. */
+#undef HAVE_GETOPT_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <libelf.h> header file. */
+#undef HAVE_LIBELF_H
+
+/* Define to 1 if you have the <libelf/libelf.h> header file. */
+#undef HAVE_LIBELF_LIBELF_H
+
+/* Define 1 if off64 is defined via libelf with GNU_SOURCE. */
+#undef HAVE_LIBELF_OFF64_OK
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define 1 if need nonstandard printf format for 64bit */
+#undef HAVE_NONSTANDARD_PRINTF_64_FORMAT
+
+/* Define 1 if plain libelf builds. */
+#undef HAVE_RAW_LIBELF_OK
+
+/* Define 1 if regex seems to be defined */
+#undef HAVE_REGEX
+
+/* Define to 1 if you have the <sgidefs.h> header file. */
+#undef HAVE_SGIDEFS_H
+
+/* Define 1 if we have the Windows specific header stdafx.h */
+#undef HAVE_STDAFX_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define 1 if the tsearch functions seem to be defined */
+#undef HAVE_TSEARCH
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* See if __uint32_t is predefined in the compiler. */
+#undef HAVE___UINT32_T
+
+/* Define 1 if sys/types.h defines __uint32_t. */
+#undef HAVE___UINT32_T_IN_SYS_TYPES_H
+
+/* See if __uint64_t is predefined in the compiler. */
+#undef HAVE___UINT64_T
+
+/* Define to header that first defines elf. */
+#undef LOCATION_OF_LIBELFHEADER
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
diff --git a/dwarfdump/configure b/dwarfdump/configure
new file mode 100755
index 0000000..67ede72
--- /dev/null
+++ b/dwarfdump/configure
@@ -0,0 +1,5109 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.68.
+#
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+# Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ # We cannot yet assume a decent shell, so we have to provide a
+ # neutralization value for shells without unset; and this also
+ # works around shells that cannot unset nonexistent variables.
+ # Preserve -v and -x to the replacement shell.
+ BASH_ENV=/dev/null
+ ENV=/dev/null
+ (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+ export CONFIG_SHELL
+ case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+ esac
+ exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -p'
+ fi
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+PACKAGE_URL=
+
+ac_unique_file="dwarfdump.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+AR
+RANLIB
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+EGREP
+GREP
+CPP
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_nonstandardprintf
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used" >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-option-checking ignore unrecognized --enable/--with options
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --enable-nonstandardprintf
+ Use a special printf format for 64bit (default is
+ NO)
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.68
+
+Copyright (C) 2010 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if eval \${$3+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_header_compiler=yes
+else
+ ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ ac_header_preproc=yes
+else
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+ yes:no: )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+ no:yes:* )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: program exited with status $ac_status" >&5
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=$ac_status
+fi
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ $as_test_x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.68. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+if test -z "$ac_file"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if ${ac_cv_prog_CPP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+if test $ac_cv_c_compiler_gnu = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC needs -traditional" >&5
+$as_echo_n "checking whether $CC needs -traditional... " >&6; }
+if ${ac_cv_prog_gcc_traditional+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_pattern="Autoconf.*'x'"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sgtty.h>
+Autoconf TIOCGETP
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "$ac_pattern" >/dev/null 2>&1; then :
+ ac_cv_prog_gcc_traditional=yes
+else
+ ac_cv_prog_gcc_traditional=no
+fi
+rm -f conftest*
+
+
+ if test $ac_cv_prog_gcc_traditional = no; then
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <termio.h>
+Autoconf TCGETA
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "$ac_pattern" >/dev/null 2>&1; then :
+ ac_cv_prog_gcc_traditional=yes
+fi
+rm -f conftest*
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_gcc_traditional" >&5
+$as_echo "$ac_cv_prog_gcc_traditional" >&6; }
+ if test $ac_cv_prog_gcc_traditional = yes; then
+ CC="$CC -traditional"
+ fi
+fi
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if ${ac_cv_path_install+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+ ./ | .// | /[cC]/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ rm -rf conftest.one conftest.two conftest.dir
+ echo one > conftest.one
+ echo two > conftest.two
+ mkdir conftest.dir
+ if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+ test -s conftest.one && test -s conftest.two &&
+ test -s conftest.dir/conftest.one &&
+ test -s conftest.dir/conftest.two
+ then
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+
+ done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+ ac_ct_AR=$AR
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_AR="ar"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_AR" = x; then
+ AR=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ AR=$ac_ct_AR
+ fi
+else
+ AR="$ac_cv_prog_AR"
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_stdc=yes
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then :
+ :
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in elf.h getopt.h libelf.h libelf/libelf.h sgidefs.h sys/types.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for elf64_getehdr in -lelf" >&5
+$as_echo_n "checking for elf64_getehdr in -lelf... " >&6; }
+if ${ac_cv_lib_elf_elf64_getehdr+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lelf $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char elf64_getehdr ();
+int
+main ()
+{
+return elf64_getehdr ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_elf_elf64_getehdr=yes
+else
+ ac_cv_lib_elf_elf64_getehdr=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_elf_elf64_getehdr" >&5
+$as_echo "$ac_cv_lib_elf_elf64_getehdr" >&6; }
+if test "x$ac_cv_lib_elf_elf64_getehdr" = xyes; then :
+
+$as_echo "#define HAVE_ELF64_GETEHDR 1" >>confdefs.h
+
+fi
+
+
+if test "$ac_cv_header_elf_h" = yes; then
+
+$as_echo "#define LOCATION_OF_LIBELFHEADER <elf.h>" >>confdefs.h
+
+elif test "$ac_cv_header_libelf_h" = yes; then
+
+$as_echo "#define LOCATION_OF_LIBELFHEADER <libelf.h>" >>confdefs.h
+
+elif test "$ac_cv_header_libelf_libelf_h" = yes; then
+
+$as_echo "#define LOCATION_OF_LIBELFHEADER <libelf/libelf.h>" >>confdefs.h
+
+fi
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include "stdafx.h"
+int
+main ()
+{
+ int p; p = 27;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE_STDAFX_H 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include LOCATION_OF_LIBELFHEADER
+int
+main ()
+{
+Elf64_Rel *p; int i; i = p->r_info;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE_ELF64_R_INFO 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+__uint32_t p; p = 3;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE___UINT32_T 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+__uint64_t p; p = 3;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE___UINT64_T 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+int
+main ()
+{
+ __uint32_t p; p = 3;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE___UINT32_T_IN_SYS_TYPES_H 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <regex.h>
+int
+main ()
+{
+ int i;
+ regex_t r;
+ int cflags = REG_EXTENDED;
+ const char *s = "abc";
+ i = regcomp(&r,s,cflags);
+ regfree(&r);
+ ;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE_REGEX 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+#include <stdlib.h>
+/* On Ubuntu 10.x, tsearch is in package libc6-dev. */
+/* The tdestroy function is GNU, not POSIX. */
+#define __USE_GNU 1
+#include <search.h>
+struct my_tentry {
+ long mt_key;
+ char * mt_name;
+};
+struct my_tentry * make_my_tentry(long k,char *name) { return 0; }
+void mt_free_func(void *mt_data) { return; }
+int mt_compare_func(const void *l, const void *r) { return 0; }
+int
+main ()
+{
+
+ long i = 1;
+ void *tree1 = 0;
+ char *dbuf = 0;
+ struct my_tentry *mt = 0;
+ struct my_tentry *retval = 0;
+ mt = make_my_tentry(i,dbuf);
+ retval = tsearch(mt,&tree1, mt_compare_func );
+ tdestroy(tree1,mt_free_func);
+ exit(0);
+;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+$as_echo "#define HAVE_TSEARCH 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+
+# Check whether --enable-nonstandardprintf was given.
+if test "${enable_nonstandardprintf+set}" = set; then :
+ enableval=$enable_nonstandardprintf;
+$as_echo "#define HAVE_NONSTANDARD_PRINTF_64_FORMAT 1" >>confdefs.h
+
+fi
+
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <libelf.h>
+
+int
+main ()
+{
+ int p; p = 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE_RAW_LIBELF_OK 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#define _GNU_SOURCE
+#include <libelf.h>
+
+int
+main ()
+{
+ off64_t p; p = 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE_LIBELF_OFF64_OK 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+
+ac_config_files="$ac_config_files Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -p'
+ fi
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.68. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.68,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2010 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+ --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+ ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+ if test -z "$ac_tt"; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any. Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[ ]*#[ ]*define[ ][ ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ for (key in D) D_is_set[key] = 1
+ FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+ line = \$ 0
+ split(line, arg, " ")
+ if (arg[1] == "#") {
+ defundef = arg[2]
+ mac1 = arg[3]
+ } else {
+ defundef = substr(arg[1], 2)
+ mac1 = arg[2]
+ }
+ split(mac1, mac2, "(") #)
+ macro = mac2[1]
+ prefix = substr(line, 1, index(line, defundef) - 1)
+ if (D_is_set[macro]) {
+ # Preserve the white space surrounding the "#".
+ print prefix "define", macro P[macro] D[macro]
+ next
+ } else {
+ # Replace #undef with comments. This is necessary, for example,
+ # in the case of _POSIX_SOURCE, which is predefined and required
+ # on some systems where configure will not decide to define it.
+ if (defundef == "undef") {
+ print "/*", prefix defundef, macro, "*/"
+ next
+ }
+ }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS "
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+ if test x"$ac_file" != x-; then
+ {
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+ } >"$ac_tmp/config.h" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f "$ac_file"
+ mv "$ac_tmp/config.h" "$ac_file" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ fi
+ else
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+ || as_fn_error $? "could not create -" "$LINENO" 5
+ fi
+ ;;
+
+
+ esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/dwarfdump/configure.in b/dwarfdump/configure.in
new file mode 100644
index 0000000..753a1b4
--- /dev/null
+++ b/dwarfdump/configure.in
@@ -0,0 +1,98 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(dwarfdump.c)
+AC_CONFIG_HEADER(config.h)
+
+AC_PROG_CC
+AC_GCC_TRADITIONAL
+AC_PROG_INSTALL
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+AC_CHECK_TOOL(AR, ar)
+dnl AC_ARFLAGS
+
+AC_CHECK_HEADERS(elf.h getopt.h libelf.h libelf/libelf.h sgidefs.h sys/types.h)
+AC_CHECK_LIB(elf,elf64_getehdr,
+ AC_DEFINE(HAVE_ELF64_GETEHDR,1,
+ [Define to 1 if the elf64_getehdr function is in libelf.a.]))
+
+dnl Find out where the elf header is.
+if test "$ac_cv_header_elf_h" = yes; then
+ AC_DEFINE(LOCATION_OF_LIBELFHEADER,[<elf.h>], [Define to header that first defines elf])
+elif test "$ac_cv_header_libelf_h" = yes; then
+ AC_DEFINE(LOCATION_OF_LIBELFHEADER, [<libelf.h>],
+ [Define to header that first defines elf.])
+elif test "$ac_cv_header_libelf_libelf_h" = yes; then
+ AC_DEFINE(LOCATION_OF_LIBELFHEADER,[<libelf/libelf.h>],
+ [Define to header that first defines elf.])
+fi
+
+AC_TRY_COMPILE([#include "stdafx.h"],[ int p; p = 27;] ,
+ AC_DEFINE(HAVE_STDAFX_H,1,
+ [Define 1 if we have the Windows specific header stdafx.h]))
+
+AC_TRY_COMPILE([#include LOCATION_OF_LIBELFHEADER], Elf64_Rel *p; int i; i = p->r_info; ,AC_DEFINE(HAVE_ELF64_R_INFO,1,
+ [Define to 1 if the Elf64_Rel structure has r_info field.]))
+AC_TRY_COMPILE([], __uint32_t p; p = 3; ,AC_DEFINE(HAVE___UINT32_T,
+ 1,[See if __uint32_t is predefined in the compiler. ]))
+AC_TRY_COMPILE([], __uint64_t p; p = 3; ,AC_DEFINE(HAVE___UINT64_T,
+ 1,[See if __uint64_t is predefined in the compiler. ]))
+AC_TRY_COMPILE([#include <sys/types.h>],[ __uint32_t p; p = 3]; ,
+ AC_DEFINE(HAVE___UINT32_T_IN_SYS_TYPES_H,1,
+ [Define 1 if sys/types.h defines __uint32_t.]))
+AC_TRY_COMPILE([#include <sys/types.h>
+ #include <regex.h>],[ int i;
+ regex_t r;
+ int cflags = REG_EXTENDED;
+ const char *s = "abc";
+ i = regcomp(&r,s,cflags);
+ regfree(&r);
+ ]; ,
+ AC_DEFINE(HAVE_REGEX,1,
+ [Define 1 if regex seems to be defined]))
+AC_TRY_LINK([#include <stdio.h>
+#include <stdlib.h>
+/* On Ubuntu 10.x, tsearch is in package libc6-dev. */
+/* The tdestroy function is GNU, not POSIX. */
+#define __USE_GNU 1
+#include <search.h>
+struct my_tentry {
+ long mt_key;
+ char * mt_name;
+};
+struct my_tentry * make_my_tentry(long k,char *name) { return 0; }
+void mt_free_func(void *mt_data) { return; }
+int mt_compare_func(const void *l, const void *r) { return 0; }],[
+ long i = 1;
+ void *tree1 = 0;
+ char *dbuf = 0;
+ struct my_tentry *mt = 0;
+ struct my_tentry *retval = 0;
+ mt = make_my_tentry(i,dbuf);
+ retval = tsearch(mt,&tree1, mt_compare_func );
+ tdestroy(tree1,mt_free_func);
+ exit(0);
+];,
+ AC_DEFINE(HAVE_TSEARCH,1,
+ [Define 1 if the tsearch functions seem to be defined]))
+
+
+AC_ARG_ENABLE(nonstandardprintf,AC_HELP_STRING([--enable-nonstandardprintf],
+ [Use a special printf format for 64bit (default is NO)]),
+ [ AC_DEFINE([HAVE_NONSTANDARD_PRINTF_64_FORMAT],[1],
+ [Define 1 if need nonstandard printf format for 64bit] )],
+ [])
+
+AC_TRY_COMPILE([
+#include <libelf.h>
+],[ int p; p = 0; ] ,
+ AC_DEFINE(HAVE_RAW_LIBELF_OK,1,
+ [Define 1 if plain libelf builds.]))
+AC_TRY_COMPILE([
+#define _GNU_SOURCE
+#include <libelf.h>
+],[ off64_t p; p = 0;] ,
+ AC_DEFINE(HAVE_LIBELF_OFF64_OK,1,
+ [Define 1 if off64 is defined via libelf with GNU_SOURCE.]))
+
+
+
+AC_OUTPUT(Makefile)
diff --git a/dwarfdump/dwarfdump.1 b/dwarfdump/dwarfdump.1
new file mode 100644
index 0000000..bb7ee37
--- /dev/null
+++ b/dwarfdump/dwarfdump.1
@@ -0,0 +1,523 @@
+.TH DWARFDUMP
+.SH NAME
+dwarfdump \- dumps DWARF debug information of an ELF object
+.SH SYNOPSIS
+.B dwarfdump [options] \f2objectfilename\fP
+.SH DESCRIPTION
+The
+.B dwarfdump
+command prints or checks DWARF sections as requested by specific options.
+With no options (but with the required \f2objectfilename\fP )
+all sections print (but some sections cannot be printed independently
+safely, so those are only printed at offsets where the .debug_info section
+refers to those sections).
+.PP
+As of June 2011 the printing options and the checking options
+are mutually exclusive (if checking options are selected
+the section details are not printed). When errors are encountered
+dwarfdump does attempt to print sufficient context so that
+one can understand exactly where the error is in the DWARF.
+This change makes checking really large object files
+much easier.
+.PP
+The format is intended to be human readable.
+If a script is to parse the output, the
+.B \-d
+option is useful.
+.PP
+Not all sections actually exist in any given object file.
+.PP
+The format may change from release to release, so it is
+unwise to depend too heavily on the format.
+.PP
+Frame information (.debug_frame and .eh_frame) is heavily
+dependent on the ABI/ISA of the object file.
+By default we use a generic set of register names
+handling up to 100 registers named r0-100.
+The '-R' option uses a built-in generic register name set
+handling up to 1200 registers named r0-r1199.
+The '-x abi=<abi>'
+description below shows how to name an abi and use that to guide
+the -f or -F processing.
+Unless the cpu for the object file being dumped has many registers,
+do not use -R or -x abi=generic as those can be needlessly
+slow dumping frame sections. Instead, use the correct
+abi (if it exists in dwarfdump.conf) or a generic such
+as -x abi=generic100 or -x abi=generic500.
+To get MIPS/IRIX register names names and call the old version 2 libdwarf
+frame interface use the option '-x abi=mips'.
+Without '-R' or '-x abi=<abi>' dwarfdump ignores
+the dwarfdump.conf file and uses compiled-in generic set of
+register names.
+If no '-x name=<path>' is given, dwarfdump
+looks for "./dwarfdump.conf", "$HOME/.dwarfdump.conf", "<install-prefix>/lib/dwarfdump.conf" and takes the first it finds.
+If one or more '-x name=<path>' is given the last of these is
+used and all other such files are ignored.
+.PP
+Some -k (checking) options print so-called harmless errors.
+These are compiler errors that do not cause any
+known problem and are only detected inside libdwarf itself.
+These are difficult to properly report in dwarfdump and
+any error strings may not appear close to the time the
+error was encountered.
+.SH URI STYLE INPUT STRINGS
+.PP
+The <objectfilename> and the options taking name strings look for URIs and
+translate the URI strings to characters by default
+(see -x, -c<compiler name>, -S, -u).
+So any single % character is treated as if the following two
+characters are hex digits representing the underlying true character.
+Various characters are meaningful to shells (such as bash or sh)
+and to getopt (such as the space character)
+If the URI translation does anything it prints the before and after
+of the URI translation on standard output, so inspection of the first
+lines of output will show if URI did anything.
+The actual options themselves are assumed to be non-URI.
+So in the option '-cS&T' the -c portion must be non-URI, but the
+& character might cause input issues so '-cS%26T' could be used instead.
+To actually input a single % character (in a name, for example),
+double it to %% on the command line.
+.PP
+Options -U (turning off URI interpretation) and -q (making finding
+URI sequences silent) give finer control of URI interpretation.
+PP
+As an example, to get a string'a b' make the string 'a%20b'
+(here the quote (') is for exposition not part of the string, though
+quote is certainly problematic in a name).
+Instead of escaping " quotes in the string, type %25, as in
+ 'a "b' should be typed 'a%20%25b'
+Any characters can be typed in URI style, not just characters
+which are problematic to the shell or getopt.
+We strongly suggest you not type URI-style characters where
+such are not needed or use
+the % character itself in command line strings unless you must.
+.SH PRINTING OPTIONS
+.TP
+.B \-a
+Print each section as independently as possible. Sections that
+can safely be printed independently (like .debug_abbrev)
+have relevant info printed in the report (sometimes dependent
+on -v).
+
+.TP
+.B \-b
+Print the .debug_abbrev section. Because the DWARF specfications
+do not rule out garbage data areas in .debug_abbrev (if they are not
+referenced from .debug_info) any garbage bytes can result in
+this print failing.
+
+.TP
+.B \-c
+Print locations lists.
+
+.TP
+.B \-f
+Print the .debug_frame section.
+.TP
+.B \-F
+Print the .eh_frame section.
+
+.TP
+.B \-i
+Print the .debug_info section.
+
+.TP
+.B \-l
+Print the .debug_info section and the associated line section data.
+
+.TP
+.B \-m
+Print the .debug_macinfo section.
+
+.TP
+.B \-N
+Print .debug_ranges section. Because the DWARF specfications
+do not rule out garbage data areas in .debug_ranges (if they are not
+referenced from .debug_info) any garbage bytes can result in
+this print failing.
+
+.TP
+.B \-p
+Print the .debug_pubnames section.
+
+.TP
+.B \-r
+Print the .debug_aranges section.
+.TP
+.B \-s
+Print .debug_string section.
+
+.TP
+.B \-ta
+Print the IRIX only sections .debug_static_funcs and .debug_static_vars.
+
+.TP
+.B \-tf
+Print the IRIX only section .debug_static_funcs.
+.TP
+.B \-tv
+Print the IRIX only section .debug_static_vars.
+
+.TP
+.B \-w
+Print the IRIX-only .debug_weaknames section.
+
+.TP
+.B \-y
+Print the .debug_pubtypes section (and .debug_typenames,
+an SGI IRIX-only section).
+
+.PP
+Having dwarfdump print relocations may help establish whether
+dwarfdump understands any relocations that might exist.
+
+.TP
+.B \-o
+Print all relocation records as well as we can manage.
+.TP
+.B \-oi
+Print .rel*debug_info relocations.
+.TP
+.B \-ol
+Print .rel*debug_line relocation.
+.TP
+.B \-op
+Print .rel*debug_pubnames relocation.
+.TP
+.B \-oa
+Has no effect.
+.TP
+.B \-or
+Print .rel*debug_aranges relocations.
+.TP
+.B \-of
+Print .rel*debug_frame relocations.
+.TP
+.B \-oo
+Print .rel*debug_loc relocations.
+.TP
+.B \-oR
+Print .rel*debug_ranges relocations.
+
+.TP
+.B \-g
+Normally used only for testing libdwarf, this tells dwarfdump to
+print .debug_info and use an older dwarf_loclist() interface
+function (a function that cannot handle all current
+location lists).
+.TP
+.B \-V
+Print a dwarfdump date/version string and stop.
+
+.SH CHECKING OPTIONS
+.TP
+.B \-cg
+Restricts checking to compilers whose
+producer string starts with 'GNU'
+and turns off -cs .
+
+.TP
+.B \-cs
+Restricts checking to compilers whose
+producer string starts with 'SN'
+and turns off -cg .
+.TP
+.B \-cname
+Restricts checking to compilers whose
+producer string contains 'name' (not case sensitive).
+The 'name' is read as a URI string.
+
+.TP
+.B \
+-ka : Turns on all checking options except -kxe (-kxe might
+ be slow enough one mignt not want to use it routinely.)
+
+.TP
+.B \
+-kb : Checks for certain abbreviations section errors when reading
+ DIEs.
+.TP
+.B \-kc
+Checks for errors in constants in debug_info.
+.TP
+.B \-kd
+Turns on full reporting of error totals per producer.
+(the default shows less detail).
+.TP
+.B \-ke
+Turns on reading pubnames and checking for fde errors.
+.TP
+.B \-kf
+Turns on checking for FDE errors.
+.TP
+.B \-kF
+Turns on checking for line table errors.
+.TP
+.B \-kg
+Turns on checking for unused gaps in .debug_info (these
+gaps are not an error, just a waste of space).
+
+.TP
+.B \-ki
+Causes a summary of checking results per compiler (producer)
+to be printed at the end.
+.TP
+.B \-kl
+Turns on locations list checking.
+.TP
+.B \-km
+Turns on checking of ranges.
+.TP
+.B \-kM
+Turns on checking of aranges.
+.TP
+.B \-kr
+Turns on DIE tag-attr combinations checking.
+.TP
+.B \-kR
+Turns on reading DIEs and checking for forward declarations
+rom DW_AT_specification attributes.
+(which are not an error but can be a source of inefficiency
+for debuggers).
+.TP
+.B \-ks
+Turns on extra reporting for some DIE errors checking detects .
+.TP
+.B \-kS
+Turns on checking DIE references for circular references.
+.TP
+.B \-kt
+Turns on tag-tag combinations checking.
+.TP
+.B \-kx
+Turns on check_frames.
+.TP
+.B \-kxe
+Turns off basic check_frames and turns on extended frame checking.
+.TP
+.B \-ky
+Turns on type_offset, decl_file checking,
+
+.SH OPTION MODIFIERS
+
+.TP
+.B \-C
+Normally when checking for tag-tag or tag-attribute combinations
+both the standard combinations and some common extensions are allowed.
+With -C the extensions are taken out of the allowed class of combinations.
+
+.TP
+.B \-d
+When printing DIEs, put all the attributes for each DIE on the same (long)
+line as the TAG. This makes searching for DIE information
+(as with grep) much simpler as the entire DIE is on one line.
+
+.TP
+.B \-D
+Turns off the display of section offsets and attribute values in printed output.
+So the .debug_info output isjust TAGs and Attributes.
+For pubnames (and the like) it removes offsets from the output.
+For locations lists it removes offsets from the output, but that
+is useless since the attribute values don't show so neither does
+the location data.
+
+.TP
+.B \-e
+Turns on truncation of attribute and tag names. For example
+DW_TAG_foo becomes foo . Not compatible with
+checking, only useful for printing DIEs.
+
+.TP
+.B \-G
+When printing, add global offsets to the offsets printed.
+
+.TP
+.B \-H number
+When printing or checking .debug_info, this terminates
+the search after 'number' compilation units. When printing
+frame information this terminates the FDE reporting
+after 'number' FDEs and the CIE reporting (which occurs if one adds -v)
+after 'number' CIEs. Example '-H 1'
+
+.TP
+.B \-M
+When printing, this means one want to have the FORM show for each attribute.
+If a -v is also added (or more than one) then details of any form indirection
+are also shown.
+
+.TP
+.B \-n
+When printing frames, this turns off the search for function names.
+In a really large object the search can take more time than
+one wants to wait, so this avoids the search.
+
+.TP
+.B \-Q
+Suppresses section data printing (set automatically with a checking option).
+
+.TP
+.B \-R
+When printing frames for ABIs with lots of registers, this allows
+up to 1200 registers to be named (like R999) without choosing an ABI
+with, for example '-x abi=ppc'
+
+.TP
+.B \-v
+Increases the detail shown when printing.
+In some sections, using more -v options
+will increase the detail (one to three are useful) or may
+change the report to show, for example, the actual
+line-data-commands instead of the resultant line-table.
+
+.SH SELECTIVE ENTRY PRINTING
+
+.PP
+These -S options stand alone and basic print information about the compilation
+unit and DIE where the string(s) appear.
+At most one of each of the following is effective (so for example
+one can only have one 'match', but one can
+have a 'match', an 'any', and a 'regex').
+Any -S causes the .debug_info section to be inspected.
+No checking options or printing options should be supplied with -S.
+
+.TP
+.B \-S match=string
+When printing DIEs
+for each tag value or attribute name that matches 'string' exactly
+print the compilation unit information and its section offset.
+Any CU with no match is not printed.
+The 'string' is read as a URI string.
+.TP
+.B \-S any=string
+When printing DIEs
+for each tag value or attribute name that contains 'string'
+somewhere in the tag or attribute (case insensitive)
+print the compilation unit information and its section offset.
+Any CU with no match is not printed.
+The 'string' is read as a URI string.
+.TP
+.B \-S regex=string
+When printing DIEs
+for each tag value or attribute name where the 'string' reqular
+expression matches print the compilation unit information
+and its section offset.
+Any CU with no match is not printed.
+The 'string' is read as a URI string.
+
+.PP
+The string cannot have spaces or other characters which are
+meaningful to getopt(3) and the shell will strip off quotes and
+other characters.
+So the string is assumed to be in URI style and is translated.
+In other words, to match 'a b' make the -S string 'a%20b'
+Instead of escaping " quotes in the string, type %25, as in
+ 'a "b' should be typed 'a%20%25b'
+(the ' are for exposition here, not part of the strings).
+Any characters can be typed in URI style, not just characters
+which are problematic to the shell or getopt.
+.PP
+The -S any= and -S regex= options are only usable
+if the library functions required are found at configure time.
+.PP
+The -W option is a modifier to the -S option, and
+increases the amount of output -W prints.
+Now we show the -W in context with a -S option.
+
+.TP
+.B \-S match=string1 -W
+Prints the parent tree and the children tree for the
+DIEs that -S matches.
+
+.TP
+.B \-S match=string2 -Wp
+Prints the parent tree for the DIEs that -S matches.
+
+.TP
+.B \-S match=string3 -Wc
+Prints the parent tree for the DIEs that -S matches.
+
+.SH OTHER OPTIONS
+
+.TP
+.B \-# number
+This option controls internal debugging output,
+higher numbers mean more debug actions. See the source code.
+
+
+.TP
+.B \-x name=/p/a/t/h.conf
+The file path given is the name of a file assumed to be
+a dwarfdump.conf-like file.
+The file path is read as a URI string.
+
+.TP
+.B \-x abi=ppc
+Selects the abi (from a dwarfdump.conf file) to be used in
+printing frame information (here using ppc as an example).
+The abi is read as a URI string.
+
+.TP
+.B \-P
+When checking this adds the list of compilation-unit names
+seen for each producer-compiler to the printed checking results.
+.TP
+.B \-q
+When a URI is found and translated while reading
+the command line, be quiet about
+the URI translation. That is, don't print the
+original and translated option strings.
+
+.TP
+.B \-E
+Turns on printing object-internal header data for some
+systems (for Unix/Linux does nothing).
+
+.TP
+.B \-u cuname
+Turns on selective printing of DIEs (printing like -i).
+Only the DIEs for a compilation unit that match the
+name provided are printed.
+If the compilation unit is ./a/b/c.c
+the 'cuname' you provide should be c.c as the characters
+through the final path-separating / are ignored.
+If 'cuname' begins with a / then the entire name string
+of a compilation unit must match 'cuname'.
+The 'cuname' is read as a URI string.
+
+.TP
+.B \-U
+Turn off the URI interpretation of the command line
+strings entirely. Must be be on the command line before
+any URI strings encountered to be fully effective.
+
+.TP
+.B \-z
+No longer suported.
+
+
+.SH FILES
+dwarfdump
+
+dwarfdump.conf
+
+./dwarfdump.conf
+
+$(HOME)/.dwarfdump.conf
+
+$(HOME)/dwarfdump.conf
+
+<install-prefix>/lib/dwarfdump.conf
+.SH NOTES
+In some cases compilers use DW_FORM_data1 (for example)
+and in such cases the signedness of the value must be taken
+from context. Rather than attempt to determine the
+context, dwarfdump prints the value with both signednesses
+whenever there is ambiguity about the correct interpretation.
+For example,
+"DW_AT_const_value 176(as signed = -80)".
+For normal DWARF consumers that correctly and fully
+evaluate all attributes there is no ambiguity of signedness:
+the ambiguity for dwarfdump is due to dwarfdump evaluating
+DIEs in a simple order and not keeping track of much context.
+.SH BUGS
+Support for DWARF3 is being completed but may not be complete.
diff --git a/dwarfdump/dwarfdump.c b/dwarfdump/dwarfdump.c
new file mode 100644
index 0000000..f8bc309
--- /dev/null
+++ b/dwarfdump/dwarfdump.c
@@ -0,0 +1,2357 @@
+/*
+ Copyright (C) 2000,2002,2004,2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/dwarfdump.c,v 1.48 2006/04/18 18:05:57 davea Exp $ */
+
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include "globals.h"
+/* for 'open' */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h> /* For getopt */
+#include "makename.h"
+#include "dwconf.h"
+#include "common.h"
+#include "esb.h" /* For flexible string buffer. */
+
+#ifdef WIN32
+extern int elf_open(char *name,int mode);
+#endif
+
+#define DWARFDUMP_VERSION " Tue Apr 10 11:43:32 PDT 2012 "
+
+extern char *optarg;
+
+
+#define OKAY 0
+#define BYTES_PER_INSTRUCTION 4
+
+static const char* process_args(int argc, char *argv[]);
+
+char * program_name;
+static int check_error = 0;
+
+/* The type of Bucket. */
+#define KIND_RANGES_INFO 1
+#define KIND_SECTIONS_INFO 2
+#define KIND_VISITED_INFO 3
+
+/* pRangesInfo records the DW_AT_high_pc and DW_AT_low_pc
+ and is used to check that line range info falls inside
+ the known valid ranges. The data is per CU, and is
+ reset per CU in tag_specific_checks_setup(). */
+Bucket_Group *pRangesInfo = NULL;
+
+/* pLinkonceInfo records data about the link once sections.
+ If a line range is not valid in the current CU it might
+ be valid in a linkonce section, this data records the
+ linkonce sections. So it is filled in when an
+ object file is read and remains unchanged for an entire
+ object file. */
+Bucket_Group *pLinkonceInfo = NULL;
+/* pVisitedInfo records a recursive traversal of DIE attributes
+ DW_AT_specification DW_AT_abstract_origin DW_AT_type
+ that let DWARF refer (as in a general graph) to
+ arbitrary other DIEs.
+ These traversals use pVisitedInfo to
+ detect any compiler errors that introduce circular references.
+ Printing of the traversals is also done on request.
+ Entries are added and deleted as they are visited in
+ a depth-first traversal. */
+Bucket_Group *pVisitedInfo = NULL;
+
+/* Options to enable debug tracing */
+int nTrace[MAX_TRACE_LEVEL + 1];
+
+/* Build section information */
+void build_linkonce_info(Dwarf_Debug dbg);
+static const char * do_uri_translation(const char *s,
+ const char *context);
+static void reset_overall_CU_error_data();
+
+boolean info_flag = FALSE;
+boolean use_old_dwarf_loclist = FALSE; /* This so both dwarf_loclist()
+ and dwarf_loclist_n() can be
+ tested. Defaults to new
+ dwarf_loclist_n() */
+
+boolean line_flag = FALSE;
+static boolean abbrev_flag = FALSE;
+static boolean frame_flag = FALSE; /* .debug_frame section. */
+static boolean eh_frame_flag = FALSE; /* GNU .eh_frame section. */
+static boolean pubnames_flag = FALSE;
+static boolean macinfo_flag = FALSE;
+static boolean loc_flag = FALSE;
+static boolean aranges_flag = FALSE; /* .debug_aranges section. */
+static boolean ranges_flag = FALSE; /* .debug_ranges section. */
+static boolean string_flag = FALSE;
+static boolean reloc_flag = FALSE;
+static boolean static_func_flag = FALSE;
+static boolean static_var_flag = FALSE;
+static boolean type_flag = FALSE;
+static boolean weakname_flag = FALSE;
+static boolean header_flag = FALSE; /* Control printing of Elf header. */
+boolean producer_children_flag = FALSE; /* List of CUs per compiler */
+
+/* Bitmap for relocations. See globals.h for DW_SECTION_REL_DEBUG_RANGES etc.*/
+static unsigned reloc_map = 0;
+
+/* Start verbose at zero. verbose can
+ be incremented with -v but not decremented. */
+int verbose = 0;
+
+boolean dense = FALSE;
+boolean ellipsis = FALSE;
+boolean show_global_offsets = FALSE; /* Show global and relative offsets */
+boolean show_form_used = FALSE;
+boolean display_offsets = TRUE; /* Emit offsets */
+
+boolean check_abbrev_code = FALSE;
+boolean check_pubname_attr = FALSE;
+boolean check_reloc_offset = FALSE;
+boolean check_attr_tag = FALSE;
+boolean check_tag_tree = FALSE;
+boolean check_type_offset = FALSE;
+boolean check_decl_file = FALSE;
+boolean check_lines = FALSE;
+boolean check_fdes = FALSE;
+boolean check_ranges = FALSE;
+boolean check_aranges = FALSE;
+boolean check_harmless = FALSE;
+boolean check_abbreviations = FALSE;
+boolean check_dwarf_constants = FALSE;
+boolean check_di_gaps = FALSE;
+boolean check_forward_decl = FALSE;
+boolean check_self_references = FALSE;
+boolean generic_1200_regs = FALSE;
+boolean suppress_check_extensions_tables = FALSE;
+
+/* suppress_nested_name_search is a band-aid.
+ A workaround. A real fix for N**2 behavior is needed.
+*/
+boolean suppress_nested_name_search = FALSE;
+static boolean uri_options_translation = TRUE;
+static boolean do_print_uri_in_input = TRUE;
+
+
+/* break_after_n_units is mainly for testing.
+ It enables easy limiting of output size/running time
+ when one wants the output limited.
+ For example,
+ -H 2
+ limits the -i output to 2 compilation units and
+ the -f or -F output to 2 FDEs and 2 CIEs.
+*/
+int break_after_n_units = INT_MAX;
+
+boolean check_names = FALSE;
+boolean check_verbose_mode = TRUE; /* During '-k' mode, display errors */
+boolean check_frames = FALSE;
+boolean check_frames_extended = FALSE; /* Extensive frames check */
+boolean check_locations = FALSE; /* Location list check */
+
+static boolean check_all_compilers = TRUE;
+static boolean check_snc_compiler = FALSE; /* Check SNC compiler */
+static boolean check_gcc_compiler = FALSE;
+static boolean print_summary_all = FALSE;
+
+#define COMPILER_TABLE_MAX 100
+typedef struct anc {
+ struct anc *next;
+ char *item;
+} a_name_chain;
+
+/* Records information about compilers (producers) found in the
+ debug information, including the check results for several
+ categories (see -k option). */
+typedef struct {
+ const char *name;
+ boolean verified;
+ a_name_chain *cu_list;
+ a_name_chain *cu_last;
+ Dwarf_Check_Result results[LAST_CATEGORY];
+} Compiler;
+
+/* Record compilers whose CU names have been seen.
+ Full CU names recorded here, though only a portion
+ of the name may have been checked to cause the
+ compiler data to be entered here.
+ The +1 guarantees we do not overstep the array.
+*/
+static Compiler compilers_detected[COMPILER_TABLE_MAX];
+static int compilers_detected_count = 0;
+
+/* compilers_targeted is a list of indications of compilers
+ on which we wish error checking (and the counts
+ of checks made and errors found). We do substring
+ comparisons, so the compilers_targeted name might be simply a
+ compiler version number or a short substring of a
+ CU producer name.
+ The +1 guarantees we do not overstep the array.
+*/
+static Compiler compilers_targeted[COMPILER_TABLE_MAX];
+static int compilers_targeted_count = 0;
+static int current_compiler = -1;
+
+static void reset_compiler_entry(Compiler *compiler);
+static void PRINT_CHECK_RESULT(char *str,
+ Compiler *pCompiler, Dwarf_Check_Categories category);
+
+
+/* The check and print flags here make it easy to
+ allow check-only or print-only. We no longer support
+ check-and-print in a single run. */
+boolean do_check_dwarf = FALSE;
+boolean do_print_dwarf = FALSE;
+boolean check_show_results = FALSE; /* Display checks results. */
+boolean record_dwarf_error = FALSE; /* A test has failed, this
+ is normally set FALSE shortly after being set TRUE, it is
+ a short-range hint we should print something we might not
+ otherwise print (under the circumstances). */
+
+
+/* These names make diagnostic messages more complete, the
+ fixed length is safe, though ultra long names will get
+ truncated. */
+char PU_name[COMPILE_UNIT_NAME_LEN];
+char CU_name[COMPILE_UNIT_NAME_LEN];
+char CU_producer[COMPILE_UNIT_NAME_LEN];
+
+boolean seen_PU = FALSE; /* Detected a PU */
+boolean seen_CU = FALSE; /* Detected a CU */
+boolean need_CU_name = TRUE; /* Need CU name */
+boolean need_CU_base_address = TRUE; /* Need CU Base address */
+boolean need_CU_high_address = TRUE; /* Need CU High address */
+boolean need_PU_valid_code = TRUE; /* Need PU valid code */
+
+boolean seen_PU_base_address = FALSE; /* Detected a Base address for PU */
+boolean seen_PU_high_address = FALSE; /* Detected a High address for PU */
+Dwarf_Addr PU_base_address = 0; /* PU Base address */
+Dwarf_Addr PU_high_address = 0; /* PU High address */
+
+Dwarf_Off DIE_offset = 0; /* DIE offset in compile unit */
+Dwarf_Off DIE_overall_offset = 0; /* DIE offset in .debug_info */
+
+/* These globals enable better error reporting. */
+Dwarf_Off DIE_CU_offset = 0; /* CU DIE offset in compile unit */
+Dwarf_Off DIE_CU_overall_offset = 0; /* CU DIE offset in .debug_info */
+int current_section_id = 0; /* Section being process */
+
+Dwarf_Addr CU_base_address = 0; /* CU Base address */
+Dwarf_Addr CU_high_address = 0; /* CU High address */
+
+Dwarf_Addr elf_max_address = 0; /* Largest representable address offset */
+Dwarf_Half elf_address_size = 0; /* Target pointer size */
+
+/* Display parent/children when in wide format? */
+boolean display_parent_tree = FALSE;
+boolean display_children_tree = FALSE;
+int stop_indent_level = 0;
+
+/* Print search results in wide format? */
+boolean search_wide_format = FALSE;
+/* -S option: strings for 'any' and 'match' */
+boolean search_is_on = FALSE;
+const char *search_any_text = 0;
+const char *search_match_text = 0;
+const char *search_regex_text = 0;
+#ifdef HAVE_REGEX
+/* -S option: the compiled_regex */
+regex_t search_re;
+#endif
+
+
+/* These configure items are for the
+ frame data. We're pretty flexible in
+ the path to dwarfdump.conf .
+*/
+static const char *config_file_path = 0;
+static const char *config_file_abi = 0;
+static char *config_file_defaults[] = {
+ "dwarfdump.conf",
+ "./dwarfdump.conf",
+ "HOME/.dwarfdump.conf",
+ "HOME/dwarfdump.conf",
+#ifdef CONFPREFIX
+/* See Makefile.in "libdir" and CFLAGS */
+/* We need 2 levels of macro to get the name turned into
+ the string we want. */
+#define STR2(s) # s
+#define STR(s) STR2(s)
+ STR(CONFPREFIX)
+ "/dwarfdump.conf",
+#else
+ "/usr/lib/dwarfdump.conf",
+#endif
+ 0
+};
+static struct dwconf_s config_file_data;
+
+char cu_name[BUFSIZ];
+boolean cu_name_flag = FALSE;
+Dwarf_Unsigned cu_offset = 0;
+
+Dwarf_Error err;
+
+static void suppress_check_dwarf()
+{
+ do_print_dwarf = TRUE;
+ if(do_check_dwarf) {
+ fprintf(stderr,"Warning: check flag turned off, "
+ "checking and printing are separate.\n");
+ }
+ do_check_dwarf = FALSE;
+}
+static void suppress_print_dwarf()
+{
+ do_print_dwarf = FALSE;
+ do_check_dwarf = TRUE;
+}
+
+static int process_one_file(Elf * elf, const char * file_name, int archive,
+ struct dwconf_s *conf);
+static int
+open_a_file(const char * name)
+{
+ /* Set to a file number that cannot be legal. */
+ int f = -1;
+
+#if defined(__CYGWIN__) || defined(WIN32)
+ /* It is not possible to share file handles
+ between applications or DLLs. Each application has its own
+ file-handle table. For two applications to use the same file
+ using a DLL, they must both open the file individually.
+ Let the 'libelf' dll to open and close the file. */
+
+ /* For WIN32 open the file as binary */
+ f = elf_open(name, O_RDONLY | O_BINARY);
+#else
+ f = open(name, O_RDONLY);
+#endif
+ return f;
+
+}
+static void
+close_a_file(int f)
+{
+ close(f);
+}
+
+/*
+ Iterate through dwarf and print all info.
+*/
+int
+main(int argc, char *argv[])
+{
+ const char * file_name = 0;
+ int f = 0;
+ Elf_Cmd cmd = 0;
+ Elf *arf = 0;
+ Elf *elf = 0;
+ int archive = 0;
+
+#ifdef WIN32
+ /* Windows specific. */
+ /* Redirect stderr to stdout. */
+ /* Tried to use SetStdHandle, but it does not work properly. */
+ //BOOL bbb = SetStdHandle(STD_ERROR_HANDLE,GetStdHandle(STD_OUTPUT_HANDLE));
+ //_iob[2]._file = _iob[1]._file;
+ stderr->_file = stdout->_file;
+#endif /* WIN32 */
+
+ print_version_details(argv[0],FALSE);
+
+ (void) elf_version(EV_NONE);
+ if (elf_version(EV_CURRENT) == EV_NONE) {
+ (void) fprintf(stderr, "dwarfdump: libelf.a out of date.\n");
+ exit(1);
+ }
+
+ file_name = process_args(argc, argv);
+
+ /* Because LibDwarf now generates some new warnings,
+ allow the user to hide them by using command line options */
+ {
+ Dwarf_Cmdline_Options cmd;
+ cmd.check_verbose_mode = check_verbose_mode;
+ dwarf_record_cmdline_options(cmd);
+ }
+ print_args(argc,argv);
+ f = open_a_file(file_name);
+ if (f == -1) {
+ fprintf(stderr, "%s ERROR: can't open %s\n", program_name,
+ file_name);
+ return (FAILED);
+ }
+
+ cmd = ELF_C_READ;
+ arf = elf_begin(f, cmd, (Elf *) 0);
+ if (elf_kind(arf) == ELF_K_AR) {
+ archive = 1;
+ }
+
+ /* If we are checking .debug_line, .debug_ranges, .debug_aranges,
+ or .debug_loc build the tables containing
+ the pairs LowPC and HighPC. It is safer (and not
+ expensive) to build all
+ of these at once so mistakes in options do not lead
+ to coredumps (like -ka -p did once). */
+ if (check_decl_file || check_ranges || check_locations ||
+ do_check_dwarf || check_self_references) {
+ pRangesInfo = AllocateBucketGroup(KIND_RANGES_INFO);
+ pLinkonceInfo = AllocateBucketGroup(KIND_SECTIONS_INFO);
+ pVisitedInfo = AllocateBucketGroup(KIND_VISITED_INFO);
+ }
+
+ while ((elf = elf_begin(f, cmd, arf)) != 0) {
+ Elf32_Ehdr *eh32;
+
+#ifdef HAVE_ELF64_GETEHDR
+ Elf64_Ehdr *eh64;
+#endif /* HAVE_ELF64_GETEHDR */
+ eh32 = elf32_getehdr(elf);
+ if (!eh32) {
+#ifdef HAVE_ELF64_GETEHDR
+ /* not a 32-bit obj */
+ eh64 = elf64_getehdr(elf);
+ if (!eh64) {
+ /* not a 64-bit obj either! */
+ /* dwarfdump is almost-quiet when not an object */
+ fprintf(stderr, "Can't process %s: unknown format\n",file_name);
+ check_error = 1;
+ } else {
+ process_one_file(elf, file_name, archive,
+ &config_file_data);
+ }
+#endif /* HAVE_ELF64_GETEHDR */
+ } else {
+ process_one_file(elf, file_name, archive,
+ &config_file_data);
+ }
+ cmd = elf_next(elf);
+ elf_end(elf);
+ }
+ elf_end(arf);
+ /* Trivial malloc space cleanup. */
+ clean_up_die_esb();
+ clean_up_syms_malloc_data();
+
+ if(pRangesInfo) {
+ ReleaseBucketGroup(pRangesInfo);
+ pRangesInfo = 0;
+ }
+
+ if(pLinkonceInfo) {
+ ReleaseBucketGroup(pLinkonceInfo);
+ pLinkonceInfo = 0;
+ }
+
+ if(pVisitedInfo) {
+ ReleaseBucketGroup(pVisitedInfo);
+ pVisitedInfo = 0;
+ }
+
+#ifdef HAVE_REGEX
+ if(search_regex_text) {
+ regfree(&search_re);
+ }
+#endif
+ close_a_file(f);
+ if (check_error)
+ return FAILED;
+ else
+ return OKAY;
+}
+
+void
+print_any_harmless_errors(Dwarf_Debug dbg)
+{
+#define LOCAL_PTR_ARY_COUNT 50
+ /* We do not need to initialize the local array,
+ libdwarf does it. */
+ const char *buf[LOCAL_PTR_ARY_COUNT];
+ unsigned totalcount = 0;
+ unsigned i = 0;
+ unsigned printcount = 0;
+ int res = dwarf_get_harmless_error_list(dbg,LOCAL_PTR_ARY_COUNT,buf,
+ &totalcount);
+ if(res == DW_DLV_NO_ENTRY) {
+ return;
+ }
+ if(totalcount > 0) {
+ printf("\n*** HARMLESS ERROR COUNT: %u ***\n",totalcount);
+ }
+ for(i = 0 ; buf[i]; ++i) {
+ ++printcount;
+ DWARF_CHECK_COUNT(harmless_result,1);
+ DWARF_CHECK_ERROR(harmless_result,buf[i]);
+ }
+ if(totalcount > printcount) {
+ //harmless_result.checks += (totalcount - printcount);
+ DWARF_CHECK_COUNT(harmless_result,(totalcount - printcount));
+ //harmless_result.errors += (totalcount - printcount);
+ DWARF_ERROR_COUNT(harmless_result,(totalcount - printcount));
+ }
+}
+
+static void
+print_object_header(Elf *elf,Dwarf_Debug dbg)
+{
+#ifdef WIN32
+ /* Standard libelf has no function generating the names of the
+ encodings, but this libelf apparently does. */
+ Elf_Ehdr_Literal eh_literals;
+ Elf32_Ehdr *eh32;
+#ifdef HAVE_ELF64_GETEHDR
+ Elf64_Ehdr *eh64;
+#endif /* HAVE_ELF64_GETEHDR */
+
+ eh32 = elf32_getehdr(elf);
+ if (eh32) {
+ /* Get literal strings for header fields */
+ elf32_gethdr_literals(eh32,&eh_literals);
+ /* Print 32-bit obj header */
+ printf("\nObject Header:\ne_ident:\n");
+ printf(" File ID = %s\n",eh_literals.e_ident_file_id);
+ printf(" File class = %02x (%s)\n",
+ eh32->e_ident[EI_CLASS], eh_literals.e_ident_file_class);
+ printf(" Data encoding = %02x (%s)\n",
+ eh32->e_ident[EI_DATA], eh_literals.e_ident_data_encoding);
+ printf(" File version = %02x (%s)\n",
+ eh32->e_ident[EI_VERSION], eh_literals.e_ident_file_version);
+ printf(" OS ABI = %02x (%s) (%s)\n", eh32->e_ident[EI_OSABI],
+ eh_literals.e_ident_os_abi_s, eh_literals.e_ident_os_abi_l);
+ //printf(" ABI version = %02x (%s)\n",
+ // eh32->e_ident[EI_ABIVERSION], eh_literals.e_ident_abi_version);
+ printf("e_type : 0x%x (%s)\n",
+ eh32->e_type, eh_literals.e_type);
+ printf("e_machine: 0x%x (%s) (%s)\n", eh32->e_machine,
+ eh_literals.e_machine_s, eh_literals.e_machine_l);
+ printf("e_version: 0x%x\n", eh32->e_version);
+ //printf("e_entry = 0x%I64x\n", eh32->e_entry);
+ printf("e_flags : 0x%x\n", eh32->e_flags);
+ printf("e_phnum : 0x%x\n", eh32->e_phnum);
+ printf("e_shnum : 0x%x\n", eh32->e_shnum);
+ }
+ else {
+#ifdef HAVE_ELF64_GETEHDR
+ /* not a 32-bit obj */
+ eh64 = elf64_getehdr(elf);
+ if (eh64) {
+ /* Get literal strings for header fields */
+ elf64_gethdr_literals(eh64,&eh_literals);
+ /* Print 64-bit obj header */
+ printf("\nObject Header:\ne_ident:\n");
+ printf(" File ID = %s\n",eh_literals.e_ident_file_id);
+ printf(" File class = %02x (%s)\n",
+ eh64->e_ident[EI_CLASS], eh_literals.e_ident_file_class);
+ printf(" Data encoding = %02x (%s)\n",
+ eh64->e_ident[EI_DATA], eh_literals.e_ident_data_encoding);
+ printf(" File version = %02x (%s)\n",
+ eh64->e_ident[EI_VERSION], eh_literals.e_ident_file_version);
+ printf(" OS ABI = %02x (%s) (%s)\n", eh64->e_ident[EI_OSABI],
+ eh_literals.e_ident_os_abi_s, eh_literals.e_ident_os_abi_l);
+ //printf(" ABI version = %02x (%s)\n",
+ // eh64->e_ident[EI_ABIVERSION], eh_literals.e_ident_abi_version);
+ printf("e_type : 0x%x (%s)\n",
+ eh64->e_type, eh_literals.e_type);
+ printf("e_machine: 0x%x (%s) (%s)\n", eh64->e_machine,
+ eh_literals.e_machine_s, eh_literals.e_machine_l);
+ printf("e_version: 0x%x\n", eh64->e_version);
+ //printf("e_entry = 0x%I64x\n", eh64->e_entry);
+ printf("e_flags : 0x%x\n", eh64->e_flags);
+ printf("e_phnum : 0x%x\n", eh64->e_phnum);
+ printf("e_shnum : 0x%x\n", eh64->e_shnum);
+ }
+#endif /* HAVE_ELF64_GETEHDR */
+ }
+#endif /* WIN32 */
+}
+
+/* Print checks and errors for a specific compiler */
+static void
+print_specific_checks_results(Compiler *pCompiler)
+{
+ fprintf(stderr, "\nDWARF CHECK RESULT\n");
+ fprintf(stderr, "<item> <checks> <errors>\n");
+ if (check_pubname_attr) {
+ PRINT_CHECK_RESULT("pubname_attr", pCompiler, pubname_attr_result);
+ }
+ if (check_attr_tag) {
+ PRINT_CHECK_RESULT("attr_tag", pCompiler, attr_tag_result);
+ }
+ if (check_tag_tree) {
+ PRINT_CHECK_RESULT("tag_tree", pCompiler, tag_tree_result);
+ }
+ if (check_type_offset) {
+ PRINT_CHECK_RESULT("type_offset", pCompiler, type_offset_result);
+ }
+ if (check_decl_file) {
+ PRINT_CHECK_RESULT("decl_file", pCompiler, decl_file_result);
+ }
+ if (check_ranges) {
+ PRINT_CHECK_RESULT("ranges", pCompiler, ranges_result);
+ }
+ if (check_lines) {
+ PRINT_CHECK_RESULT("line_table", pCompiler, lines_result);
+ }
+ if (check_fdes) {
+ PRINT_CHECK_RESULT("fde table", pCompiler, fde_duplication);
+ }
+ if (check_aranges) {
+ PRINT_CHECK_RESULT("aranges", pCompiler, aranges_result);
+ }
+
+ if (check_names) {
+ PRINT_CHECK_RESULT("names",pCompiler, names_result);
+ }
+ if (check_frames) {
+ PRINT_CHECK_RESULT("frames",pCompiler, frames_result);
+ }
+ if (check_locations) {
+ PRINT_CHECK_RESULT("locations",pCompiler, locations_result);
+ }
+
+ if(check_harmless) {
+ PRINT_CHECK_RESULT("harmless_errors", pCompiler, harmless_result);
+ }
+
+ if (check_abbreviations) {
+ PRINT_CHECK_RESULT("abbreviations", pCompiler, abbreviations_result);
+ }
+
+ if (check_dwarf_constants) {
+ PRINT_CHECK_RESULT("dwarf_constants",
+ pCompiler, dwarf_constants_result);
+ }
+
+ if (check_di_gaps) {
+ PRINT_CHECK_RESULT("debug_info_gaps", pCompiler, di_gaps_result);
+ }
+
+ if (check_forward_decl) {
+ PRINT_CHECK_RESULT("forward_declarations",
+ pCompiler, forward_decl_result);
+ }
+
+ if (check_self_references) {
+ PRINT_CHECK_RESULT("self_references",
+ pCompiler, self_references_result);
+ }
+
+ PRINT_CHECK_RESULT("** Summarize **",pCompiler, total_check_result);
+}
+
+static int
+qsort_compare_compiler(const void *elem1,const void *elem2)
+{
+ Compiler cmp1 = *(Compiler *)elem1;
+ Compiler cmp2 = *(Compiler *)elem2;
+ int cnt1 = cmp1.results[total_check_result].errors;
+ int cnt2 = cmp2.results[total_check_result].errors;
+ int sc = 0;
+
+ if (cnt1 < cnt2) {
+ return 1;
+ } else if (cnt1 > cnt2) {
+ return -1;
+ }
+ /* When error counts match, sort on name. */
+ sc = strcmp(cmp2.name,cmp1.name);
+ return sc;
+}
+
+/* Print a summary of checks and errors */
+static void
+print_checks_results()
+{
+ int index = 0;
+ Compiler *pCompilers;
+ Compiler *pCompiler;
+
+ fflush(stdout);
+
+ /* Sort based on errors detected; the first entry is reserved */
+ pCompilers = &compilers_detected[1];
+ qsort((void *)pCompilers, compilers_detected_count,
+ sizeof(Compiler),qsort_compare_compiler);
+
+ /* Print list of CUs for each compiler detected */
+ if (producer_children_flag) {
+
+ a_name_chain *nc = 0;
+ a_name_chain *nc_next = 0;
+ int count = 0;
+ int total = 0;
+
+ fprintf(stderr,"\n*** CU NAMES PER COMPILER ***\n");
+ for (index = 1; index <= compilers_detected_count; ++index) {
+ pCompiler = &compilers_detected[index];
+ fprintf(stderr,"\n%02d: %s\n",index,pCompiler->name);
+ count = 0;
+ for (nc = pCompiler->cu_list; nc; nc = nc_next) {
+ fprintf(stderr,"\n %02d: '%s'",++count,nc->item);
+ nc_next = nc->next;
+ free(nc);
+ }
+ total += count;
+ fprintf(stderr,"\n");
+ }
+ fprintf(stderr,"\nDetected %d CU names\n",total);
+ }
+
+ /* Print error report only if errors have been detected */
+ /* Print error report if the -kd option */
+ if ((do_check_dwarf && check_error) || check_show_results) {
+ int count = 0;
+ int compilers_not_detected = 0;
+ int compilers_verified = 0;
+
+ /* Find out how many compilers have been verified. */
+ for (index = 1; index <= compilers_detected_count; ++index) {
+ if (compilers_detected[index].verified) {
+ ++compilers_verified;
+ }
+ }
+ /* Find out how many compilers have been not detected. */
+ for (index = 1; index <= compilers_targeted_count; ++index) {
+ if (!compilers_targeted[index].verified) {
+ ++compilers_not_detected;
+ }
+ }
+
+ /* Print compilers detected list */
+ fprintf(stderr,
+ "\n%d Compilers detected:\n",compilers_detected_count);
+ for (index = 1; index <= compilers_detected_count; ++index) {
+ pCompiler = &compilers_detected[index];
+ fprintf(stderr,"%02d: %s\n",index,pCompiler->name);
+ }
+
+ /* Print compiler list specified by the user with the
+ '-c<str>', that were not detected. */
+ if (compilers_not_detected) {
+ count = 0;
+ fprintf(stderr,
+ "\n%d Compilers not detected:\n",compilers_not_detected);
+ for (index = 1; index <= compilers_targeted_count; ++index) {
+ if (!compilers_targeted[index].verified) {
+ fprintf(stderr,
+ "%02d: '%s'\n",
+ ++count,compilers_targeted[index].name);
+ }
+ }
+ }
+
+ count = 0;
+ fprintf(stderr,"\n%d Compilers verified:\n",compilers_verified);
+ for (index = 1; index <= compilers_detected_count; ++index) {
+ pCompiler = &compilers_detected[index];
+ if (pCompiler->verified) {
+ fprintf(stderr,"%02d: errors = %5d, %s\n",
+ ++count,
+ pCompiler->results[total_check_result].errors,
+ pCompiler->name);
+ }
+ }
+
+ /* Print summary if we have verified compilers or
+ if the -kd option used. */
+ if (compilers_verified || check_show_results) {
+ /* Print compilers detected summary*/
+ if (print_summary_all) {
+ count = 0;
+ fprintf(stderr,"\n*** ERRORS PER COMPILER ***\n");
+ for (index = 1; index <= compilers_detected_count; ++index) {
+ pCompiler = &compilers_detected[index];
+ if (pCompiler->verified) {
+ fprintf(stderr,"%02d: %s\n",
+ ++count,pCompiler->name);
+ print_specific_checks_results(pCompiler);
+ }
+ }
+ }
+
+ /* Print general summary (all compilers checked) */
+ fprintf(stderr,"\n*** TOTAL ERRORS FOR ALL COMPILERS ***\n");
+ print_specific_checks_results(&compilers_detected[0]);
+ }
+ }
+}
+
+/*
+ Given a file which we know is an elf file, process
+ the dwarf data.
+
+*/
+static int
+process_one_file(Elf * elf, const char * file_name, int archive,
+ struct dwconf_s *config_file_data)
+{
+ Dwarf_Debug dbg;
+ int dres;
+
+ dres = dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL, &dbg, &err);
+ if (dres == DW_DLV_NO_ENTRY) {
+ printf("No DWARF information present in %s\n", file_name);
+ return 0;
+ }
+ if (dres != DW_DLV_OK) {
+ print_error(dbg, "dwarf_elf_init", dres, err);
+ }
+
+ if (archive) {
+ Elf_Arhdr *mem_header = elf_getarhdr(elf);
+
+ printf("\narchive member \t%s\n",
+ mem_header ? mem_header->ar_name : "");
+ }
+ dwarf_set_frame_rule_initial_value(dbg,
+ config_file_data->cf_initial_rule_value);
+ dwarf_set_frame_rule_table_size(dbg,
+ config_file_data->cf_table_entry_count);
+ dwarf_set_frame_cfa_value(dbg,
+ config_file_data->cf_cfa_reg);
+ dwarf_set_frame_same_value(dbg,
+ config_file_data->cf_same_val);
+ dwarf_set_frame_undefined_value(dbg,
+ config_file_data->cf_undefined_val);
+ if(config_file_data->cf_address_size) {
+ dwarf_set_default_address_size(dbg, config_file_data->cf_address_size);
+ }
+ dwarf_set_harmless_error_list_size(dbg,50);
+
+
+ /* Get address size and largest representable address */
+ dres = dwarf_get_address_size(dbg,&elf_address_size,&err);
+ if (dres != DW_DLV_OK) {
+ print_error(dbg, "get_location_list", dres, err);
+ }
+
+ elf_max_address = (elf_address_size == 8 ) ?
+ 0xffffffffffffffffULL : 0xffffffff;
+
+ /* Get .text and .debug_ranges info if in check mode */
+ if (do_check_dwarf) {
+ Dwarf_Addr lower = 0;
+ Dwarf_Addr upper = 0;
+ Dwarf_Unsigned size = 0;
+ int res = 0;
+ res = dwarf_get_section_info_by_name(dbg,".text",&lower,&size,&err);
+ if (DW_DLV_OK == res) {
+ upper = lower + size;
+ }
+
+ /* Set limits for Ranges Information */
+ if (pRangesInfo) {
+ SetLimitsBucketGroup(pRangesInfo,lower,upper);
+ }
+
+ /* Build section information */
+ build_linkonce_info(dbg);
+ }
+
+ if (header_flag) {
+ print_object_header(elf,dbg);
+ }
+ reset_overall_CU_error_data();
+ if (info_flag || line_flag || cu_name_flag || search_is_on ||
+ producer_children_flag) {
+ print_infos(dbg,TRUE);
+ reset_overall_CU_error_data();
+ print_infos(dbg,FALSE);
+ }
+ if (pubnames_flag) {
+ reset_overall_CU_error_data();
+ print_pubnames(dbg);
+ }
+ if (macinfo_flag) {
+ reset_overall_CU_error_data();
+ print_macinfo(dbg);
+ }
+ if (loc_flag) {
+ reset_overall_CU_error_data();
+ print_locs(dbg);
+ }
+ if (abbrev_flag) {
+ reset_overall_CU_error_data();
+ print_abbrevs(dbg);
+ }
+ if (string_flag) {
+ reset_overall_CU_error_data();
+ print_strings(dbg);
+ }
+ if (aranges_flag) {
+ reset_overall_CU_error_data();
+ print_aranges(dbg);
+ }
+ if (ranges_flag) {
+ reset_overall_CU_error_data();
+ print_ranges(dbg);
+ }
+ if (frame_flag || eh_frame_flag) {
+ reset_overall_CU_error_data();
+ current_cu_die_for_print_frames = 0;
+ print_frames(dbg, frame_flag, eh_frame_flag, config_file_data);
+ }
+ if (static_func_flag) {
+ reset_overall_CU_error_data();
+ print_static_funcs(dbg);
+ }
+ if (static_var_flag) {
+ reset_overall_CU_error_data();
+ print_static_vars(dbg);
+ }
+ /* DWARF_PUBTYPES is the standard typenames dwarf section.
+ SGI_TYPENAME is the same concept but is SGI specific ( it was
+ defined 10 years before dwarf pubtypes). */
+
+ if (type_flag) {
+ reset_overall_CU_error_data();
+ print_types(dbg, DWARF_PUBTYPES);
+ reset_overall_CU_error_data();
+ print_types(dbg, SGI_TYPENAME);
+ }
+ if (weakname_flag) {
+ reset_overall_CU_error_data();
+ print_weaknames(dbg);
+ }
+ if (reloc_flag) {
+ reset_overall_CU_error_data();
+ print_relocinfo(dbg, reloc_map);
+ }
+ /* The right time to do this is unclear. But we need to do it. */
+ print_any_harmless_errors(dbg);
+
+ /* Print error report only if errors have been detected */
+ /* Print error report if the -kd option */
+ print_checks_results();
+
+ dres = dwarf_finish(dbg, &err);
+ if (dres != DW_DLV_OK) {
+ print_error(dbg, "dwarf_finish", dres, err);
+ }
+
+ printf("\n");
+ fflush(stderr);
+ return 0;
+
+}
+
+/* Do printing of most sections.
+ Do not do detailed checking.
+*/
+static void
+do_all()
+{
+ info_flag = line_flag = frame_flag = TRUE;
+ pubnames_flag = macinfo_flag = TRUE;
+ aranges_flag = TRUE;
+ /* Do not do
+ loc_flag = TRUE
+ abbrev_flag = TRUE;
+ ranges_flag = TRUE;
+ because nothing in
+ the DWARF spec guarantees the sections are free of random bytes
+ in areas not referenced by .debug_info */
+ string_flag = TRUE;
+ /* Do not do
+ reloc_flag = TRUE;
+ as print_relocs makes no sense for non-elf dwarfdump users. */
+ static_func_flag = static_var_flag = TRUE;
+ type_flag = weakname_flag = TRUE;
+ header_flag = TRUE; /* Dump header info */
+}
+
+
+static const char *usage_text[] = {
+"options:\t-a\tprint all .debug_* sections",
+"\t\t-b\tprint abbrev section",
+"\t\t-c\tprint loc section",
+"\t\t-c<str>\tcheck only specific compiler objects",
+"\t\t \t <str> is described by 'DW_AT_producer'. Examples:",
+"\t\t \t -cg check only GCC compiler objects",
+"\t\t \t -cs check only SNC compiler objects",
+"\t\t \t -c'350.1' check only compiler objects with 350.1 in the CU name",
+"\t\t-C\tactivate printing (with -i) of warnings about",
+"\t\t\tcertain common extensions of DWARF.",
+"\t\t-d\tdense: one line per entry (info section only)",
+"\t\t-D\tdo not show offsets", /* Do not show any offsets */
+"\t\t-e\tellipsis: short names for tags, attrs etc.",
+"\t\t-E\tprint object Header information",
+"\t\t-f\tprint dwarf frame section",
+"\t\t-F\tprint gnu .eh_frame section",
+"\t\t-g\t(use incomplete loclist support)",
+"\t\t-G\tshow global die offsets",
+"\t\t-h\tprint IRIX exception tables (unsupported)",
+"\t\t-H <num>\tlimit output to the first <num> major units",
+"\t\t\t example: to stop after <num> compilation units",
+"\t\t-i\tprint info section",
+"\t\t-k[abcdeEfFgilmMnrRsStx[e]y] check dwarf information",
+"\t\t a\tdo all checks",
+"\t\t b\tcheck abbreviations", /* Check abbreviations */
+"\t\t c\texamine DWARF constants", /* Check for valid DWARF constants */
+"\t\t d\tshow check results", /* Show check results */
+"\t\t e\texamine attributes of pubnames",
+"\t\t E\tignore DWARF extensions", /* Ignore DWARF extensions */
+"\t\t f\texamine frame information (use with -f or -F)",
+"\t\t F\texamine integrity of files-lines attributes", /* Files-Lines integrity */
+"\t\t g\tcheck debug info gaps", /* Check for debug info gaps */
+"\t\t i\tdisplay summary for all compilers", /* Summary all compilers */
+"\t\t l\tcheck location list (.debug_loc)", /* Location list integrity */
+"\t\t m\tcheck ranges list (.debug_ranges)", /* Ranges list integrity */
+"\t\t M\tcheck ranges list (.debug_aranges)",/* Aranges list integrity */
+"\t\t n\texamine names in attributes", /* Check for valid names */
+"\t\t r\texamine tag-attr relation",
+"\t\t R\tcheck forward references to DIEs (declarations)", /* Check DW_AT_specification references */
+"\t\t s\tperform checks in silent mode",
+"\t\t S\tcheck self references to DIEs",
+"\t\t t\texamine tag-tag relations",
+"\t\t x\tbasic frames check (.eh_frame, .debug_frame)",
+"\t\t xe\textensive frames check (.eh_frame, .debug_frame)",
+"\t\t y\texamine type info",
+"\t\t\tUnless -C option given certain common tag-attr and tag-tag",
+"\t\t\textensions are assumed to be ok (not reported).",
+"\t\t-l\tprint line section",
+"\t\t-m\tprint macinfo section",
+"\t\t-M\tprint the form name for each attribute",
+"\t\t-n\tsuppress frame information function name lookup",
+"\t\t \t(when printing frame information from multi-gigabyte",
+"\t\t \tobject files this option may save significant time).",
+"\t\t-N\tprint ranges section",
+"\t\t-o[liaprfoR]\tprint relocation info",
+"\t\t \tl=line,i=info,a=abbrev,p=pubnames,r=aranges,f=frames,o=loc,R=Ranges",
+"\t\t-p\tprint pubnames section",
+"\t\t-P\tprint list of compile units per producer", /* List of CUs per compiler */
+"\t\t-Q\tsuppress printing section data",
+"\t\t-r\tprint aranges section",
+"\t\t-R\tPrint frame register names as r33 etc",
+"\t\t \t and allow up to 1200 registers.",
+"\t\t \t Print using a 'generic' register set.",
+"\t\t-s\tprint string section",
+"\t\t-S <option>=<text>\tsearch for <text> in attributes",
+"\t\t \twith <option>:",
+"\t\t \t-S any=<text>\tany <text>",
+"\t\t \t-S match=<text>\tmatching <text>",
+#ifdef HAVE_REGEX
+"\t\t \t-S regex=<text>\tuse regular expression matching",
+#endif
+"\t\t \t (only one -S option allowed, any= and regex= ",
+"\t\t \t only usable if the functions required are ",
+"\t\t \t found at configure time)",
+"\t\t-t[afv] static: ",
+"\t\t a\tprint both sections",
+"\t\t f\tprint static func section",
+"\t\t v\tprint static var section",
+"\t\t-u<file> print sections only for specified file",
+"\t\t-v\tverbose: show more information",
+"\t\t-vv verbose: show even more information",
+"\t\t-V print version information",
+"\t\t-x name=<path>\tname dwarfdump.conf",
+"\t\t-x abi=<abi>\tname abi in dwarfdump.conf",
+"\t\t-w\tprint weakname section",
+"\t\t-W\tprint parent and children tree (wide format) with the -S option",
+"\t\t-Wp\tprint parent tree (wide format) with the -S option",
+"\t\t-Wc\tprint children tree (wide format) with the -S option",
+"\t\t-y\tprint type section",
+"",
+
+0
+};
+
+
+/* Remove matching leading/trailing quotes.
+ Does not alter the passed in string.
+ If quotes removed does a makename on a modified string. */
+static const char *
+remove_quotes_pair(const char *text)
+{
+ static char single_quote = '\'';
+ static char double_quote = '\"';
+ char quote = 0;
+ const char *p = text;
+ int len = strlen(text);
+
+ if (len < 2) {
+ return p;
+ }
+
+ /* Compare first character with ' or " */
+ if (p[0] == single_quote) {
+ quote = single_quote;
+ } else {
+ if (p[0] == double_quote) {
+ quote = double_quote;
+ }
+ else {
+ return p;
+ }
+ }
+ {
+ if (p[len - 1] == quote) {
+ char *altered = calloc(1,len+1);
+ const char *str2 = 0;
+ strcpy(altered,p+1);
+ altered[len - 2] = '\0';
+ str2 = makename(altered);
+ free(altered);
+ return str2;
+ }
+ }
+ return p;
+}
+
+/* process arguments and return object filename */
+static const char *
+process_args(int argc, char *argv[])
+{
+ extern int optind;
+ int c = 0;
+ boolean usage_error = FALSE;
+ int oarg = 0;
+
+ program_name = argv[0];
+
+ suppress_check_dwarf();
+ if (argv[1] != NULL && argv[1][0] != '-') {
+ do_all();
+ }
+
+ /* j unused */
+ while ((c = getopt(argc, argv,
+ "#:abc::CdDeEfFgGhH:ik:lmMnNo::pPqQrRsS:t:u:UvVwW::x:yz")) != EOF) {
+
+ switch (c) {
+ /* Internal debug level setting. */
+ case '#':
+ {
+ int nTraceLevel = atoi(optarg);
+ if (nTraceLevel > 0 && nTraceLevel <= MAX_TRACE_LEVEL) {
+ nTrace[nTraceLevel] = 1;
+ }
+ break;
+ }
+ case 'M':
+ show_form_used = TRUE;
+ break;
+ case 'x': /* Select abi/path to use */
+ {
+ const char *path = 0;
+ const char *abi = 0;
+ /* -x name=<path> meaning name dwarfdump.conf file -x
+ abi=<abi> meaning select abi from dwarfdump.conf
+ file. Must always select abi to use dwarfdump.conf */
+ if (strncmp(optarg, "name=", 5) == 0) {
+ path = do_uri_translation(&optarg[5],"-x name=");
+ if (strlen(path) < 1) {
+ goto badopt;
+ }
+ config_file_path = path;
+ } else if (strncmp(optarg, "abi=", 4) == 0) {
+ abi = do_uri_translation(&optarg[4],"-x abi=");
+ if (strlen(abi) < 1) {
+ goto badopt;
+ }
+ config_file_abi = abi;
+ break;
+ } else {
+ badopt:
+ fprintf(stderr, "-x name=<path-to-conf> \n");
+ fprintf(stderr, " and \n");
+ fprintf(stderr, "-x abi=<abi-in-conf> \n");
+ fprintf(stderr, "are legal, not -x %s\n", optarg);
+ usage_error = TRUE;
+ break;
+ }
+ }
+ break;
+ case 'C':
+ suppress_check_extensions_tables = TRUE;
+ break;
+ case 'g':
+ use_old_dwarf_loclist = TRUE;
+ info_flag = TRUE;
+ suppress_check_dwarf();
+ break;
+ case 'i':
+ info_flag = TRUE;
+ suppress_check_dwarf();
+ break;
+ case 'n':
+ suppress_nested_name_search = TRUE;
+ break;
+ case 'l':
+ line_flag = TRUE;
+ suppress_check_dwarf();
+ break;
+ case 'f':
+ frame_flag = TRUE;
+ suppress_check_dwarf();
+ break;
+ case 'H':
+ {
+ int break_val = atoi(optarg);
+ if(break_val > 0) {
+ break_after_n_units = break_val;
+ }
+ }
+ break;
+ case 'F':
+ eh_frame_flag = TRUE;
+ suppress_check_dwarf();
+ break;
+ case 'b':
+ abbrev_flag = TRUE;
+ suppress_check_dwarf();
+ break;
+ case 'p':
+ pubnames_flag = TRUE;
+ suppress_check_dwarf();
+ break;
+ case 'P':
+ /* List of CUs per compiler */
+ producer_children_flag = TRUE;
+ break;
+ case 'r':
+ aranges_flag = TRUE;
+ suppress_check_dwarf();
+ break;
+ case 'N':
+ ranges_flag = TRUE;
+ suppress_check_dwarf();
+ break;
+ case 'R':
+ generic_1200_regs = TRUE;
+ break;
+ case 'm':
+ macinfo_flag = TRUE;
+ suppress_check_dwarf();
+ break;
+ case 'c':
+ /* Specify compiler name. */
+ if (optarg) {
+ if ('s' == optarg[0]) {
+ /* -cs : Check SNC compiler */
+ check_snc_compiler = TRUE;
+ check_all_compilers = FALSE;
+ }
+ else {
+ if ('g' == optarg[0]) {
+ /* -cg : Check GCC compiler */
+ check_gcc_compiler = TRUE;
+ check_all_compilers = FALSE;
+ }
+ else {
+ /* Assume a compiler version to check,
+ most likely a substring of a compiler name. */
+ if ((compilers_targeted_count+1) < COMPILER_TABLE_MAX) {
+ Compiler *pCompiler = 0;
+ const char *cmp = 0;
+ cmp = do_uri_translation(optarg,"-c<compiler name>");
+ /* First compiler at position [1] */
+ compilers_targeted_count++;
+ pCompiler = &compilers_targeted[compilers_targeted_count];
+ reset_compiler_entry(pCompiler);
+ pCompiler->name = cmp;
+ check_all_compilers = FALSE;
+ } else {
+ fprintf(stderr, "Compiler table max %d exceeded, "
+ "limiting the tracked compilers to %d\n",
+ COMPILER_TABLE_MAX,COMPILER_TABLE_MAX);
+ }
+ }
+ }
+ } else {
+ loc_flag = TRUE;
+ suppress_check_dwarf();
+ }
+ break;
+ case 'Q':
+ /* Q suppresses section data printing. */
+ do_print_dwarf = FALSE;
+ break;
+ case 'q':
+ /* Suppress uri-did-transate notification */
+ do_print_uri_in_input = FALSE;
+ break;
+ case 's':
+ string_flag = TRUE;
+ suppress_check_dwarf();
+ break;
+ case 'S':
+ /* -S option: strings for 'any' and 'match' */
+ {
+ boolean err = TRUE;
+ search_is_on = TRUE;
+ const char *tempstr = 0;
+ /* -S text */
+ if (strncmp(optarg,"match=",6) == 0) {
+
+ search_match_text = makename(&optarg[6]);
+ tempstr = remove_quotes_pair(search_match_text);
+ search_match_text = do_uri_translation(tempstr,"-S match=");
+ if (strlen(search_match_text) > 0) {
+ err = FALSE;
+ }
+ }
+ else {
+ if (strncmp(optarg,"any=",4) == 0) {
+ search_any_text = makename(&optarg[4]);
+ tempstr = remove_quotes_pair(search_any_text);
+ search_any_text = do_uri_translation(tempstr,"-S any=");
+ if (strlen(search_any_text) > 0) {
+ err = FALSE;
+ }
+ }
+#ifdef HAVE_REGEX
+ else {
+ if (strncmp(optarg,"regex=",6) == 0) {
+ search_regex_text = makename(&optarg[6]);
+ tempstr = remove_quotes_pair(
+ search_regex_text);
+ search_regex_text = do_uri_translation(tempstr,
+ "-S regex=");
+ if (strlen(search_regex_text) > 0) {
+ if (regcomp(&search_re,search_regex_text,
+ REG_EXTENDED)) {
+ fprintf(stderr,
+ "regcomp: unable to compile %s\n",
+ search_regex_text);
+ }
+ else {
+ err = FALSE;
+ }
+ }
+ }
+ }
+#endif /* HAVE_REGEX */
+ }
+ if (err) {
+ fprintf(stderr,"-S any=<text> or -S match=<text> or -S regex=<text>\n");
+ fprintf(stderr, "is allowed, not -S %s\n",optarg);
+ usage_error = TRUE;
+ }
+ }
+ break;
+
+ case 'a':
+ suppress_check_dwarf();
+ do_all();
+ break;
+ case 'v':
+ verbose++;
+ break;
+ case 'V':
+ /* Display dwarfdump compilation date and time */
+ print_version_details(argv[0],TRUE);
+ exit(OKAY);
+ break;
+ case 'd':
+ /* This is sort of useless unless printing,
+ but harmless, so we do not insist we
+ are printing with suppress_check_dwarf(). */
+ dense = TRUE;
+ break;
+ case 'D':
+ /* Do not emit offset in output */
+ display_offsets = FALSE;
+ break;
+ case 'e':
+ suppress_check_dwarf();
+ ellipsis = TRUE;
+ break;
+ case 'E':
+ /* Object Header information (but maybe really print) */
+ header_flag = TRUE;
+ break;
+ case 'o':
+ reloc_flag = TRUE;
+ if (optarg) {
+ switch (optarg[0]) {
+ case 'i':
+ reloc_map |= (1 << DW_SECTION_REL_DEBUG_INFO); break;
+ reloc_map |= (1 << DW_SECTION_REL_DEBUG_TYPES); break;
+ case 'l': reloc_map |= (1 << DW_SECTION_REL_DEBUG_LINE); break;
+ case 'p': reloc_map |= (1 << DW_SECTION_REL_DEBUG_PUBNAMES); break;
+ /* Case a has no effect, no relocations can point out
+ of the abbrev section. */
+ case 'a': reloc_map |= (1 << DW_SECTION_REL_DEBUG_ABBREV); break;
+ case 'r': reloc_map |= (1 << DW_SECTION_REL_DEBUG_ARANGES); break;
+ case 'f': reloc_map |= (1 << DW_SECTION_REL_DEBUG_FRAME); break;
+ case 'o': reloc_map |= (1 << DW_SECTION_REL_DEBUG_LOC); break;
+ case 'R': reloc_map |= (1 << DW_SECTION_REL_DEBUG_RANGES); break;
+ default: usage_error = TRUE; break;
+ }
+ } else {
+ /* Display all relocs */
+ reloc_map = 0x00ff;
+ }
+ break;
+ case 'k':
+ suppress_print_dwarf();
+ oarg = optarg[0];
+ switch (oarg) {
+ case 'a':
+ check_pubname_attr = TRUE;
+ check_attr_tag = TRUE;
+ check_tag_tree = check_type_offset = TRUE;
+ check_names = TRUE;
+ pubnames_flag = info_flag = TRUE;
+ check_decl_file = TRUE;
+ check_frames = TRUE;
+ /*check_frames_extended = FALSE; */
+ check_locations = TRUE;
+ frame_flag = eh_frame_flag = TRUE;
+ check_ranges = TRUE;
+ check_lines = TRUE;
+ check_fdes = TRUE;
+ check_harmless = TRUE;
+ check_aranges = TRUE;
+ aranges_flag = TRUE; /* Aranges section */
+ check_abbreviations = TRUE;
+ check_dwarf_constants = TRUE;
+ check_di_gaps = TRUE; /* Check debug info gaps */
+ check_forward_decl = TRUE; /* Check forward declarations */
+ check_self_references = TRUE; /* Check self references */
+ break;
+ /* Abbreviations */
+ case 'b':
+ check_abbreviations = TRUE;
+ info_flag = TRUE;
+ break;
+ /* DWARF constants */
+ case 'c':
+ check_dwarf_constants = TRUE;
+ info_flag = TRUE;
+ break;
+ /* Display check results */
+ case 'd':
+ check_show_results = TRUE;
+ break;
+ case 'e':
+ check_pubname_attr = TRUE;
+ pubnames_flag = TRUE;
+ check_harmless = TRUE;
+ check_fdes = TRUE;
+ break;
+ case 'f':
+ check_harmless = TRUE;
+ check_fdes = TRUE;
+ break;
+ /* files-lines */
+ case 'F':
+ check_decl_file = TRUE;
+ check_lines = TRUE;
+ info_flag = TRUE;
+ break;
+ /* Check debug info gaps */
+ case 'g':
+ check_di_gaps = TRUE;
+ info_flag = TRUE;
+ break;
+ /* Locations list */
+ case 'l':
+ check_locations = TRUE;
+ info_flag = TRUE;
+ loc_flag = TRUE;
+ break;
+ /* Ranges */
+ case 'm':
+ check_ranges = TRUE;
+ info_flag = TRUE;
+ break;
+ /* Aranges */
+ case 'M':
+ check_aranges = TRUE;
+ aranges_flag = TRUE;
+ break;
+ /* invalid names */
+ case 'n':
+ check_names = TRUE;
+ info_flag = TRUE;
+ break;
+ case 'r':
+ check_attr_tag = TRUE;
+ info_flag = TRUE;
+ check_harmless = TRUE;
+ break;
+ /* forward declarations in DW_AT_specification */
+ case 'R':
+ check_forward_decl = TRUE;
+ info_flag = TRUE;
+ break;
+ /* Check verbose mode */
+ case 's':
+ check_verbose_mode = FALSE;
+ break;
+ /* self references in:
+ DW_AT_specification, DW_AT_type, DW_AT_abstract_origin */
+ case 'S':
+ check_self_references = TRUE;
+ info_flag = TRUE;
+ break;
+ case 't':
+ check_tag_tree = TRUE;
+ check_harmless = TRUE;
+ info_flag = TRUE;
+ break;
+ case 'y':
+ check_type_offset = TRUE;
+ check_harmless = TRUE;
+ check_decl_file = TRUE;
+ info_flag = TRUE;
+ check_ranges = TRUE;
+ check_aranges = TRUE;
+ break;
+ /* Summary for each compiler */
+ case 'i':
+ print_summary_all = TRUE;
+ break;
+ /* Frames check */
+ case 'x':
+ check_frames = TRUE;
+ frame_flag = TRUE;
+ eh_frame_flag = TRUE;
+ if (optarg[1]) {
+ if ('e' == optarg[1]) {
+ /* -xe : Extended frames check */
+ check_frames = FALSE;
+ check_frames_extended = TRUE;
+ } else {
+ usage_error = TRUE;
+ }
+ }
+ break;
+ default:
+ usage_error = TRUE;
+ break;
+ }
+ break;
+ case 'u': { /* compile unit */
+ const char *tstr = 0;
+ cu_name_flag = TRUE;
+ tstr = do_uri_translation(optarg,"-u<cu name>");
+ safe_strcpy(cu_name,sizeof(cu_name), tstr,strlen(tstr));
+ }
+ break;
+ case 'U':
+ uri_options_translation = FALSE;
+ break;
+ case 't':
+ oarg = optarg[0];
+ switch (oarg) {
+ case 'a':
+ /* all */
+ static_func_flag = static_var_flag = TRUE;
+ suppress_check_dwarf();
+ break;
+ case 'f':
+ /* .debug_static_func */
+ static_func_flag = TRUE;
+ suppress_check_dwarf();
+ break;
+ case 'v':
+ /* .debug_static_var */
+ static_var_flag = TRUE;
+ suppress_check_dwarf();
+ break;
+ default:
+ usage_error = TRUE;
+ break;
+ }
+ break;
+ case 'y': /* .debug_types */
+ suppress_check_dwarf();
+ type_flag = TRUE;
+ break;
+ case 'w': /* .debug_weaknames */
+ weakname_flag = TRUE;
+ suppress_check_dwarf();
+ break;
+ case 'z':
+ fprintf(stderr, "-z is no longer supported:ignored\n");
+ break;
+ case 'G':
+ show_global_offsets = TRUE;
+ break;
+ case 'W':
+ /* Search results in wide format */
+ search_wide_format = TRUE;
+ if (optarg) {
+ if ('c' == optarg[0]) {
+ /* -Wc : Display children tree */
+ display_children_tree = TRUE;
+ } else {
+ if ('p' == optarg[0]) {
+ /* -Wp : Display parent tree */
+ display_parent_tree = TRUE;
+ } else {
+ usage_error = TRUE;
+ }
+ }
+ }
+ else {
+ /* -W : Display parent and children tree */
+ display_children_tree = TRUE;
+ display_parent_tree = TRUE;
+ }
+ break;
+ default:
+ usage_error = TRUE;
+ break;
+ }
+ }
+
+ init_conf_file_data(&config_file_data);
+ if (config_file_abi && generic_1200_regs) {
+ printf("Specifying both -R and -x abi= is not allowed. Use one "
+ "or the other. -x abi= ignored.\n");
+ config_file_abi = FALSE;
+ }
+ if(generic_1200_regs) {
+ init_generic_config_1200_regs(&config_file_data);
+ }
+ if (config_file_abi && (frame_flag || eh_frame_flag)) {
+ int res = find_conf_file_and_read_config(config_file_path,
+ config_file_abi,
+ config_file_defaults,
+ &config_file_data);
+
+ if (res > 0) {
+ printf
+ ("Frame not configured due to error(s). Giving up.\n");
+ eh_frame_flag = FALSE;
+ frame_flag = FALSE;
+ }
+ }
+ if (usage_error || (optind != (argc - 1))) {
+ print_usage_message(program_name,usage_text);
+ exit(FAILED);
+ }
+
+ if (do_check_dwarf) {
+ /* Reduce verbosity when checking (checking means checking-only). */
+ verbose = 1;
+ }
+ return do_uri_translation(argv[optind],"file-to-process");
+}
+
+
+void
+print_error(Dwarf_Debug dbg, string msg, int dwarf_code,
+ Dwarf_Error err)
+{
+ print_error_and_continue(dbg,msg,dwarf_code,err);
+ dwarf_finish(dbg, &err);
+ exit(FAILED);
+}
+/* ARGSUSED */
+void
+print_error_and_continue(Dwarf_Debug dbg, string msg, int dwarf_code,
+ Dwarf_Error err)
+{
+ fflush(stdout);
+ fflush(stderr);
+
+ fprintf(stderr,"\n");
+
+ if (dwarf_code == DW_DLV_ERROR) {
+ string errmsg = dwarf_errmsg(err);
+ Dwarf_Unsigned myerr = dwarf_errno(err);
+
+ fprintf(stderr, "%s ERROR: %s: %s (%lu)\n",
+ program_name, msg, errmsg, (unsigned long) myerr);
+ } else if (dwarf_code == DW_DLV_NO_ENTRY) {
+ fprintf(stderr, "%s NO ENTRY: %s: \n", program_name, msg);
+ } else if (dwarf_code == DW_DLV_OK) {
+ fprintf(stderr, "%s: %s \n", program_name, msg);
+ } else {
+ fprintf(stderr, "%s InternalError: %s: code %d\n",
+ program_name, msg, dwarf_code);
+ }
+ fflush(stderr);
+
+ /* Display compile unit name */
+ PRINT_CU_INFO();
+}
+
+/* Predicate function. Returns 'true' if the CU should
+ be skipped as the DW_AT_name of the CU
+ does not match the command-line-supplied
+ cu name. Else returns false.*/
+boolean
+should_skip_this_cu(Dwarf_Debug dbg, Dwarf_Die cu_die, Dwarf_Error err)
+{
+ Dwarf_Half tag = 0;
+ Dwarf_Attribute attrib = 0;
+ Dwarf_Half theform = 0;
+ int dares = 0;
+ int tres = 0;
+ int fres = 0;
+
+ tres = dwarf_tag(cu_die, &tag, &err);
+ if (tres != DW_DLV_OK) {
+ print_error(dbg, "dwarf_tag in aranges",
+ tres, err);
+ }
+ dares = dwarf_attr(cu_die, DW_AT_name, &attrib,
+ &err);
+ if (dares != DW_DLV_OK) {
+ print_error(dbg, "dwarf_attr arange"
+ " derived die has no name",
+ dares, err);
+ }
+ fres = dwarf_whatform(attrib, &theform, &err);
+ if (fres == DW_DLV_OK) {
+ if (theform == DW_FORM_string
+ || theform == DW_FORM_strp) {
+ char * temps = 0;
+ int sres = dwarf_formstring(attrib, &temps,
+ &err);
+ if (sres == DW_DLV_OK) {
+ char *p = temps;
+ if (cu_name[0] != '/') {
+ p = strrchr(temps, '/');
+ if (p == NULL) {
+ p = temps;
+ } else {
+ p++;
+ }
+ }
+ /* Ignore case if Windows */
+#if WIN32
+ if (stricmp(cu_name, p)) {
+ // skip this cu.
+ return TRUE;
+ }
+#else
+ if (strcmp(cu_name, p)) {
+ // skip this cu.
+ return TRUE;
+ }
+#endif /* WIN32 */
+
+ } else {
+ print_error(dbg,
+ "arange: string missing",
+ sres, err);
+ }
+ }
+ } else {
+ print_error(dbg,
+ "dwarf_whatform unexpected value",
+ fres, err);
+ }
+ dwarf_dealloc(dbg, attrib, DW_DLA_ATTR);
+ return FALSE;
+}
+
+/* Returns the DW_AT_name of the CU */
+string
+old_get_cu_name(Dwarf_Debug dbg, Dwarf_Die cu_die, Dwarf_Error err)
+{
+ static struct esb_s esb_attr_name;
+ Dwarf_Half tag;
+ Dwarf_Attribute attrib;
+ Dwarf_Half theform;
+ int dares;
+ int tres;
+ int fres;
+
+ /* Initialize flexible string buffer */
+ esb_empty_string(&esb_attr_name);
+
+ tres = dwarf_tag(cu_die, &tag, &err);
+ if (tres != DW_DLV_OK) {
+ print_error(dbg, "dwarf_tag in aranges",
+ tres, err);
+ }
+ dares = dwarf_attr(cu_die, DW_AT_name, &attrib,
+ &err);
+ if (dares != DW_DLV_OK) {
+ print_error(dbg, "dwarf_attr arange"
+ " derived die has no name",
+ dares, err);
+ }
+ fres = dwarf_whatform(attrib, &theform, &err);
+ if (fres == DW_DLV_OK) {
+ if (theform == DW_FORM_string
+ || theform == DW_FORM_strp) {
+ char * temps = 0;
+ int sres = dwarf_formstring(attrib, &temps,
+ &err);
+ if (sres == DW_DLV_OK) {
+ char *p = temps;
+ if (cu_name[0] != '/') {
+ p = strrchr(temps, '/');
+ if (p == NULL) {
+ p = temps;
+ } else {
+ p++;
+ }
+ }
+ esb_append(&esb_attr_name,p);
+ } else {
+ print_error(dbg,
+ "arange: string missing",
+ sres, err);
+ }
+ }
+ } else {
+ print_error(dbg,
+ "dwarf_whatform unexpected value",
+ fres, err);
+ }
+ dwarf_dealloc(dbg, attrib, DW_DLA_ATTR);
+
+ /* Return the esb internal string */
+ return esb_get_string(&esb_attr_name);
+}
+
+/* Returns the cu of the CU */
+int get_cu_name(Dwarf_Debug dbg, Dwarf_Die cu_die,
+ Dwarf_Error err, string *short_name, string *long_name)
+{
+ Dwarf_Attribute name_attr = 0;
+ int ares;
+
+ ares = dwarf_attr(cu_die, DW_AT_name, &name_attr, &err);
+ if (ares == DW_DLV_ERROR) {
+ print_error(dbg, "hassattr on DW_AT_name", ares, err);
+ } else {
+ if (ares == DW_DLV_NO_ENTRY) {
+ *short_name = "<unknown name>";
+ *long_name = "<unknown name>";
+ } else {
+ /* DW_DLV_OK */
+ /* The string return is valid until the next call to this
+ function; so if the caller needs to keep the returned
+ string, the string must be copied (makename()). */
+ static struct esb_s esb_short_name;
+ static struct esb_s esb_long_name;
+ char *filename;
+ esb_empty_string(&esb_long_name);
+ get_attr_value(dbg, DW_TAG_compile_unit,
+ cu_die, name_attr, NULL, 0, &esb_long_name,
+ 0 /*show_form_used*/,0 /* verbose */);
+ *long_name = esb_get_string(&esb_long_name);
+ /* Generate the short name (filename) */
+ filename = strrchr(*long_name,'/');
+ if (!filename) {
+ filename = strrchr(*long_name,'\\');
+ }
+ if (filename) {
+ ++filename;
+ } else {
+ filename = *long_name;
+ }
+ esb_empty_string(&esb_short_name);
+ esb_append(&esb_short_name,filename);
+ *short_name = esb_get_string(&esb_short_name);
+ }
+ }
+
+ dwarf_dealloc(dbg, name_attr, DW_DLA_ATTR);
+ return ares;
+}
+
+/* Returns the producer of the CU */
+int get_producer_name(Dwarf_Debug dbg, Dwarf_Die cu_die,
+ Dwarf_Error err, string *producer_name)
+{
+ Dwarf_Attribute producer_attr = 0;
+ int ares;
+
+ ares = dwarf_attr(cu_die, DW_AT_producer, &producer_attr, &err);
+ if (ares == DW_DLV_ERROR) {
+ print_error(dbg, "hassattr on DW_AT_producer", ares, err);
+ } else {
+ if (ares == DW_DLV_NO_ENTRY) {
+ /* We add extra quotes so it looks more like
+ the names for real producers that get_attr_value
+ produces. */
+ *producer_name = "\"<CU-missing-DW_AT_producer>\"";
+ } else {
+ /* DW_DLV_OK */
+ /* The string return is valid until the next call to this
+ function; so if the caller needs to keep the returned
+ string, the string must be copied (makename()). */
+ static struct esb_s esb_producer;
+ esb_empty_string(&esb_producer);
+ get_attr_value(dbg, DW_TAG_compile_unit,
+ cu_die, producer_attr, NULL, 0, &esb_producer,
+ 0 /*show_form_used*/,0 /* verbose */);
+ *producer_name = esb_get_string(&esb_producer);
+ }
+ }
+
+ dwarf_dealloc(dbg, producer_attr, DW_DLA_ATTR);
+ return ares;
+}
+
+/* GCC linkonce names */
+char *lo_text = ".text."; /*".gnu.linkonce.t.";*/
+char *lo_debug_abbr = ".gnu.linkonce.wa.";
+char *lo_debug_aranges = ".gnu.linkonce.wr.";
+char *lo_debug_frame_1 = ".gnu.linkonce.wf.";
+char *lo_debug_frame_2 = ".gnu.linkonce.wF.";
+char *lo_debug_info = ".gnu.linkonce.wi.";
+char *lo_debug_line = ".gnu.linkonce.wl.";
+char *lo_debug_macinfo = ".gnu.linkonce.wm.";
+char *lo_debug_loc = ".gnu.linkonce.wo.";
+char *lo_debug_pubnames = ".gnu.linkonce.wp.";
+char *lo_debug_ranges = ".gnu.linkonce.wR.";
+char *lo_debug_str = ".gnu.linkonce.ws.";
+
+/* SNC compiler/linker linkonce names */
+char *nlo_text = ".text.";
+char *nlo_debug_abbr = ".debug.wa.";
+char *nlo_debug_aranges = ".debug.wr.";
+char *nlo_debug_frame_1 = ".debug.wf.";
+char *nlo_debug_frame_2 = ".debug.wF.";
+char *nlo_debug_info = ".debug.wi.";
+char *nlo_debug_line = ".debug.wl.";
+char *nlo_debug_macinfo = ".debug.wm.";
+char *nlo_debug_loc = ".debug.wo.";
+char *nlo_debug_pubnames = ".debug.wp.";
+char *nlo_debug_ranges = ".debug.wR.";
+char *nlo_debug_str = ".debug.ws.";
+
+/* Build linkonce section information */
+void
+build_linkonce_info(Dwarf_Debug dbg)
+{
+ int nCount = 0;
+ int section_index = 0;
+ int res = 0;
+
+ static char **linkonce_names[] = {
+ &lo_text, /* .text */
+ &nlo_text, /* .text */
+ &lo_debug_abbr, /* .debug_abbr */
+ &nlo_debug_abbr, /* .debug_abbr */
+ &lo_debug_aranges, /* .debug_aranges */
+ &nlo_debug_aranges, /* .debug_aranges */
+ &lo_debug_frame_1, /* .debug_frame */
+ &nlo_debug_frame_1, /* .debug_frame */
+ &lo_debug_frame_2, /* .debug_frame */
+ &nlo_debug_frame_2, /* .debug_frame */
+ &lo_debug_info, /* .debug_info */
+ &nlo_debug_info, /* .debug_info */
+ &lo_debug_line, /* .debug_line */
+ &nlo_debug_line, /* .debug_line */
+ &lo_debug_macinfo, /* .debug_macinfo */
+ &nlo_debug_macinfo, /* .debug_macinfo */
+ &lo_debug_loc, /* .debug_loc */
+ &nlo_debug_loc, /* .debug_loc */
+ &lo_debug_pubnames, /* .debug_pubnames */
+ &nlo_debug_pubnames, /* .debug_pubnames */
+ &lo_debug_ranges, /* .debug_ranges */
+ &nlo_debug_ranges, /* .debug_ranges */
+ &lo_debug_str, /* .debug_str */
+ &nlo_debug_str, /* .debug_str */
+ NULL
+ };
+
+ const char *section_name = NULL;
+ Dwarf_Addr section_addr = 0;
+ Dwarf_Unsigned section_size = 0;
+ Dwarf_Error error = 0;
+ int nIndex = 0;
+
+ nCount = dwarf_get_section_count(dbg);
+
+ /* Ignore section with index=0 */
+ for (section_index = 1; section_index < nCount; ++section_index) {
+ res = dwarf_get_section_info_by_index(dbg,section_index,
+ &section_name,
+ &section_addr,
+ &section_size,
+ &error);
+
+ if (res == DW_DLV_OK) {
+ for (nIndex = 0; linkonce_names[nIndex]; ++nIndex) {
+ if (section_name == strstr(section_name,
+ *linkonce_names[nIndex])) {
+
+ /* Insert only linkonce sections */
+ AddEntryIntoBucketGroup(pLinkonceInfo,
+ section_index,
+ section_addr,section_addr,
+ section_addr + section_size,
+ section_name,
+ TRUE);
+ break;
+ }
+ }
+ }
+ }
+
+ if (dump_linkonce_info) {
+ PrintBucketGroup(pLinkonceInfo,TRUE);
+ }
+}
+
+/* Check for specific TAGs and initialize some
+ information used by '-k' options */
+void
+tag_specific_checks_setup(Dwarf_Half val,int die_indent_level)
+{
+ switch (val) {
+ case DW_TAG_compile_unit:
+ /* To help getting the compile unit name */
+ seen_CU = TRUE;
+ /* If we are checking line information, build
+ the table containing the pairs LowPC and HighPC */
+ if (check_decl_file || check_ranges || check_locations) {
+ ResetBucketGroup(pRangesInfo);
+ }
+ /* The following flag indicate that only low_pc and high_pc
+ values found in DW_TAG_subprograms are going to be considered when
+ building the address table used to check ranges, lines, etc */
+ need_PU_valid_code = TRUE;
+ break;
+
+ case DW_TAG_subprogram:
+ /* Keep track of a PU */
+ if (die_indent_level == 1) {
+ /* A DW_TAG_subprogram can be nested, when is used to
+ declare a member function for a local class; process the DIE
+ only if we are at level zero in the DIEs tree */
+ seen_PU = TRUE;
+ seen_PU_base_address = FALSE;
+ seen_PU_high_address = FALSE;
+ PU_name[0] = 0;
+ need_PU_valid_code = TRUE;
+ }
+ break;
+ }
+}
+
+/* Indicates if the current CU is a target */
+static boolean current_cu_is_checked_compiler = TRUE;
+
+/* Are we checking for errors from the
+ compiler of the current compilation unit?
+*/
+boolean
+checking_this_compiler()
+{
+ /* This flag has been update by 'update_compiler_target()'
+ and indicates if the current CU is in a targeted compiler
+ specified by the user. Default value is TRUE, which
+ means test all compilers until a CU is detected. */
+ return current_cu_is_checked_compiler || check_all_compilers;
+}
+
+static int
+hasprefix(const char *sample, const char *prefix)
+{
+ unsigned prelen = strlen(prefix);
+ if ( strncmp(sample,prefix,prelen) == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* Record which compiler was used (or notice we saw
+ it before) and set a couple variables as
+ a side effect (which are used all over):
+ current_cu_is_checked_compiler (used in checking_this_compiler() )
+ current_compiler
+ The compiler name is from DW_AT_producer.
+*/
+void
+update_compiler_target(const char *producer_name)
+{
+ Dwarf_Bool cFound = FALSE;
+ int index = 0;
+
+ safe_strcpy(CU_producer,sizeof(CU_producer),producer_name,
+ strlen(producer_name));
+ current_cu_is_checked_compiler = FALSE;
+
+ /* This list of compilers is just a start:
+ GCC id : "GNU"
+ SNC id : "SN Systems" */
+
+ /* Find a compiler version to check */
+ if (compilers_targeted_count) {
+ for (index = 1; index <= compilers_targeted_count; ++index) {
+ if (is_strstrnocase(CU_producer,compilers_targeted[index].name)) {
+ compilers_targeted[index].verified = TRUE;
+ current_cu_is_checked_compiler = TRUE;
+ break;
+ }
+ }
+ } else {
+ /* Take into account that internally all strings are double quoted */
+ boolean snc_compiler = hasprefix(CU_producer,"\"SN")? TRUE : FALSE;
+ boolean gcc_compiler = hasprefix(CU_producer,"\"GNU")?TRUE : FALSE;
+ current_cu_is_checked_compiler = check_all_compilers ||
+ (snc_compiler && check_snc_compiler) ||
+ (gcc_compiler && check_gcc_compiler) ;
+ }
+
+ /* Check for already detected compiler */
+ for (index = 1; index <= compilers_detected_count; ++index) {
+ if (
+#if WIN32
+ !stricmp(compilers_detected[index].name,CU_producer)
+#else
+ !strcmp(compilers_detected[index].name,CU_producer)
+#endif
+ ) {
+ /* Set current compiler index */
+ current_compiler = index;
+ cFound = TRUE;
+ break;
+ }
+ }
+ if (!cFound) {
+ /* Record a new detected compiler name. */
+ if (compilers_detected_count + 1 < COMPILER_TABLE_MAX) {
+ Compiler *pCompiler = 0;
+ char *cmp = makename(CU_producer);
+ /* Set current compiler index, first compiler at position [1] */
+ current_compiler = ++compilers_detected_count;
+ pCompiler = &compilers_detected[current_compiler];
+ reset_compiler_entry(pCompiler);
+ pCompiler->name = cmp;
+ }
+ }
+}
+
+/* Add a CU name to the current compiler entry, specified by the
+ 'current_compiler'; the name is added to the 'compilers_detected'
+ table and is printed if the '-P' option is specified in the
+ command line. */
+void
+add_cu_name_compiler_target(char *name)
+{
+ a_name_chain *cu_last = 0;
+ a_name_chain *nc = 0;
+ Compiler *pCompiler = 0;
+
+ if (current_compiler < 1) {
+ fprintf(stderr,"Current compiler set to %d, cannot add "
+ "Compilation unit name. Giving up.",current_compiler);
+ exit(1);
+ }
+ pCompiler = &compilers_detected[current_compiler];
+ cu_last = pCompiler->cu_last;
+ /* Record current cu name */
+ nc = (a_name_chain *)malloc(sizeof(a_name_chain));
+ nc->item = makename(name);
+ nc->next = NULL;
+ if (cu_last) {
+ cu_last->next = nc;
+ } else {
+ pCompiler->cu_list = nc;
+ }
+ pCompiler->cu_last = nc;
+}
+
+/* Reset a compiler entry, so all fields are properly set */
+static void
+reset_compiler_entry(Compiler *compiler)
+{
+ memset(compiler,0,sizeof(Compiler));
+}
+
+/* Making this a named string makes it simpler to change
+ what the reset,or 'I do not know' value is for
+ CU name or producer name for PRINT_CU_INFO. */
+static const char * default_cu_producer = "<unknown>";
+static void
+reset_overall_CU_error_data()
+{
+ strcpy(CU_name,default_cu_producer);
+ strcpy(CU_producer,default_cu_producer);
+ DIE_offset = 0;
+ DIE_overall_offset = 0;
+ DIE_CU_offset = 0;
+ DIE_CU_overall_offset = 0;
+ CU_base_address = 0;
+ CU_high_address = 0;
+}
+
+
+static boolean
+cu_data_is_set()
+{
+ if(strcmp(CU_name,default_cu_producer) ||
+ strcmp(CU_producer,default_cu_producer)) {
+ return 1;
+ }
+ if(DIE_offset || DIE_overall_offset) {
+ return 1;
+ }
+ if(CU_base_address || CU_high_address) {
+ return 1;
+ }
+ return 0;
+}
+/* Print CU basic information */
+void PRINT_CU_INFO()
+{
+ if (current_section_id == DEBUG_LINE ||
+ current_section_id == DEBUG_ARANGES) {
+ /* Only in the DEBUG_LINE/ARANGES case is DIE_CU_offset or
+ DIE_CU_overall_offset what we want to print here.
+ In other cases DIE_CU_offset is not really a CU
+ offset at all. */
+ DIE_offset = DIE_CU_offset;
+ DIE_overall_offset = DIE_CU_overall_offset;
+ }
+ if(!cu_data_is_set()) {
+ return;
+ }
+ printf("\n");
+ printf("CU Name = %s\n",CU_name);
+ printf("CU Producer = %s\n",CU_producer);
+ printf("DIE OFF = 0x%08" DW_PR_DUx
+ " GOFF = 0x%08" DW_PR_DUx ,DIE_offset,DIE_overall_offset);
+ printf(", Low PC = 0x%08" DW_PR_DUx ", High PC = 0x%08" DW_PR_DUx ,
+ CU_base_address,CU_high_address);
+ printf("\n");
+ fflush(stdout);
+}
+
+void DWARF_CHECK_COUNT(Dwarf_Check_Categories category, int inc)
+{
+ compilers_detected[0].results[category].checks += inc;
+ compilers_detected[0].results[total_check_result].checks += inc;
+ if(current_compiler > 0 && current_compiler < COMPILER_TABLE_MAX) {
+ compilers_detected[current_compiler].results[category].checks += inc;
+ compilers_detected[current_compiler].results[total_check_result].checks
+ += inc;
+ compilers_detected[current_compiler].verified = TRUE;
+ }
+}
+
+void DWARF_ERROR_COUNT(Dwarf_Check_Categories category, int inc)
+{
+ compilers_detected[0].results[category].errors += inc;
+ compilers_detected[0].results[total_check_result].errors += inc;
+ if(current_compiler > 0 && current_compiler < COMPILER_TABLE_MAX) {
+ compilers_detected[current_compiler].results[category].errors += inc;
+ compilers_detected[current_compiler].results[total_check_result].errors
+ += inc;
+ }
+}
+
+void PRINT_CHECK_RESULT(char *str,
+ Compiler *pCompiler, Dwarf_Check_Categories category)
+{
+ Dwarf_Check_Result result = pCompiler->results[category];
+ fprintf(stderr, "%-24s%10d %10d\n", str, result.checks, result.errors);
+}
+
+void DWARF_CHECK_ERROR_PRINT_CU()
+{
+ if (check_verbose_mode) {
+ PRINT_CU_INFO();
+ }
+ check_error++;
+ record_dwarf_error = TRUE;
+}
+
+void DWARF_CHECK_ERROR(Dwarf_Check_Categories category,
+ const char *str)
+{
+ if (checking_this_compiler()) {
+ DWARF_ERROR_COUNT(category,1);
+ if (check_verbose_mode) {
+ printf("\n*** DWARF CHECK: %s ***\n", str);
+ }
+ DWARF_CHECK_ERROR_PRINT_CU();
+ }
+}
+
+void DWARF_CHECK_ERROR2(Dwarf_Check_Categories category,
+ const char *str1, const char *str2)
+{
+ if (checking_this_compiler()) {
+ DWARF_ERROR_COUNT(category,1);
+ if (check_verbose_mode) {
+ printf("\n*** DWARF CHECK: %s: %s ***\n", str1, str2);
+ }
+ DWARF_CHECK_ERROR_PRINT_CU();
+ }
+}
+
+void DWARF_CHECK_ERROR3(Dwarf_Check_Categories category,
+ const char *str1, const char *str2, const char *strexpl)
+{
+ if (checking_this_compiler()) {
+ DWARF_ERROR_COUNT(category,1);
+ if (check_verbose_mode) {
+ printf("\n*** DWARF CHECK: %s -> %s: %s ***\n",
+ str1, str2,strexpl);
+ }
+ DWARF_CHECK_ERROR_PRINT_CU();
+ }
+}
+
+/* Precondition: 'out' is already constructed and empty. */
+static const char *
+do_uri_translation(const char *s,const char *context)
+{
+ struct esb_s str;
+ char *finalstr = 0;
+ if (!uri_options_translation) {
+ return makename(s);
+ }
+ esb_constructor(&str);
+ translate_from_uri(s,&str);
+ if (do_print_uri_in_input) {
+ if(strcmp(s,esb_get_string(&str))) {
+ printf("Uri Translation on option %s\n",context);
+ printf(" \'%s\'\n",s);
+ printf(" \'%s\'\n",esb_get_string(&str));
+ }
+ }
+ finalstr = makename(esb_get_string(&str));
+ esb_destructor(&str);
+ return finalstr;
+}
diff --git a/dwarfdump/dwarfdump.conf b/dwarfdump/dwarfdump.conf
new file mode 100644
index 0000000..d70bab8
--- /dev/null
+++ b/dwarfdump/dwarfdump.conf
@@ -0,0 +1,810 @@
+# MIPS/IRIX ISA/ABI
+# Used to configure dwarfdump printing of .debug_frame and
+# .eh_frame.
+
+# Any number of abi's can be described. Only one can be selected
+# in a given dwarfdump run (see dwarfdump options)
+# Available commands are
+# beginabi: <abiname>
+# reg: <regname> <dwarf regnumber>
+# frame_interface: <integer value 2 or 3>
+# cfa_reg: <number>
+# initial_reg_value: <number: often 1034 or 1035 >
+# same_val_reg: 1035
+# undefined_val_reg: 1034
+# reg_table_size: <size of table>
+# address_size: <4 or 8, Rarely needed, see example below. >
+# includeabi: <abiname Inserts the referenced abi as if its text was
+# directly inserted at this point.>
+# endabi: <abiname>
+#
+# Symbolic names do not work here, use literal numbers
+# where applicable (in C standard decimal, octal (leading 0) or
+# hexadecimal <leading 0x>).
+#
+# Whitespace is required to separate command: from operands and
+# operands from each other on a line.
+#
+# There is no ordering required within a beginabi/endabi pair.
+# As many ABIs as required may be listed.
+# dwarfdump will choose exactly one abi to dump frame information.
+#
+
+
+# MIPS abi,the old IRIX form, not to be used on modern objects.
+# Begin with abi name (use here and on dwarfdump command line).
+beginabi: mips-irix
+
+# Instructs dwarfdump to default to the older frame interface.
+# Use value 3 to use the newer interface.
+# The '2' interface is supported but deprecated (deprecated
+# because it cannot work with all popular ABIs: mixing
+# the cfa-rule into the table column set was not a good idea
+# but it is part of the MIPS/IRIX standard usage).
+frame_interface: 2
+
+# If (and only if) using frame_interface: 2 tell dwarfdump
+# what table colum that DW_FRAME_CFA_COL is.
+# If using frame_interface: 3 cfa_reg: should be
+# DW_FRAME_CFA_COL3 (1436)
+cfa_reg: 0
+
+# For MIPS, the same as DW_FRAME_SAME_VAL (1035).
+# For other ISA/ABIs 1034 (DW_FRAME_UNDEFINED_VAL) might be better.
+# Depends on the ABI convention, if set wrong way too many
+# regs will be listed in the frame output.
+# This instructs dwarfdump to set libdwarf to this value,
+# overriding the libdwarf default.
+# If initial_reg_value not set the libdwarf default is used
+# (see libdwarf.h DW_FRAME_REG_INITIAL_VALUE).
+initial_reg_value: 1035 # DW_FRAME_SAME_VAL
+same_val_reg: 1035
+undefined_val_reg: 1034
+
+# Built in to frame_interface: 2 as 66.
+reg_table_size: 66
+
+
+# Only name registers for wich a r4 (for example) is not what you
+# want to see
+# No particular order of the reg: lines required.
+reg: cfa 0 # Used with MIPS/IRIX original DWARF2 interface
+reg: r1/at 1
+reg: r2/v0 2
+reg: r3/v1 3
+reg: r4/a0 4
+reg: r5/a1 5
+reg: r6/a2 6
+reg: r7/a3 7
+reg: r8/t0 8
+reg: r9/t1 9
+reg: r10/t2 10
+reg: r11/t3 11
+reg: r12/t4 12
+reg: r13/t5 13
+reg: r14/t6 14
+reg: r15/t7 15
+reg: r16/s0 16
+reg: r17/s1 17
+reg: r18/s2 18
+reg: r19/s3 19
+reg: r20/s4 20
+reg: r21/s5 21
+reg: r22/s6 22
+reg: r23/s7 23
+reg: r24/t8 24
+reg: r25/t9 25
+reg: r26/k0 26
+reg: r27/k1 27
+reg: r28/gp 28
+reg: r29/sp 29
+reg: r30/s8 30
+reg: r31 31
+
+reg: $f0 32
+reg: $f1 33
+reg: $f2 34
+reg: $f3 35
+reg: $f4 36
+reg: $f5 37
+reg: $f6 38
+reg: $f7 39
+reg: $f8 40
+reg: $f9 41
+reg: $f10 42
+reg: $f11 43
+reg: $f12 44
+reg: $f13 45
+reg: $f14 46
+reg: $f15 47
+reg: $f16 48
+reg: $f17 49
+reg: $f18 50
+reg: $f19 51
+reg: $f20 52
+reg: $f21 53
+reg: $f22 54
+reg: $f23 55
+reg: $f24 56
+reg: $f25 57
+reg: $f26 58
+reg: $f27 59
+reg: $f28 60
+reg: $f29 61
+reg: $f30 62
+reg: $f31 63
+reg: ra 64
+reg: slk 65
+
+
+# End of abi definition.
+endabi: mips-irix
+
+
+# Make 'mips' abi be a modern MIPS, not an old IRIX version.
+beginabi: mips
+includeabi: mips-simple3
+endabi: mips
+
+
+# MIPS/IRIX ISA/ABI for testing libdwarf.
+beginabi: mips-irix2
+frame_interface: 2
+reg_table_size: 66
+cfa_reg: 0
+same_val_reg: 1035
+undefined_val_reg: 1034
+initial_reg_value: 1035
+
+reg: cfa 0 # Used with MIPS/IRIX original DWARF2 interface
+reg: ra 64
+reg: slk 65
+
+# End of abi definition.
+endabi: mips-irix2
+
+# MIPS/IRIX ISA/ABI for testing the new frame interface
+# with libdwarf.
+beginabi: mips-simple3
+frame_interface: 3
+
+# When using frame_interface: 3 the size of the register table
+# is not fixed. It can be as large as needed.
+reg_table_size: 66
+cfa_reg: 1436 # DW_FRAME_CFA_COL3
+initial_reg_value: 1035
+same_val_reg: 1035
+undefined_val_reg: 1034
+
+# No cfa as a 'normal' register.
+# Rule 0 is just register 0, which is not used
+# in frame descriptions.
+# (so cfa does not have a number here, and dwarfdump gives
+# it the name 'cfa' automatically).
+reg: ra 64
+reg: slk 65
+# End of abi definition.
+endabi: mips-simple3
+
+
+beginabi: ia64
+frame_interface: 3
+initial_reg_value: 1034 # DW_FRAME_UNDEFINED_VAL
+cfa_reg: 1436 # DW_FRAME_CFA_COL3
+reg_table_size: 695
+same_val_reg: 1035
+undefined_val_reg: 1034
+
+# The following register names are not necessarily correct...
+# Register indexes r32-r127 not used.
+reg: f0 128
+# ...
+reg: f127 255
+reg: b0 321
+reg: b1 322
+reg: b2 323
+reg: b3 324
+reg: b4 325
+reg: b5 326
+reg: b6 327
+reg: b7 328
+reg: vfp 329
+reg: vrap 330
+reg: pr 331
+reg: ip 332
+reg: psr 333
+reg: cfm 334
+reg: k0 335
+reg: k1 336
+reg: k2 337
+reg: k3 338
+reg: k4 339
+reg: k5 340
+reg: k6 341
+reg: k7 342
+reg: rsc 350
+reg: bsp 351
+reg: bspstore 352
+reg: rnat 353
+reg: fcr 355
+reg: eflag 358
+reg: csd 359
+reg: ssd 360
+reg: cflg 361
+reg: fsr 362
+reg: fir 363
+reg: fdr 364
+reg: pfs 398
+reg: lc 399
+reg: ec 400
+
+endabi: ia64
+
+
+beginabi: x86
+frame_interface: 3
+initial_reg_value: 1035 # DW_FRAME_SAME_VAL
+reg_table_size: 66 # more than large enough, hopefully.
+cfa_reg: 1436 # DW_FRAME_CFA_COL3
+same_val_reg: 1035
+undefined_val_reg: 1034
+
+# The following register names are not necessarily correct...
+reg: eax 0
+reg: ecx 1
+reg: edx 2
+reg: ebx 3
+reg: esp 4
+reg: ebp 5
+reg: esi 6
+reg: edi 7
+reg: eip 8
+reg: eflags 9
+
+reg: trapno 10
+reg: st0 11
+reg: st1 12
+reg: st2 13
+reg: st3 14
+reg: st4 15
+reg: st5 16
+reg: st6 17
+reg: st7 18
+# 19 is ? 20 is ?
+reg: xmm0 21
+reg: xmm1 22
+reg: xmm2 23
+reg: xmm3 24
+reg: xmm4 25
+reg: xmm5 26
+reg: xmm6 27
+reg: xmm7 28
+
+reg: mm0 29
+reg: mm1 30
+reg: mm2 31
+reg: mm3 32
+reg: mm4 33
+reg: mm5 34
+reg: mm6 35
+reg: mm7 36
+
+reg: fcw 37
+reg: fsw 38
+reg: mxcsr 39
+
+reg: es 40
+reg: cs 41
+reg: ss 42
+reg: ds 43
+reg: fs 44
+reg: gs 45
+# 46 47 are ?
+reg: tr 48
+reg: ldtr 49
+
+
+endabi: x86
+
+
+beginabi: x86_64
+frame_interface: 3
+initial_reg_value: 1035 # DW_FRAME_SAME_VAL
+reg_table_size: 66 # more than large enough, hopefully.
+cfa_reg: 1436 # DW_FRAME_CFA_COL3
+same_val_reg: 1035
+undefined_val_reg: 1034
+
+# The following register names are not necessarily correct...
+reg: rax 0
+reg: rdx 1
+reg: rcx 2
+reg: rbx 3
+reg: rsi 4
+reg: rdi 5
+reg: rbp 6
+reg: rsp 7
+reg: r8 8
+reg: r9 9
+reg: r10 10
+reg: r11 11
+reg: r12 12
+reg: r13 13
+reg: r14 14
+reg: r15 15
+reg: rip 16
+reg: xmm0 17
+reg: xmm1 18
+reg: xmm2 19
+reg: xmm3 20
+reg: xmm4 21
+reg: xmm5 22
+reg: xmm6 23
+reg: xmm7 24
+reg: xmm8 25
+reg: xmm9 26
+reg: xmm10 27
+reg: xmm11 28
+reg: xmm12 29
+reg: xmm13 30
+reg: xmm14 31
+reg: xmm15 32
+
+reg: st0 33
+reg: st1 34
+reg: st2 35
+reg: st3 36
+reg: st4 37
+reg: st5 38
+reg: st6 39
+reg: st7 40
+
+reg: mm0 41
+reg: mm1 42
+reg: mm2 43
+reg: mm3 44
+reg: mm4 45
+reg: mm5 46
+reg: mm6 47
+reg: mm7 48
+
+reg: rflags 49
+reg: es 50
+reg: cs 51
+reg: ss 52
+reg: ds 53
+reg: fs 54
+reg: gs 55
+# 56, 57 are ?
+reg: fs.base 58
+reg: gs.base 59
+# 60 61 are ?
+reg: tr 62
+reg: ldtr 63
+
+endabi: x86_64
+
+beginabi: m68k
+frame_interface: 3
+initial_reg_value: 1035 # DW_FRAME_SAME_VAL
+reg_table_size: 66 # more than large enough, hopefully.
+cfa_reg: 1436 # DW_FRAME_CFA_COL3
+same_val_reg: 1035
+undefined_val_reg: 1034
+
+reg: d0 0
+reg: d1 1
+reg: d2 2
+reg: d3 3
+reg: d4 4
+reg: d5 5
+reg: d6 6
+reg: d7 7
+
+reg: a0 8
+reg: a1 9
+reg: a2 10
+reg: a3 11
+reg: a4 12
+reg: a5 13
+reg: a6 14
+reg: sp 15
+
+reg: fp0 16
+reg: fp1 17
+reg: fp2 18
+reg: fp3 19
+reg: fp4 20
+reg: fp5 21
+reg: fp6 22
+reg: pc 23
+
+endabi: m68k
+
+# Demonstrates use of address_size and includeabi keywords.
+# address_size is useful when an Elf64 object has DWARF2
+# 32bit (4 byte) address-size frame data (which has no address_size field)
+# and no .debug_info section to provide the 32bit address size.
+beginabi: ppc32bitaddress
+address_size: 4
+includeabi: ppc
+endabi: ppc32bitaddress
+
+beginabi: ppc
+# This abi defined Oct 2008 based on:
+# http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html
+frame_interface: 3
+# abi dwarf table uses up thru 1155.
+# As of Oct 2008, the only ABI requiring a higher
+# DW_FRAME_SAME_VAL and DW_FRAME_CFA_COL3.
+initial_reg_value: 1235 # DW_FRAME_SAME_VAL
+cfa_reg: 1436 # DW_FRAME_CFA_COL3
+same_val_reg: 1235
+undefined_val_reg: 1234
+reg_table_size: 1200
+
+reg: r0 0
+reg: f0 32
+reg: f1 33
+reg: f2 34
+reg: f3 35
+reg: f4 36
+reg: f5 37
+reg: f6 38
+reg: f7 39
+reg: f8 40
+reg: f9 41
+reg: f10 42
+reg: f11 43
+reg: f12 44
+reg: f13 45
+reg: f14 46
+reg: f16 47
+reg: f17 48
+reg: f18 49
+reg: f19 50
+reg: f20 51
+reg: f21 52
+reg: f22 53
+reg: f23 54
+reg: f24 55
+reg: f25 56
+reg: f26 57
+reg: f27 58
+reg: f28 59
+reg: f29 60
+reg: f30 62
+reg: f31 63
+reg: cr 64
+reg: fpcsr 65
+# spr0 is also called MQ
+reg: spr0 100
+# spr1 is also called XER
+reg: spr1 101
+# spr4 also called rtcu
+reg: spr4 104
+# spr5 also called rtcl
+reg: spr5 105
+#spr8 also called LR
+reg: spr8 108
+# spr9 also called ctr
+reg: spr9 109
+reg: msr 66
+reg: sr0 70
+reg: sr1 71
+reg: sr2 72
+reg: sr3 73
+reg: sr4 74
+reg: sr5 75
+reg: sr6 76
+reg: sr7 77
+reg: sr8 78
+reg: sr9 79
+
+#dsisr also called spr18
+reg: spr18 118
+# dar also called spr19
+reg: spr19 119
+#dec also called spr22
+reg: spr22 122
+#sdr1 also called spr25
+reg: spr25 125
+#srr0 also called spr26
+reg: spr26 126
+#srr1 also called spr27
+reg: spr27 127
+
+#vrsave also called spr256
+reg: spr256 356
+#sprg0 also called spr272
+reg: spr272 372
+#sprg1 also called spr273
+reg: spr273 373
+#sprg2 also called spr274
+reg: spr274 374
+#sprg3 also called spr275
+reg: spr275 375
+#asr also called spr280
+reg: spr280 380
+#ear also called spr282
+reg: spr282 382
+#tb also called spr284
+reg: spr284 384
+#tbu also called spr285
+reg: spr285 385
+#pvr also called spr287
+reg: spr287 387
+#ibat0u also called spr528
+reg: spr528 628
+#ibat0l also called spr529
+reg: spr529 629
+#ibat1u also called spr530
+reg: spr530 630
+#ibat1l also called spr531
+reg: spr531 631
+#ibat2u also called spr532
+reg: spr532 632
+#ibat2l also called spr533
+reg: spr533 633
+#ibat3u also called spr534
+reg: spr534 634
+#ibat3l also called spr535
+reg: spr535 635
+#dbat0u also called spr536
+reg: spr536 636
+#dbat0l also called spr537
+reg: spr537 637
+#dbat1u also called spr538
+reg: spr538 638
+#dbat1l also called spr539
+reg: spr539 639
+#dbat2u also called spr540
+reg: spr540 640
+#dbat2l also called spr541
+reg: spr541 641
+#dbat3u also called spr542
+reg: spr542 642
+#dbat3l also called spr543
+reg: spr543 643
+
+#hid0 also called spr1008
+reg: spr1008 1108
+#hid1 also called spr1009
+reg: spr1009 1109
+#hid2 also called iabr or spr1010
+reg: spr1010 1110
+#hid5 also called dabr or spr1013
+reg: spr1013 1113
+#hid15 also called pir or spr1023
+reg: spr1023 1123
+
+# vector registers 0-31
+reg: vr0 1124
+reg: vr1 1125
+reg: vr2 1126
+reg: vr3 1127
+reg: vr4 1128
+reg: vr5 1129
+reg: vr6 1130
+reg: vr7 1131
+reg: vr8 1132
+reg: vr9 1133
+reg: vr10 1134
+reg: vr11 1135
+reg: vr12 1136
+reg: vr13 1137
+reg: vr14 1138
+reg: vr15 1130
+reg: vr16 1140
+reg: vr17 1141
+reg: vr18 1142
+reg: vr19 1143
+reg: vr20 1144
+reg: vr21 1145
+reg: vr22 1146
+reg: vr23 1147
+reg: vr24 1148
+reg: vr25 1149
+reg: vr26 1150
+reg: vr27 1151
+reg: vr28 1152
+reg: vr29 1153
+reg: vr30 1154
+reg: vr31 1155
+endabi: ppc
+
+# 'Generic 1000 register abi'.
+# This is useful as a 'general' ABI settings for
+# cpus using up to 1000 registers. The register names
+# show as a number, like 'r991'.
+beginabi: generic
+frame_interface: 3
+initial_reg_value: 1035 # DW_FRAME_SAME_VAL
+cfa_reg: 1436 # DW_FRAME_CFA_COL3
+reg_table_size: 1000
+same_val_reg: 1035
+undefined_val_reg: 1034
+reg: r0 0
+endabi: generic
+
+# 'Generic 500 register abi'.
+# This is useful as a 'general' ABI settings for
+# cpus using up to 500 registers. The register names
+# show as a number, like 'r91'.
+beginabi: generic500
+frame_interface: 3
+initial_reg_value: 1035 # DW_FRAME_SAME_VAL
+cfa_reg: 1436 # DW_FRAME_CFA_COL3
+reg_table_size: 500
+same_val_reg: 1035
+undefined_val_reg: 1034
+reg: r0 0
+endabi: generic500
+
+# 'Generic 100 register abi'.
+# This is useful as a 'general' ABI settings for
+# cpus using up to 100 registers. The register names
+# show as a number, like 'r91'.
+beginabi: generic100
+frame_interface: 3
+initial_reg_value: 1035 # DW_FRAME_SAME_VAL
+cfa_reg: 1436 # DW_FRAME_CFA_COL3
+reg_table_size: 100
+same_val_reg: 1035
+undefined_val_reg: 1034
+reg: r0 0
+endabi: generic100
+
+
+beginabi: arm
+frame_interface: 3
+# When using frame_interface: 3 the size of the register
+# table is not fixed. It can be as large as needed.
+reg_table_size: 288
+cfa_reg: 1436 # DW_FRAME_CFA_COL3
+initial_reg_value: 1034
+same_val_reg: 1035
+undefined_val_reg: 1034
+# If the vendor co-processor registers are allowed
+# or other numbers above 287 used then
+# the reg_table_size must be increased and (possibly)
+# the cfa, same_value, undefined_value reg values changed
+# here.
+# r0-r15 are 0 through 15.
+# Numbers 16 through 63 had meaning
+# in some ARM DWARF register mappings.
+reg: s0 64
+reg: s1 65
+reg: s2 66
+reg: s3 67
+reg: s4 68
+reg: s5 69
+reg: s6 70
+reg: s7 71
+reg: s8 72
+reg: s9 73
+reg: s10 74
+reg: s11 75
+reg: s12 76
+reg: s13 77
+reg: s14 78
+reg: s15 79
+reg: s16 80
+reg: s17 81
+reg: s18 82
+reg: s19 83
+reg: s20 84
+reg: s21 85
+reg: s22 86
+reg: s23 87
+reg: s24 88
+reg: s25 89
+reg: s26 90
+reg: s27 91
+reg: s28 92
+reg: s29 93
+reg: s30 94
+reg: s31 95
+reg: f0 96
+reg: f1 97
+reg: f2 98
+reg: f3 99
+reg: f4 100
+reg: f5 101
+reg: f6 102
+reg: f7 103
+reg: wcgr0 104
+reg: wcgr0 105
+reg: wcgr0 106
+reg: wcgr0 107
+reg: wcgr0 108
+reg: wcgr0 109
+reg: wcgr0 110
+reg: wcgr0 111
+reg: wr0 112
+reg: wr1 113
+reg: wr2 114
+reg: wr3 115
+reg: wr4 116
+reg: wr5 117
+reg: wr6 118
+reg: wr7 119
+reg: wr8 120
+reg: wr9 121
+reg: wr10 122
+reg: wr11 123
+reg: wr12 124
+reg: wr13 125
+reg: wr14 126
+reg: wr15 127
+reg: spsr 128
+reg: spsr_fiq 129
+reg: spsr_irq 130
+reg: spsr_abt 131
+reg: spsr_und 132
+reg: spsr_svc 133
+reg: r8_usr 144
+reg: r9_usr 145
+reg: r10_usr 146
+reg: r11_usr 147
+reg: r12_usr 148
+reg: r13_usr 149
+reg: r14_usr 150
+reg: r8_fiq 151
+reg: r9_fiq 152
+reg: r10_fiq 153
+reg: r11_fiq 154
+reg: r12_fiq 155
+reg: r13_fiq 156
+reg: r14_fiq 157
+reg: r13_riq 158
+reg: r14_riq 159
+reg: r14_abt 160
+reg: r13_abt 161
+reg: r14_und 162
+reg: r13_und 163
+reg: r14_svc 164
+reg: r13_svc 165
+reg: wc0 192
+reg: wc1 193
+reg: wc2 192
+reg: wc3 192
+reg: wc4 192
+reg: wc5 197
+reg: wc6 198
+reg: wc7 199
+reg: d0 256
+reg: d1 257
+reg: d2 258
+reg: d3 259
+reg: d4 260
+reg: d5 261
+reg: d6 262
+reg: d7 263
+reg: d8 264
+reg: d9 265
+reg: d10 266
+reg: d11 267
+reg: d12 268
+reg: d13 269
+reg: d14 270
+reg: d15 271
+reg: d16 272
+reg: d17 273
+reg: d18 274
+reg: d19 275
+reg: d20 266
+reg: d21 277
+reg: d22 278
+reg: d23 279
+reg: d24 280
+reg: d25 281
+reg: d26 282
+reg: d27 283
+reg: d28 284
+reg: d29 285
+reg: d30 286
+reg: d31 287
+# End of abi definition.
+endabi: arm
+
diff --git a/dwarfdump/dwconf.c b/dwarfdump/dwconf.c
new file mode 100644
index 0000000..1b59053
--- /dev/null
+++ b/dwarfdump/dwconf.c
@@ -0,0 +1,1424 @@
+/*
+ Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+ $Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/dwconf.c,v 1.4 2006/04/18 18:05:57 davea Exp $ */
+
+
+/* Windows specific */
+#ifdef HAVE_STDAFX_H
+#include "stdafx.h"
+#endif /* HAVE_STDAFX_H */
+
+#include "globals.h"
+#include "dwarf.h"
+#include "libdwarf.h"
+
+#include <ctype.h>
+#include "dwconf.h"
+#include "makename.h"
+
+extern int verbose;
+
+/* The nesting level is arbitrary, 2 should suffice.
+ But at least this prevents an infinite loop.
+*/
+#define MAX_NEST_LEVEL 3
+
+struct token_s {
+ unsigned tk_len;
+ char *tk_data;
+};
+enum linetype_e {
+ LT_ERROR,
+ LT_COMMENT,
+ LT_BLANK,
+ LT_BEGINABI,
+ LT_REG,
+ LT_FRAME_INTERFACE,
+ LT_CFA_REG,
+ LT_INITIAL_REG_VALUE,
+ LT_SAME_VAL_REG,
+ LT_UNDEFINED_VAL_REG,
+ LT_REG_TABLE_SIZE,
+ LT_ADDRESS_SIZE,
+ LT_INCLUDEABI,
+ LT_ENDABI
+};
+
+struct comtable_s {
+ enum linetype_e type;
+ char *name;
+ size_t namelen;
+};
+
+static int errcount = 0; /* Count errors found in this scan of
+ the configuration file. */
+
+static char name_begin_abi[] = "beginabi:";
+static char name_reg[] = "reg:";
+static char name_frame_interface[] = "frame_interface:";
+static char name_cfa_reg[] = "cfa_reg:";
+static char name_initial_reg_value[] = "initial_reg_value:";
+static char name_same_val_reg[] = "same_val_reg:";
+static char name_undefined_val_reg[] = "undefined_val_reg:";
+static char name_reg_table_size[] = "reg_table_size:";
+static char name_address_size[] = "address_size:";
+static char name_includeabi[] = "includeabi:";
+static char name_endabi[] = "endabi:";
+
+static struct comtable_s comtable[] = {
+ {LT_BEGINABI, name_begin_abi},
+ {LT_REG, name_reg},
+ {LT_FRAME_INTERFACE, name_frame_interface},
+ {LT_CFA_REG, name_cfa_reg},
+ {LT_INITIAL_REG_VALUE, name_initial_reg_value},
+ {LT_SAME_VAL_REG, name_same_val_reg},
+ {LT_UNDEFINED_VAL_REG, name_undefined_val_reg},
+ {LT_REG_TABLE_SIZE, name_reg_table_size},
+ {LT_ADDRESS_SIZE, name_address_size},
+ {LT_INCLUDEABI, name_includeabi},
+ {LT_ENDABI, name_endabi},
+};
+
+struct conf_internal_s {
+ unsigned long beginabi_lineno;
+ unsigned long frame_interface_lineno;
+ unsigned long initial_reg_value_lineno;
+ unsigned long reg_table_size_lineno;
+ unsigned long address_size_lineno;
+ unsigned long same_val_reg_lineno;
+ unsigned long undefined_val_reg_lineno;
+ unsigned long cfa_reg_lineno;
+ unsigned long regcount;
+ struct dwconf_s * conf_out;
+ const char * conf_name_used;
+ char ** conf_defaults;
+};
+static void
+init_conf_internal(struct conf_internal_s *s,
+ struct dwconf_s * conf_out)
+{
+ s->beginabi_lineno = 0;
+ s->frame_interface_lineno = 0;
+ s->initial_reg_value_lineno = 0;
+ s->reg_table_size_lineno = 0;
+ s->address_size_lineno = 0;
+ s->same_val_reg_lineno = 0;
+ s->undefined_val_reg_lineno = 0;
+ s->cfa_reg_lineno = 0;
+ s->cfa_reg_lineno = 0;
+ s->conf_name_used = 0;
+ s->conf_defaults = 0;
+ s->regcount = 0;
+ s->conf_out = conf_out;
+}
+
+static int size_of_comtable = sizeof(comtable) / sizeof(comtable[0]);
+
+static FILE *find_a_file(const char *named_file, char **defaults,
+ const char** name_used);
+static int find_abi_start(FILE * stream, const char *abi_name, long *offset,
+ unsigned long *lineno_out);
+static int parse_abi(FILE * stream, const char *fname, const char *abiname,
+ struct conf_internal_s *out, unsigned long lineno, unsigned nest_level);
+static char *get_token(char *cp, struct token_s *outtok);
+
+/* This finds a dwarfdump.conf file and
+ then parses it. It updates
+ conf_out as appropriate.
+
+ This finds the first file (looking in a set of places)
+ with that name. It then looks for the right ABI entry.
+ If the first file it finds does not have that ABI entry it
+ gives up.
+
+ It would also be reasonable to search every 'dwarfdump.conf'
+ it finds for the abi. But we stop at the first dwarfdump.conf
+ we find.
+ This is the internal call to get the conf data to implement
+ a crude 'includeabi' feature.
+
+ Returns 0 if no errors found, else returns > 0.
+*/
+static int
+find_conf_file_and_read_config_inner(const char *named_file,
+ const char *named_abi,
+ struct conf_internal_s *conf_internal,
+ unsigned nest_level)
+{
+
+ FILE *conf_stream = 0;
+ const char *name_used = 0;
+ long offset = 0;
+ int res = FALSE;
+ unsigned long lineno = 0;
+
+ errcount = 0;
+
+ conf_stream = find_a_file(named_file, conf_internal->conf_defaults,
+ &name_used);
+ if (!conf_stream) {
+ ++errcount;
+ printf("dwarfdump found no file %s!\n",
+ named_file ? named_file : "readable for configuration. "
+ "(add options -v -v to see what file names tried)\n");
+ return errcount;
+ }
+ if (verbose > 1) {
+ printf("dwarfdump using configuration file %s\n", name_used);
+ }
+ conf_internal->conf_name_used = name_used;
+
+ res = find_abi_start(conf_stream, named_abi, &offset, &lineno);
+ if (errcount > 0) {
+ ++errcount;
+ printf("dwarfdump found no ABI %s in file %s.\n",
+ named_abi, name_used);
+ return errcount;
+ }
+ res = fseek(conf_stream, offset, SEEK_SET);
+ if (res != 0) {
+ ++errcount;
+ printf("dwarfdump seek to %ld offset in %s failed!\n",
+ offset, name_used);
+ return errcount;
+ }
+ parse_abi(conf_stream, name_used, named_abi, conf_internal, lineno,
+ nest_level);
+ fclose(conf_stream);
+ return errcount;
+}
+
+/* This is the external-facing call to get the conf data. */
+int
+find_conf_file_and_read_config(const char *named_file,
+ const char *named_abi, char **defaults,
+ struct dwconf_s *conf_out)
+{
+ int res = 0;
+ struct conf_internal_s conf_internal;
+ init_conf_file_data(conf_out);
+ init_conf_internal(&conf_internal,conf_out);
+ conf_internal.conf_defaults = defaults;
+ res = find_conf_file_and_read_config_inner(named_file,
+ named_abi,
+ &conf_internal,0);
+ return res;
+}
+
+/* Given path strings, attempt to make a canonical file name:
+ that is, avoid superfluous '/' so that no
+ '//' (or worse) is created in the output. The path components
+ are to be separated so at least one '/'
+ is to appear between the two 'input strings' when
+ creating the output.
+*/
+static char *
+canonical_append(char *target, unsigned int target_size,
+ const char *first_string, const char *second_string)
+{
+ size_t firstlen = strlen(first_string);
+
+ /* +1 +1: Leave room for added "/" and final NUL, though that is
+ overkill, as we drop a NUL byte too. */
+ if ((firstlen + strlen(second_string) + 1 + 1) >= target_size) {
+ /* Not enough space. */
+ return NULL;
+ }
+ for (; *second_string == '/'; ++second_string) {
+ }
+ for (; firstlen > 0 && first_string[firstlen - 1] == '/';
+ --firstlen) {
+ }
+ target[0] = 0;
+ if (firstlen > 0) {
+ strncpy(target, first_string, firstlen);
+ target[firstlen + 1] = 0;
+ }
+ target[firstlen] = '/';
+ firstlen++;
+ target[firstlen] = 0;
+ strcat(target, second_string);
+ return target;
+}
+
+#ifdef BUILD_FOR_TEST
+#define CANBUF 25
+struct canap_s {
+ char *res_exp;
+ char *first;
+ char *second;
+} canap[] = {
+ {
+ "ab/c", "ab", "c"}, {
+ "ab/c", "ab/", "c"}, {
+ "ab/c", "ab", "/c"}, {
+ "ab/c", "ab////", "/////c"}, {
+ "ab/", "ab", ""}, {
+ "ab/", "ab////", ""}, {
+ "ab/", "ab////", ""}, {
+ "/a", "", "a"}, {
+ 0, "/abcdefgbijkl", "pqrstuvwxyzabcd"}, {
+ 0, 0, 0}
+};
+static void
+test_canonical_append(void)
+{
+ /* Make buf big, this is test code, so be safe. */
+ char lbuf[1000];
+ unsigned i;
+ unsigned failcount = 0;
+
+ printf("Entry test_canonical_append\n");
+ for (i = 0;; ++i) {
+ char *res = 0;
+
+ if (canap[i].first == 0 && canap[i].second == 0)
+ break;
+
+ res = canonical_append(lbuf, CANBUF, canap[i].first,
+ canap[i].second);
+ if (res == 0) {
+ if (canap[i].res_exp == 0) {
+ /* GOOD */
+ printf("PASS %u\n", i);
+ } else {
+ ++failcount;
+ printf("FAIL: entry %u wrong, expected %s, got NULL\n",
+ i, canap[i].res_exp);
+ }
+ } else {
+ if (canap[i].res_exp == 0) {
+ ++failcount;
+ printf("FAIL: entry %u wrong, got %s expected NULL\n",
+ i, res);
+ } else {
+ if (strcmp(res, canap[i].res_exp) == 0) {
+ printf("PASS %u\n", i);
+ /* GOOD */
+ } else {
+ ++failcount;
+ printf("FAIL: entry %u wrong, expected %s got %s\n",
+ i, canap[i].res_exp, res);
+ }
+ }
+ }
+ }
+ printf("FAIL count %u\n", failcount);
+
+}
+#endif /* BUILD_FOR_TEST */
+/* Try to find a file as named and open for read.
+ We treat each name as a full name, we are not
+ combining separate name and path components.
+ This is an arbitrary choice...
+
+ The defaults are listed in dwarfdump.c in the array
+ config_file_defaults[].
+*/
+static FILE *
+find_a_file(const char *named_file, char **defaults, const char ** name_used)
+{
+ FILE *fin = 0;
+ const char *lname = named_file;
+ const char *type = "rw";
+ int i = 0;
+
+#ifdef BUILD_FOR_TEST
+ test_canonical_append();
+#endif /* BUILD_FOR_TEST */
+
+ if (lname) {
+ /* Name given, just assume it is fully correct, try no other. */
+ if (verbose > 1) {
+ printf("dwarfdump looking for configuration as %s\n",
+ lname);
+ }
+ fin = fopen(lname, type);
+ if (fin) {
+ *name_used = lname;
+ return fin;
+ }
+ return 0;
+ }
+ /* No name given, find a default, if we can. */
+ for (i = 0; defaults[i]; ++i) {
+ lname = defaults[i];
+#ifdef WIN32
+ /* Open the configuration file, located
+ in the directory where the tool is loaded from */
+ {
+ static char szPath[MAX_PATH];
+ if (GetModuleFileName(NULL,szPath,MAX_PATH)) {
+ char *pDir = strrchr(szPath,'/');
+ if (!pDir) {
+ pDir = strrchr(szPath,'\\');
+ if (!pDir) {
+ /* No file was found */
+ return 0;
+ }
+ }
+ /* Add the configuration name to the pathname */
+ ++pDir;
+ strcpy(pDir,"dwarfdump.conf");
+ lname = szPath;
+ }
+ }
+#else /* non-Win */
+ if (strncmp(lname, "HOME/", 5) == 0) {
+ /* arbitrary size */
+ char buf[2000];
+ char *homedir = getenv("HOME");
+ if (homedir) {
+ char *cp = canonical_append(buf, sizeof(buf),
+ homedir, lname + 5);
+ if (!cp) {
+ /* OOps, ignore this one. */
+ continue;
+ }
+ lname = makename(buf);
+ }
+ }
+#endif /* WIN32 */
+ if (verbose > 1) {
+ printf("dwarfdump looking for configuration as %s\n",
+ lname);
+ }
+ fin = fopen(lname, type);
+ if (fin) {
+ *name_used = lname;
+ return fin;
+ }
+ }
+ return 0;
+}
+
+/* Start at a token begin, see how long it is,
+ return length. */
+unsigned
+find_token_len(char *cp)
+{
+ unsigned len = 0;
+
+ for (; *cp; ++cp) {
+ if (isspace(*cp)) {
+ return len;
+ }
+ if (*cp == '#') {
+ return len; /* begins comment */
+ }
+ ++len;
+ }
+ return len;
+}
+
+/*
+ Skip past all whitespace: the only code that even knows
+ what whitespace is.
+*/
+static char *
+skipwhite(char *cp)
+{
+ for (; *cp; ++cp) {
+ if (!isspace(*cp)) {
+ return cp;
+ }
+ }
+ return cp;
+}
+
+/* Return TRUE if ok. FALSE if find more tokens.
+ Emit error message if error.
+*/
+static int
+ensure_has_no_more_tokens(char *cp, const char *fname, unsigned long lineno)
+{
+ struct token_s tok;
+
+ cp = get_token(cp, &tok);
+ if (tok.tk_len > 0) {
+ printf("dwarfdump.conf error: "
+ "extra characters after command operands, found "
+ "\"%s\" in %s line %lu\n", tok.tk_data, fname, lineno);
+ ++errcount;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+/* There may be many beginabi: lines in a dwarfdump.conf file,
+ find the one we want and return its file offset.
+*/
+static int
+find_abi_start(FILE * stream, const char *abi_name,
+ long *offset, unsigned long *lineno_out)
+{
+ char buf[100];
+ unsigned long lineno = 0;
+
+ for (; !feof(stream);) {
+
+ struct token_s tok;
+ char *line = 0;
+ long loffset = ftell(stream);
+
+ line = fgets(buf, sizeof(buf), stream);
+ ++lineno;
+ if (!line) {
+ ++errcount;
+ return FALSE;
+ }
+
+ line = get_token(buf, &tok);
+
+ if (strcmp(tok.tk_data, name_begin_abi) != 0) {
+ continue;
+ }
+ get_token(line, &tok);
+ if (strcmp(tok.tk_data, abi_name) != 0) {
+ continue;
+ }
+
+ *offset = loffset;
+ *lineno_out = lineno;
+ return TRUE;
+ }
+
+ ++errcount;
+ return FALSE;
+}
+
+static char *tempstr = 0;
+static unsigned tempstr_len = 0;
+
+/* Use a global buffer (tempstr) to turn a non-delimited
+ input char array into a NUL-terminated C string
+ (with the help of makename() to get a permanent
+ address for the result ing string).
+*/
+static char *
+build_string(unsigned tlen, char *cp)
+{
+ if (tlen >= tempstr_len) {
+ free(tempstr);
+ tempstr = malloc(tlen + 100);
+ }
+ strncpy(tempstr, cp, tlen);
+ tempstr[tlen] = 0;
+ return makename(tempstr);
+}
+
+/* The tokenizer for our simple parser.
+*/
+static char *
+get_token(char *cp, struct token_s *outtok)
+{
+ char *lcp = skipwhite(cp);
+ unsigned tlen = find_token_len(lcp);
+
+ outtok->tk_len = tlen;
+ if (tlen > 0) {
+ outtok->tk_data = build_string(tlen, lcp);
+ } else {
+ outtok->tk_data = "";
+ }
+ return lcp + tlen;
+
+}
+
+/*
+ We can't get all the field set up statically very easily,
+ so we get the command string length set here.
+*/
+static void
+finish_comtable_setup(void)
+{
+ unsigned i;
+
+ for (i = 0; i < size_of_comtable; ++i) {
+ comtable[i].namelen = strlen(comtable[i].name);
+ }
+}
+
+/*
+ Given a line of the table, determine if it is a command
+ or not, and if a command, which one is it.
+ Return LT_ERROR if it's not recognized.
+*/
+static enum linetype_e
+which_command(char *cp, struct comtable_s **tableentry)
+{
+ int i;
+ struct token_s tok;
+
+ if (*cp == '#')
+ return LT_COMMENT;
+ if (!*cp)
+ return LT_BLANK;
+
+ get_token(cp, &tok);
+
+ for (i = 0; i < size_of_comtable; ++i) {
+ if (tok.tk_len == comtable[i].namelen &&
+ strcmp(comtable[i].name, tok.tk_data) == 0) {
+
+ *tableentry = &comtable[i];
+ return comtable[i].type;
+ }
+ }
+
+ return LT_ERROR;
+}
+
+/* We are promised it's an abiname: command
+ find the name on the line.
+*/
+static int
+parsebeginabi(char *cp, const char *fname, const char *abiname,
+ unsigned long lineno, struct comtable_s *comtab)
+{
+ size_t clen = comtab->namelen;
+ size_t abinamelen = strlen(abiname);
+ struct token_s tok;
+
+
+ cp = cp + clen + 1;
+ cp = skipwhite(cp);
+ get_token(cp, &tok);
+ if (tok.tk_len != abinamelen ||
+ strncmp(cp, abiname, abinamelen) != 0) {
+ printf("dwarfdump internal error: "
+ "mismatch %s with %s %s line %lu\n",
+ cp, tok.tk_data, fname, lineno);
+ ++errcount;
+ return FALSE;
+ }
+ ensure_has_no_more_tokens(cp + tok.tk_len, fname, lineno);
+ return TRUE;
+}
+
+/* This expands register names as required, but does not
+ ensure no names duplicated.
+*/
+#define CONF_TABLE_OVERSIZE 100
+static void
+add_to_reg_table(struct dwconf_s *conf,
+ char *rname, unsigned long rval, const char *fname,
+ unsigned long lineno)
+{
+ if (conf->cf_regs_malloced == 0) {
+ conf->cf_regs = 0;
+ conf->cf_named_regs_table_size = 0;
+ }
+ if (rval >= conf->cf_named_regs_table_size) {
+ char **newregs = 0;
+ unsigned long newtablen = rval + CONF_TABLE_OVERSIZE;
+ unsigned long newtabsize = newtablen * sizeof(char *);
+ unsigned long oldtabsize =
+ conf->cf_named_regs_table_size * sizeof(char *);
+ newregs = realloc(conf->cf_regs, newtabsize);
+ if (!newregs) {
+ printf("dwarfdump: unable to malloc table %lu bytes. "
+ " %s line %lu\n", newtabsize, fname, lineno);
+ exit(1);
+ }
+ /* Zero out the new entries. */
+ memset((char *) newregs + (oldtabsize), 0,
+ (newtabsize - oldtabsize));
+ conf->cf_named_regs_table_size = (unsigned long) newtablen;
+ conf->cf_regs = newregs;
+ conf->cf_regs_malloced = 1;
+ }
+ conf->cf_regs[rval] = rname;
+ return;
+}
+
+/* Our input is supposed to be a number.
+ Determine the value (and return it) or generate an error message.
+*/
+static int
+make_a_number(char *cmd, const char *filename, unsigned long
+ lineno, struct token_s *tok, unsigned long *val_out)
+{
+ char *endnum = 0;
+ unsigned long val = 0;
+
+ val = strtoul(tok->tk_data, &endnum, 0);
+ if (val == 0 && endnum == (tok->tk_data)) {
+ printf("dwarfdump.conf error: "
+ "%s missing register number (\"%s\" not valid) %s line %lu\n",
+ cmd, tok->tk_data, filename, lineno);
+ ++errcount;
+ return FALSE;
+ }
+ if (endnum != (tok->tk_data + tok->tk_len)) {
+ printf("dwarfdump.conf error: "
+ "%s Missing register number (\"%s\" not valid) %s line %lu\n",
+ cmd, tok->tk_data, filename, lineno);
+ ++errcount;
+ return FALSE;
+ }
+ *val_out = val;
+ return TRUE;
+
+
+
+}
+
+/* We are guaranteed it's a reg: command, so parse that command
+ and record the interesting data.
+*/
+static int
+parsereg(char *cp, const char *fname, unsigned long lineno,
+ struct conf_internal_s *conf, struct comtable_s *comtab)
+{
+ size_t clen = comtab->namelen;
+ struct token_s regnum;
+ struct token_s tokreg;
+ unsigned long val = 0;
+ int ok = FALSE;
+ int res = FALSE;
+
+ cp = cp + clen + 1;
+ cp = get_token(cp, &tokreg);
+ cp = get_token(cp, &regnum);
+ if (tokreg.tk_len == 0) {
+ printf("dwarfdump.conf error: "
+ "reg: missing register name %s line %lu",
+ fname, lineno);
+ ++errcount;
+ return FALSE;
+
+ }
+ if (regnum.tk_len == 0) {
+ printf("dwarfdump.conf error: "
+ "reg: missing register number %s line %lu",
+ fname, lineno);
+ ++errcount;
+ return FALSE;
+ }
+
+ ok = make_a_number(comtab->name, fname, lineno, &regnum, &val);
+
+ if (!ok) {
+ ++errcount;
+ return FALSE;
+ }
+
+ add_to_reg_table(conf->conf_out, tokreg.tk_data, val, fname, lineno);
+
+ res = ensure_has_no_more_tokens(cp, fname, lineno);
+ return res;
+}
+
+/*
+ We are guaranteed it's an frame_interface: command.
+ Parse it and record the value data.
+*/
+static int
+parseframe_interface(char *cp, const char *fname, unsigned long lineno,
+ struct conf_internal_s *conf, struct comtable_s *comtab)
+{
+ size_t clen = comtab->namelen;
+ struct token_s tok;
+ unsigned long val = 0;
+ int ok = FALSE;
+ int res = FALSE;
+
+ cp = cp + clen + 1;
+ cp = get_token(cp, &tok);
+ if (tok.tk_len == 0) {
+ printf("dwarfdump.conf error: "
+ "%s missing interface number %s line %lu",
+ comtab->name, fname, lineno);
+ ++errcount;
+ return FALSE;
+ }
+
+ ok = make_a_number(comtab->name, fname, lineno, &tok, &val);
+
+ if (!ok) {
+ ++errcount;
+ return FALSE;
+ }
+ if (val != 2 && val != 3) {
+ printf("dwarfdump.conf error: "
+ "%s only interface numbers 2 or 3 are allowed, "
+ " not %lu. %s line %lu",
+ comtab->name, val, fname, lineno);
+ ++errcount;
+ return FALSE;
+ }
+
+ conf->conf_out->cf_interface_number = (int) val;
+ res = ensure_has_no_more_tokens(cp, fname, lineno);
+ return res;
+}
+
+/*
+ We are guaranteed it's a cfa_reg: command. Parse it
+ and record the important data.
+*/
+static int
+parsecfa_reg(char *cp, const char *fname, unsigned long lineno,
+ struct conf_internal_s *conf, struct comtable_s *comtab)
+{
+ size_t clen = comtab->namelen;
+ struct token_s tok;
+ unsigned long val = 0;
+ int ok = FALSE;
+ int res = FALSE;
+
+ cp = cp + clen + 1;
+ cp = get_token(cp, &tok);
+ if (tok.tk_len == 0) {
+ printf("dwarfdump.conf error: "
+ "%s missing cfa_reg number %s line %lu",
+ comtab->name, fname, lineno);
+ ++errcount;
+ return FALSE;
+ }
+
+ ok = make_a_number(comtab->name, fname, lineno, &tok, &val);
+
+ if (!ok) {
+ ++errcount;
+ return FALSE;
+ }
+ conf->conf_out->cf_cfa_reg = (int) val;
+ res = ensure_has_no_more_tokens(cp, fname, lineno);
+ return res;
+}
+
+
+/* We are guaranteed it's an initial_reg_value: command,
+ parse it and put the reg value where it will be remembered.
+*/
+static int
+parseinitial_reg_value(char *cp, const char *fname,
+ unsigned long lineno,
+ struct conf_internal_s *conf, struct comtable_s *comtab)
+{
+ size_t clen = comtab->namelen;
+ struct token_s tok;
+ unsigned long val = 0;
+ int ok = FALSE;
+ int res = FALSE;
+
+ cp = cp + clen + 1;
+ cp = get_token(cp, &tok);
+ if (tok.tk_len == 0) {
+ printf("dwarfdump.conf error: "
+ "%s missing initial reg value %s line %lu",
+ comtab->name, fname, lineno);
+ ++errcount;
+ return FALSE;
+ }
+
+ ok = make_a_number(comtab->name, fname, lineno, &tok, &val);
+
+ if (!ok) {
+
+ ++errcount;
+ return FALSE;
+ }
+ conf->conf_out->cf_initial_rule_value = (int) val;
+ res = ensure_has_no_more_tokens(cp, fname, lineno);
+ return res;
+}
+
+static int
+parsesame_val_reg(char *cp, const char *fname,
+ unsigned long lineno,
+ struct conf_internal_s *conf, struct comtable_s *comtab)
+{
+ size_t clen = comtab->namelen;
+ struct token_s tok;
+ unsigned long val = 0;
+ int ok = FALSE;
+ int res = FALSE;
+
+ cp = cp + clen + 1;
+ cp = get_token(cp, &tok);
+ if (tok.tk_len == 0) {
+ printf("dwarfdump.conf error: "
+ "%s missing same_reg value %s line %lu",
+ comtab->name, fname, lineno);
+ ++errcount;
+ return FALSE;
+ }
+
+ ok = make_a_number(comtab->name, fname, lineno, &tok, &val);
+
+ if (!ok) {
+
+ ++errcount;
+ return FALSE;
+ }
+ conf->conf_out->cf_same_val = (int) val;
+ res = ensure_has_no_more_tokens(cp, fname, lineno);
+ return res;
+}
+
+static int
+parseundefined_val_reg(char *cp, const char *fname,
+ unsigned long lineno,
+ struct conf_internal_s *conf, struct comtable_s *comtab)
+{
+ size_t clen = comtab->namelen;
+ struct token_s tok;
+ unsigned long val = 0;
+ int ok = FALSE;
+ int res = FALSE;
+
+ cp = cp + clen + 1;
+ cp = get_token(cp, &tok);
+ if (tok.tk_len == 0) {
+ printf("dwarfdump.conf error: "
+ "%s missing undefined_reg value %s line %lu",
+ comtab->name, fname, lineno);
+ ++errcount;
+ return FALSE;
+ }
+
+ ok = make_a_number(comtab->name, fname, lineno, &tok, &val);
+
+ if (!ok) {
+
+ ++errcount;
+ return FALSE;
+ }
+ conf->conf_out->cf_undefined_val = (int) val;
+ res = ensure_has_no_more_tokens(cp, fname, lineno);
+ return res;
+}
+
+
+
+/* We are guaranteed it's a table size command, parse it
+ and record the table size.
+*/
+static int
+parsereg_table_size(char *cp, const char *fname, unsigned long lineno,
+ struct conf_internal_s *conf, struct comtable_s *comtab)
+{
+ size_t clen = comtab->namelen;
+ struct token_s tok;
+ unsigned long val = 0;
+ int ok = FALSE;
+ int res = FALSE;
+
+ cp = cp + clen + 1;
+ cp = get_token(cp, &tok);
+ if (tok.tk_len == 0) {
+ printf("dwarfdump.conf error: "
+ "%s missing reg table size value %s line %lu",
+ comtab->name, fname, lineno);
+ ++errcount;
+ return FALSE;
+ }
+
+ ok = make_a_number(comtab->name, fname, lineno, &tok, &val);
+
+ if (!ok) {
+ ++errcount;
+ return FALSE;
+ }
+ conf->conf_out->cf_table_entry_count = (unsigned long) val;
+ res = ensure_has_no_more_tokens(cp, fname, lineno);
+ return res;
+}
+
+/* We are guaranteed it's a table size command, parse it
+ and record the table size.
+*/
+static int
+parseaddress_size(char *cp, const char *fname, unsigned long lineno,
+ struct conf_internal_s *conf, struct comtable_s *comtab)
+{
+ size_t clen = comtab->namelen;
+ struct token_s tok;
+ unsigned long val = 0;
+ int ok = FALSE;
+ int res = FALSE;
+
+ cp = cp + clen + 1;
+ cp = get_token(cp, &tok);
+ if (tok.tk_len == 0) {
+ printf("dwarfdump.conf error: "
+ "%s missing address size value %s line %lu",
+ comtab->name, fname, lineno);
+ ++errcount;
+ return FALSE;
+ }
+
+ ok = make_a_number(comtab->name, fname, lineno, &tok, &val);
+
+ if (!ok) {
+ ++errcount;
+ return FALSE;
+ }
+ conf->conf_out->cf_address_size = (unsigned long) val;
+ res = ensure_has_no_more_tokens(cp, fname, lineno);
+ return res;
+}
+
+
+/* We are guaranteed it's an endabi: command, parse it and
+ check we have the right abi.
+*/
+static int
+parseendabi(char *cp, const char *fname,
+ const char *abiname, unsigned long lineno,
+ struct comtable_s *comtab)
+{
+ size_t clen = comtab->namelen;
+ struct token_s tok;
+ int res = 0;
+
+
+ cp = cp + clen + 1;
+ cp = get_token(cp, &tok);
+ if (strcmp(abiname, tok.tk_data) != 0) {
+ printf("%s error: "
+ "mismatch abi name %s (here) vs. %s (beginabi:) %s line %lu\n",
+ comtab->name, tok.tk_data, abiname, fname, lineno);
+ ++errcount;
+ return FALSE;
+ }
+ res = ensure_has_no_more_tokens(cp, fname, lineno);
+ return res;
+}
+static int
+parseincludeabi(char *cp, const char *fname, unsigned long lineno,
+ char **abiname_out,
+ struct comtable_s *comtab)
+{
+ size_t clen = comtab->namelen;
+ struct token_s tok;
+ char *name = 0;
+ int res = FALSE;
+
+ cp = cp + clen + 1;
+ cp = get_token(cp, &tok);
+ name = makename(tok.tk_data);
+
+ *abiname_out = name;
+ res = ensure_has_no_more_tokens(cp, fname, lineno);
+ return res;
+}
+
+
+
+
+/* Return TRUE if we succeeded and filed in *out.
+ Return FALSE if we failed (and fill in nothing).
+ beginabi: <abiname>
+ reg: <regname> <dwarf regnumber>
+ frame_interface: <integer value 2 or 3>
+ cfa_reg: <number>
+ initial_reg_value: <number: normally 1034 or 1035 >
+ reg_table_size: <size of table>
+ endabi: <abiname>
+
+ We are positioned at the start of a beginabi: line when
+ called.
+
+*/
+static int
+parse_abi(FILE * stream, const char *fname, const char *abiname,
+ struct conf_internal_s *conf_internal,
+ unsigned long lineno,
+ unsigned int nest_level)
+{
+ struct dwconf_s *localconf = conf_internal->conf_out;
+ char buf[1000];
+ int comtype = 0;
+
+ static int first_time_done = 0;
+ struct comtable_s *comtabp = 0;
+
+ if( nest_level > MAX_NEST_LEVEL) {
+ ++errcount;
+ printf("dwarfdump.conf: includeabi nest too deep in %s at line %lu\n",
+ fname, lineno);
+ return FALSE;
+ }
+
+
+ if (first_time_done == 0) {
+ finish_comtable_setup();
+ first_time_done = 1;
+ }
+
+ for (; !feof(stream);) {
+ char *line = 0;
+
+ /* long loffset = ftell(stream); */
+ line = fgets(buf, sizeof(buf), stream);
+ if (!line) {
+ ++errcount;
+ printf
+ ("dwarfdump: end of file or error before endabi: in %s, line %lu\n",
+ fname, lineno);
+ return FALSE;
+ }
+ ++lineno;
+ line = skipwhite(line);
+ comtype = which_command(line, &comtabp);
+ switch (comtype) {
+ case LT_ERROR:
+ ++errcount;
+ printf
+ ("dwarfdump: Unknown text in %s is \"%s\" at line %lu\n",
+ fname, line, lineno);
+ break;
+ case LT_COMMENT:
+ break;
+ case LT_BLANK:
+ break;
+ case LT_BEGINABI:
+ if (conf_internal->beginabi_lineno > 0) {
+ ++errcount;
+ printf
+ ("dwarfdump: Encountered beginabi: when not expected. "
+ "%s line %lu previous beginabi line %lu\n", fname,
+ lineno, conf_internal->beginabi_lineno);
+ }
+ conf_internal->beginabi_lineno = lineno;
+ parsebeginabi(line, fname, abiname, lineno, comtabp);
+ break;
+
+ case LT_REG:
+ parsereg(line, fname, lineno, conf_internal, comtabp);
+ conf_internal->regcount++;
+ break;
+ case LT_FRAME_INTERFACE:
+ if (conf_internal->frame_interface_lineno > 0) {
+ ++errcount;
+ printf
+ ("dwarfdump: Encountered duplicate frame_interface: "
+ "%s line %lu previous frame_interface: line %lu\n",
+ fname, lineno, conf_internal->frame_interface_lineno);
+ }
+ conf_internal->frame_interface_lineno = lineno;
+ parseframe_interface(line, fname,
+ lineno, conf_internal, comtabp);
+ break;
+ case LT_CFA_REG:
+ if (conf_internal->cfa_reg_lineno > 0) {
+ printf("dwarfdump: Encountered duplicate cfa_reg: "
+ "%s line %lu previous cfa_reg line %lu\n",
+ fname, lineno, conf_internal->cfa_reg_lineno);
+ ++errcount;
+ }
+ conf_internal->cfa_reg_lineno = lineno;
+ parsecfa_reg(line, fname, lineno, conf_internal, comtabp);
+ break;
+ case LT_INITIAL_REG_VALUE:
+ if (conf_internal->initial_reg_value_lineno > 0) {
+ printf
+ ("dwarfdump: Encountered duplicate initial_reg_value: "
+ "%s line %lu previous initial_reg_value: line %lu\n",
+ fname, lineno, conf_internal->initial_reg_value_lineno);
+ ++errcount;
+ }
+ conf_internal->initial_reg_value_lineno = lineno;
+ parseinitial_reg_value(line, fname,
+ lineno, conf_internal, comtabp);
+ break;
+ case LT_SAME_VAL_REG:
+ if (conf_internal->same_val_reg_lineno > 0) {
+ ++errcount;
+ printf
+ ("dwarfdump: Encountered duplicate same_val_reg: "
+ "%s line %lu previous initial_reg_value: line %lu\n",
+ fname, lineno, conf_internal->initial_reg_value_lineno);
+ }
+ conf_internal->same_val_reg_lineno = lineno;
+ parsesame_val_reg(line, fname,
+ lineno, conf_internal, comtabp);
+ break;
+ case LT_UNDEFINED_VAL_REG:
+ if (conf_internal->undefined_val_reg_lineno > 0) {
+ ++errcount;
+ printf
+ ("dwarfdump: Encountered duplicate undefined_val_reg: "
+ "%s line %lu previous initial_reg_value: line %lu\n",
+ fname, lineno, conf_internal->initial_reg_value_lineno);
+ }
+ conf_internal->undefined_val_reg_lineno = lineno;
+ parseundefined_val_reg(line, fname,
+ lineno, conf_internal, comtabp);
+ break;
+ case LT_REG_TABLE_SIZE:
+ if (conf_internal->reg_table_size_lineno > 0) {
+ printf("dwarfdump: duplicate reg_table_size: "
+ "%s line %lu previous reg_table_size: line %lu\n",
+ fname, lineno, conf_internal->reg_table_size_lineno);
+ ++errcount;
+ }
+ conf_internal->reg_table_size_lineno = lineno;
+ parsereg_table_size(line, fname,
+ lineno, conf_internal, comtabp);
+ break;
+ case LT_ENDABI:
+ parseendabi(line, fname, abiname, lineno, comtabp);
+
+ if (conf_internal->regcount > localconf->cf_table_entry_count) {
+ printf("dwarfdump: more registers named than "
+ " in %s ( %lu named vs %s %lu) %s line %lu\n",
+ abiname, (unsigned long) conf_internal->regcount,
+ name_reg_table_size,
+ (unsigned long) localconf->cf_table_entry_count,
+ fname, (unsigned long) lineno);
+ ++errcount;
+ }
+ return TRUE;
+ case LT_ADDRESS_SIZE:
+ if (conf_internal->address_size_lineno > 0) {
+ printf("dwarfdump: duplicate address_size: "
+ "%s line %lu previous address_size: line %lu\n",
+ fname, lineno, conf_internal->address_size_lineno);
+ ++errcount;
+ }
+ conf_internal->address_size_lineno = lineno;
+ parseaddress_size(line, fname,
+ lineno, conf_internal, comtabp);
+ break;
+ case LT_INCLUDEABI: {
+ char *abiname_inner = 0;
+ unsigned long abilno = conf_internal->beginabi_lineno;
+ int ires = 0;
+ ires = parseincludeabi(line,fname,lineno, &abiname_inner,comtabp);
+ if(ires == FALSE) {
+ return FALSE;
+ }
+ /* For the nested abi read, the abi line number must be
+ set as if not-yet-read, and then restored. */
+ conf_internal->beginabi_lineno = 0;
+ find_conf_file_and_read_config_inner(
+ conf_internal->conf_name_used,
+ abiname_inner, conf_internal,nest_level+1);
+ conf_internal->beginabi_lineno = abilno;
+ }
+ break;
+ default:
+ printf
+ ("dwarfdump internal error, impossible line type %d %s %lu \n",
+ (int) comtype, fname, lineno);
+ exit(1);
+
+ }
+ }
+ ++errcount;
+ printf("End of file, no endabi: found. %s, line %lu\n",
+ fname, lineno);
+ return FALSE;
+}
+
+/* MIPS/IRIX frame register names.
+ For alternate name sets, use dwarfdump.conf or
+ revise dwarf.h and libdwarf.h and this table.
+*/
+static char *regnames[] = {
+ "cfa",
+ "r1/at", "r2/v0", "r3/v1",
+ "r4/a0", "r5/a1", "r6/a2", "r7/a3",
+ "r8/t0", "r9/t1", "r10/t2", "r11/t3",
+ "r12/t4", "r13/t5", "r14/t6", "r15/t7",
+ "r16/s0", "r17/s1", "r18/s2", "r19/s3",
+ "r20/s4", "r21/s5", "r22/s6", "r23/s7",
+ "r24/t8", "r25/t9", "r26/k0", "r27/k1",
+ "r28/gp", "r29/sp", "r30/s8", "r31",
+
+ "$f0", "$f1",
+ "$f2", "$f3",
+ "$f4", "$f5",
+ "$f6", "$f7",
+ "$f8", "$f9",
+ "$f10", "$f11",
+ "$f12", "$f13",
+ "$f14", "$f15",
+ "$f16", "$f17",
+ "$f18", "$f19",
+ "$f20", "$f21",
+ "$f22", "$f23",
+ "$f24", "$f25",
+ "$f26", "$f27",
+ "$f28", "$f29",
+ "$f30", "$f31",
+ "ra", "slk",
+};
+
+
+/* Naming a few registers makes printing these just
+ a little bit faster.
+*/
+static char *genericregnames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
+ "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19",
+ "r20"
+};
+
+/* This is a simple generic set of registers. The
+ table entry count is pretty arbitrary.
+*/
+void
+init_conf_file_data(struct dwconf_s *config_file_data)
+{
+ unsigned generic_table_count;
+ config_file_data->cf_abi_name = "";
+ config_file_data->cf_config_file_path = "";
+ config_file_data->cf_interface_number = 3;
+ config_file_data->cf_table_entry_count = 100;
+ config_file_data->cf_initial_rule_value = DW_FRAME_UNDEFINED_VAL;
+ config_file_data->cf_cfa_reg = DW_FRAME_CFA_COL3;
+ config_file_data->cf_address_size = 0;
+ config_file_data->cf_same_val = DW_FRAME_SAME_VAL;
+ config_file_data->cf_undefined_val = DW_FRAME_UNDEFINED_VAL;
+ config_file_data->cf_regs = genericregnames;
+ generic_table_count =
+ sizeof(genericregnames) / sizeof(genericregnames[0]);
+ config_file_data->cf_named_regs_table_size = generic_table_count;
+ config_file_data->cf_regs_malloced = 0;
+}
+
+/* These defaults match MIPS/IRIX ABI defaults, but this
+ function is not actually used.
+ For a 'generic' ABI, see -R or init_conf_file_data().
+ To really get the old MIPS, use '-x abi=mips'.
+ For other ABIs, see -x abi=<whatever>
+ to configure dwarfdump (and libdwarf) frame
+ data reporting at runtime.
+*/
+void
+init_mips_conf_file_data(struct dwconf_s *config_file_data)
+{
+ unsigned long base_table_count =
+ sizeof(regnames) / sizeof(regnames[0]);
+
+ memset(config_file_data, 0, sizeof(*config_file_data));
+ /* Interface 2 is deprecated, but for testing purposes
+ is acceptable. */
+ config_file_data->cf_interface_number = 2;
+ config_file_data->cf_table_entry_count = DW_REG_TABLE_SIZE;
+ config_file_data->cf_initial_rule_value =
+ DW_FRAME_REG_INITIAL_VALUE;
+ config_file_data->cf_cfa_reg = DW_FRAME_CFA_COL;
+ config_file_data->cf_address_size = 0;
+ config_file_data->cf_same_val = DW_FRAME_SAME_VAL;
+ config_file_data->cf_undefined_val = DW_FRAME_UNDEFINED_VAL;
+ config_file_data->cf_regs = regnames;
+ config_file_data->cf_named_regs_table_size = base_table_count;
+ config_file_data->cf_regs_malloced = 0;
+ if (config_file_data->cf_table_entry_count != base_table_count) {
+ printf("dwarfdump: improper base table initization, "
+ "header files wrong: "
+ "DW_REG_TABLE_SIZE %u != string table size %lu\n",
+ (unsigned) DW_REG_TABLE_SIZE,
+ (unsigned long) base_table_count);
+ exit(1);
+ }
+ return;
+}
+
+/* A 'generic' ABI. For up to 1200 registers.
+ Perhaps cf_initial_rule_value should be d
+ UNDEFINED VALUE (1034) instead, but for the purposes of
+ getting the dwarfdump output correct
+ either will work.
+*/
+void
+init_generic_config_1200_regs(struct dwconf_s *config_file_data)
+{
+ unsigned long generic_table_count =
+ sizeof(genericregnames) / sizeof(genericregnames[0]);
+ config_file_data->cf_interface_number = 3;
+ config_file_data->cf_table_entry_count = 1200;
+ /* There is no defined name for cf_initial_rule_value,
+ cf_same_val, or cf_undefined_val in libdwarf.h,
+ these must just be high enough to be higher than
+ any real register number.
+ DW_FRAME_CFA_COL3 must also be higher than any
+ real register number. */
+ config_file_data->cf_initial_rule_value = 1235; /* SAME VALUE */
+ config_file_data->cf_cfa_reg = DW_FRAME_CFA_COL3;
+ config_file_data->cf_address_size = 0;
+ config_file_data->cf_same_val = 1235;
+ config_file_data->cf_undefined_val = 1234;
+ config_file_data->cf_regs = genericregnames;
+ config_file_data->cf_named_regs_table_size = generic_table_count;
+ config_file_data->cf_regs_malloced = 0;
+}
+
+/* Print the 'right' string for the register we are given.
+ Deal sensibly with the special regs as well as numbers
+ we know and those we have not been told about.
+
+*/
+void
+print_reg_from_config_data(Dwarf_Signed reg,
+ struct dwconf_s *config_data)
+{
+ char *name = 0;
+
+ if (reg == config_data->cf_cfa_reg) {
+ fputs("cfa",stdout);
+ return;
+ }
+ if (reg == config_data->cf_undefined_val) {
+ fputs("u",stdout);
+ return;
+ }
+ if (reg == config_data->cf_same_val) {
+ fputs("s",stdout);
+ return;
+ }
+
+ if (config_data->cf_regs == 0 ||
+ reg < 0 ||
+ reg >= config_data->cf_named_regs_table_size) {
+ printf("r%" DW_PR_DSd "", (Dwarf_Signed) reg);
+ return;
+ }
+ name = config_data->cf_regs[reg];
+ if (!name) {
+ /* Can happen, the reg names table can be sparse. */
+ printf("r%" DW_PR_DSd "", (Dwarf_Signed) reg);
+ return;
+ }
+ fputs(name,stdout);
+ return;
+}
diff --git a/dwarfdump/dwconf.h b/dwarfdump/dwconf.h
new file mode 100644
index 0000000..471a3d4
--- /dev/null
+++ b/dwarfdump/dwconf.h
@@ -0,0 +1,106 @@
+/*
+ Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+ $Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/dwconf.h,v 1.2 2006/04/18 04:29:39 davea Exp $ */
+
+
+/* declarations helping configure the frame reader. */
+struct dwconf_s {
+ char *cf_config_file_path;
+ char *cf_abi_name;
+
+ /* 2 for old, 3 for frame interface 3. 2 means use the old
+ mips-abi-oriented frame interface. 3 means use the new
+ DWARF3-capable and configureable-abi interface.
+
+ Now, anyone who revises dwarf.h and libdwarf.h to match their
+ abi-of-interest will still be able to use cf_interface_number 2
+ as before. But most folks don't update those header files and
+ instead of making *them* configurable we make dwarfdump (and
+ libdwarf) configurable sufficiently to print frame information
+ sensibly. */
+ int cf_interface_number;
+
+ /* The number of table rules , aka columns. For MIPS/IRIX is 66. */
+ unsigned long cf_table_entry_count;
+
+ /* Array of cf_table_entry_count reg names. Names not filled in
+ from dwarfdump.conf have NULL (0) pointer value.
+ cf_named_regs_table_size must match size of cf_regs array.
+ Set cf_regs_malloced 1 if table was malloced. Set 0
+ if static.
+ */
+ char **cf_regs;
+ unsigned long cf_named_regs_table_size;
+ int cf_regs_malloced;
+
+ /* The 'default initial value' when intializing a table. for MIPS
+ is DW_FRAME_SAME_VAL(1035). For other ISA/ABIs may be
+ DW_FRAME_UNDEFINED_VAL(1034). */
+ int cf_initial_rule_value;
+ int cf_same_val;
+ int cf_undefined_val;
+
+ /* The number of the cfa 'register'. For cf_interface_number 2 of
+ MIPS this is 0. For other architectures (and anytime using
+ cf_interface_number 3) this should be outside the table, a
+ special value such as 1436, not a table column at all). */
+ int cf_cfa_reg;
+
+ /* If non-zero it is the number of bytes in an address
+ for the frame data. Normally it will be zero because
+ there are usually other sources for the correct address size.
+ However, with DWARF2 frame data there is no explicit address
+ size in the frame data and the object file might not have
+ other .debug_ sections to work with.
+ If zero, no address size was supplied, and that is normal and
+ the already-set (or defaulted) address size is to be used.
+ Only an exceptional frame configure will specify address
+ size here. This won't work at all if the object needing
+ this setting has different address size in different CUs. */
+ int cf_address_size;
+};
+
+
+/* Returns DW_DLV_OK if works. DW_DLV_ERROR if cannot do what is asked. */
+int find_conf_file_and_read_config(const char *named_file,
+ const char *named_abi, char **defaults,
+ struct dwconf_s *conf_out);
+void init_conf_file_data(struct dwconf_s *config_file_data);
+void init_mips_conf_file_data(struct dwconf_s *config_file_data);
+
+void print_reg_from_config_data(Dwarf_Signed reg,
+ struct dwconf_s *config_data);
+
+
+void init_generic_config_1200_regs(struct dwconf_s *conf);
diff --git a/dwarfdump/esb.c b/dwarfdump/esb.c
new file mode 100644
index 0000000..8c806c8
--- /dev/null
+++ b/dwarfdump/esb.c
@@ -0,0 +1,242 @@
+/*
+ Copyright (C) 2005 Silicon Graphics, Inc. All Rights Reserved.
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/esb.c,v 1.1 2005/08/04 05:09:37 davea Exp $ */
+
+/* esb.c
+ extensible string buffer.
+
+ A simple means (vaguely like a C++ class) that
+ enables safely saving strings of arbitrary length built up
+ in small pieces.
+
+*/
+
+#include "globals.h"
+#include <stdarg.h> /* For va_start etc. */
+#include "esb.h"
+
+#define INITIAL_ALLOC 1024
+static size_t alloc_size = INITIAL_ALLOC;
+
+
+static void
+init_esb_string(struct esb_s *data, size_t min_len)
+{
+ string d;
+
+ if (data->esb_allocated_size > 0) {
+ return;
+ }
+ if (min_len < alloc_size) {
+ min_len = alloc_size;
+ }
+ d = malloc(min_len);
+ if (!d) {
+ fprintf(stderr,
+ "dwarfdump is out of memory allocating %lu bytes\n",
+ (unsigned long) min_len);
+ exit(5);
+ }
+ data->esb_string = d;
+ data->esb_allocated_size = min_len;
+ data->esb_string[0] = 0;
+ data->esb_used_bytes = 0;
+}
+
+/* Make more room. Leaving contents unchanged, effectively.
+*/
+static void
+allocate_more(struct esb_s *data, size_t len)
+{
+ size_t new_size = data->esb_allocated_size + len;
+ string newd = 0;
+
+ if (new_size < alloc_size)
+ new_size = alloc_size;
+ newd = realloc(data->esb_string, new_size);
+ if (!newd) {
+ fprintf(stderr, "dwarfdump is out of memory re-allocating "
+ "%lu bytes\n", (unsigned long) new_size);
+ exit(5);
+ }
+ data->esb_string = newd;
+ data->esb_allocated_size = new_size;
+}
+
+static void
+esb_appendn_internal(struct esb_s *data, const char * in_string, size_t len);
+
+void
+esb_appendn(struct esb_s *data, const char * in_string, size_t len)
+{
+ size_t full_len = strlen(in_string);
+
+ if (full_len < len) {
+ fprintf(stderr, "dwarfdump internal error, bad string length "
+ " %lu < %lu \n",
+ (unsigned long) full_len, (unsigned long) len);
+ len = full_len;
+ }
+
+ esb_appendn_internal(data, in_string, len);
+}
+
+/* The length is gotten from the in_string itself. */
+void
+esb_append(struct esb_s *data, const char * in_string)
+{
+ size_t len = strlen(in_string);
+
+ esb_appendn_internal(data, in_string, len);
+}
+
+/* The 'len' is believed. Do not pass in strings < len bytes long. */
+static void
+esb_appendn_internal(struct esb_s *data, const char * in_string, size_t len)
+{
+ size_t remaining = 0;
+ size_t needed = len + 1;
+
+ if (data->esb_allocated_size == 0) {
+ size_t maxlen = (len > alloc_size) ? len : alloc_size;
+
+ init_esb_string(data, maxlen);
+ }
+ remaining = data->esb_allocated_size - data->esb_used_bytes;
+ if (remaining < needed) {
+ allocate_more(data, needed);
+ }
+ strncpy(&data->esb_string[data->esb_used_bytes], in_string, len);
+ data->esb_used_bytes += len;
+ /* Insist on explicit NUL terminator */
+ data->esb_string[data->esb_used_bytes] = 0;
+}
+
+/* Always returns an empty string or a non-empty string. Never 0. */
+string
+esb_get_string(struct esb_s *data)
+{
+ if (data->esb_allocated_size == 0) {
+ init_esb_string(data, alloc_size);
+ }
+ return data->esb_string;
+}
+
+
+/* Sets esb_used_bytes to zero. The string is not freed and
+ esb_allocated_size is unchanged. */
+void
+esb_empty_string(struct esb_s *data)
+{
+ if (data->esb_allocated_size == 0) {
+ init_esb_string(data, alloc_size);
+ }
+ data->esb_used_bytes = 0;
+ data->esb_string[0] = 0;
+
+}
+
+
+/* Return esb_used_bytes. */
+size_t
+esb_string_len(struct esb_s *data)
+{
+ return data->esb_used_bytes;
+}
+
+
+/* The following are for testing esb, not use by dwarfdump. */
+
+/* *data is presumed to contain garbage, not values, and
+ is properly initialized. */
+void
+esb_constructor(struct esb_s *data)
+{
+ memset(data, 0, sizeof(*data));
+}
+
+/* The string is freed, contents of *data set to zeroes. */
+void
+esb_destructor(struct esb_s *data)
+{
+ if (data->esb_string) {
+ free(data->esb_string);
+ }
+ esb_constructor(data);
+}
+
+
+/* To get all paths in the code tested, this sets the
+ allocation/reallocation to the given value, which can be quite small
+ but must not be zero. */
+void
+esb_alloc_size(size_t size)
+{
+ alloc_size = size;
+}
+
+size_t
+esb_get_allocated_size(struct esb_s *data)
+{
+ return data->esb_allocated_size;
+}
+
+/* Append a formatted string */
+void
+esb_append_printf(struct esb_s *data,const char *in_string, ...)
+{
+#if WIN32
+ #define NULL_DEVICE_FILE "NUL"
+#else
+ #define NULL_DEVICE_FILE "/dev/null"
+#endif /* WIN32 */
+
+ static FILE *null_file = NULL;
+
+ int needed_size = 0;
+ int length = 0;
+ va_list ap;
+ va_start(ap,in_string);
+ if (null_file == NULL) {
+ null_file = fopen(NULL_DEVICE_FILE,"w");
+ }
+ length = vfprintf(null_file,in_string,ap);
+
+ /* Check if we require allocate more space */
+ needed_size = data->esb_used_bytes + length;
+ if (needed_size > data->esb_allocated_size) {
+ allocate_more(data,length);
+ }
+ vsprintf(&data->esb_string[data->esb_used_bytes],in_string,ap);
+ data->esb_used_bytes += length;
+ va_end(ap);
+}
diff --git a/dwarfdump/esb.h b/dwarfdump/esb.h
new file mode 100644
index 0000000..260db07
--- /dev/null
+++ b/dwarfdump/esb.h
@@ -0,0 +1,86 @@
+/*
+ Copyright (C) 2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2011 David Anderson. All Rights Reserved.
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+ $Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/esb.h,v 1.1 2005/08/04 05:09:37 davea Exp $ */
+
+
+/* esb.h
+ Extensible string buffer.
+ A simple vaguely object oriented extensible string buffer.
+
+ The struct could be opaque here, but it seems ok to expose
+ the contents: simplifies debugging.
+*/
+
+
+struct esb_s {
+ string esb_string; /* pointer to the data itself, or NULL. */
+ size_t esb_allocated_size; /* Size of allocated data or 0 */
+ size_t esb_used_bytes; /* Amount of space used or 0 */
+};
+
+/* string length taken from string itself. */
+void esb_append(struct esb_s *data, const char * in_string);
+
+/* The 'len' is believed. Do not pass in strings < len bytes long. */
+void esb_appendn(struct esb_s *data, const char * in_string, size_t len);
+
+/* Always returns an empty string or a non-empty string. Never 0. */
+string esb_get_string(struct esb_s *data);
+
+
+/* Sets esb_used_bytes to zero. The string is not freed and
+ esb_allocated_size is unchanged. */
+void esb_empty_string(struct esb_s *data);
+
+
+/* Return esb_used_bytes. */
+size_t esb_string_len(struct esb_s *data);
+
+/* The following are for testing esb, not use by dwarfdump. */
+
+/* *data is presumed to contain garbage, not values, and
+ is properly initialized. */
+void esb_constructor(struct esb_s *data);
+
+/* The string is freed, contents of *data set to zeroes. */
+void esb_destructor(struct esb_s *data);
+
+
+/* To get all paths in the code tested, this sets the
+ allocation/reallocation to the given value, which can be quite small
+ but must not be zero. */
+void esb_alloc_size(size_t size);
+size_t esb_get_allocated_size(struct esb_s *data);
+
+/* Append a formatted string */
+void esb_append_printf(struct esb_s *data,const char *in_string, ...);
diff --git a/dwarfdump/globals.h b/dwarfdump/globals.h
new file mode 100644
index 0000000..46cbc11
--- /dev/null
+++ b/dwarfdump/globals.h
@@ -0,0 +1,459 @@
+/*
+ Copyright (C) 2000,2004,2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/globals.h,v 1.25 2006/04/17 00:09:56 davea Exp $ */
+
+#ifndef globals_INCLUDED
+#define globals_INCLUDED
+
+#include "config.h"
+#if (!defined(HAVE_RAW_LIBELF_OK) && defined(HAVE_LIBELF_OFF64_OK) )
+/* At a certain point libelf.h requires _GNU_SOURCE.
+ here we assume the criteria in configure determine that
+ usefully.
+*/
+#define _GNU_SOURCE 1
+#endif
+
+/* We want __uint32_t and __uint64_t and __int32_t __int64_t
+ properly defined but not duplicated, since duplicate typedefs
+ are not legal C.
+ HAVE___UINT32_T
+ HAVE___UINT64_T will be set by configure if
+ our 4 types are predefined in compiler
+*/
+
+
+#if (!defined(HAVE___UINT32_T)) && defined(HAVE_SGIDEFS_H)
+#include <sgidefs.h> /* sgidefs.h defines them */
+#define HAVE___UINT32_T 1
+#define HAVE___UINT64_T 1
+#endif
+
+
+
+#if (!defined(HAVE___UINT32_T)) && defined(HAVE_SYS_TYPES_H) && defined(HAVE___UINT32_T_IN_SYS_TYPES_H)
+# include <sys/types.h>
+/* we assume __[u]int32_t and __[u]int64_t defined
+ since __uint32_t defined in the sys/types.h in use */
+#define HAVE___UINT32_T 1
+#define HAVE___UINT64_T 1
+#endif
+
+#ifndef HAVE___UINT32_T
+typedef int __int32_t;
+typedef unsigned __uint32_t;
+#define HAVE___UINT32_T 1
+#endif
+#ifndef HAVE___UINT64_T
+typedef long long __int64_t;
+typedef unsigned long long __uint64_t;
+#define HAVE___UINT64_T 1
+#endif
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Windows specific */
+#ifdef HAVE_STDAFX_H
+#include "stdafx.h"
+#endif /* HAVE_STDAFX_H */
+
+#ifdef HAVE_ELF_H
+#include <elf.h>
+#endif
+#ifdef HAVE_LIBELF_H
+#include <libelf.h>
+#else
+#ifdef HAVE_LIBELF_LIBELF_H
+#include <libelf/libelf.h>
+#endif
+#endif
+#include <dwarf.h>
+#include <libdwarf.h>
+#ifdef HAVE_REGEX
+#include <regex.h>
+#endif
+typedef char * string;
+
+#include "checkutil.h"
+#ifndef BOOLEAN_TYPEDEFED
+#define BOOLEAN_TYPEDEFED
+typedef int boolean;
+#endif /* BOOLEAN_TYPEDEFED */
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FAILED
+#define FAILED 1
+#endif
+
+/* size of attrib_buffer, defined in print_die.c */
+#define ATTRIB_BUFSIZ 999
+
+typedef struct {
+ int checks;
+ int errors;
+} Dwarf_Check_Result;
+
+extern boolean do_check_dwarf;
+extern boolean do_print_dwarf;
+
+extern boolean record_dwarf_error; /* A test has failed, this
+ is normally set FALSE shortly after being set TRUE, it is
+ a short-range hint we should print something we might not
+ otherwise print (under the circumstances). */
+
+/* Compilation Unit information for improved error messages.
+ If the strings are too short we just truncate so fixed length
+ here is fine. */
+#define COMPILE_UNIT_NAME_LEN 512
+extern char PU_name[COMPILE_UNIT_NAME_LEN]; /* PU Name */
+extern char CU_name[COMPILE_UNIT_NAME_LEN]; /* CU Name */
+extern char CU_producer[COMPILE_UNIT_NAME_LEN]; /* CU Producer Name */
+
+extern boolean seen_PU; /* Detected a PU. */
+extern boolean seen_CU; /* Detected a CU. */
+extern boolean need_CU_name; /* Need CU name. */
+extern boolean need_CU_base_address; /* Need CU Base address. */
+extern boolean need_CU_high_address; /* Need CU High address. */
+extern boolean need_PU_valid_code; /* Need PU valid code. */
+
+extern boolean seen_PU_base_address; /* Detected a Base address for PU */
+extern boolean seen_PU_high_address; /* Detected a High address for PU */
+extern Dwarf_Addr PU_base_address; /* PU Base address */
+extern Dwarf_Addr PU_high_address; /* PU High address */
+
+extern Dwarf_Off DIE_offset; /* DIE offset in compile unit. */
+extern Dwarf_Off DIE_overall_offset; /* DIE offset in .debug_info. */
+
+/* Current CU information for better error reporting. */
+extern Dwarf_Off DIE_CU_offset; /* CU DIE offset in compile unit */
+extern Dwarf_Off DIE_CU_overall_offset; /* CU DIE offset in .debug_info */
+extern int current_section_id; /* Section being process. */
+
+extern Dwarf_Addr CU_base_address; /* CU Base address. */
+extern Dwarf_Addr CU_high_address; /* CU High address. */
+
+extern Dwarf_Addr elf_max_address; /* Largest representable
+ address offset. */
+extern Dwarf_Half elf_address_size; /* Target pointer size. */
+
+/* Ranges and Location tables for better error checking: see
+ dwarfdump.c comments for more information. */
+extern Bucket_Group *pRangesInfo;
+extern Bucket_Group *pLinkonceInfo;
+extern Bucket_Group *pVisitedInfo;
+
+/* Display parent/children when in wide format. */
+extern boolean display_parent_tree;
+extern boolean display_children_tree;
+extern int stop_indent_level;
+
+/* Print search results when in wide format. */
+extern boolean search_wide_format;
+extern boolean search_is_on;
+
+const extern char *search_any_text;
+const extern char *search_match_text;
+const extern char *search_regex_text;
+#ifdef HAVE_REGEX
+extern regex_t search_re;
+#endif
+extern boolean is_strstrnocase(const char *data, const char *pattern);
+
+/* Options to enable debug tracing. */
+#define MAX_TRACE_LEVEL 10
+extern int nTrace[MAX_TRACE_LEVEL + 1];
+
+#define DUMP_RANGES_INFO 1 /* Dump RangesInfo Table. */
+#define DUMP_LOCATION_SECTION_INFO 2 /* Dump Location (.debug_loc) Info. */
+#define DUMP_RANGES_SECTION_INFO 3 /* Dump Ranges (.debug_ranges) Info. */
+#define DUMP_LINKONCE_INFO 4 /* Dump Linkonce Table. */
+#define DUMP_VISITED_INFO 5 /* Dump Visited Info. */
+
+#define dump_ranges_info nTrace[DUMP_RANGES_INFO]
+#define dump_location_section_info nTrace[DUMP_LOCATION_SECTION_INFO]
+#define dump_ranges_section_info nTrace[DUMP_RANGES_SECTION_INFO]
+#define dump_linkonce_info nTrace[DUMP_LINKONCE_INFO]
+#define dump_visited_info nTrace[DUMP_VISITED_INFO]
+
+/* Section IDs */
+#define DEBUG_ABBREV 1
+#define DEBUG_ARANGES 2
+#define DEBUG_FRAME 3
+#define DEBUG_INFO 4
+#define DEBUG_LINE 5
+#define DEBUG_LOC 6
+#define DEBUG_MACINFO 7
+#define DEBUG_PUBNAMES 8
+#define DEBUG_RANGES 9
+#define DEBUG_STATIC_VARS 10
+#define DEBUG_STATIC_FUNC 11
+#define DEBUG_STR 12
+#define DEBUG_WEAKNAMES 13
+#define DEBUG_TYPES 14
+
+extern int verbose;
+extern boolean dense;
+extern boolean ellipsis;
+extern boolean use_mips_regnames;
+extern boolean show_global_offsets;
+extern boolean show_form_used;
+extern boolean display_offsets;
+
+extern boolean check_pubname_attr;
+extern boolean check_attr_tag;
+extern boolean check_tag_tree;
+extern boolean check_type_offset;
+extern boolean check_decl_file;
+extern boolean check_lines;
+extern boolean check_ranges; /* Ranges (aranges & ranges) check */
+extern boolean check_fdes;
+extern boolean check_aranges;
+extern boolean check_harmless;
+extern boolean check_abbreviations;
+extern boolean check_dwarf_constants;
+extern boolean check_di_gaps;
+extern boolean check_forward_decl;
+extern boolean check_self_references;
+extern boolean suppress_nested_name_search;
+extern boolean suppress_check_extensions_tables;
+
+extern int break_after_n_units;
+
+extern boolean check_names; /* Check for invalid names */
+extern boolean check_verbose_mode; /* During '-k' mode, display errors */
+extern boolean check_frames; /* Frames check */
+extern boolean check_frames_extended;/* Extensive frames check */
+extern boolean check_locations; /* Location list check */
+
+/* Check categories corresponding to the -k option */
+typedef enum /* Dwarf_Check_Categories */ {
+ abbrev_code_result,
+ pubname_attr_result,
+ reloc_offset_result,
+ attr_tag_result,
+ tag_tree_result,
+ type_offset_result,
+ decl_file_result,
+ ranges_result,
+ lines_result,
+ aranges_result,
+ /* Harmless errors are errors detected inside libdwarf but
+ not reported via DW_DLE_ERROR returns because the errors
+ won't really affect client code. The 'harmless' errors
+ are reported and otherwise ignored. It is difficult to report
+ the error when the error is noticed by libdwarf, the error
+ is reported at a later time.
+ The other errors dwarfdump reports are also generally harmless
+ but are detected by dwarfdump so it's possble to report the
+ error as soon as the error is discovered. */
+ harmless_result,
+ fde_duplication,
+ frames_result,
+ locations_result,
+ names_result,
+ abbreviations_result,
+ dwarf_constants_result,
+ di_gaps_result,
+ forward_decl_result,
+ self_references_result,
+ total_check_result,
+ LAST_CATEGORY /* Must be last */
+} Dwarf_Check_Categories;
+
+extern boolean info_flag;
+extern boolean line_flag;
+extern boolean use_old_dwarf_loclist;
+extern boolean producer_children_flag; /* List of CUs per compiler */
+
+extern char cu_name[ ];
+extern boolean cu_name_flag;
+extern Dwarf_Unsigned cu_offset;
+extern Dwarf_Off fde_offset_for_cu_low;
+extern Dwarf_Off fde_offset_for_cu_high;
+
+/* Process TAGs for checking mode and reset pRangesInfo table
+ if appropriate. */
+extern void tag_specific_checks_setup(Dwarf_Half val,int die_indent_level);
+
+extern char *program_name;
+extern Dwarf_Error err;
+extern void print_error_and_continue (Dwarf_Debug dbg, string msg,int res, Dwarf_Error err);
+extern void print_error (Dwarf_Debug dbg, string msg,int res, Dwarf_Error err);
+
+extern void print_line_numbers_this_cu (Dwarf_Debug dbg, Dwarf_Die in_die);
+
+struct dwconf_s;
+extern void print_frames (Dwarf_Debug dbg, int print_debug_frame,
+ int print_eh_frame,struct dwconf_s *);
+extern void print_ranges (Dwarf_Debug dbg);
+extern void print_pubnames (Dwarf_Debug dbg);
+extern void print_macinfo (Dwarf_Debug dbg);
+extern void print_infos (Dwarf_Debug dbg,Dwarf_Bool is_info);
+extern void print_locs (Dwarf_Debug dbg);
+extern void print_abbrevs (Dwarf_Debug dbg);
+extern void print_strings (Dwarf_Debug dbg);
+extern void print_aranges (Dwarf_Debug dbg);
+extern void print_relocinfo (Dwarf_Debug dbg,unsigned reloc_map);
+extern void print_static_funcs(Dwarf_Debug dbg);
+extern void print_static_vars(Dwarf_Debug dbg);
+enum type_type_e {SGI_TYPENAME, DWARF_PUBTYPES} ;
+extern void print_types(Dwarf_Debug dbg,enum type_type_e type_type);
+extern void print_weaknames(Dwarf_Debug dbg);
+extern void print_exception_tables(Dwarf_Debug dbg);
+
+struct esb_s;
+extern void print_ranges_list_to_extra(Dwarf_Debug dbg,
+ Dwarf_Unsigned off,
+ Dwarf_Ranges *rangeset,
+ Dwarf_Signed rangecount,
+ Dwarf_Unsigned bytecount,
+ struct esb_s *stringbuf);
+boolean should_skip_this_cu(Dwarf_Debug dbg, Dwarf_Die cu_die, Dwarf_Error err);
+
+/* Returns the DW_AT_name of the CU */
+string old_get_cu_name(Dwarf_Debug dbg,Dwarf_Die cu_die,Dwarf_Error err);
+
+/* Returns the producer of the CU */
+int get_cu_name(Dwarf_Debug dbg,Dwarf_Die cu_die,
+ Dwarf_Error err,char **short_name,char **long_name);
+int get_producer_name(Dwarf_Debug dbg,Dwarf_Die cu_die,
+ Dwarf_Error err,char **producer_name);
+
+/* Get number of abbreviations for a CU */
+extern void get_abbrev_array_info(Dwarf_Debug dbg,Dwarf_Unsigned offset);
+/* Validate an abbreviation */
+extern void validate_abbrev_code(Dwarf_Debug dbg,Dwarf_Unsigned abbrev_code);
+
+extern void print_die_and_children(
+ Dwarf_Debug dbg,
+ Dwarf_Die in_die,
+ Dwarf_Bool is_info,
+ char **srcfiles,
+ Dwarf_Signed cnt);
+extern boolean print_one_die(
+ Dwarf_Debug dbg,
+ Dwarf_Die die,
+ boolean print_information,
+ int die_indent_level,
+ char **srcfiles,
+ Dwarf_Signed cnt,
+ boolean ignore_die_stack);
+
+/* Check for specific compiler */
+extern boolean checking_this_compiler();
+extern void update_compiler_target(const char *producer_name);
+extern void add_cu_name_compiler_target(char *name);
+
+/* General error reporting routines. These were
+ macros for a short time and when changed into functions
+ they kept (for now) their capitalization.
+ The capitalization will likely change. */
+extern void PRINT_CU_INFO();
+extern void DWARF_CHECK_COUNT(Dwarf_Check_Categories category, int inc);
+extern void DWARF_ERROR_COUNT(Dwarf_Check_Categories category, int inc);
+extern void DWARF_CHECK_ERROR_PRINT_CU();
+extern void DWARF_CHECK_ERROR(Dwarf_Check_Categories category,
+ const char *str);
+extern void DWARF_CHECK_ERROR2(Dwarf_Check_Categories category,
+ const char *str1, const char *str2);
+extern void DWARF_CHECK_ERROR3(Dwarf_Check_Categories category,
+ const char *str1, const char *str2, const char *strexpl);
+
+struct esb_s;
+
+extern Dwarf_Die current_cu_die_for_print_frames; /* This is
+ an awful hack, making current_cu_die_for_print_frames public.
+ But it enables cleaning up (doing all dealloc needed). */
+
+extern void printreg(Dwarf_Signed reg,struct dwconf_s *config_data);
+extern void print_frame_inst_bytes(Dwarf_Debug dbg,
+ Dwarf_Ptr cie_init_inst, Dwarf_Signed len,
+ Dwarf_Signed data_alignment_factor,
+ int code_alignment_factor, Dwarf_Half addr_size,
+ struct dwconf_s *config_data);
+
+int
+get_proc_name(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr low_pc,
+ char *proc_name_buf, int proc_name_buf_len, void **pcMap);
+
+void get_attr_value(Dwarf_Debug dbg, Dwarf_Half tag,
+ Dwarf_Die die,
+ Dwarf_Attribute attrib,
+ char **srcfiles,
+ Dwarf_Signed cnt, struct esb_s *esbp,
+ int show_form,int local_verbose);
+
+
+extern Dwarf_Unsigned local_dwarf_decode_u_leb128(unsigned char *leb128,
+ unsigned int *leb128_length);
+
+extern Dwarf_Signed local_dwarf_decode_s_leb128(unsigned char *leb128,
+ unsigned int *leb128_length);
+
+extern void dump_block(char *prefix, char *data, Dwarf_Signed len);
+
+extern void format_sig8_string(Dwarf_Sig8 *data,struct esb_s *out);
+
+int
+dwarfdump_print_one_locdesc(Dwarf_Debug dbg,
+ Dwarf_Locdesc * llbuf,
+ int skip_locdesc_header,
+ struct esb_s *string_out);
+void clean_up_die_esb();
+void clean_up_syms_malloc_data();
+void safe_strcpy(char *out, long outlen, const char *in, long inlen);
+
+
+void print_any_harmless_errors(Dwarf_Debug dbg);
+
+/* Definitions for printing relocations. */
+#define DW_SECTION_REL_DEBUG_INFO 0
+#define DW_SECTION_REL_DEBUG_LINE 1
+#define DW_SECTION_REL_DEBUG_PUBNAMES 2
+#define DW_SECTION_REL_DEBUG_ABBREV 3
+#define DW_SECTION_REL_DEBUG_ARANGES 4
+#define DW_SECTION_REL_DEBUG_FRAME 5
+#define DW_SECTION_REL_DEBUG_LOC 6
+#define DW_SECTION_REL_DEBUG_RANGES 7
+#define DW_SECTION_REL_DEBUG_TYPES 8
+
+#endif /* globals_INCLUDED */
diff --git a/dwarfdump/install.sh b/dwarfdump/install.sh
new file mode 100755
index 0000000..0ff4b6a
--- /dev/null
+++ b/dwarfdump/install.sh
@@ -0,0 +1,119 @@
+#!/bin/sh
+
+#
+# install - install a program, script, or datafile
+# This comes from X11R5; it is not part of GNU.
+#
+# $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+
+instcmd="$mvprog"
+chmodcmd=""
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+fi
+
+if [ x"$dst" = x ]
+then
+ echo "install: no destination specified"
+ exit 1
+fi
+
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+if [ -d $dst ]
+then
+ dst="$dst"/`basename $src`
+fi
+
+# Make a temp file name in the proper directory.
+
+dstdir=`dirname $dst`
+dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+$doit $instcmd $src $dsttmp
+
+# and set any options; do chmod last to preserve setuid bits
+
+if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi
+if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi
+if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi
+if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi
+
+# Now rename the file to the real destination.
+
+$doit $rmcmd $dst
+$doit $mvcmd $dsttmp $dst
+
+
+exit 0
diff --git a/dwarfdump/makename.c b/dwarfdump/makename.c
new file mode 100644
index 0000000..e97e1d0
--- /dev/null
+++ b/dwarfdump/makename.c
@@ -0,0 +1,68 @@
+
+/*
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+ makename.c
+ $Revision: 1.4 $
+ $Date: 2005/11/08 21:48:42 $
+
+ This used to be elaborate stuff.
+ Now it is trivial, as duplicating names is
+ unimportant in dwarfdump (in general).
+
+ And in fact, this is only called for attributes and
+ tags etc whose true name is unknown. Not for
+ any normal case.
+
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "makename.h"
+
+char *
+makename(const char *s)
+{
+ char *newstr;
+
+ if (!s) {
+ return "";
+ }
+
+ newstr = strdup(s);
+ if (newstr == 0) {
+ fprintf(stderr, "Out of memory mallocing %d bytes\n",
+ (int) strlen(s));
+ exit(1);
+ }
+ return newstr;
+}
diff --git a/dwarfdump/makename.h b/dwarfdump/makename.h
new file mode 100644
index 0000000..da1f798
--- /dev/null
+++ b/dwarfdump/makename.h
@@ -0,0 +1,53 @@
+#ifndef names_h
+#define names_h
+/*
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+*/
+
+/* makename.h
+ $Revision: 1.3 $
+ $Date: 2004/10/28 22:26:58 $
+
+ This is for putting strings into stable storage.
+
+ Effectively an strdup() wrapper.
+
+ Rarely called.
+
+ It leaks memory, (the memory
+ is never freed) but that seems unimportant since
+ use of this is very rare.
+*/
+
+char * makename(const char *); /* Makes a copy of the string in
+ a malloc area. Can never return 0. */
+#endif
diff --git a/dwarfdump/naming.c b/dwarfdump/naming.c
new file mode 100644
index 0000000..115fd09
--- /dev/null
+++ b/dwarfdump/naming.c
@@ -0,0 +1,261 @@
+/*
+ Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
+ Portions Copyright (C) 2010-2011 SN Systems Ltd. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+
+
+/* naming.c */
+#include "globals.h"
+#include "dwarf.h"
+#include "libdwarf.h"
+#include "makename.h"
+
+static const char *
+skipunder(const char *v)
+{
+ const char *cp = v;
+ int undercount = 0;
+ for( ; *cp ; ++cp) {
+ if( *cp == '_') {
+ ++undercount;
+ if(undercount == 2) {
+ return cp+1;
+ }
+ }
+ }
+ return "";
+}
+
+static const char *
+ellipname(int res, int val_in, const char *v,const char *ty,int printonerr)
+{
+#ifndef TRIVIAL_NAMING
+ if (check_dwarf_constants && checking_this_compiler()) {
+ DWARF_CHECK_COUNT(dwarf_constants_result,1);
+ }
+#endif
+ if(res != DW_DLV_OK) {
+ char buf[100];
+ char *n;
+ snprintf(buf,sizeof(buf),"<Unknown %s value 0x%x>",ty,val_in);
+ /* Capture any name error in DWARF constants */
+#ifndef TRIVIAL_NAMING
+ if(printonerr && check_dwarf_constants && checking_this_compiler()) {
+ if (check_verbose_mode) {
+ fprintf(stderr,"%s of %d (0x%x) is unknown to dwarfdump. "
+ "Continuing. \n",ty,val_in,val_in );
+ }
+ DWARF_ERROR_COUNT(dwarf_constants_result,1);
+ DWARF_CHECK_ERROR_PRINT_CU();
+ }
+#else
+ /* This is for the tree-generation, not dwarfdump itself. */
+ if(printonerr) {
+ fprintf(stderr,"%s of %d (0x%x) is unknown to dwarfdump. "
+ "Continuing. \n",ty,val_in,val_in );
+ }
+#endif
+ n = makename(buf);
+ return n;
+ }
+ if(ellipsis) {
+ return skipunder(v);
+ }
+ return v;
+}
+
+const char * get_TAG_name(unsigned int val_in,int printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_TAG_name(val_in,&v);
+ return ellipname(res,val_in,v,"TAG",printonerr);
+}
+const char * get_children_name(unsigned int val_in,int printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_children_name(val_in,&v);
+ return ellipname(res,val_in,v,"children",printonerr);
+}
+const char * get_FORM_name(unsigned int val_in,int printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_FORM_name(val_in,&v);
+ return ellipname(res,val_in,v,"FORM",printonerr);
+}
+const char * get_AT_name(unsigned int val_in,int printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_AT_name(val_in,&v);
+ return ellipname(res,val_in,v,"AT",printonerr);
+}
+const char * get_OP_name(unsigned int val_in,int printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_OP_name(val_in,&v);
+ return ellipname(res,val_in,v,"OP",printonerr);
+}
+const char * get_ATE_name(unsigned int val_in,int printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_ATE_name(val_in,&v);
+ return ellipname(res,val_in,v,"ATE",printonerr);
+}
+const char * get_DS_name(unsigned int val_in,int printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_DS_name(val_in,&v);
+ return ellipname(res,val_in,v,"DS",printonerr);
+}
+const char * get_END_name(unsigned int val_in,int printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_END_name(val_in,&v);
+ return ellipname(res,val_in,v,"END",printonerr);
+}
+const char * get_ATCF_name(unsigned int val_in,int printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_ATCF_name(val_in,&v);
+ return ellipname(res,val_in,v,"ATCF",printonerr);
+}
+const char * get_ACCESS_name(unsigned int val_in,int printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_ACCESS_name(val_in,&v);
+ return ellipname(res,val_in,v,"ACCESS",printonerr);
+}
+const char * get_VIS_name(unsigned int val_in,int printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_VIS_name(val_in,&v);
+ return ellipname(res,val_in,v,"VIS",printonerr);
+}
+const char * get_VIRTUALITY_name(unsigned int val_in,int printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_VIRTUALITY_name(val_in,&v);
+ return ellipname(res,val_in,v,"VIRTUALITY",printonerr);
+}
+const char * get_LANG_name(unsigned int val_in,int printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_LANG_name(val_in,&v);
+ return ellipname(res,val_in,v,"LANG",printonerr);
+}
+const char * get_ID_name(unsigned int val_in,int printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_ID_name(val_in,&v);
+ return ellipname(res,val_in,v,"ID",printonerr);
+}
+const char * get_CC_name(unsigned int val_in,int printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_CC_name(val_in,&v);
+ return ellipname(res,val_in,v,"CC",printonerr);
+}
+const char * get_INL_name(unsigned int val_in,int printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_INL_name(val_in,&v);
+ return ellipname(res,val_in,v,"INL",printonerr);
+}
+const char * get_ORD_name(unsigned int val_in,int printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_ORD_name(val_in,&v);
+ return ellipname(res,val_in,v,"ORD",printonerr);
+}
+const char * get_DSC_name(unsigned int val_in,int printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_DSC_name(val_in,&v);
+ return ellipname(res,val_in,v,"DSC",printonerr);
+}
+const char * get_LNS_name(unsigned int val_in,int printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_LNS_name(val_in,&v);
+ return ellipname(res,val_in,v,"LNS",printonerr);
+}
+const char * get_LNE_name(unsigned int val_in,int printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_LNE_name(val_in,&v);
+ return ellipname(res,val_in,v,"LNE",printonerr);
+}
+const char * get_MACINFO_name(unsigned int val_in,int printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_MACINFO_name(val_in,&v);
+ return ellipname(res,val_in,v,"MACINFO",printonerr);
+}
+const char * get_CFA_name(unsigned int val_in,int printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_CFA_name(val_in,&v);
+ return ellipname(res,val_in,v,"CFA",printonerr);
+}
+const char * get_EH_name(unsigned int val_in,int printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_EH_name(val_in,&v);
+ return ellipname(res,val_in,v,"EH",printonerr);
+}
+const char * get_FRAME_name(unsigned int val_in,int printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_FRAME_name(val_in,&v);
+ return ellipname(res,val_in,v,"FRAME",printonerr);
+}
+const char * get_CHILDREN_name(unsigned int val_in,int printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_CHILDREN_name(val_in,&v);
+ return ellipname(res,val_in,v,"CHILDREN",printonerr);
+}
+const char * get_ADDR_name(unsigned int val_in,int printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_ADDR_name(val_in,&v);
+ return ellipname(res,val_in,v,"ADDR",printonerr);
+}
+
+
diff --git a/dwarfdump/naming.h b/dwarfdump/naming.h
new file mode 100644
index 0000000..89a1594
--- /dev/null
+++ b/dwarfdump/naming.h
@@ -0,0 +1,73 @@
+
+/*
+ Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
+
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+
+/* naming.h */
+
+extern const char * get_TAG_name(unsigned int val_in,int printonerr);
+extern const char * get_children_name(unsigned int val_in,int printonerr);
+extern const char * get_FORM_name(unsigned int val_in,int printonerr);
+extern const char * get_AT_name(unsigned int val_in,int printonerr);
+extern const char * get_OP_name(unsigned int val_in,int printonerr);
+extern const char * get_ATE_name(unsigned int val_in,int printonerr);
+extern const char * get_DS_name(unsigned int val_in,int printonerr);
+extern const char * get_END_name(unsigned int val_in,int printonerr);
+extern const char * get_ATCF_name(unsigned int val_in,int printonerr);
+extern const char * get_ACCESS_name(unsigned int val_in,int printonerr);
+extern const char * get_VIS_name(unsigned int val_in,int printonerr);
+extern const char * get_VIRTUALITY_name(unsigned int val_in,int printonerr);
+extern const char * get_LANG_name(unsigned int val_in,int printonerr);
+extern const char * get_ID_name(unsigned int val_in,int printonerr);
+extern const char * get_CC_name(unsigned int val_in,int printonerr);
+extern const char * get_INL_name(unsigned int val_in,int printonerr);
+extern const char * get_ORD_name(unsigned int val_in,int printonerr);
+extern const char * get_DSC_name(unsigned int val_in,int printonerr);
+extern const char * get_LNS_name(unsigned int val_in,int printonerr);
+extern const char * get_LNE_name(unsigned int val_in,int printonerr);
+extern const char * get_MACINFO_name(unsigned int val_in,int printonerr);
+extern const char * get_CFA_name(unsigned int val_in,int printonerr);
+extern const char * get_EH_name(unsigned int val_in,int printonerr);
+extern const char * get_FRAME_name(unsigned int val_in,int printonerr);
+extern const char * get_CHILDREN_name(unsigned int val_in,int printonerr);
+extern const char * get_ADDR_name(unsigned int val_in,int printonerr);
+
+
diff --git a/dwarfdump/print_abbrevs.c b/dwarfdump/print_abbrevs.c
new file mode 100644
index 0000000..76a08f5
--- /dev/null
+++ b/dwarfdump/print_abbrevs.c
@@ -0,0 +1,304 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2011 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include "globals.h"
+#include "naming.h"
+#include "dwconf.h"
+#include "esb.h"
+
+#include "print_sections.h"
+
+
+/* The following relevent for one specific Linker. */
+#define SNLINKER_MAX_ATTRIB_COUNT 16
+
+/* Print data in .debug_abbrev
+ This is inherently unsafe as it assumes there
+ are no byte sequences in .debug_abbrev other than
+ legal abbrev sequences. But the Dwarf spec
+ does not promise that. The spec only promises
+ that any bytes at an offset referred to from
+ .debug_info are legal sequences.
+*/
+extern void
+print_abbrevs(Dwarf_Debug dbg)
+{
+ Dwarf_Abbrev ab;
+ Dwarf_Unsigned offset = 0;
+ Dwarf_Unsigned length = 0;
+ Dwarf_Unsigned abbrev_entry_count = 0;
+ /* Maximum defined tag is 0xffff, DW_TAG_hi_user. */
+ Dwarf_Half tag = 0;
+ Dwarf_Half attr = 0;
+ Dwarf_Signed form = 0;
+ Dwarf_Off off = 0;
+ Dwarf_Unsigned i = 0;
+ const char * child_name = 0;
+ Dwarf_Unsigned abbrev_num = 1;
+ Dwarf_Signed child_flag = 0;
+ int abres = 0;
+ int tres = 0;
+ int acres = 0;
+ Dwarf_Unsigned abbrev_code = 0;
+
+ current_section_id = DEBUG_ABBREV;
+
+ if (do_print_dwarf) {
+ printf("\n.debug_abbrev\n");
+ }
+ while ((abres = dwarf_get_abbrev(dbg, offset, &ab,
+ &length, &abbrev_entry_count,
+ &err)) == DW_DLV_OK) {
+
+ if (abbrev_entry_count == 0) {
+ /* Simple innocuous zero : null abbrev entry */
+ if (dense) {
+ printf("<%" DW_PR_DUu "><0x%" DW_PR_XZEROS DW_PR_DUx "><%"
+ DW_PR_DSd "><%s>\n",
+ abbrev_num,
+ offset,
+ (Dwarf_Signed) /* abbrev_code */ 0,
+ "null .debug_abbrev entry");
+ } else {
+ printf("<%5" DW_PR_DUu "><0x%" DW_PR_XZEROS DW_PR_DUx
+ "><code: %3" DW_PR_DSd "> %-20s\n",
+ abbrev_num,
+ offset,
+ (Dwarf_Signed) /* abbrev_code */ 0,
+ "null .debug_abbrev entry");
+ }
+
+ offset += length;
+ ++abbrev_num;
+ dwarf_dealloc(dbg, ab, DW_DLA_ABBREV);
+ continue;
+ }
+ tres = dwarf_get_abbrev_tag(ab, &tag, &err);
+ if (tres != DW_DLV_OK) {
+ dwarf_dealloc(dbg, ab, DW_DLA_ABBREV);
+ print_error(dbg, "dwarf_get_abbrev_tag", tres, err);
+ }
+ tres = dwarf_get_abbrev_code(ab, &abbrev_code, &err);
+ if (tres != DW_DLV_OK) {
+ dwarf_dealloc(dbg, ab, DW_DLA_ABBREV);
+ print_error(dbg, "dwarf_get_abbrev_code", tres, err);
+ }
+ if (dense) {
+ printf("<%" DW_PR_DUu "><0x%" DW_PR_XZEROS DW_PR_DUx
+ "><%" DW_PR_DSd "><%s>",
+ abbrev_num,
+ offset, abbrev_code,
+ get_TAG_name(tag,dwarf_names_print_on_error));
+ }
+ else {
+ printf("<%5" DW_PR_DUu "><0x%" DW_PR_XZEROS DW_PR_DUx "><code: %3"
+ DW_PR_DSd "> %-20s",
+ abbrev_num,
+ offset, abbrev_code,
+ get_TAG_name(tag,dwarf_names_print_on_error));
+ }
+ /* Process specific TAGs specially. */
+ tag_specific_checks_setup(tag,0);
+ ++abbrev_num;
+ acres = dwarf_get_abbrev_children_flag(ab, &child_flag, &err);
+ if (acres == DW_DLV_ERROR) {
+ dwarf_dealloc(dbg, ab, DW_DLA_ABBREV);
+ print_error(dbg, "dwarf_get_abbrev_children_flag", acres,
+ err);
+ }
+ if (acres == DW_DLV_NO_ENTRY) {
+ child_flag = 0;
+ }
+ child_name = get_children_name(child_flag,
+ dwarf_names_print_on_error);
+ if (dense)
+ printf(" %s", child_name);
+ else
+ printf(" %s\n", child_name);
+ /* Abbrev just contains the format of a die, which debug_info
+ then points to with the real data. So here we just print the
+ given format. */
+ for (i = 0; i < abbrev_entry_count; i++) {
+ int aeres = 0;
+
+ aeres =
+ dwarf_get_abbrev_entry(ab, i, &attr, &form, &off, &err);
+ if (aeres == DW_DLV_ERROR) {
+ dwarf_dealloc(dbg, ab, DW_DLA_ABBREV);
+ print_error(dbg, "dwarf_get_abbrev_entry", aeres, err);
+ }
+ if (aeres == DW_DLV_NO_ENTRY) {
+ attr = -1LL;
+ form = -1LL;
+ }
+ if (dense) {
+ printf(" <%ld>%s<%s>", (unsigned long) off,
+ get_AT_name(attr,dwarf_names_print_on_error),
+ get_FORM_name((Dwarf_Half) form,
+ dwarf_names_print_on_error));
+ } else {
+ printf(" <0x%08lx> %-28s%s\n",
+ (unsigned long) off,
+ get_AT_name(attr,
+ dwarf_names_print_on_error),
+ get_FORM_name((Dwarf_Half) form,
+ dwarf_names_print_on_error));
+ }
+ }
+ dwarf_dealloc(dbg, ab, DW_DLA_ABBREV);
+ offset += length;
+ if (dense) {
+ printf("\n");
+ }
+ }
+ if (abres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_abbrev", abres, err);
+ }
+}
+
+/* Number of abbreviations for current CU */
+static Dwarf_Unsigned CU_abbrev_count = 0;
+
+/* Abbreviations array info for checking abbrev tags.
+ The [zero] entry is not used.
+ We never shrink the array, but it never grows beyond
+ the largest abbreviation count of all the CUs.
+*/
+
+static Dwarf_Signed *abbrev_array = NULL;
+/* Size of the array, the same as the abbrev tag
+ count of the CU with the most of them. */
+static Dwarf_Unsigned abbrev_array_size = 0;
+#define ABBREV_ARRAY_INITIAL_SIZE 64
+
+/* Calculate the number of abbreviations for the
+ current CU and set up a basic abbreviations array info,
+ storing the number of attributes per abbreviation.
+*/
+void
+get_abbrev_array_info(Dwarf_Debug dbg, Dwarf_Unsigned offset_in)
+{
+ Dwarf_Unsigned offset = offset_in;
+ if (check_abbreviations) {
+ Dwarf_Abbrev ab;
+ Dwarf_Unsigned length = 0;
+ Dwarf_Unsigned abbrev_entry_count = 0;
+ Dwarf_Unsigned abbrev_code;
+ int abres = DW_DLV_OK;
+ Dwarf_Error err;
+
+ Dwarf_Bool bMore = TRUE;
+ CU_abbrev_count = 0;
+
+ if (abbrev_array == NULL) {
+ /* Allocate initial abbreviation array info */
+ abbrev_array = (Dwarf_Signed *)
+ calloc(ABBREV_ARRAY_INITIAL_SIZE+1,sizeof(Dwarf_Signed));
+ abbrev_array_size = ABBREV_ARRAY_INITIAL_SIZE;
+ } else {
+ /* Clear out values from previous CU */
+ memset((void *)abbrev_array,0,
+ (abbrev_array_size+1) * sizeof(Dwarf_Signed));
+ }
+
+ while (bMore && (abres = dwarf_get_abbrev(dbg, offset, &ab,
+ &length, &abbrev_entry_count,
+ &err)) == DW_DLV_OK) {
+ dwarf_get_abbrev_code(ab,&abbrev_code,&err);
+ if (abbrev_code == 0) {
+ /* End of abbreviation table for this CU */
+ ++offset; /* Skip abbreviation code */
+ bMore = FALSE;
+ } else {
+ /* Valid abbreviation code */
+ if (abbrev_code > 0) {
+ if (abbrev_code > abbrev_array_size) {
+ /* Resize abbreviation array */
+ abbrev_array_size *= 2;
+ abbrev_array = (Dwarf_Signed *)
+ realloc(abbrev_array,
+ (abbrev_array_size+1) * sizeof(Dwarf_Signed));
+ }
+ abbrev_array[abbrev_code] = abbrev_entry_count;
+ ++CU_abbrev_count;
+ offset += length;
+ } else {
+ /* Invalid abbreviation code */
+ print_error(dbg, "get_abbrev_array_info", abres, err);
+ }
+ }
+ dwarf_dealloc(dbg, ab, DW_DLA_ABBREV);
+ }
+ }
+}
+
+/* Validate an abbreviation for the current CU. */
+void
+validate_abbrev_code(Dwarf_Debug dbg,Dwarf_Unsigned abbrev_code)
+{
+ char buf[128];
+
+ DWARF_CHECK_COUNT(abbreviations_result,1);
+ if (abbrev_code < 0 || (abbrev_code && abbrev_code > CU_abbrev_count)) {
+ snprintf(buf, sizeof(buf),
+ "Abbrev code %" DW_PR_DUu
+ " outside valid range of [0-%" DW_PR_DUu "]",
+ abbrev_code,CU_abbrev_count);
+ DWARF_CHECK_ERROR2(abbreviations_result,buf,
+ "Invalid abbreviation code.");
+ } else {
+ Dwarf_Signed abbrev_entry_count =
+ abbrev_array[abbrev_code];
+ if (abbrev_entry_count < 0 ||
+ abbrev_entry_count > SNLINKER_MAX_ATTRIB_COUNT) {
+ snprintf(buf, sizeof(buf),
+ "Abbrev code %" DW_PR_DUu
+ ", with %" DW_PR_DUu " attributes: "
+ "outside valid range.",
+ abbrev_code,
+ abbrev_entry_count);
+ DWARF_CHECK_ERROR2(abbreviations_result,buf,
+ "Invalid number of attributes.");
+ }
+ }
+}
diff --git a/dwarfdump/print_aranges.c b/dwarfdump/print_aranges.c
new file mode 100644
index 0000000..f3e076c
--- /dev/null
+++ b/dwarfdump/print_aranges.c
@@ -0,0 +1,267 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2011 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include "globals.h"
+#include "naming.h"
+#include "dwconf.h"
+#include "esb.h"
+
+#include "print_sections.h"
+
+
+static void
+do_checking(Dwarf_Debug dbg, Dwarf_Arange *arange_buf,Dwarf_Signed i,
+ Dwarf_Off cu_die_offset,Dwarf_Bool first_cu,
+ Dwarf_Off cu_die_offset_prev, Dwarf_Die cu_die )
+{
+ int dres = 0;
+ Dwarf_Off cuhdroff = 0;
+ Dwarf_Off cudieoff3 = 0;
+ dres = dwarf_get_arange_cu_header_offset(
+ arange_buf[i],&cuhdroff,&err);
+ if(dres == DW_DLV_OK) {
+ Dwarf_Off cudieoff2 = 0;
+
+ /* Get the CU offset for easy error reporting */
+ if (first_cu || cu_die_offset != cu_die_offset_prev) {
+ cu_die_offset_prev = cu_die_offset;
+ dres = dwarf_die_offsets(cu_die,&DIE_overall_offset,&DIE_offset,&err);
+ if (dres != DW_DLV_OK) {
+ print_error(dbg, "dwarf_die_offsets", dres, err);
+ }
+ }
+ dres = dwarf_get_cu_die_offset_given_cu_header_offset(
+ dbg,cuhdroff,&cudieoff2,&err);
+ if(dres == DW_DLV_OK) {
+ /* Get the CU offset for easy error reporting */
+ dwarf_die_offsets(cu_die,&DIE_overall_offset,&DIE_offset,&err);
+ DWARF_CHECK_COUNT(aranges_result,1);
+ if(cudieoff2 != cu_die_offset) {
+ printf("Error, cu_die offsets mismatch, 0x%"
+ DW_PR_DUx
+ " != 0x%" DW_PR_DUx " from arange data",
+ cu_die_offset,cudieoff2);
+ DWARF_CHECK_ERROR(aranges_result,
+ " dwarf_get_cu_die_offset_given_cu..."
+ " gets wrong offset");
+ }
+ } else {
+ print_error(dbg, "dwarf_get_cu_die_offset_given...", dres, err);
+ }
+ } else {
+ print_error(dbg, "dwarf_get_arange_cu_header_offset", dres, err);
+ }
+ dres = dwarf_get_cu_die_offset(arange_buf[i],&cudieoff3,
+ &err);
+ if(dres == DW_DLV_OK) {
+ DWARF_CHECK_COUNT(aranges_result,1);
+ if(cudieoff3 != cu_die_offset) {
+ printf(
+ "Error, cu_die offsets (b) mismatch , 0x%"
+ DW_PR_DUx
+ " != 0x%" DW_PR_DUx " from arange data",
+ cu_die_offset,cudieoff3);
+ DWARF_CHECK_ERROR(aranges_result,
+ " dwarf_get_cu_die_offset "
+ " gets wrong offset");
+ }
+ } else {
+ print_error(dbg, "dwarf_get_cu_die_offset failed ",
+ dres,err);
+ }
+}
+
+/* get all the data in .debug_aranges */
+extern void
+print_aranges(Dwarf_Debug dbg)
+{
+ Dwarf_Signed count = 0;
+ Dwarf_Signed i = 0;
+ Dwarf_Arange *arange_buf = NULL;
+ int ares = 0;
+ int aires = 0;
+ Dwarf_Off prev_off = 0; /* Holds previous CU offset */
+ Dwarf_Bool first_cu = TRUE;
+ Dwarf_Off cu_die_offset_prev = 0;
+
+ /* Reset the global state, so we can traverse the debug_info */
+ seen_CU = FALSE;
+ need_CU_name = TRUE;
+ need_CU_base_address = TRUE;
+ need_CU_high_address = TRUE;
+
+ current_section_id = DEBUG_ARANGES;
+ if (do_print_dwarf) {
+ printf("\n.debug_aranges\n");
+ }
+ ares = dwarf_get_aranges(dbg, &arange_buf, &count, &err);
+ if (ares == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_aranges", ares, err);
+ } else if (ares == DW_DLV_NO_ENTRY) {
+ /* no arange is included */
+ } else {
+ for (i = 0; i < count; i++) {
+ Dwarf_Unsigned segment = 0;
+ Dwarf_Unsigned segment_entry_size = 0;
+ Dwarf_Addr start = 0;
+ Dwarf_Unsigned length = 0;
+ Dwarf_Off cu_die_offset = 0;
+ Dwarf_Die cu_die = NULL;
+ aires = dwarf_get_arange_info_b(arange_buf[i],
+ &segment,
+ &segment_entry_size,
+ &start, &length,
+ &cu_die_offset, &err);
+ if (aires != DW_DLV_OK) {
+ print_error(dbg, "dwarf_get_arange_info", aires, err);
+ } else {
+ int dres;
+ char *producer_name = 0;
+
+ /* Get basic locations for error reporting */
+ dres = dwarf_offdie(dbg, cu_die_offset, &cu_die, &err);
+ if (dres != DW_DLV_OK) {
+ print_error(dbg, "dwarf_offdie", dres, err);
+ }
+
+ if (cu_name_flag) {
+ if(should_skip_this_cu(dbg,cu_die,err)) {
+ continue;
+ }
+ }
+ /* Get producer name for this CU and update compiler list */
+ get_producer_name(dbg,cu_die,err,&producer_name);
+ update_compiler_target(producer_name);
+ if (!checking_this_compiler()) {
+ continue;
+ }
+
+ if (check_aranges) {
+ do_checking(dbg,arange_buf,i,cu_die_offset,first_cu,
+ cu_die_offset_prev,cu_die);
+ }
+ /* Get the offset of the cu header itself in the
+ section, but not for end-entries. */
+ if(start || length) {
+ Dwarf_Off off = 0;
+ int cures3 = dwarf_get_arange_cu_header_offset(
+ arange_buf[i], &off, &err);
+ if (cures3 != DW_DLV_OK) {
+ print_error(dbg, "dwarf_get_cu_hdr_offset",
+ cures3, err);
+ }
+
+ /* Print the CU information if different. */
+ if (prev_off != off || first_cu) {
+ first_cu = FALSE;
+ prev_off = off;
+ /* We are faking the indent level. We do not know
+ what level it is, really.
+
+ If do_check_dwarf we do not want to do
+ the die print call as it will do
+ check/print we may not have asked for.
+ And if we did ask for debug_info checks
+ this will do the checks a second time!
+ So only call print_one_die if printing.
+ */
+ if(do_print_dwarf){
+ /* There is no die if its a set-end entry */
+ print_one_die(dbg, cu_die,
+ /* print_information= */ (boolean) TRUE,
+ /* indent_level = */0,
+ /* srcfiles= */ 0,
+ /* cnt= */ 0,
+ /* ignore_die_stack= */TRUE);
+ }
+ /* Reset the state, so we can traverse the debug_info */
+ seen_CU = FALSE;
+ need_CU_name = TRUE;
+ if (do_print_dwarf) {
+ printf("\n");
+ }
+ }
+
+ if (do_print_dwarf) {
+ /* Print current aranges record */
+ if(segment_entry_size) {
+ printf(
+ "\narange starts at seg,off 0x%"
+ DW_PR_XZEROS DW_PR_DUx
+ ",0x%" DW_PR_XZEROS DW_PR_DUx
+ ", ",
+ segment,
+ (Dwarf_Unsigned)start);
+ } else {
+ printf("\narange starts at 0x%"
+ DW_PR_XZEROS DW_PR_DUx ", ",
+ (Dwarf_Unsigned)start);
+ }
+ printf("length of 0x%" DW_PR_XZEROS DW_PR_DUx
+ ", cu_die_offset = 0x%" DW_PR_XZEROS DW_PR_DUx,
+ length,
+ (Dwarf_Unsigned)cu_die_offset);
+
+ }
+ if (verbose && do_print_dwarf) {
+ printf(" cuhdr 0x%" DW_PR_XZEROS DW_PR_DUx "\n",
+ (Dwarf_Unsigned)off);
+ }
+ dwarf_dealloc(dbg, cu_die, DW_DLA_DIE);
+ cu_die = 0;
+ } else {
+ /* Must be a range end. We really do want to print
+ this as there is a real record here, an
+ 'arange end' record. */
+ if (do_print_dwarf) {
+ printf("\narange end");
+ }
+ }/* end start||length test */
+ } /* end aires DW_DLV_OK test */
+
+ /* print associated die too? */
+ dwarf_dealloc(dbg, arange_buf[i], DW_DLA_ARANGE);
+ }
+ dwarf_dealloc(dbg, arange_buf, DW_DLA_LIST);
+ }
+}
diff --git a/dwarfdump/print_die.c b/dwarfdump/print_die.c
new file mode 100644
index 0000000..5951385
--- /dev/null
+++ b/dwarfdump/print_die.c
@@ -0,0 +1,3540 @@
+/*
+
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2011 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2007-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+$ Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_die.c,v 1.51 2006/04/01 16:20:21 davea Exp $ */
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address. */
+
+
+#include "globals.h"
+#include "naming.h"
+#include "esb.h" /* For flexible string buffer. */
+#include "makename.h" /* Non-duplicating string table. */
+#include "print_frames.h" /* for get_string_from_locs() . */
+#include "tag_common.h"
+
+/* Traverse a DIE and attributes to check self references */
+static boolean traverse_one_die(Dwarf_Debug dbg, Dwarf_Attribute attrib,
+ Dwarf_Die die, char **srcfiles,
+ Dwarf_Signed cnt, int die_indent_level);
+static boolean traverse_attribute(Dwarf_Debug dbg, Dwarf_Die die,
+ Dwarf_Half attr, Dwarf_Attribute attr_in,
+ boolean print_information,
+ char **srcfiles, Dwarf_Signed cnt,
+ int die_indent_level);
+static void print_die_and_children_internal(Dwarf_Debug dbg,
+ Dwarf_Die in_die_in,
+ Dwarf_Bool is_info,
+ char **srcfiles, Dwarf_Signed cnt);
+static int print_one_die_section(Dwarf_Debug dbg,Dwarf_Bool is_info);
+
+/* Is this a PU has been invalidated by the SN Systems linker? */
+#define IsInvalidCode(low,high) ((low == elf_max_address) || (low == 0 && high == 0))
+
+
+static int get_form_values(Dwarf_Attribute attrib,
+ Dwarf_Half * theform, Dwarf_Half * directform);
+static void show_form_itself(int show_form,int verbose,
+ int theform, int directform, struct esb_s * str_out);
+static void print_exprloc_content(Dwarf_Debug dbg,Dwarf_Die die, Dwarf_Attribute attrib,
+ int showhextoo, struct esb_s *esbp);
+static boolean print_attribute(Dwarf_Debug dbg, Dwarf_Die die,
+ Dwarf_Half attr,
+ Dwarf_Attribute actual_addr,
+ boolean print_information,
+ int die_indent_level, char **srcfiles,
+ Dwarf_Signed cnt);
+static void get_location_list(Dwarf_Debug dbg, Dwarf_Die die,
+ Dwarf_Attribute attr, struct esb_s *esbp);
+static int legal_tag_attr_combination(Dwarf_Half tag, Dwarf_Half attr);
+static int legal_tag_tree_combination(Dwarf_Half parent_tag,
+ Dwarf_Half child_tag);
+static int _dwarf_print_one_expr_op(Dwarf_Debug dbg,Dwarf_Loc* expr,
+ int index, struct esb_s *string_out);
+static int formxdata_print_value(Dwarf_Debug dbg,Dwarf_Attribute attrib,
+ struct esb_s *esbp, Dwarf_Error * err, Dwarf_Bool hex_format);
+
+/* esb_base is static so gets initialized to zeros.
+ It is not thread-safe or
+ safe for multiple open producer instances for
+ but that does not matter here in dwarfdump.
+
+ The memory used by esb_base and esb_extra is never freed.
+*/
+static struct esb_s esb_base;
+static struct esb_s esb_extra;
+
+static int dwarf_names_print_on_error = 1;
+
+static int die_stack_indent_level = 0;
+static boolean local_symbols_already_began = FALSE;
+
+typedef const char *(*encoding_type_func) (unsigned,int doprintingonerr);
+
+Dwarf_Off fde_offset_for_cu_low = DW_DLV_BADOFFSET;
+Dwarf_Off fde_offset_for_cu_high = DW_DLV_BADOFFSET;
+
+/* Indicators to record a pair [low,high], these
+ are used in printing DIEs to accumulate the high
+ and low pc across attributes and to record the pair
+ as soon as both are known. Probably would be better to
+ use variables as arguments to
+ print_attribute(). */
+static Dwarf_Addr lowAddr = 0;
+static Dwarf_Addr highAddr = 0;
+static Dwarf_Bool bSawLow = FALSE;
+static Dwarf_Bool bSawHigh = FALSE;
+
+/* The following too is related to high and low pc
+attributes of a function. It's misnamed, it really means
+'yes, we have high and low pc' if it is TRUE. Defaulting to TRUE
+seems bogus. */
+static Dwarf_Bool in_valid_code = TRUE;
+
+struct operation_descr_s {
+ int op_code;
+ int op_count;
+ const char * op_1type;
+};
+struct operation_descr_s opdesc[]= {
+ {DW_OP_addr,1,"addr" },
+ {DW_OP_deref,0 },
+ {DW_OP_const1u,1,"1u" },
+ {DW_OP_const1s,1,"1s" },
+ {DW_OP_const2u,1,"2u" },
+ {DW_OP_const2s,1,"2s" },
+ {DW_OP_const4u,1,"4u" },
+ {DW_OP_const4s,1,"4s" },
+ {DW_OP_const8u,1,"8u" },
+ {DW_OP_const8s,1,"8s" },
+ {DW_OP_constu,1,"uleb" },
+ {DW_OP_consts,1,"sleb" },
+ {DW_OP_dup,0,""},
+ {DW_OP_drop,0,""},
+ {DW_OP_over,0,""},
+ {DW_OP_pick,1,"1u"},
+ {DW_OP_swap,0,""},
+ {DW_OP_rot,0,""},
+ {DW_OP_xderef,0,""},
+ {DW_OP_abs,0,""},
+ {DW_OP_and,0,""},
+ {DW_OP_div,0,""},
+ {DW_OP_minus,0,""},
+ {DW_OP_mod,0,""},
+ {DW_OP_mul,0,""},
+ {DW_OP_neg,0,""},
+ {DW_OP_not,0,""},
+ {DW_OP_or,0,""},
+ {DW_OP_plus,0,""},
+ {DW_OP_plus_uconst,1,"uleb"},
+ {DW_OP_shl,0,""},
+ {DW_OP_shr,0,""},
+ {DW_OP_shra,0,""},
+ {DW_OP_xor,0,""},
+ {DW_OP_skip,1,"2s"},
+ {DW_OP_bra,1,"2s"},
+ {DW_OP_eq,0,""},
+ {DW_OP_ge,0,""},
+ {DW_OP_gt,0,""},
+ {DW_OP_le,0,""},
+ {DW_OP_lt,0,""},
+ {DW_OP_ne,0,""},
+ /* lit0 thru reg31 handled specially, no operands */
+ /* breg0 thru breg31 handled specially, 1 operand */
+ {DW_OP_regx,1,"uleb"},
+ {DW_OP_fbreg,1,"sleb"},
+ {DW_OP_bregx,2,"uleb"},
+ {DW_OP_piece,1,"uleb"},
+ {DW_OP_deref_size,1,"1u"},
+ {DW_OP_xderef_size,1,"1u"},
+ {DW_OP_nop,0,""},
+ {DW_OP_push_object_address,0,""},
+ {DW_OP_call2,1,"2u"},
+ {DW_OP_call4,1,"4u"},
+ {DW_OP_call_ref,1,"off"},
+ {DW_OP_form_tls_address,0,""},
+ {DW_OP_call_frame_cfa,0,""},
+ {DW_OP_bit_piece,2,"uleb"},
+ {DW_OP_implicit_value,2,"uleb"},
+ {DW_OP_stack_value,0,""},
+ {DW_OP_GNU_uninit,0,""},
+ {DW_OP_GNU_encoded_addr,1,"addr"},
+ {DW_OP_GNU_implicit_pointer,1,"addr" },
+ {DW_OP_GNU_entry_value,1,"val" },
+ /* terminator */
+ {0,0,""}
+};
+
+struct die_stack_data_s {
+ Dwarf_Die die_;
+ boolean already_printed_;
+};
+struct die_stack_data_s empty_stack_entry;
+
+#define DIE_STACK_SIZE 800
+static struct die_stack_data_s die_stack[DIE_STACK_SIZE];
+
+#define SET_DIE_STACK_ENTRY(i,x) { die_stack[i].die_ = x; \
+ die_stack[die_stack_indent_level].already_printed_ = FALSE; }
+#define EMPTY_DIE_STACK_ENTRY(i) { die_stack[i] = empty_stack_entry; }
+
+static int
+print_as_info_or_cu()
+{
+ return (info_flag || cu_name_flag);
+}
+
+
+/* process each compilation unit in .debug_info */
+void
+print_infos(Dwarf_Debug dbg,Dwarf_Bool is_info)
+{
+ int nres = 0;
+ if(is_info) {
+ nres = print_one_die_section(dbg,TRUE);
+ if (nres == DW_DLV_ERROR) {
+ char * errmsg = dwarf_errmsg(err);
+ Dwarf_Unsigned myerr = dwarf_errno(err);
+
+ fprintf(stderr, "%s ERROR: %s: %s (%lu)\n",
+ program_name, "attempting to print .debug_info",
+ errmsg, (unsigned long) myerr);
+ fprintf(stderr, "attempting to continue.\n");
+ }
+ return;
+ }
+ nres = print_one_die_section(dbg,FALSE);
+ if (nres == DW_DLV_ERROR) {
+ char * errmsg = dwarf_errmsg(err);
+ Dwarf_Unsigned myerr = dwarf_errno(err);
+
+ fprintf(stderr, "%s ERROR: %s: %s (%lu)\n",
+ program_name, "attempting to print .debug_types",
+ errmsg, (unsigned long) myerr);
+ fprintf(stderr, "attempting to continue.\n");
+ }
+}
+static void
+print_std_cu_hdr(Dwarf_Unsigned cu_header_length,
+ Dwarf_Unsigned abbrev_offset,
+ Dwarf_Half version_stamp,
+ Dwarf_Half address_size)
+{
+ if(dense) {
+ printf(" %s<0x%" DW_PR_XZEROS DW_PR_DUx
+ ">", "cu_header_length",
+ cu_header_length);
+ printf(" %s<0x%04x>", "version_stamp",
+ version_stamp);
+ printf(" %s<0x%" DW_PR_XZEROS DW_PR_DUx
+ ">", "abbrev_offset", abbrev_offset);
+ printf(" %s<0x%02x>", "address_size",
+ address_size);
+ } else {
+ printf(" %-16s = 0x%" DW_PR_XZEROS DW_PR_DUx
+ " %" DW_PR_DUu
+ "\n", "cu_header_length",
+ cu_header_length,
+ cu_header_length);
+ printf(" %-16s = 0x%04x %u\n", "version_stamp",
+ version_stamp,version_stamp);
+ printf(" %-16s = 0x%" DW_PR_XZEROS DW_PR_DUx
+ " %" DW_PR_DUu
+ "\n", "abbrev_offset",
+ abbrev_offset,
+ abbrev_offset);
+ printf(" %-16s = 0x%02x %u\n", "address_size",
+ address_size,address_size);
+ }
+}
+static void
+print_std_cu_signature(Dwarf_Sig8 *signature,Dwarf_Unsigned typeoffset)
+{
+ if(dense) {
+ struct esb_s sig8str;
+ esb_constructor(&sig8str);
+ format_sig8_string(signature,&sig8str);
+ printf(" %s<%s>", "signature",esb_get_string(&sig8str));
+ printf(" %s<0x%" DW_PR_XZEROS DW_PR_DUx ">",
+ "typeoffset", typeoffset);
+ esb_destructor(&sig8str);
+ } else {
+ struct esb_s sig8str;
+ esb_constructor(&sig8str);
+ format_sig8_string(signature,&sig8str);
+ printf(" %-16s = %s\n", "signature",esb_get_string(&sig8str));
+ printf(" %-16s = 0x%" DW_PR_XZEROS DW_PR_DUx " %" DW_PR_DUu "\n",
+ "typeoffset",
+ typeoffset,typeoffset);
+ esb_destructor(&sig8str);
+ }
+}
+
+static int
+print_one_die_section(Dwarf_Debug dbg,Dwarf_Bool is_info)
+{
+ Dwarf_Unsigned cu_header_length = 0;
+ Dwarf_Unsigned abbrev_offset = 0;
+ Dwarf_Half version_stamp = 0;
+ Dwarf_Half address_size = 0;
+ Dwarf_Half extension_size = 0;
+ Dwarf_Half length_size = 0;
+ Dwarf_Sig8 signature;
+ Dwarf_Unsigned typeoffset = 0;
+ Dwarf_Unsigned next_cu_offset = 0;
+ unsigned loop_count = 0;
+ int nres = DW_DLV_OK;
+ int cu_count = 0;
+ char * cu_short_name = NULL;
+ char * cu_long_name = NULL;
+ char * producer_name = NULL;
+
+ current_section_id = DEBUG_INFO;
+
+ if (print_as_info_or_cu() && do_print_dwarf) {
+ if(is_info) {
+ printf("\n.debug_info\n");
+ }
+ }
+
+ /* Loop until it fails. */
+ for(;;++loop_count) {
+ int sres = DW_DLV_OK;
+ Dwarf_Die cu_die = 0;
+
+ nres = dwarf_next_cu_header_c(dbg,
+ is_info,
+ &cu_header_length, &version_stamp,
+ &abbrev_offset, &address_size,
+ &length_size,&extension_size,
+ &signature, &typeoffset,
+ &next_cu_offset, &err);
+ if (nres == DW_DLV_NO_ENTRY) {
+ return nres;
+ }
+ if( loop_count == 0 &&!is_info &&
+ print_as_info_or_cu() && do_print_dwarf) {
+ printf("\n.debug_types\n");
+ }
+ if (nres != DW_DLV_OK) {
+ return nres;
+ }
+ if(cu_count >= break_after_n_units) {
+ printf("Break at %d\n",cu_count);
+ break;
+ }
+ /* Regardless of any options used, get basic
+ information about the current CU: producer, name */
+ sres = dwarf_siblingof_b(dbg, NULL,is_info, &cu_die, &err);
+ if (sres != DW_DLV_OK) {
+ print_error(dbg, "siblingof cu header", sres, err);
+ }
+ /* Get the CU offset for easy error reporting */
+ dwarf_die_offsets(cu_die,&DIE_overall_offset,&DIE_offset,&err);
+
+ if (cu_name_flag) {
+ if(should_skip_this_cu(dbg,cu_die,err)) {
+ dwarf_dealloc(dbg, cu_die, DW_DLA_DIE);
+ cu_die = 0;
+ ++cu_count;
+ cu_offset = next_cu_offset;
+ continue;
+ }
+ }
+
+ /* Get producer name for this CU and update compiler list */
+ get_producer_name(dbg,cu_die,err,&producer_name);
+ update_compiler_target(producer_name);
+
+ /* Once the compiler table has been updated, see
+ if we need to generate the list of CU compiled
+ by all the producers contained in the elf file */
+ if (producer_children_flag) {
+ get_cu_name(dbg,cu_die,err,&cu_short_name,&cu_long_name);
+ /* Add CU name to current compiler entry */
+ add_cu_name_compiler_target(cu_long_name);
+ }
+
+ /* If the current compiler is not requested by the
+ user, then move to the next CU */
+ if (!checking_this_compiler()) {
+ dwarf_dealloc(dbg, cu_die, DW_DLA_DIE);
+ ++cu_count;
+ cu_offset = next_cu_offset;
+ cu_die = 0;
+ continue;
+ }
+
+ /* We have not seen the compile unit yet, reset these
+ error-reporting globals. */
+ seen_CU = FALSE;
+ need_CU_name = TRUE;
+ need_CU_base_address = TRUE;
+ need_CU_high_address = TRUE;
+ seen_PU_base_address = FALSE;
+ seen_PU_high_address = FALSE;
+
+ /* Release the 'cu_die' created by the call
+ to 'dwarf_siblingof' at the top of the main loop. */
+ dwarf_dealloc(dbg, cu_die, DW_DLA_DIE);
+ cu_die = 0; /* For debugging, stale die should be NULL. */
+
+ if (info_flag && do_print_dwarf) {
+ if(verbose) {
+ if (dense) {
+ printf("<%s>", "cu_header");
+ } else {
+ printf("\nCU_HEADER:\n");
+ }
+ print_std_cu_hdr(cu_header_length,abbrev_offset,
+ version_stamp,address_size);
+ if(!is_info) {
+ print_std_cu_signature(&signature,typeoffset);
+ }
+ if(dense) {
+ printf("\n");
+ }
+ } else {
+ if(!is_info) {
+ if(dense) {
+ printf("<%s>", "cu_header");
+ } else {
+ printf("\nCU_HEADER:\n");
+ }
+ print_std_cu_signature(&signature,typeoffset);
+ if(dense) {
+ printf("\n");
+ }
+ }
+ }
+ }
+
+ /* Get abbreviation info for this CU */
+ get_abbrev_array_info(dbg,abbrev_offset);
+
+ /* process a single compilation unit in .debug_info. */
+ sres = dwarf_siblingof_b(dbg, NULL,is_info, &cu_die, &err);
+ if (sres == DW_DLV_OK) {
+ if (print_as_info_or_cu() || search_is_on) {
+ Dwarf_Signed cnt = 0;
+ char **srcfiles = 0;
+ int srcf = dwarf_srcfiles(cu_die,
+ &srcfiles, &cnt, &err);
+ if (srcf != DW_DLV_OK) {
+ srcfiles = 0;
+ cnt = 0;
+ }
+
+ /* Get the CU offset for easy error reporting */
+ dwarf_die_offsets(cu_die,&DIE_CU_overall_offset,
+ &DIE_CU_offset,&err);
+ print_die_and_children(dbg, cu_die,is_info, srcfiles, cnt);
+ if (srcf == DW_DLV_OK) {
+ int si = 0;
+ for (si = 0; si < cnt; ++si) {
+ dwarf_dealloc(dbg, srcfiles[si], DW_DLA_STRING);
+ }
+ dwarf_dealloc(dbg, srcfiles, DW_DLA_LIST);
+ }
+ }
+
+ /* Dump Ranges Information */
+ if (dump_ranges_info) {
+ PrintBucketGroup(pRangesInfo,TRUE);
+ }
+
+ /* Traverse the line section if in check mode */
+ if (line_flag || check_decl_file) {
+ print_line_numbers_this_cu(dbg, cu_die);
+ }
+ dwarf_dealloc(dbg, cu_die, DW_DLA_DIE);
+ cu_die = 0;
+ } else if (sres == DW_DLV_NO_ENTRY) {
+ /* Do nothing I guess. */
+ } else {
+ print_error(dbg, "Regetting cu_die", sres, err);
+ }
+ ++cu_count;
+ cu_offset = next_cu_offset;
+ }
+ return nres;
+}
+
+static void
+print_a_die_stack(Dwarf_Debug dbg,char **srcfiles,Dwarf_Signed cnt,int lev)
+{
+ boolean print_information = TRUE;
+ boolean ignore_die_stack = FALSE;
+ print_one_die(dbg,die_stack[lev].die_,print_information,lev,srcfiles,cnt,
+ ignore_die_stack);
+}
+extern void
+print_die_and_children(Dwarf_Debug dbg,
+ Dwarf_Die in_die_in,
+ Dwarf_Bool is_info,
+ char **srcfiles, Dwarf_Signed cnt)
+{
+ print_die_and_children_internal(dbg,
+ in_die_in,is_info,srcfiles,cnt);
+}
+
+static void
+print_die_stack(Dwarf_Debug dbg,char **srcfiles,Dwarf_Signed cnt)
+{
+ int lev = 0;
+ boolean print_information = TRUE;
+ boolean ignore_die_stack = FALSE;
+
+ for(lev = 0; lev <= die_stack_indent_level; ++lev)
+ {
+ print_one_die(dbg,die_stack[lev].die_,print_information,
+ lev,srcfiles,cnt,
+ ignore_die_stack);
+ }
+}
+
+/* recursively follow the die tree */
+static void
+print_die_and_children_internal(Dwarf_Debug dbg,
+ Dwarf_Die in_die_in,
+ Dwarf_Bool is_info,
+ char **srcfiles, Dwarf_Signed cnt)
+{
+ Dwarf_Die child = 0;
+ Dwarf_Die sibling = 0;
+ Dwarf_Error err = 0;
+ int tres = 0;
+ int cdres = 0;
+ Dwarf_Die in_die = in_die_in;
+
+ for (;;) {
+ SET_DIE_STACK_ENTRY(die_stack_indent_level,in_die);
+
+ /* Get the CU offset for easy error reporting */
+ dwarf_die_offsets(in_die,&DIE_overall_offset,&DIE_offset,&err);
+
+ if (check_tag_tree) {
+ DWARF_CHECK_COUNT(tag_tree_result,1);
+ if (die_stack_indent_level == 0) {
+ Dwarf_Half tag = 0;
+
+ tres = dwarf_tag(in_die, &tag, &err);
+ if (tres != DW_DLV_OK) {
+ DWARF_CHECK_ERROR(tag_tree_result,
+ "Tag-tree root is not DW_TAG_compile_unit");
+ } else if (tag == DW_TAG_compile_unit) {
+ /* OK */
+ } else {
+ DWARF_CHECK_ERROR(tag_tree_result,
+ "tag-tree root is not DW_TAG_compile_unit");
+ }
+ } else {
+ Dwarf_Half tag_parent = 0;
+ Dwarf_Half tag_child = 0;
+ int pres = 0;
+ int cres = 0;
+ const char *ctagname = "<child tag invalid>";
+ const char *ptagname = "<parent tag invalid>";
+
+ pres = dwarf_tag(die_stack[die_stack_indent_level - 1].die_,
+ &tag_parent, &err);
+ cres = dwarf_tag(in_die, &tag_child, &err);
+ if (pres != DW_DLV_OK)
+ tag_parent = 0;
+ if (cres != DW_DLV_OK)
+ tag_child = 0;
+
+ /* Check for specific compiler */
+ if (checking_this_compiler()) {
+ /* Process specific TAGs. */
+ tag_specific_checks_setup(tag_child,die_stack_indent_level);
+ if (cres != DW_DLV_OK || pres != DW_DLV_OK) {
+ if (cres == DW_DLV_OK) {
+ ctagname = get_TAG_name(tag_child,
+ dwarf_names_print_on_error);
+ }
+ if (pres == DW_DLV_OK) {
+ ptagname = get_TAG_name(tag_parent,
+ dwarf_names_print_on_error);
+ }
+ DWARF_CHECK_ERROR3(tag_tree_result,ptagname,
+ ctagname,
+ "Tag-tree relation is not standard..");
+ } else if (legal_tag_tree_combination(tag_parent,
+ tag_child)) {
+ /* OK */
+ } else {
+ DWARF_CHECK_ERROR3(tag_tree_result,
+ get_TAG_name(tag_parent,
+ dwarf_names_print_on_error),
+ get_TAG_name(tag_child,
+ dwarf_names_print_on_error),
+ "tag-tree relation is not standard.");
+ }
+ }
+ }
+ }
+
+ if (record_dwarf_error && check_verbose_mode) {
+ record_dwarf_error = FALSE;
+ }
+
+ /* Here do pre-descent processing of the die. */
+ {
+ boolean retry_print_on_match = FALSE;
+ boolean ignore_die_stack = FALSE;
+ retry_print_on_match = print_one_die(dbg, in_die,
+ print_as_info_or_cu(),
+ die_stack_indent_level, srcfiles, cnt,ignore_die_stack);
+ if(!print_as_info_or_cu() && retry_print_on_match) {
+ if (display_parent_tree) {
+ print_die_stack(dbg,srcfiles,cnt);
+ } else {
+ if (display_children_tree) {
+ print_a_die_stack(dbg,srcfiles,cnt,die_stack_indent_level);
+ }
+ }
+ if (display_children_tree) {
+ stop_indent_level = die_stack_indent_level;
+ info_flag = TRUE;
+ }
+ }
+ }
+
+ cdres = dwarf_child(in_die, &child, &err);
+
+ /* Check for specific compiler */
+ if (check_abbreviations && checking_this_compiler()) {
+ Dwarf_Half ab_has_child;
+ Dwarf_Bool bError = FALSE;
+ Dwarf_Half tag = 0;
+ tres = dwarf_die_abbrev_children_flag(in_die,&ab_has_child);
+ if (tres == DW_DLV_OK) {
+ DWARF_CHECK_COUNT(abbreviations_result,1);
+ tres = dwarf_tag(in_die, &tag, &err);
+ if (tres == DW_DLV_OK) {
+ switch (tag) {
+ case DW_TAG_array_type:
+ case DW_TAG_class_type:
+ case DW_TAG_compile_unit:
+ case DW_TAG_enumeration_type:
+ case DW_TAG_lexical_block:
+ case DW_TAG_namespace:
+ case DW_TAG_structure_type:
+ case DW_TAG_subprogram:
+ case DW_TAG_subroutine_type:
+ case DW_TAG_union_type:
+ case DW_TAG_entry_point:
+ case DW_TAG_inlined_subroutine:
+ break;
+ default:
+ bError = (cdres == DW_DLV_OK && !ab_has_child) ||
+ (cdres == DW_DLV_NO_ENTRY && ab_has_child);
+ if (bError) {
+ DWARF_CHECK_ERROR(abbreviations_result,
+ "check 'dw_children' flag combination.");
+ }
+ break;
+ }
+ }
+ }
+ }
+
+
+ /* child first: we are doing depth-first walk */
+ if (cdres == DW_DLV_OK) {
+ die_stack_indent_level++;
+ SET_DIE_STACK_ENTRY(die_stack_indent_level,0);
+ if(die_stack_indent_level >= DIE_STACK_SIZE ) {
+ print_error(dbg,
+ "compiled in DIE_STACK_SIZE limit exceeded",
+ DW_DLV_OK,err);
+ }
+ print_die_and_children_internal(dbg, child,is_info, srcfiles, cnt);
+ EMPTY_DIE_STACK_ENTRY(die_stack_indent_level);
+ die_stack_indent_level--;
+ if (die_stack_indent_level == 0)
+ local_symbols_already_began = FALSE;
+ dwarf_dealloc(dbg, child, DW_DLA_DIE);
+ child = 0;
+ } else if (cdres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_child", cdres, err);
+ }
+
+ /* Stop the display of all children */
+ if (display_children_tree && info_flag &&
+ stop_indent_level == die_stack_indent_level) {
+
+ info_flag = FALSE;
+ }
+
+ cdres = dwarf_siblingof_b(dbg, in_die,is_info, &sibling, &err);
+ if (cdres == DW_DLV_OK) {
+ /* print_die_and_children(dbg, sibling, srcfiles, cnt); We
+ loop around to actually print this, rather than
+ recursing. Recursing is horribly wasteful of stack
+ space. */
+ } else if (cdres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_siblingof", cdres, err);
+ }
+
+ /* If we have a sibling, verify that its offset
+ is next to the last processed DIE;
+ An incorrect sibling chain is a nasty bug. */
+ if (cdres == DW_DLV_OK && sibling && check_di_gaps &&
+ checking_this_compiler()) {
+
+ Dwarf_Off glb_off;
+ DWARF_CHECK_COUNT(di_gaps_result,1);
+ if (dwarf_validate_die_sibling(sibling,&glb_off) == DW_DLV_ERROR) {
+ static char msg[128];
+ Dwarf_Off sib_off;
+ dwarf_dieoffset(sibling,&sib_off,&err);
+ sprintf(msg,
+ "GSIB = 0x%" DW_PR_XZEROS DW_PR_DUx
+ " GOFF = 0x%" DW_PR_XZEROS DW_PR_DUx
+ " Gap = %" DW_PR_DUu " bytes",
+ sib_off,glb_off,sib_off-glb_off);
+ DWARF_CHECK_ERROR2(di_gaps_result,
+ "Incorrect sibling chain",msg);
+ }
+ }
+
+ /* Here do any post-descent (ie post-dwarf_child) processing of
+ the in_die. */
+
+ EMPTY_DIE_STACK_ENTRY(die_stack_indent_level);
+ if (in_die != in_die_in) {
+ /* Dealloc our in_die, but not the argument die, it belongs
+ to our caller. Whether the siblingof call worked or not. */
+ dwarf_dealloc(dbg, in_die, DW_DLA_DIE);
+ in_die = 0;
+ }
+ if (cdres == DW_DLV_OK) {
+ /* Set to process the sibling, loop again. */
+ in_die = sibling;
+ } else {
+ /* We are done, no more siblings at this level. */
+ break;
+ }
+ } /* end for loop on siblings */
+ return;
+}
+
+/* Print one die on error and verbose or non check mode */
+#define PRINTING_DIES (do_print_dwarf || (record_dwarf_error && check_verbose_mode))
+
+/* If print_information is FALSE, check the TAG and if it is a CU die
+ print the information anyway. */
+boolean
+print_one_die(Dwarf_Debug dbg, Dwarf_Die die,
+ boolean print_information,
+ int die_indent_level,
+ char **srcfiles, Dwarf_Signed cnt,
+ boolean ignore_die_stack)
+{
+ Dwarf_Signed i = 0;
+ Dwarf_Off offset = 0;
+ Dwarf_Off overall_offset = 0;
+ const char * tagname = 0;
+ Dwarf_Half tag = 0;
+ Dwarf_Signed atcnt = 0;
+ Dwarf_Attribute *atlist = 0;
+ int tres = 0;
+ int ores = 0;
+ int atres = 0;
+ int abbrev_code = dwarf_die_abbrev_code(die);
+ boolean attribute_matched = FALSE;
+
+ /* Print using indentation
+ < 1><0x000854ff GOFF=0x00546047> DW_TAG_pointer_type -> 34
+ < 1><0x000854ff> DW_TAG_pointer_type -> 18
+ DW_TAG_pointer_type -> 2
+ */
+ /* Attribute indent. */
+ int nColumn = show_global_offsets ? 34 : 18;
+
+ if (check_abbreviations && checking_this_compiler()) {
+ validate_abbrev_code(dbg,abbrev_code);
+ }
+
+ if(!ignore_die_stack && die_stack[die_indent_level].already_printed_) {
+ /* FALSE seems like a safe return. */
+ return FALSE;
+ }
+
+ /* Reset indentation column if no offsets */
+ if (!display_offsets) {
+ nColumn = 2;
+ }
+
+ tres = dwarf_tag(die, &tag, &err);
+ if (tres != DW_DLV_OK) {
+ print_error(dbg, "accessing tag of die!", tres, err);
+ }
+ tagname = get_TAG_name(tag,dwarf_names_print_on_error);
+
+ tag_specific_checks_setup(tag,die_indent_level);
+ ores = dwarf_dieoffset(die, &overall_offset, &err);
+ if (ores != DW_DLV_OK) {
+ print_error(dbg, "dwarf_dieoffset", ores, err);
+ }
+ ores = dwarf_die_CU_offset(die, &offset, &err);
+ if (ores != DW_DLV_OK) {
+ print_error(dbg, "dwarf_die_CU_offset", ores, err);
+ }
+
+ if (dump_visited_info && check_self_references) {
+ printf("<%2d><0x%" DW_PR_XZEROS DW_PR_DUx
+ " GOFF=0x%" DW_PR_XZEROS DW_PR_DUx "> ",
+ die_indent_level, (Dwarf_Unsigned)offset,
+ (Dwarf_Unsigned)overall_offset);
+ printf("%*s%s\n",die_indent_level * 2 + 2," ",tagname);
+ }
+
+ /* Print the die */
+ if (PRINTING_DIES && print_information) {
+ if (!ignore_die_stack) {
+ die_stack[die_indent_level].already_printed_ = TRUE;
+ }
+ if (die_indent_level == 0) {
+ if (dense) {
+ printf("\n");
+ } else {
+ printf("\nCOMPILE_UNIT<header overall offset = 0x%"
+ DW_PR_XZEROS DW_PR_DUx ">:\n",
+ (Dwarf_Unsigned)(overall_offset - offset));
+ }
+ } else if (local_symbols_already_began == FALSE &&
+ die_indent_level == 1 && !dense) {
+
+ printf("\nLOCAL_SYMBOLS:\n");
+ local_symbols_already_began = TRUE;
+ }
+
+ /* Print just the Tags and Attributes */
+ if (!display_offsets) {
+ /* Print using indentation */
+ printf("%*s%s\n",die_stack_indent_level * 2 + 2," ",tagname);
+ } else {
+ if (dense) {
+ if (show_global_offsets) {
+ if (die_indent_level == 0) {
+ printf("<%d><0x%" DW_PR_DUx "+0x%" DW_PR_DUx " GOFF=0x%"
+ DW_PR_DUx ">", die_indent_level,
+ (Dwarf_Unsigned)(overall_offset - offset),
+ (Dwarf_Unsigned)offset,
+ (Dwarf_Unsigned)overall_offset);
+ } else {
+ printf("<%d><0x%" DW_PR_DUx " GOFF=0x%" DW_PR_DUx ">",
+ die_indent_level,
+ (Dwarf_Unsigned)offset,
+ (Dwarf_Unsigned)overall_offset);
+ }
+ } else {
+ if (die_indent_level == 0) {
+ printf("<%d><0x%" DW_PR_DUx "+0x%" DW_PR_DUx ">",
+ die_indent_level,
+ (Dwarf_Unsigned)(overall_offset - offset),
+ (Dwarf_Unsigned)offset);
+ } else {
+ printf("<%d><0x%" DW_PR_DUx ">", die_indent_level,
+ (Dwarf_Unsigned)offset);
+ }
+ }
+ printf("<%s>",tagname);
+ if(verbose) {
+ printf(" <abbrev %d>",abbrev_code);
+ }
+ } else {
+ if (show_global_offsets) {
+ printf("<%2d><0x%" DW_PR_XZEROS DW_PR_DUx
+ " GOFF=0x%" DW_PR_XZEROS DW_PR_DUx ">",
+ die_indent_level, (Dwarf_Unsigned)offset,
+ (Dwarf_Unsigned)overall_offset);
+ } else {
+ printf("<%2d><0x%" DW_PR_XZEROS DW_PR_DUx ">",
+ die_indent_level,
+ (Dwarf_Unsigned)offset);
+ }
+
+ /* Print using indentation */
+ printf("%*s%s",die_indent_level * 2 + 2," ",tagname);
+ if(verbose) {
+ printf(" <abbrev %d>",abbrev_code);
+ }
+ fputs("\n",stdout);
+ }
+ }
+ }
+
+ atres = dwarf_attrlist(die, &atlist, &atcnt, &err);
+ if (atres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_attrlist", atres, err);
+ } else if (atres == DW_DLV_NO_ENTRY) {
+ /* indicates there are no attrs. It is not an error. */
+ atcnt = 0;
+ }
+
+ /* Reset any loose references to low or high PC */
+ bSawLow = FALSE;
+ bSawHigh = FALSE;
+
+ /* Get the CU offset for easy error reporting */
+ dwarf_die_offsets(die,&DIE_CU_overall_offset,&DIE_CU_offset,&err);
+
+ for (i = 0; i < atcnt; i++) {
+ Dwarf_Half attr;
+ int ares;
+
+ ares = dwarf_whatattr(atlist[i], &attr, &err);
+ if (ares == DW_DLV_OK) {
+ /* Print using indentation */
+ if (!dense && PRINTING_DIES && print_information) {
+ printf("%*s",die_indent_level * 2 + 2 + nColumn," ");
+ }
+
+ {
+ boolean attr_match = print_attribute(dbg, die, attr,
+ atlist[i],
+ print_information, die_indent_level, srcfiles, cnt);
+ if(print_information == FALSE && attr_match) {
+ attribute_matched = TRUE;
+ }
+ }
+
+ if (record_dwarf_error && check_verbose_mode) {
+ record_dwarf_error = FALSE;
+ }
+ } else {
+ print_error(dbg, "dwarf_whatattr entry missing", ares, err);
+ }
+ }
+
+ for (i = 0; i < atcnt; i++) {
+ dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);
+ }
+ if (atres == DW_DLV_OK) {
+ dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
+ }
+
+ if (PRINTING_DIES && dense && print_information) {
+ printf("\n");
+ }
+ return attribute_matched;
+}
+
+/* Encodings have undefined signedness. Accept either
+ signedness. The values are integer-like (they are defined
+ in the DWARF specification), so the
+ form the compiler uses (as long as it is
+ a constant value) is a non-issue.
+
+ The numbers need not be small (in spite of the
+ function name), but the result should be an integer.
+
+ If string_out is non-NULL, construct a string output, either
+ an error message or the name of the encoding.
+ The function pointer passed in is to code generated
+ by a script at dwarfdump build time. The code for
+ the val_as_string function is generated
+ from dwarf.h. See <build dir>/dwarf_names.c
+
+ The known_signed bool is set true(nonzero) or false (zero)
+ and *both* uval_out and sval_out are set to the value,
+ though of course uval_out cannot represent a signed
+ value properly and sval_out cannot represent all unsigned
+ values properly.
+
+ If string_out is non-NULL then attr_name and val_as_string
+ must also be non-NULL. */
+static int
+get_small_encoding_integer_and_name(Dwarf_Debug dbg,
+ Dwarf_Attribute attrib,
+ Dwarf_Unsigned * uval_out,
+ char *attr_name,
+ const char ** string_out,
+ encoding_type_func val_as_string,
+ Dwarf_Error * err,
+ int show_form)
+{
+ Dwarf_Unsigned uval = 0;
+ char buf[100]; /* The strings are small. */
+ int vres = dwarf_formudata(attrib, &uval, err);
+
+ if (vres != DW_DLV_OK) {
+ Dwarf_Signed sval = 0;
+ vres = dwarf_formsdata(attrib, &sval, err);
+ if (vres != DW_DLV_OK) {
+ vres = dwarf_global_formref(attrib,&uval,err);
+ if (vres != DW_DLV_OK) {
+ if (string_out != 0) {
+ snprintf(buf, sizeof(buf),
+ "%s has a bad form.", attr_name);
+ *string_out = makename(buf);
+ }
+ return vres;
+ }
+ *uval_out = uval;
+ } else {
+ uval = (Dwarf_Unsigned) sval;
+ *uval_out = uval;
+ }
+ } else {
+ *uval_out = uval;
+ }
+ if (string_out) {
+ Dwarf_Half theform = 0;
+ Dwarf_Half directform = 0;
+ get_form_values(attrib,&theform,&directform);
+ esb_empty_string(&esb_base);
+ esb_append(&esb_base, val_as_string((Dwarf_Half) uval,
+ dwarf_names_print_on_error));
+ show_form_itself(show_form, verbose, theform, directform,&esb_base);
+ *string_out = makename(esb_get_string(&esb_base));
+ }
+ return DW_DLV_OK;
+}
+
+
+
+
+/* We need a 32-bit signed number here, but there's no portable
+ way of getting that. So use __uint32_t instead. It's supplied
+ in a reliable way by the autoconf infrastructure. */
+
+static void
+get_FLAG_BLOCK_string(Dwarf_Debug dbg, Dwarf_Attribute attrib,
+ struct esb_s*esbp)
+{
+ int fres = 0;
+ Dwarf_Block *tempb = 0;
+ __uint32_t * array = 0;
+ Dwarf_Unsigned array_len = 0;
+ __uint32_t * array_ptr;
+ Dwarf_Unsigned array_remain = 0;
+ char linebuf[100];
+
+ /* first get compressed block data */
+ fres = dwarf_formblock (attrib,&tempb, &err);
+ if (fres != DW_DLV_OK) {
+ print_error(dbg,"DW_FORM_blockn cannot get block\n",fres,err);
+ return;
+ }
+
+ /* uncompress block into int array */
+ array = dwarf_uncompress_integer_block(dbg,
+ 1, /* 'true' (meaning signed ints)*/
+ 32, /* bits per unit */
+ tempb->bl_data,
+ tempb->bl_len,
+ &array_len, /* len of out array */
+ &err);
+ if (array == (void*) DW_DLV_BADOFFSET) {
+ print_error(dbg,"DW_AT_SUN_func_offsets cannot uncompress data\n",0,err);
+ return;
+ }
+ if (array_len == 0) {
+ print_error(dbg,"DW_AT_SUN_func_offsets has no data\n",0,err);
+ return;
+ }
+
+ /* fill in string buffer */
+ array_remain = array_len;
+ array_ptr = array;
+ while (array_remain > 8) {
+ /* Print a full line */
+ /* If you touch this string, update the magic number 8 in
+ the += and -= below! */
+ snprintf(linebuf, sizeof(linebuf),
+ "\n 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x",
+ array_ptr[0], array_ptr[1],
+ array_ptr[2], array_ptr[3],
+ array_ptr[4], array_ptr[5],
+ array_ptr[6], array_ptr[7]);
+ array_ptr += 8;
+ array_remain -= 8;
+ esb_append(&esb_base, linebuf);
+ }
+
+ /* now do the last line */
+ if (array_remain > 0) {
+ esb_append(&esb_base, "\n ");
+ while (array_remain > 0) {
+ snprintf(linebuf, sizeof(linebuf), " 0x%08x", *array_ptr);
+ array_remain--;
+ array_ptr++;
+ esb_append(&esb_base, linebuf);
+ }
+ }
+
+ /* free array buffer */
+ dwarf_dealloc_uncompressed_block(dbg, array);
+
+}
+
+static const char *
+get_rangelist_type_descr(Dwarf_Ranges *r)
+{
+ switch(r->dwr_type) {
+ case DW_RANGES_ENTRY: return "range entry";
+ case DW_RANGES_ADDRESS_SELECTION: return "addr selection";
+ case DW_RANGES_END: return "range end";
+ }
+ /* Impossible. */
+ return "Unknown";
+}
+
+
+void
+print_ranges_list_to_extra(Dwarf_Debug dbg,
+ Dwarf_Unsigned off,
+ Dwarf_Ranges *rangeset,
+ Dwarf_Signed rangecount,
+ Dwarf_Unsigned bytecount,
+ struct esb_s *stringbuf)
+{
+ char tmp[200];
+ Dwarf_Signed i;
+ if(dense) {
+ snprintf(tmp,sizeof(tmp),
+ "< ranges: %" DW_PR_DSd " ranges at .debug_ranges offset %"
+ DW_PR_DUu " (0x%" DW_PR_XZEROS DW_PR_DUx ") "
+ "(%" DW_PR_DUu " bytes)>",
+ rangecount,
+ off,
+ off,
+ bytecount);
+ esb_append(stringbuf,tmp);
+ } else {
+ snprintf(tmp,sizeof(tmp),
+ "\t\tranges: %" DW_PR_DSd " at .debug_ranges offset %"
+ DW_PR_DUu " (0x%" DW_PR_XZEROS DW_PR_DUx ") "
+ "(%" DW_PR_DUu " bytes)\n",
+ rangecount,
+ off,
+ off,
+ bytecount);
+ esb_append(stringbuf,tmp);
+ }
+ for(i = 0; i < rangecount; ++i) {
+ Dwarf_Ranges * r = rangeset +i;
+ const char *type = get_rangelist_type_descr(r);
+ if(dense) {
+ snprintf(tmp,sizeof(tmp),
+ "<[%2" DW_PR_DSd
+ "] %s 0x%" DW_PR_XZEROS DW_PR_DUx
+ " 0x%" DW_PR_XZEROS DW_PR_DUx ">",
+ (Dwarf_Signed)i,
+ type,
+ (Dwarf_Unsigned)r->dwr_addr1,
+ (Dwarf_Unsigned)r->dwr_addr2);
+ } else {
+ snprintf(tmp,sizeof(tmp),
+ "\t\t\t[%2" DW_PR_DSd
+ "] %-14s 0x%" DW_PR_XZEROS DW_PR_DUx
+ " 0x%" DW_PR_XZEROS DW_PR_DUx "\n",
+ (Dwarf_Signed)i,
+ type,
+ (Dwarf_Unsigned)r->dwr_addr1,
+ (Dwarf_Unsigned)r->dwr_addr2);
+ }
+ esb_append(stringbuf,tmp);
+ }
+}
+
+
+static boolean
+is_location_form(int form)
+{
+ if(form == DW_FORM_block1 ||
+ form == DW_FORM_block2 ||
+ form == DW_FORM_block4 ||
+ form == DW_FORM_block ||
+ form == DW_FORM_data4 ||
+ form == DW_FORM_data8 ||
+ form == DW_FORM_sec_offset) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void
+show_attr_form_error(Dwarf_Debug dbg,unsigned attr,unsigned form,struct esb_s *out)
+{
+ const char *n = 0;
+ int res;
+ char buf[30];
+ esb_append(out,"ERROR: Attribute ");
+ snprintf(buf,sizeof(buf),"%u",attr);
+ esb_append(out,buf);
+ esb_append(out," (");
+ res = dwarf_get_AT_name(attr,&n);
+ if(res != DW_DLV_OK) {
+ n = "UknownAttribute";
+ }
+ esb_append(out,n);
+ esb_append(out,") ");
+ esb_append(out," has form ");
+ snprintf(buf,sizeof(buf),"%u",form);
+ esb_append(out,buf);
+ esb_append(out," (");
+ res = dwarf_get_FORM_name(form,&n);
+ if(res != DW_DLV_OK) {
+ n = "UknownForm";
+ }
+ esb_append(out,n);
+ esb_append(out,"), a form which is not appropriate");
+ print_error_and_continue(dbg,esb_get_string(out), DW_DLV_OK,err);
+}
+
+/* Traverse an attribute and following any reference
+ in order to detect self references to DIES (loop). */
+static boolean
+traverse_attribute(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Half attr,
+ Dwarf_Attribute attr_in,
+ boolean print_information,
+ char **srcfiles, Dwarf_Signed cnt,
+ int die_indent_level)
+{
+ Dwarf_Attribute attrib = 0;
+ const char * atname = 0;
+ const char * valname = 0;
+ int tres = 0;
+ Dwarf_Half tag = 0;
+ boolean circular_reference = FALSE;
+ Dwarf_Bool is_info = TRUE;
+
+ is_info = dwarf_get_die_infotypes_flag(die);
+ atname = get_AT_name(attr,dwarf_names_print_on_error);
+
+ /* The following gets the real attribute, even in the face of an
+ incorrect doubling, or worse, of attributes. */
+ attrib = attr_in;
+ /* Do not get attr via dwarf_attr: if there are (erroneously)
+ multiple of an attr in a DIE, dwarf_attr will not get the
+ second, erroneous one and dwarfdump will print the first one
+ multiple times. Oops. */
+
+ tres = dwarf_tag(die, &tag, &err);
+ if (tres == DW_DLV_ERROR) {
+ tag = 0;
+ } else if (tres == DW_DLV_NO_ENTRY) {
+ tag = 0;
+ } else {
+ /* ok */
+ }
+
+ switch (attr) {
+ case DW_AT_specification:
+ case DW_AT_abstract_origin:
+ case DW_AT_type: {
+ int res = 0;
+ Dwarf_Off die_off = 0;
+ Dwarf_Off ref_off = 0;
+ Dwarf_Die ref_die = 0;
+
+ ++die_indent_level;
+ esb_empty_string(&esb_base);
+ get_attr_value(dbg, tag, die, attrib, srcfiles, cnt,
+ &esb_base, show_form_used,verbose);
+ valname = esb_get_string(&esb_base);
+
+ /* Get the global offset for reference */
+ res = dwarf_global_formref(attrib, &ref_off, &err);
+ if (res != DW_DLV_OK) {
+ int errno = dwarf_errno(err);
+ if (errno == DW_DLE_REF_SIG8_NOT_HANDLED ) {
+ // No need to stop, ref_sig8 refers out of
+ // the current section.
+ break;
+ } else {
+ print_error(dbg, "dwarf_global_formref fails in traversal",
+ res, err);
+ }
+ }
+ res = dwarf_dieoffset(die, &die_off, &err);
+ if (res != DW_DLV_OK) {
+ int errno = dwarf_errno(err);
+ if (errno == DW_DLE_REF_SIG8_NOT_HANDLED ) {
+ // No need to stop, ref_sig8 refers out of
+ // the current section.
+ break;
+ } else {
+ print_error(dbg, "dwarf_dieoffset fails in traversal", res, err);
+ }
+ }
+
+ /* Follow reference chain, looking for self references */
+ res = dwarf_offdie_b(dbg,ref_off,is_info,&ref_die,&err);
+ if (res == DW_DLV_OK) {
+ ++die_indent_level;
+ /* Dump visited information */
+ if (dump_visited_info) {
+ Dwarf_Off off = 0;
+ dwarf_die_CU_offset(die, &off, &err);
+ /* Check above call return status? FIXME */
+
+ printf("<%2d><0x%" DW_PR_XZEROS DW_PR_DUx
+ " GOFF=0x%" DW_PR_XZEROS DW_PR_DUx "> ",
+ die_indent_level, (Dwarf_Unsigned)off,
+ (Dwarf_Unsigned)die_off);
+ printf("%*s%s -> %s\n",die_indent_level * 2 + 2,
+ " ",atname,valname);
+ }
+ circular_reference = traverse_one_die(dbg,attrib,ref_die,
+ srcfiles,cnt,die_indent_level);
+ DeleteKeyInBucketGroup(pVisitedInfo,ref_off);
+ dwarf_dealloc(dbg,ref_die,DW_DLA_DIE);
+ --die_indent_level;
+ ref_die = 0;
+ }
+ }
+ break;
+ } /* End switch. */
+ return circular_reference;
+}
+
+/* Traverse one DIE in order to detect self references to DIES. */
+static boolean
+traverse_one_die(Dwarf_Debug dbg, Dwarf_Attribute attrib, Dwarf_Die die,
+ char **srcfiles, Dwarf_Signed cnt, int die_indent_level)
+{
+ Dwarf_Half tag = 0;
+ Dwarf_Off overall_offset = 0;
+ Dwarf_Signed atcnt = 0;
+ int res = 0;
+ boolean circular_reference = FALSE;
+ boolean print_information = FALSE;
+
+ res = dwarf_tag(die, &tag, &err);
+ if (res != DW_DLV_OK) {
+ print_error(dbg, "accessing tag of die!", res, err);
+ }
+ res = dwarf_dieoffset(die, &overall_offset, &err);
+ if (res != DW_DLV_OK) {
+ print_error(dbg, "dwarf_dieoffset", res, err);
+ }
+
+ /* Print visited information */
+ if (dump_visited_info) {
+ Dwarf_Off offset = 0;
+ const char * tagname = 0;
+ res = dwarf_die_CU_offset(die, &offset, &err);
+ if (res != DW_DLV_OK) {
+ print_error(dbg, "dwarf_die_CU_offsetC", res, err);
+ }
+ tagname = get_TAG_name(tag,dwarf_names_print_on_error);
+ printf("<%2d><0x%" DW_PR_XZEROS DW_PR_DUx
+ " GOFF=0x%" DW_PR_XZEROS DW_PR_DUx "> ",
+ die_indent_level, (Dwarf_Unsigned)offset,
+ (Dwarf_Unsigned)overall_offset);
+ printf("%*s%s\n",die_indent_level * 2 + 2," ",tagname);
+ }
+
+ DWARF_CHECK_COUNT(self_references_result,1);
+ if (FindKeyInBucketGroup(pVisitedInfo,overall_offset)) {
+ char * valname = NULL;
+ Dwarf_Half attr = 0;
+ const char *atname = NULL;
+ esb_empty_string(&esb_base);
+ get_attr_value(dbg, tag, die, attrib, srcfiles,
+ cnt, &esb_base, show_form_used,verbose);
+ valname = esb_get_string(&esb_base);
+ dwarf_whatattr(attrib, &attr, &err);
+ atname = get_AT_name(attr,dwarf_names_print_on_error);
+
+ /* We have a self reference */
+ DWARF_CHECK_ERROR3(self_references_result,
+ "Invalid self reference to DIE: ",atname,valname);
+ circular_reference = TRUE;
+ } else {
+ Dwarf_Signed i = 0;
+ Dwarf_Attribute *atlist = 0;
+
+ /* Add current DIE */
+ AddEntryIntoBucketGroup(pVisitedInfo,overall_offset,
+ 0,0,0,NULL,FALSE);
+
+ res = dwarf_attrlist(die, &atlist, &atcnt, &err);
+ if (res == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_attrlist", res, err);
+ } else if (res == DW_DLV_NO_ENTRY) {
+ /* indicates there are no attrs. It is not an error. */
+ atcnt = 0;
+ }
+
+ for (i = 0; i < atcnt; i++) {
+ Dwarf_Half attr;
+ int ares;
+
+ ares = dwarf_whatattr(atlist[i], &attr, &err);
+ if (ares == DW_DLV_OK) {
+ circular_reference = traverse_attribute(dbg, die, attr,
+ atlist[i],
+ print_information, srcfiles, cnt,
+ die_indent_level);
+ } else {
+ print_error(dbg, "dwarf_whatattr entry missing",
+ ares, err);
+ }
+ }
+
+ for (i = 0; i < atcnt; i++) {
+ dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);
+ }
+ if (res == DW_DLV_OK) {
+ dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
+ }
+
+ /* Delete current DIE */
+ DeleteKeyInBucketGroup(pVisitedInfo,overall_offset);
+ }
+ return circular_reference;
+}
+
+
+/* Extracted this from print_attribute()
+ to get tolerable indents.
+ In other words to make it readable.
+ It uses global data fields excessively, but so does
+ print_attribute().
+ The majority of the code here is checking for
+ compiler errors. */
+static void
+print_range_attribute(Dwarf_Debug dbg,
+ Dwarf_Die die,
+ Dwarf_Half attr,
+ Dwarf_Attribute attr_in,
+ Dwarf_Half theform,
+ int dwarf_names_print_on_error,
+ boolean print_information,
+ int *append_extra_string)
+{
+ Dwarf_Error err = 0;
+ Dwarf_Unsigned original_off = 0;
+ int fres = 0;
+
+ fres = dwarf_global_formref(attr_in, &original_off, &err);
+ if( fres == DW_DLV_OK) {
+ Dwarf_Ranges *rangeset = 0;
+ Dwarf_Signed rangecount = 0;
+ Dwarf_Unsigned bytecount = 0;
+ int rres = dwarf_get_ranges_a(dbg,original_off,
+ die,
+ &rangeset,
+ &rangecount,&bytecount,&err);
+ if(rres == DW_DLV_OK) {
+ /* Ignore ranges inside a stripped function */
+ if (check_ranges &&
+ in_valid_code && checking_this_compiler()) {
+ Dwarf_Unsigned off = original_off;
+
+ Dwarf_Signed index = 0;
+ Dwarf_Addr base_address = CU_base_address;
+ Dwarf_Addr lopc = 0;
+ Dwarf_Addr hipc = 0;
+ Dwarf_Bool bError = FALSE;
+
+ /* Ignore last entry, is the end-of-list */
+ for (index = 0; index < rangecount - 1; index++) {
+ Dwarf_Ranges *r = rangeset + index;
+
+ if (r->dwr_addr1 == elf_max_address) {
+ /* (0xffffffff,addr), use specific address (current PU address) */
+ base_address = r->dwr_addr2;
+ } else {
+ /* (offset,offset), update using CU address */
+ lopc = r->dwr_addr1 + base_address;
+ hipc = r->dwr_addr2 + base_address;
+ DWARF_CHECK_COUNT(ranges_result,1);
+
+ /* Check the low_pc and high_pc
+ are within a valid range in
+ the .text section */
+ if (IsValidInBucketGroup(pRangesInfo,lopc) &&
+ IsValidInBucketGroup(pRangesInfo,hipc)) {
+ /* Valid values; do nothing */
+ } else {
+ /* At this point may be we
+ are dealing with a
+ linkonce symbol */
+ if (IsValidInLinkonce(pLinkonceInfo,
+ PU_name,lopc,hipc)) {
+ /* Valid values; do nothing */
+ } else {
+ bError = TRUE;
+ DWARF_CHECK_ERROR(ranges_result,
+ ".debug_ranges: Address outside a "
+ "valid .text range");
+ if (check_verbose_mode) {
+ printf(
+ "Offset = 0x%" DW_PR_XZEROS DW_PR_DUx
+ ", Base = 0x%" DW_PR_XZEROS DW_PR_DUx
+ ", "
+ "Low = 0x%" DW_PR_XZEROS DW_PR_DUx
+ " (0x%" DW_PR_XZEROS DW_PR_DUx
+ "), High = 0x%"
+ DW_PR_XZEROS DW_PR_DUx
+ " (0x%" DW_PR_XZEROS DW_PR_DUx
+ ")\n",
+ off,base_address,lopc,
+ r->dwr_addr1,hipc,
+ r->dwr_addr2);
+ }
+ }
+ }
+ }
+ /* Each entry holds 2 addresses (offsets) */
+ off += elf_address_size * 2;
+ }
+ if (bError && check_verbose_mode) {
+ printf("\n");
+ }
+ }
+ if(print_information) {
+ *append_extra_string = 1;
+ esb_empty_string(&esb_extra);
+ print_ranges_list_to_extra(dbg,original_off,
+ rangeset,rangecount,bytecount,
+ &esb_extra);
+ }
+ dwarf_ranges_dealloc(dbg,rangeset,rangecount);
+ } else if (rres == DW_DLV_ERROR) {
+ if (do_print_dwarf) {
+ printf("\ndwarf_get_ranges() "
+ "cannot find DW_AT_ranges at offset 0x%"
+ DW_PR_XZEROS DW_PR_DUx
+ " (0x%" DW_PR_XZEROS DW_PR_DUx ").",
+ original_off,
+ original_off);
+ } else {
+ DWARF_CHECK_COUNT(ranges_result,1);
+ DWARF_CHECK_ERROR2(ranges_result,
+ get_AT_name(attr,
+ dwarf_names_print_on_error),
+ " cannot find DW_AT_ranges at offset");
+ }
+ } else {
+ /* NO ENTRY */
+ if (do_print_dwarf) {
+ printf("\ndwarf_get_ranges() "
+ "finds no DW_AT_ranges at offset 0x%"
+ DW_PR_XZEROS DW_PR_DUx
+ " (0x%" DW_PR_XZEROS DW_PR_DUx ").",
+ original_off,
+ original_off);
+ } else {
+ DWARF_CHECK_COUNT(ranges_result,1);
+ DWARF_CHECK_ERROR2(ranges_result,
+ get_AT_name(attr,
+ dwarf_names_print_on_error),
+ " fails to find DW_AT_ranges at offset");
+ }
+ }
+ } else {
+ if (do_print_dwarf) {
+ struct esb_s local;
+ char tmp[100];
+
+ snprintf(tmp,sizeof(tmp)," attr 0x%x form 0x%x ",
+ (unsigned)attr,(unsigned)theform);
+ esb_constructor(&local);
+ esb_append(&local,
+ " fails to find DW_AT_ranges offset");
+ esb_append(&local,tmp);
+ printf(" %s ",esb_get_string(&local));
+ esb_destructor(&local);
+ } else {
+ DWARF_CHECK_COUNT(ranges_result,1);
+ DWARF_CHECK_ERROR2(ranges_result,
+ get_AT_name(attr,
+ dwarf_names_print_on_error),
+ " fails to find DW_AT_ranges offset");
+ }
+ }
+}
+
+/* A DW_AT_name in a CU DIE will likely have dots
+ and be entirely sensible. So lets
+ not call things a possible error when they are not.
+ Some assemblers allow '.' in an identifier too.
+ We should check for that, but we don't yet.
+
+ We should check the compiler before checking
+ for 'altabi.' too (FIXME).
+
+ This is a heuristic, not all that reliable.
+
+ Return 0 if it is a vaguely standard identifier.
+ Else return 1, meaning 'it might be a file name
+ or have '.' in it quite sensibly.'
+
+ If we don't do the TAG check we might report "t.c"
+ as a questionable DW_AT_name. Which would be silly.
+*/
+static int
+dot_ok_in_identifier(int tag,Dwarf_Die die, const char *val)
+{
+ if (strncmp(val,"altabi.",7)) {
+ /* Ignore the names of the form 'altabi.name',
+ which apply to one specific compiler. */
+ return 1;
+ }
+ if(tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit ||
+ tag == DW_TAG_imported_unit || tag == DW_TAG_type_unit) {
+ return 1;
+ }
+ return 0;
+}
+
+static void
+trim_quotes(const char *val,struct esb_s *es)
+{
+ if(val[0] == '"') {
+ size_t l = strlen(val);
+ if(l > 2 && val[l-1] == '"') {
+ esb_appendn(es,val+1,l-2);
+ return;
+ }
+ }
+ esb_append(es,val);
+}
+
+static int
+have_a_search_match(const char *valname,const char *atname)
+{
+ /* valname may have had quotes inserted, but search_match_text
+ will not. So we need to use a new copy, not valname here.
+ */
+ struct esb_s esb_match;
+ char *s2;
+ esb_constructor(&esb_match);
+
+ trim_quotes(valname,&esb_match);
+ s2 = esb_get_string(&esb_match);
+ if (search_match_text ) {
+ if(!strcmp(s2,search_match_text) ||
+ !strcmp(atname,search_match_text)) {
+
+ esb_destructor(&esb_match);
+ return TRUE;
+ }
+ }
+ if (search_any_text) {
+ if(is_strstrnocase(s2,search_any_text) ||
+ is_strstrnocase(atname,search_any_text)) {
+
+ esb_destructor(&esb_match);
+ return TRUE;
+ }
+ }
+#ifdef HAVE_REGEX
+ if (search_regex_text) {
+ if(!regexec(&search_re,s2,0,NULL,0) ||
+ !regexec(&search_re,atname,0,NULL,0)) {
+
+ esb_destructor(&esb_match);
+ return TRUE;
+ }
+ }
+#endif
+ esb_destructor(&esb_match);
+ return FALSE;
+}
+
+
+static boolean
+print_attribute(Dwarf_Debug dbg, Dwarf_Die die,
+ Dwarf_Half attr,
+ Dwarf_Attribute attr_in,
+ boolean print_information,
+ int die_indent_level,
+ char **srcfiles, Dwarf_Signed cnt)
+{
+ Dwarf_Attribute attrib = 0;
+ Dwarf_Unsigned uval = 0;
+ const char * atname = 0;
+ const char * valname = 0;
+ int tres = 0;
+ Dwarf_Half tag = 0;
+ int append_extra_string = 0;
+ boolean found_search_attr = FALSE;
+ boolean bTextFound = FALSE;
+ Dwarf_Bool is_info = FALSE;
+
+ is_info = dwarf_get_die_infotypes_flag(die);
+ esb_empty_string(&esb_extra);
+ atname = get_AT_name(attr,dwarf_names_print_on_error);
+
+ /* The following gets the real attribute, even in the face of an
+ incorrect doubling, or worse, of attributes. */
+ attrib = attr_in;
+ /* Do not get attr via dwarf_attr: if there are (erroneously)
+ multiple of an attr in a DIE, dwarf_attr will not get the
+ second, erroneous one and dwarfdump will print the first one
+ multiple times. Oops. */
+
+ tres = dwarf_tag(die, &tag, &err);
+ if (tres == DW_DLV_ERROR) {
+ tag = 0;
+ } else if (tres == DW_DLV_NO_ENTRY) {
+ tag = 0;
+ } else {
+ /* ok */
+ }
+ if (check_attr_tag && checking_this_compiler()) {
+ const char *tagname = "<tag invalid>";
+
+ DWARF_CHECK_COUNT(attr_tag_result,1);
+ if (tres == DW_DLV_ERROR) {
+ DWARF_CHECK_ERROR3(attr_tag_result,tagname,
+ get_AT_name(attr,dwarf_names_print_on_error),
+ "check the tag-attr combination, dwarf_tag failed.");
+ } else if (tres == DW_DLV_NO_ENTRY) {
+ DWARF_CHECK_ERROR3(attr_tag_result,tagname,
+ get_AT_name(attr,dwarf_names_print_on_error),
+ "check the tag-attr combination, dwarf_tag NO ENTRY?.");
+ } else if (legal_tag_attr_combination(tag, attr)) {
+ /* OK */
+ } else {
+ tagname = get_TAG_name(tag,dwarf_names_print_on_error);
+ tag_specific_checks_setup(tag,die_stack_indent_level);
+ DWARF_CHECK_ERROR3(attr_tag_result,tagname,
+ get_AT_name(attr,dwarf_names_print_on_error),
+ "check the tag-attr combination");
+ }
+ }
+
+ switch (attr) {
+ case DW_AT_language:
+ get_small_encoding_integer_and_name(dbg, attrib, &uval,
+ "DW_AT_language", &valname,
+ get_LANG_name, &err,
+ show_form_used);
+ break;
+ case DW_AT_accessibility:
+ get_small_encoding_integer_and_name(dbg, attrib, &uval,
+ "DW_AT_accessibility",
+ &valname, get_ACCESS_name,
+ &err,
+ show_form_used);
+ break;
+ case DW_AT_visibility:
+ get_small_encoding_integer_and_name(dbg, attrib, &uval,
+ "DW_AT_visibility",
+ &valname, get_VIS_name,
+ &err,
+ show_form_used);
+ break;
+ case DW_AT_virtuality:
+ get_small_encoding_integer_and_name(dbg, attrib, &uval,
+ "DW_AT_virtuality",
+ &valname,
+ get_VIRTUALITY_name, &err,
+ show_form_used);
+ break;
+ case DW_AT_identifier_case:
+ get_small_encoding_integer_and_name(dbg, attrib, &uval,
+ "DW_AT_identifier",
+ &valname, get_ID_name,
+ &err,
+ show_form_used);
+ break;
+ case DW_AT_inline:
+ get_small_encoding_integer_and_name(dbg, attrib, &uval,
+ "DW_AT_inline", &valname,
+ get_INL_name, &err,
+ show_form_used);
+ break;
+ case DW_AT_encoding:
+ get_small_encoding_integer_and_name(dbg, attrib, &uval,
+ "DW_AT_encoding", &valname,
+ get_ATE_name, &err,
+ show_form_used);
+ break;
+ case DW_AT_ordering:
+ get_small_encoding_integer_and_name(dbg, attrib, &uval,
+ "DW_AT_ordering", &valname,
+ get_ORD_name, &err,
+ show_form_used);
+ break;
+ case DW_AT_calling_convention:
+ get_small_encoding_integer_and_name(dbg, attrib, &uval,
+ "DW_AT_calling_convention",
+ &valname, get_CC_name,
+ &err,
+ show_form_used);
+ break;
+ case DW_AT_discr_list: /* DWARF3 */
+ get_small_encoding_integer_and_name(dbg, attrib, &uval,
+ "DW_AT_discr_list",
+ &valname, get_DSC_name,
+ &err,
+ show_form_used);
+ break;
+ case DW_AT_data_member_location:
+ {
+ /* Value is a constant or a location
+ description or location list.
+ If a constant, it could be signed or
+ unsigned. Telling whether a constant
+ or a reference is nontrivial
+ since DW_FORM_data{4,8}
+ could be either in DWARF{2,3} */
+ enum Dwarf_Form_Class fc = DW_FORM_CLASS_UNKNOWN;
+ Dwarf_Half theform = 0;
+ Dwarf_Half directform = 0;
+ Dwarf_Half version = 0;
+ Dwarf_Half offset_size = 0;
+ int wres = 0;
+
+ get_form_values(attrib,&theform,&directform);
+ wres = dwarf_get_version_of_die(die ,
+ &version,&offset_size);
+ if(wres != DW_DLV_OK) {
+ print_error(dbg,"Cannot get DIE context version number",wres,err);
+ break;
+ }
+ fc = dwarf_get_form_class(version,attr,offset_size,theform);
+ if(fc == DW_FORM_CLASS_CONSTANT) {
+ esb_empty_string(&esb_base);
+ wres = formxdata_print_value(dbg,attrib,&esb_base,
+ &err, FALSE);
+ show_form_itself(show_form_used,verbose, theform,
+ directform,&esb_base);
+ valname = esb_get_string(&esb_base);
+ if(wres == DW_DLV_OK){
+ /* String appended already. */
+ break;
+ } else if (wres == DW_DLV_NO_ENTRY) {
+ print_error(dbg,"Cannot get DW_AT_data_member_location, how can it be NO_ENTRY? ",wres,err);
+ break;
+ } else {
+ print_error(dbg,"Cannot get DW_AT_data_member_location ",wres,err);
+ break;
+ }
+ }
+ /* FALL THRU, this is a
+ a location description, or a reference
+ to one, or a mistake. */
+ }
+ /* FALL THRU to location description */
+ case DW_AT_location:
+ case DW_AT_vtable_elem_location:
+ case DW_AT_string_length:
+ case DW_AT_return_addr:
+ case DW_AT_use_location:
+ case DW_AT_static_link:
+ case DW_AT_frame_base:
+ {
+ /* The value is a location description
+ or location list. */
+
+ Dwarf_Half theform = 0;
+ Dwarf_Half directform = 0;
+ get_form_values(attrib,&theform,&directform);
+ esb_empty_string(&esb_base);
+ if(is_location_form(theform)) {
+ get_location_list(dbg, die, attrib, &esb_base);
+ show_form_itself(show_form_used,verbose,
+ theform, directform,&esb_base);
+ } else if (theform == DW_FORM_exprloc) {
+ int showhextoo = 1;
+ print_exprloc_content(dbg,die,attrib,showhextoo,&esb_base);
+ } else {
+ show_attr_form_error(dbg,attr,theform,&esb_base);
+ }
+ valname = esb_get_string(&esb_base);
+ }
+ break;
+ case DW_AT_SUN_func_offsets:
+ {
+ /* value is a location description or location list */
+ Dwarf_Half theform = 0;
+ Dwarf_Half directform = 0;
+ get_form_values(attrib,&theform,&directform);
+ esb_empty_string(&esb_base);
+ get_FLAG_BLOCK_string(dbg, attrib,&esb_base);
+ show_form_itself(show_form_used,verbose, theform,
+ directform,&esb_base);
+ valname = esb_get_string(&esb_base);
+ }
+ break;
+ case DW_AT_SUN_cf_kind:
+ {
+ Dwarf_Half kind = 0;
+ Dwarf_Unsigned tempud = 0;
+ Dwarf_Error err = 0;
+ int wres = 0;
+ Dwarf_Half theform = 0;
+ Dwarf_Half directform = 0;
+ get_form_values(attrib,&theform,&directform);
+ wres = dwarf_formudata (attrib,&tempud, &err);
+ esb_empty_string(&esb_base);
+ if(wres == DW_DLV_OK) {
+ kind = tempud;
+ esb_append(&esb_base,
+ get_ATCF_name(kind,dwarf_names_print_on_error));
+ } else if (wres == DW_DLV_NO_ENTRY) {
+ esb_append(&esb_base, "?");
+ } else {
+ print_error(dbg,"Cannot get formudata....",wres,err);
+ esb_append(&esb_base, "??");
+ }
+ show_form_itself(show_form_used,verbose, theform,
+ directform,&esb_base);
+ valname = esb_get_string(&esb_base);
+ }
+ break;
+ case DW_AT_upper_bound:
+ {
+ Dwarf_Half theform;
+ int rv;
+ rv = dwarf_whatform(attrib,&theform,&err);
+ /* depending on the form and the attribute, process the form */
+ if(rv == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_whatform Cannot find attr form",
+ rv, err);
+ } else if (rv == DW_DLV_NO_ENTRY) {
+ break;
+ }
+
+ esb_empty_string(&esb_base);
+ switch (theform) {
+ case DW_FORM_block1: {
+ Dwarf_Half theform = 0;
+ Dwarf_Half directform = 0;
+ get_form_values(attrib,&theform,&directform);
+ get_location_list(dbg, die, attrib, &esb_base);
+ show_form_itself(show_form_used,verbose, theform,
+ directform,&esb_base);
+ valname = esb_get_string(&esb_base);
+ }
+ break;
+ default:
+ get_attr_value(dbg, tag, die,
+ attrib, srcfiles, cnt, &esb_base, show_form_used,verbose);
+ valname = esb_get_string(&esb_base);
+ break;
+ }
+ break;
+ }
+ case DW_AT_low_pc:
+ case DW_AT_high_pc:
+ {
+ Dwarf_Half theform;
+ int rv;
+ rv = dwarf_whatform(attrib,&theform,&err);
+ /* Depending on the form and the attribute,
+ process the form. */
+ if(rv == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_whatform cannot Find attr form",
+ rv, err);
+ } else if (rv == DW_DLV_NO_ENTRY) {
+ break;
+ }
+ esb_empty_string(&esb_base);
+ if( theform != DW_FORM_addr) {
+ /* New in DWARF4: other forms are not an address
+ but are instead offset from pc.
+ One could test for DWARF4 here before adding
+ this string, but that seems unnecessary as this
+ could not happen with DWARF3 or earlier.
+ A normal consumer would have to add this value to
+ DW_AT_low_pc to get a true pc. */
+ esb_append(&esb_base,"<offset-from-lowpc>");
+ }
+ get_attr_value(dbg, tag, die, attrib, srcfiles, cnt,
+ &esb_base,show_form_used,verbose);
+ valname = esb_get_string(&esb_base);
+
+ /* Update base and high addresses for CU */
+ if (seen_CU && (need_CU_base_address ||
+ need_CU_high_address)) {
+
+ /* Update base address for CU */
+ if (need_CU_base_address && attr == DW_AT_low_pc) {
+ dwarf_formaddr(attrib, &CU_base_address, &err);
+ need_CU_base_address = FALSE;
+ }
+
+ /* Update high address for CU */
+ if (need_CU_high_address && attr == DW_AT_high_pc) {
+ dwarf_formaddr(attrib, &CU_high_address, &err);
+ need_CU_high_address = FALSE;
+ }
+ }
+
+ /* Record the low and high addresses as we have them */
+ if ((check_decl_file || check_ranges ||
+ check_locations) && theform == DW_FORM_addr) {
+ Dwarf_Addr addr = 0;
+ dwarf_formaddr(attrib, &addr, &err);
+ if (attr == DW_AT_low_pc) {
+ lowAddr = addr;
+ bSawLow = TRUE;
+ /* Record the base address of the last seen PU
+ to be used when checking line information */
+ if (seen_PU && !seen_PU_base_address) {
+ seen_PU_base_address = TRUE;
+ PU_base_address = addr;
+ }
+ } else {
+ highAddr = addr;
+ bSawHigh = TRUE;
+ /* Record the high address of the last seen PU
+ to be used when checking line information */
+ if (seen_PU && !seen_PU_high_address) {
+ seen_PU_high_address = TRUE;
+ PU_high_address = addr;
+ }
+ }
+
+ /* We have now both low_pc and high_pc values */
+ if (bSawLow && bSawHigh) {
+
+ /* We need to decide if this PU is
+ valid, as the SN Linker marks a stripped
+ function by setting lowpc to -1;
+ also for discarded comdat, both lowpc
+ and highpc are zero */
+ if (need_PU_valid_code) {
+ need_PU_valid_code = FALSE;
+
+ /* To ignore a PU as invalid code,
+ only consider the lowpc and
+ highpc values associated with the
+ DW_TAG_subprogram; other
+ instances of lowpc and highpc,
+ must be ignore (lexical blocks) */
+ in_valid_code = TRUE;
+ if (IsInvalidCode(lowAddr,highAddr) &&
+ tag == DW_TAG_subprogram) {
+ in_valid_code = FALSE;
+ }
+ }
+
+ /* We have a low_pc/high_pc pair;
+ check if they are valid */
+ if (in_valid_code) {
+ DWARF_CHECK_COUNT(ranges_result,1);
+ if (lowAddr != elf_max_address &&
+ lowAddr > highAddr) {
+ DWARF_CHECK_ERROR(ranges_result,
+ ".debug_info: Incorrect values "
+ "for low_pc/high_pc");
+ if (check_verbose_mode) {
+ printf("Low = 0x%" DW_PR_XZEROS DW_PR_DUx
+ ", High = 0x%" DW_PR_XZEROS DW_PR_DUx "\n",
+ lowAddr,highAddr);
+ }
+ }
+ if (check_decl_file || check_ranges ||
+ check_locations) {
+ AddEntryIntoBucketGroup(pRangesInfo,0,lowAddr,
+ lowAddr,highAddr,NULL,FALSE);
+ }
+ }
+ bSawLow = FALSE;
+ bSawHigh = FALSE;
+ }
+ }
+ }
+ break;
+ case DW_AT_ranges:
+ {
+ Dwarf_Half theform = 0;
+ int rv;
+
+ rv = dwarf_whatform(attrib,&theform,&err);
+ if(rv == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_whatform cannot find Attr Form",
+ rv, err);
+ } else if (rv == DW_DLV_NO_ENTRY) {
+ break;
+ }
+
+ esb_empty_string(&esb_base);
+ get_attr_value(dbg, tag,die, attrib, srcfiles, cnt, &esb_base,
+ show_form_used,verbose);
+ print_range_attribute(dbg, die, attr,attr_in, theform,
+ dwarf_names_print_on_error,print_information,
+ &append_extra_string);
+ valname = esb_get_string(&esb_base);
+ }
+ break;
+ case DW_AT_MIPS_linkage_name:
+ esb_empty_string(&esb_base);
+ get_attr_value(dbg, tag, die, attrib, srcfiles,
+ cnt, &esb_base, show_form_used,verbose);
+ valname = esb_get_string(&esb_base);
+
+ if (check_locations || check_ranges) {
+ int local_show_form = 0;
+ int local_verbose = 0;
+ struct esb_s lesb;
+ const char *name = 0;
+ esb_constructor(&lesb);
+ get_attr_value(dbg, tag, die, attrib, srcfiles, cnt,
+ &lesb, local_show_form,local_verbose);
+ /* Look for specific name forms, attempting to
+ notice and report 'odd' identifiers. */
+ name = esb_get_string(&lesb);
+ safe_strcpy(PU_name,sizeof(PU_name),name,strlen(name));
+ }
+ break;
+ case DW_AT_name:
+ case DW_AT_GNU_template_name:
+ esb_empty_string(&esb_base);
+ get_attr_value(dbg, tag, die, attrib, srcfiles, cnt,
+ &esb_base, show_form_used,verbose);
+ valname = esb_get_string(&esb_base);
+
+ if (check_names && checking_this_compiler()) {
+ int local_show_form = FALSE;
+ int local_verbose = 0;
+ struct esb_s lesb;
+ const char *name = 0;
+ esb_constructor(&lesb);
+ get_attr_value(dbg, tag, die, attrib, srcfiles, cnt,
+ &lesb, local_show_form,local_verbose);
+ /* Look for specific name forms, attempting to
+ notice and report 'odd' identifiers. */
+ name = esb_get_string(&lesb);
+ DWARF_CHECK_COUNT(names_result,1);
+ if (!strcmp("\"(null)\"",name)) {
+ DWARF_CHECK_ERROR(names_result,
+ "string attribute is \"(null)\".");
+ } else {
+ if (!dot_ok_in_identifier(tag,die,name)
+ && !need_CU_name && strchr(name,'.')) {
+ /* This is a suggestion there 'might' be
+ a surprising name, not a guarantee of an
+ error. */
+ DWARF_CHECK_ERROR(names_result,
+ "string attribute is invalid.");
+ }
+ }
+ esb_destructor(&lesb);
+ }
+
+ /* If we are in checking mode and we do not have a PU name */
+ if ((check_locations || check_ranges) && seen_PU && !PU_name[0]) {
+ int local_show_form = FALSE;
+ int local_verbose = 0;
+ const char *name = 0;
+ struct esb_s lesb;
+ esb_constructor(&lesb);
+ get_attr_value(dbg, tag, die, attrib, srcfiles, cnt,
+ &lesb, local_show_form,local_verbose);
+ name = esb_get_string(&lesb);
+
+ safe_strcpy(PU_name,sizeof(PU_name),name,strlen(name));
+ esb_destructor(&lesb);
+ }
+
+ /* If we are processing the compile unit, record the name */
+ if (seen_CU && need_CU_name) {
+ /* Lets not get the form name included. */
+ struct esb_s lesb;
+ int local_show_form_used = FALSE;
+ int local_verbose = 0;
+ char *localname = 0;
+ esb_constructor(&lesb);
+ get_attr_value(dbg, tag, die, attrib, srcfiles, cnt,
+ &lesb, local_show_form_used,local_verbose);
+ localname = esb_get_string(&lesb);
+ safe_strcpy(CU_name,sizeof(CU_name),localname,strlen(localname));
+ need_CU_name = FALSE;
+ esb_destructor(&lesb);
+ }
+ break;
+
+ case DW_AT_producer:
+ esb_empty_string(&esb_base);
+ get_attr_value(dbg, tag, die, attrib, srcfiles, cnt,
+ &esb_base, show_form_used,verbose);
+ valname = esb_get_string(&esb_base);
+ /* If we are in checking mode, identify the compiler */
+ if (do_check_dwarf || search_is_on) {
+ /* Do not use show-form here! We just want the producer name, not
+ the form name. */
+ int show_form_local = FALSE;
+ int local_verbose = 0;
+ struct esb_s local_e;
+ esb_constructor(&local_e);
+ get_attr_value(dbg, tag, die, attrib, srcfiles, cnt,
+ &local_e, show_form_local,local_verbose);
+ /* Check if this compiler version is a target */
+ update_compiler_target(esb_get_string(&local_e));
+ esb_destructor(&local_e);
+ }
+ break;
+
+
+ /* When dealing with linkonce symbols, the low_pc and high_pc
+ are associated with a specific symbol; SNC always generate a name in
+ the for of DW_AT_MIPS_linkage_name; GCC does not; instead it generates
+ DW_AT_abstract_origin or DW_AT_specification; in that case we have to
+ traverse this attribute in order to get the name for the linkonce */
+ case DW_AT_specification:
+ case DW_AT_abstract_origin:
+ case DW_AT_type:
+ esb_empty_string(&esb_base);
+ get_attr_value(dbg, tag, die, attrib, srcfiles, cnt, &esb_base,
+ show_form_used,verbose);
+ valname = esb_get_string(&esb_base);
+ if (check_forward_decl || check_self_references) {
+ Dwarf_Off die_off = 0;
+ Dwarf_Off ref_off = 0;
+ int res = 0;
+ int suppress_check = 0;
+
+ /* Get the global offset for reference */
+ res = dwarf_global_formref(attrib, &ref_off, &err);
+ if (res != DW_DLV_OK) {
+ int myerr = dwarf_errno(err);
+ if(myerr == DW_DLE_REF_SIG8_NOT_HANDLED) {
+ /* DW_DLE_REF_SIG8_NOT_HANDLED */
+ /* No offset available, it makes little sense
+ to delve into this sort of reference unless
+ we think a graph of self-refs *across*
+ type-units is possible. Hmm. FIXME? */
+ suppress_check = 1 ;
+ dwarf_dealloc(dbg,err,DW_DLA_ERROR);
+ err = 0;
+ } else {
+ print_error(dbg, "dwarf_die_CU_offsetD", res, err);
+ }
+ }
+ res = dwarf_dieoffset(die, &die_off, &err);
+ if (res != DW_DLV_OK) {
+ print_error(dbg, "ref formwith no ref?!", res, err);
+ }
+
+ if (!suppress_check && check_self_references) {
+ Dwarf_Die ref_die = 0;
+
+ ResetBucketGroup(pVisitedInfo);
+ AddEntryIntoBucketGroup(pVisitedInfo,die_off,0,0,0,NULL,FALSE);
+
+ /* Follow reference chain, looking for self references */
+ res = dwarf_offdie_b(dbg,ref_off,is_info,&ref_die,&err);
+ if (res == DW_DLV_OK) {
+ ++die_indent_level;
+ struct esb_s copy_base;
+ if (dump_visited_info) {
+ Dwarf_Off off;
+ dwarf_die_CU_offset(die, &off, &err);
+ printf("<%2d><0x%" DW_PR_XZEROS DW_PR_DUx
+ " GOFF=0x%" DW_PR_XZEROS DW_PR_DUx "> ",
+ die_indent_level, (Dwarf_Unsigned)off,
+ (Dwarf_Unsigned)die_off);
+ printf("%*s%s -> %s\n",die_indent_level * 2 + 2,
+ " ",atname,valname);
+ }
+ /* Because esb_base is global, lets not
+ let the traversal trash what we have here. */
+ esb_constructor(&copy_base);
+ esb_append(&copy_base,esb_get_string(&esb_base));
+ esb_empty_string(&esb_base);
+ traverse_one_die(dbg,attrib,ref_die,srcfiles,cnt,die_indent_level);
+ esb_empty_string(&esb_base);
+ esb_append(&esb_base,esb_get_string(&copy_base));
+ esb_destructor(&copy_base);
+ dwarf_dealloc(dbg,ref_die,DW_DLA_DIE);
+ ref_die = 0;
+ --die_indent_level;
+ }
+ DeleteKeyInBucketGroup(pVisitedInfo,die_off);
+ }
+
+ if (!suppress_check && check_forward_decl) {
+ if (attr == DW_AT_specification) {
+ /* Check the DW_AT_specification does not make forward
+ references to DIEs.
+ DWARF4 specifications, section 2.13.2,
+ but really they are legal,
+ this test is probably wrong. */
+ DWARF_CHECK_COUNT(forward_decl_result,1);
+ if (ref_off > die_off) {
+ DWARF_CHECK_ERROR2(forward_decl_result,
+ "Invalid forward reference to DIE: ",valname);
+ }
+ }
+ }
+ }
+ /* If we are in checking mode and we do not have a PU name */
+ if ((check_locations || check_ranges) && seen_PU && !PU_name[0]) {
+ if (tag == DW_TAG_subprogram) {
+ /* This gets the DW_AT_name if this DIE has one. */
+ Dwarf_Addr low_pc = 0;
+ static char proc_name[BUFSIZ];
+ proc_name[0] = 0;
+ get_proc_name(dbg,die,low_pc,proc_name,BUFSIZ,/*pcMap=*/0);
+ if (proc_name[0]) {
+ safe_strcpy(PU_name,sizeof(PU_name),proc_name,
+ strlen(proc_name));
+ }
+ }
+ }
+ break;
+ default:
+ esb_empty_string(&esb_base);
+ get_attr_value(dbg, tag,die, attrib, srcfiles, cnt, &esb_base,
+ show_form_used,verbose);
+ valname = esb_get_string(&esb_base);
+ break;
+ }
+ if (!print_information) {
+ if(have_a_search_match(valname,atname) )
+ {
+ if (search_wide_format) {
+ found_search_attr = TRUE;
+ } else {
+ PRINT_CU_INFO();
+ bTextFound = TRUE;
+ }
+ }
+ }
+ if ((PRINTING_DIES && print_information) || bTextFound) {
+ /* Print just the Tags and Attributes */
+ if (!display_offsets) {
+ printf("%-28s\n",atname);
+ } else {
+ if (dense) {
+ printf(" %s<%s>", atname, valname);
+ if(append_extra_string) {
+ char *v = esb_get_string(&esb_extra);
+ printf("%s", v);
+ }
+ } else {
+ printf("%-28s%s\n", atname, valname);
+ if( append_extra_string) {
+ char *v = esb_get_string(&esb_extra);
+ printf("%s", v);
+ }
+ }
+ }
+ /* Due to redirection of stderr */
+ fflush(stdout);
+ bTextFound = FALSE;
+ }
+ return found_search_attr;
+}
+
+
+int
+dwarfdump_print_one_locdesc(Dwarf_Debug dbg,
+ Dwarf_Locdesc * llbuf,
+ int skip_locdesc_header,
+ struct esb_s *string_out)
+{
+
+ Dwarf_Locdesc *locd = 0;
+ Dwarf_Half no_of_ops = 0;
+ int i = 0;
+ char small_buf[100];
+
+ if (!skip_locdesc_header && (verbose || llbuf->ld_from_loclist)) {
+ snprintf(small_buf, sizeof(small_buf),
+ "<lowpc=0x%" DW_PR_XZEROS DW_PR_DUx ">",
+ (Dwarf_Unsigned) llbuf->ld_lopc);
+ esb_append(string_out, small_buf);
+
+
+ snprintf(small_buf, sizeof(small_buf),
+ "<highpc=0x%" DW_PR_XZEROS DW_PR_DUx ">",
+ (Dwarf_Unsigned) llbuf->ld_hipc);
+ esb_append(string_out, small_buf);
+ if (display_offsets && verbose) {
+ snprintf(small_buf, sizeof(small_buf),
+ "<from %s offset 0x%" DW_PR_XZEROS DW_PR_DUx ">",
+ llbuf->ld_from_loclist ? ".debug_loc" : ".debug_info",
+ llbuf->ld_section_offset);
+ esb_append(string_out, small_buf);
+ }
+ }
+
+ locd = llbuf;
+ no_of_ops = llbuf->ld_cents;
+ for (i = 0; i < no_of_ops; i++) {
+ Dwarf_Loc * op = &locd->ld_s[i];
+
+ int res = _dwarf_print_one_expr_op(dbg,op,i,string_out);
+ if(res == DW_DLV_ERROR) {
+ return res;
+ }
+ }
+ return DW_DLV_OK;
+}
+
+
+
+static int
+op_has_no_operands(int op)
+{
+ unsigned i = 0;
+ if(op >= DW_OP_lit0 && op <= DW_OP_reg31) {
+ return TRUE;
+ }
+ for( ; ; ++i) {
+ struct operation_descr_s *odp = opdesc+i;
+ if(odp->op_code == 0) {
+ break;
+ }
+ if(odp->op_code != op) {
+ continue;
+ }
+ if (odp->op_count == 0) {
+ return TRUE;
+ }
+ return FALSE;
+ }
+ return FALSE;
+}
+
+int
+_dwarf_print_one_expr_op(Dwarf_Debug dbg,Dwarf_Loc* expr,int index,
+ struct esb_s *string_out)
+{
+ /* local_space_needed is intended to be 'more than big enough'
+ for a short group of loclist entries. */
+ char small_buf[100];
+ Dwarf_Small op;
+ Dwarf_Unsigned opd1;
+ Dwarf_Unsigned opd2;
+ const char * op_name;
+
+ if (index > 0) {
+ esb_append(string_out, " ");
+ }
+
+ op = expr->lr_atom;
+
+ /* We have valid operands whose values are bigger than the
+ DW_OP_nop = 0x96; for example: DW_OP_GNU_push_tls_address = 0xe0
+ Also, the function 'get_OP_name' handles this case, generating a
+ name 'Unknown OP value'. */
+ if (op > DW_OP_hi_user) {
+ print_error(dbg, "dwarf_op unexpected value!", DW_DLV_OK,
+ err);
+ return DW_DLV_ERROR;
+ }
+ op_name = get_OP_name(op,dwarf_names_print_on_error);
+ esb_append(string_out, op_name);
+
+ opd1 = expr->lr_number;
+ if(op_has_no_operands(op)) {
+ /* Nothing to add. */
+ } else if (op >= DW_OP_breg0 && op <= DW_OP_breg31) {
+ snprintf(small_buf, sizeof(small_buf),
+ "%+" DW_PR_DSd , (Dwarf_Signed) opd1);
+ esb_append(string_out, small_buf);
+ } else {
+ switch (op) {
+ case DW_OP_addr:
+ snprintf(small_buf, sizeof(small_buf),
+ " 0x%" DW_PR_XZEROS DW_PR_DUx , opd1);
+ esb_append(string_out, small_buf);
+ break;
+ case DW_OP_const1s:
+ case DW_OP_const2s:
+ case DW_OP_const4s:
+ case DW_OP_const8s:
+ case DW_OP_consts:
+ case DW_OP_skip:
+ case DW_OP_bra:
+ case DW_OP_fbreg:
+ snprintf(small_buf, sizeof(small_buf),
+ " %" DW_PR_DSd, (Dwarf_Signed) opd1);
+ esb_append(string_out, small_buf);
+ break;
+ case DW_OP_const1u:
+ case DW_OP_const2u:
+ case DW_OP_const4u:
+ case DW_OP_const8u:
+ case DW_OP_constu:
+ case DW_OP_pick:
+ case DW_OP_plus_uconst:
+ case DW_OP_regx:
+ case DW_OP_piece:
+ case DW_OP_deref_size:
+ case DW_OP_xderef_size:
+ snprintf(small_buf, sizeof(small_buf),
+ " %" DW_PR_DUu , opd1);
+ esb_append(string_out, small_buf);
+ break;
+ case DW_OP_bregx:
+ snprintf(small_buf, sizeof(small_buf),
+ "0x%08" DW_PR_DUx , opd1);
+ esb_append(string_out, small_buf);
+ opd2 = expr->lr_number2;
+ snprintf(small_buf, sizeof(small_buf),
+ "+%" DW_PR_DSd , (Dwarf_Signed) opd2);
+ esb_append(string_out, small_buf);
+ break;
+ case DW_OP_call2:
+ snprintf(small_buf, sizeof(small_buf),
+ " 0x%" DW_PR_XZEROS DW_PR_DUx , opd1);
+ esb_append(string_out, small_buf);
+ break;
+ case DW_OP_call4:
+ snprintf(small_buf, sizeof(small_buf),
+ " 0x%" DW_PR_XZEROS DW_PR_DUx , opd1);
+ esb_append(string_out, small_buf);
+ break;
+ case DW_OP_call_ref:
+ snprintf(small_buf, sizeof(small_buf),
+ " 0x%" DW_PR_XZEROS DW_PR_DUx , opd1);
+ esb_append(string_out, small_buf);
+ break;
+ case DW_OP_bit_piece:
+ snprintf(small_buf, sizeof(small_buf),
+ " 0x%" DW_PR_XZEROS DW_PR_DUx , opd1);
+ esb_append(string_out, small_buf);
+ opd2 = expr->lr_number2;
+ snprintf(small_buf, sizeof(small_buf),
+ " offset 0x%" DW_PR_DUx , (Dwarf_Signed) opd2);
+ esb_append(string_out, small_buf);
+ break;
+ case DW_OP_implicit_value:
+ {
+#define IMPLICIT_VALUE_PRINT_MAX 12
+ unsigned int print_len = 0;
+ snprintf(small_buf, sizeof(small_buf),
+ " 0x%" DW_PR_XZEROS DW_PR_DUx , opd1);
+ esb_append(string_out, small_buf);
+ /* The other operand is a block of opd1 bytes. */
+ /* FIXME */
+ print_len = opd1;
+ if(print_len > IMPLICIT_VALUE_PRINT_MAX) {
+ print_len = IMPLICIT_VALUE_PRINT_MAX;
+ }
+#undef IMPLICIT_VALUE_PRINT_MAX
+ if(print_len > 0) {
+ const unsigned char *bp = 0;
+ unsigned int i = 0;
+ opd2 = expr->lr_number2;
+ /* This is a really ugly cast, a way
+ to implement DW_OP_implicit value in
+ this libdwarf context. */
+ bp = (const unsigned char *) opd2;
+ esb_append(string_out," contents 0x");
+ for( ; i < print_len; ++i,++bp) {
+ /* Do not use DW_PR_DUx here,
+ the value *bp is a const unsigned char. */
+ snprintf(small_buf, sizeof(small_buf),
+ "%02x", *bp);
+ esb_append(string_out,small_buf);
+ }
+ }
+ }
+ break;
+
+ /* We do not know what the operands, if any, are. */
+ case DW_OP_HP_unknown:
+ case DW_OP_HP_is_value:
+ case DW_OP_HP_fltconst4:
+ case DW_OP_HP_fltconst8:
+ case DW_OP_HP_mod_range:
+ case DW_OP_HP_unmod_range:
+ case DW_OP_HP_tls:
+ case DW_OP_INTEL_bit_piece:
+ break;
+ case DW_OP_stack_value: /* DWARF4 */
+ break;
+ case DW_OP_GNU_uninit: /* DW_OP_APPLE_uninit */
+ /* No operands. */
+ break;
+ case DW_OP_GNU_encoded_addr:
+ snprintf(small_buf, sizeof(small_buf),
+ " 0x%" DW_PR_XZEROS DW_PR_DUx , opd1);
+ esb_append(string_out, small_buf);
+ break;
+ case DW_OP_GNU_implicit_pointer:
+ snprintf(small_buf, sizeof(small_buf),
+ " 0x%" DW_PR_XZEROS DW_PR_DUx , opd1);
+ esb_append(string_out, small_buf);
+ break;
+ case DW_OP_GNU_entry_value:
+ snprintf(small_buf, sizeof(small_buf),
+ " 0x%" DW_PR_XZEROS DW_PR_DUx , opd1);
+ esb_append(string_out, small_buf);
+ break;
+ default:
+ {
+ snprintf(small_buf, sizeof(small_buf),
+ " dwarf_op unknown 0x%x", (unsigned)op);
+ esb_append(string_out,small_buf);
+ }
+ break;
+ }
+ }
+ return DW_DLV_OK;
+}
+
+/* Fill buffer with location lists
+ Buffer esbp expands as needed.
+*/
+/*ARGSUSED*/ static void
+get_location_list(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Attribute attr,
+ struct esb_s *esbp)
+{
+ Dwarf_Locdesc *llbuf = 0;
+ Dwarf_Locdesc **llbufarray = 0;
+ Dwarf_Signed no_of_elements;
+ Dwarf_Error err;
+ int i;
+ int lres = 0;
+ int llent = 0;
+ int skip_locdesc_header = 0;
+
+ /* Base address used to update entries in .debug_loc */
+ Dwarf_Addr base_address = CU_base_address;
+ Dwarf_Addr lopc = 0;
+ Dwarf_Addr hipc = 0;
+ Dwarf_Bool bError = FALSE;
+
+ if (use_old_dwarf_loclist) {
+ lres = dwarf_loclist(attr, &llbuf, &no_of_elements, &err);
+ if (lres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_loclist", lres, err);
+ } else if (lres == DW_DLV_NO_ENTRY) {
+ return;
+ }
+ dwarfdump_print_one_locdesc(dbg, llbuf,skip_locdesc_header,esbp);
+ dwarf_dealloc(dbg, llbuf->ld_s, DW_DLA_LOC_BLOCK);
+ dwarf_dealloc(dbg, llbuf, DW_DLA_LOCDESC);
+ return;
+ }
+
+ lres = dwarf_loclist_n(attr, &llbufarray, &no_of_elements, &err);
+ if (lres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_loclist", lres, err);
+ } else if (lres == DW_DLV_NO_ENTRY) {
+ return;
+ }
+ for (llent = 0; llent < no_of_elements; ++llent) {
+ char small_buf[100];
+ Dwarf_Off offset = 0;
+
+ llbuf = llbufarray[llent];
+ /* If we have a location list refering to the .debug_loc
+ Check for specific compiler we are validating. */
+ if (check_locations && in_valid_code &&
+ llbuf->ld_from_loclist && checking_this_compiler()) {
+ /* To calculate the offset, we use:
+ sizeof(Dwarf_Half) -> number of expression list
+ 2 * address_size -> low_pc and high_pc */
+ offset = llbuf->ld_section_offset -
+ llbuf->ld_cents * sizeof(Dwarf_Half) -
+ 2 * elf_address_size;
+
+ if (llbuf->ld_lopc == elf_max_address) {
+ /* (0xffffffff,addr), use specific address
+ (current PU address) */
+ base_address = llbuf->ld_hipc;
+ } else {
+ /* (offset,offset), update using CU address */
+ lopc = llbuf->ld_lopc + base_address;
+ hipc = llbuf->ld_hipc + base_address;
+
+ DWARF_CHECK_COUNT(locations_result,1);
+
+ /* Check the low_pc and high_pc are within
+ a valid range in the .text section */
+ if (IsValidInBucketGroup(pRangesInfo,lopc) &&
+ IsValidInBucketGroup(pRangesInfo,hipc)) {
+ /* Valid values; do nothing */
+ } else {
+ /* At this point may be we are dealing with
+ a linkonce symbol */
+ if (IsValidInLinkonce(pLinkonceInfo,PU_name,
+ lopc,hipc)) {
+ /* Valid values; do nothing */
+ } else {
+ bError = TRUE;
+ DWARF_CHECK_ERROR(locations_result,
+ ".debug_loc: Address outside a "
+ "valid .text range");
+ if (check_verbose_mode) {
+ printf(
+ "Offset = 0x%" DW_PR_XZEROS DW_PR_DUx
+ ", Base = 0x%" DW_PR_XZEROS DW_PR_DUx ", "
+ "Low = 0x%" DW_PR_XZEROS DW_PR_DUx
+ " (0x%" DW_PR_XZEROS DW_PR_DUx
+ "), High = 0x%" DW_PR_XZEROS DW_PR_DUx
+ " (0x%" DW_PR_XZEROS DW_PR_DUx ")\n",
+ offset,base_address,lopc,
+ llbuf->ld_lopc,
+ hipc,
+ llbuf->ld_hipc);
+ }
+ }
+ }
+ }
+ }
+
+ if (!dense && llbuf->ld_from_loclist) {
+ if (llent == 0) {
+ snprintf(small_buf, sizeof(small_buf),
+ "<loclist with %ld entries follows>",
+ (long) no_of_elements);
+ esb_append(esbp, small_buf);
+ }
+ esb_append(esbp, "\n\t\t\t");
+ snprintf(small_buf, sizeof(small_buf), "[%2d]", llent);
+ esb_append(esbp, small_buf);
+ }
+ lres = dwarfdump_print_one_locdesc(dbg,
+ llbuf,
+ skip_locdesc_header,
+ esbp);
+ if (lres == DW_DLV_ERROR) {
+ return;
+ } else {
+ /* DW_DLV_OK so we add follow-on at end, else is
+ DW_DLV_NO_ENTRY (which is impossible, treat like
+ DW_DLV_OK). */
+ }
+ }
+
+ if (bError && check_verbose_mode) {
+ printf("\n");
+ }
+
+ for (i = 0; i < no_of_elements; ++i) {
+ dwarf_dealloc(dbg, llbufarray[i]->ld_s, DW_DLA_LOC_BLOCK);
+ dwarf_dealloc(dbg, llbufarray[i], DW_DLA_LOCDESC);
+ }
+ dwarf_dealloc(dbg, llbufarray, DW_DLA_LIST);
+}
+
+static void
+formx_unsigned(Dwarf_Unsigned u, struct esb_s *esbp, Dwarf_Bool hex_format)
+{
+ char small_buf[40];
+ if (hex_format) {
+ snprintf(small_buf, sizeof(small_buf),"0x%" DW_PR_XZEROS DW_PR_DUx , u);
+ } else {
+ snprintf(small_buf, sizeof(small_buf),
+ "%" DW_PR_DUu , u);
+ }
+ esb_append(esbp, small_buf);
+}
+static void
+formx_signed(Dwarf_Signed u, struct esb_s *esbp)
+{
+ char small_buf[40];
+ snprintf(small_buf, sizeof(small_buf),
+ "%" DW_PR_DSd , u);
+ esb_append(esbp, small_buf);
+}
+/* We think this is an integer. Figure out how to print it.
+ In case the signedness is ambiguous (such as on
+ DW_FORM_data1 (ie, unknown signedness) print two ways.
+*/
+static int
+formxdata_print_value(Dwarf_Debug dbg,Dwarf_Attribute attrib,
+ struct esb_s *esbp,
+ Dwarf_Error * err, Dwarf_Bool hex_format)
+{
+ Dwarf_Signed tempsd = 0;
+ Dwarf_Unsigned tempud = 0;
+ int sres = 0;
+ int ures = 0;
+ Dwarf_Error serr = 0;
+
+ ures = dwarf_formudata(attrib, &tempud, err);
+ sres = dwarf_formsdata(attrib, &tempsd, &serr);
+ if(ures == DW_DLV_OK) {
+ if(sres == DW_DLV_OK) {
+ if(tempud == tempsd && tempsd >= 0) {
+ /* Data is the same value and not negative,
+ so makes no difference which
+ we print. */
+ formx_unsigned(tempud,esbp,hex_format);
+ } else {
+ formx_unsigned(tempud,esbp,hex_format);
+ esb_append(esbp,"(as signed = ");
+ formx_signed(tempsd,esbp);
+ esb_append(esbp,")");
+ }
+ } else if (sres == DW_DLV_NO_ENTRY) {
+ formx_unsigned(tempud,esbp,hex_format);
+ } else /* DW_DLV_ERROR */{
+ formx_unsigned(tempud,esbp,hex_format);
+ }
+ goto cleanup;
+ } else {
+ /* ures == DW_DLV_ERROR or DW_DLV_NO_ENTRY*/
+ if(sres == DW_DLV_OK) {
+ formx_signed(tempsd,esbp);
+ } else {
+ /* Neither worked. */
+ }
+ }
+ /* Clean up any unused Dwarf_Error data.
+ DW_DLV_NO_ENTRY cannot really happen,
+ so a complete cleanup for that is
+ not necessary. */
+ cleanup:
+ if(sres == DW_DLV_OK || ures == DW_DLV_OK) {
+ if(sres == DW_DLV_ERROR) {
+ dwarf_dealloc(dbg,serr,DW_DLA_ERROR);
+ }
+ if(ures == DW_DLV_ERROR) {
+ dwarf_dealloc(dbg,*err,DW_DLA_ERROR);
+ *err = 0;
+ }
+ return DW_DLV_OK;
+ }
+ if(sres == DW_DLV_ERROR || ures == DW_DLV_ERROR) {
+ if(sres == DW_DLV_ERROR && ures == DW_DLV_ERROR) {
+ dwarf_dealloc(dbg,serr,DW_DLA_ERROR);
+ return DW_DLV_ERROR;
+ }
+ if(sres == DW_DLV_ERROR) {
+ *err = serr;
+ }
+ return DW_DLV_ERROR;
+ }
+ /* Both are DW_DLV_NO_ENTRY which is crazy, impossible. */
+ return DW_DLV_NO_ENTRY;
+}
+
+static char *
+get_form_number_as_string(int form, char *buf, unsigned bufsize)
+{
+ snprintf(buf,bufsize," %d",form);
+ return buf;
+}
+
+static void
+print_exprloc_content(Dwarf_Debug dbg,Dwarf_Die die, Dwarf_Attribute attrib,
+ int showhextoo, struct esb_s *esbp)
+{
+ Dwarf_Ptr x = 0;
+ Dwarf_Unsigned tempud = 0;
+ char small_buf[80];
+ Dwarf_Error err = 0;
+ int wres = 0;
+ wres = dwarf_formexprloc(attrib,&tempud,&x,&err);
+ if(wres == DW_DLV_NO_ENTRY) {
+ /* Show nothing? Impossible. */
+ } else if(wres == DW_DLV_ERROR) {
+ print_error(dbg, "Cannot get a DW_FORM_exprbloc....", wres, err);
+ } else {
+ Dwarf_Half address_size = 0;
+ int ares = 0;
+ unsigned u = 0;
+ snprintf(small_buf, sizeof(small_buf),
+ "len 0x%04" DW_PR_DUx ": ",tempud);
+ esb_append(esbp, small_buf);
+ if(showhextoo) {
+ for (u = 0; u < tempud; u++) {
+ snprintf(small_buf, sizeof(small_buf), "%02x",
+ *(u + (unsigned char *) x));
+ esb_append(esbp, small_buf);
+ }
+ esb_append(esbp,": ");
+ }
+ address_size = 0;
+ ares = dwarf_get_die_address_size(die,&address_size,&err);
+ if(wres == DW_DLV_NO_ENTRY) {
+ print_error(dbg,"Cannot get die address size for exprloc",
+ ares,err);
+ } else if(wres == DW_DLV_ERROR) {
+ print_error(dbg,"Cannot Get die address size for exprloc",
+ ares,err);
+ } else {
+ get_string_from_locs(dbg,x,tempud,address_size, esbp);
+ }
+ }
+}
+
+
+
+
+/* Fill buffer with attribute value.
+ We pass in tag so we can try to do the right thing with
+ broken compiler DW_TAG_enumerator
+
+ We append to esbp's buffer.
+*/
+void
+get_attr_value(Dwarf_Debug dbg, Dwarf_Half tag,
+ Dwarf_Die die, Dwarf_Attribute attrib,
+ char **srcfiles, Dwarf_Signed cnt, struct esb_s *esbp,
+ int show_form,
+ int local_verbose)
+{
+ Dwarf_Half theform = 0;
+ char * temps = 0;
+ Dwarf_Block *tempb = 0;
+ Dwarf_Signed tempsd = 0;
+ Dwarf_Unsigned tempud = 0;
+ int i = 0;
+ Dwarf_Half attr = 0;
+ Dwarf_Off off = 0;
+ Dwarf_Off goff = 0; /* Global offset */
+ Dwarf_Die die_for_check = 0;
+ Dwarf_Half tag_for_check = 0;
+ Dwarf_Bool tempbool = 0;
+ Dwarf_Addr addr = 0;
+ int fres = 0;
+ int bres = 0;
+ int wres = 0;
+ int dres = 0;
+ Dwarf_Half direct_form = 0;
+ char small_buf[COMPILE_UNIT_NAME_LEN]; /* Size to hold a filename */
+ Dwarf_Bool is_info = TRUE;
+
+
+ is_info = dwarf_get_die_infotypes_flag(die);
+ /* Dwarf_whatform gets the real form, DW_FORM_indir is
+ never returned: instead the real form following
+ DW_FORM_indir is returned. */
+ fres = dwarf_whatform(attrib, &theform, &err);
+ /* Depending on the form and the attribute, process the form. */
+ if (fres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_whatform cannot Find Attr Form", fres,
+ err);
+ } else if (fres == DW_DLV_NO_ENTRY) {
+ return;
+ }
+
+ /* dwarf_whatform_direct gets the 'direct' form, so if
+ the form is DW_FORM_indir that is what is returned. */
+ dwarf_whatform_direct(attrib, &direct_form, &err);
+ /* Ignore errors in dwarf_whatform_direct() */
+
+
+ switch (theform) {
+ case DW_FORM_addr:
+ bres = dwarf_formaddr(attrib, &addr, &err);
+ if (bres == DW_DLV_OK) {
+ snprintf(small_buf, sizeof(small_buf),
+ "0x%" DW_PR_XZEROS DW_PR_DUx ,
+ (Dwarf_Unsigned) addr);
+ esb_append(esbp, small_buf);
+ } else {
+ print_error(dbg, "addr formwith no addr?!", bres, err);
+ }
+ break;
+ case DW_FORM_ref_addr:
+ /* DW_FORM_ref_addr is not accessed thru formref: ** it is an
+ address (global section offset) in ** the .debug_info
+ section. */
+ bres = dwarf_global_formref(attrib, &off, &err);
+ if (bres == DW_DLV_OK) {
+ snprintf(small_buf, sizeof(small_buf),
+ "<global die offset 0x%" DW_PR_XZEROS DW_PR_DUx
+ ">",
+ (Dwarf_Unsigned) off);
+ esb_append(esbp, small_buf);
+ } else {
+ print_error(dbg,
+ "DW_FORM_ref_addr form with no reference?!",
+ bres, err);
+ }
+ wres = dwarf_whatattr(attrib, &attr, &err);
+ if (wres == DW_DLV_ERROR) {
+ } else if (wres == DW_DLV_NO_ENTRY) {
+ } else {
+ if (attr == DW_AT_sibling) {
+ /* The value had better be inside the current CU
+ else there is a nasty error here, as a sibling
+ has to be in the same CU, it seems. */
+ Dwarf_Off cuoff = 0;
+ Dwarf_Off culen = 0;
+ int res = dwarf_die_CU_offset_range(die,&cuoff,
+ &culen,&err);
+ DWARF_CHECK_COUNT(tag_tree_result,1);
+ if(res != DW_DLV_OK) {
+ } else {
+ Dwarf_Off cuend = cuoff+culen;
+ if(off < cuoff || off >= cuend) {
+ DWARF_CHECK_ERROR(tag_tree_result,
+ "DW_AT_sibling DW_FORM_ref_addr offset points "
+ "outside of current CU");
+ }
+ }
+ }
+ }
+
+ break;
+ case DW_FORM_ref1:
+ case DW_FORM_ref2:
+ case DW_FORM_ref4:
+ case DW_FORM_ref8:
+ case DW_FORM_ref_udata:
+ bres = dwarf_formref(attrib, &off, &err);
+ if (bres != DW_DLV_OK) {
+ /* Report incorrect offset */
+ snprintf(small_buf,sizeof(small_buf),
+ "%s, offset=<0x%" DW_PR_XZEROS DW_PR_DUx
+ ">","reference form with no valid local ref?!",off);
+ print_error(dbg, small_buf, bres, err);
+ }
+
+ /* Convert the local offset into a relative section offset */
+ if (show_global_offsets) {
+ bres = dwarf_convert_to_global_offset(attrib,
+ off, &goff, &err);
+ if (bres != DW_DLV_OK) {
+ /* Report incorrect offset */
+ snprintf(small_buf,sizeof(small_buf),
+ "%s, global die offset=<0x%" DW_PR_XZEROS DW_PR_DUx
+ ">","invalid offset",goff);
+ print_error(dbg, small_buf, bres, err);
+ }
+ }
+
+ /* Do references inside <> to distinguish them ** from
+ constants. In dense form this results in <<>>. Ugly for
+ dense form, but better than ambiguous. davea 9/94 */
+ if (show_global_offsets) {
+ snprintf(small_buf, sizeof(small_buf),
+ "<0x%" DW_PR_XZEROS DW_PR_DUx " GOFF=0x%" DW_PR_XZEROS DW_PR_DUx ">",
+ (Dwarf_Unsigned)off, goff);
+ } else {
+ snprintf(small_buf, sizeof(small_buf),
+ "<0x%" DW_PR_XZEROS DW_PR_DUx ">", off);
+ }
+
+ esb_append(esbp, small_buf);
+ if (check_type_offset) {
+ attr = 0;
+ wres = dwarf_whatattr(attrib, &attr, &err);
+ if (wres == DW_DLV_ERROR) {
+
+ } else if (wres == DW_DLV_NO_ENTRY) {
+ }
+ if (attr == DW_AT_type) {
+ dres = dwarf_offdie_b(dbg, cu_offset + off,
+ is_info,
+ &die_for_check, &err);
+ DWARF_CHECK_COUNT(type_offset_result,1);
+ if (dres != DW_DLV_OK) {
+ snprintf(small_buf,sizeof(small_buf),
+ "DW_AT_type offset does not point to a DIE for global offset 0x%" DW_PR_DUx " cu off 0x%" DW_PR_DUx " local offset 0x%" DW_PR_DUx,
+ cu_offset + off,cu_offset,off);
+ DWARF_CHECK_ERROR(type_offset_result,small_buf);
+ } else {
+ int tres2 =
+ dwarf_tag(die_for_check, &tag_for_check, &err);
+ if (tres2 == DW_DLV_OK) {
+ switch (tag_for_check) {
+ case DW_TAG_array_type:
+ case DW_TAG_class_type:
+ case DW_TAG_enumeration_type:
+ case DW_TAG_pointer_type:
+ case DW_TAG_reference_type:
+ case DW_TAG_string_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_subroutine_type:
+ case DW_TAG_typedef:
+ case DW_TAG_union_type:
+ case DW_TAG_ptr_to_member_type:
+ case DW_TAG_set_type:
+ case DW_TAG_subrange_type:
+ case DW_TAG_base_type:
+ case DW_TAG_const_type:
+ case DW_TAG_file_type:
+ case DW_TAG_packed_type:
+ case DW_TAG_thrown_type:
+ case DW_TAG_volatile_type:
+ case DW_TAG_template_type_parameter:
+ case DW_TAG_template_value_parameter:
+ case DW_TAG_unspecified_type:
+ /* OK */
+ break;
+ default:
+ {
+ snprintf(small_buf,sizeof(small_buf),
+ "DW_AT_type offset does not point to Type info we got tag 0x%x %s",
+ tag_for_check,
+ get_TAG_name(tag_for_check,
+ dwarf_names_print_on_error));
+ DWARF_CHECK_ERROR(type_offset_result,small_buf);
+ }
+ break;
+ }
+ dwarf_dealloc(dbg, die_for_check, DW_DLA_DIE);
+ die_for_check = 0;
+ } else {
+ DWARF_CHECK_ERROR(type_offset_result,
+ "DW_AT_type offset does not exist");
+ }
+ }
+ }
+ }
+ break;
+ case DW_FORM_block:
+ case DW_FORM_block1:
+ case DW_FORM_block2:
+ case DW_FORM_block4:
+ fres = dwarf_formblock(attrib, &tempb, &err);
+ if (fres == DW_DLV_OK) {
+ for (i = 0; i < tempb->bl_len; i++) {
+ snprintf(small_buf, sizeof(small_buf), "%02x",
+ *(i + (unsigned char *) tempb->bl_data));
+ esb_append(esbp, small_buf);
+ }
+ dwarf_dealloc(dbg, tempb, DW_DLA_BLOCK);
+ tempb = 0;
+ } else {
+ print_error(dbg, "DW_FORM_blockn cannot get block\n", fres,
+ err);
+ }
+ break;
+ case DW_FORM_data1:
+ case DW_FORM_data2:
+ case DW_FORM_data4:
+ case DW_FORM_data8:
+ fres = dwarf_whatattr(attrib, &attr, &err);
+ if (fres == DW_DLV_ERROR) {
+ print_error(dbg, "FORM_datan cannot get attr", fres, err);
+ } else if (fres == DW_DLV_NO_ENTRY) {
+ print_error(dbg, "FORM_datan cannot get attr", fres, err);
+ } else {
+ switch (attr) {
+ case DW_AT_ordering:
+ case DW_AT_byte_size:
+ case DW_AT_bit_offset:
+ case DW_AT_bit_size:
+ case DW_AT_inline:
+ case DW_AT_language:
+ case DW_AT_visibility:
+ case DW_AT_virtuality:
+ case DW_AT_accessibility:
+ case DW_AT_address_class:
+ case DW_AT_calling_convention:
+ case DW_AT_discr_list: /* DWARF3 */
+ case DW_AT_encoding:
+ case DW_AT_identifier_case:
+ case DW_AT_MIPS_loop_unroll_factor:
+ case DW_AT_MIPS_software_pipeline_depth:
+ case DW_AT_decl_column:
+ case DW_AT_decl_file:
+ case DW_AT_decl_line:
+ case DW_AT_call_column:
+ case DW_AT_call_file:
+ case DW_AT_call_line:
+ case DW_AT_start_scope:
+ case DW_AT_byte_stride:
+ case DW_AT_bit_stride:
+ case DW_AT_count:
+ case DW_AT_stmt_list:
+ case DW_AT_MIPS_fde:
+ { int show_form_here = 0;
+ wres = get_small_encoding_integer_and_name(dbg,
+ attrib,
+ &tempud,
+ /* attrname */ (char *) NULL,
+ /* err_string */ (const char **) NULL,
+ (encoding_type_func) 0,
+ &err,show_form_here);
+
+ if (wres == DW_DLV_OK) {
+ snprintf(small_buf, sizeof(small_buf),
+ "0x%08" DW_PR_DUx ,
+ tempud);
+ esb_append(esbp, small_buf);
+ if (attr == DW_AT_decl_file || attr == DW_AT_call_file) {
+ if (srcfiles && tempud > 0 && tempud <= cnt) {
+ /* added by user request */
+ /* srcfiles is indexed starting at 0, but
+ DW_AT_decl_file defines that 0 means no
+ file, so tempud 1 means the 0th entry in
+ srcfiles, thus tempud-1 is the correct
+ index into srcfiles. */
+ char *fname = srcfiles[tempud - 1];
+
+ esb_append(esbp, " ");
+ esb_append(esbp, fname);
+ }
+
+ /* Validate integrity of files
+ referenced in .debug_line */
+ if(check_decl_file) {
+ DWARF_CHECK_COUNT(decl_file_result,1);
+ /* Zero is always a legal index, it means
+ no source name provided. */
+ if(tempud != 0 && tempud > cnt) {
+ if(!srcfiles) {
+ snprintf(small_buf,sizeof(small_buf),
+ "There is a file number=%" DW_PR_DUu
+ " but no source files "
+ " are known.",tempud);
+ } else {
+ snprintf(small_buf, sizeof(small_buf),
+ "Does not point to valid file info "
+ " filenum=%" DW_PR_DUu
+ " filecount=%" DW_PR_DUu ".",
+ tempud,cnt);
+ }
+ DWARF_CHECK_ERROR2(decl_file_result,
+ get_AT_name(attr,
+ dwarf_names_print_on_error),
+ small_buf);
+ }
+ }
+ }
+ } else {
+ print_error(dbg, "Cannot get encoding attribute ..",
+ wres, err);
+ }
+ }
+ break;
+ case DW_AT_const_value:
+ /* Do not use hexadecimal format */
+ wres = formxdata_print_value(dbg,attrib,esbp, &err, FALSE);
+ if(wres == DW_DLV_OK){
+ /* String appended already. */
+ } else if (wres == DW_DLV_NO_ENTRY) {
+ /* nothing? */
+ } else {
+ print_error(dbg,"Cannot get DW_AT_const_value ",wres,err);
+ }
+
+
+ break;
+ case DW_AT_upper_bound:
+ case DW_AT_lower_bound:
+ default:
+ /* Do not use hexadecimal format except for
+ DW_AT_ranges. */
+ wres = formxdata_print_value(dbg,attrib,esbp, &err,
+ (DW_AT_ranges == attr));
+ if (wres == DW_DLV_OK) {
+ /* String appended already. */
+ } else if (wres == DW_DLV_NO_ENTRY) {
+ /* nothing? */
+ } else {
+ print_error(dbg, "Cannot get form data..", wres,
+ err);
+ }
+ break;
+ }
+ }
+ if (cu_name_flag) {
+ if (attr == DW_AT_MIPS_fde) {
+ if (fde_offset_for_cu_low == DW_DLV_BADOFFSET) {
+ fde_offset_for_cu_low
+ = fde_offset_for_cu_high = tempud;
+ } else if (tempud < fde_offset_for_cu_low) {
+ fde_offset_for_cu_low = tempud;
+ } else if (tempud > fde_offset_for_cu_high) {
+ fde_offset_for_cu_high = tempud;
+ }
+ }
+ }
+ break;
+ case DW_FORM_sdata:
+ wres = dwarf_formsdata(attrib, &tempsd, &err);
+ if (wres == DW_DLV_OK) {
+ snprintf(small_buf, sizeof(small_buf),
+ "0x%" DW_PR_XZEROS DW_PR_DUx , tempsd);
+ esb_append(esbp, small_buf);
+ } else if (wres == DW_DLV_NO_ENTRY) {
+ /* nothing? */
+ } else {
+ print_error(dbg, "Cannot get formsdata..", wres, err);
+ }
+ break;
+ case DW_FORM_udata:
+ wres = dwarf_formudata(attrib, &tempud, &err);
+ if (wres == DW_DLV_OK) {
+ snprintf(small_buf, sizeof(small_buf), "0x%" DW_PR_XZEROS DW_PR_DUx ,
+ tempud);
+ esb_append(esbp, small_buf);
+ } else if (wres == DW_DLV_NO_ENTRY) {
+ /* nothing? */
+ } else {
+ print_error(dbg, "Cannot get formudata....", wres, err);
+ }
+ break;
+ case DW_FORM_string:
+ case DW_FORM_strp:
+ wres = dwarf_formstring(attrib, &temps, &err);
+ if (wres == DW_DLV_OK) {
+ /* Print as quoted string for clarity. */
+ esb_append(esbp, "\"");
+ esb_append(esbp, temps);
+ esb_append(esbp, "\"");
+ } else if (wres == DW_DLV_NO_ENTRY) {
+ /* nothing? */
+ } else {
+ print_error(dbg, "Cannot get a formstr (or a formstrp)....",
+ wres, err);
+ }
+
+ break;
+ case DW_FORM_flag:
+ wres = dwarf_formflag(attrib, &tempbool, &err);
+ if (wres == DW_DLV_OK) {
+ if (tempbool) {
+ snprintf(small_buf, sizeof(small_buf), "yes(%d)",
+ tempbool);
+ esb_append(esbp, small_buf);
+ } else {
+ snprintf(small_buf, sizeof(small_buf), "no");
+ esb_append(esbp, small_buf);
+ }
+ } else if (wres == DW_DLV_NO_ENTRY) {
+ /* nothing? */
+ } else {
+ print_error(dbg, "Cannot get formflag/p....", wres, err);
+ }
+ break;
+ case DW_FORM_indirect:
+ /* We should not ever get here, since the true form was
+ determined and direct_form has the DW_FORM_indirect if it is
+ used here in this attr. */
+ esb_append(esbp, get_FORM_name(theform,
+ dwarf_names_print_on_error));
+ break;
+ case DW_FORM_exprloc: { /* DWARF4 */
+ int showhextoo = 1;
+ print_exprloc_content(dbg,die,attrib,showhextoo,esbp);
+ }
+ break;
+ case DW_FORM_sec_offset: { /* DWARF4 */
+ string emptyattrname = 0;
+ int show_form_here = 0;
+ wres = get_small_encoding_integer_and_name(dbg,
+ attrib,
+ &tempud,
+ emptyattrname,
+ /* err_string */ NULL,
+ (encoding_type_func) 0,
+ &err,show_form_here);
+ if(wres == DW_DLV_NO_ENTRY) {
+ /* Show nothing? */
+ } else if(wres == DW_DLV_ERROR) {
+ print_error(dbg,
+ "Cannot get a DW_FORM_sec_offset....",
+ wres, err);
+ } else {
+ snprintf(small_buf, sizeof(small_buf),
+ "0x%" DW_PR_XZEROS DW_PR_DUx,
+ tempud);
+ esb_append(esbp,small_buf);
+ }
+ }
+
+ break;
+ case DW_FORM_flag_present: /* DWARF4 */
+ esb_append(esbp,"yes(1)");
+ break;
+ case DW_FORM_ref_sig8: { /* DWARF4 */
+ Dwarf_Sig8 sig8data;
+ wres = dwarf_formsig8(attrib,&sig8data,&err);
+ if(wres != DW_DLV_OK) {
+ /* Show nothing? */
+ print_error(dbg,
+ "Cannot get a DW_FORM_ref_sig8 ....",
+ wres, err);
+ } else {
+ struct esb_s sig8str;
+ esb_constructor(&sig8str);
+ format_sig8_string(&sig8data,&sig8str);
+ esb_append(esbp,esb_get_string(&sig8str));
+ esb_destructor(&sig8str);
+ }
+ }
+ break;
+
+ default:
+ print_error(dbg, "dwarf_whatform unexpected value", DW_DLV_OK,
+ err);
+ }
+ show_form_itself(show_form,local_verbose,theform, direct_form,esbp);
+}
+
+void
+format_sig8_string(Dwarf_Sig8*data, struct esb_s *out)
+{
+ unsigned i = 0;
+ char small_buf[40];
+ esb_append(out,"0x");
+ for( ; i < sizeof(data->signature); ++i) {
+ if (i == 4) {
+ esb_append(out," 0x");
+ }
+ snprintf(small_buf,sizeof(small_buf), "%02x",
+ (unsigned char)(data->signature[i]));
+ esb_append(out,small_buf);
+ }
+}
+
+
+/* A cleanup so that when using a memory checker
+ we don't show irrelevant leftovers.
+*/
+void
+clean_up_die_esb()
+{
+ esb_destructor(&esb_base);
+}
+
+static int
+get_form_values(Dwarf_Attribute attrib,
+ Dwarf_Half * theform, Dwarf_Half * directform)
+{
+ Dwarf_Error err = 0;
+ int res = dwarf_whatform(attrib, theform, &err);
+ dwarf_whatform_direct(attrib, directform, &err);
+ return res;
+}
+static void
+show_form_itself(int local_show_form,
+ int local_verbose,
+ int theform,
+ int directform, struct esb_s *esbp)
+{
+ char small_buf[100];
+ if (local_show_form
+ && directform && directform == DW_FORM_indirect) {
+ char *form_indir = " (used DW_FORM_indirect";
+ char *form_indir2 = ") ";
+ esb_append(esbp, form_indir);
+ if(local_verbose) {
+ esb_append(esbp, get_form_number_as_string(DW_FORM_indirect,
+ small_buf,sizeof(small_buf)));
+ }
+ esb_append(esbp, form_indir2);
+ }
+ if(local_show_form) {
+ esb_append(esbp," <form ");
+ esb_append(esbp,get_FORM_name(theform,
+ dwarf_names_print_on_error));
+ if(local_verbose) {
+ esb_append(esbp, get_form_number_as_string(theform,
+ small_buf, sizeof(small_buf)));
+ }
+ esb_append(esbp,">");
+ }
+}
+
+
+#include "tmp-ta-table.c"
+#include "tmp-ta-ext-table.c"
+
+static int
+legal_tag_attr_combination(Dwarf_Half tag, Dwarf_Half attr)
+{
+ if(tag <= 0) {
+ return FALSE;
+ }
+ if(tag < ATTR_TREE_ROW_COUNT) {
+ int index = attr / BITS_PER_WORD;
+ if ( index < ATTR_TREE_COLUMN_COUNT) {
+ unsigned bitflag = 1 << (attr % BITS_PER_WORD);
+ int known = ((tag_attr_combination_table[tag][index]
+ & bitflag) > 0 ? TRUE : FALSE);
+ if(known) {
+ return TRUE;
+ }
+ }
+ }
+ /* DW_AT_MIPS_fde used to return TRUE as that was
+ convenient for SGI/MIPS users. */
+ if(!suppress_check_extensions_tables) {
+ int r = 0;
+ for ( ; r < ATTR_TREE_EXT_ROW_COUNT; ++r ) {
+ int c = 1;
+ if(tag != tag_attr_combination_ext_table[r][0]) {
+ continue;
+ }
+ for( ; c < ATTR_TREE_EXT_COLUMN_COUNT ; ++c) {
+ if (tag_attr_combination_ext_table[r][c] == attr) {
+ return TRUE;
+ }
+ }
+ }
+ }
+ return (FALSE);
+}
+
+#include "tmp-tt-table.c"
+#include "tmp-tt-ext-table.c"
+
+/* Look only at valid table entries
+ The check here must match the building-logic in
+ tag_tree.c
+ And must match the tags defined in dwarf.h
+ The tag_tree_combination_table is a table of bit flags. */
+static int
+legal_tag_tree_combination(Dwarf_Half tag_parent, Dwarf_Half tag_child)
+{
+ if(tag_parent <= 0) {
+ return FALSE;
+ }
+ if ( tag_parent < TAG_TREE_ROW_COUNT) {
+ int index = tag_child / BITS_PER_WORD;
+ if ( index < TAG_TREE_COLUMN_COUNT) {
+ unsigned bitflag = 1 << (tag_child % BITS_PER_WORD);
+ int known = ((tag_tree_combination_table[tag_parent]
+ [index] & bitflag) > 0 ? TRUE : FALSE);
+ if(known) {
+ return TRUE;
+ }
+ }
+ }
+ if(!suppress_check_extensions_tables) {
+ int r = 0;
+ for ( ; r < TAG_TREE_EXT_ROW_COUNT; ++r ) {
+ int c = 1;
+ if(tag_parent != tag_tree_combination_ext_table[r][0]) {
+ continue;
+ }
+ for( ; c < TAG_TREE_EXT_COLUMN_COUNT ; ++c) {
+ if (tag_tree_combination_ext_table[r][c] == tag_child) {
+ return TRUE;
+ }
+ }
+ }
+ }
+ return (FALSE);
+}
+
diff --git a/dwarfdump/print_frames.c b/dwarfdump/print_frames.c
new file mode 100644
index 0000000..01e4130
--- /dev/null
+++ b/dwarfdump/print_frames.c
@@ -0,0 +1,1823 @@
+/*
+ Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2011 SN Systems Ltd. All Rights Reserved.
+ Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+ $Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_frames.c,v 1.5 2006/06/14 20:34:02 davea Exp $ */
+
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+/* From 199x through 2010 print_frames relied on
+ the order of the fdes matching the order of the functions
+ in the CUs when it came to printing a function name with
+ an FDE. This sometimes worked for SGI/IRIX because of
+ the way the compiler often emitted things. It always worked poorly
+ for gcc and other compilers.
+
+ As of 2010 the addrmap.h addrmap.h code provides help
+ in doing a better job when the tsearch functions (part of
+ POSIX) are available. */
+
+#include "globals.h"
+
+#include "print_frames.h"
+#include "dwconf.h"
+#include "esb.h"
+#include "addrmap.h"
+
+static void
+print_one_frame_reg_col(Dwarf_Debug dbg,
+ Dwarf_Unsigned rule_id,
+ Dwarf_Small value_type,
+ Dwarf_Unsigned reg_used,
+ Dwarf_Half addr_size,
+ struct dwconf_s *config_data,
+ Dwarf_Signed offset_relevant,
+ Dwarf_Signed offset, Dwarf_Ptr block_ptr);
+
+/* A strcpy which ensures NUL terminated string
+ and never overruns the output.
+*/
+void
+safe_strcpy(char *out, long outlen, const char *in, long inlen)
+{
+ if (inlen >= (outlen - 1)) {
+ strncpy(out, in, outlen - 1);
+ out[outlen - 1] = 0;
+ } else {
+ strcpy(out, in);
+ }
+}
+
+/* For inlined functions, try to find name */
+static int
+get_abstract_origin_funcname(Dwarf_Debug dbg,Dwarf_Attribute attr,
+ char *name_out, unsigned maxlen)
+{
+ Dwarf_Off off = 0;
+ Dwarf_Die origin_die = 0;
+ Dwarf_Attribute *atlist = NULL;
+ Dwarf_Signed atcnt = 0;
+ Dwarf_Signed i = 0;
+ int dres = 0;
+ int atres;
+ int name_found = 0;
+ int res = dwarf_global_formref(attr,&off,&err);
+ if(res != DW_DLV_OK) {
+ return DW_DLV_NO_ENTRY;
+ }
+ dres = dwarf_offdie(dbg,off,&origin_die,&err);
+ if(dres != DW_DLV_OK) {
+ return DW_DLV_NO_ENTRY;
+ }
+ atres = dwarf_attrlist(origin_die, &atlist, &atcnt, &err);
+ if (atres != DW_DLV_OK) {
+ dwarf_dealloc(dbg,origin_die,DW_DLA_DIE);
+ return DW_DLV_NO_ENTRY;
+ }
+ for (i = 0; i < atcnt; i++) {
+ Dwarf_Half lattr;
+ int ares;
+ ares = dwarf_whatattr(atlist[i], &lattr, &err);
+ if (ares == DW_DLV_ERROR) {
+ break;
+ } else if (ares == DW_DLV_OK) {
+ if(lattr == DW_AT_name) {
+ int sres = 0;
+ char* temps = 0;
+ sres = dwarf_formstring(atlist[i], &temps, &err);
+ if (sres == DW_DLV_OK) {
+ long len = (long) strlen(temps);
+ safe_strcpy(name_out, maxlen, temps, len);
+ name_found = 1;
+ break;
+ }
+ }
+ }
+ }
+ for (i = 0; i < atcnt; i++) {
+ dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);
+ }
+ dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
+ dwarf_dealloc(dbg,origin_die,DW_DLA_DIE);
+ if(!name_found) {
+ return DW_DLV_NO_ENTRY;
+ }
+ return DW_DLV_OK;
+}
+/*
+ Returns 1 if a proc with this low_pc found.
+ Else returns 0.
+
+ From print_die.c this has no pcMap passed in,
+ we do not really have a sensible context, so this
+ really just looks at the current attributes for a name.
+*/
+int
+get_proc_name(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr low_pc,
+ char *proc_name_buf, int proc_name_buf_len, void **pcMap)
+{
+ Dwarf_Signed atcnt = 0;
+ Dwarf_Signed i = 0;
+ Dwarf_Attribute *atlist = NULL;
+ Dwarf_Addr low_pc_die = 0;
+ int atres = 0;
+ int funcres = 1;
+ int funcpcfound = 0;
+ int funcnamefound = 0;
+
+ proc_name_buf[0] = 0; /* always set to something */
+ if(pcMap) {
+ struct Addr_Map_Entry *ame = 0;
+ ame = addr_map_find(low_pc,pcMap);
+ if(ame && ame->mp_name) {
+ /* mp_name is NULL only if we ran out of heap space. */
+ safe_strcpy(proc_name_buf, proc_name_buf_len,
+ ame->mp_name,(long) strlen(ame->mp_name));
+ return 1;
+ }
+ }
+
+ atres = dwarf_attrlist(die, &atlist, &atcnt, &err);
+ if (atres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_attrlist", atres, err);
+ return 0;
+ }
+ if (atres == DW_DLV_NO_ENTRY) {
+ return 0;
+ }
+ for (i = 0; i < atcnt; i++) {
+ Dwarf_Half attr = 0;
+ int ares = 0;
+ string temps = 0;
+ int sres = 0;
+ int dres = 0;
+
+ if (funcnamefound == 1 && funcpcfound == 1) {
+ /* stop as soon as both found */
+ break;
+ }
+ ares = dwarf_whatattr(atlist[i], &attr, &err);
+ if (ares == DW_DLV_ERROR) {
+ print_error(dbg, "get_proc_name whatattr error", ares, err);
+ } else if (ares == DW_DLV_OK) {
+ switch (attr) {
+ case DW_AT_specification:
+ case DW_AT_abstract_origin:
+ {
+ if(!funcnamefound) {
+ /* Only use this if we have not seen DW_AT_name
+ yet .*/
+ int aores = get_abstract_origin_funcname(dbg,
+ atlist[i], proc_name_buf,proc_name_buf_len);
+ if(aores == DW_DLV_OK) {
+ /* FOUND THE NAME */
+ funcnamefound = 1;
+ }
+ }
+ }
+ break;
+ case DW_AT_name:
+ /* Even if we saw DW_AT_abstract_origin, go ahead
+ and take DW_AT_name. */
+ sres = dwarf_formstring(atlist[i], &temps, &err);
+ if (sres == DW_DLV_ERROR) {
+ print_error(dbg,
+ "formstring in get_proc_name failed",
+ sres, err);
+ /* 50 is safe wrong length since is bigger than the
+ actual string */
+ safe_strcpy(proc_name_buf, proc_name_buf_len,
+ "ERROR in dwarf_formstring!", 50);
+ } else if (sres == DW_DLV_NO_ENTRY) {
+ /* 50 is safe wrong length since is bigger than the
+ actual string */
+ safe_strcpy(proc_name_buf, proc_name_buf_len,
+ "NO ENTRY on dwarf_formstring?!", 50);
+ } else {
+ long len = (long) strlen(temps);
+
+ safe_strcpy(proc_name_buf, proc_name_buf_len, temps,
+ len);
+ }
+ funcnamefound = 1; /* FOUND THE NAME */
+ break;
+ case DW_AT_low_pc:
+ dres = dwarf_formaddr(atlist[i], &low_pc_die, &err);
+ if (dres == DW_DLV_ERROR) {
+ print_error(dbg, "formaddr in get_proc_name failed",
+ dres, err);
+ low_pc_die = ~low_pc;
+ /* ensure no match */
+ }
+ funcpcfound = 1;
+
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ for (i = 0; i < atcnt; i++) {
+ dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);
+ }
+ dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
+ if(funcnamefound && funcpcfound && pcMap ) {
+ /* Insert every name to map, not just the one
+ we are looking for.
+ This version does extra work in that
+ early symbols in a CU will be inserted
+ multiple times (the extra times have no
+ effect), the dwarfdump2
+ version of this does less work. */
+ addr_map_insert(low_pc_die,proc_name_buf,pcMap);
+ }
+ if (funcnamefound == 0 || funcpcfound == 0 || low_pc != low_pc_die) {
+ funcres = 0;
+ }
+ return (funcres);
+}
+
+/* Modified Depth First Search looking for the procedure:
+ a) only looks for children of subprogram.
+ b) With subprogram looks at current die *before* looking
+ for a child.
+
+ Needed since some languages, including SGI MP Fortran,
+ have nested functions.
+ Return 0 on failure, 1 on success.
+*/
+static int
+load_nested_proc_name(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr low_pc,
+ char *ret_name_buf, int ret_name_buf_len,
+ void **pcMap)
+{
+ char name_buf[BUFSIZ];
+ Dwarf_Die curdie = die;
+ int die_locally_gotten = 0;
+ Dwarf_Die prev_child = 0;
+ Dwarf_Die newchild = 0;
+ Dwarf_Die newsibling = 0;
+ Dwarf_Half tag;
+ Dwarf_Error err = 0;
+ int chres = DW_DLV_OK;
+
+ ret_name_buf[0] = 0;
+ name_buf[0] = 0;
+ while (chres == DW_DLV_OK) {
+ int tres;
+
+ tres = dwarf_tag(curdie, &tag, &err);
+ newchild = 0;
+ err = 0;
+ if (tres == DW_DLV_OK) {
+ int lchres;
+
+ if (tag == DW_TAG_subprogram) {
+ int proc_name_v = get_proc_name(dbg, curdie, low_pc,
+ name_buf, BUFSIZ,pcMap);
+ if (proc_name_v) {
+ safe_strcpy(ret_name_buf, ret_name_buf_len,
+ name_buf, (long) strlen(name_buf));
+ if (die_locally_gotten) {
+ /* If we got this die from the parent, we do
+ not want to dealloc here! */
+ dwarf_dealloc(dbg, curdie, DW_DLA_DIE);
+ }
+ return 1;
+ }
+ /* Check children of subprograms recursively should
+ this really be check children of anything,
+ or just children of subprograms? */
+
+ lchres = dwarf_child(curdie, &newchild, &err);
+ if (lchres == DW_DLV_OK) {
+ /* look for inner subprogram */
+ int newprog =
+ load_nested_proc_name(dbg, newchild, low_pc,
+ name_buf, BUFSIZ,
+ pcMap);
+
+ dwarf_dealloc(dbg, newchild, DW_DLA_DIE);
+ if (newprog) {
+ /* Found it. We could just take this name or
+ we could concatenate names together For now,
+ just take name */
+ if (die_locally_gotten) {
+ /* If we got this die from the parent, we
+ do not want to dealloc here! */
+ dwarf_dealloc(dbg, curdie, DW_DLA_DIE);
+ }
+ safe_strcpy(ret_name_buf, ret_name_buf_len,
+ name_buf, (long) strlen(name_buf));
+ return 1;
+ }
+ } else if (lchres == DW_DLV_NO_ENTRY) {
+ /* nothing to do */
+ } else {
+ print_error(dbg,
+ "load_nested_proc_name dwarf_child() failed ",
+ chres, err);
+ if (die_locally_gotten) {
+ /* If we got this die from the parent, we do
+ not want to dealloc here! */
+ dwarf_dealloc(dbg, curdie, DW_DLA_DIE);
+ }
+ return 0;
+ }
+ } /* end if TAG_subprogram */
+ } else {
+ print_error(dbg, "no tag on child read ", tres, err);
+ if (die_locally_gotten) {
+ /* If we got this die from the parent, we do not want
+ to dealloc here! */
+ dwarf_dealloc(dbg, curdie, DW_DLA_DIE);
+ }
+ return 0;
+ }
+ /* try next sibling */
+ prev_child = curdie;
+ chres = dwarf_siblingof(dbg, curdie, &newsibling, &err);
+ if (chres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_cu_header On Child read ", chres,
+ err);
+ if (die_locally_gotten) {
+ /* If we got this die from the parent, we do not want
+ to dealloc here! */
+ dwarf_dealloc(dbg, curdie, DW_DLA_DIE);
+ }
+ return 0;
+ } else if (chres == DW_DLV_NO_ENTRY) {
+ if (die_locally_gotten) {
+ /* If we got this die from the parent, we do not want
+ to dealloc here! */
+ dwarf_dealloc(dbg, prev_child, DW_DLA_DIE);
+ }
+ return 0;/* proc name not at this level */
+ } else {
+ /* DW_DLV_OK */
+ curdie = newsibling;
+ if (die_locally_gotten) {
+ /* If we got this die from the parent, we do not want
+ to dealloc here! */
+ dwarf_dealloc(dbg, prev_child, DW_DLA_DIE);
+ }
+ prev_child = 0;
+ die_locally_gotten = 1;
+ }
+
+ }
+ if (die_locally_gotten) {
+ /* If we got this die from the parent, we do not want to
+ dealloc here! */
+ dwarf_dealloc(dbg, curdie, DW_DLA_DIE);
+ }
+ return 0;
+}
+
+/* For SGI MP Fortran and other languages, functions
+ nest! As a result, we must dig thru all functions,
+ not just the top level.
+ This remembers the CU die and restarts each search at the start
+ of the current cu.
+*/
+static string
+get_fde_proc_name(Dwarf_Debug dbg, Dwarf_Addr low_pc,
+ void **pcMap,
+ int *all_cus_seen)
+{
+ static char proc_name[BUFSIZ];
+ Dwarf_Unsigned cu_header_length = 0;
+ Dwarf_Unsigned abbrev_offset = 0;
+ Dwarf_Half version_stamp = 0;
+ Dwarf_Half address_size = 0;
+ Dwarf_Unsigned next_cu_offset = 0;
+ int cures = DW_DLV_OK;
+ int dres = DW_DLV_OK;
+ int chres = DW_DLV_OK;
+ int looping = 0;
+
+ proc_name[0] = 0;
+ {
+ struct Addr_Map_Entry *ame = 0;
+ ame = addr_map_find(low_pc,pcMap);
+ if(ame && ame->mp_name) {
+ /* mp_name is only NULL here if we just ran out of heap memory! */
+ safe_strcpy(proc_name, sizeof(proc_name),
+ ame->mp_name,(long) strlen(ame->mp_name));
+ return proc_name;
+ }
+ if (*all_cus_seen) {
+ return "";
+ }
+ }
+ if (current_cu_die_for_print_frames == NULL) {
+ /* Call depends on dbg->cu_context to know what to do. */
+ cures = dwarf_next_cu_header(dbg, &cu_header_length,
+ &version_stamp, &abbrev_offset,
+ &address_size, &next_cu_offset,
+ &err);
+ if (cures == DW_DLV_ERROR) {
+ return NULL;
+ } else if (cures == DW_DLV_NO_ENTRY) {
+ /* loop thru the list again */
+ current_cu_die_for_print_frames = 0;
+ ++looping;
+ } else { /* DW_DLV_OK */
+ dres = dwarf_siblingof(dbg, NULL,
+ &current_cu_die_for_print_frames,
+ &err);
+ if (dres == DW_DLV_ERROR) {
+ return NULL;
+ }
+ }
+ }
+ if (dres == DW_DLV_OK) {
+ Dwarf_Die child = 0;
+
+ if (current_cu_die_for_print_frames == 0) {
+ /* no information. Possibly a stripped file */
+ return NULL;
+ }
+ chres =
+ dwarf_child(current_cu_die_for_print_frames, &child, &err);
+ if (chres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_cu_header on child read ", chres,
+ err);
+ } else if (chres == DW_DLV_NO_ENTRY) {
+ } else { /* DW_DLV_OK */
+ int gotname =
+ load_nested_proc_name(dbg, child, low_pc, proc_name,
+ BUFSIZ,pcMap);
+
+ dwarf_dealloc(dbg, child, DW_DLA_DIE);
+ if (gotname) {
+ return (proc_name);
+ }
+ child = 0;
+ }
+ }
+ for (;;) {
+ Dwarf_Die ldie = 0;
+
+ cures = dwarf_next_cu_header(dbg, &cu_header_length,
+ &version_stamp, &abbrev_offset,
+ &address_size, &next_cu_offset,
+ &err);
+ if (cures != DW_DLV_OK) {
+ *all_cus_seen = 1;
+ break;
+ }
+
+ dres = dwarf_siblingof(dbg, NULL, &ldie, &err);
+ if (current_cu_die_for_print_frames) {
+ dwarf_dealloc(dbg, current_cu_die_for_print_frames,
+ DW_DLA_DIE);
+ }
+ current_cu_die_for_print_frames = 0;
+ if (dres == DW_DLV_ERROR) {
+ print_error(dbg,
+ "dwarf_cu_header Child Read finding proc name for .debug_frame",
+ chres, err);
+ continue;
+ } else if (dres == DW_DLV_NO_ENTRY) {
+ ++looping;
+ if (looping > 1) {
+ print_error(dbg, "looping on cu headers!", dres, err);
+ return NULL;
+ }
+ continue;
+ }
+ /* DW_DLV_OK */
+ current_cu_die_for_print_frames = ldie;
+ {
+ int chres = 0;
+ Dwarf_Die child = 0;
+
+ chres =
+ dwarf_child(current_cu_die_for_print_frames, &child,
+ &err);
+ if (chres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf Child Read ", chres, err);
+ } else if (chres == DW_DLV_NO_ENTRY) {
+
+ ;/* do nothing, loop on cu */
+ } else {
+ /* DW_DLV_OK) */
+
+ int gotname =
+ load_nested_proc_name(dbg, child, low_pc, proc_name,
+ BUFSIZ,pcMap);
+
+ dwarf_dealloc(dbg, child, DW_DLA_DIE);
+ if (gotname) {
+ return (proc_name);
+ }
+ }
+ }
+ }
+ return (NULL);
+}
+
+/* Gather the fde print logic here so the control logic
+ determining what FDE to print is clearer. */
+static int
+print_one_fde(Dwarf_Debug dbg, Dwarf_Fde fde,
+ Dwarf_Unsigned fde_index,
+ Dwarf_Cie * cie_data,
+ Dwarf_Signed cie_element_count,
+ Dwarf_Half address_size, int is_eh,
+ struct dwconf_s *config_data,
+ void **pcMap,
+ void **lowpcSet,
+ int * all_cus_seen)
+{
+ Dwarf_Addr j = 0;
+ Dwarf_Addr low_pc = 0;
+ Dwarf_Unsigned func_length = 0;
+ Dwarf_Ptr fde_bytes = NULL;
+ Dwarf_Unsigned fde_bytes_length = 0;
+ Dwarf_Off cie_offset = 0;
+ Dwarf_Signed cie_index = 0;
+ Dwarf_Off fde_offset = 0;
+ Dwarf_Signed eh_table_offset = 0;
+ int fres = 0;
+ int offres = 0;
+ string temps = 0;
+ Dwarf_Error err = 0;
+ int printed_intro_addr = 0;
+
+ fres = dwarf_get_fde_range(fde,
+ &low_pc, &func_length,
+ &fde_bytes,
+ &fde_bytes_length,
+ &cie_offset, &cie_index,
+ &fde_offset, &err);
+ if (fres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_fde_range", fres, err);
+ }
+ if (fres == DW_DLV_NO_ENTRY) {
+ return DW_DLV_NO_ENTRY;
+ }
+ if (cu_name_flag &&
+ fde_offset_for_cu_low != DW_DLV_BADOFFSET &&
+ (fde_offset < fde_offset_for_cu_low ||
+ fde_offset > fde_offset_for_cu_high)) {
+ return DW_DLV_NO_ENTRY;
+ }
+ /* eh_table_offset is IRIX ONLY. */
+ fres = dwarf_get_fde_exception_info(fde, &eh_table_offset, &err);
+ if (fres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_fde_exception_info", fres, err);
+ }
+ if(suppress_nested_name_search) {
+ temps = 0;
+ } else {
+#ifdef HAVE_TSEARCH
+ struct Addr_Map_Entry *mp = 0;
+ temps = get_fde_proc_name(dbg, low_pc,pcMap,all_cus_seen);
+ mp = addr_map_find(low_pc,lowpcSet);
+ if (check_frames || check_frames_extended) {
+ DWARF_CHECK_COUNT(fde_duplication,1);
+ }
+ if (mp) {
+ if (check_frames || check_frames_extended) {
+ char msg[400];
+ if(temps && (strlen(temps) > 0)) {
+ snprintf(msg,sizeof(msg),"An fde low pc of 0x%"
+ DW_PR_DUx
+ " is not the first fde with that pc. "
+ "The first is named \"%s\"",
+ (Dwarf_Unsigned)low_pc,
+ temps);
+ } else {
+ snprintf(msg,sizeof(msg),"An fde low pc of 0x%"
+ DW_PR_DUx
+ " is not the first fde with that pc. "
+ "The first is not named.",
+ (Dwarf_Unsigned)low_pc);
+
+ }
+ DWARF_CHECK_ERROR(fde_duplication,msg);
+ }
+ } else {
+ addr_map_insert(low_pc,0,lowpcSet);
+ }
+#endif
+ }
+
+ /* Do not print if in check mode */
+ if (!check_frames_extended) {
+ printf("<%5" DW_PR_DSd "><0x%" DW_PR_XZEROS DW_PR_DUx
+ ":0x%" DW_PR_XZEROS DW_PR_DUx
+ "><%s><fde offset 0x%" DW_PR_XZEROS DW_PR_DUx
+ " length: 0x%" DW_PR_XZEROS DW_PR_DUx ">",
+ cie_index, (Dwarf_Unsigned)low_pc,
+ (Dwarf_Unsigned)(low_pc + func_length),
+ temps ? temps : "", (Dwarf_Unsigned)fde_offset, fde_bytes_length);
+ }
+
+
+
+ if (!is_eh) {
+ /* IRIX uses eh_table_offset. */
+ /* Do not print if in check mode */
+ if (!check_frames_extended) {
+ if (eh_table_offset == DW_DLX_NO_EH_OFFSET) {
+ printf("<eh offset %s>\n", "none");
+ } else if (eh_table_offset == DW_DLX_EH_OFFSET_UNAVAILABLE) {
+ printf("<eh offset %s>\n", "unknown");
+ } else {
+ printf("<eh offset 0x%" DW_PR_XZEROS DW_PR_DUx
+ ">\n", eh_table_offset);
+ }
+ }
+ } else {
+ int ares = 0;
+ Dwarf_Small *data = 0;
+ Dwarf_Unsigned len = 0;
+
+ ares = dwarf_get_fde_augmentation_data(fde, &data, &len, &err);
+ if (ares == DW_DLV_NO_ENTRY) {
+ /* do nothing. */
+ } else if (ares == DW_DLV_OK) {
+ /* Do not print if in check mode */
+ if (!check_frames_extended) {
+ int k2 = 0;
+
+ printf("<eh aug data len 0x%" DW_PR_DUx , len);
+ for (k2 = 0; k2 < len; ++k2) {
+ if (k2 == 0) {
+ printf(" bytes 0x");
+ }
+ printf("%02x ", (unsigned char) data[k2]);
+ }
+ printf(">");
+ }
+ } /* else DW_DLV_ERROR, do nothing */
+
+ /* Do not print if in check mode */
+ if (!check_frames_extended) {
+ printf("\n");
+
+ }
+ }
+
+ for (j = low_pc; j < low_pc + func_length; j++) {
+ Dwarf_Half k = 0;
+
+ if (config_data->cf_interface_number == 3) {
+ Dwarf_Signed reg = 0;
+ Dwarf_Signed offset_relevant = 0;
+ Dwarf_Small value_type = 0;
+ Dwarf_Signed offset_or_block_len = 0;
+ Dwarf_Signed offset = 0;
+ Dwarf_Ptr block_ptr = 0;
+ Dwarf_Addr row_pc = 0;
+
+ int fires = dwarf_get_fde_info_for_cfa_reg3(fde,
+ j,
+ &value_type,
+ &offset_relevant,
+ &reg,
+ &offset_or_block_len,
+ &block_ptr,
+ &row_pc,
+ &err);
+ offset = offset_or_block_len;
+ if (fires == DW_DLV_ERROR) {
+ print_error(dbg,
+ "dwarf_get_fde_info_for_reg", fires, err);
+ }
+ if (fires == DW_DLV_NO_ENTRY) {
+ continue;
+ }
+ if (row_pc != j) {
+ /* duplicate row */
+ continue;
+ }
+
+ /* Do not print if in check mode */
+ if (!printed_intro_addr && !check_frames_extended) {
+ printf(" 0x%" DW_PR_XZEROS DW_PR_DUx
+ ": ", (Dwarf_Unsigned)j);
+ printed_intro_addr = 1;
+ }
+ print_one_frame_reg_col(dbg, config_data->cf_cfa_reg,
+ value_type,
+ reg,
+ address_size,
+ config_data,
+ offset_relevant, offset, block_ptr);
+ }
+ for (k = 0; k < config_data->cf_table_entry_count; k++) {
+ Dwarf_Signed reg = 0;
+ Dwarf_Signed offset_relevant = 0;
+ int fires = 0;
+ Dwarf_Small value_type = 0;
+ Dwarf_Ptr block_ptr = 0;
+ Dwarf_Signed offset_or_block_len = 0;
+ Dwarf_Signed offset = 0;
+ Dwarf_Addr row_pc = 0;
+
+ if (config_data->cf_interface_number == 3) {
+ fires = dwarf_get_fde_info_for_reg3(fde,
+ k,
+ j,
+ &value_type,
+ &offset_relevant,
+ &reg,
+ &offset_or_block_len,
+ &block_ptr,
+ &row_pc, &err);
+ offset = offset_or_block_len;
+ } else {
+ /* This interface is deprecated. Is the old
+ MIPS/DWARF2 interface. */
+ /* ASSERT: config_data->cf_interface_number == 2 */
+ value_type = DW_EXPR_OFFSET;
+ fires = dwarf_get_fde_info_for_reg(fde,
+ k,
+ j,
+ &offset_relevant,
+ &reg,
+ &offset, &row_pc,
+ &err);
+ }
+ if (fires == DW_DLV_ERROR) {
+ printf("\n");
+ print_error(dbg,
+ "dwarf_get_fde_info_for_reg", fires, err);
+ }
+ if (fires == DW_DLV_NO_ENTRY) {
+ continue;
+ }
+ if (row_pc != j) {
+ /* duplicate row */
+ break;
+ }
+
+ /* Do not print if in check mode */
+ if (!printed_intro_addr && !check_frames_extended) {
+ printf(" 0x%" DW_PR_XZEROS DW_PR_DUx ": ",
+ (Dwarf_Unsigned)j);
+ printed_intro_addr = 1;
+ }
+ print_one_frame_reg_col(dbg,k,
+ value_type,
+ reg,
+ address_size,
+ config_data,
+ offset_relevant, offset, block_ptr);
+ }
+ if (printed_intro_addr) {
+ printf("\n");
+ printed_intro_addr = 0;
+ }
+ }
+ if (verbose > 1) {
+ Dwarf_Off fde_off = 0;
+ Dwarf_Off cie_off = 0;
+
+ /* Get the fde instructions and print them in raw form, just
+ like cie instructions */
+ Dwarf_Ptr instrs = 0;
+ Dwarf_Unsigned ilen = 0;
+ int res = 0;
+
+ res = dwarf_get_fde_instr_bytes(fde, &instrs, &ilen, &err);
+ offres =
+ dwarf_fde_section_offset(dbg, fde, &fde_off, &cie_off,
+ &err);
+ if (offres == DW_DLV_OK) {
+ /* Do not print if in check mode */
+ if (!check_frames_extended) {
+ printf(" fde section offset %" DW_PR_DUu
+ " 0x%" DW_PR_XZEROS DW_PR_DUx
+ " cie offset for fde: %" DW_PR_DUu
+ " 0x%" DW_PR_XZEROS DW_PR_DUx "\n",
+ (Dwarf_Unsigned) fde_off,
+ (Dwarf_Unsigned) fde_off,
+ (Dwarf_Unsigned) cie_off,
+ (Dwarf_Unsigned) cie_off);
+ }
+ }
+
+
+ if (res == DW_DLV_OK) {
+ int cires = 0;
+ Dwarf_Unsigned cie_length = 0;
+ Dwarf_Small version = 0;
+ string augmenter = 0;
+ Dwarf_Unsigned code_alignment_factor = 0;
+ Dwarf_Signed data_alignment_factor = 0;
+ Dwarf_Half return_address_register_rule = 0;
+ Dwarf_Ptr initial_instructions = 0;
+ Dwarf_Unsigned initial_instructions_length = 0;
+
+ if (cie_index >= cie_element_count) {
+ printf("Bad cie index %" DW_PR_DSd
+ " with fde index %" DW_PR_DUu "! "
+ "(table entry max %" DW_PR_DSd ")\n",
+ cie_index, fde_index,
+ cie_element_count);
+ exit(1);
+ }
+ cires = dwarf_get_cie_info(cie_data[cie_index],
+ &cie_length,
+ &version,
+ &augmenter,
+ &code_alignment_factor,
+ &data_alignment_factor,
+ &return_address_register_rule,
+ &initial_instructions,
+ &initial_instructions_length,
+ &err);
+ if (cires == DW_DLV_ERROR) {
+ printf
+ ("Bad cie index %" DW_PR_DSd
+ " with fde index %" DW_PR_DUu "!\n",
+ cie_index, fde_index);
+ print_error(dbg, "dwarf_get_cie_info", cires, err);
+ }
+ if (cires == DW_DLV_NO_ENTRY) {
+ ; /* ? */
+ } else {
+ /* Do not print if in check mode */
+ if (!check_frames_extended) {
+ print_frame_inst_bytes(dbg, instrs,
+ (Dwarf_Signed) ilen,
+ data_alignment_factor,
+ (int) code_alignment_factor,
+ address_size, config_data);
+ }
+ }
+ } else if (res == DW_DLV_NO_ENTRY) {
+ printf("Impossible: no instr bytes for fde index %"
+ DW_PR_DUu "?\n",
+ fde_index);
+ } else {
+ /* DW_DLV_ERROR */
+ printf("Error: on gettinginstr bytes for fde index %"
+ DW_PR_DUu "?\n",
+ fde_index);
+ print_error(dbg, "dwarf_get_fde_instr_bytes", res, err);
+ }
+
+ }
+ return DW_DLV_OK;
+}
+
+
+/* Print a cie. Gather the print logic here so the
+ control logic deciding what to print
+ is clearer.
+*/
+int
+print_one_cie(Dwarf_Debug dbg, Dwarf_Cie cie,
+ Dwarf_Unsigned cie_index, Dwarf_Half address_size,
+ struct dwconf_s *config_data)
+{
+
+ int cires = 0;
+ Dwarf_Unsigned cie_length = 0;
+ Dwarf_Small version = 0;
+ string augmenter = "";
+ Dwarf_Unsigned code_alignment_factor = 0;
+ Dwarf_Signed data_alignment_factor = 0;
+ Dwarf_Half return_address_register_rule = 0;
+ Dwarf_Ptr initial_instructions = 0;
+ Dwarf_Unsigned initial_instructions_length = 0;
+ Dwarf_Off cie_off = 0;
+ Dwarf_Error err = 0;
+
+ cires = dwarf_get_cie_info(cie,
+ &cie_length,
+ &version,
+ &augmenter,
+ &code_alignment_factor,
+ &data_alignment_factor,
+ &return_address_register_rule,
+ &initial_instructions,
+ &initial_instructions_length, &err);
+ if (cires == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_cie_info", cires, err);
+ }
+ if (cires == DW_DLV_NO_ENTRY) {
+ printf("Impossible DW_DLV_NO_ENTRY on cie %" DW_PR_DUu "\n",
+ cie_index);
+ return DW_DLV_NO_ENTRY;
+ }
+ {
+ /* Do not print if in check mode */
+ if (!check_frames_extended) {
+ printf("<%5" DW_PR_DUu ">\tversion\t\t\t\t%d\n",
+ cie_index, version);
+ cires = dwarf_cie_section_offset(dbg, cie, &cie_off, &err);
+ if (cires == DW_DLV_OK) {
+ printf("\tcie section offset\t\t%" DW_PR_DUu
+ " 0x%" DW_PR_XZEROS DW_PR_DUx "\n",
+ (Dwarf_Unsigned) cie_off,
+ (Dwarf_Unsigned) cie_off);
+ }
+ printf("\taugmentation\t\t\t%s\n", augmenter);
+ printf("\tcode_alignment_factor\t\t%" DW_PR_DUu "\n",
+ code_alignment_factor);
+ printf("\tdata_alignment_factor\t\t%" DW_PR_DSd "\n",
+ data_alignment_factor);
+ printf("\treturn_address_register\t\t%d\n",
+ return_address_register_rule);
+ }
+
+ {
+ int ares = 0;
+ Dwarf_Small *data = 0;
+ Dwarf_Unsigned len = 0;
+
+ ares =
+ dwarf_get_cie_augmentation_data(cie, &data, &len, &err);
+ if (ares == DW_DLV_NO_ENTRY) {
+ /* do nothing. */
+ } else if (ares == DW_DLV_OK && len > 0) {
+ /* Do not print if in check mode */
+ if (!check_frames_extended) {
+ int k2 = 0;
+
+ printf(" eh aug data len 0x%" DW_PR_DUx , len);
+ for (k2 = 0; data && k2 < len; ++k2) {
+ if (k2 == 0) {
+ printf(" bytes 0x");
+ }
+ printf("%02x ", (unsigned char) data[k2]);
+ }
+ printf("\n");
+ }
+ } /* else DW_DLV_ERROR or no data, do nothing */
+ }
+
+ /* Do not print if in check mode */
+ if (!check_frames_extended) {
+ printf("\tbytes of initial instructions\t%" DW_PR_DUu "\n",
+ initial_instructions_length);
+ printf("\tcie length\t\t\t%" DW_PR_DUu "\n", cie_length);
+ /* For better layout */
+ printf("\tinitial instructions\n");
+ print_frame_inst_bytes(dbg, initial_instructions,
+ (Dwarf_Signed) initial_instructions_length,
+ data_alignment_factor,
+ (int) code_alignment_factor,
+ address_size, config_data);
+ }
+ }
+ return DW_DLV_OK;
+}
+
+void
+get_string_from_locs(Dwarf_Debug dbg,
+ Dwarf_Ptr bytes_in,
+ Dwarf_Unsigned block_len,
+ Dwarf_Half addr_size,
+ struct esb_s *out_string)
+{
+
+ Dwarf_Locdesc *locdescarray = 0;
+ Dwarf_Signed listlen = 0;
+ Dwarf_Error err2 =0;
+ int skip_locdesc_header=1;
+ int res = 0;
+ int res2 = dwarf_loclist_from_expr_a(dbg,
+ bytes_in,block_len,
+ addr_size,
+ &locdescarray,
+ &listlen,&err2);
+ if (res2 == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_loclist_from_expr_a",
+ res2, err2);
+ }
+ if(res2==DW_DLV_NO_ENTRY) {
+ return;
+ }
+ /* lcnt is always 1 */
+
+ /* Use locdescarray here.*/
+ res = dwarfdump_print_one_locdesc(dbg,
+ locdescarray,
+ skip_locdesc_header,
+ out_string);
+ if(res != DW_DLV_OK) {
+ printf("Bad status from _dwarf_print_one_locdesc %d\n",res);
+ exit(1);
+ }
+
+ dwarf_dealloc(dbg, locdescarray->ld_s, DW_DLA_LOC_BLOCK);
+ dwarf_dealloc(dbg, locdescarray, DW_DLA_LOCDESC);
+ return ;
+}
+
+/* Print the frame instructions in detail for a glob of instructions.
+*/
+
+/*ARGSUSED*/ void
+print_frame_inst_bytes(Dwarf_Debug dbg,
+ Dwarf_Ptr cie_init_inst, Dwarf_Signed len,
+ Dwarf_Signed data_alignment_factor,
+ int code_alignment_factor, Dwarf_Half addr_size,
+ struct dwconf_s *config_data)
+{
+ unsigned char *instp = (unsigned char *) cie_init_inst;
+ Dwarf_Unsigned uval = 0;
+ Dwarf_Unsigned uval2 = 0;
+ unsigned int uleblen = 0;
+ unsigned int off = 0;
+ unsigned int loff = 0;
+ unsigned short u16 = 0;
+ unsigned int u32 = 0;
+ unsigned long long u64;
+
+ for (; len > 0;) {
+ unsigned char ibyte = *instp;
+ int top = ibyte & 0xc0;
+ int bottom = ibyte & 0x3f;
+ int delta = 0;
+ int reg = 0;
+
+ switch (top) {
+ case DW_CFA_advance_loc:
+ delta = ibyte & 0x3f;
+ printf("\t%2u DW_CFA_advance_loc %d", off,
+ (int) (delta * code_alignment_factor));
+ if (verbose) {
+ printf(" (%d * %d)", (int) delta,
+ (int) code_alignment_factor);
+ }
+ printf("\n");
+ break;
+ case DW_CFA_offset:
+ loff = off;
+ reg = ibyte & 0x3f;
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ printf("\t%2u DW_CFA_offset ", loff);
+ printreg((Dwarf_Signed) reg, config_data);
+ printf(" %" DW_PR_DSd , (Dwarf_Signed)
+ (((Dwarf_Signed) uval) * data_alignment_factor));
+ if (verbose) {
+ printf(" (%" DW_PR_DUu " * %" DW_PR_DSd ")", uval,
+ data_alignment_factor);
+ }
+ printf("\n");
+ break;
+
+ case DW_CFA_restore:
+ reg = ibyte & 0x3f;
+ printf("\t%2u DW_CFA_restore ", off);
+ printreg((Dwarf_Signed) reg, config_data);
+ printf("\n");
+ break;
+
+ default:
+ loff = off;
+ switch (bottom) {
+ case DW_CFA_set_loc:
+ /* operand is address, so need address size */
+ /* which will be 4 or 8. */
+ switch (addr_size) {
+ case 4:
+ {
+ __uint32_t v32 = 0;
+ memcpy(&v32, instp + 1, addr_size);
+ uval = v32;
+ }
+ break;
+ case 8:
+ {
+ __uint64_t v64 = 0;
+ memcpy(&v64, instp + 1, addr_size);
+ uval = v64;
+ }
+ break;
+ default:
+ printf
+ ("Error: Unexpected address size %d in DW_CFA_set_loc!\n",
+ addr_size);
+ uval = 0;
+ }
+
+ instp += addr_size;
+ len -= (Dwarf_Signed) addr_size;
+ off += addr_size;
+ printf("\t%2u DW_CFA_set_loc %" DW_PR_DUu "\n",
+ loff, uval);
+ break;
+ case DW_CFA_advance_loc1:
+ delta = (unsigned char) *(instp + 1);
+ uval2 = delta;
+ instp += 1;
+ len -= 1;
+ off += 1;
+ printf("\t%2u DW_CFA_advance_loc1 %" DW_PR_DUu "\n",
+ loff, uval2);
+ break;
+ case DW_CFA_advance_loc2:
+ memcpy(&u16, instp + 1, 2);
+ uval2 = u16;
+ instp += 2;
+ len -= 2;
+ off += 2;
+ printf("\t%2u DW_CFA_advance_loc2 %" DW_PR_DUu "\n",
+ loff, uval2);
+ break;
+ case DW_CFA_advance_loc4:
+ memcpy(&u32, instp + 1, 4);
+ uval2 = u32;
+ instp += 4;
+ len -= 4;
+ off += 4;
+ printf("\t%2u DW_CFA_advance_loc4 %" DW_PR_DUu "\n",
+ loff, uval2);
+ break;
+ case DW_CFA_MIPS_advance_loc8:
+ memcpy(&u64, instp + 1, 8);
+ uval2 = u64;
+ instp += 8;
+ len -= 8;
+ off += 8;
+ printf("\t%2u DW_CFA_MIPS_advance_loc8 %" DW_PR_DUu "\n",
+ loff, uval2);
+ break;
+ case DW_CFA_offset_extended:
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ uval2 =
+ local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ printf("\t%2u DW_CFA_offset_extended ", loff);
+ printreg((Dwarf_Signed) uval, config_data);
+ printf(" %" DW_PR_DSd ,
+ (Dwarf_Signed) (((Dwarf_Signed) uval2) *
+ data_alignment_factor));
+ if (verbose) {
+ printf(" (%" DW_PR_DUu " * %d)", uval2,
+ (int) data_alignment_factor);
+ }
+ printf("\n");
+ break;
+
+ case DW_CFA_restore_extended:
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ printf("\t%2u DW_CFA_restore_extended ", loff);
+ printreg((Dwarf_Signed) uval, config_data);
+ printf("\n");
+ break;
+ case DW_CFA_undefined:
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ printf("\t%2u DW_CFA_undefined ", loff);
+ printreg((Dwarf_Signed) uval, config_data);
+ printf("\n");
+ break;
+ case DW_CFA_same_value:
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ printf("\t%2u DW_CFA_same_value ", loff);
+ printreg((Dwarf_Signed) uval, config_data);
+ printf("\n");
+ break;
+ case DW_CFA_register:
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ uval2 =
+ local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ printf("\t%2u DW_CFA_register ", loff);
+ printreg((Dwarf_Signed) uval, config_data);
+ printf(" = ");
+ printreg((Dwarf_Signed) uval2, config_data);
+ printf("\n");
+ break;
+ case DW_CFA_remember_state:
+ printf("\t%2u DW_CFA_remember_state\n", loff);
+ break;
+ case DW_CFA_restore_state:
+ printf("\t%2u DW_CFA_restore_state\n", loff);
+ break;
+ case DW_CFA_def_cfa:
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ uval2 =
+ local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ printf("\t%2u DW_CFA_def_cfa ", loff);
+ printreg((Dwarf_Signed) uval, config_data);
+ printf(" %" DW_PR_DUu , (unsigned long long) uval2);
+ printf("\n");
+ break;
+ case DW_CFA_def_cfa_register:
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ printf("\t%2u DW_CFA_def_cfa_register ", loff);
+ printreg((Dwarf_Signed) uval, config_data);
+ printf("\n");
+ break;
+ case DW_CFA_def_cfa_offset:
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ printf("\t%2u DW_CFA_def_cfa_offset %" DW_PR_DUu "\n",
+ loff, uval);
+ break;
+
+ case DW_CFA_nop:
+ printf("\t%2u DW_CFA_nop\n", loff);
+ break;
+
+ case DW_CFA_def_cfa_expression: /* DWARF3 */
+ {
+ Dwarf_Unsigned block_len =
+ local_dwarf_decode_u_leb128(instp + 1,
+ &uleblen);
+
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ printf
+ ("\t%2u DW_CFA_def_cfa_expression expr block len %"
+ DW_PR_DUu "\n",
+ loff,
+ block_len);
+ dump_block("\t\t", (char *) instp+1,
+ (Dwarf_Signed) block_len);
+ printf("\n");
+ if(verbose) {
+ struct esb_s exprstring;
+ esb_constructor(&exprstring);
+ get_string_from_locs(dbg,
+ instp+1,block_len,addr_size,&exprstring);
+ printf("\t\t%s\n",esb_get_string(&exprstring));
+ esb_destructor(&exprstring);
+ }
+ instp += block_len;
+ len -= block_len;
+ off += block_len;
+ }
+ break;
+ case DW_CFA_expression: /* DWARF3 */
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ {
+ /* instp is always 1 byte back, so we need +1
+ when we use it. See the final increment
+ of this for loop. */
+ Dwarf_Unsigned block_len =
+ local_dwarf_decode_u_leb128(instp + 1,
+ &uleblen);
+
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ printf
+ ("\t%2u DW_CFA_expression %" DW_PR_DUu
+ " expr block len %" DW_PR_DUu "\n",
+ loff, uval,
+ block_len);
+ dump_block("\t\t", (char *) instp+1,
+ (Dwarf_Signed) block_len);
+ printf("\n");
+ if(verbose) {
+ struct esb_s exprstring;
+ esb_constructor(&exprstring);
+ get_string_from_locs(dbg,
+ instp+1,block_len,addr_size,&exprstring);
+ printf("\t\t%s\n",esb_get_string(&exprstring));
+ esb_destructor(&exprstring);
+ }
+ instp += block_len;
+ len -= block_len;
+ off += block_len;
+ }
+ break;
+ case DW_CFA_offset_extended_sf: /* DWARF3 */
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ {
+ /* instp is always 1 byte back, so we need +1
+ when we use it. See the final increment
+ of this for loop. */
+ Dwarf_Signed sval2 =
+ local_dwarf_decode_s_leb128(instp + 1,
+ &uleblen);
+
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ printf("\t%2u DW_CFA_offset_extended_sf ", loff);
+ printreg((Dwarf_Signed) uval, config_data);
+ printf(" %" DW_PR_DSd , (Dwarf_Signed)
+ ((sval2) * data_alignment_factor));
+ if (verbose) {
+ printf(" (%" DW_PR_DSd " * %d)", sval2,
+ (int) data_alignment_factor);
+ }
+ }
+ printf("\n");
+ break;
+ case DW_CFA_def_cfa_sf: /* DWARF3 */
+ /* instp is always 1 byte back, so we need +1
+ when we use it. See the final increment
+ of this for loop. */
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ {
+ Dwarf_Signed sval2 =
+ local_dwarf_decode_s_leb128(instp + 1,
+ &uleblen);
+
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ printf("\t%2u DW_CFA_def_cfa_sf ", loff);
+ printreg((Dwarf_Signed) uval, config_data);
+ printf(" %" DW_PR_DSd , (long long) sval2);
+ printf(" (*data alignment factor=>%" DW_PR_DSd ")",
+ (Dwarf_Signed)(sval2*data_alignment_factor));
+ }
+ printf("\n");
+ break;
+ case DW_CFA_def_cfa_offset_sf: /* DWARF3 */
+ {
+ /* instp is always 1 byte back, so we need +1
+ when we use it. See the final increment
+ of this for loop. */
+ Dwarf_Signed sval =
+ local_dwarf_decode_s_leb128(instp + 1,
+ &uleblen);
+
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ printf("\t%2u DW_CFA_def_cfa_offset_sf %"
+ DW_PR_DSd " (*data alignment factor=> %"
+ DW_PR_DSd ")\n",
+ loff, sval,
+ (Dwarf_Signed)(data_alignment_factor*sval));
+
+ }
+ break;
+ case DW_CFA_val_offset: /* DWARF3 */
+ /* instp is always 1 byte back, so we need +1
+ when we use it. See the final increment
+ of this for loop. */
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ {
+ Dwarf_Signed sval2 =
+ local_dwarf_decode_s_leb128(instp + 1,
+ &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ printf("\t%2u DW_CFA_val_offset ", loff);
+ printreg((Dwarf_Signed)uval, config_data);
+ printf(" %" DW_PR_DSd ,
+ (Dwarf_Signed) (sval2 *
+ data_alignment_factor));
+ if (verbose) {
+ printf(" (%" DW_PR_DSd " * %d)",
+ (Dwarf_Signed) sval2,
+ (int) data_alignment_factor);
+ }
+ }
+ printf("\n");
+
+ break;
+ case DW_CFA_val_offset_sf: /* DWARF3 */
+ /* instp is always 1 byte back, so we need +1
+ when we use it. See the final increment
+ of this for loop. */
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ {
+ Dwarf_Signed sval2 =
+ local_dwarf_decode_s_leb128(instp + 1,
+ &uleblen);
+
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ printf("\t%2u DW_CFA_val_offset_sf ", loff);
+ printreg((Dwarf_Signed) uval, config_data);
+ printf(" %" DW_PR_DSd , (signed long long)
+ ((sval2) * data_alignment_factor));
+ if (verbose) {
+ printf(" (%" DW_PR_DSd " * %d)", sval2,
+ (int) data_alignment_factor);
+ }
+ }
+ printf("\n");
+
+ break;
+ case DW_CFA_val_expression: /* DWARF3 */
+ /* instp is always 1 byte back, so we need +1
+ when we use it. See the final increment
+ of this for loop. */
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ {
+ Dwarf_Unsigned block_len =
+ local_dwarf_decode_u_leb128(instp + 1,
+ &uleblen);
+
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ printf
+ ("\t%2u DW_CFA_val_expression %" DW_PR_DUu
+ " expr block len %" DW_PR_DUu "\n",
+ loff, uval,
+ block_len);
+ dump_block("\t\t", (char *) instp+1,
+ (Dwarf_Signed) block_len);
+ printf("\n");
+ if(verbose) {
+ struct esb_s exprstring;
+ esb_constructor(&exprstring);
+ get_string_from_locs(dbg,
+ instp+1,block_len,addr_size,&exprstring);
+ printf("\t\t%s\n",esb_get_string(&exprstring));
+ esb_destructor(&exprstring);
+ }
+ instp += block_len;
+ len -= block_len;
+ off += block_len;
+ }
+
+
+ break;
+
+
+#ifdef DW_CFA_GNU_window_save
+ case DW_CFA_GNU_window_save:{
+ /* no information: this just tells unwinder to
+ restore the window registers from the previous
+ frame's window save area */
+ printf("\t%2u DW_CFA_GNU_window_save \n", loff);
+ }
+ break;
+#endif
+#ifdef DW_CFA_GNU_negative_offset_extended
+ case DW_CFA_GNU_negative_offset_extended:{
+ printf("\t%2u DW_CFA_GNU_negative_offset_extended \n",
+ loff);
+ }
+ break;
+#endif
+#ifdef DW_CFA_GNU_args_size
+ /* single uleb128 is the current arg area size in
+ bytes. no register exists yet to save this in */
+ case DW_CFA_GNU_args_size:{
+ Dwarf_Unsigned lreg = 0;
+
+ /* instp is always 1 byte back, so we need +1
+ when we use it. See the final increment
+ of this for loop. */
+ lreg = local_dwarf_decode_u_leb128(instp + 1,
+ &uleblen);
+ printf("\t%2u DW_CFA_GNU_args_size arg size: %"
+ DW_PR_DUu "\n",
+ loff, lreg);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ }
+ break;
+#endif
+
+ default:
+ printf(" %u Unexpected op 0x%x: \n",
+ loff, (unsigned int) bottom);
+ len = 0;
+ break;
+ }
+ }
+ instp++;
+ len--;
+ off++;
+ }
+}
+
+/* Print our register names for the cases we have a name.
+ Delegate to the configure code to actually do the print.
+*/
+void
+printreg(Dwarf_Signed reg, struct dwconf_s *config_data)
+{
+ print_reg_from_config_data(reg, config_data);
+}
+
+/* Actually does the printing of a rule in the table.
+ This may print something or may print nothing! */
+static void
+print_one_frame_reg_col(Dwarf_Debug dbg,
+ Dwarf_Unsigned rule_id,
+ Dwarf_Small value_type,
+ Dwarf_Unsigned reg_used,
+ Dwarf_Half addr_size,
+ struct dwconf_s *config_data,
+ Dwarf_Signed offset_relevant,
+ Dwarf_Signed offset,
+ Dwarf_Ptr block_ptr)
+{
+ char *type_title = "";
+ int print_type_title = 1;
+
+ if (check_frames_extended) {
+ return;
+ }
+
+ if (config_data->cf_interface_number == 2)
+ print_type_title = 0;
+
+ switch (value_type) {
+ case DW_EXPR_OFFSET:
+ type_title = "off";
+ goto preg2;
+ case DW_EXPR_VAL_OFFSET:
+ type_title = "valoff";
+
+ preg2:
+ if (reg_used == config_data->cf_initial_rule_value) {
+ break;
+ }
+ if (print_type_title)
+ printf("<%s ", type_title);
+ printreg((Dwarf_Signed) rule_id, config_data);
+ printf("=");
+ if (offset_relevant == 0) {
+ printreg((Dwarf_Signed) reg_used, config_data);
+ printf(" ");
+ } else {
+ printf("%02" DW_PR_DSd , offset);
+ printf("(");
+ printreg((Dwarf_Signed) reg_used, config_data);
+ printf(") ");
+ }
+ if (print_type_title)
+ printf("%s", "> ");
+ break;
+ case DW_EXPR_EXPRESSION:
+ type_title = "expr";
+ goto pexp2;
+ case DW_EXPR_VAL_EXPRESSION:
+ type_title = "valexpr";
+
+ pexp2:
+ if (print_type_title)
+ printf("<%s ", type_title);
+ printreg((Dwarf_Signed) rule_id, config_data);
+ printf("=");
+ printf("expr-block-len=%" DW_PR_DSd , offset);
+ if (print_type_title)
+ printf("%s", "> ");
+ if (verbose) {
+ char pref[40];
+
+ strcpy(pref, "<");
+ strcat(pref, type_title);
+ strcat(pref, "bytes:");
+ dump_block(pref, block_ptr, offset);
+ printf("%s", "> ");
+ if(verbose) {
+ struct esb_s exprstring;
+ esb_constructor(&exprstring);
+ get_string_from_locs(dbg,
+ block_ptr,offset,addr_size,&exprstring);
+ printf("<expr:%s>",esb_get_string(&exprstring));
+ esb_destructor(&exprstring);
+ }
+ }
+ break;
+ default:
+ printf("Internal error in libdwarf, value type %d\n",
+ value_type);
+ exit(1);
+ }
+ return;
+}
+
+
+/* get all the data in .debug_frame (or .eh_frame).
+ The '3' versions mean print using the dwarf3 new interfaces.
+ The non-3 mean use the old interfaces.
+ All combinations of requests are possible. */
+extern void
+print_frames(Dwarf_Debug dbg, int print_debug_frame, int print_eh_frame,
+ struct dwconf_s *config_data)
+{
+ Dwarf_Signed i;
+ int fres = 0;
+ Dwarf_Half address_size = 0;
+ int framed = 0;
+ void * map_lowpc_to_name = 0;
+
+ current_section_id = DEBUG_FRAME;
+
+ /* The address size here will not be right for all frames.
+ Only in DWARF4 is there a real address size known
+ in the frame data itself. If any DIE
+ is known then a real address size can be gotten from
+ dwarf_get_die_address_size(). */
+ fres = dwarf_get_address_size(dbg, &address_size, &err);
+ if (fres != DW_DLV_OK) {
+ print_error(dbg, "dwarf_get_address_size", fres, err);
+ }
+ for (framed = 0; framed < 2; ++framed) {
+ Dwarf_Cie *cie_data = NULL;
+ Dwarf_Signed cie_element_count = 0;
+ Dwarf_Fde *fde_data = NULL;
+ Dwarf_Signed fde_element_count = 0;
+ int frame_count = 0;
+ int cie_count = 0;
+ int all_cus_seen = 0;
+ void * lowpcSet = 0;
+ char *framename = 0;
+ int silent_if_missing = 0;
+ int is_eh = 0;
+
+ if (framed == 0) {
+ if (!print_debug_frame) {
+ continue;
+ }
+ framename = ".debug_frame";
+ /* Big question here is how to print all the info?
+ Can print the logical matrix, but that is huge,
+ though could skip lines that don't change.
+ Either that, or print the instruction statement program
+ that describes the changes. */
+ fres = dwarf_get_fde_list(dbg, &cie_data, &cie_element_count,
+ &fde_data, &fde_element_count, &err);
+ if(check_harmless) {
+ print_any_harmless_errors(dbg);
+ }
+ } else {
+ if (!print_eh_frame) {
+ continue;
+ }
+ is_eh = 1;
+ /* This is gnu g++ exceptions in a .eh_frame section. Which
+ is just like .debug_frame except that the empty, or
+ 'special' CIE_id is 0, not -1 (to distinguish fde from
+ cie). And the augmentation is "eh". As of egcs-1.1.2
+ anyway. A non-zero cie_id is in a fde and is the
+ difference between the fde address and the beginning of
+ the cie it belongs to. This makes sense as this is
+ intended to be referenced at run time, and is part of
+ the running image. For more on augmentation strings, see
+ libdwarf/dwarf_frame.c. */
+
+ /* Big question here is how to print all the info?
+ Can print the logical matrix, but that is huge,
+ though could skip lines that don't change.
+ Either that, or print the instruction statement program
+ that describes the changes. */
+ silent_if_missing = 1;
+ framename = ".eh_frame";
+ fres = dwarf_get_fde_list_eh(dbg, &cie_data,
+ &cie_element_count, &fde_data,
+ &fde_element_count, &err);
+ if(check_harmless) {
+ print_any_harmless_errors(dbg);
+ }
+ }
+
+ /* Do not print any frame info if in check mode */
+ if (check_frames) {
+ addr_map_destroy(lowpcSet);
+ lowpcSet = 0;
+ continue;
+ }
+
+ if (fres == DW_DLV_ERROR) {
+ printf("\n%s\n", framename);
+ print_error(dbg, "dwarf_get_fde_list", fres, err);
+ } else if (fres == DW_DLV_NO_ENTRY) {
+ if (!silent_if_missing) {
+ printf("\n%s\n", framename);
+ }
+ /* no frame information */
+ } else { /* DW_DLV_OK */
+ /* Do not print if in check mode */
+ if (!check_frames_extended) {
+ printf("\n%s\n", framename);
+ printf("\nfde:\n");
+ }
+
+ for (i = 0; i < fde_element_count; i++) {
+ print_one_fde(dbg, fde_data[i],
+ i, cie_data, cie_element_count,
+ address_size, is_eh, config_data,
+ &map_lowpc_to_name,
+ &lowpcSet,
+ &all_cus_seen);
+ ++frame_count;
+ if(frame_count >= break_after_n_units) {
+ break;
+ }
+ }
+ /* Print the cie set. */
+ if (verbose) {
+ /* Do not print if in check mode */
+ if (!check_frames_extended) {
+ printf("\ncie:\n");
+ }
+ for (i = 0; i < cie_element_count; i++) {
+ print_one_cie(dbg, cie_data[i], i, address_size,
+ config_data);
+ ++cie_count;
+ if(cie_count >= break_after_n_units) {
+ break;
+ }
+ }
+ }
+ dwarf_fde_cie_list_dealloc(dbg, cie_data, cie_element_count,
+ fde_data, fde_element_count);
+ }
+ addr_map_destroy(lowpcSet);
+ lowpcSet = 0;
+ }
+ if (current_cu_die_for_print_frames) {
+ dwarf_dealloc(dbg, current_cu_die_for_print_frames, DW_DLA_DIE);
+ current_cu_die_for_print_frames = 0;
+ }
+ addr_map_destroy(map_lowpc_to_name);
+}
+
diff --git a/dwarfdump/print_frames.h b/dwarfdump/print_frames.h
new file mode 100644
index 0000000..2a133d8
--- /dev/null
+++ b/dwarfdump/print_frames.h
@@ -0,0 +1,47 @@
+/*
+ Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+ $Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_frames.h,v 1.2 2006/04/17 00:09:56 davea Exp $ */
+
+int print_one_cie(Dwarf_Debug dbg, Dwarf_Cie cie,
+ Dwarf_Unsigned cie_index,
+ Dwarf_Half address_size,
+ struct dwconf_s * config_data);
+
+void get_string_from_locs(Dwarf_Debug dbg,
+ Dwarf_Ptr bytes_in,
+ Dwarf_Unsigned block_len,
+ Dwarf_Half addr_size,
+ struct esb_s *out_string);
+
diff --git a/dwarfdump/print_lines.c b/dwarfdump/print_lines.c
new file mode 100644
index 0000000..4b33994
--- /dev/null
+++ b/dwarfdump/print_lines.c
@@ -0,0 +1,433 @@
+
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2011 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address. */
+
+#include "globals.h"
+#include "naming.h"
+#include "dwconf.h"
+#include "esb.h"
+#include "uri.h"
+#include <ctype.h>
+
+#include "print_sections.h"
+
+/*
+ Print line number information:
+ [line] [address] <new statement>
+ new basic-block
+ filename
+*/
+
+
+static void
+print_source_intro(Dwarf_Die cu_die)
+{
+ Dwarf_Off off = 0;
+ int ores = dwarf_dieoffset(cu_die, &off, &err);
+
+ if (ores == DW_DLV_OK) {
+ printf("Source lines (from CU-DIE at .debug_info offset 0x%"
+ DW_PR_XZEROS DW_PR_DUx "):\n",
+ (Dwarf_Unsigned) off);
+ } else {
+ printf("Source lines (for the CU-DIE at unknown location):\n");
+ }
+}
+
+static void
+record_line_error(const char *where, Dwarf_Error err)
+{
+ char tmp_buff[500];
+ if(check_lines && checking_this_compiler()) {
+ snprintf(tmp_buff, sizeof(tmp_buff),
+ "Error getting line details calling %s dwarf error is %s",
+ where,dwarf_errmsg(err));
+ DWARF_CHECK_ERROR(lines_result,tmp_buff);
+ }
+}
+
+extern void
+print_line_numbers_this_cu(Dwarf_Debug dbg, Dwarf_Die cu_die)
+{
+ Dwarf_Signed linecount = 0;
+ Dwarf_Line *linebuf = NULL;
+ Dwarf_Signed i = 0;
+ Dwarf_Addr pc = 0;
+ Dwarf_Unsigned lineno = 0;
+ Dwarf_Unsigned column = 0;
+
+ Dwarf_Bool newstatement = 0;
+ Dwarf_Bool lineendsequence = 0;
+ Dwarf_Bool new_basic_block = 0;
+ int lres = 0;
+ int sres = 0;
+ int ares = 0;
+ int lires = 0;
+ int cores = 0;
+ int line_errs = 0;
+
+ Dwarf_Bool SkipRecord = FALSE;
+
+ current_section_id = DEBUG_LINE;
+
+ /* line_flag is TRUE */
+
+ if (do_print_dwarf) {
+ printf("\n.debug_line: line number info for a single cu\n");
+ }
+ if (verbose > 1) {
+ int errcount = 0;
+ print_source_intro(cu_die);
+ print_one_die(dbg, cu_die,
+ /* print_information= */ 1,
+ /* indent level */0,
+ /* srcfiles= */ 0, /* cnt= */ 0,
+ /* ignore_die_stack= */TRUE);
+ DWARF_CHECK_COUNT(lines_result,1);
+ lres = dwarf_print_lines(cu_die, &err,&errcount);
+ if(errcount > 0) {
+ DWARF_ERROR_COUNT(lines_result,errcount);
+ DWARF_CHECK_COUNT(lines_result,(errcount-1));
+ }
+ if (lres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_srclines details", lres, err);
+ }
+ return;
+ }
+
+ if(check_lines && checking_this_compiler()) {
+ DWARF_CHECK_COUNT(lines_result,1);
+ dwarf_check_lineheader(cu_die,&line_errs);
+ if(line_errs > 0) {
+ DWARF_CHECK_ERROR_PRINT_CU();
+ DWARF_ERROR_COUNT(lines_result,line_errs);
+ DWARF_CHECK_COUNT(lines_result,(line_errs-1));
+ }
+ }
+ lres = dwarf_srclines(cu_die, &linebuf, &linecount, &err);
+ if (lres == DW_DLV_ERROR) {
+ /* Do not terminate processing */
+ if (check_decl_file) {
+ DWARF_CHECK_COUNT(decl_file_result,1);
+ DWARF_CHECK_ERROR2(decl_file_result,"dwarf_srclines",
+ dwarf_errmsg(err));
+ record_dwarf_error = FALSE; /* Clear error condition */
+ } else {
+ print_error(dbg, "dwarf_srclines", lres, err);
+ }
+ } else if (lres == DW_DLV_NO_ENTRY) {
+ /* no line information is included */
+ } else {
+ struct esb_s lastsrc;;
+ esb_constructor(&lastsrc);
+ if (do_print_dwarf) {
+ print_source_intro(cu_die);
+ if (verbose) {
+ print_one_die(dbg, cu_die,
+ /* print_information= */ TRUE,
+ /* indent_level= */ 0,
+ /* srcfiles= */ 0, /* cnt= */ 0,
+ /* ignore_die_stack= */TRUE);
+ }
+ printf("\n<pc> [row,col] "
+ "NS BB ET PE EB IS= DI= uri: \"filepath\"\n");
+ printf("NS new statement, BB new basic block, "
+ "ET end of text sequence\n");
+ printf("PE prologue end, EB epilogue begin\n");
+ printf("IA=val ISA number, DI=val discriminator value\n");
+ }
+ for (i = 0; i < linecount; i++) {
+ Dwarf_Line line = linebuf[i];
+ string filename = 0;
+ int nsres = 0;
+ Dwarf_Bool found_line_error = FALSE;
+ Dwarf_Bool has_is_addr_set = FALSE;
+ char *where = NULL;
+
+ if (check_decl_file && checking_this_compiler()) {
+ /* A line record with addr=0 was detected */
+ if (SkipRecord) {
+ /* Skip records that do not have ís_addr_set' */
+ ares = dwarf_line_is_addr_set(line, &has_is_addr_set, &err);
+ if (ares == DW_DLV_OK && has_is_addr_set) {
+ SkipRecord = FALSE;
+ }
+ else {
+ /* Keep ignoring records until we have
+ one with 'is_addr_set' */
+ continue;
+ }
+ }
+ }
+
+ if(check_lines && checking_this_compiler()) {
+ DWARF_CHECK_COUNT(lines_result,1);
+ }
+ filename = "<unknown>";
+ sres = dwarf_linesrc(line, &filename, &err);
+ if (sres == DW_DLV_ERROR) {
+ /* Do not terminate processing */
+ where = "dwarf_linesrc()";
+ record_line_error(where,err);
+ found_line_error = TRUE;
+ }
+
+ ares = dwarf_lineaddr(line, &pc, &err);
+
+ if (ares == DW_DLV_ERROR) {
+ /* Do not terminate processing */
+ where = "dwarf_lineaddr()";
+ record_line_error(where,err);
+ found_line_error = TRUE;
+ }
+ if (ares == DW_DLV_NO_ENTRY) {
+ pc = 0;
+ }
+ lires = dwarf_lineno(line, &lineno, &err);
+ if (lires == DW_DLV_ERROR) {
+ /* Do not terminate processing */
+ where = "dwarf_lineno()";
+ record_line_error(where,err);
+ found_line_error = TRUE;
+ }
+ if (lires == DW_DLV_NO_ENTRY) {
+ lineno = -1LL;
+ }
+ cores = dwarf_lineoff_b(line, &column, &err);
+ if (cores == DW_DLV_ERROR) {
+ /* Do not terminate processing */
+ where = "dwarf_lineoff()";
+ record_line_error(where,err);
+ found_line_error = TRUE;
+ }
+ if (cores == DW_DLV_NO_ENTRY) {
+ /* Zero was always the correct default, meaning
+ the left edge. DWARF2/3/4 spec sec 6.2.2 */
+ column = 0;
+ }
+
+ /* Process any possible error condition, though
+ we won't be at the first such error. */
+ if (check_decl_file && checking_this_compiler()) {
+ DWARF_CHECK_COUNT(decl_file_result,1);
+ if (found_line_error) {
+ DWARF_CHECK_ERROR2(decl_file_result,where,dwarf_errmsg(err));
+ } else if (do_check_dwarf) {
+ /* Check the address lies with a valid [lowPC:highPC]
+ in the .text section*/
+ if (IsValidInBucketGroup(pRangesInfo,pc)) {
+ /* Valid values; do nothing */
+ } else {
+ /* At this point may be we are dealing with
+ a linkonce symbol. The problem we have here
+ is we have consumed the deug_info section
+ and we are dealing just with the records
+ from the .debug_line, so no PU_name is
+ available and no high_pc. Traverse the linkonce
+ table if try to match the pc value with
+ one of those ranges.
+ */
+ if(check_lines && checking_this_compiler()) {
+ DWARF_CHECK_COUNT(lines_result,1);
+ }
+ if (FindAddressInBucketGroup(pLinkonceInfo,pc)){
+ /* Valid values; do nothing */
+ } else {
+ /* The SN Systems Linker generates
+ line records
+ with addr=0, when dealing with linkonce
+ symbols and no stripping */
+ if (pc) {
+ char addr_tmp[100];
+ if(check_lines && checking_this_compiler()) {
+ snprintf(addr_tmp,sizeof(addr_tmp),
+ ".debug_line: Address"
+ " 0x%" DW_PR_XZEROS DW_PR_DUx
+ " outside a valid .text range",pc);
+ DWARF_CHECK_ERROR(lines_result,
+ addr_tmp);
+ }
+ } else {
+ SkipRecord = TRUE;
+ }
+ }
+ }
+ /* Check the last record for the .debug_line,
+ the one created by DW_LNE_end_sequence,
+ is the same as the high_pc
+ address for the last known user program
+ unit (PU) */
+ if ((i + 1 == linecount) &&
+ seen_PU_high_address) {
+ /* Ignore those PU that have been stripped
+ by the linker; their low_pc values are
+ set to -1 (snc linker only) */
+ /* It is perfectly sensible for a compiler
+ to leave a few bytes of NOP or other stuff
+ after the last instruction in a subprogram,
+ for cache-alignment or other purposes, so
+ a mismatch here is not necessarily
+ an error. */
+
+ if (check_lines && checking_this_compiler()) {
+ DWARF_CHECK_COUNT(lines_result,1);
+ if ((pc != PU_high_address) &&
+ (PU_base_address != elf_max_address)) {
+ char addr_tmp[100];
+ snprintf(addr_tmp,sizeof(addr_tmp),
+ ".debug_line: Address"
+ " 0x%" DW_PR_XZEROS DW_PR_DUx
+ " may be incorrect"
+ " as DW_LNE_end_sequence address",pc);
+ DWARF_CHECK_ERROR(lines_result,
+ addr_tmp);
+ }
+ }
+ }
+ }
+ }
+
+ /* Display the error information */
+ if (found_line_error || record_dwarf_error) {
+ if (check_verbose_mode) {
+ /* Print the record number for better error description */
+ printf("Record = %" DW_PR_DUu
+ " Addr = 0x%" DW_PR_XZEROS DW_PR_DUx
+ " [%4" DW_PR_DUu ",%2" DW_PR_DUu "] '%s'\n",
+ i, pc,lineno,column,filename);
+ /* Flush due to the redirection of stderr */
+ fflush(stdout);
+ /* The compilation unit was already printed */
+ if (!check_decl_file) {
+ PRINT_CU_INFO();
+ }
+ }
+ record_dwarf_error = FALSE;
+ /* Due to a fatal error, skip current record */
+ if (found_line_error) {
+ continue;
+ }
+ }
+ if (do_print_dwarf) {
+ printf("0x%08" DW_PR_DUx
+ " [%4" DW_PR_DUu ",%2" DW_PR_DUu "]", pc, lineno,
+ column);
+ }
+
+ nsres = dwarf_linebeginstatement(line, &newstatement, &err);
+ if (nsres == DW_DLV_OK) {
+ if (newstatement && do_print_dwarf) {
+ printf(" %s","NS");
+ }
+ } else if (nsres == DW_DLV_ERROR) {
+ print_error(dbg, "linebeginstatment failed", nsres, err);
+ }
+ nsres = dwarf_lineblock(line, &new_basic_block, &err);
+ if (nsres == DW_DLV_OK) {
+ if (new_basic_block && do_print_dwarf) {
+ printf(" %s","BB");
+ }
+ } else if (nsres == DW_DLV_ERROR) {
+ print_error(dbg, "lineblock failed", nsres, err);
+ }
+ nsres = dwarf_lineendsequence(line, &lineendsequence, &err);
+ if (nsres == DW_DLV_OK) {
+ if (lineendsequence && do_print_dwarf) {
+ printf(" %s", "ET");
+ }
+ } else if (nsres == DW_DLV_ERROR) {
+ print_error(dbg, "lineblock failed", nsres, err);
+ }
+ if(do_print_dwarf) {
+ Dwarf_Bool prologue_end = 0;
+ Dwarf_Bool epilogue_begin = 0;
+ Dwarf_Unsigned isa = 0;
+ Dwarf_Unsigned discriminator = 0;
+ int disres = dwarf_prologue_end_etc(line,
+ &prologue_end,&epilogue_begin,
+ &isa,&discriminator,&err);
+ if (disres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_prologue_end_etc() failed",
+ disres, err);
+ }
+ if(prologue_end) {
+ printf(" PE");
+ }
+ if(epilogue_begin) {
+ printf(" EB");
+ }
+ if(isa) {
+ printf(" IS=0x%" DW_PR_DUx, isa);
+ }
+ if(discriminator) {
+ printf(" DI=0x%" DW_PR_DUx, discriminator);
+ }
+ }
+
+
+ if (i > 0 && verbose < 3 &&
+ strcmp(filename,esb_get_string(&lastsrc)) == 0) {
+ /* Do not print name. */
+ } else {
+ struct esb_s urs;
+ esb_constructor(&urs);
+ esb_append(&urs, " uri: \"");
+ translate_to_uri(filename,&urs);
+ esb_append(&urs,"\"");
+ if(do_print_dwarf) {
+ printf("%s",esb_get_string(&urs));
+ }
+ esb_destructor(&urs);
+ esb_empty_string(&lastsrc);
+ esb_append(&lastsrc,filename);
+ }
+ if (sres == DW_DLV_OK) {
+ dwarf_dealloc(dbg, filename, DW_DLA_STRING);
+ }
+ if (do_print_dwarf) {
+ printf("\n");
+ }
+ }
+ esb_destructor(&lastsrc);
+ dwarf_srclines_dealloc(dbg, linebuf, linecount);
+ }
+}
diff --git a/dwarfdump/print_locs.c b/dwarfdump/print_locs.c
new file mode 100644
index 0000000..c7cf99f
--- /dev/null
+++ b/dwarfdump/print_locs.c
@@ -0,0 +1,128 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include "globals.h"
+#include "naming.h"
+#include "dwconf.h"
+#include "esb.h"
+
+#include "print_sections.h"
+#include "print_frames.h"
+
+/* print data in .debug_loc
+ There is no guarantee this will work because we are assuming
+ that all bytes are valid loclist data, that there are no
+ odd padding or garbage bytes. In normal use one gets
+ into here via an offset from .debug_info, so it could be
+ that bytes not referenced from .debug_info are garbage
+ or even zero padding. So this can fail (error off) as such bytes
+ can lead dwarf_get_loclist_entry() astray.
+
+ It's also wrong because we don't know what CU or frame each
+ loclist is from, so we don't know the address_size for sure.
+*/
+extern void
+print_locs(Dwarf_Debug dbg)
+{
+ Dwarf_Unsigned offset = 0;
+ Dwarf_Addr hipc_offset = 0;
+ Dwarf_Addr lopc_offset = 0;
+ Dwarf_Ptr data = 0;
+ Dwarf_Unsigned entry_len = 0;
+ Dwarf_Unsigned next_entry = 0;
+ struct esb_s exprstring;
+ int index = 0;
+ int lres = 0;
+ int fres = 0;
+
+ /* This is sometimes wrong, we need a frame-specific size. */
+ Dwarf_Half address_size = 0;
+
+ current_section_id = DEBUG_LOC;
+
+ /* Do nothing if not printing. */
+ if (!do_print_dwarf) {
+ return;
+ }
+
+ fres = dwarf_get_address_size(dbg, &address_size, &err);
+ if (fres != DW_DLV_OK) {
+ print_error(dbg, "dwarf_get_address_size", fres, err);
+ }
+
+ printf("\n.debug_loc");
+
+ printf("\nFormat <i o b e l>: "
+ "index section-offset begin-addr end-addr length-of-block-entry\n");
+ esb_constructor(&exprstring);
+ while ((lres = dwarf_get_loclist_entry(dbg, offset,
+ &hipc_offset, &lopc_offset,
+ &data, &entry_len,
+ &next_entry,
+ &err)) == DW_DLV_OK) {
+ get_string_from_locs(dbg,data,entry_len,address_size,
+ &exprstring);
+ /* Display offsets */
+ if (display_offsets) {
+ ++index;
+ printf(" <iobel> [%8d] 0x%" DW_PR_XZEROS DW_PR_DUx,
+ index, offset);
+ if(verbose) {
+ printf(" <expr-off 0x%" DW_PR_XZEROS DW_PR_DUx ">",
+ next_entry - entry_len);
+ }
+ }
+ printf(" 0x%" DW_PR_XZEROS DW_PR_DUx
+ " 0x%" DW_PR_XZEROS DW_PR_DUx
+ " %8" DW_PR_DUu " %s\n",
+ (Dwarf_Unsigned) lopc_offset,
+ (Dwarf_Unsigned) hipc_offset, entry_len,
+ esb_get_string(&exprstring));
+ esb_empty_string(&exprstring);
+ offset = next_entry;
+ }
+ esb_destructor(&exprstring);
+ if (lres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_loclist_entry", lres, err);
+ }
+}
diff --git a/dwarfdump/print_macros.c b/dwarfdump/print_macros.c
new file mode 100644
index 0000000..0a36fc9
--- /dev/null
+++ b/dwarfdump/print_macros.c
@@ -0,0 +1,216 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2011 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include "globals.h"
+#include "naming.h"
+#include "dwconf.h"
+#include "esb.h"
+
+#include "print_sections.h"
+#include "print_frames.h"
+
+
+struct macro_counts_s {
+ long mc_start_file;
+ long mc_end_file;
+ long mc_define;
+ long mc_undef;
+ long mc_extension;
+ long mc_code_zero;
+ long mc_unknown;
+};
+
+static void
+print_one_macro_entry_detail(long i,
+ char *type,
+ struct Dwarf_Macro_Details_s *mdp)
+{
+ /* "DW_MACINFO_*: section-offset file-index [line] string\n" */
+ if (mdp->dmd_macro) {
+ printf("%3ld %s: %6" DW_PR_DUu " %2" DW_PR_DSd " [%4"
+ DW_PR_DSd "] \"%s\" \n",
+ i,
+ type,
+ (Dwarf_Unsigned)mdp->dmd_offset,
+ mdp->dmd_fileindex, mdp->dmd_lineno, mdp->dmd_macro);
+ } else {
+ printf("%3ld %s: %6" DW_PR_DUu " %2" DW_PR_DSd " [%4"
+ DW_PR_DSd "] 0\n",
+ i,
+ type,
+ (Dwarf_Unsigned)mdp->dmd_offset,
+ mdp->dmd_fileindex, mdp->dmd_lineno);
+ }
+
+}
+
+static void
+print_one_macro_entry(long i,
+ struct Dwarf_Macro_Details_s *mdp,
+ struct macro_counts_s *counts)
+{
+
+ switch (mdp->dmd_type) {
+ case 0:
+ counts->mc_code_zero++;
+ print_one_macro_entry_detail(i, "DW_MACINFO_type-code-0", mdp);
+ break;
+
+ case DW_MACINFO_start_file:
+ counts->mc_start_file++;
+ print_one_macro_entry_detail(i, "DW_MACINFO_start_file", mdp);
+ break;
+
+ case DW_MACINFO_end_file:
+ counts->mc_end_file++;
+ print_one_macro_entry_detail(i, "DW_MACINFO_end_file ", mdp);
+ break;
+
+ case DW_MACINFO_vendor_ext:
+ counts->mc_extension++;
+ print_one_macro_entry_detail(i, "DW_MACINFO_vendor_ext", mdp);
+ break;
+
+ case DW_MACINFO_define:
+ counts->mc_define++;
+ print_one_macro_entry_detail(i, "DW_MACINFO_define ", mdp);
+ break;
+
+ case DW_MACINFO_undef:
+ counts->mc_undef++;
+ print_one_macro_entry_detail(i, "DW_MACINFO_undef ", mdp);
+ break;
+
+ default:
+ {
+ char create_type[50]; /* More than large enough. */
+
+ counts->mc_unknown++;
+ snprintf(create_type, sizeof(create_type),
+ "DW_MACINFO_0x%x", mdp->dmd_type);
+ print_one_macro_entry_detail(i, create_type, mdp);
+ }
+ break;
+ }
+}
+
+/* print data in .debug_macinfo */
+/* FIXME: should print name of file whose index is in macro data
+ here -- somewhere. */
+/*ARGSUSED*/ extern void
+print_macinfo(Dwarf_Debug dbg)
+{
+ Dwarf_Off offset = 0;
+ Dwarf_Unsigned max = 0;
+ Dwarf_Signed count = 0;
+ long group = 0;
+ Dwarf_Macro_Details *maclist = NULL;
+ int lres = 0;
+
+ current_section_id = DEBUG_MACINFO;
+ if (!do_print_dwarf) {
+ return;
+ }
+
+ printf("\n.debug_macinfo\n");
+
+ while ((lres = dwarf_get_macro_details(dbg, offset,
+ max, &count, &maclist,
+ &err)) == DW_DLV_OK) {
+ long i = 0;
+ struct macro_counts_s counts;
+
+
+ memset(&counts, 0, sizeof(counts));
+
+ printf("\n");
+ printf("compilation-unit .debug_macinfo # %ld\n", group);
+ printf
+ ("num name section-offset file-index [line] \"string\"\n");
+ for (i = 0; i < count; i++) {
+ struct Dwarf_Macro_Details_s *mdp = &maclist[i];
+
+ print_one_macro_entry(i, mdp, &counts);
+ }
+
+ if (counts.mc_start_file == 0) {
+ printf
+ ("DW_MACINFO file count of zero is invalid DWARF2/3\n");
+ }
+ if (counts.mc_start_file != counts.mc_end_file) {
+ printf("Counts of DW_MACINFO file (%ld) end_file (%ld) "
+ "do not match!.\n",
+ counts.mc_start_file, counts.mc_end_file);
+ }
+ if (counts.mc_code_zero < 1) {
+ printf("Count of zeros in macro group should be non-zero "
+ "(1 preferred), count is %ld\n",
+ counts.mc_code_zero);
+ }
+ printf("Macro counts: start file %ld, "
+ "end file %ld, "
+ "define %ld, "
+ "undef %ld, "
+ "ext %ld, "
+ "code-zero %ld, "
+ "unknown %ld\n",
+ counts.mc_start_file,
+ counts.mc_end_file,
+ counts.mc_define,
+ counts.mc_undef,
+ counts.mc_extension,
+ counts.mc_code_zero, counts.mc_unknown);
+
+
+ /* int type= maclist[count - 1].dmd_type; */
+ /* ASSERT: type is zero */
+
+ offset = maclist[count - 1].dmd_offset + 1;
+ dwarf_dealloc(dbg, maclist, DW_DLA_STRING);
+ ++group;
+ }
+ if (lres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_macro_details", lres, err);
+ }
+}
+
diff --git a/dwarfdump/print_pubnames.c b/dwarfdump/print_pubnames.c
new file mode 100644
index 0000000..8018152
--- /dev/null
+++ b/dwarfdump/print_pubnames.c
@@ -0,0 +1,300 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+v Portions Copyright 2009-2011 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include "globals.h"
+#include "naming.h"
+#include "dwconf.h"
+#include "esb.h"
+#include "print_sections.h"
+
+/* This unifies the code for some error checks to
+ avoid code duplication.
+*/
+static void
+check_info_offset_sanity(char *sec,
+ char *field,
+ char *global,
+ Dwarf_Unsigned offset, Dwarf_Unsigned maxoff)
+{
+ if (maxoff == 0) {
+ /* Lets make a heuristic check. */
+ if (offset > 0xffffffff) {
+ printf("Warning: section %s %s %s offset 0x%"
+ DW_PR_XZEROS DW_PR_DUx " "
+ "exceptionally large \n",
+ sec, field, global, offset);
+ }
+ return;
+ }
+ if (offset >= maxoff) {
+ printf("Warning: section %s %s %s offset 0x%"
+ DW_PR_XZEROS DW_PR_DUx " "
+ "larger than max of 0x%" DW_PR_DUx "\n",
+ sec, field, global, offset, maxoff);
+ }
+}
+
+/* Unified pubnames style output.
+ The error checking here against maxoff may be useless
+ (in that libdwarf may return an error if the offset is bad
+ and we will not get called here).
+ But we leave it in nonetheless as it looks sensible.
+ In at least one gigantic executable such offsets turned out wrong.
+*/
+void
+print_pubname_style_entry(Dwarf_Debug dbg,
+ char *line_title,
+ char *name,
+ Dwarf_Unsigned die_off,
+ Dwarf_Unsigned cu_off,
+ Dwarf_Unsigned global_cu_offset,
+ Dwarf_Unsigned maxoff)
+{
+ Dwarf_Die die = NULL;
+ Dwarf_Off die_CU_off = 0;
+ int dres = 0;
+ int ddres = 0;
+ int cudres = 0;
+ char tmp_buf[100];
+
+ /* get die at die_off */
+ dres = dwarf_offdie(dbg, die_off, &die, &err);
+ if (dres != DW_DLV_OK) {
+ struct esb_s details;
+ esb_constructor(&details);
+ esb_append(&details,line_title);
+ esb_append(&details," dwarf_offdie : "
+ "die offset does not reference valid DIE. ");
+ snprintf(tmp_buf,sizeof(tmp_buf),"0x%" DW_PR_DUx, die_off);
+ esb_append(&details,tmp_buf);
+ esb_append(&details,".");
+ print_error(dbg, esb_get_string(&details), dres, err);
+ esb_destructor(&details);
+ }
+
+ /* get offset of die from its cu-header */
+ ddres = dwarf_die_CU_offset(die, &die_CU_off, &err);
+ if (ddres != DW_DLV_OK) {
+ struct esb_s details;
+ esb_constructor(&details);
+ esb_append(&details,line_title);
+ esb_append(&details," cannot get CU die offset");
+ print_error(dbg, esb_get_string(&details), dres, err);
+ esb_destructor(&details);
+ die_CU_off = 0;
+ }
+
+ /* Get die at offset cu_off to check its existence. */
+ {
+ Dwarf_Die cu_die = NULL;
+ cudres = dwarf_offdie(dbg, cu_off, &cu_die, &err);
+ if (cudres != DW_DLV_OK) {
+ struct esb_s details;
+ esb_constructor(&details);
+ esb_append(&details,line_title);
+ esb_append(&details," dwarf_offdie: "
+ "cu die offset does not reference valid CU DIE. ");
+ snprintf(tmp_buf,sizeof(tmp_buf),"0x%" DW_PR_DUx, cu_off);
+ esb_append(&details,tmp_buf);
+ esb_append(&details,".");
+ print_error(dbg, esb_get_string(&details), dres, err);
+ esb_destructor(&details);
+ } else {
+ /* It exists, all is well. */
+ dwarf_dealloc(dbg, cu_die, DW_DLA_DIE);
+ }
+ }
+ /* Display offsets */
+ if (display_offsets) {
+ /* Print 'name'at the end for better layout */
+ printf("%s die-in-sect 0x%" DW_PR_XZEROS DW_PR_DUx
+ ", cu-in-sect 0x%" DW_PR_XZEROS DW_PR_DUx ","
+ " die-in-cu 0x%" DW_PR_XZEROS DW_PR_DUx
+ ", cu-header-in-sect 0x%" DW_PR_XZEROS DW_PR_DUx ,
+ line_title,
+ die_off, cu_off,
+ (Dwarf_Unsigned) die_CU_off,
+ /* Following is absolute offset of the ** beginning of the
+ cu */
+ (Dwarf_Signed) (die_off - die_CU_off));
+ }
+
+ if ((die_off - die_CU_off) != global_cu_offset) {
+ printf(" error: real cuhdr 0x%" DW_PR_XZEROS DW_PR_DUx,
+ global_cu_offset);
+ exit(1);
+ }
+
+ /* Display offsets */
+ if (display_offsets && verbose) {
+ printf(" cuhdr 0x%" DW_PR_XZEROS DW_PR_DUx , global_cu_offset);
+ }
+
+ /* Print 'name'at the end for better layout */
+ printf(" '%s'\n",name);
+
+ dwarf_dealloc(dbg, die, DW_DLA_DIE);
+
+ check_info_offset_sanity(line_title,
+ "die offset", name, die_off, maxoff);
+ check_info_offset_sanity(line_title,
+ "die cu offset", name, die_CU_off, maxoff);
+ check_info_offset_sanity(line_title,
+ "cu offset", name,
+ (die_off - die_CU_off), maxoff);
+
+}
+
+/* Get all the data in .debug_pubnames */
+void
+print_pubnames(Dwarf_Debug dbg)
+{
+ Dwarf_Global *globbuf = NULL;
+ Dwarf_Signed count = 0;
+ Dwarf_Signed i = 0;
+ Dwarf_Off die_off = 0;
+ Dwarf_Off cu_off = 0;
+
+ /* Offset to previous CU */
+ Dwarf_Off prev_cu_off = elf_max_address;
+
+ char *name = 0;
+ int res = 0;
+
+ current_section_id = DEBUG_PUBNAMES;
+ if (do_print_dwarf) {
+ printf("\n.debug_pubnames\n");
+ }
+ res = dwarf_get_globals(dbg, &globbuf, &count, &err);
+ if (res == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_globals", res, err);
+ } else if (res == DW_DLV_NO_ENTRY) {
+ /* (err == 0 && count == DW_DLV_NOCOUNT) means there are no
+ pubnames. */
+ } else {
+ Dwarf_Unsigned maxoff = get_info_max_offset(dbg);
+
+ for (i = 0; i < count; i++) {
+ int nres = 0;
+ int cures3 = 0;
+ Dwarf_Off global_cu_off = 0;
+
+ nres = dwarf_global_name_offsets(globbuf[i],
+ &name, &die_off, &cu_off,
+ &err);
+ deal_with_name_offset_err(dbg, "dwarf_global_name_offsets",
+ name, die_off, nres, err);
+ cures3 = dwarf_global_cu_offset(globbuf[i],
+ &global_cu_off, &err);
+ if (cures3 != DW_DLV_OK) {
+ print_error(dbg, "dwarf_global_cu_offset", cures3, err);
+ }
+
+ if (check_pubname_attr) {
+ Dwarf_Bool has_attr;
+ int ares;
+ int dres;
+ Dwarf_Die die;
+
+ /* We are processing a new set of pubnames
+ for a different CU; get the producer ID, at 'cu_off'
+ to see if we need to skip these pubnames */
+ if (cu_off != prev_cu_off) {
+ char *producer_name = 0;
+
+ /* Record offset for previous CU */
+ prev_cu_off = cu_off;
+
+ dres = dwarf_offdie(dbg, cu_off, &die, &err);
+ if (dres != DW_DLV_OK) {
+ print_error(dbg, "print pubnames: dwarf_offdie a", dres,err);
+ }
+
+ /* Get producer name for this CU and update compiler list */
+ get_producer_name(dbg,die,err,&producer_name);
+ update_compiler_target(producer_name);
+
+ dwarf_dealloc(dbg, die, DW_DLA_DIE);
+ }
+
+ /* get die at die_off */
+ dres = dwarf_offdie(dbg, die_off, &die, &err);
+ if (dres != DW_DLV_OK) {
+ print_error(dbg, "print pubnames: dwarf_offdie b", dres, err);
+ }
+
+
+ ares =
+ dwarf_hasattr(die, DW_AT_external, &has_attr, &err);
+ if (ares == DW_DLV_ERROR) {
+ print_error(dbg, "hassattr on DW_AT_external", ares,
+ err);
+ }
+
+ /* Check for specific compiler */
+ if (checking_this_compiler()) {
+ DWARF_CHECK_COUNT(pubname_attr_result,1);
+ if (ares == DW_DLV_OK && has_attr) {
+ /* Should the value of flag be examined? */
+ } else {
+ DWARF_CHECK_ERROR2(pubname_attr_result,name,
+ "pubname does not have DW_AT_external");
+ }
+ }
+ dwarf_dealloc(dbg, die, DW_DLA_DIE);
+ }
+
+ /* Now print pubname, after the test */
+ if (do_print_dwarf || (record_dwarf_error && check_verbose_mode)) {
+ print_pubname_style_entry(dbg,
+ "global",
+ name, die_off, cu_off,
+ global_cu_off, maxoff);
+ record_dwarf_error = FALSE; /* Clear error condition */
+ }
+
+ }
+ dwarf_globals_dealloc(dbg, globbuf, count);
+ }
+} /* print_pubnames() */
+
diff --git a/dwarfdump/print_ranges.c b/dwarfdump/print_ranges.c
new file mode 100644
index 0000000..aee55e0
--- /dev/null
+++ b/dwarfdump/print_ranges.c
@@ -0,0 +1,106 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2011 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include "globals.h"
+#include "naming.h"
+#include "dwconf.h"
+#include "esb.h"
+#include "print_sections.h"
+
+static struct esb_s esb_string;
+
+/* Because we do not know what DIE is involved, if the
+ object being printed has different address sizes
+ in different compilation units this will not work
+ properly: anything could happen. */
+extern void
+print_ranges(Dwarf_Debug dbg)
+{
+ Dwarf_Unsigned off = 0;
+ int group_number = 0;
+ int wasdense = 0;
+
+ current_section_id = DEBUG_RANGES;
+ if (!do_print_dwarf) {
+ return;
+ }
+ printf("\n.debug_ranges\n");
+
+ /* Turn off dense, we do not want print_ranges_list_to_extra
+ to use dense form here. */
+ wasdense = dense;
+ dense = 0;
+ for(;;) {
+ Dwarf_Ranges *rangeset = 0;
+ Dwarf_Signed rangecount = 0;
+ Dwarf_Unsigned bytecount = 0;
+
+ /* We do not know what DIE is involved, we use
+ the older call here. */
+ int rres = dwarf_get_ranges(dbg,off,&rangeset,
+ &rangecount,&bytecount,&err);
+ if(rres == DW_DLV_OK) {
+ char *val = 0;
+ printf(" Ranges group %d:\n",group_number);
+ esb_empty_string(&esb_string);
+ print_ranges_list_to_extra(dbg,off,
+ rangeset,rangecount,bytecount,
+ &esb_string);
+ dwarf_ranges_dealloc(dbg,rangeset,rangecount);
+ val = esb_get_string(&esb_string);
+ printf("%s",val);
+ ++group_number;
+ } else if (rres == DW_DLV_NO_ENTRY) {
+ printf("End of .debug_ranges.\n");
+ break;
+ } else {
+ /* ERROR, which does not quite mean a real error,
+ as we might just be misaligned reading things without
+ a DW_AT_ranges offset.*/
+ printf("End of .debug_ranges..\n");
+ break;
+ }
+ off += bytecount;
+ }
+ dense = wasdense;
+}
diff --git a/dwarfdump/print_reloc.c b/dwarfdump/print_reloc.c
new file mode 100644
index 0000000..35a1574
--- /dev/null
+++ b/dwarfdump/print_reloc.c
@@ -0,0 +1,1150 @@
+/*
+ Copyright (C) 2000,2004,2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
+ Portions Copyright (C) 2011 SN Systems Ltd. All Rights Reserved
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_reloc.c,v 1.11 2005/08/04 05:09:37 davea Exp $ */
+
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+
+
+
+#include "globals.h"
+#include "print_reloc.h"
+
+#define DW_SECTION_REL_DEBUG_NUM 9 /* Number of sections */
+/* .debug_abbrev should never have a relocation applied to it as it
+ never refers to another section! (other sections refer to
+ .debug_abbrev) */
+
+#define DW_SECTNAME_RELA_DEBUG ".rela.debug_"
+#define DW_SECTNAME_RELA_DEBUG_INFO ".rela.debug_info"
+#define DW_SECTNAME_RELA_DEBUG_LINE ".rela.debug_line"
+#define DW_SECTNAME_RELA_DEBUG_PUBNAMES ".rela.debug_pubnames"
+#define DW_SECTNAME_RELA_DEBUG_ABBREV ".rela.debug_abbrev"
+#define DW_SECTNAME_RELA_DEBUG_ARANGES ".rela.debug_aranges"
+#define DW_SECTNAME_RELA_DEBUG_FRAME ".rela.debug_frame"
+#define DW_SECTNAME_RELA_DEBUG_LOC ".rela.debug_loc"
+#define DW_SECTNAME_RELA_DEBUG_RANGES ".rela.debug_ranges"
+#define DW_SECTNAME_RELA_DEBUG_TYPES ".rela.debug_types"
+
+#define DW_SECTNAME_REL_DEBUG ".rel.debug_"
+#define DW_SECTNAME_REL_DEBUG_INFO ".rel.debug_info"
+#define DW_SECTNAME_REL_DEBUG_LINE ".rel.debug_line"
+#define DW_SECTNAME_REL_DEBUG_PUBNAMES ".rel.debug_pubnames"
+#define DW_SECTNAME_REL_DEBUG_ABBREV ".rel.debug_abbrev"
+#define DW_SECTNAME_REL_DEBUG_ARANGES ".rel.debug_aranges"
+#define DW_SECTNAME_REL_DEBUG_FRAME ".rel.debug_frame"
+#define DW_SECTNAME_REL_DEBUG_LOC ".rel.debug_loc"
+#define DW_SECTNAME_REL_DEBUG_RANGES ".rel.debug_ranges"
+#define DW_SECTNAME_REL_DEBUG_TYPES ".rel.debug_types"
+
+
+#define STRING_FOR_DUPLICATE " duplicate"
+#define STRING_FOR_NULL " null"
+
+static char *sectnames[] = {
+ DW_SECTNAME_REL_DEBUG_INFO,
+ DW_SECTNAME_REL_DEBUG_LINE,
+ DW_SECTNAME_REL_DEBUG_PUBNAMES,
+ DW_SECTNAME_REL_DEBUG_ABBREV,
+ DW_SECTNAME_REL_DEBUG_ARANGES,
+ DW_SECTNAME_REL_DEBUG_FRAME,
+ DW_SECTNAME_REL_DEBUG_LOC,
+ DW_SECTNAME_REL_DEBUG_RANGES,
+ DW_SECTNAME_REL_DEBUG_TYPES,
+};
+static char *sectnamesa[] = {
+ DW_SECTNAME_RELA_DEBUG_INFO,
+ DW_SECTNAME_RELA_DEBUG_LINE,
+ DW_SECTNAME_RELA_DEBUG_PUBNAMES,
+ DW_SECTNAME_RELA_DEBUG_ABBREV,
+ DW_SECTNAME_RELA_DEBUG_ARANGES,
+ DW_SECTNAME_RELA_DEBUG_FRAME,
+ DW_SECTNAME_RELA_DEBUG_LOC,
+ DW_SECTNAME_RELA_DEBUG_RANGES,
+ DW_SECTNAME_RELA_DEBUG_TYPES,
+};
+
+static char *error_msg_duplicate[] = {
+ DW_SECTNAME_REL_DEBUG_INFO STRING_FOR_DUPLICATE,
+ DW_SECTNAME_REL_DEBUG_LINE STRING_FOR_DUPLICATE,
+ DW_SECTNAME_REL_DEBUG_PUBNAMES STRING_FOR_DUPLICATE,
+ DW_SECTNAME_REL_DEBUG_ABBREV STRING_FOR_DUPLICATE,
+ DW_SECTNAME_REL_DEBUG_ARANGES STRING_FOR_DUPLICATE,
+ DW_SECTNAME_REL_DEBUG_FRAME STRING_FOR_DUPLICATE,
+ DW_SECTNAME_REL_DEBUG_LOC STRING_FOR_DUPLICATE,
+ DW_SECTNAME_REL_DEBUG_RANGES STRING_FOR_DUPLICATE,
+ DW_SECTNAME_REL_DEBUG_TYPES STRING_FOR_DUPLICATE,
+};
+
+static char *error_msg_null[] = {
+ DW_SECTNAME_REL_DEBUG_INFO STRING_FOR_NULL,
+ DW_SECTNAME_REL_DEBUG_LINE STRING_FOR_NULL,
+ DW_SECTNAME_REL_DEBUG_PUBNAMES STRING_FOR_NULL,
+ DW_SECTNAME_REL_DEBUG_ABBREV STRING_FOR_NULL,
+ DW_SECTNAME_REL_DEBUG_ARANGES STRING_FOR_NULL,
+ DW_SECTNAME_REL_DEBUG_FRAME STRING_FOR_NULL,
+ DW_SECTNAME_REL_DEBUG_LOC STRING_FOR_NULL,
+ DW_SECTNAME_REL_DEBUG_RANGES STRING_FOR_NULL,
+ DW_SECTNAME_REL_DEBUG_TYPES STRING_FOR_NULL,
+};
+
+/* Include Section type, to be able to deal with all the
+ Elf32_Rel, Elf32_Rela, Elf64_Rel, Elf64_Rela relocation types */
+#define SECT_DATA_SET(x,t,n) { \
+ if (sect_data[(x)].buf != NULL) { \
+ print_error(dbg, error_msg_duplicate[(x)], DW_DLV_OK, err); \
+ } \
+ if ((data = elf_getdata(scn, 0)) == NULL || data->d_size == 0) {\
+ print_error(dbg, error_msg_null[(x)],DW_DLV_OK, err); \
+ } \
+ sect_data[(x)].buf = data -> d_buf; \
+ sect_data[(x)].size = data -> d_size; \
+ sect_data[(x)].type = t; \
+ sect_data[(x)].name = n; \
+ }
+
+/* PowerPC relocations defined by the ABIs */
+static char *reloc_type_names_PPC[] = {
+ "R_PPC_NONE", /* 00 */
+ "R_PPC_ADDR32", /* 01 */
+ "R_PPC_ADDR24", /* 02 */
+ "R_PPC_ADDR16", /* 03 */
+ "R_PPC_ADDR16_LO", /* 04 */
+ "R_PPC_ADDR16_HI", /* 05 */
+ "R_PPC_ADDR16_HA", /* 06 */
+ "R_PPC_ADDR14", /* 07 */
+ "R_PPC_ADDR14_BRTAKEN", /* 08 */
+ "R_PPC_ADDR14_BRNTAKEN", /* 09 */
+ "R_PPC_REL24", /* 10 */
+ "R_PPC_REL14", /* 11 */
+ "R_PPC_REL14_BRTAKEN", /* 12 */
+ "R_PPC_REL14_BRNTAKEN", /* 13 */
+ "R_PPC_GOT16", /* 14 */
+ "R_PPC_GOT16_LO", /* 15 */
+ "R_PPC_GOT16_HI", /* 16 */
+ "R_PPC_GOT16_HA", /* 17 */
+ "R_PPC_PLTREL24", /* 18 */
+ "R_PPC_COPY", /* 19 */
+ "R_PPC_GLOB_DAT", /* 20 */
+ "R_PPC_JMP_SLOT", /* 21 */
+ "R_PPC_RELATIVE", /* 22 */
+ "R_PPC_LOCAL24PC", /* 23 */
+ "R_PPC_UADDR32", /* 24 */
+ "R_PPC_UADDR16", /* 25 */
+ "R_PPC_REL32", /* 26 */
+ "R_PPC_PLT32", /* 27 */
+ "R_PPC_PLTREL32", /* 28 */
+ "R_PPC_PLT16_LO", /* 29 */
+ "R_PPC_PLT16_HI", /* 30 */
+ "R_PPC_PLT16_HA", /* 31 */
+ "R_PPC_SDAREL16", /* 32 */
+ "R_PPC_SECTOFF", /* 33 */
+ "R_PPC_SECTOFF_LO", /* 34 */
+ "R_PPC_SECTOFF_HI", /* 35 */
+ "R_PPC_SECTOFF_HA", /* 36 */
+ "R_PPC_37", /* 37 */
+ "R_PPC_38", /* 38 */
+ "R_PPC_39", /* 39 */
+ "R_PPC_40", /* 40 */
+ "R_PPC_41", /* 41 */
+ "R_PPC_42", /* 42 */
+ "R_PPC_43", /* 43 */
+ "R_PPC_44", /* 44 */
+ "R_PPC_45", /* 45 */
+ "R_PPC_46", /* 46 */
+ "R_PPC_47", /* 47 */
+ "R_PPC_48", /* 48 */
+ "R_PPC_49", /* 49 */
+ "R_PPC_50", /* 50 */
+ "R_PPC_51", /* 51 */
+ "R_PPC_52", /* 52 */
+ "R_PPC_53", /* 53 */
+ "R_PPC_54", /* 54 */
+ "R_PPC_55", /* 55 */
+ "R_PPC_56", /* 56 */
+ "R_PPC_57", /* 57 */
+ "R_PPC_58", /* 58 */
+ "R_PPC_59", /* 59 */
+ "R_PPC_60", /* 60 */
+ "R_PPC_61", /* 61 */
+ "R_PPC_62", /* 62 */
+ "R_PPC_63", /* 63 */
+ "R_PPC_64", /* 64 */
+ "R_PPC_65", /* 65 */
+ "R_PPC_66", /* 66 */
+ "R_PPC_TLS", /* 67 */
+ "R_PPC_DTPMOD32", /* 68 */
+ "R_PPC_TPREL16", /* 69 */
+ "R_PPC_TPREL16_LO", /* 70 */
+ "R_PPC_TPREL16_HI", /* 71 */
+ "R_PPC_TPREL16_HA", /* 72 */
+ "R_PPC_TPREL32", /* 73 */
+ "R_PPC_DTPREL16", /* 74 */
+ "R_PPC_DTPREL16_LO", /* 75 */
+ "R_PPC_DTPREL16_HI", /* 76 */
+ "R_PPC_DTPREL16_HA", /* 77 */
+ "R_PPC_DTPREL64", /* 78 */
+ "R_PPC_GOT_TLSGD16", /* 79 */
+ "R_PPC_GOT_TLSGD16_LO", /* 80 */
+ "R_PPC_GOT_TLSGD16_HI", /* 81 */
+ "R_PPC_GOT_TLSGD16_HA", /* 82 */
+ "R_PPC_GOT_TLSLD16", /* 83 */
+ "R_PPC_GOT_TLSLD16_LO", /* 84 */
+ "R_PPC_GOT_TLSLD16_HI", /* 85 */
+ "R_PPC_GOT_TLSLD16_HA", /* 86 */
+ "R_PPC_GOT_TPREL16_DS", /* 87 */
+ "R_PPC_GOT_TPREL16_LO", /* 88 */
+ "R_PPC_GOT_TPREL16_HI", /* 89 */
+ "R_PPC_GOT_TPREL16_HA", /* 90 */
+ "R_PPC_GOT_DTPREL16", /* 91 */
+ "R_PPC_GOT_DTPREL16_LO", /* 92 */
+ "R_PPC_GOT_DTPREL16_HI", /* 93 */
+ "R_PPC_GOT_DTPREL16_HA", /* 94 */
+};
+
+/* PowerPC64 relocations defined by the ABIs */
+static char *reloc_type_names_PPC64[] = {
+ "R_PPC64_NONE", /* 00 */
+ "R_PPC64_ADDR32", /* 01 */
+ "R_PPC64_ADDR24", /* 02 */
+ "R_PPC64_ADDR16", /* 03 */
+ "R_PPC64_ADDR16_LO", /* 04 */
+ "R_PPC64_ADDR16_HI", /* 05 */
+ "R_PPC64_ADDR16_HA", /* 06 */
+ "R_PPC64_ADDR14", /* 07 */
+ "R_PPC64_ADDR14_BRTAKEN", /* 08 */
+ "R_PPC64_ADDR14_BRNTAKEN", /* 09 */
+ "R_PPC64_REL24", /* 10 */
+ "R_PPC64_REL14", /* 11 */
+ "R_PPC64_REL14_BRTAKEN", /* 12 */
+ "R_PPC64_REL14_BRNTAKEN", /* 13 */
+ "R_PPC64_GOT16", /* 14 */
+ "R_PPC64_GOT16_LO", /* 15 */
+ "R_PPC64_GOT16_HI", /* 16 */
+ "R_PPC64_GOT16_HA", /* 17 */
+ "R_PPC64_PLTREL24", /* 18 */
+ "R_PPC64_COPY", /* 19 */
+ "R_PPC64_GLOB_DAT", /* 20 */
+ "R_PPC64_JMP_SLOT", /* 21 */
+ "R_PPC64_RELATIVE", /* 22 */
+ "R_PPC64_LOCAL24PC", /* 23 */
+ "R_PPC64_UADDR32", /* 24 */
+ "R_PPC64_UADDR16", /* 25 */
+ "R_PPC64_REL32", /* 26 */
+ "R_PPC64_PLT32", /* 27 */
+ "R_PPC64_PLTREL32", /* 28 */
+ "R_PPC64_PLT16_LO", /* 29 */
+ "R_PPC64_PLT16_HI", /* 30 */
+ "R_PPC64_PLT16_HA", /* 31 */
+ "R_PPC64_SDAREL16", /* 32 */
+ "R_PPC64_SECTOFF", /* 33 */
+ "R_PPC64_SECTOFF_LO", /* 34 */
+ "R_PPC64_SECTOFF_HI", /* 35 */
+ "R_PPC64_SECTOFF_HA", /* 36 */
+ "R_PPC64_REL30", /* 37 */
+ "R_PPC64_ADDR64", /* 38 */
+ "R_PPC64_ADDR16_HIGHER", /* 39 */
+ "R_PPC64_ADDR16_HIGHERA", /* 40 */
+ "R_PPC64_ADDR16_HIGHEST", /* 41 */
+ "R_PPC64_ADDR16_HIGHESTA", /* 42 */
+ "R_PPC64_UADDR64", /* 43 */
+ "R_PPC64_REL64", /* 44 */
+ "R_PPC64_PLT64", /* 45 */
+ "R_PPC64_PLTREL64", /* 46 */
+ "R_PPC64_TOC16", /* 47 */
+ "R_PPC64_TOC16_LO", /* 48 */
+ "R_PPC64_TOC16_HI", /* 49 */
+ "R_PPC64_TOC16_HA", /* 50 */
+ "R_PPC64_TOC", /* 51 */
+ "R_PPC64_PLTGOT16", /* 52 */
+ "R_PPC64_PLTGOT16_LO", /* 53 */
+ "R_PPC64_PLTGOT16_HI", /* 54 */
+ "R_PPC64_PLTGOT16_HA", /* 55 */
+ "R_PPC64_ADDR16_DS", /* 56 */
+ "R_PPC64_ADDR16_LO_DS", /* 57 */
+ "R_PPC64_GOT16_DS", /* 58 */
+ "R_PPC64_GOT16_LO_DS", /* 59 */
+ "R_PPC64_PLT16_LO_DS", /* 60 */
+ "R_PPC64_SECTOFF_DS", /* 61 */
+ "R_PPC64_SECTOFF_LO_DS", /* 62 */
+ "R_PPC64_TOC16_DS", /* 63 */
+ "R_PPC64_TOC16_LO_DS", /* 64 */
+ "R_PPC64_PLTGOT16_DS", /* 65 */
+ "R_PPC64_PLTGOT16_LO_DS", /* 66 */
+ "R_PPC64_TLS", /* 67 */
+ "R_PPC64_DTPMOD32", /* 68 */
+ "R_PPC64_TPREL16", /* 69 */
+ "R_PPC64_TPREL16_LO", /* 70 */
+ "R_PPC64_TPREL16_HI", /* 71 */
+ "R_PPC64_TPREL16_HA", /* 72 */
+ "R_PPC64_TPREL32", /* 73 */
+ "R_PPC64_DTPREL16", /* 74 */
+ "R_PPC64_DTPREL16_LO", /* 75 */
+ "R_PPC64_DTPREL16_HI", /* 76 */
+ "R_PPC64_DTPREL16_HA", /* 77 */
+ "R_PPC64_DTPREL64", /* 78 */
+ "R_PPC64_GOT_TLSGD16", /* 79 */
+ "R_PPC64_GOT_TLSGD16_LO", /* 80 */
+ "R_PPC64_GOT_TLSGD16_HI", /* 81 */
+ "R_PPC64_GOT_TLSGD16_HA", /* 82 */
+ "R_PPC64_GOT_TLSLD16", /* 83 */
+ "R_PPC64_GOT_TLSLD16_LO", /* 84 */
+ "R_PPC64_GOT_TLSLD16_HI", /* 85 */
+ "R_PPC64_GOT_TLSLD16_HA", /* 86 */
+ "R_PPC64_GOT_TPREL16_DS", /* 87 */
+ "R_PPC64_GOT_TPREL16_LO", /* 88 */
+ "R_PPC64_GOT_TPREL16_HI", /* 89 */
+ "R_PPC64_GOT_TPREL16_HA", /* 90 */
+ "R_PPC64_GOT_DTPREL16", /* 91 */
+ "R_PPC64_GOT_DTPREL16_LO", /* 92 */
+ "R_PPC64_GOT_DTPREL16_HI", /* 93 */
+ "R_PPC64_GOT_DTPREL16_HA", /* 94 */
+ "R_PPC64_TPREL16_DS", /* 95 */
+ "R_PPC64_TPREL16_LO_DS", /* 96 */
+ "R_PPC64_TPREL16_HIGHER", /* 97 */
+ "R_PPC64_TPREL16_HIGHERA", /* 98 */
+ "R_PPC64_TPREL16_HIGHEST", /* 99 */
+ "R_PPC64_TPREL16_HIGHESTA", /* 100 */
+ "R_PPC64_DTPREL16_DS", /* 101 */
+ "R_PPC64_DTPREL16_LO_DS", /* 102 */
+ "R_PPC64_DTPREL16_HIGHER", /* 103 */
+ "R_PPC64_DTPREL16_HIGHERA", /* 104 */
+ "R_PPC64_DTPREL16_HIGHEST", /* 105 */
+ "R_PPC64_DTPREL16_HIGHESTA", /* 106 */
+ "R_PPC64_TOC32", /* 107 */
+ "R_PPC64_DTPMOD32", /* 108 */
+ "R_PPC64_TPREL32", /* 109 */
+ "R_PPC64_DTPREL32", /* 110 */
+};
+
+/* Relocation types for MIPS */
+static char *reloc_type_names_MIPS[] = {
+ "R_MIPS_NONE", "R_MIPS_16", "R_MIPS_32", "R_MIPS_REL32",
+ "R_MIPS_26", "R_MIPS_HI16", "R_MIPS_LO16", "R_MIPS_GPREL16",
+ "R_MIPS_LITERAL", "R_MIPS_GOT16", "R_MIPS_PC16", "R_MIPS_CALL16",
+ "R_MIPS_GPREL32", /* 12 */
+ "reloc type 13?", "reloc type 14?", "reloc type 15?",
+ "R_MIPS_SHIFT5", /* 16 */
+ "R_MIPS_SHIFT6", /* 17 */
+ "R_MIPS_64", /* 18 */
+ "R_MIPS_GOT_DISP", /* 19 */
+ "R_MIPS_GOT_PAGE", /* 20 */
+ "R_MIPS_GOT_OFST", /* 21 */
+ "R_MIPS_GOT_HI16", /* 22 */
+ "R_MIPS_GOT_LO16", /* 23 */
+ "R_MIPS_SUB", /* 24 */
+ "R_MIPS_INSERT_A", /* 25 */
+ "R_MIPS_INSERT_B", /* 26 */
+ "R_MIPS_DELETE", /* 27 */
+ "R_MIPS_HIGHER", /* 28 */
+ "R_MIPS_HIGHEST", /* 29 */
+ "R_MIPS_CALL_HI16", /* 30 */
+ "R_MIPS_CALL_LO16", /* 31 */
+ "R_MIPS_SCN_DISP", /* 32 */
+ "R_MIPS_REL16", /* 33 */
+ "R_MIPS_ADD_IMMEDIATE", /* 34 */
+};
+
+/* ARM relocations defined by the ABIs */
+static char *reloc_type_names_ARM[] = {
+ "R_ARM_NONE", /* 00 */
+ "R_ARM_PC24", /* 01 */
+ "R_ARM_ABS32", /* 02 */
+ "R_ARM_REL32", /* 03 */
+ "R_ARM_LDR_PC_G0", /* 04 */
+ "R_ARM_ABS16", /* 05 */
+ "R_ARM_ABS12", /* 06 */
+ "R_ARM_THM_ABS5", /* 07 */
+ "R_ARM_ABS8", /* 08 */
+ "R_ARM_SBREL32", /* 09 */
+ "R_ARM_THM_CALL", /* 10 */
+ "R_ARM_THM_PC8", /* 11 */
+ "R_ARM_BREL_ADJ", /* 12 */
+ "R_ARM_TLS_DESC", /* 13 */
+ "R_ARM_THM_SWI8", /* 14 */
+ "R_ARM_XPC25", /* 15 */
+ "R_ARM_THM_XPC22", /* 16 */
+ "R_ARM_TLS_DTPMOD32", /* 17 */
+ "R_ARM_TLS_DTPOFF32", /* 18 */
+ "R_ARM_TLS_TPOFF32", /* 19 */
+ "R_ARM_COPY", /* 20 */
+ "R_ARM_GLOB_DAT", /* 21 */
+ "R_ARM_JUMP_SLOT", /* 22 */
+ "R_ARM_RELATIVE", /* 23 */
+ "R_ARM_GOTOFF32", /* 24 */
+ "R_ARM_BASE_PREL", /* 25 */
+ "R_ARM_GOT_BREL", /* 26 */
+ "R_ARM_PLT32", /* 27 */
+ "R_ARM_CALL", /* 28 */
+ "R_ARM_JUMP24", /* 29 */
+ "R_ARM_THM_JUMP24", /* 30 */
+ "R_ARM_BASE_ABS", /* 31 */
+ "R_ARM_ALU_PCREL_7_0", /* 32 */
+ "R_ARM_ALU_PCREL_15_8", /* 33 */
+ "R_ARM_ALU_PCREL_23_15", /* 34 */
+ "R_ARM_LDR_SBREL_11_0_NC", /* 35 */
+ "R_ARM_ALU_SBREL_19_12_NC", /* 36 */
+ "R_ARM_ALU_SBREL_27_20_CK", /* 37 */
+ "R_ARM_TARGET1", /* 38 */
+ "R_ARM_SBREL31", /* 39 */
+ "R_ARM_V4BX", /* 40 */
+ "R_ARM_TARGET2", /* 41 */
+ "R_ARM_PREL31", /* 42 */
+ "R_ARM_MOVW_ABS_NC", /* 43 */
+ "R_ARM_MOVT_ABS", /* 44 */
+ "R_ARM_MOVW_PREL_NC", /* 45 */
+ "R_ARM_MOVT_PREL", /* 46 */
+ "R_ARM_THM_MOVW_ABS_NC", /* 47 */
+ "R_ARM_THM_MOVT_ABS", /* 48 */
+ "R_ARM_THM_MOVW_PREL_NC", /* 49 */
+ "R_ARM_THM_MOVT_PREL", /* 50 */
+ "R_ARM_THM_JUMP19", /* 51 */
+ "R_ARM_THM_JUMP6", /* 52 */
+ "R_ARM_THM_ALU_PREL_11_0", /* 53 */
+ "R_ARM_THM_PC12", /* 54 */
+ "R_ARM_ABS32_NOI", /* 55 */
+ "R_ARM_REL32_NOI", /* 56 */
+ "R_ARM_ALU_PC_G0_NC", /* 57 */
+ "R_ARM_ALU_PC_G0", /* 58 */
+ "R_ARM_ALU_PC_G1_NC", /* 59 */
+ "R_ARM_ALU_PC_G1", /* 60 */
+ "R_ARM_ALU_PC_G2", /* 61 */
+ "R_ARM_LDR_PC_G1", /* 62 */
+ "R_ARM_LDR_PC_G2", /* 63 */
+ "R_ARM_LDRS_PC_G0", /* 64 */
+ "R_ARM_LDRS_PC_G1", /* 65 */
+ "R_ARM_LDRS_PC_G2", /* 66 */
+ "R_ARM_LDC_PC_G0", /* 67 */
+ "R_ARM_LDC_PC_G1", /* 68 */
+ "R_ARM_LDC_PC_G2", /* 69 */
+ "R_ARM_ALU_SB_G0_NC", /* 70 */
+ "R_ARM_ALU_SB_G0", /* 71 */
+ "R_ARM_ALU_SB_G1_NC", /* 72 */
+ "R_ARM_ALU_SB_G1", /* 73 */
+ "R_ARM_ALU_SB_G2", /* 74 */
+ "R_ARM_LDR_SB_G0", /* 75 */
+ "R_ARM_LDR_SB_G1", /* 76 */
+ "R_ARM_LDR_SB_G2", /* 77 */
+ "R_ARM_LDRS_SB_G0", /* 78 */
+ "R_ARM_LDRS_SB_G1", /* 79 */
+ "R_ARM_LDRS_SB_G2", /* 80 */
+ "R_ARM_LDC_SB_G0", /* 81 */
+ "R_ARM_LDC_SB_G1", /* 82 */
+ "R_ARM_LDC_SB_G2", /* 83 */
+ "R_ARM_MOVW_BREL_NC", /* 84 */
+ "R_ARM_MOVT_BREL", /* 85 */
+ "R_ARM_MOVW_BREL", /* 86 */
+ "R_ARM_THM_MOVW_BREL_NC", /* 87 */
+ "R_ARM_THM_MOVT_BREL", /* 88 */
+ "R_ARM_THM_MOVW_BREL", /* 89 */
+ "R_ARM_TLS_GOTDESC", /* 90 */
+ "R_ARM_TLS_CALL", /* 91 */
+ "R_ARM_TLS_DESCSEQ", /* 92 */
+ "R_ARM_THM_TLS_CALL", /* 93 */
+ "R_ARM_PLT32_ABS", /* 94 */
+ "R_ARM_GOT_ABS", /* 95 */
+ "R_ARM_GOT_PREL", /* 96 */
+ "R_ARM_GOT_BREL12", /* 97 */
+ "R_ARM_GOTOFF12", /* 98 */
+ "R_ARM_GOTRELAX", /* 99 */
+ "R_ARM_GNU_VTENTRY", /* 100 */
+ "R_ARM_GNU_VTINHERIT", /* 101 */
+ "R_ARM_THM_JUMP11", /* 102 */
+ "R_ARM_THM_JUMP8", /* 103 */
+ "R_ARM_TLS_GD32", /* 104 */
+ "R_ARM_TLS_LDM32", /* 105 */
+ "R_ARM_TLS_LDO32", /* 106 */
+ "R_ARM_TLS_IE32", /* 107 */
+ "R_ARM_TLS_LE32", /* 108 */
+ "R_ARM_TLS_LDO12", /* 109 */
+ "R_ARM_TLS_LE12", /* 110 */
+ "R_ARM_TLS_IE12GP", /* 111 */
+ "R_ARM_TLS_MOVT_TPOFF32", /* 112 */ /* "R_ARM_PRIVATE_0" */
+ "R_ARM_TLS_MOVW_TPOFF32", /* 113 */ /* "R_ARM_PRIVATE_1" */
+ "R_ARM_THM_TLS_MOVT_TPOFF32", /* 114 */ /* "R_ARM_PRIVATE_2" */
+ "R_ARM_THM_TLS_MOVT_TPOFF32", /* 115 */ /* "R_ARM_PRIVATE_3" */
+ "R_ARM_PRIVATE_4", /* 116 */
+ "R_ARM_PRIVATE_5", /* 117 */
+ "R_ARM_PRIVATE_6", /* 118 */
+ "R_ARM_PRIVATE_7", /* 119 */
+ "R_ARM_PRIVATE_8", /* 120 */
+ "R_ARM_PRIVATE_9", /* 121 */
+ "R_ARM_PRIVATE_10", /* 122 */
+ "R_ARM_PRIVATE_11", /* 123 */
+ "R_ARM_PRIVATE_12", /* 124 */
+ "R_ARM_PRIVATE_13", /* 125 */
+ "R_ARM_PRIVATE_14", /* 126 */
+ "R_ARM_PRIVATE_15", /* 127 */
+ "R_ARM_ME_TOO", /* 128 */
+ "R_ARM_THM_TLS_DESCSEQ16", /* 129 */
+ "R_ARM_THM_TLS_DESCSEQ32", /* 130 */
+};
+
+/* Record the relocation table name information */
+static char **reloc_type_names = NULL;
+static Dwarf_Small number_of_reloc_type_names = 0;
+
+/* Set the relocation names based on the machine type */
+static void
+set_relocation_table_names(Dwarf_Small machine_type)
+{
+ switch (machine_type) {
+ case EM_MIPS:
+ reloc_type_names = reloc_type_names_MIPS;
+ number_of_reloc_type_names =
+ sizeof(reloc_type_names_MIPS) / sizeof(char *);
+ break;
+ case EM_PPC:
+ reloc_type_names = reloc_type_names_PPC;
+ number_of_reloc_type_names =
+ sizeof(reloc_type_names_PPC) / sizeof(char *);
+ break;
+ case EM_PPC64:
+ reloc_type_names = reloc_type_names_PPC64;
+ number_of_reloc_type_names =
+ sizeof(reloc_type_names_PPC64) / sizeof(char *);
+ break;
+ case EM_ARM:
+ reloc_type_names = reloc_type_names_ARM;
+ number_of_reloc_type_names =
+ sizeof(reloc_type_names_ARM) / sizeof(char *);
+ break;
+ default:
+ /* We don't have others covered. */
+ reloc_type_names = 0;
+ number_of_reloc_type_names = 0;
+ break;
+ }
+}
+
+/*
+ Return valid reloc type names.
+ If buf is used, it is static, so beware: it
+ will be overwritten by the next call.
+*/
+static char *
+get_reloc_type_names(int index)
+{
+ static char buf[100];
+ char *retval = 0;
+
+ if (index < 0 || index >= number_of_reloc_type_names) {
+ sprintf(buf, "reloc type %d unknown", (int) index);
+ retval = buf;
+ } else {
+ retval = reloc_type_names[index];
+ }
+ return retval;
+}
+
+#ifndef HAVE_ELF64_GETEHDR
+#define Elf64_Addr long
+#define Elf64_Word unsigned long
+#define Elf64_Xword unsigned long
+#define Elf64_Sym long
+#endif
+
+static struct {
+ Dwarf_Small *buf;
+ Dwarf_Unsigned size;
+ Dwarf_Bool display; /* Display reloc if TRUE */
+ const char *name; /* Section name */
+ Elf64_Xword type; /* To cover 32 and 64 records types */
+} sect_data[DW_SECTION_REL_DEBUG_NUM];
+
+
+typedef size_t indx_type;
+
+typedef struct {
+ indx_type indx;
+ char *name;
+ Elf32_Addr value;
+ Elf32_Word size;
+ int type;
+ int bind;
+ unsigned char other;
+ Elf32_Half shndx;
+} SYM;
+
+
+typedef struct {
+ indx_type indx;
+ char *name;
+ Elf64_Addr value;
+ Elf64_Xword size;
+ int type;
+ int bind;
+ unsigned char other;
+ unsigned short shndx;
+} SYM64;
+
+static void print_reloc_information_64(int section_no,
+ Dwarf_Small * buf,
+ Dwarf_Unsigned size,
+ Elf64_Xword type,
+ char **scn_names,int scn_names_count);
+static void print_reloc_information_32(int section_no,
+ Dwarf_Small * buf,
+ Dwarf_Unsigned size,
+ Elf64_Xword type,
+ char **scn_names,int scn_names_count);
+static SYM *readsyms(Elf32_Sym * data, size_t num, Elf * elf,
+ Elf32_Word link);
+static SYM64 *read_64_syms(Elf64_Sym * data, size_t num, Elf * elf,
+ Elf64_Word link);
+static void *get_scndata(Elf_Scn * fd_scn, size_t * scn_size);
+static void print_relocinfo_64(Dwarf_Debug dbg, Elf * elf);
+static void print_relocinfo_32(Dwarf_Debug dbg, Elf * elf);
+
+static SYM *sym_data;
+static SYM64 *sym_data_64;
+static long sym_data_entry_count;
+static long sym_data_64_entry_count;
+
+typedef struct {
+ indx_type index;
+ char *name_rel; /* .rel.debug_* names */
+ char *name_rela; /* .rela.debug_* names */
+} REL_INFO;
+
+/* If the incoming scn_name is known, record the name
+ in our reloc section names table.
+ For a given (debug) section there can be a .rel or a .rela,
+ not both.
+ The name-to-index in this table is fixed, invariant.
+ It has to match other tables like
+*/
+static int
+get_reloc_section(Dwarf_Debug dbg,
+ Elf_Scn *scn,
+ char *scn_name,
+ Elf64_Word sh_type)
+{
+ static REL_INFO rel_info[DW_SECTION_REL_DEBUG_NUM] = {
+ {/*0*/ DW_SECTION_REL_DEBUG_INFO,
+ DW_SECTNAME_REL_DEBUG_INFO,
+ DW_SECTNAME_RELA_DEBUG_INFO},
+
+ {/*1*/ DW_SECTION_REL_DEBUG_LINE,
+ DW_SECTNAME_REL_DEBUG_LINE,
+ DW_SECTNAME_RELA_DEBUG_LINE},
+
+ {/*2*/ DW_SECTION_REL_DEBUG_PUBNAMES,
+ DW_SECTNAME_REL_DEBUG_PUBNAMES,
+ DW_SECTNAME_RELA_DEBUG_PUBNAMES},
+
+ {/*3*/ DW_SECTION_REL_DEBUG_ABBREV,
+ DW_SECTNAME_REL_DEBUG_ABBREV,
+ DW_SECTNAME_RELA_DEBUG_ABBREV},
+
+ {/*4*/ DW_SECTION_REL_DEBUG_ARANGES,
+ DW_SECTNAME_REL_DEBUG_ARANGES,
+ DW_SECTNAME_RELA_DEBUG_ARANGES},
+
+ {/*5*/ DW_SECTION_REL_DEBUG_FRAME,
+ DW_SECTNAME_REL_DEBUG_FRAME,
+ DW_SECTNAME_RELA_DEBUG_FRAME},
+
+ {/*6*/ DW_SECTION_REL_DEBUG_LOC,
+ DW_SECTNAME_REL_DEBUG_LOC,
+ DW_SECTNAME_RELA_DEBUG_LOC},
+
+ {/*7*/ DW_SECTION_REL_DEBUG_RANGES,
+ DW_SECTNAME_REL_DEBUG_RANGES,
+ DW_SECTNAME_RELA_DEBUG_RANGES},
+
+ {/*8*/ DW_SECTION_REL_DEBUG_TYPES,
+ DW_SECTNAME_REL_DEBUG_TYPES,
+ DW_SECTNAME_RELA_DEBUG_TYPES},
+ };
+
+ Elf_Data *data;
+ int index;
+ for (index = 0; index < DW_SECTION_REL_DEBUG_NUM; ++index) {
+ const char *n = rel_info[index].name_rel;
+ const char *na = rel_info[index].name_rela;
+ if (strcmp(scn_name, n) == 0) {
+ SECT_DATA_SET(rel_info[index].index,sh_type,n)
+ return TRUE;
+ }
+ if (strcmp(scn_name, na) == 0) {
+ SECT_DATA_SET(rel_info[index].index,sh_type,na)
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void
+print_relocinfo(Dwarf_Debug dbg, unsigned reloc_map)
+{
+ Elf *elf;
+ char *endr_ident;
+ int is_64bit;
+ int res;
+ int i;
+
+ for (i = 0; i < DW_SECTION_REL_DEBUG_NUM; i++) {
+ sect_data[i].display = reloc_map & (1 << i);
+ sect_data[i].buf = 0;
+ sect_data[i].size = 0;
+ sect_data[i].type = SHT_NULL;
+ }
+ res = dwarf_get_elf(dbg, &elf, &err);
+ if (res != DW_DLV_OK) {
+ print_error(dbg, "dwarf_get_elf error", res, err);
+ }
+ if ((endr_ident = elf_getident(elf, NULL)) == NULL) {
+ print_error(dbg, "DW_ELF_GETIDENT_ERROR", res, err);
+ }
+ is_64bit = (endr_ident[EI_CLASS] == ELFCLASS64);
+ if (is_64bit) {
+ print_relocinfo_64(dbg, elf);
+ } else {
+ print_relocinfo_32(dbg, elf);
+ }
+}
+
+static void
+print_relocinfo_64(Dwarf_Debug dbg, Elf * elf)
+{
+#ifdef HAVE_ELF64_GETEHDR
+ Elf_Scn *scn = NULL;
+ Elf64_Ehdr *ehdr64 = 0;
+ Elf64_Shdr *shdr64 = 0;
+ char *scn_name = 0;
+ int i = 0;
+ Elf64_Sym *sym_64 = 0;
+ char **scn_names = 0;
+ int scn_names_cnt = 0;
+
+ ehdr64 = elf64_getehdr(elf);
+ if (ehdr64 == NULL) {
+ print_error(dbg, "DW_ELF_GETEHDR_ERROR", DW_DLV_OK, err);
+ }
+
+ /* Make the section name array big enough
+ that we don't need to check for overrun in the loop. */
+ scn_names = (char **)calloc(ehdr64->e_shnum + 1, sizeof(char *));
+
+ while ((scn = elf_nextscn(elf, scn)) != NULL) {
+
+ shdr64 = elf64_getshdr(scn);
+ if (shdr64 == NULL) {
+ print_error(dbg, "DW_ELF_GETSHDR_ERROR", DW_DLV_OK, err);
+ }
+ scn_name = elf_strptr(elf, ehdr64->e_shstrndx, shdr64->sh_name);
+ if (scn_name == NULL) {
+ print_error(dbg, "DW_ELF_STRPTR_ERROR", DW_DLV_OK, err);
+ }
+
+ if (scn_names) {
+ /* elf_nextscn() skips section with index '0' */
+ scn_names[++scn_names_cnt] = scn_name;
+ }
+ if (shdr64->sh_type == SHT_SYMTAB) {
+ size_t sym_size = 0;
+ size_t count = 0;
+
+ sym_64 = (Elf64_Sym *) get_scndata(scn, &sym_size);
+ if (sym_64 == NULL) {
+ print_error(dbg, "no symbol table data", DW_DLV_OK,
+ err);
+ }
+ count = sym_size / sizeof(Elf64_Sym);
+ sym_64++;
+ free(sym_data_64);
+ sym_data_64 = read_64_syms(sym_64, count, elf, shdr64->sh_link);
+ sym_data_64_entry_count = count;
+ if (sym_data_64 == NULL) {
+ print_error(dbg, "problem reading symbol table data",
+ DW_DLV_OK, err);
+ }
+ } else if (!get_reloc_section(dbg,scn,scn_name,shdr64->sh_type)) {
+ continue;
+ }
+ } /* while */
+
+ /* Set the relocation names based on the machine type */
+ set_relocation_table_names(ehdr64->e_machine);
+
+ for (i = 0; i < DW_SECTION_REL_DEBUG_NUM; i++) {
+ if (sect_data[i].display &&
+ sect_data[i].buf != NULL &&
+ sect_data[i].size > 0) {
+ print_reloc_information_64(i, sect_data[i].buf,
+ sect_data[i].size, sect_data[i].type,scn_names,
+ scn_names_cnt);
+ }
+ }
+
+ if (scn_names) {
+ free(scn_names);
+ scn_names = 0;
+ scn_names_cnt = 0;
+ }
+#endif
+}
+
+static void
+print_relocinfo_32(Dwarf_Debug dbg, Elf * elf)
+{
+ Elf_Scn *scn = NULL;
+ Elf32_Ehdr *ehdr32 = 0;
+ Elf32_Shdr *shdr32 = 0;
+ char *scn_name = 0;
+ int i = 0;
+ Elf32_Sym *sym = 0;
+ char **scn_names = 0;
+ int scn_names_cnt = 0;
+
+ ehdr32 = elf32_getehdr(elf);
+ if (ehdr32 == NULL) {
+ print_error(dbg, "DW_ELF_GETEHDR_ERROR", DW_DLV_OK, err);
+ }
+
+ /* Make the section name array big enough
+ that we don't need to check for overrun in the loop. */
+ scn_names = (char **)calloc(ehdr32->e_shnum + 1, sizeof(char *));
+
+ while ((scn = elf_nextscn(elf, scn)) != NULL) {
+ shdr32 = elf32_getshdr(scn);
+ if (shdr32 == NULL) {
+ print_error(dbg, "DW_ELF_GETSHDR_ERROR", DW_DLV_OK, err);
+ }
+ scn_name = elf_strptr(elf, ehdr32->e_shstrndx, shdr32->sh_name);
+ if (scn_name == NULL) {
+ print_error(dbg, "DW_ELF_STRPTR_ERROR", DW_DLV_OK, err);
+ }
+
+ if (scn_names) {
+ /* elf_nextscn() skips section with index '0' */
+ scn_names[++scn_names_cnt] = scn_name;
+ }
+
+ if (shdr32->sh_type == SHT_SYMTAB) {
+ size_t sym_size = 0;
+ size_t count = 0;
+
+ sym = (Elf32_Sym *) get_scndata(scn, &sym_size);
+ if (sym == NULL) {
+ print_error(dbg, "no symbol table data", DW_DLV_OK,
+ err);
+ }
+ sym = (Elf32_Sym *) get_scndata(scn, &sym_size);
+ count = sym_size / sizeof(Elf32_Sym);
+ sym++;
+ free(sym_data);
+ sym_data = readsyms(sym, count, elf, shdr32->sh_link);
+ sym_data_entry_count = count;
+ if (sym_data == NULL) {
+ print_error(dbg, "problem reading symbol table data",
+ DW_DLV_OK, err);
+ }
+ } else if (!get_reloc_section(dbg,scn,scn_name,shdr32->sh_type)) {
+ continue;
+ }
+ } /* End while. */
+
+ /* Set the relocation names based on the machine type */
+ set_relocation_table_names(ehdr32->e_machine);
+
+ for (i = 0; i < DW_SECTION_REL_DEBUG_NUM; i++) {
+ if (sect_data[i].display &&
+ sect_data[i].buf != NULL &&
+ sect_data[i].size > 0) {
+ print_reloc_information_32(i, sect_data[i].buf,
+ sect_data[i].size,sect_data[i].type,scn_names,
+ scn_names_cnt);
+ }
+ }
+
+ if (scn_names) {
+ free(scn_names);
+ scn_names = 0;
+ scn_names_cnt = 0;
+ }
+}
+
+#if HAVE_ELF64_R_INFO
+#ifndef ELF64_R_TYPE
+#define ELF64_R_TYPE(x) 0 /* FIXME */
+#endif
+#ifndef ELF64_R_SYM
+#define ELF64_R_SYM(x) 0 /* FIXME */
+#endif
+#ifndef ELF64_ST_TYPE
+#define ELF64_ST_TYPE(x) 0 /* FIXME */
+#endif
+#ifndef ELF64_ST_BIND
+#define ELF64_ST_BIND(x) 0 /* FIXME */
+#endif
+#endif /* HAVE_ELF64_R_INFO */
+
+
+static void
+print_reloc_information_64(int section_no, Dwarf_Small * buf,
+ Dwarf_Unsigned size, Elf64_Xword type,
+ char **scn_names, int scn_names_count)
+{
+ /* Include support for Elf64_Rel and Elf64_Rela */
+ Dwarf_Unsigned add = 0;
+ Dwarf_Half rel_size = SHT_RELA == type ?
+ sizeof(Elf64_Rela) : sizeof(Elf64_Rel);
+ Dwarf_Unsigned off = 0;
+
+ printf("\n%s:\n", type== SHT_RELA?sectnamesa[section_no]:
+ sectnames[section_no]);
+
+ /* Print some headers and change the order for better reading */
+ printf("Offset Addend %-26s Index Symbol Name\n","Reloc Type");
+
+#if HAVE_ELF64_GETEHDR
+ for (off = 0; off < size; off += rel_size) {
+#if HAVE_ELF64_R_INFO
+ /* This works for the Elf64_Rel in linux */
+ Elf64_Rel *p = (Elf64_Rel *) (buf + off);
+ char *name = 0;
+ if(sym_data ) {
+ size_t index = ELF64_R_SYM(p->r_info) - 1;
+ if(index < sym_data_entry_count) {
+ name = sym_data[index].name;
+ }
+ } else if (sym_data_64) {
+ size_t index = ELF64_R_SYM(p->r_info) - 1;
+ if(index < sym_data_64_entry_count) {
+ name = sym_data_64[index].name;
+ }
+ }
+
+ /* When the name is not available, use the
+ section name as a reference for the name.*/
+ if (!name || !name[0]) {
+ size_t index = ELF64_R_SYM(p->r_info) - 1;
+ if(index < sym_data_64_entry_count) {
+ SYM64 *sym_64 = &sym_data_64[index];
+ if (sym_64->type == STT_SECTION &&
+ sym_64->shndx < scn_names_count) {
+ name = scn_names[sym_64->shndx];
+ }
+ }
+ }
+ if(!name || !name[0]) {
+ name = "<no name>";
+ }
+
+ if (SHT_RELA == type) {
+ Elf64_Rela *pa = (Elf64_Rela *)p;
+ add = pa->r_addend;
+ }
+
+ printf("0x%08lx 0x%08lx %-26s <%5ld> %s\n",
+ (unsigned long int) (p->r_offset),
+ (unsigned long int) (add),
+ get_reloc_type_names(ELF64_R_TYPE(p->r_info)),
+ (long)ELF64_R_SYM(p->r_info),
+ name);
+#else
+ /* sgi/mips -64 does not have r_info in the 64bit relocations,
+ but seperate fields, with 3 types, actually. Only one of
+ which prints here, as only one really used with dwarf */
+ Elf64_Rel *p = (Elf64_Rel *) (buf + off);
+ char *name = 0;
+ if(sym_data ) {
+ size_t index = p->r_sym - 1;
+ if(index < sym_data_entry_count) {
+ name = sym_data[index].name;
+ }
+ } else if (sym_data_64) {
+ size_t index = p->r_sym - 1;
+ if(index < sym_data_64_entry_count) {
+ name = sym_data_64[index].name;
+ }
+ }
+ if(!name || !name[0]) {
+ name = "<no name>";
+ }
+ printf("%5" DW_PR_DUu " %-26s <%3ld> %s\n",
+ (Dwarf_Unsigned) (p->r_offset),
+ get_reloc_type_names(p->r_type),
+ (long)p->r_sym,
+ name);
+#endif
+ }
+#endif /* HAVE_ELF64_GETEHDR */
+}
+
+static void
+print_reloc_information_32(int section_no, Dwarf_Small * buf,
+ Dwarf_Unsigned size, Elf64_Xword type, char **scn_names,
+ int scn_names_count)
+{
+ /* Include support for Elf32_Rel and Elf32_Rela */
+ Dwarf_Unsigned add = 0;
+ Dwarf_Half rel_size = SHT_RELA == type ?
+ sizeof(Elf32_Rela) : sizeof(Elf32_Rel);
+ Dwarf_Unsigned off = 0;
+
+ printf("\n%s:\n", type== SHT_RELA?sectnamesa[section_no]:
+ sectnames[section_no]);
+
+
+ /* Print some headers and change the order for better reading. */
+ printf("Offset Addend %-26s Index Symbol Name\n","Reloc Type");
+
+ for (off = 0; off < size; off += rel_size) {
+ Elf32_Rel *p = (Elf32_Rel *) (buf + off);
+ char *name = 0;
+
+ if(sym_data) {
+ size_t index = ELF32_R_SYM(p->r_info) - 1;
+ if(index < sym_data_entry_count) {
+ name = sym_data[index].name;
+ }
+ }
+
+ /* When the name is not available, use the
+ section name as a reference for the name. */
+ if (!name || !name[0]) {
+ size_t index = ELF32_R_SYM(p->r_info) - 1;
+ if(index < sym_data_entry_count) {
+ SYM *sym = &sym_data[index];
+ if (sym->type == STT_SECTION&&
+ sym->shndx < scn_names_count) {
+ name = scn_names[sym->shndx];
+ }
+ }
+ }
+ if(!name || !name[0]) {
+ name = "<no name>";
+ }
+ if (SHT_RELA == type) {
+ Elf32_Rela *pa = (Elf32_Rela *)p;
+ add = pa->r_addend;
+ }
+ printf("0x%08lx 0x%08lx %-26s <%5ld> %s\n",
+ (unsigned long int) (p->r_offset),
+ (unsigned long int) (add),
+ get_reloc_type_names(ELF32_R_TYPE(p->r_info)),
+ (long)ELF32_R_SYM(p->r_info),
+ name);
+ }
+}
+
+static SYM *
+readsyms(Elf32_Sym * data, size_t num, Elf * elf, Elf32_Word link)
+{
+ SYM *s, *buf;
+ indx_type i;
+
+ buf = (SYM *) calloc(num, sizeof(SYM));
+ if (buf == NULL) {
+ return NULL;
+ }
+ s = buf; /* save pointer to head of array */
+ for (i = 1; i < num; i++, data++, buf++) {
+ buf->indx = i;
+ buf->name = (char *) elf_strptr(elf, link, data->st_name);
+ buf->value = data->st_value;
+ buf->size = data->st_size;
+ buf->type = ELF32_ST_TYPE(data->st_info);
+ buf->bind = ELF32_ST_BIND(data->st_info);
+ buf->other = data->st_other;
+ buf->shndx = data->st_shndx;
+ } /* end for loop */
+ return (s);
+}
+
+static SYM64 *
+read_64_syms(Elf64_Sym * data, size_t num, Elf * elf, Elf64_Word link)
+{
+#ifdef HAVE_ELF64_GETEHDR
+
+ SYM64 *s, *buf;
+ indx_type i;
+
+ buf = (SYM64 *) calloc(num, sizeof(SYM64));
+ if (buf == NULL) {
+ return NULL;
+ }
+ s = buf; /* save pointer to head of array */
+ for (i = 1; i < num; i++, data++, buf++) {
+ buf->indx = i;
+ buf->name = (char *) elf_strptr(elf, link, data->st_name);
+ buf->value = data->st_value;
+ buf->size = data->st_size;
+ buf->type = ELF64_ST_TYPE(data->st_info);
+ buf->bind = ELF64_ST_BIND(data->st_info);
+ buf->other = data->st_other;
+ buf->shndx = data->st_shndx;
+ } /* end for loop */
+ return (s);
+#else
+ return 0;
+#endif /* HAVE_ELF64_GETEHDR */
+}
+
+static void *
+get_scndata(Elf_Scn * fd_scn, size_t * scn_size)
+{
+ Elf_Data *p_data;
+
+ p_data = 0;
+ if ((p_data = elf_getdata(fd_scn, p_data)) == 0 ||
+ p_data->d_size == 0) {
+ return NULL;
+ }
+ *scn_size = p_data->d_size;
+ return (p_data->d_buf);
+}
+
+/* Cleanup of malloc space (some of the pointers will be 0 here)
+ so dwarfdump looks 'clean' to a malloc checker.
+*/
+void
+clean_up_syms_malloc_data()
+{
+ free(sym_data);
+ sym_data = 0;
+ free(sym_data_64);
+ sym_data_64 = 0;
+ sym_data_64_entry_count = 0;
+ sym_data_entry_count = 0;
+}
diff --git a/dwarfdump/print_reloc.h b/dwarfdump/print_reloc.h
new file mode 100644
index 0000000..d511b71
--- /dev/null
+++ b/dwarfdump/print_reloc.h
@@ -0,0 +1,307 @@
+/*
+ Copyright (C) 2000,2004,2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
+ Portions Copyright (C) 2011 SN Systems Ltd. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_reloc.c,v 1.11 2005/08/04 05:09:37 davea Exp $ */
+
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+/* PowerPC relocations defined by the ABIs */
+#define R_PPC_NONE 0
+#define R_PPC_ADDR32 1 /* 32bit absolute address */
+#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */
+#define R_PPC_ADDR16 3 /* 16bit absolute address */
+#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */
+#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */
+#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */
+#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */
+#define R_PPC_ADDR14_BRTAKEN 8
+#define R_PPC_ADDR14_BRNTAKEN 9
+#define R_PPC_REL24 10 /* PC relative 26 bit */
+#define R_PPC_REL14 11 /* PC relative 16 bit */
+#define R_PPC_REL14_BRTAKEN 12
+#define R_PPC_REL14_BRNTAKEN 13
+#define R_PPC_GOT16 14
+#define R_PPC_GOT16_LO 15
+#define R_PPC_GOT16_HI 16
+#define R_PPC_GOT16_HA 17
+#define R_PPC_PLTREL24 18
+#define R_PPC_COPY 19
+#define R_PPC_GLOB_DAT 20
+#define R_PPC_JMP_SLOT 21
+#define R_PPC_RELATIVE 22
+#define R_PPC_LOCAL24PC 23
+#define R_PPC_UADDR32 24
+#define R_PPC_UADDR16 25
+#define R_PPC_REL32 26
+#define R_PPC_PLT32 27
+#define R_PPC_PLTREL32 28
+#define R_PPC_PLT16_LO 29
+#define R_PPC_PLT16_HI 30
+#define R_PPC_PLT16_HA 31
+#define R_PPC_SDAREL16 32
+#define R_PPC_SECTOFF 33
+#define R_PPC_SECTOFF_LO 34
+#define R_PPC_SECTOFF_HI 35
+#define R_PPC_SECTOFF_HA 36
+
+/* Unused types */
+#define R_PPC_37 37
+#define R_PPC_38 38
+#define R_PPC_39 39
+#define R_PPC_40 40
+#define R_PPC_41 41
+#define R_PPC_42 42
+#define R_PPC_43 43
+#define R_PPC_44 44
+#define R_PPC_45 45
+#define R_PPC_46 46
+#define R_PPC_47 47
+#define R_PPC_48 48
+#define R_PPC_49 49
+#define R_PPC_50 50
+#define R_PPC_51 51
+#define R_PPC_52 52
+#define R_PPC_53 53
+#define R_PPC_54 54
+#define R_PPC_55 55
+
+/* Unused types */
+#define R_PPC_56 56
+#define R_PPC_57 57
+#define R_PPC_58 58
+#define R_PPC_59 59
+#define R_PPC_60 60
+#define R_PPC_61 61
+#define R_PPC_62 62
+#define R_PPC_63 63
+#define R_PPC_64 64
+#define R_PPC_65 65
+#define R_PPC_66 66
+
+/* PowerPC relocations defined for the TLS access ABI. */
+#define R_PPC_TLS 67 /* none (sym+add)@tls */
+#define R_PPC_DTPMOD32 68 /* word32 (sym+add)@dtpmod */
+#define R_PPC_TPREL16 69 /* half16* (sym+add)@tprel */
+#define R_PPC_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */
+#define R_PPC_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */
+#define R_PPC_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */
+#define R_PPC_TPREL32 73 /* word32 (sym+add)@tprel */
+#define R_PPC_DTPREL16 74 /* half16* (sym+add)@dtprel */
+#define R_PPC_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */
+#define R_PPC_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */
+#define R_PPC_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */
+#define R_PPC_DTPREL32 78 /* word32 (sym+add)@dtprel */
+#define R_PPC_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */
+#define R_PPC_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */
+#define R_PPC_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */
+#define R_PPC_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */
+#define R_PPC_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */
+#define R_PPC_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */
+#define R_PPC_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */
+#define R_PPC_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */
+#define R_PPC_GOT_TPREL16 87 /* half16* (sym+add)@got@tprel */
+#define R_PPC_GOT_TPREL16_LO 88 /* half16 (sym+add)@got@tprel@l */
+#define R_PPC_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */
+#define R_PPC_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */
+#define R_PPC_GOT_DTPREL16 91 /* half16* (sym+add)@got@dtprel */
+#define R_PPC_GOT_DTPREL16_LO 92 /* half16* (sym+add)@got@dtprel@l */
+#define R_PPC_GOT_DTPREL16_HI 93 /* half16* (sym+add)@got@dtprel@h */
+#define R_PPC_GOT_DTPREL16_HA 94 /* half16* (sym+add)@got@dtprel@ha */
+
+/* Keep this the last entry. */
+#define R_PPC_NUM 95
+
+/* PowerPC64 relocations defined by the ABIs */
+#define R_PPC64_NONE R_PPC_NONE
+#define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address. */
+#define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned. */
+#define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address. */
+#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of abs. address. */
+#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of abs. address. */
+#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */
+#define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned. */
+#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN
+#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN
+#define R_PPC64_REL24 R_PPC_REL24 /* PC relative 26 bit, word aligned. */
+#define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit. */
+#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN
+#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN
+#define R_PPC64_GOT16 R_PPC_GOT16
+#define R_PPC64_GOT16_LO R_PPC_GOT16_LO
+#define R_PPC64_GOT16_HI R_PPC_GOT16_HI
+#define R_PPC64_GOT16_HA R_PPC_GOT16_HA
+
+#define R_PPC64_COPY R_PPC_COPY
+#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT
+#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT
+#define R_PPC64_RELATIVE R_PPC_RELATIVE
+
+#define R_PPC64_UADDR32 R_PPC_UADDR32
+#define R_PPC64_UADDR16 R_PPC_UADDR16
+#define R_PPC64_REL32 R_PPC_REL32
+#define R_PPC64_PLT32 R_PPC_PLT32
+#define R_PPC64_PLTREL32 R_PPC_PLTREL32
+#define R_PPC64_PLT16_LO R_PPC_PLT16_LO
+#define R_PPC64_PLT16_HI R_PPC_PLT16_HI
+#define R_PPC64_PLT16_HA R_PPC_PLT16_HA
+
+#define R_PPC64_SECTOFF R_PPC_SECTOFF
+#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO
+#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI
+#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA
+#define R_PPC64_ADDR30 37 /* word30 (S + A - P) >> 2. */
+#define R_PPC64_ADDR64 38 /* doubleword64 S + A. */
+#define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A). */
+#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A). */
+#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A). */
+#define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A). */
+#define R_PPC64_UADDR64 43 /* doubleword64 S + A. */
+#define R_PPC64_REL64 44 /* doubleword64 S + A - P. */
+#define R_PPC64_PLT64 45 /* doubleword64 L + A. */
+#define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P. */
+#define R_PPC64_TOC16 47 /* half16* S + A - .TOC. */
+#define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.). */
+#define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.). */
+#define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.). */
+#define R_PPC64_TOC 51 /* doubleword64 .TOC. */
+#define R_PPC64_PLTGOT16 52 /* half16* M + A. */
+#define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A). */
+#define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A). */
+#define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A). */
+
+#define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2. */
+#define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2. */
+#define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2. */
+#define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2. */
+#define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2. */
+#define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2. */
+#define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2. */
+#define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2. */
+#define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2. */
+#define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2. */
+#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2. */
+
+/* PowerPC64 relocations defined for the TLS access ABI. */
+#define R_PPC64_TLS 67 /* none (sym+add)@tls */
+#define R_PPC64_DTPMOD64 68 /* doubleword64 (sym+add)@dtpmod */
+#define R_PPC64_TPREL16 69 /* half16* (sym+add)@tprel */
+#define R_PPC64_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */
+#define R_PPC64_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */
+#define R_PPC64_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */
+#define R_PPC64_TPREL64 73 /* doubleword64 (sym+add)@tprel */
+#define R_PPC64_DTPREL16 74 /* half16* (sym+add)@dtprel */
+#define R_PPC64_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */
+#define R_PPC64_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */
+#define R_PPC64_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */
+#define R_PPC64_DTPREL64 78 /* doubleword64 (sym+add)@dtprel */
+#define R_PPC64_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */
+#define R_PPC64_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */
+#define R_PPC64_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */
+#define R_PPC64_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */
+#define R_PPC64_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */
+#define R_PPC64_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */
+#define R_PPC64_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */
+#define R_PPC64_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */
+#define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got@tprel */
+#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got@tprel@l */
+#define R_PPC64_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */
+#define R_PPC64_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */
+#define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds* (sym+add)@got@dtprel */
+#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got@dtprel@l */
+#define R_PPC64_GOT_DTPREL16_HI 93 /* half16 (sym+add)@got@dtprel@h */
+#define R_PPC64_GOT_DTPREL16_HA 94 /* half16 (sym+add)@got@dtprel@ha */
+#define R_PPC64_TPREL16_DS 95 /* half16ds* (sym+add)@tprel */
+#define R_PPC64_TPREL16_LO_DS 96 /* half16ds (sym+add)@tprel@l */
+#define R_PPC64_TPREL16_HIGHER 97 /* half16 (sym+add)@tprel@higher */
+#define R_PPC64_TPREL16_HIGHERA 98 /* half16 (sym+add)@tprel@highera */
+#define R_PPC64_TPREL16_HIGHEST 99 /* half16 (sym+add)@tprel@highest */
+#define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel@highesta */
+#define R_PPC64_DTPREL16_DS 101 /* half16ds* (sym+add)@dtprel */
+#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel@l */
+#define R_PPC64_DTPREL16_HIGHER 103 /* half16 (sym+add)@dtprel@higher */
+#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */
+#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */
+#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel@highesta */
+
+/* Additional relocation types */
+#define R_PPC64_TOC32 107
+#define R_PPC64_DTPMOD32 108
+#define R_PPC64_TPREL32 109
+#define R_PPC64_DTPREL32 110
+
+/* Keep this the last entry. */
+#define R_PPC64_NUM 111
+
+/* Relocation types for MIPS */
+#define R_MIPS_NONE 0
+#define R_MIPS_16 1
+#define R_MIPS_32 2
+#define R_MIPS_ADD 2
+#define R_MIPS_REL 3
+#define R_MIPS_REL32 3
+#define R_MIPS_26 4
+#define R_MIPS_HI16 5
+#define R_MIPS_LO16 6
+#define R_MIPS_GPREL 7
+#define R_MIPS_GPREL16 7
+#define R_MIPS_LITERAL 8
+#define R_MIPS_GOT 9
+#define R_MIPS_GOT16 9
+#define R_MIPS_PC16 10
+#define R_MIPS_CALL 11
+#define R_MIPS_CALL16 11
+#define R_MIPS_GPREL32 12
+
+#define R_MIPS_SHIFT5 16
+#define R_MIPS_SHIFT6 17
+#define R_MIPS_64 18
+#define R_MIPS_GOT_DISP 19
+#define R_MIPS_GOT_PAGE 20
+#define R_MIPS_GOT_OFST 21
+#define R_MIPS_GOT_HI16 22
+#define R_MIPS_GOT_LO16 23
+#define R_MIPS_SUB 24
+#define R_MIPS_INSERT_A 25
+#define R_MIPS_INSERT_B 26
+#define R_MIPS_DELETE 27
+#define R_MIPS_HIGHER 28
+#define R_MIPS_HIGHEST 29
+#define R_MIPS_CALL_HI16 30
+#define R_MIPS_CALL_LO16 31
+#define R_MIPS_SCN_DISP 32
+#define R_MIPS_REL16 33
+#define R_MIPS_ADD_IMMEDIATE 34
diff --git a/dwarfdump/print_sections.c b/dwarfdump/print_sections.c
new file mode 100644
index 0000000..a5e6ef1
--- /dev/null
+++ b/dwarfdump/print_sections.c
@@ -0,0 +1,206 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include "globals.h"
+#include "naming.h"
+#include "dwconf.h"
+#include "esb.h"
+
+#include "print_sections.h"
+#include "print_frames.h"
+
+/*
+ Print line number information:
+ filename
+ new basic-block
+ [line] [address] <new statement>
+*/
+
+int dwarf_names_print_on_error = 1;
+
+/* referred in dwarfdump.c */
+Dwarf_Die current_cu_die_for_print_frames;
+
+void
+deal_with_name_offset_err(Dwarf_Debug dbg,
+ char *err_loc,
+ char *name, Dwarf_Unsigned die_off,
+ int nres, Dwarf_Error err)
+{
+ if (nres == DW_DLV_ERROR) {
+ Dwarf_Unsigned myerr = dwarf_errno(err);
+
+ if (myerr == DW_DLE_OFFSET_BAD) {
+ printf("Error: bad offset %s, %s %" DW_PR_DUu
+ " (0x%08" DW_PR_DUx ")\n",
+ err_loc,
+ name,
+ die_off,
+ die_off);
+ }
+ print_error(dbg, err_loc, nres, err);
+ }
+}
+
+
+
+/* The April 2005 dwarf_get_section_max_offsets()
+ in libdwarf returns all max-offsets, but we only
+ want one of those offsets. This function returns
+ the one we want from that set,
+ making functions needing this offset as readable as possible.
+ (avoiding code duplication).
+*/
+Dwarf_Unsigned
+get_info_max_offset(Dwarf_Debug dbg)
+{
+ Dwarf_Unsigned debug_info_size = 0;
+ Dwarf_Unsigned debug_abbrev_size = 0;
+ Dwarf_Unsigned debug_line_size = 0;
+ Dwarf_Unsigned debug_loc_size = 0;
+ Dwarf_Unsigned debug_aranges_size = 0;
+ Dwarf_Unsigned debug_macinfo_size = 0;
+ Dwarf_Unsigned debug_pubnames_size = 0;
+ Dwarf_Unsigned debug_str_size = 0;
+ Dwarf_Unsigned debug_frame_size = 0;
+ Dwarf_Unsigned debug_ranges_size = 0;
+ Dwarf_Unsigned debug_pubtypes_size = 0;
+
+ dwarf_get_section_max_offsets(dbg,
+ &debug_info_size,
+ &debug_abbrev_size,
+ &debug_line_size,
+ &debug_loc_size,
+ &debug_aranges_size,
+ &debug_macinfo_size,
+ &debug_pubnames_size,
+ &debug_str_size,
+ &debug_frame_size,
+ &debug_ranges_size,
+ &debug_pubtypes_size);
+
+ return debug_info_size;
+}
+
+/*
+ decode ULEB
+*/
+Dwarf_Unsigned
+local_dwarf_decode_u_leb128(unsigned char *leb128,
+ unsigned int *leb128_length)
+{
+ unsigned char byte = 0;
+ Dwarf_Unsigned number = 0;
+ unsigned int shift = 0;
+ unsigned int byte_length = 1;
+
+ byte = *leb128;
+ for (;;) {
+ number |= (byte & 0x7f) << shift;
+ shift += 7;
+
+ if ((byte & 0x80) == 0) {
+ if (leb128_length != NULL)
+ *leb128_length = byte_length;
+ return (number);
+ }
+
+ byte_length++;
+ byte = *(++leb128);
+ }
+}
+
+#define BITSINBYTE 8
+Dwarf_Signed
+local_dwarf_decode_s_leb128(unsigned char *leb128,
+ unsigned int *leb128_length)
+{
+ Dwarf_Signed number = 0;
+ Dwarf_Bool sign = 0;
+ Dwarf_Signed shift = 0;
+ unsigned char byte = *leb128;
+ Dwarf_Signed byte_length = 1;
+
+ /* byte_length being the number of bytes of data absorbed so far in
+ turning the leb into a Dwarf_Signed. */
+
+ for (;;) {
+ sign = byte & 0x40;
+ number |= ((Dwarf_Signed) ((byte & 0x7f))) << shift;
+ shift += 7;
+
+ if ((byte & 0x80) == 0) {
+ break;
+ }
+ ++leb128;
+ byte = *leb128;
+ byte_length++;
+ }
+
+ if ((shift < sizeof(Dwarf_Signed) * BITSINBYTE) && sign) {
+ number |= -((Dwarf_Signed) 1 << shift);
+ }
+
+ if (leb128_length != NULL)
+ *leb128_length = byte_length;
+ return (number);
+}
+
+
+/* Dumping a dwarf-expression as a byte stream. */
+void
+dump_block(char *prefix, char *data, Dwarf_Signed len)
+{
+ char *end_data = data + len;
+ char *cur = data;
+ int i = 0;
+
+ printf("%s", prefix);
+ for (; cur < end_data; ++cur, ++i) {
+ if (i > 0 && i % 4 == 0)
+ printf(" ");
+ printf("%02x", 0xff & *cur);
+
+ }
+}
+
diff --git a/dwarfdump/print_sections.h b/dwarfdump/print_sections.h
new file mode 100644
index 0000000..63015cd
--- /dev/null
+++ b/dwarfdump/print_sections.h
@@ -0,0 +1,54 @@
+/*
+ Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+*/
+
+
+extern int dwarf_names_print_on_error;
+
+void deal_with_name_offset_err(Dwarf_Debug dbg,
+ char *err_loc,
+ char *name,
+ Dwarf_Unsigned die_off,
+ int nres,
+ Dwarf_Error err);
+
+Dwarf_Unsigned get_info_max_offset(Dwarf_Debug dbg);
+
+void print_pubname_style_entry(Dwarf_Debug dbg,
+ char *line_title,
+ char *name,
+ Dwarf_Unsigned die_off,
+ Dwarf_Unsigned cu_off,
+ Dwarf_Unsigned global_cu_off,
+ Dwarf_Unsigned maxoff);
diff --git a/dwarfdump/print_static_funcs.c b/dwarfdump/print_static_funcs.c
new file mode 100644
index 0000000..c3dc59d
--- /dev/null
+++ b/dwarfdump/print_static_funcs.c
@@ -0,0 +1,137 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2011 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include "globals.h"
+#include "naming.h"
+#include "dwconf.h"
+#include "esb.h"
+
+#include "print_sections.h"
+#include "print_frames.h"
+
+
+/* Get all the data in .debug_static_funcs
+ On error, this allows some dwarf memory leaks.
+*/
+extern void
+print_static_funcs(Dwarf_Debug dbg)
+{
+ Dwarf_Func *funcbuf = NULL;
+ Dwarf_Signed count = 0;
+ Dwarf_Signed i = 0;
+ Dwarf_Off die_off = 0;
+ Dwarf_Off cu_off = 0;
+ int gfres = 0;
+
+ current_section_id = DEBUG_STATIC_FUNC;
+
+ if (!do_print_dwarf) {
+ return;
+ }
+
+ printf("\n.debug_static_func\n");
+ gfres = dwarf_get_funcs(dbg, &funcbuf, &count, &err);
+ if (gfres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_funcs", gfres, err);
+ } else if (gfres == DW_DLV_NO_ENTRY) {
+ /* no static funcs */
+ } else {
+ Dwarf_Unsigned maxoff = get_info_max_offset(dbg);
+
+ for (i = 0; i < count; i++) {
+ int fnres = 0;
+ int cures3 = 0;
+ Dwarf_Unsigned global_cu_off = 0;
+ char *name = 0;
+
+ fnres = dwarf_func_name_offsets(funcbuf[i], &name, &die_off,
+ &cu_off, &err);
+ deal_with_name_offset_err(dbg, "dwarf_func_name_offsets",
+ name, die_off, fnres, err);
+ cures3 = dwarf_func_cu_offset(funcbuf[i],
+ &global_cu_off, &err);
+ if (cures3 != DW_DLV_OK) {
+ print_error(dbg, "dwarf_global_cu_offset", cures3, err);
+ }
+
+ if (check_pubname_attr) {
+ Dwarf_Bool has_attr;
+ int ares;
+ int dres;
+ Dwarf_Die die;
+
+ /* get die at die_off */
+ dres = dwarf_offdie(dbg, die_off, &die, &err);
+ if (dres != DW_DLV_OK) {
+ print_error(dbg, "dwarf_offdie", dres, err);
+ }
+
+
+ ares =
+ dwarf_hasattr(die, DW_AT_external, &has_attr, &err);
+ if (ares == DW_DLV_ERROR) {
+ print_error(dbg, "hassattr on DW_AT_external", ares,
+ err);
+ }
+ if (checking_this_compiler()) {
+ DWARF_CHECK_COUNT(pubname_attr_result,1);
+ if (ares == DW_DLV_OK && has_attr) {
+ /* Should the value of flag be examined? */
+ } else {
+ DWARF_CHECK_ERROR2(pubname_attr_result,name,
+ "pubname (in static funcs section) does not have DW_AT_external");
+ }
+ }
+ dwarf_dealloc(dbg, die, DW_DLA_DIE);
+ }
+
+ if (do_print_dwarf || record_dwarf_error) {
+ print_pubname_style_entry(dbg,
+ "static-func", name, die_off,
+ cu_off, global_cu_off, maxoff);
+ record_dwarf_error = FALSE; /* Clear error condition */
+ }
+ }
+ dwarf_funcs_dealloc(dbg, funcbuf, count);
+ }
+} /* print_static_funcs() */
diff --git a/dwarfdump/print_static_vars.c b/dwarfdump/print_static_vars.c
new file mode 100644
index 0000000..5e42b67
--- /dev/null
+++ b/dwarfdump/print_static_vars.c
@@ -0,0 +1,104 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+ $Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include "globals.h"
+#include "naming.h"
+#include "dwconf.h"
+#include "esb.h"
+
+#include "print_sections.h"
+#include "print_frames.h"
+
+/* Get all the data in .debug_static_vars */
+extern void
+print_static_vars(Dwarf_Debug dbg)
+{
+ Dwarf_Var *varbuf = NULL;
+ Dwarf_Signed count = 0;
+ Dwarf_Signed i = 0;
+ Dwarf_Off die_off = 0;
+ Dwarf_Off cu_off = 0;
+ char *name = 0;
+ int gvres = 0;
+
+ current_section_id = DEBUG_STATIC_VARS;
+
+ if (!do_print_dwarf) {
+ return;
+ }
+
+ printf("\n.debug_static_vars\n");
+ gvres = dwarf_get_vars(dbg, &varbuf, &count, &err);
+ if (gvres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_vars", gvres, err);
+ } else if (gvres == DW_DLV_NO_ENTRY) {
+ /* no static vars */
+ } else {
+ Dwarf_Unsigned maxoff = get_info_max_offset(dbg);
+
+ for (i = 0; i < count; i++) {
+ int vnres = 0;
+ int cures3 = 0;
+ Dwarf_Off global_cu_off = 0;
+
+ vnres = dwarf_var_name_offsets(varbuf[i], &name, &die_off,
+ &cu_off, &err);
+ deal_with_name_offset_err(dbg,
+ "dwarf_var_name_offsets",
+ name, die_off, vnres, err);
+ cures3 = dwarf_var_cu_offset(varbuf[i],
+ &global_cu_off, &err);
+ if (cures3 != DW_DLV_OK) {
+ print_error(dbg, "dwarf_global_cu_offset", cures3, err);
+ }
+
+ print_pubname_style_entry(dbg,
+ "static-var",
+ name, die_off, cu_off,
+ global_cu_off, maxoff);
+
+ /* print associated die too? */
+ }
+ dwarf_vars_dealloc(dbg, varbuf, count);
+ }
+} /* print_static_vars */
+
diff --git a/dwarfdump/print_strings.c b/dwarfdump/print_strings.c
new file mode 100644
index 0000000..0cd67b3
--- /dev/null
+++ b/dwarfdump/print_strings.c
@@ -0,0 +1,80 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include "globals.h"
+#include "naming.h"
+#include "dwconf.h"
+#include "esb.h"
+
+#include "print_sections.h"
+
+/* print data in .debug_string */
+extern void
+print_strings(Dwarf_Debug dbg)
+{
+ Dwarf_Signed length = 0;
+ string name;
+ Dwarf_Off offset = 0;
+ int sres = 0;
+
+ current_section_id = DEBUG_STR;
+ printf("\n.debug_string\n");
+ while ((sres = dwarf_get_str(dbg, offset, &name, &length, &err))
+ == DW_DLV_OK) {
+ if (display_offsets) {
+ printf("name at offset 0x%" DW_PR_XZEROS DW_PR_DUx
+ ", length %4" DW_PR_DSd " is '%s'\n",
+ (Dwarf_Unsigned)offset, length, name);
+ } else {
+ printf("name: length %4" DW_PR_DSd " is '%s'\n",
+ length, name);
+ }
+ offset += length + 1;
+ }
+ /* An inability to find the section is not necessarily
+ a real error, so do not report error unless we've
+ seen a real record. */
+ if(sres == DW_DLV_ERROR && offset != 0) {
+ print_error(dbg, "dwarf_get_str failure", sres, err);
+ }
+}
diff --git a/dwarfdump/print_types.c b/dwarfdump/print_types.c
new file mode 100644
index 0000000..f3fddba
--- /dev/null
+++ b/dwarfdump/print_types.c
@@ -0,0 +1,141 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include "globals.h"
+#include "naming.h"
+#include "dwconf.h"
+#include "esb.h"
+
+#include "print_sections.h"
+#include "print_frames.h"
+
+/* get all the data in .debug_types */
+extern void
+print_types(Dwarf_Debug dbg, enum type_type_e type_type)
+{
+ Dwarf_Type *typebuf = NULL;
+ Dwarf_Signed count = 0;
+ Dwarf_Signed i = 0;
+ char *name = NULL;
+ int gtres = 0;
+
+ char *section_name = NULL;
+ char *offset_err_name = NULL;
+ char *section_open_name = NULL;
+ char *print_name_prefix = NULL;
+ int (*get_types) (Dwarf_Debug, Dwarf_Type **, Dwarf_Signed *,
+ Dwarf_Error *) = 0;
+ int (*get_offset) (Dwarf_Type, char **, Dwarf_Off *, Dwarf_Off *,
+ Dwarf_Error *) = NULL;
+ int (*get_cu_offset) (Dwarf_Type, Dwarf_Off *, Dwarf_Error *) =
+ NULL;
+ void (*dealloctype) (Dwarf_Debug, Dwarf_Type *, Dwarf_Signed) =
+ NULL;
+
+ /* Do nothing if in check mode */
+ if (!do_print_dwarf) {
+ return;
+ }
+
+
+ if (type_type == DWARF_PUBTYPES) {
+ section_name = ".debug_pubtypes";
+ offset_err_name = "dwarf_pubtype_name_offsets";
+ section_open_name = "dwarf_get_pubtypes";
+ print_name_prefix = "pubtype";
+ get_types = dwarf_get_pubtypes;
+ get_offset = dwarf_pubtype_name_offsets;
+ get_cu_offset = dwarf_pubtype_cu_offset;
+ dealloctype = dwarf_pubtypes_dealloc;
+ } else {
+ /* SGI_TYPENAME */
+ section_name = ".debug_typenames";
+ offset_err_name = "dwarf_type_name_offsets";
+ section_open_name = "dwarf_get_types";
+ print_name_prefix = "type";
+ get_types = dwarf_get_types;
+ get_offset = dwarf_type_name_offsets;
+ get_cu_offset = dwarf_type_cu_offset;
+ dealloctype = dwarf_types_dealloc;
+ }
+
+
+
+ gtres = get_types(dbg, &typebuf, &count, &err);
+ if (gtres == DW_DLV_ERROR) {
+ print_error(dbg, section_open_name, gtres, err);
+ } else if (gtres == DW_DLV_NO_ENTRY) {
+ /* no types */
+ } else {
+ Dwarf_Unsigned maxoff = get_info_max_offset(dbg);
+
+ /* Before July 2005, the section name was printed
+ unconditionally, now only prints if non-empty section really
+ exists. */
+ printf("\n%s\n", section_name);
+
+ for (i = 0; i < count; i++) {
+ int tnres = 0;
+ int cures3 = 0;
+ Dwarf_Off die_off = 0;
+ Dwarf_Off cu_off = 0;
+ Dwarf_Off global_cu_off = 0;
+
+ tnres =
+ get_offset(typebuf[i], &name, &die_off, &cu_off, &err);
+ deal_with_name_offset_err(dbg, offset_err_name, name,
+ die_off, tnres, err);
+ cures3 = get_cu_offset(typebuf[i], &global_cu_off, &err);
+ if (cures3 != DW_DLV_OK) {
+ print_error(dbg, "dwarf_var_cu_offset", cures3, err);
+ }
+ print_pubname_style_entry(dbg,
+ print_name_prefix,
+ name, die_off, cu_off,
+ global_cu_off, maxoff);
+
+ /* print associated die too? */
+ }
+ dealloctype(dbg, typebuf, count);
+ }
+} /* print_types() */
diff --git a/dwarfdump/print_weaknames.c b/dwarfdump/print_weaknames.c
new file mode 100644
index 0000000..fd60ea8
--- /dev/null
+++ b/dwarfdump/print_weaknames.c
@@ -0,0 +1,104 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2011 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+ $Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include "globals.h"
+#include "naming.h"
+#include "dwconf.h"
+#include "esb.h"
+
+#include "print_sections.h"
+
+/* Get all the data in .debug_weaknames */
+extern void
+print_weaknames(Dwarf_Debug dbg)
+{
+ Dwarf_Weak *weaknamebuf = NULL;
+ Dwarf_Signed count = 0;
+ Dwarf_Signed i = 0;
+ Dwarf_Off die_off = 0;
+ Dwarf_Off cu_off = 0;
+ char *name = NULL;
+ int wkres = 0;
+
+ current_section_id = DEBUG_WEAKNAMES;
+
+ if (!do_print_dwarf) {
+ return;
+ }
+ printf("\n.debug_weaknames\n");
+ wkres = dwarf_get_weaks(dbg, &weaknamebuf, &count, &err);
+ if (wkres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_weaks", wkres, err);
+ } else if (wkres == DW_DLV_NO_ENTRY) {
+ /* no weaknames */
+ } else {
+ Dwarf_Unsigned maxoff = get_info_max_offset(dbg);
+
+ for (i = 0; i < count; i++) {
+ int tnres = 0;
+ int cures3 = 0;
+ Dwarf_Unsigned global_cu_off = 0;
+
+ tnres = dwarf_weak_name_offsets(weaknamebuf[i],
+ &name, &die_off, &cu_off,
+ &err);
+ deal_with_name_offset_err(dbg,
+ "dwarf_weak_name_offsets",
+ name, die_off, tnres, err);
+ cures3 = dwarf_weak_cu_offset(weaknamebuf[i],
+ &global_cu_off, &err);
+ if (cures3 != DW_DLV_OK) {
+ print_error(dbg, "dwarf_weakname_cu_offset",
+ cures3, err);
+ }
+ print_pubname_style_entry(dbg,
+ "weakname",
+ name, die_off, cu_off,
+ global_cu_off, maxoff);
+
+ /* print associated die too? */
+ }
+ dwarf_weaks_dealloc(dbg, weaknamebuf, count);
+ }
+} /* print_weaknames() */
diff --git a/dwarfdump/strstrnocase.c b/dwarfdump/strstrnocase.c
new file mode 100755
index 0000000..082af66
--- /dev/null
+++ b/dwarfdump/strstrnocase.c
@@ -0,0 +1,118 @@
+/*
+ Copyright (C) 2009-2010 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+
+
+/*
+This tries to find the string 'contained' in the
+string 'container'. it returns true if found, else false.
+The comparisons are independent of case.
+
+Regrettably there is no generally accepted version that
+does this job, though GNU Linux has strcasestr() which
+does what we need. Our code here do not behave like
+strstr or strcasestr in the case of
+an empty 'contained' argument: we return FALSE (this
+case is not interesting for dwarfdump).
+
+There is a public domain stristr(). But given that dwarfdump is GPL,
+it would seem (IANAL) that we cannot mix public domain code
+into the release.
+
+The software here is independently written and indeed trivial.
+
+The POSIX function tolower() is only properly defined on unsigned char, hence
+the ugly casts.
+
+strstrnocase.c
+
+*/
+#include <ctype.h>
+#include <stdio.h>
+#include <globals.h>
+
+boolean
+is_strstrnocase(const char * container, const char * contained)
+{
+ const unsigned char *ct = (const unsigned char *)container;
+ for( ; *ct; ++ct )
+ {
+ const unsigned char * cntnd = (const unsigned char *)contained;
+ boolean innerwrong = TRUE;
+ for( ; *cntnd; ++cntnd,++ct)
+ {
+ char lct = tolower(*ct);
+ char tlc = tolower(*cntnd);
+ if(lct != tlc) {
+ innerwrong=TRUE;
+ break; /* Go to outer loop */
+ }
+ innerwrong=FALSE;
+ }
+ if(!innerwrong) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+#ifdef TEST
+static void
+test(const char *t1, const char *t2,int resexp)
+{
+ boolean res = is_strstrnocase(t1,t2);
+ if (res == resexp) {
+ return;
+ }
+ printf("Error,mismatch %s and %s. Expected %d got %d\n",
+ t1,t2,resexp,res);
+}
+
+int main()
+{
+ test("aaaaa","a",1);
+ test("aaaaa","b",0);
+ test("abaaba","ba",1);
+ test("abaaxa","x",1);
+ test("abaabA","Ba",1);
+ test("a","ab",0);
+ test("b","c",0);
+ test("b","",0);
+ test("","c",0);
+ test("","",0);
+ test("aaaaa","aaaaaaaa",0);
+}
+#endif
diff --git a/dwarfdump/tag_attr.c b/dwarfdump/tag_attr.c
new file mode 100644
index 0000000..899a357
--- /dev/null
+++ b/dwarfdump/tag_attr.c
@@ -0,0 +1,286 @@
+/*
+ Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2009-2010 SN Systems Ltd. All Rights Reserved.
+ Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/tag_attr.c,v 1.8 2005/12/01 17:34:59 davea Exp $ */
+#include <dwarf.h>
+#include <stdio.h>
+#include <stdlib.h> /* For exit() declaration etc. */
+#include <errno.h> /* For errno declaration. */
+#include <unistd.h> /* For getopt. */
+
+#include "globals.h"
+#include "libdwarf.h"
+#include "common.h"
+#include "tag_common.h"
+
+boolean ellipsis = FALSE; /* So we can use dwarf_names.c */
+
+/* Expected input format
+
+0xffffffff
+value of a tag
+value of a standard attribute that follows that tag
+...
+0xffffffff
+value of a tag
+value of a standard attribute that follows that tag
+...
+0xffffffff
+...
+
+No blank lines or commentary allowed, no symbols, just numbers.
+
+
+*/
+
+unsigned int tag_attr_combination_table[ATTR_TABLE_ROW_MAXIMUM][ATTR_TABLE_COLUMN_MAXIMUM];
+
+
+static const char *usage[] = {
+ "Usage: tag_attr_build <options>",
+ " -i input-table-path",
+ " -o output-table-path",
+ " -s (Generate standard attribute table)",
+ " -e (Generate extended attribute table (common extensions))",
+ ""
+};
+
+char *program_name = 0;
+char *input_name = 0;
+char *output_name = 0;
+int standard_flag = FALSE;
+int extended_flag = FALSE;
+
+/* process arguments */
+void
+process_args(int argc, char *argv[])
+{
+ int c = 0;
+ boolean usage_error = FALSE;
+
+ program_name = argv[0];
+
+ while ((c = getopt(argc, argv, "i:o:se")) != EOF) {
+ switch (c) {
+ case 'i':
+ input_name = optarg;
+ break;
+ case 'o':
+ output_name = optarg;
+ break;
+ case 'e':
+ extended_flag = TRUE;
+ break;
+ case 's':
+ standard_flag = TRUE;
+ break;
+ default:
+ usage_error = TRUE;
+ break;
+ }
+ }
+
+ if (usage_error || 1 == optind || optind != argc) {
+ print_usage_message(argv[0],usage);
+ exit(FAILED);
+ }
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+ int i = 0;
+ unsigned int num = 0;
+ int input_eof = 0;
+ int table_rows = 0;
+ int table_columns = 0;
+ int current_row = 0;
+ FILE * fileInp = 0;
+ FILE * fileOut = 0;
+
+ print_version_details(argv[0],FALSE);
+ process_args(argc,argv);
+ print_args(argc,argv);
+
+ if (!input_name ) {
+ fprintf(stderr,"Input name required, not supplied.\n");
+ print_usage_message(argv[0],usage);
+ exit(FAILED);
+ }
+ fileInp = fopen(input_name,"r");
+ if (!fileInp) {
+ fprintf(stderr,"Invalid input filename, could not open '%s'\n",
+ input_name);
+ print_usage_message(argv[0],usage);
+ exit(FAILED);
+ }
+
+
+ if (!output_name ) {
+ fprintf(stderr,"Output name required, not supplied.\n");
+ print_usage_message(argv[0],usage);
+ exit(FAILED);
+ }
+ fileOut = fopen(output_name,"w");
+ if (!fileOut) {
+ fprintf(stderr,"Invalid output filename, could not open: '%s'\n",
+ output_name);
+ print_usage_message(argv[0],usage);
+ exit(FAILED);
+ }
+ if ((standard_flag && extended_flag) ||
+ (!standard_flag && !extended_flag)) {
+ fprintf(stderr,"Invalid table type\n");
+ fprintf(stderr,"Choose -e or -s .\n");
+ print_usage_message(argv[0],usage);
+ exit(FAILED);
+ }
+
+
+ if(standard_flag) {
+ table_rows = STD_ATTR_TABLE_ROWS;
+ table_columns = STD_ATTR_TABLE_COLUMNS;
+ } else {
+ table_rows = EXT_ATTR_TABLE_ROWS;
+ table_columns = EXT_ATTR_TABLE_COLS;
+ }
+
+ input_eof = read_value(&num,fileInp); /* 0xffffffff */
+ if (IS_EOF == input_eof) {
+ bad_line_input("Empty input file");
+ }
+ if (num != MAGIC_TOKEN_VALUE) {
+ bad_line_input("Expected 0xffffffff");
+ }
+ while (!feof(stdin)) {
+ unsigned int tag;
+ int curcol = 0;
+
+ input_eof = read_value(&tag,fileInp);
+ if (IS_EOF == input_eof) {
+ /* Reached normal eof */
+ break;
+ }
+ if(standard_flag) {
+ if (tag >= table_rows ) {
+ bad_line_input("tag value exceeds standard table size");
+ }
+ } else {
+ if(current_row >= table_rows) {
+ bad_line_input("too many extended table rows.");
+ }
+ tag_attr_combination_table[current_row][0] = tag;
+ }
+
+ input_eof = read_value(&num,fileInp);
+ if (IS_EOF == input_eof) {
+ bad_line_input("Not terminated correctly..");
+ }
+ curcol = 1;
+ while (num != MAGIC_TOKEN_VALUE) {
+ if(standard_flag) {
+ unsigned idx = num / BITS_PER_WORD;
+ unsigned bit = num % BITS_PER_WORD;
+
+ if (idx >= table_columns) {
+ bad_line_input
+ ("too many attributes: table incomplete.");
+ }
+ tag_attr_combination_table[tag][idx] |= (1 << bit);
+ } else {
+ if (curcol >= table_columns) {
+ bad_line_input("too many attributes: table incomplete.");
+ }
+ tag_attr_combination_table[current_row][curcol] = num;
+ curcol++;
+
+ }
+ input_eof = read_value(&num,fileInp);
+ if (IS_EOF == input_eof) {
+ bad_line_input("Not terminated correctly.");
+ }
+ }
+ ++current_row;
+ }
+ fprintf(fileOut,"/* Generated code, do not edit. */\n");
+ fprintf(fileOut,"/* Generated on %s %s */\n",__DATE__,__TIME__);
+ fprintf(fileOut,"\n/* BEGIN FILE */\n\n");
+ if (standard_flag) {
+ fprintf(fileOut,"#define ATTR_TREE_ROW_COUNT %d\n\n",table_rows);
+ fprintf(fileOut,"#define ATTR_TREE_COLUMN_COUNT %d\n\n",table_columns);
+ fprintf(fileOut,
+ "static unsigned int tag_attr_combination_table"
+ "[ATTR_TREE_ROW_COUNT][ATTR_TREE_COLUMN_COUNT] = {\n");
+ }
+ else {
+ fprintf(fileOut,"/* Common extensions */\n");
+ fprintf(fileOut,"#define ATTR_TREE_EXT_ROW_COUNT %d\n\n",table_rows);
+ fprintf(fileOut,"#define ATTR_TREE_EXT_COLUMN_COUNT %d\n\n",
+ table_columns);
+ fprintf(fileOut,
+ "static unsigned int tag_attr_combination_ext_table"
+ "[ATTR_TREE_EXT_ROW_COUNT][ATTR_TREE_EXT_COLUMN_COUNT] = {\n");
+ }
+
+ for (i = 0; i < table_rows; i++) {
+ int j = 0;
+ const char *name = 0;
+ if(standard_flag) {
+ dwarf_get_TAG_name(i,&name);
+ fprintf(fileOut,"/* %d %-37s*/\n",i,name);
+ } else {
+ int k = tag_attr_combination_table[i][0];
+ dwarf_get_TAG_name(k,&name);
+ fprintf(fileOut,"/* %u %-37s*/\n",k,name);
+ }
+ fprintf(fileOut," { ");
+ for(j = 0; j < table_columns; ++j ) {
+ fprintf(fileOut,"0x%08x,",tag_attr_combination_table[i][j]);
+ }
+ fprintf(fileOut,"},\n");
+ }
+ fprintf(fileOut,"};\n");
+ fprintf(fileOut,"\n/* END FILE */\n");
+ fclose(fileInp);
+ fclose(fileOut);
+ return (0);
+}
+/* A fake so we can use dwarf_names.c */
+void print_error (Dwarf_Debug dbg, string msg,int res, Dwarf_Error err)
+{
+}
+
diff --git a/dwarfdump/tag_attr.list b/dwarfdump/tag_attr.list
new file mode 100644
index 0000000..813ae18
--- /dev/null
+++ b/dwarfdump/tag_attr.list
@@ -0,0 +1,880 @@
+/*
+ Copyright (C) 2000-2010 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+ $Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/tag_attr.list,v 1.7 2005/12/01 17:34:59 davea Exp $
+*/
+#include <dwarf.h>
+
+/*
+ list for semantic check of tag-attr relation.
+
+ 0xffffffff is a "punctuation." The final line of this file
+ must be 0xffffffff. The next line after each 0xffffffff
+ (except the final line) is a tag. The lines after this line
+ before the next 0xffffffff are the attributes that can be given
+ to the tag."
+
+ For example,
+
+ 0xffffffff
+ DW_TAG_access_declaration
+ DW_AT_decl_column
+ DW_AT_decl_file
+ DW_AT_decl_line
+ DW_AT_accessibility
+ DW_AT_name
+ DW_AT_sibling
+ 0xffffffff
+
+ means "only DW_AT_decl_column, DW_AT_decl_file, DW_AT_decl_line,
+ DW_AT_accessibility, DW_AT_name and DW_AT_sibling can be given to
+ DW_TAG_access_declaration."
+
+ This file is applied to the preprocessor, thus any C comment and
+ preprocessor control line is available.
+*/
+
+0xffffffff
+DW_TAG_access_declaration
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_accessibility
+DW_AT_name
+DW_AT_sibling
+0xffffffff
+DW_TAG_array_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_accessibility
+DW_AT_allocated
+DW_AT_associated
+DW_AT_bit_stride
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 */
+DW_AT_data_location
+DW_AT_declaration
+DW_AT_description
+DW_AT_name
+DW_AT_ordering
+DW_AT_sibling
+DW_AT_specification
+DW_AT_start_scope
+DW_AT_type
+DW_AT_visibility
+0xffffffff
+DW_TAG_base_type
+DW_AT_allocated
+DW_AT_associated
+DW_AT_binary_scale
+DW_AT_bit_offset
+DW_AT_bit_size
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 */
+DW_AT_data_bit_offset
+DW_AT_data_location
+DW_AT_decimal_scale
+DW_AT_decimal_sign
+DW_AT_description
+DW_AT_digit_count
+DW_AT_encoding
+DW_AT_endianity
+DW_AT_name
+DW_AT_name
+DW_AT_picture_string
+DW_AT_sibling
+DW_AT_small
+0xffffffff
+DW_TAG_catch_block
+DW_AT_abstract_origin
+DW_AT_high_pc
+DW_AT_low_pc
+DW_AT_ranges
+DW_AT_segment
+DW_AT_sibling
+0xffffffff
+DW_TAG_class_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_accessibility
+DW_AT_allocated
+DW_AT_associated
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 */
+DW_AT_data_location
+DW_AT_declaration
+DW_AT_description
+DW_AT_name
+DW_AT_sibling
+DW_AT_signature
+DW_AT_specification
+DW_AT_start_scope
+DW_AT_visibility
+0xffffffff
+DW_TAG_common_block
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_declaration
+DW_AT_location
+DW_AT_name
+DW_AT_segment
+DW_AT_sibling
+DW_AT_visibility
+0xffffffff
+DW_TAG_common_inclusion
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_common_reference
+DW_AT_declaration
+DW_AT_sibling
+DW_AT_visibility
+0xffffffff
+DW_TAG_compile_unit
+DW_AT_base_types
+DW_AT_comp_dir
+DW_AT_identifier_case
+DW_AT_high_pc
+DW_AT_language
+DW_AT_low_pc
+DW_AT_macro_info
+DW_AT_main_subprogram
+DW_AT_name
+DW_AT_producer
+DW_AT_ranges
+DW_AT_segment
+DW_AT_sibling
+DW_AT_stmt_list
+DW_AT_use_UTF8
+DW_AT_entry_pc
+0xffffffff
+DW_TAG_condition
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_name
+DW_AT_sibling
+0xffffffff
+DW_TAG_const_type
+DW_AT_allocated
+DW_AT_associated
+DW_AT_data_location
+DW_AT_name
+DW_AT_sibling
+DW_AT_type
+0xffffffff
+DW_TAG_constant
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_accessibility
+DW_AT_const_value
+DW_AT_declaration
+DW_AT_description
+DW_AT_endianity
+DW_AT_external
+DW_AT_linkage_name
+DW_AT_name
+DW_AT_sibling
+DW_AT_start_scope
+DW_AT_type
+DW_AT_visibility
+0xffffffff
+DW_TAG_dwarf_procedure
+DW_AT_location
+0xffffffff
+DW_TAG_entry_point
+DW_AT_address_class
+DW_AT_description
+DW_AT_linkage_name
+DW_AT_low_pc
+DW_AT_name
+DW_AT_return_addr
+DW_AT_segment
+DW_AT_sibling
+DW_AT_static_link
+DW_AT_type
+0xffffffff
+DW_TAG_enumeration_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_accessibility
+DW_AT_allocated
+DW_AT_associated
+DW_AT_bit_stride
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 */
+DW_AT_byte_stride
+DW_AT_data_location
+DW_AT_declaration
+DW_AT_description
+DW_AT_enum_class
+DW_AT_name
+DW_AT_sibling
+DW_AT_signature
+DW_AT_specification
+DW_AT_start_scope
+DW_AT_type
+DW_AT_visibility
+0xffffffff
+DW_TAG_enumerator
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_const_value
+DW_AT_description
+DW_AT_name
+DW_AT_sibling
+0xffffffff
+DW_TAG_file_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_allocated
+DW_AT_associated
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 */
+DW_AT_data_location
+DW_AT_description
+DW_AT_name
+DW_AT_sibling
+DW_AT_start_scope
+DW_AT_type
+DW_AT_visibility
+0xffffffff
+DW_TAG_formal_parameter
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_artificial
+DW_AT_const_value
+DW_AT_default_value
+DW_AT_description
+DW_AT_endianity
+DW_AT_is_optional
+DW_AT_location
+DW_AT_name
+DW_AT_segment
+DW_AT_sibling
+DW_AT_type
+DW_AT_variable_parameter
+0xffffffff
+DW_TAG_friend
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_friend
+DW_AT_sibling
+0xffffffff
+DW_TAG_imported_declaration
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_accessibility
+DW_AT_description
+DW_AT_import
+DW_AT_name
+DW_AT_sibling
+DW_AT_start_scope
+0xffffffff
+DW_TAG_imported_module
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_import
+DW_AT_sibling
+DW_AT_start_scope
+0xffffffff
+DW_TAG_imported_unit
+DW_AT_import
+0xffffffff
+DW_TAG_inheritance
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_accessibility
+DW_AT_data_member_location
+DW_AT_sibling
+DW_AT_type
+DW_AT_virtuality
+0xffffffff
+DW_TAG_inlined_subroutine
+DW_AT_abstract_origin
+DW_AT_call_column
+DW_AT_call_file
+DW_AT_call_line
+DW_AT_const_expr
+DW_AT_entry_pc
+DW_AT_high_pc
+DW_AT_low_pc
+DW_AT_ranges
+DW_AT_return_addr
+DW_AT_segment
+DW_AT_sibling
+DW_AT_start_scope
+DW_AT_trampoline
+0xffffffff
+DW_TAG_interface_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_accessibility
+DW_AT_description
+DW_AT_name
+DW_AT_sibling
+DW_AT_start_scope
+0xffffffff
+DW_TAG_label
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_description
+DW_AT_low_pc
+DW_AT_name
+DW_AT_segment
+DW_AT_start_scope
+DW_AT_sibling
+0xffffffff
+DW_TAG_lexical_block
+DW_AT_abstract_origin
+DW_AT_description
+DW_AT_high_pc
+DW_AT_low_pc
+DW_AT_name
+DW_AT_ranges
+DW_AT_segment
+DW_AT_sibling
+0xffffffff
+DW_TAG_member
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_accessibility
+DW_AT_bit_offset
+DW_AT_bit_size
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 */
+DW_AT_data_bit_offset
+DW_AT_data_member_location
+DW_AT_declaration
+DW_AT_description
+DW_AT_mutable
+DW_AT_name
+DW_AT_sibling
+DW_AT_type
+DW_AT_visibility
+DW_AT_artificial
+0xffffffff
+DW_TAG_module
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_accessibility
+DW_AT_declaration
+DW_AT_description
+DW_AT_entry_pc
+DW_AT_high_pc
+DW_AT_low_pc
+DW_AT_name
+DW_AT_priority
+DW_AT_segment
+DW_AT_sibling
+DW_AT_specification
+DW_AT_visibility
+0xffffffff
+DW_TAG_namelist
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_accessibility
+DW_AT_abstract_origin
+DW_AT_declaration
+DW_AT_name
+DW_AT_sibling
+DW_AT_visibility
+0xffffffff
+DW_TAG_namelist_item
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_namelist_item
+DW_AT_sibling
+0xffffffff
+DW_TAG_namespace
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_description
+DW_AT_extension
+DW_AT_name
+DW_AT_sibling
+DW_AT_start_scope
+0xffffffff
+DW_TAG_packed_type
+DW_AT_allocated
+DW_AT_associated
+DW_AT_data_location
+DW_AT_name
+DW_AT_sibling
+DW_AT_type
+0xffffffff
+DW_TAG_partial_unit
+DW_AT_base_types
+DW_AT_comp_dir
+DW_AT_description
+DW_AT_identifier_case
+DW_AT_high_pc
+DW_AT_language
+DW_AT_low_pc
+DW_AT_macro_info
+DW_AT_main_subprogram
+DW_AT_name
+DW_AT_producer
+DW_AT_ranges
+DW_AT_segment
+DW_AT_sibling
+DW_AT_stmt_list
+DW_AT_use_UTF8
+0xffffffff
+DW_TAG_pointer_type
+DW_AT_address_class
+DW_AT_allocated
+DW_AT_associated
+DW_AT_data_location
+DW_AT_name
+DW_AT_sibling
+DW_AT_specification
+DW_AT_type
+/* Comment from 1993:
+ "Though DWARF spec doesn't refer to DW_AT_byte_size, it may well be
+ given to DW_TAG_pointer_type."
+ Comment 31 January 2009:
+ Discussed in the dwarf-workgroup mailing list Jan 5 2009, that
+ DW_AT_byte_size is allowed.
+*/
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 (if DW_AT_byte_size allowed) */
+0xffffffff
+DW_TAG_ptr_to_member_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_address_class
+DW_AT_allocated
+DW_AT_associated
+DW_AT_containing_type
+DW_AT_data_location
+DW_AT_declaration
+DW_AT_description
+DW_AT_name
+DW_AT_sibling
+DW_AT_type
+DW_AT_use_location
+DW_AT_visibility
+0xffffffff
+DW_TAG_rvalue_reference_type
+DW_AT_address_class
+DW_AT_allocated
+DW_AT_associated
+DW_AT_data_location
+DW_AT_name
+DW_AT_sibling
+DW_AT_type
+0xffffffff
+DW_TAG_reference_type
+DW_AT_address_class
+DW_AT_allocated
+DW_AT_associated
+DW_AT_data_location
+DW_AT_name
+DW_AT_sibling
+DW_AT_type
+/* Comment from 1993:
+ "Though DWARF spec doesn't refer to DW_AT_byte_size, it may well be
+ given to DW_TAG_pointer_type."
+ Comment 31 January 2009:
+ Discussed in the dwarf-workgroup mailing list Jan 5 2009, that
+ DW_AT_byte_size is allowed.
+*/
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 */
+0xffffffff
+DW_TAG_template_alias
+DW_AT_abstract_origin
+DW_AT_accessibility
+DW_AT_allocated
+DW_AT_associated
+DW_AT_data_location
+DW_AT_declaration
+DW_AT_description
+DW_AT_name
+DW_AT_sibling
+DW_AT_signature
+DW_AT_start_scope
+DW_AT_type
+DW_AT_visibility
+0xffffffff
+DW_TAG_restrict_type
+DW_AT_allocated
+DW_AT_associated
+DW_AT_data_location
+DW_AT_name
+DW_AT_sibling
+DW_AT_type
+0xffffffff
+DW_TAG_set_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_accessibility
+DW_AT_allocated
+DW_AT_associated
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 */
+DW_AT_data_location
+DW_AT_declaration
+DW_AT_description
+DW_AT_name
+DW_AT_start_scope
+DW_AT_sibling
+DW_AT_type
+DW_AT_visibility
+0xffffffff
+DW_TAG_shared_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_count
+DW_AT_name
+DW_AT_sibling
+DW_AT_type
+0xffffffff
+DW_TAG_string_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_accessibility
+DW_AT_allocated
+DW_AT_associated
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 */
+DW_AT_data_location
+DW_AT_declaration
+DW_AT_description
+DW_AT_name
+DW_AT_segment
+DW_AT_sibling
+DW_AT_start_scope
+DW_AT_string_length
+DW_AT_visibility
+0xffffffff
+DW_TAG_structure_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_accessibility
+DW_AT_allocated
+DW_AT_associated
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 */
+DW_AT_containing_type
+DW_AT_data_location
+DW_AT_declaration
+DW_AT_description
+DW_AT_name
+DW_AT_sibling
+DW_AT_signature
+DW_AT_specification
+DW_AT_start_scope
+DW_AT_visibility
+0xffffffff
+DW_TAG_subprogram
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_accessibility
+DW_AT_address_class
+DW_AT_artificial
+DW_AT_calling_convention
+DW_AT_containing_type
+DW_AT_declaration
+DW_AT_description
+DW_AT_elemental
+DW_AT_entry_pc
+DW_AT_explicit
+DW_AT_external
+DW_AT_frame_base
+DW_AT_high_pc
+DW_AT_inline
+DW_AT_linkage_name
+DW_AT_low_pc
+DW_AT_main_subprogram
+DW_AT_name
+DW_AT_object_pointer
+DW_AT_prototyped
+DW_AT_pure
+DW_AT_ranges
+DW_AT_recursive
+DW_AT_return_addr
+DW_AT_segment
+DW_AT_sibling
+DW_AT_specification
+DW_AT_start_scope
+DW_AT_static_link
+DW_AT_trampoline
+DW_AT_type
+DW_AT_visibility
+DW_AT_virtuality
+DW_AT_vtable_elem_location
+0xffffffff
+DW_TAG_subrange_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_accessibility
+DW_AT_allocated
+DW_AT_associated
+DW_AT_bit_stride
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 */
+DW_AT_byte_stride
+DW_AT_count
+DW_AT_data_location
+DW_AT_declaration
+DW_AT_description
+DW_AT_lower_bound
+DW_AT_name
+DW_AT_sibling
+DW_AT_threads_scaled
+DW_AT_type
+DW_AT_upper_bound
+DW_AT_visibility
+0xffffffff
+DW_TAG_subroutine_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_accessibility
+DW_AT_address_class
+DW_AT_allocated
+DW_AT_associated
+DW_AT_data_location
+DW_AT_declaration
+DW_AT_description
+DW_AT_name
+DW_AT_prototyped
+DW_AT_sibling
+DW_AT_start_scope
+DW_AT_type
+DW_AT_visibility
+0xffffffff
+DW_TAG_template_type_parameter
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_description
+DW_AT_name
+DW_AT_sibling
+DW_AT_type
+0xffffffff
+DW_TAG_template_value_parameter
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_const_value
+DW_AT_description
+DW_AT_name
+DW_AT_sibling
+DW_AT_type
+0xffffffff
+DW_TAG_thrown_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_allocated
+DW_AT_associated
+DW_AT_data_location
+DW_AT_sibling
+DW_AT_type
+0xffffffff
+DW_TAG_try_block
+DW_AT_abstract_origin
+DW_AT_high_pc
+DW_AT_low_pc
+DW_AT_ranges
+DW_AT_segment
+DW_AT_sibling
+0xffffffff
+DW_TAG_typedef
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_accessibility
+DW_AT_allocated
+DW_AT_associated
+DW_AT_data_location
+DW_AT_declaration
+DW_AT_description
+DW_AT_name
+DW_AT_sibling
+DW_AT_start_scope
+DW_AT_type
+DW_AT_visibility
+0xffffffff
+DW_TAG_union_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_accessibility
+DW_AT_allocated
+DW_AT_associated
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 */
+DW_AT_data_location
+DW_AT_declaration
+DW_AT_description
+DW_AT_name
+DW_AT_sibling
+DW_AT_signature
+DW_AT_specification
+DW_AT_start_scope
+DW_AT_visibility
+0xffffffff
+DW_TAG_unspecified_parameters
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_artificial
+DW_AT_sibling
+0xffffffff
+DW_TAG_unspecified_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_description
+DW_AT_sibling
+0xffffffff
+DW_TAG_variable
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_accessibility
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 */
+DW_AT_const_expr
+DW_AT_const_value
+DW_AT_declaration
+DW_AT_description
+DW_AT_endianity
+DW_AT_external
+DW_AT_linkage_name
+DW_AT_location
+DW_AT_name
+DW_AT_segment
+DW_AT_sibling
+DW_AT_specification
+DW_AT_start_scope
+DW_AT_type
+DW_AT_visibility
+DW_AT_artificial
+0xffffffff
+DW_TAG_variant
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_accessibility
+DW_AT_abstract_origin
+DW_AT_declaration
+DW_AT_discr_list
+DW_AT_discr_value
+DW_AT_sibling
+0xffffffff
+DW_TAG_variant_part
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_accessibility
+DW_AT_abstract_origin
+DW_AT_declaration
+DW_AT_discr
+DW_AT_sibling
+DW_AT_type
+0xffffffff
+DW_TAG_volatile_type
+DW_AT_allocated
+DW_AT_associated
+DW_AT_data_location
+DW_AT_name
+DW_AT_sibling
+DW_AT_type
+0xffffffff
+DW_TAG_with_stmt
+DW_AT_accessibility
+DW_AT_address_class
+DW_AT_declaration
+DW_AT_high_pc
+DW_AT_location
+DW_AT_low_pc
+DW_AT_ranges
+DW_AT_segment
+DW_AT_sibling
+DW_AT_type
+DW_AT_visibility
+0xffffffff
+DW_TAG_type_unit
+DW_AT_language
+0xffffffff
+
diff --git a/dwarfdump/tag_attr_ext.list b/dwarfdump/tag_attr_ext.list
new file mode 100644
index 0000000..ce6d8b0
--- /dev/null
+++ b/dwarfdump/tag_attr_ext.list
@@ -0,0 +1,78 @@
+/*
+ Copyright (C) 2000-2010 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2008-2010 SN Systems Ltd. All Rights Reserved.
+ Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+ $Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/tag_attr.list,v 1.7 2005/12/01 17:34:59 davea Exp $
+*/
+#include <dwarf.h>
+
+/* list for semantic check of tag-attr relation.
+ See tag_attr.list for details.
+*/
+
+/* Common DWARF extensions */
+
+0xffffffff
+DW_TAG_member
+DW_AT_GNU_guarded_by /* gcc.gnu.org/wiki/ThreadSafetyAnnotationsInDWARF */
+DW_AT_GNU_pt_guarded_by /* gcc.gnu.org/wiki/ThreadSafetyAnnotationsInDWARF */
+DW_AT_GNU_guarded /* gcc.gnu.org/wiki/ThreadSafetyAnnotationsInDWARF */
+DW_AT_GNU_pt_guarded /* gcc.gnu.org/wiki/ThreadSafetyAnnotationsInDWARF */
+0xffffffff
+DW_TAG_array_type
+DW_AT_GNU_vector
+0xffffffff
+DW_TAG_subprogram
+DW_AT_MIPS_linkage_name /* Used by GNU, SGI-IRIX, and others. */
+DW_AT_MIPS_fde /* SGI-IRIX uses this */
+DW_AT_GNU_locks_excluded /* gcc.gnu.org/wiki/ThreadSafetyAnnotationsInDWARF */
+DW_AT_GNU_exclusive_locks_required
+DW_AT_GNU_shared_locks_required
+0xffffffff
+DW_TAG_variable
+DW_AT_MIPS_linkage_name /* Used by GNU, SGI-IRIX, and others. */
+DW_AT_GNU_guarded_by
+DW_AT_GNU_pt_guarded_by
+DW_AT_GNU_guarded
+DW_AT_GNU_pt_guarded
+0xffffffff
+DW_TAG_GNU_template_template_parameter
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_name
+DW_AT_GNU_template_name
+DW_AT_GNU_guarded_by /* GNU changed the name of 0x2108! */
+0xffffffff
+
diff --git a/dwarfdump/tag_common.c b/dwarfdump/tag_common.c
new file mode 100644
index 0000000..28b2d2c
--- /dev/null
+++ b/dwarfdump/tag_common.c
@@ -0,0 +1,145 @@
+/*
+ Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2009-2010 SN Systems Ltd. All Rights Reserved.
+ Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/tag_common.c,v 1.8 2008/01/23 09:47:59 davea Exp $ */
+
+#include <dwarf.h>
+#include <stdio.h>
+#include <stdlib.h>/* For exit() declaration etc. */
+#include <errno.h>/* For errno declaration. */
+#include <ctype.h> /* For isspace() declaration */
+
+#include "globals.h"
+#include "naming.h"
+#include "tag_common.h"
+
+static int linecount = 0;
+static char line_in[MAX_LINE_SIZE];
+
+void
+bad_line_input(char *msg)
+{
+ fprintf(stderr,
+ "tag_(tree,attr) table build failed %s, line %d: \"%s\" \n",
+ msg, linecount, line_in);
+ exit(FAILED);
+}
+
+void
+trim_newline(char *line, int max)
+{
+ char *end = line + max - 1;
+
+ for (; *line && (line < end); ++line) {
+ if (*line == '\n') {
+ /* Found newline, drop it */
+ *line = 0;
+ return;
+ }
+ }
+ return;
+}
+
+/* Detect empty lines (and other lines we do not want to read) */
+boolean
+is_skippable_line(char *pLine)
+{
+ boolean empty = TRUE;
+
+ if(pLine[0] == '#') {
+ /* Preprocessor lines are of no interest. */
+ return TRUE;
+ }
+ for (; *pLine && empty; ++pLine) {
+ empty = isspace(*pLine);
+ }
+ return empty;
+}
+
+/* Reads a value from the text table.
+ Exits with non-zero status
+ if the table is erroneous in some way.
+*/
+int
+read_value(unsigned int *outval, FILE*file)
+{
+ char *res = 0;
+ unsigned long lval;
+ char *strout = 0;
+ boolean bBlankLine = TRUE;
+
+ ++linecount;
+ *outval = 0;
+
+ while (bBlankLine) {
+ res = fgets(line_in, sizeof(line_in), file);
+ if (res == 0) {
+ if (ferror(file)) {
+ fprintf(stderr,
+ "tag_attr: Error reading table, %d lines read\n",
+ linecount);
+ exit(FAILED);
+ }
+
+ if (feof(file)) {
+ return IS_EOF;
+ }
+
+ /* Impossible */
+ fprintf(stderr, "tag_attr: Impossible error reading table, "
+ "%d lines read\n", linecount);
+ exit(FAILED);
+ }
+
+ bBlankLine = is_skippable_line(line_in);
+ }
+
+ trim_newline(line_in, sizeof(line_in));
+ errno = 0;
+ lval = strtoul(line_in, &strout, 0);
+
+ if (strout == line_in) {
+ bad_line_input("bad number input!");
+ }
+
+ if (errno != 0) {
+ int myerr = errno;
+
+ fprintf(stderr, "tag_attr errno %d\n", myerr);
+ bad_line_input("invalid number on line");
+ }
+
+ *outval = (int) lval;
+
+ return NOT_EOF;
+}
diff --git a/dwarfdump/tag_common.h b/dwarfdump/tag_common.h
new file mode 100644
index 0000000..f06d9bd
--- /dev/null
+++ b/dwarfdump/tag_common.h
@@ -0,0 +1,123 @@
+/*
+ Copyright (C) 2000-2010 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2009-2010 SN Systems Ltd. All Rights Reserved.
+ Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/tag_common.h,v 1.8 2008/01/23 09:47:59 davea Exp $ */
+
+#ifndef tag_common_INCLUDED
+#define tag_common_INCLUDED
+
+
+
+/* The following is the magic token used to
+ distinguish real tags/attrs from group-delimiters.
+ Blank lines have been eliminated by an awk script.
+*/
+#define MAGIC_TOKEN_VALUE 0xffffffff
+
+/* TAG_TREE.LIST Expected input format
+
+0xffffffff
+value of a tag
+value of a standard tag that may be a child of that tag
+...
+0xffffffff
+value of a tag
+value of a standard tag that may be a child of that tag
+...
+0xffffffff
+...
+
+No blank lines or commentary allowed, no symbols, just numbers.
+
+*/
+
+/* TAG_ATTR.LIST Expected input format
+
+0xffffffff
+value of a tag
+value of a standard attribute that follows that tag
+...
+0xffffffff
+value of a tag
+value of a standard attribute that follows that tag
+...
+0xffffffff
+...
+
+No blank lines or commentary allowed, no symbols, just numbers.
+
+*/
+
+/* We don't need really long lines: the input file is simple. */
+#define MAX_LINE_SIZE 1000
+
+/* 1 more than the highest number in the DW_TAG defines,
+ this is for standard TAGs. Number of rows. */
+#define STD_TAG_TABLE_ROWS 0x44
+/* Enough entries to have a bit for each standard legal tag. */
+#define STD_TAG_TABLE_COLUMNS 7
+
+/* TAG tree common extension maximums. */
+#define EXT_TAG_TABLE_ROWS 7
+#define EXT_TAG_TABLE_COLS 7
+
+/* The following 2 used in tag_tree.c only. */
+#define TAG_TABLE_ROW_MAXIMUM STD_TAG_TABLE_ROWS
+#define TAG_TABLE_COLUMN_MAXIMUM EXT_TAG_TABLE_COLS
+
+/* Number of attributes columns per tag. The array is bit fields,
+ BITS_PER_WORD fields per word. Dense and quick to inspect */
+#define COUNT_ATTRIBUTE_STD 7
+
+#define STD_ATTR_TABLE_ROWS STD_TAG_TABLE_ROWS
+#define STD_ATTR_TABLE_COLUMNS 7
+/* tag/attr tree common extension maximums. */
+#define EXT_ATTR_TABLE_ROWS 7
+#define EXT_ATTR_TABLE_COLS 7
+
+/* The following 2 used in tag_attr.c only. */
+#define ATTR_TABLE_ROW_MAXIMUM STD_ATTR_TABLE_ROWS
+#define ATTR_TABLE_COLUMN_MAXIMUM EXT_ATTR_TABLE_COLS
+
+/* Bits per 'int' to mark legal attrs. */
+#define BITS_PER_WORD 32
+
+#define IS_EOF 1
+#define NOT_EOF 0
+
+extern void bad_line_input(char *msg);
+extern void trim_newline(char *line, int max);
+extern boolean is_blank_line(char *pLine);
+extern int read_value(unsigned int *outval,FILE *f);
+
+#endif /* tag_common_INCLUDED */
diff --git a/dwarfdump/tag_tree.c b/dwarfdump/tag_tree.c
new file mode 100644
index 0000000..b508d06
--- /dev/null
+++ b/dwarfdump/tag_tree.c
@@ -0,0 +1,290 @@
+/*
+ Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2009-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/tag_tree.c,v 1.8 2005/12/01 17:34:59 davea Exp $ */
+#include <dwarf.h>
+#include <stdio.h>
+#include <stdlib.h> /* For exit() declaration etc. */
+#include <errno.h> /* For errno declaration. */
+#include <unistd.h> /* For getopt. */
+
+#include "globals.h"
+#include "libdwarf.h"
+#include "common.h"
+#include "tag_common.h"
+
+unsigned int tag_tree_combination_table[TAG_TABLE_ROW_MAXIMUM][TAG_TABLE_COLUMN_MAXIMUM];
+
+string program_name;
+
+boolean ellipsis = FALSE; /* So we can use dwarf_names.c */
+
+/* Expected input format
+
+0xffffffff
+value of a tag
+value of a standard tag that may be a child ofthat tag
+...
+0xffffffff
+value of a tag
+value of a standard tag that may be a child ofthat tag
+...
+0xffffffff
+...
+
+No commentary allowed, no symbols, just numbers.
+Blank lines are allowed and are dropped.
+
+*/
+
+static const char *usage[] = {
+ "Usage: tag_tree_build <options>",
+ "options:\t-t\tGenerate Tags table",
+ " -i Input-file-path",
+ " -o Output-table-path",
+ " -e (Want Extended table (common extensions))",
+ " -s (Want Standard table)",
+ ""
+};
+
+static char *input_name = 0;
+static char *output_name = 0;
+int extended_flag = FALSE;
+int standard_flag = FALSE;
+
+static void
+process_args(int argc, char *argv[])
+{
+ int c = 0;
+ boolean usage_error = FALSE;
+
+ program_name = argv[0];
+
+ while ((c = getopt(argc, argv, "i:o:es")) != EOF) {
+ switch (c) {
+ case 'i':
+ input_name = strdup(optarg);
+ break;
+ case 'o':
+ output_name = strdup(optarg);
+ break;
+ case 'e':
+ extended_flag = TRUE;
+ break;
+ case 's':
+ standard_flag = TRUE;
+ break;
+
+ default:
+ usage_error = TRUE;
+ break;
+ }
+ }
+
+ if (usage_error || 1 == optind || optind != argc) {
+ print_usage_message(argv[0],usage);
+ exit(FAILED);
+ }
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+ int i = 0;
+ unsigned int num = 0;
+ int input_eof = 0;
+ int table_rows = 0;
+ int table_columns = 0;
+ int current_row = 0;
+ FILE *fileInp = 0;
+ FILE *fileOut = 0;
+
+
+ print_version_details(argv[0],FALSE);
+ process_args(argc,argv);
+ print_args(argc,argv);
+
+ if (!input_name ) {
+ fprintf(stderr,"Input name required, not supplied.\n");
+ print_usage_message(argv[0],usage);
+ exit(FAILED);
+ }
+ fileInp = fopen(input_name,"r");
+ if (!fileInp) {
+ fprintf(stderr,"Invalid input filename, could not open '%s'\n",
+ input_name);
+ print_usage_message(argv[0],usage);
+ exit(FAILED);
+ }
+
+
+ if (!output_name ) {
+ fprintf(stderr,"Output name required, not supplied.\n");
+ print_usage_message(argv[0],usage);
+ exit(FAILED);
+ }
+ fileOut = fopen(output_name,"w");
+ if (!fileOut) {
+ fprintf(stderr,"Invalid output filename, could not open: '%s'\n",
+ output_name);
+ print_usage_message(argv[0],usage);
+ exit(FAILED);
+ }
+ if ((standard_flag && extended_flag) || (!standard_flag && !extended_flag)) {
+ fprintf(stderr,"Invalid table type\n");
+ fprintf(stderr,"Choose -e or -s .\n");
+ print_usage_message(argv[0],usage);
+ exit(FAILED);
+ }
+ if(standard_flag) {
+ table_rows = STD_TAG_TABLE_ROWS;
+ table_columns = STD_TAG_TABLE_COLUMNS;
+ } else {
+ table_rows = EXT_TAG_TABLE_ROWS;
+ table_columns = EXT_TAG_TABLE_COLS;
+ }
+
+
+
+ input_eof = read_value(&num,fileInp); /* 0xffffffff */
+ if (IS_EOF == input_eof) {
+ bad_line_input("Empty input file");
+ }
+ if (num != MAGIC_TOKEN_VALUE) {
+ bad_line_input("Expected 0xffffffff");
+ }
+
+ while (!feof(stdin)) {
+ unsigned int tag = 0;
+ int nTagLoc = 0;
+
+ input_eof = read_value(&tag,fileInp);
+ if (IS_EOF == input_eof) {
+ /* Reached normal eof */
+ break;
+ }
+ if(standard_flag) {
+ if (tag >= table_rows ) {
+ bad_line_input("tag value exceeds standard table size");
+ }
+ } else {
+ if(current_row >= table_rows) {
+ bad_line_input("too many extended table rows.");
+ }
+ tag_tree_combination_table[current_row][0] = tag;
+ }
+ input_eof = read_value(&num,fileInp);
+ if (IS_EOF == input_eof) {
+ bad_line_input("Not terminated correctly..");
+ }
+ nTagLoc = 1;
+ while (num != 0xffffffff) {
+ if(standard_flag) {
+ int idx = num / BITS_PER_WORD;
+ int bit = num % BITS_PER_WORD;
+
+ if (idx >= table_columns) {
+ fprintf(stderr,"Want column %d, have only %d\n",
+ idx,table_columns);
+ bad_line_input("too many TAGs: table incomplete.");
+ }
+ tag_tree_combination_table[tag][idx] |= (1 << bit);
+ } else {
+ if(nTagLoc >= table_columns) {
+ printf("Attempting to use colum %d, max is %d\n",
+ nTagLoc,table_columns);
+ bad_line_input("too many subTAGs, table incomplete.");
+ }
+ tag_tree_combination_table[current_row][nTagLoc] = num;
+ nTagLoc++;
+ }
+ input_eof = read_value(&num,fileInp);
+ if (IS_EOF == input_eof) {
+ bad_line_input("Not terminated correctly.");
+ }
+ }
+ ++current_row; /* for extended table */
+ }
+ fprintf(fileOut,"/* Generated code, do not edit. */\n");
+ fprintf(fileOut,"/* Generated on %s %s */\n",__DATE__,__TIME__);
+ fprintf(fileOut,"\n/* BEGIN FILE */\n\n");
+ if (standard_flag) {
+ fprintf(fileOut,"#define TAG_TREE_COLUMN_COUNT %d\n\n",table_columns);
+ fprintf(fileOut,"#define TAG_TREE_ROW_COUNT %d\n\n",table_rows);
+ fprintf(fileOut,
+ "static unsigned int tag_tree_combination_table"
+ "[TAG_TREE_ROW_COUNT][TAG_TREE_COLUMN_COUNT] = {\n");
+ } else {
+ fprintf(fileOut,"#define TAG_TREE_EXT_COLUMN_COUNT %d\n\n",
+ table_columns);
+ fprintf(fileOut,"#define TAG_TREE_EXT_ROW_COUNT %d\n\n",table_rows);
+ fprintf(fileOut,"/* Common extensions */\n");
+ fprintf(fileOut,
+ "static unsigned int tag_tree_combination_ext_table"
+ "[TAG_TREE_EXT_ROW_COUNT][TAG_TREE_EXT_COLUMN_COUNT] = {\n");
+ }
+
+ for (i = 0; i < table_rows; i++) {
+ int j = 0;
+ const char *name = 0;
+ if (standard_flag) {
+ dwarf_get_TAG_name(i,&name);;
+ fprintf(fileOut,"/* %d %-37s*/\n",i, name);
+ } else {
+ int k = tag_tree_combination_table[i][0];
+ dwarf_get_TAG_name(i,&name);;
+ fprintf(fileOut,"/* %u %-37s*/\n", k, name);
+ }
+ fprintf(fileOut," { ");
+ for(j = 0; j < table_columns; ++j ) {
+ fprintf(fileOut,"0x%08x,",tag_tree_combination_table[i][j]);
+ }
+ fprintf(fileOut,"},\n");
+
+ }
+ fprintf(fileOut,"};\n");
+ fprintf(fileOut,"\n/* END FILE */\n");
+ fclose(fileInp);
+ fclose(fileOut);
+ return (0);
+}
+
+/* A fake so we can use dwarf_names.c */
+void print_error (Dwarf_Debug dbg, string msg,int res, Dwarf_Error err)
+{
+}
+
diff --git a/dwarfdump/tag_tree.list b/dwarfdump/tag_tree.list
new file mode 100644
index 0000000..ebad794
--- /dev/null
+++ b/dwarfdump/tag_tree.list
@@ -0,0 +1,486 @@
+/*
+ Copyright (C) 2000-2010 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+ $Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/tag_tree.list,v 1.6 2005/12/01 17:34:59 davea Exp $
+*/
+#include <dwarf.h>
+
+/*
+ list for semantic check of tag-tree.
+
+ 0xffffffff is a "punctuation." The final line of this file
+ must be 0xffffffff. The next line after each 0xffffffff
+ (except the final line) stands for "parent-tag." The lines
+ after this line before the next 0xffffffff are the tags that
+ can be children of the "parent-tag."
+
+ For example,
+
+ 0xffffffff
+ DW_TAG_array_type
+ DW_TAG_subrange_type
+ DW_TAG_enumeration_type
+ 0xffffffff
+
+ means "only DW_TAG_subrange_type and DW_TAG_enumeration_type can
+ be children of DW_TAG_array_type.
+
+ This file is applied to the preprocessor, thus any C comment and
+ preprocessor control line is available.
+*/
+
+0xffffffff
+DW_TAG_access_declaration
+0xffffffff
+DW_TAG_array_type
+DW_TAG_subrange_type
+DW_TAG_enumeration_type
+0xffffffff
+DW_TAG_base_type
+0xffffffff
+DW_TAG_catch_block
+DW_TAG_formal_parameter
+DW_TAG_unspecified_parameters
+DW_TAG_array_type
+DW_TAG_class_type
+DW_TAG_enumeration_type
+DW_TAG_pointer_type
+DW_TAG_reference_type
+DW_TAG_string_type
+DW_TAG_structure_type
+DW_TAG_subroutine_type
+DW_TAG_typedef
+DW_TAG_union_type
+DW_TAG_ptr_to_member_type
+DW_TAG_set_type
+DW_TAG_subrange_type
+DW_TAG_base_type
+DW_TAG_const_type
+DW_TAG_constant
+DW_TAG_file_type
+DW_TAG_packed_type
+DW_TAG_subprogram
+DW_TAG_variable
+DW_TAG_volatile_type
+0xffffffff
+DW_TAG_class_type
+DW_TAG_member
+DW_TAG_inheritance
+DW_TAG_access_declaration
+DW_TAG_friend
+DW_TAG_ptr_to_member_type
+DW_TAG_subprogram
+DW_TAG_template_type_parameter /* template instantiations */
+DW_TAG_template_value_parameter /* template instantiations */
+DW_TAG_typedef
+DW_TAG_base_type
+DW_TAG_pointer_type
+DW_TAG_union_type
+DW_TAG_const_type
+DW_TAG_class_type /* Nested classes */
+DW_TAG_structure_type /* Nested structures */
+DW_TAG_enumeration_type /* Nested enums */
+DW_TAG_imported_declaration
+DW_TAG_template_alias /* C++ 2010 template alias */
+0xffffffff
+DW_TAG_common_block
+DW_TAG_variable
+0xffffffff
+DW_TAG_common_inclusion
+0xffffffff
+DW_TAG_compile_unit
+DW_TAG_array_type
+DW_TAG_class_type
+DW_TAG_enumeration_type
+DW_TAG_imported_declaration
+DW_TAG_pointer_type
+DW_TAG_reference_type
+DW_TAG_string_type
+DW_TAG_structure_type
+DW_TAG_subroutine_type
+DW_TAG_typedef
+DW_TAG_union_type
+DW_TAG_common_block
+DW_TAG_inlined_subroutine
+DW_TAG_module
+DW_TAG_ptr_to_member_type
+DW_TAG_set_type
+DW_TAG_subrange_type
+DW_TAG_base_type
+DW_TAG_const_type
+DW_TAG_constant
+DW_TAG_file_type
+DW_TAG_namelist
+DW_TAG_namespace
+DW_TAG_packed_type
+DW_TAG_subprogram
+DW_TAG_variable
+DW_TAG_volatile_type
+DW_TAG_imported_module
+DW_TAG_template_alias /* C++ 2010 template alias */
+0xffffffff
+DW_TAG_type_unit
+DW_TAG_array_type
+DW_TAG_class_type
+DW_TAG_enumeration_type
+DW_TAG_imported_declaration
+DW_TAG_pointer_type
+DW_TAG_reference_type
+DW_TAG_string_type
+DW_TAG_structure_type
+DW_TAG_subroutine_type
+DW_TAG_typedef
+DW_TAG_union_type
+DW_TAG_common_block
+DW_TAG_inlined_subroutine
+DW_TAG_module
+DW_TAG_ptr_to_member_type
+DW_TAG_set_type
+DW_TAG_subrange_type
+DW_TAG_base_type
+DW_TAG_const_type
+DW_TAG_constant
+DW_TAG_file_type
+DW_TAG_namelist
+DW_TAG_namespace
+DW_TAG_packed_type
+DW_TAG_subprogram
+DW_TAG_variable
+DW_TAG_volatile_type
+DW_TAG_imported_module
+DW_TAG_template_alias /* C++ 2010 template alias */
+0xffffffff
+DW_TAG_condition /* COBOL */
+DW_TAG_constant
+DW_TAG_subrange_type
+0xffffffff
+DW_TAG_const_type
+0xffffffff
+DW_TAG_constant
+0xffffffff
+DW_TAG_dwarf_procedure
+0xffffffff
+DW_TAG_entry_point
+DW_TAG_formal_parameter
+DW_TAG_unspecified_parameters
+DW_TAG_common_inclusion
+0xffffffff
+DW_TAG_enumeration_type
+DW_TAG_enumerator
+0xffffffff
+DW_TAG_enumerator
+0xffffffff
+DW_TAG_file_type
+0xffffffff
+DW_TAG_formal_parameter
+0xffffffff
+DW_TAG_friend
+0xffffffff
+DW_TAG_imported_declaration
+0xffffffff
+DW_TAG_imported_module
+0xffffffff
+DW_TAG_imported_unit
+0xffffffff
+DW_TAG_inheritance
+0xffffffff
+DW_TAG_inlined_subroutine
+DW_TAG_formal_parameter
+DW_TAG_unspecified_parameters
+DW_TAG_array_type
+DW_TAG_class_type
+DW_TAG_enumeration_type
+DW_TAG_pointer_type
+DW_TAG_reference_type
+DW_TAG_string_type
+DW_TAG_structure_type
+DW_TAG_subroutine_type
+DW_TAG_lexical_block
+DW_TAG_typedef
+DW_TAG_union_type
+DW_TAG_inlined_subroutine
+DW_TAG_ptr_to_member_type
+DW_TAG_set_type
+DW_TAG_subrange_type
+DW_TAG_base_type
+DW_TAG_const_type
+DW_TAG_constant
+DW_TAG_file_type
+DW_TAG_namelist
+DW_TAG_packed_type
+DW_TAG_subprogram
+DW_TAG_variable
+DW_TAG_volatile_type
+0xffffffff
+DW_TAG_interface_type
+DW_TAG_member
+DW_TAG_subprogram
+0xffffffff
+DW_TAG_label
+0xffffffff
+DW_TAG_lexical_block
+DW_TAG_array_type
+DW_TAG_class_type
+DW_TAG_enumeration_type
+DW_TAG_imported_declaration
+DW_TAG_pointer_type
+DW_TAG_reference_type
+DW_TAG_string_type
+DW_TAG_structure_type
+DW_TAG_subroutine_type
+DW_TAG_typedef
+DW_TAG_union_type
+DW_TAG_inlined_subroutine
+DW_TAG_lexical_block
+DW_TAG_module
+DW_TAG_ptr_to_member_type
+DW_TAG_set_type
+DW_TAG_subrange_type
+DW_TAG_base_type
+DW_TAG_const_type
+DW_TAG_constant
+DW_TAG_namelist
+DW_TAG_packed_type
+DW_TAG_subprogram
+DW_TAG_variable
+DW_TAG_volatile_type
+DW_TAG_formal_parameter
+0xffffffff
+DW_TAG_member
+0xffffffff
+DW_TAG_module
+0xffffffff
+DW_TAG_namelist
+DW_TAG_namelist_item
+0xffffffff
+DW_TAG_namelist_item
+0xffffffff
+DW_TAG_namespace
+DW_TAG_array_type
+DW_TAG_class_type
+DW_TAG_enumeration_type
+DW_TAG_imported_declaration
+DW_TAG_pointer_type
+DW_TAG_reference_type
+DW_TAG_string_type
+DW_TAG_structure_type
+DW_TAG_subroutine_type
+DW_TAG_typedef
+DW_TAG_union_type
+DW_TAG_common_block
+DW_TAG_inlined_subroutine
+DW_TAG_module
+DW_TAG_ptr_to_member_type
+DW_TAG_set_type
+DW_TAG_subrange_type
+DW_TAG_base_type
+DW_TAG_const_type
+DW_TAG_constant
+DW_TAG_namelist
+DW_TAG_packed_type
+DW_TAG_subprogram
+DW_TAG_variable
+DW_TAG_volatile_type
+DW_TAG_namespace /* Allow a nested namespace */
+DW_TAG_imported_module /* Allow imported module */
+0xffffffff
+DW_TAG_packed_type
+0xffffffff
+DW_TAG_partial_unit
+DW_TAG_array_type
+DW_TAG_class_type
+DW_TAG_enumeration_type
+DW_TAG_imported_declaration
+DW_TAG_pointer_type
+DW_TAG_reference_type
+DW_TAG_string_type
+DW_TAG_structure_type
+DW_TAG_subroutine_type
+DW_TAG_typedef
+DW_TAG_union_type
+DW_TAG_common_block
+DW_TAG_inlined_subroutine
+DW_TAG_module
+DW_TAG_ptr_to_member_type
+DW_TAG_set_type
+DW_TAG_subrange_type
+DW_TAG_base_type
+DW_TAG_const_type
+DW_TAG_constant
+DW_TAG_file_type
+DW_TAG_namelist
+DW_TAG_packed_type
+DW_TAG_subprogram
+DW_TAG_variable
+DW_TAG_volatile_type
+0xffffffff
+DW_TAG_pointer_type
+DW_TAG_rvalue_reference_type
+DW_TAG_reference_type
+DW_TAG_restrict_type
+DW_TAG_ptr_to_member_type
+0xffffffff
+DW_TAG_ptr_to_member_type
+DW_TAG_rvalue_reference_type
+DW_TAG_reference_type
+DW_TAG_pointer_type
+DW_TAG_restrict_type
+0xffffffff
+DW_TAG_reference_type
+DW_TAG_rvalue_reference_type
+DW_TAG_reference_type
+DW_TAG_pointer_type
+DW_TAG_restrict_type
+DW_TAG_ptr_to_member_type
+0xffffffff
+DW_TAG_rvalue_reference_type
+DW_TAG_pointer_type
+DW_TAG_restrict_type
+DW_TAG_ptr_to_member_type
+DW_TAG_reference_type
+0xffffffff
+DW_TAG_restrict_type
+DW_TAG_pointer_type
+DW_TAG_ptr_to_member_type
+DW_TAG_rvalue_reference_type
+0xffffffff
+DW_TAG_set_type
+0xffffffff
+DW_TAG_shared_type
+0xffffffff
+DW_TAG_string_type
+0xffffffff
+DW_TAG_structure_type
+DW_TAG_member
+DW_TAG_inheritance
+DW_TAG_access_declaration
+DW_TAG_friend
+DW_TAG_ptr_to_member_type
+DW_TAG_variant_part
+DW_TAG_subprogram
+DW_TAG_template_type_parameter /* template instantiations */
+DW_TAG_template_value_parameter /* template instantiations */
+DW_TAG_typedef
+DW_TAG_base_type
+DW_TAG_pointer_type
+DW_TAG_union_type
+DW_TAG_const_type
+DW_TAG_structure_type /* nested structures */
+DW_TAG_enumeration_type /* nested enums */
+DW_TAG_class_type /* nested classes */
+DW_TAG_imported_declaration /* References to namespaces */
+DW_TAG_template_alias /* C++ 2010 template alias */
+0xffffffff
+DW_TAG_subprogram
+DW_TAG_formal_parameter
+DW_TAG_unspecified_parameters
+DW_TAG_thrown_type
+DW_TAG_template_type_parameter
+DW_TAG_template_value_parameter
+DW_TAG_common_inclusion
+DW_TAG_common_block
+DW_TAG_array_type
+DW_TAG_class_type
+DW_TAG_enumeration_type
+DW_TAG_pointer_type
+DW_TAG_reference_type
+DW_TAG_string_type
+DW_TAG_lexical_block
+DW_TAG_structure_type
+DW_TAG_subroutine_type
+DW_TAG_typedef
+DW_TAG_union_type
+DW_TAG_inlined_subroutine
+DW_TAG_ptr_to_member_type
+DW_TAG_set_type
+DW_TAG_subrange_type
+DW_TAG_base_type
+DW_TAG_const_type
+DW_TAG_constant
+DW_TAG_file_type
+DW_TAG_namelist
+DW_TAG_packed_type
+DW_TAG_subprogram
+DW_TAG_variable
+DW_TAG_volatile_type
+DW_TAG_label
+DW_TAG_imported_module /* References to namespaces */
+DW_TAG_imported_declaration /* References to namespaces */
+0xffffffff
+DW_TAG_subrange_type
+0xffffffff
+DW_TAG_subroutine_type
+DW_TAG_formal_parameter
+DW_TAG_unspecified_parameters
+0xffffffff
+DW_TAG_template_type_parameter
+0xffffffff
+DW_TAG_template_value_parameter
+0xffffffff
+DW_TAG_thrown_type
+0xffffffff
+DW_TAG_try_block
+0xffffffff
+DW_TAG_typedef
+0xffffffff
+DW_TAG_union_type
+DW_TAG_friend
+DW_TAG_member
+DW_TAG_class_type /* Nested classes */
+DW_TAG_enumeration_type /* Nested enums */
+DW_TAG_structure_type /* Nested structures */
+DW_TAG_typedef /* Nested typedef */
+DW_TAG_subprogram
+DW_TAG_template_type_parameter /* template instantiations */
+DW_TAG_template_value_parameter /* template instantiations */
+0xffffffff
+DW_TAG_template_alias
+DW_TAG_template_type_parameter
+DW_TAG_template_value_parameter
+0xffffffff
+DW_TAG_unspecified_parameters
+0xffffffff
+DW_TAG_unspecified_type
+0xffffffff
+DW_TAG_variable
+0xffffffff
+DW_TAG_variant
+DW_TAG_variant_part
+0xffffffff
+DW_TAG_variant_part
+0xffffffff
+DW_TAG_volatile_type
+0xffffffff
+DW_TAG_with_stmt
+0xffffffff
diff --git a/dwarfdump/tag_tree_ext.list b/dwarfdump/tag_tree_ext.list
new file mode 100644
index 0000000..e671373
--- /dev/null
+++ b/dwarfdump/tag_tree_ext.list
@@ -0,0 +1,63 @@
+/*
+ Copyright (C) 2000-2010 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved.
+ Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/tag_attr.list,v 1.7 2005/12/01 17:34:59 davea Exp $
+*/
+#include <dwarf.h>
+
+/* list for semantic check of tag-tree relation.
+ See tag_tree.list for details.
+
+*/
+
+/* Common DWARF extensions */
+
+0xffffffff
+DW_TAG_structure_type
+DW_TAG_variable /* GNU gcc usage. */
+0xffffffff
+DW_TAG_class_type
+DW_TAG_variable /* GNU gcc usage. */
+DW_TAG_GNU_template_template_parameter /* template instantiations */
+0xffffffff
+DW_TAG_structure_type
+DW_TAG_GNU_template_template_parameter /* template instantiations */
+0xffffffff
+DW_TAG_subprogram
+DW_TAG_GNU_template_template_parameter /* template instantiations */
+0xffffffff
+DW_TAG_union_type
+DW_TAG_GNU_template_template_parameter /* template instantiations */
+0xffffffff
diff --git a/dwarfdump/testesb.c b/dwarfdump/testesb.c
new file mode 100644
index 0000000..c3ea2f0
--- /dev/null
+++ b/dwarfdump/testesb.c
@@ -0,0 +1,78 @@
+/* testesb.c
+ test code for esb.h esb.c
+
+ Not part of a compiled dwarfdump.
+
+*/
+
+#include <stdio.h>
+#include <string.h>
+typedef char *string;
+
+#include "esb.h"
+
+void
+check(string msg, struct esb_s *data, string v)
+{
+ string b = esb_get_string(data);
+ size_t l = 0;
+ size_t alloc = 0;
+
+ if (strcmp(b, v)) {
+ fprintf(stderr, "ERROR: %s content error %s != %s\n", msg, b,
+ v);
+ }
+
+ l = esb_string_len(data);
+
+ if (l != strlen(v)) {
+ fprintf(stderr, "ERROR: %s length error %lu != %lu\n", msg,
+ (unsigned long) l, (unsigned long) strlen(v));
+ }
+ alloc = esb_get_allocated_size(data);
+ if (l > alloc) {
+ fprintf(stderr, "ERROR: %s allocation error %lu > %lu\n", msg,
+ (unsigned long) l, (unsigned long) alloc);
+
+ }
+
+ return;
+}
+
+int
+main(void)
+{
+ struct esb_s data;
+
+
+ esb_alloc_size(2); /* small to get all code paths tested. */
+ esb_constructor(&data);
+
+ esb_append(&data, "a");
+ esb_appendn(&data, "bc", 1);
+ esb_append(&data, "d");
+ esb_append(&data, "e");
+ check("test 1", &data, "abde");
+
+ esb_destructor(&data);
+ esb_constructor(&data);
+
+ esb_append(&data, "abcdefghij" "0123456789");
+ check("test 2", &data, "abcdefghij" "0123456789");
+
+ esb_destructor(&data);
+ esb_constructor(&data);
+ esb_append(&data, "abcdefghij" "0123456789");
+
+ esb_append(&data, "abcdefghij" "0123456789");
+
+ esb_append(&data, "abcdefghij" "0123456789");
+
+ esb_append(&data, "abcdefghij" "0123456789");
+ check("test 3", &data, "abcdefghij"
+ "0123456789"
+ "abcdefghij"
+ "0123456789"
+ "abcdefghij" "0123456789" "abcdefghij" "0123456789");
+ return 0;
+}
diff --git a/dwarfdump/uri.c b/dwarfdump/uri.c
new file mode 100644
index 0000000..1353ab8
--- /dev/null
+++ b/dwarfdump/uri.c
@@ -0,0 +1,493 @@
+/*
+ Copyright 2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include "globals.h"
+#include "esb.h"
+#include "uri.h"
+#include <stdio.h>
+#include <ctype.h>
+
+/* dwarfdump_ctype table. See uritablebuild.c */
+static char dwarfdump_ctype_table[256] = {
+0, /* NUL 0x00 */
+0, /* control 0x01 */
+0, /* control 0x02 */
+0, /* control 0x03 */
+0, /* control 0x04 */
+0, /* control 0x05 */
+0, /* control 0x06 */
+0, /* control 0x07 */
+0, /* control 0x08 */
+0, /* whitespace 0x09 */
+0, /* whitespace 0x0a */
+0, /* whitespace 0x0b */
+0, /* whitespace 0x0c */
+0, /* whitespace 0x0d */
+0, /* control 0x0e */
+0, /* control 0x0f */
+0, /* control 0x10 */
+0, /* control 0x11 */
+0, /* control 0x12 */
+0, /* control 0x13 */
+0, /* control 0x14 */
+0, /* control 0x15 */
+0, /* control 0x16 */
+0, /* control 0x17 */
+0, /* control 0x18 */
+0, /* control 0x19 */
+0, /* control 0x1a */
+0, /* control 0x1b */
+0, /* control 0x1c */
+0, /* control 0x1d */
+0, /* control 0x1e */
+0, /* control 0x1f */
+1, /* ' ' 0x20 */
+1, /* '!' 0x21 */
+0, /* '"' 0x22 */
+1, /* '#' 0x23 */
+1, /* '$' 0x24 */
+0, /* '%' 0x25 */
+1, /* '&' 0x26 */
+0, /* ''' 0x27 */
+1, /* '(' 0x28 */
+1, /* ')' 0x29 */
+1, /* '*' 0x2a */
+1, /* '+' 0x2b */
+1, /* ',' 0x2c */
+1, /* '-' 0x2d */
+1, /* '.' 0x2e */
+1, /* '/' 0x2f */
+1, /* '0' 0x30 */
+1, /* '1' 0x31 */
+1, /* '2' 0x32 */
+1, /* '3' 0x33 */
+1, /* '4' 0x34 */
+1, /* '5' 0x35 */
+1, /* '6' 0x36 */
+1, /* '7' 0x37 */
+1, /* '8' 0x38 */
+1, /* '9' 0x39 */
+1, /* ':' 0x3a */
+0, /* ';' 0x3b */
+1, /* '<' 0x3c */
+1, /* '=' 0x3d */
+1, /* '>' 0x3e */
+1, /* '?' 0x3f */
+1, /* '@' 0x40 */
+1, /* 'A' 0x41 */
+1, /* 'B' 0x42 */
+1, /* 'C' 0x43 */
+1, /* 'D' 0x44 */
+1, /* 'E' 0x45 */
+1, /* 'F' 0x46 */
+1, /* 'G' 0x47 */
+1, /* 'H' 0x48 */
+1, /* 'I' 0x49 */
+1, /* 'J' 0x4a */
+1, /* 'K' 0x4b */
+1, /* 'L' 0x4c */
+1, /* 'M' 0x4d */
+1, /* 'N' 0x4e */
+1, /* 'O' 0x4f */
+1, /* 'P' 0x50 */
+1, /* 'Q' 0x51 */
+1, /* 'R' 0x52 */
+1, /* 'S' 0x53 */
+1, /* 'T' 0x54 */
+1, /* 'U' 0x55 */
+1, /* 'V' 0x56 */
+1, /* 'W' 0x57 */
+1, /* 'X' 0x58 */
+1, /* 'Y' 0x59 */
+1, /* 'Z' 0x5a */
+1, /* '[' 0x5b */
+1, /* '\' 0x5c */
+1, /* ']' 0x5d */
+1, /* '^' 0x5e */
+1, /* '_' 0x5f */
+0, /* '`' 0x60 */
+1, /* 'a' 0x61 */
+1, /* 'b' 0x62 */
+1, /* 'c' 0x63 */
+1, /* 'd' 0x64 */
+1, /* 'e' 0x65 */
+1, /* 'f' 0x66 */
+1, /* 'g' 0x67 */
+1, /* 'h' 0x68 */
+1, /* 'i' 0x69 */
+1, /* 'j' 0x6a */
+1, /* 'k' 0x6b */
+1, /* 'l' 0x6c */
+1, /* 'm' 0x6d */
+1, /* 'n' 0x6e */
+1, /* 'o' 0x6f */
+1, /* 'p' 0x70 */
+1, /* 'q' 0x71 */
+1, /* 'r' 0x72 */
+1, /* 's' 0x73 */
+1, /* 't' 0x74 */
+1, /* 'u' 0x75 */
+1, /* 'v' 0x76 */
+1, /* 'w' 0x77 */
+1, /* 'x' 0x78 */
+1, /* 'y' 0x79 */
+1, /* 'z' 0x7a */
+1, /* '{' 0x7b */
+1, /* '|' 0x7c */
+1, /* '}' 0x7d */
+1, /* '~' 0x7e */
+0, /* DEL 0x7f */
+1, /* 0x80 */
+1, /* 0x81 */
+1, /* 0x82 */
+1, /* 0x83 */
+1, /* 0x84 */
+1, /* 0x85 */
+1, /* 0x86 */
+1, /* 0x87 */
+1, /* 0x88 */
+1, /* 0x89 */
+1, /* 0x8a */
+1, /* 0x8b */
+1, /* 0x8c */
+1, /* 0x8d */
+1, /* 0x8e */
+1, /* 0x8f */
+1, /* 0x90 */
+1, /* 0x91 */
+1, /* 0x92 */
+1, /* 0x93 */
+1, /* 0x94 */
+1, /* 0x95 */
+1, /* 0x96 */
+1, /* 0x97 */
+1, /* 0x98 */
+1, /* 0x99 */
+1, /* 0x9a */
+1, /* 0x9b */
+1, /* 0x9c */
+1, /* 0x9d */
+1, /* 0x9e */
+1, /* 0x9f */
+0, /* other: 0xa0 */
+1, /* 0xa1 */
+1, /* 0xa2 */
+1, /* 0xa3 */
+1, /* 0xa4 */
+1, /* 0xa5 */
+1, /* 0xa6 */
+1, /* 0xa7 */
+1, /* 0xa8 */
+1, /* 0xa9 */
+1, /* 0xaa */
+1, /* 0xab */
+1, /* 0xac */
+1, /* 0xad */
+1, /* 0xae */
+1, /* 0xaf */
+1, /* 0xb0 */
+1, /* 0xb1 */
+1, /* 0xb2 */
+1, /* 0xb3 */
+1, /* 0xb4 */
+1, /* 0xb5 */
+1, /* 0xb6 */
+1, /* 0xb7 */
+1, /* 0xb8 */
+1, /* 0xb9 */
+1, /* 0xba */
+1, /* 0xbb */
+1, /* 0xbc */
+1, /* 0xbd */
+1, /* 0xbe */
+1, /* 0xbf */
+1, /* 0xc0 */
+1, /* 0xc1 */
+1, /* 0xc2 */
+1, /* 0xc3 */
+1, /* 0xc4 */
+1, /* 0xc5 */
+1, /* 0xc6 */
+1, /* 0xc7 */
+1, /* 0xc8 */
+1, /* 0xc9 */
+1, /* 0xca */
+1, /* 0xcb */
+1, /* 0xcc */
+1, /* 0xcd */
+1, /* 0xce */
+1, /* 0xcf */
+1, /* 0xd0 */
+1, /* 0xd1 */
+1, /* 0xd2 */
+1, /* 0xd3 */
+1, /* 0xd4 */
+1, /* 0xd5 */
+1, /* 0xd6 */
+1, /* 0xd7 */
+1, /* 0xd8 */
+1, /* 0xd9 */
+1, /* 0xda */
+1, /* 0xdb */
+1, /* 0xdc */
+1, /* 0xdd */
+1, /* 0xde */
+1, /* 0xdf */
+1, /* 0xe0 */
+1, /* 0xe1 */
+1, /* 0xe2 */
+1, /* 0xe3 */
+1, /* 0xe4 */
+1, /* 0xe5 */
+1, /* 0xe6 */
+1, /* 0xe7 */
+1, /* 0xe8 */
+1, /* 0xe9 */
+1, /* 0xea */
+1, /* 0xeb */
+1, /* 0xec */
+1, /* 0xed */
+1, /* 0xee */
+1, /* 0xef */
+1, /* 0xf0 */
+1, /* 0xf1 */
+1, /* 0xf2 */
+1, /* 0xf3 */
+1, /* 0xf4 */
+1, /* 0xf5 */
+1, /* 0xf6 */
+1, /* 0xf7 */
+1, /* 0xf8 */
+1, /* 0xf9 */
+1, /* 0xfa */
+1, /* 0xfb */
+1, /* 0xfc */
+1, /* 0xfd */
+1, /* 0xfe */
+0, /* other: 0xff */
+};
+static char *
+xchar(int c, char *buf, int size)
+{
+ snprintf(buf, size,"%%%02x",c);
+ return buf;
+}
+
+/* Translate dangerous and some other characters to safe
+ %xx form.
+*/
+void
+translate_to_uri(const char * filename, struct esb_s *out)
+{
+ char buf[8];
+ const char *cp = 0;
+ for(cp = filename ; *cp; ++cp) {
+ char v[2];
+ int c = 0xff & (unsigned char)*cp;
+ if(dwarfdump_ctype_table[c]) {
+ v[0] = c;
+ v[1] = 0;
+ esb_append(out,v);
+ } else {
+ char *b = xchar(c,buf,sizeof(buf));
+ esb_append(out,b);
+ }
+ }
+}
+
+/* This is not very efficient, but it is seldom called. */
+static char
+hexdig(char c)
+{
+ char ochar = 0;
+ if(c >= 0 && c <= '9') {
+ ochar = (c - '0');
+ return ochar;
+ }
+ if(c >= 'a' && c <= 'f') {
+ ochar = (c - 'a')+10;
+ return ochar;
+ }
+ if(c >= 'A' && c <= 'F') {
+ ochar = (c - 'A')+10;
+ return ochar;
+ }
+ // We have an input botch here.
+ fprintf(stderr,"Translating from uri: "
+ "A supposed hexadecimal input character is "
+ "not 0-9 or a-f or A-F, it is (shown as hex here): %x\n",c);
+ return ochar;
+}
+
+static char tohex(char c1, char c2)
+{
+ char out = (hexdig(c1) << 4) | hexdig(c2);
+ return out;
+}
+static int
+hexpairtochar(const char *cp, char*myochar)
+{
+ char ochar = 0;
+ int olen = 0;
+ char c = cp[0];
+ if(c) {
+ char c2 = cp[1];
+ if(c2) {
+ ochar = tohex(c,c2);
+ olen = 2;
+ } else {
+ fprintf(stderr,"Translating from uri: "
+ "A supposed hexadecimal input character pair "
+ "runs off the end of the input after 1 hex digit.\n");
+ /* botched input. */
+ ochar = c;
+ olen = 1;
+ }
+ } else {
+ /* botched input. */
+ fprintf(stderr,"Translating from uri: "
+ "A supposed hexadecimal input character pair "
+ "runs off the end of the input.\n");
+ ochar = '%';
+ olen = 0;
+ }
+ *myochar = ochar;
+ return olen;
+}
+
+void
+translate_from_uri(const char * input, struct esb_s* out)
+{
+ const char *cp = input;
+ char tempstr[2];
+ for(; *cp; ++cp) {
+ char c = *cp;
+ if(c == '%') {
+ int increment = 0;
+ char c2 = cp[1];
+ // hexpairtochar deals with c2 being NUL.
+ if ( c2 == '%') {
+ tempstr[0] = c;
+ tempstr[1] = 0;
+ esb_append(out,tempstr);
+ ++cp;
+ continue;
+ }
+
+ increment = hexpairtochar(cp+1,&c);
+ tempstr[0] = c;
+ tempstr[1] = 0;
+ esb_append(out,tempstr);
+ cp +=increment;
+ continue;
+ }
+ tempstr[0] = c;
+ tempstr[1] = 0;
+ esb_append(out,tempstr);
+ }
+}
+
+
+
+
+#ifdef TEST
+
+unsigned errcnt = 0;
+
+static void
+mytestfrom(const char * in,const char *expected,int testnum)
+{
+ struct esb_s out;
+ esb_constructor(&out);
+ translate_from_uri(in, &out);
+ if(strcmp(expected, esb_get_string(&out))) {
+ printf(" Fail test %d expected \"%s\" got \"%s\"\n",
+ testnum,expected,esb_get_string(&out));
+ ++errcnt;
+ }
+ esb_destructor(&out);
+}
+
+
+static void
+mytest(char *in,char *expected,int testnum)
+{
+ struct esb_s out;
+ esb_constructor(&out);
+ translate_to_uri(in, &out);
+ if(strcmp(expected, esb_get_string(&out))) {
+ printf(" Fail test %d expected %s got %s\n",testnum,expected,esb_get_string(&out));
+ ++errcnt;
+ }
+ esb_destructor(&out);
+}
+
+
+int
+main()
+{
+ /* We no longer translate space to %20, that
+ turns out not to help all that much. */
+ mytest("aaa","aaa",1);
+ mytest(" bc"," bc",2);
+ mytest(";bc","%3bbc",3);
+ mytest(" bc\n"," bc%0a",4);
+ mytest(";bc\n","%3bbc%0a",5);
+ mytest(" bc\r"," bc%0d",6);
+ mytest(";bc\r","%3bbc%0d",7);
+ mytest(" \x01"," %01",8);
+ mytest(";\x01","%3b%01",9);
+ mytestfrom("abc","abc",10);
+ mytestfrom("a%20bc","a bc",11);
+ mytestfrom("a%%20bc","a%20bc",12);
+ mytestfrom("a%%%20bc","a% bc",13);
+ mytestfrom("a%%%%20bc","a%%20bc",14);
+ mytestfrom("a%20","a ",15);
+ /* The following is mistaken input. */
+ mytestfrom("a%2","a2",16);
+ mytestfrom("a%","a%",17);
+ mytest("%bc","%25bc",18);
+
+ if(errcnt) {
+ printf("uri errcount ",errcnt);
+ }
+ return errcnt? 1:0;
+}
+#endif
+
diff --git a/dwarfdump/uri.h b/dwarfdump/uri.h
new file mode 100644
index 0000000..0dfa386
--- /dev/null
+++ b/dwarfdump/uri.h
@@ -0,0 +1,37 @@
+/*
+ Copyright 2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+void translate_to_uri(const char * filename, struct esb_s *out);
+void translate_from_uri(const char * input, struct esb_s *out);
+
diff --git a/dwarfdump/uritablebuild.c b/dwarfdump/uritablebuild.c
new file mode 100644
index 0000000..c8c5501
--- /dev/null
+++ b/dwarfdump/uritablebuild.c
@@ -0,0 +1,146 @@
+/*
+ Copyright 2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include <stdio.h>
+#include <ctype.h>
+
+/* Generates a table which identifies a few dangerous characters.
+ Ones one does not want to appear in output.
+
+ It's a bit arbitrary in that we allow lots of shell-interpreted
+ characters through, and most characters generally.
+
+ But not control characters or single or double quotes.
+ The quotes would be particularly problematic for post-processing
+ dwarfdump output sensibly.
+
+*/
+static void
+print_entry(int c)
+{
+ char v[2];
+ v[0] = c;
+ v[1] = 0;
+ if(c == 0) {
+ printf("0, /* NUL 0x%02x */\n",c);
+ return;
+ }
+ if(isalnum(c) || c == ' ' ) {
+ /* We let the space character print as space since
+ lots of files are named that way in Mac and Windows.
+ */
+ printf("1, /* \'%s\' 0x%02x */\n",v,c);
+ return;
+ }
+ if(c == 0x21 || c == 0x23 || c == 0x26) {
+ /* We let the space character print as space since
+ lots of files are named that way in Mac and Windows.
+ */
+ printf("1, /* \'%s\' 0x%02x */\n",v,c);
+ return;
+ }
+ if(isspace(c) ) {
+ /* Other white space translated. */
+ printf("0, /* whitespace 0x%02x */\n",c);
+ return;
+ }
+ if(c == 0x7f) {
+ printf("0, /* DEL 0x%02x */\n",c);
+ return;
+ }
+ if(c >= 0x01 && c <= 0x20 ) {
+ /* ASCII control characters. */
+ printf("0, /* control 0x%02x */\n",c);
+ return;
+ }
+ if(c == '\'' || c == '\"' || c == '%' || c == ';' ) {
+ printf("0, /* \'%s\' 0x%02x */\n",v,c);
+ return;
+ }
+ if(c >= 0x3a && c <= 0x40 ) {
+ /* ASCII */
+ printf("1, /* \'%s\' 0x%02x */\n",v,c);
+ return;
+ }
+ if(c == 0xa0 || c == 0xff ) {
+ printf("0, /* other: 0x%02x */\n",c);
+ return;
+ }
+ if(c >= 0x27 && c <= 0x2f ) {
+ /* ASCII */
+ printf("1, /* \'%s\' 0x%02x */\n",v,c);
+ return;
+ }
+ if(c >= 0x5b && c <= 0x5f ) {
+ /* ASCII */
+ printf("1, /* \'%s\' 0x%02x */\n",v,c);
+ return;
+ }
+ if(c >= 0x60 && c <= 0x60 ) {
+ /* ASCII */
+ printf("0, /* \'%s\' 0x%02x */\n",v,c);
+ return;
+ }
+ if(c >= 0x7b && c <= 0x7e ) {
+ /* ASCII */
+ printf("1, /* \'%s\' 0x%02x */\n",v,c);
+ return;
+ }
+ if (c < 0x7f) {
+ /* ASCII */
+ printf("1, /* \'%s\' 0x%02x */\n",v,c);
+ return;
+ }
+ /* We are allowing other iso 8859 characters through unchanged. */
+ printf("1, /* 0x%02x */\n",c);
+}
+
+
+int
+main()
+{
+ int i = 0;
+ printf("/* dwarfdump_ctype table */\n");
+ printf("char dwarfdump_ctype_table[256] = { \n");
+ for ( i = 0 ; i <= 255; ++i) {
+ print_entry(i);
+ }
+ printf("};\n");
+}
+
diff --git a/dwarfdump2/COPYING b/dwarfdump2/COPYING
new file mode 100644
index 0000000..355bd60
--- /dev/null
+++ b/dwarfdump2/COPYING
@@ -0,0 +1,31 @@
+
+David Anderson: December 2006
+The code in the dwarfdump directory is (if you look
+in each file) covered by the GPL (not the LGPL). The
+DWARFDUMPCOPYRIGHT file, though, said (before December 24,
+2006) the copyright is LGPL. There is no doubt in my (David
+Anderson) mind that the intent was always that dwarfdump be
+GPL and the copyright markings in each file are correct.
+
+There are three files marked with the LGPL: tag_tree.list
+tag_attr.list acconfig.h. These markings are left as is and
+these are are therefore LGPL files.
+
+The DWARFDUMPCOPYRIGHT file now (Dec 24 2006) has both
+copyrights and an explanation of where each applies.
+
+
+
+-------------------------------------------
+The text present for years, thru Dec 23, 2006:
+The files:
+ dwarfdump.c
+ and all the .h and .c files in this implementation of
+ dwarfdump are copyrighted according to the file
+ DWARFDUMPCOPYRIGHT.
+
+
+
+$Source: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/COPYING,v $
+$Revision: 1.1 $
+$Date: 2001/01/16 17:47:55 $
diff --git a/dwarfdump2/ChangeLog b/dwarfdump2/ChangeLog
new file mode 100644
index 0000000..5c56ac1
--- /dev/null
+++ b/dwarfdump2/ChangeLog
@@ -0,0 +1,2 @@
+2012-04-10 DavidAnderson <davea42@earthlink.net>
+ * dwarfdump.cc, common.cc: Updated version string.
diff --git a/dwarfdump2/ChangeLog2009 b/dwarfdump2/ChangeLog2009
new file mode 100644
index 0000000..e3cecb9
--- /dev/null
+++ b/dwarfdump2/ChangeLog2009
@@ -0,0 +1,156 @@
+2009-12-30 DavidAnderson <davea42@earthlink.net>
+ * configure: Regenerated with autoconf 2.64.
+2009-11-24 DavidAnderson <davea42@earthlink.net>
+ * tag_common.h: Updated 'standard tag table row' and
+ tag table column maximums now the DWARF4 entries are
+ in the .list files. Removed dos 'CR' characters at line ends.
+ * tag_tree.list, tag_attr.list: Added various
+ DWARF4 entries and added DW_TAG_enumeration_type
+ under DW_TAG_union_type.
+2009-11-17 DavidAnderson <davea42@earthlink.net>
+ * dwarfdump.1: Document the -u option more fully.
+ * print_die.cc: Check for both info_flag and
+ cu_name_flag to decide when to print DIEs.
+2009-10-12 DavidAnderson <davea42@earthlink.net>
+ * dwarfdump.cc: Updated dwarfdump version string to today.
+2009-09-30 DavidAnderson <davea42@earthlink.net>
+ * dwarfdump.cc: Added globals for aranges checking and
+ to print the resulting error count.
+ * print_aranges.cc: Added checking that all 3 ways
+ of computing a cu_die_offset from an arange get
+ the same offset (checked with -r -ka).
+ * print_frames.cc: DW_CFA_cfa_offset_extended_sf
+ corrected to DW_CFA_offset_extended_sf.
+ The print_frames code now uses the dwarf_get_CFA_name() call
+ from libdwarf to print frame operation names.
+ * globals.h: New function SpaceSurround() so we can use
+ dwarf_get_CFA_name concisely in print_frames.cc.
+ Added aranges_result
+ and check_aranges so print_aranges.cc can use them.
+2009-09-01 DavidAnderson <davea42@earthlink.net>
+ * tag_tree.list: We add
+ DW_TAG_class_type as a valid child of a DW_TAG_union_type.
+2009-08-05 DavidAnderson <davea42@earthlink.net>
+ * gennames.c: Change include from getopt.h to unistd.h
+ so the code is more universally compilable.
+2009-06-23: David Anderson <davea42@earthlink.net>
+ * strstrnocase.cc: Corrected typo in TEST code and
+ added a new test.
+2009-06-22: David Anderson <davea42@earthlink.net>
+ * Makefile.in: switched to personally written
+ string comparison, strstrnocase.c.
+ * stristr.c: deleted.
+ * strstrnocase.c: New code, written by me so no
+ license issues.
+ * print_die.c: Call is_strstrnocase(),
+ the new function. Change a local variable to unsigned
+ to avoid a compiler warning about signed/unsigned comparison.
+ * dwarfdump.1: More fully document -S.
+ * globals.h: Create extern for is_strstrnocase().
+2009-06-18: David Anderson <davea42@earthlink.net>
+ * configure: Regenerated.
+ * Makefile.in: Added stristr.o
+ * dieholder.h,print_die.cc, dwarfdump.cc,print_lines.cc,print_aranges.cc:
+ Added support for -S
+ * Test for regex, set HAV_REGEX for -S support.
+ * dwarfdump.1: document -S
+ * stristr.cc: New public domain source file.
+ * config.h.in: Adding HAVE_REGEX default value.
+ * globals.h: Adding support for -S.
+2009-06-06: David Anderson <davea42@earthlink.net>
+ * fderegs.h: Remove unused line and switch
+ an argument to unsigned to avoid -Wall warning.
+ * naming.cc,naming.h: New files that implement the
+ ellipsis functionality of dwarfdump and defer to
+ libdwarf to get the names of the TAGs, FORMs, etc..
+ * gennames.cc: This file has moved to libdwarf, no longer
+ present in dwarfdump.
+ * print_static_vars.cc,print_static_funcs.cc,
+ print_sections.cc,print_strings.cc, print_locs.cc,
+ print_lines.cc, print_pubnames.cc,print_ranges.cc,
+ print_macros.cc,print_types.cc,tag_common.cc,
+ print_weaknames.cc, print_aranges.cc: Include
+ changed from dwarf_names.h to naming.h
+ * dwarfdump.cc: Updated DWARFDUMP_VERSION string.
+ * tag_tree.cc,tag_attr.cc: Include changed from
+ dwarf_names.h to naming.h. Remove dbg argument to get_TAG_name.
+ * print_die.cc,print_abbrevs.cc: Include changed from
+ dwarf_names.h to naming.h.
+ Calls to get_TAG_name (etc) no longer have a dbg argument.
+ * Makefile.in: We no longer build generated file names.c,
+ we build naming.c (hand coded, not generated).
+ * tag_common.h: Delete table of TAG names, libdwarf provides
+ the name strings now.
+2009-05-10: David Anderson <davea42@earthlink.net>
+ * dwarfdump.cc: updated DWARF_VERSION string.
+ * print_frames.cc: When using the older frame register
+ interface with -v, suggest use of -R instead of erroring off
+ or segfaulting in dwarfdump.
+2009-05-07: David Anderson <davea42@earthlink.net>
+ * Makefile.in: The dwarf_names* files are all
+ generated by C++ now, so clean cleans them out.
+2009-05-04: David Anderson <davea42@earthlink.net>
+ * dwarf_names.awk, at_list.awk: deleted. gennames.cc replaces these.
+ * common.h, common.cc: Extracted simple utility routines
+ into their own files.
+ * tag_common.c, tag_common.h: Removed the simple utility
+ routines from these files to simplify dependencies.
+ * tag_attr.cc, tag_tree.cc: Include new common.h.
+ * print_frames.cc, print_frames.h: Adding address_size argument to call.
+ * print_locs.cc: Gets and uses CU-specific address_size.
+ * print_ranges.cc: Adding commentary.
+ * print_die.cc: adding DIE argument to ensure correct
+ address size used for the CU in question.
+ * Makefile.in: Now handles common.* and gennames.cc changes.
+ * gennames.cc: New code emitting string 'get name' source.
+ * print_frames.h: Adding new address_size argument to
+ get_string_from_locs().
+ * dwarf_names_new.h: Deleted from svn, this is generated.
+2009-04-03: David Anderson <davea42@earthlink.net>
+ * Makefile.in: clean up 'clean' and 'distclean'
+ so that distributed files are not cleaned out by 'clean'
+ and all generated files (even those shipped in distribution)
+ are cleaned out by distclean.
+ * fderegs.h: New class that reads interface 2 and 3 libdwarf
+ and reduces to a common interface to simplify print_frames.cc
+ It also radically speeds up frame printing when there are
+ large numbers of registers in the ABI by using a different
+ libdwarf interface than before.
+ * print_frames.cc: Uses FdeRegs class to simplify and unify
+ getting frame registers. Uses a different libdwarf interface
+ to speed up register acquisition.
+ * dwarfdump.cc: Added calls to libdwarf to specify the correct
+ 'same value' and 'undefined value' pseudo-register numbers.
+ * dwarfdump.1: Amplified -R and -x abi= documentation.
+ * dwconf.cc: Added comments and deleted a few duplicated lines.
+ * dwarfdump.conf: Added generic500 generic100 abis.
+ Now all ABIs have same_val_reg: and undefined_val_reg:
+ defined.
+ * dwarf_names_enum.h: delete dwarf_names_enum.h from svn,
+ it is a generated file.
+2009-03-29: David Anderson <davea42@earthlink.net>
+ * Makefile.in: References dieholder.h and srcfilesholder.h.
+ * dieholder.h: New: Implements DieHolder class.
+ * srcfilesholder.h: New: Implements SrcfilesHolder class.
+ * print_aranges.cc: Use SrcfilesHolder and DieHolder classes.
+ * print_sections.cc: The dwarf_names_print_on_error flag
+ is now a bool.
+ * globals.h: Some interfaces use SrcfilesHolder and DieHolder classes.
+ Some values now external so they are visible (used in print_infos()
+ which is now in print_die.cc.
+ The dwarf_names_print_on_error flag is now a bool.
+ * print_lines.cc: Use SrcefilesHolder and DieHolder classes.
+ * dwarfdump.cc: If should_skip_this_cu() we need to
+ continue; and this fixes the omission of the continue.
+ print_infos() moved out of here.
+ * print_die.cc: Moved print_infos() to here. Interfaces use
+ DieHolder and SrcfilesHolder classes now.
+ * print_locs.cc: Add a new -v (verbose) output field so
+ entries can be matched to .debug_info output.
+ * dwarf_names.awk: The 'print on error' arg is now a bool.
+ Removed a superfluous space from the generated code.
+ * print_macros.cc: A ) was missing from the output.
+ * tag_tree.cc,tag_attr.cc: The 'print on error' argument
+ of the generated code (and all uses) is now a bool.
+2009-02-28: David Anderson <davea42@earthlink.net>
+ * Created a new source base based on dwarfdump.
diff --git a/dwarfdump2/ChangeLog2010 b/dwarfdump2/ChangeLog2010
new file mode 100644
index 0000000..084e3fa
--- /dev/null
+++ b/dwarfdump2/ChangeLog2010
@@ -0,0 +1,77 @@
+2010-09-30 DavidAnderson <davea42@earthlink.net>
+ * dwarfdump.cc: Now -a no longer implies -c because
+ the -c option is not guaranteed to work by the DWARF spec,
+ nor is -c really necessary.
+ * README: More tweaks on the 'install' issue.
+2010-09-29 DavidAnderson <davea42@earthlink.net>
+ * README, Makefile.in: Amplified make install instructions.
+2010-09-20 DavidAnderson <davea42@earthlink.net>
+ * dwarfdump.1: The -c option is not guaranteed to work.
+ Because .debug_loc can have garbage bytes in areas
+ not referenced by .debug_info.
+2010-04-22 DavidAnderson <davea42@earthlink.net>
+ * print_die.cc: If a location form is wrong report
+ an error but continue operating.
+ * dwarfdump.cc: Implement print_error_and_continue().
+ Fix typos in usage message.
+ * globals.h: Declare print_error_and_continue().
+2010-04-02 DavidAnderson <davea42@earthlink.net>
+ * dwarfdump.cc,print_lines.cc: Ensure that
+ the error checks counts are as accurate as possible.
+ New version date.
+ * print_frames.cc: Ensure that
+ the error checks counts are as accurate as possible.
+ Modify a message about fdes to get the strings to match
+ print_frames.c dwarfdump.
+2010-03-31 DavidAnderson <davea42@earthlink.net>
+ * dwarfdump.1: Added some text about 'harmless'
+ errors.
+ * dwarfdump.c: Change the harmless error list maximum
+ to 50. Change harmless error reporting to be associated
+ with -k flags.
+ * print_frames.cc: Change harmless error reporting to be
+ associated with -k flags.
+ * print_aranges.cc: Call dwarf_get_arange_info_b allowing
+ for segmented architectures which are really only
+ defined properly in aranges for DWARF4.
+ Change harmless error reporting to be
+ associated with -k flags.
+ * globals.h: Declarations added for 'harmless' error
+ reporting.
+2010-03-28 DavidAnderson <davea42@earthlink.net>
+ * dwarf_globals.h: Added interface to print_any_harmless_errors().
+ * dwarfdump.cc: Added print_any_harmless_errors() implementation
+ and we call it just before closing libdwarf.
+ * print_frames.cc: Call print_any_harmless_errors after
+ getting cie/fde list.
+ * dwarfdump.conf: Add abi named 'arm' for Arm users.
+2010-02-14 DavidAnderson <davea42@earthlink.net>
+ * print_die.cc: Add newer DW_OP operators, remove
+ bogus test of DW_OP_nop as the highest valid operator.
+ Add table of DW_OPs to simplify testing for zero-operand
+ operators.
+ Revise so that the FORM of all attributes print with -M.
+ * tag_attr.list: Updated copyright.
+ * tag_tree_ext.list, tag_attr_ext.list: Added GNU template
+ parameter tags, attributes. Updated copyright.
+ * tag_tree.list: Added template parameter tags. Added
+ entry for nested classes. Updated copyright.
+ * tag_common.h: Increased STD_TAG_TABLE_COLUMNS and
+ EXT_ATTR_TABLE_COLS.
+2010-01-30 DavidAnderson <davea42@earthlink.net>
+ * print_die.c: Changed the spelling of one
+ 'DW_AT_type offset does not point to type info' error message so
+ one can distinguish which check lead to the message.
+2010-01-26 DavidAnderson <davea42@earthlink.net>
+ * dwconf.cc, fderegs.h, dwconf.h, dwarfdump.1,
+ dwarfdump.conf: The default frame values in frame
+ output are now generic registers like r0 to r99
+ instead of MIPS register names.
+ For the MIPS register names use '-x abi=mips'.
+2010-01-17 DavidAnderson <davea42@earthlink.net>
+ * print_die.cc: The special case DW_AT_SUN_func_offsets
+ now prints identically in dwarfdump and dwarfdump2.
+2010-01-03 DavidAnderson <davea42@earthlink.net>
+ * tag_common.cc, common.cc, common.h: Remove <cr>
+ line terminator characters and update copyright year.
+ * All other files: Update copyright year.
diff --git a/dwarfdump2/DWARFDUMPCOPYRIGHT b/dwarfdump2/DWARFDUMPCOPYRIGHT
new file mode 100644
index 0000000..cf465e2
--- /dev/null
+++ b/dwarfdump2/DWARFDUMPCOPYRIGHT
@@ -0,0 +1,85 @@
+
+========The dwarfdump copyright=======
+
+The full text of the GPL version 2 is provided in the file GPL.txt.
+
+Nearly all the files in this directory have contained a GPL
+copyright, not an LGPL copyright, for years. The following
+is an example of that copyright as used in the dwarfdump
+source, and is what SGI always intended (in David
+Anderson's opinion) to have present in
+the DWARFDUMPCOPYRIGHT file. (tag_tree.list tag_attr.list
+acconfig.h have long been marked LGPL and therefore the LGPL
+copyright, not GPL, applies to those three files.) This GPL
+copyright text added here to DWARFDUMPCOPYRIGHT Dec 4, 2006
+
+ Copyright (C) 2000,2002,2004,2005 Silicon Graphics, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+The following was the entire content of this file before
+December 24 2006, Being the LGPL text this is in conflict
+with the individual source files and I (David Anderson)
+believe the source file copyright was intended for dwarfdump
+not the LGPL source directly following this note. However the
+3 files tag_tree.list tag_attr.list acconfig.h have long been
+marked LGPL and the following copyright applies to those three.
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
diff --git a/dwarfdump2/GPL.txt b/dwarfdump2/GPL.txt
new file mode 100644
index 0000000..d511905
--- /dev/null
+++ b/dwarfdump2/GPL.txt
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/dwarfdump2/Makefile.in b/dwarfdump2/Makefile.in
new file mode 100644
index 0000000..1691337
--- /dev/null
+++ b/dwarfdump2/Makefile.in
@@ -0,0 +1,175 @@
+#
+# Makefile for dwarfdump
+# This is made very simple so it should work with
+# any 'make'.
+# The Makefile does assume that libdwarf is at ../libdwarf
+# from the dwarfdump2 source directory.
+#
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = $(exec_prefix)/bin
+libdir = $(exec_prefix)/lib
+mandir = $(exec_prefix)/share/man
+man1dir = $(mandir)/man1
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+DATAROOT = @datarootdir@
+SHELL = /bin/sh
+CXX = @CXX@
+AR = @AR@
+ARFLAGS = @ARFLAGS@
+RM = rm
+RANLIB = @RANLIB@
+DEFS = @DEFS@
+# ../libdwarf gets us to local headers
+DIRINC = $(srcdir)/../libdwarf
+LIBS = @LIBS@ -L../libdwarf -ldwarf -lelf
+INCLUDES = -I. -I$(srcdir) -I$(srcdir)/../libdwarf
+CXXFLAGS = $(PREINCS) @CXXFLAGS@ $(INCLUDES) -DCONFPREFIX=${libdir} $(POSTINCS)
+LDFLAGS = $(PRELIBS) @LDFLAGS@ $(LIBS) $(POSTLIBS)
+
+
+INSTALL = cp
+
+binprefix =
+
+FINALOBJECTS = \
+ checkutil.o \
+ dwarfdump.o \
+ dwconf.o \
+ print_abbrevs.o \
+ print_aranges.o \
+ print_die.o \
+ print_frames.o \
+ print_lines.o \
+ print_locs.o \
+ print_macros.o \
+ print_pubnames.o \
+ print_ranges.o \
+ print_reloc.o \
+ print_sections.o \
+ print_static_funcs.o \
+ print_static_vars.o \
+ print_strings.o \
+ print_types.o \
+ print_weaknames.o \
+ strstrnocase.o \
+ uri.o
+GEN_HFILES = \
+ tmp-tt-table.cc \
+ tmp-ta-table.cc \
+ tmp-ta-ext-table.cc \
+ tmp-tt-ext-table.cc
+
+all: dwarfdump
+
+HEADERS = $(srcdir)/globals.h \
+ $(srcdir)/checkutil.h \
+ $(srcdir)/dieholder.h \
+ $(srcdir)/srcfilesholder.h \
+ $(srcdir)/print_frames.h \
+ $(srcdir)/dwconf.h \
+ $(srcdir)/fderegs.h \
+ $(srcdir)/common.h \
+ $(srcdir)/naming.h \
+ $(srcdir)/tag_common.h \
+ $(srcdir)/print_frames.h \
+ $(srcdir)/uri.h
+
+$(FINALOBJECTS): $(GEN_HFILES) $(HEADERS) $(srcdir)/naming.cc
+
+default: $(TARGETS)
+
+
+dwarfdump: $(FINALOBJECTS) naming.o common.o
+ $(CXX) $(CXXFLAGS) -o $@ $(FINALOBJECTS) naming.o common.o tag_common.o $(LDFLAGS)
+
+tag_common.o: $(srcdir)/tag_common.cc $(HEADERS)
+ $(CXX) $(CXXFLAGS) -c $(srcdir)/tag_common.cc
+common.o: $(srcdir)/common.cc $(srcdir)/common.h
+ $(CXX) $(CXXFLAGS) -c $(srcdir)/common.cc
+
+
+# We need this as naming.o has external references we cannot have
+# in the tree builds.
+trivial_naming.o: $(srcdir)/naming.cc
+ $(CXX) $(CXXFLAGS) -DTRIVIAL_NAMING -c $(srcdir)/naming.cc -o trivial_naming.o
+
+tag_tree_build: $(srcdir)/tag_tree.cc $(DIRINC)/dwarf.h $(HEADERS) tag_common.o trivial_naming.o common.o
+ $(CXX) $(CXXFLAGS) $(srcdir)/tag_tree.cc trivial_naming.o tag_common.o common.o $(LDFLAGS) -o tag_tree_build
+
+tag_attr_build: $(srcdir)/tag_attr.cc $(DIRINC)/dwarf.h $(HEADERS) trivial_naming.o tag_common.o naming.o common.o
+ $(CXX) $(CXXFLAGS) $(srcdir)/tag_attr.cc trivial_naming.o tag_common.o common.o $(LDFLAGS) -o tag_attr_build
+
+tmp-tt-table.cc tmp-tt-ext-table.cc: $(srcdir)/tag_tree_ext.list $(srcdir)/tag_tree.list tag_tree_build
+ # gcc -E tag_tree.list does not work, so use a .cc name
+ -rm -f tmp-t1.cc
+ cp $(srcdir)/tag_tree.list tmp-t1.cc
+ $(CXX) $(CXXFLAGS) -E tmp-t1.cc > ./tmp-tag-tree-build1.tmp
+ ./tag_tree_build -s -i tmp-tag-tree-build1.tmp -o tmp-tt-table.cc
+ -rm -f tmp-t4.cc
+ cp $(srcdir)/tag_tree_ext.list tmp-t4.cc
+ $(CXX) $(CXXFLAGS) -E tmp-t4.cc > ./tmp-tag-tree-build4.tmp
+ ./tag_tree_build -e -i tmp-tag-tree-build4.tmp -o tmp-tt-ext-table.cc
+
+tmp-ta-table.cc tmp-ta-ext-table.cc: $(srcdir)/tag_attr_ext.list $(srcdir)/tag_attr.list tag_attr_build
+ # gcc -E tag_attr.list does not work, so use a .cc name
+ -rm -f tmp-t2.cc
+ cp $(srcdir)/tag_attr.list tmp-t2.cc
+ $(CXX) $(CXXFLAGS) -E tmp-t2.cc > ./tmp-tag-attr-build2.tmp
+ ./tag_attr_build -s -i tmp-tag-attr-build2.tmp -o tmp-ta-table.cc
+ -rm -f tmp-t3.cc
+ cp $(srcdir)/tag_attr_ext.list tmp-t3.cc
+ $(CXX) $(CXXFLAGS) -E tmp-t3.cc > ./tmp-tag-attr-build3.tmp
+ ./tag_attr_build -e -i tmp-tag-attr-build3.tmp -o tmp-ta-ext-table.cc
+
+# This simply assumes that a default INSTALL (cp) command
+# will work and leave sensible permissions on the resulting files.
+# Some adjustment might be required, see README.
+install: all
+ $(INSTALL) dwarfdump $(bindir)/dwarfdump
+ $(INSTALL) $(srcdir)/dwarfdump.1 $(man1dir)/dwarfdump.1
+ $(INSTALL) $(srcdir)/dwarfdump.conf $(libdir)/dwarfdump.conf
+
+uninstall:
+ -rm -f $(bindir)/dwarfdump
+ -rm -f $(man1dir)/dwarfdump.1
+ -rm -f $(libdir)/dwarfdump.conf
+
+clean:
+ rm -f *.o dwarfdump
+ rm -f _tag_attr_table.cc
+ rm -f _tag_attr_ext_table.cc
+ rm -f _tag_tree_table.cc
+ rm -f _tag_tree_table.cc
+ -rm -f tag_attr_build*.tmp
+ -rm -f tag_tree_build*.tmp
+ rm -f tag_tree_build
+ rm -f tag_attr_build
+ rm -f printfuncs
+ -rm -f _*.cc _*.h
+ -rm -f tmp-*.cc tmp-*.h tmp-*.tmp
+ rm -f gennames
+ rm -f dwarf_names_enum.h dwarf_names_new.cc dwarf_names_new.h
+ rm -f dwarf_names.cc dwarf_names.h
+
+distclean: clean
+ rm -f config.log config.h config.cache config.status
+ rm -rf autom4te.cache
+ rm -f Makefile
+
+
+shar:
+ @echo "shar not set up yet"
+dist:
+ @echo "dist not set up yet"
+
+test:
+ $(CXX) $(CXXFLAGS) $(srcdir)/test_printfuncs.cc -o printfuncs
+ ./printfuncs
diff --git a/dwarfdump2/NEWS b/dwarfdump2/NEWS
new file mode 100644
index 0000000..a38609c
--- /dev/null
+++ b/dwarfdump2/NEWS
@@ -0,0 +1,52 @@
+December 13, 2011
+ Now prints missing line table column number as 0 (now
+ matching the DWARF spec), the previous
+ practice of printing -1 was always wrong.
+ And prints the DWARF3/4 new line table fields (when present).
+October 29, 2011
+ Added support for printing .debug_types (type unit) data.
+October 26, 2011
+ Added new features to Makefile.in and documented in README
+ how to build dwarfdump with headers or libraries in
+ non-standard places.
+October 23, 2011
+ By default the various places with string option values
+ and file paths all use URI transformation on input and
+ if the transformation does anything at all dwarfdump reports
+ the input and transformed strings. This makes it easy
+ to deal with strings and expressions and file paths
+ that are difficult to express in a shell (or that getopt
+ mangles). Options -q and -U give you control over this process.
+October 06, 2011
+ The -x abi=mips frame register abi in dwarfdump.conf is now
+ usable with modern MIPS objects as well as old IRIX objects.
+ There are other mips-* frame register setups described
+ in dwarfdump.conf for anyone testing that nothing new has
+ been added that conflicts with old IRIX/MIPS frame generation.
+October 04, 2011
+ Revised in major ways to do the additional checks and produce the same
+ output as dwarfdump. But making use of C++ features.
+March 29, 2011
+ All indentations changed to a consistent 4 characters per level.
+ This was a massive but simple change.
+January 26, 2010
+ Changed the default frame-data register names from MIPS to
+ a generic set of registers.
+ Try '-x abi=mips' to get the traditional old MIPS register
+ naming.
+June 22, 2009
+ Added the -S option to dwarfdump.
+June 10, 2009
+ Moved the gennames.c code to libdwarf.
+May 4, 2009
+ Replaced awk source-generation of certain functions
+ with new gennames.c code.
+April 04, 2009
+ Now frame printing (-f and -F) uses a different interface
+ to libdwarf which is far more efficient for the particular
+ purpose of printing all the register rules. Reduces
+ MxN print time to M (one extreme case reduces from 2 hours
+ to 2 minutes).
+Feb 28, 2009
+ Created this new source base in C++ (from dwarfdump, which
+ is C).
diff --git a/dwarfdump2/README b/dwarfdump2/README
new file mode 100644
index 0000000..b9470b3
--- /dev/null
+++ b/dwarfdump2/README
@@ -0,0 +1,86 @@
+Dwarfdump2 is a C++ version of dwarfdump. It's intended to
+have improved features and better performance and be easier
+to understand than dwarfdump, but the printed output is intended
+to be the same as dwarfdump (aside from the new features and
+improvements).
+
+If this does not work for you, please let me know.
+
+To build dwarfdump, first build libdwarf in the neighboring
+directory then type
+ ./configure
+ make
+
+Installation is a bit primitive.
+ sudo make install
+may or may not work.
+Some or all of the following might be required on Unix or Linux or MacOS:
+ sudo mkdir -p /usr/local/share/man/man1/
+ sudo mkdir -p /usr/local/lib
+ sudo mkdir -p /usr/local/bin
+Then retry the 'sudo make install' and (if necessary) try
+ sudo chmod a+x /usr/local/bin/dwarfdump
+ sudo chmod a+r /usr/local/share/man/man1/dwarfdump.1
+ sudo chmod a+r /usr/local/lib/dwarfdump.conf
+You don't really need the dwarfdump.1 man page,
+but you might as well have it. If the man page is not visible
+with 'man dwarfdump' try 'man manpath' for hints.
+
+If you don't need others using dwarfdump on your computer,
+just
+ cp dwarfdump $HOME/bin/dwarfdump
+(by convention many people put personal executables in $HOME/bin
+and fix up $PATH to refer there) which suffices as 'installation'.
+Also
+ cp dwarfdump.conf $HOME
+
+To use dwarf or libdwarf, you may want to install dwarf.h
+and libdwarf.h somewhere convenient.
+You can just copy those two headers to /usr/local/include by hand
+(or anywhere, really, that you have permission to copy to)
+(you may need to use -I/usr/local/include on compile lines
+to reference them there, but see below on configure and make).
+
+Notice that dwarf_names.cc and dwarf_names.h are supplied by
+the release though the Makefile can and may rebuild them.
+Some users find it difficult to get a reliable awk(1) program,
+so for them these prebuilt versions may be useful.
+
+If your headers or libelf/libdwarf are not in the expected places,
+use the make command line to add flags and include directories.
+For example
+ ./configure
+ PREINCS="-I /usr/local/include" POSTINCS="-I /home/x/include" make
+PREINCS content is inserted before CFLAGS as make(1) is running.
+POSTINCS content is added after the CFLAGS value.
+
+To set LDFLAGS,
+do so at configure time, for example:
+ ./configure LDFLAGS="-L /some/dir"
+And/or use PRELIBS and/or POSTLIBS at 'make' time similar to the use
+of PREINCS and POSTINCS.
+
+If the libdwarf directory
+has both libdwarf.so and libdwarf.a, the libdwarf.so
+will be picked up and
+ "./tag_tree_build: error while loading shared libraries:
+ libdwarf.so: cannot open shared object file:
+ No such file or directory"
+will probably result.
+Either: remove libdwarf.so and rebuild or set
+the environment variable LD_LIBRARY_PATH to the directory
+containing the .so or use LDFLAGS to set rpath (see just below).
+It is perhaps simpler to ensure that the libdwarf directory
+only has an archive, not a shared-library.
+But sometimes one wants a shared library.
+In that case
+one can set ld's -rpath on the gcc command line like this:
+ LDFLAGS="-Wl,-rpath=/some/path/libdir"
+so the shared library can be found at run time automatically.
+
+The same problem may arise with libelf, and the same approach
+will solve the problem.
+
+
+
+David Anderson. davea42 at earthlink dot net.
diff --git a/dwarfdump2/checkutil.cc b/dwarfdump2/checkutil.cc
new file mode 100644
index 0000000..2373700
--- /dev/null
+++ b/dwarfdump2/checkutil.cc
@@ -0,0 +1,156 @@
+/*
+ Copyright (C) 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+*/
+/*
+
+ These simple list-processing functions are in support
+ of checking DWARF for compiler-errors of various sorts.
+
+
+*/
+
+#include "globals.h"
+#include <assert.h>
+using std::cout;
+using std::cerr;
+using std::endl;
+
+
+bool
+AddressRangesData::IsAddressInAddressRange(Dwarf_Unsigned pc)
+{
+ if(pc < low_pc_) {
+ return false;
+ }
+ if(pc > high_pc_) {
+ return false;
+ }
+ for(std::list<AddressRangeEntry>::iterator it =
+ address_range_data_.begin(); it != address_range_data_.end();
+ ++it) {
+ if (it->inThisRange(pc) ) {
+ return true;
+ }
+ }
+ return false;
+
+}
+
+void
+AddressRangeEntry::printAddressRangeEntry(unsigned ct)
+{
+ cout <<"[" << IToDec(ct,6) << "] Low = " <<
+ IToHex(range_low_pc_, 10 ) <<
+ ", High = " <<
+ IToHex(range_high_pc_, 10) << std::endl;
+};
+
+// Leave overall high/low as is, delete the details.
+void
+AddressRangesData::ResetRangesList()
+{
+ address_range_data_.clear();
+}
+
+// We might want to sort these by low-address rather than printing
+// in random order!
+void
+AddressRangesData::PrintRangesData()
+{
+ unsigned ct = 0;
+ cout << "Begin Traversing, Low = "<<
+ IToHex(low_pc_,10) <<
+ " High = " <<
+ IToHex(high_pc_,10);
+ for(std::list<AddressRangeEntry>::iterator it =
+ address_range_data_.begin(); it != address_range_data_.end();
+ ++it,++ct) {
+
+ it->printAddressRangeEntry(ct);
+ }
+}
+void
+AddressRangesData::AddAddressRange(Dwarf_Unsigned low_pc, Dwarf_Unsigned high_pc)
+{
+ // Presently we are not checking for duplicates, so some
+ // can be present.
+ address_range_data_.push_back(AddressRangeEntry(low_pc,high_pc));
+};
+
+void
+AddressRangesData::SetLimitsAddressRange(Dwarf_Unsigned low_pc, Dwarf_Unsigned high_pc)
+{
+ if(low_pc < high_pc) {
+ low_pc_ = low_pc;
+ high_pc_ = high_pc;
+ }
+};
+
+void
+LinkOnceEntry::printLinkOnceEntry(unsigned ct)
+{
+ cout <<"[" << IToDec(ct,6) << "] Low = " <<
+ IToHex(lo_section_low_pc_, 10 ) <<
+ ", High = " <<
+ IToHex(lo_section_high_pc_, 10) <<
+ ", section index = " <<
+ lo_section_index_ <<
+ ", section = " <<
+ lo_section_name_ << std::endl;
+};
+
+void
+LinkOnceData::PrintLinkOnceData()
+{
+ unsigned ct = 0;
+ for(std::list<LinkOnceEntry>::iterator it =
+ link_once_data_.begin(); it != link_once_data_.end();
+ ++it,++ct) {
+
+ it->printLinkOnceEntry(ct);
+ }
+}
+
+bool LinkOnceData::FindLinkOnceEntry(Dwarf_Unsigned pc)
+{
+ std::list<LinkOnceEntry>::iterator it;
+ for( it = link_once_data_.begin(); it != link_once_data_.end();
+ ++it) {
+ if (it->inThisLinkOnceRange(pc) ) {
+ return true;
+ }
+ }
+ return false;
+}
+bool LinkOnceData::FindLinkOnceEntry(const std::string &secname,Dwarf_Unsigned lopc,Dwarf_Unsigned hipc)
+{
+ std::list<LinkOnceEntry>::iterator it;
+ for( it = link_once_data_.begin(); it != link_once_data_.end();
+ ++it) {
+ if (it->inThisLinkOnceRange(secname,lopc,hipc) ) {
+ return true;
+ }
+ }
+ return false;
+}
+
diff --git a/dwarfdump2/checkutil.h b/dwarfdump2/checkutil.h
new file mode 100644
index 0000000..0594f67
--- /dev/null
+++ b/dwarfdump2/checkutil.h
@@ -0,0 +1,158 @@
+/*
+ Copyright (C) 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+*/
+
+#ifndef CHECKUTIL_H
+#define CHECKUTIL_H
+
+// A list of section address ranges with identifying
+// information. Provides the ability to check whether
+// some line data that does not match .text does match
+// some linkonce section data.
+struct LinkOnceEntry {
+public:
+ LinkOnceEntry(Dwarf_Unsigned section, Dwarf_Unsigned lowpc,
+ Dwarf_Unsigned high_pc, const std::string name):
+ lo_section_index_(section),lo_section_low_pc_(lowpc),
+ lo_section_high_pc_(high_pc),lo_section_name_(name) {};
+ ~LinkOnceEntry () {};
+ bool inThisLinkOnceRange(Dwarf_Unsigned pc) {
+ if(pc >= lo_section_low_pc_ && pc <= lo_section_high_pc_) {
+ return true;
+ }
+ return false;
+ }
+ bool inThisLinkOnceRange(const std::string &sname,Dwarf_Unsigned lopc,
+ Dwarf_Unsigned hipc) {
+ if(sname == lo_section_name_ ) {
+ if((lopc >= lo_section_low_pc_ && lopc <=
+ lo_section_high_pc_) &&
+ (hipc >= lo_section_low_pc_ && hipc <=
+ lo_section_high_pc_)) {
+ return true;
+ }
+ }
+ return false;
+ };
+ void printLinkOnceEntry(unsigned index);
+private:
+ Dwarf_Unsigned lo_section_index_;
+ Dwarf_Unsigned lo_section_low_pc_;
+ Dwarf_Unsigned lo_section_high_pc_;
+ // There are normally relatively few sections (not thousands
+ // or millions).
+ std::string lo_section_name_;
+};
+
+// In C dwarfdump see pLinkonceInfo.
+class LinkOnceData {
+public:
+ LinkOnceData() {};
+ ~LinkOnceData() {};
+ void AddLinkOnceEntry(const LinkOnceEntry &e) {
+ link_once_data_.push_back(e);
+ };
+ bool FindLinkOnceEntry(Dwarf_Unsigned pc);
+ bool FindLinkOnceEntry(const std::string &secname,Dwarf_Unsigned lopc,
+ Dwarf_Unsigned hipc);
+ void PrintLinkOnceData();
+private:
+ std::list<LinkOnceEntry> link_once_data_;
+};
+
+extern LinkOnceData *pLinkOnceData;
+
+struct AddressRangeEntry {
+public:
+ AddressRangeEntry(Dwarf_Unsigned lowpc,
+ Dwarf_Unsigned high_pc):
+ range_low_pc_(lowpc),
+ range_high_pc_(high_pc){};
+ ~AddressRangeEntry () {};
+ bool inThisRange(Dwarf_Unsigned pc) {
+ if(pc < range_low_pc_ || pc > range_high_pc_) {
+ return false;
+ }
+ return true;
+ };
+ void printAddressRangeEntry(unsigned index);
+private:
+ Dwarf_Unsigned range_low_pc_;
+ Dwarf_Unsigned range_high_pc_;
+};
+
+
+// In C dwarfdump see pRangesInfo.
+// These address ranges are within the text section,
+// and though rather like LinkOnceEntry data, we can
+// rely on an overall valid range (before we check
+// for the specific range) as a qualifier. So
+// data that must fail the search is noted as such quickly.
+class AddressRangesData {
+public:
+ AddressRangesData():low_pc_(0xffffffffffffffff),high_pc_(0) {};
+ ~AddressRangesData() {};
+ void AddAddressRange(Dwarf_Unsigned low_pc, Dwarf_Unsigned high_pc);
+ void SetLimitsAddressRange(Dwarf_Unsigned low_pc, Dwarf_Unsigned high_pc);
+ bool IsAddressInAddressRange(Dwarf_Unsigned pc);
+ void PrintRangesData();
+ void ResetRangesList();
+private:
+ Dwarf_Unsigned low_pc_;
+ Dwarf_Unsigned high_pc_;
+ std::list<AddressRangeEntry> address_range_data_;
+};
+
+extern AddressRangesData *pAddressRangesData;
+
+// In C dwarfdump see pVisitedInfo.
+// VisitedOffsetData is used to track offsets so
+// recursion and invalid references can be noted.
+class VisitedOffsetData {
+public:
+ typedef std::set<Dwarf_Unsigned,std::less<Dwarf_Unsigned> > VODtype;
+ VisitedOffsetData () { offset_ = new VODtype; };
+ ~VisitedOffsetData () { delete offset_;};
+ void reset() {
+ delete offset_;
+ offset_ = new VODtype;
+ }
+ void AddVisitedOffset(Dwarf_Unsigned off) {
+ offset_->insert(off);
+ };
+ void DeleteVisitedOffset(Dwarf_Unsigned off) {
+ offset_->erase(off);
+ };
+ bool IsKnownOffset(Dwarf_Unsigned off) {
+ VODtype::size_type v = offset_->count(off);
+ if( v) {
+ return true;
+ }
+ return false;
+ };
+private:
+ VODtype *offset_;
+};
+
+extern VisitedOffsetData *pVisitedOffsetData;
+#endif /* CHECKUTIL_H */
diff --git a/dwarfdump2/common.cc b/dwarfdump2/common.cc
new file mode 100644
index 0000000..cea678b
--- /dev/null
+++ b/dwarfdump2/common.cc
@@ -0,0 +1,88 @@
+/*
+ Copyright (C) 2008-2010 SN Systems. All Rights Reserved.
+ Portions Copyright (C) 2008-2010 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+#include <string>
+#include <iostream>
+#include "common.h"
+#define DWARFDUMP_VERSION " Tue Apr 10 11:43:32 PDT 2012 "
+using std::string;
+using std::cout;
+using std::cerr;
+using std::endl;
+
+void
+print_version_details(const std::string & name,bool alwaysprint)
+{
+#ifdef WIN32
+# ifdef _DEBUG
+ char *acType = "Debug";
+# else
+ char *acType = "Release";
+# endif /* _DEBUG */
+ static char acVersion[32];
+ snprintf(acVersion,sizeof(acVersion),
+ "[%s %s %s]",__DATE__,__TIME__,acType);
+ cout << name << " " << acVersion << endl;
+#else /* !WIN32 */
+ if(alwaysprint) {
+ cout << DWARFDUMP_VERSION << endl;
+ }
+#endif /* WIN32 */
+}
+
+
+void
+print_args(int argc, char *argv[])
+{
+#ifdef WIN32
+ int nIndex;
+ cout << "Arguments:";
+ for (nIndex = 1; nIndex < argc; ++nIndex) {
+ cout << " " << argv[nIndex] ;
+ }
+ cout << endl;
+#endif
+}
+
+void
+print_usage_message(const std::string &progname,
+ const char **text)
+{
+#ifndef WIN32
+ cerr <<"Usage: " << progname<<" <options> <object file>" << endl;
+#endif
+ for (unsigned i = 0; *text[i]; ++i) {
+ cerr << text[i] << endl;
+ }
+}
diff --git a/dwarfdump2/common.h b/dwarfdump2/common.h
new file mode 100644
index 0000000..f60d262
--- /dev/null
+++ b/dwarfdump2/common.h
@@ -0,0 +1,46 @@
+/*
+ Copyright (C) 2008-2010 SN Systems. All Rights Reserved.
+ Portions Copyright (C) 2008-2010 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+#ifndef common_INCLUDED
+#define common_INCLUDED
+
+#include <stdio.h>
+
+
+void print_args(int argc, char *argv[]);
+void print_usage_message(const std::string &program_name,
+ const char **options);
+void print_version_details(const std::string& name,bool alwaysprint);
+
+#endif /* common_INCLUDED */
diff --git a/dwarfdump2/config.h.in b/dwarfdump2/config.h.in
new file mode 100644
index 0000000..6c53389
--- /dev/null
+++ b/dwarfdump2/config.h.in
@@ -0,0 +1,94 @@
+/* config.h.in. Generated from configure.in by autoheader. */
+
+/* Define to 1 if the elf64_getehdr function is in libelf.a. */
+#undef HAVE_ELF64_GETEHDR
+
+/* Define to 1 if the Elf64_Rel structure has r_info field. */
+#undef HAVE_ELF64_R_INFO
+
+/* Define to 1 if you have the <elf.h> header file. */
+#undef HAVE_ELF_H
+
+/* Define to 1 if you have the <getopt.h> header file. */
+#undef HAVE_GETOPT_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <libelf.h> header file. */
+#undef HAVE_LIBELF_H
+
+/* Define to 1 if you have the <libelf/libelf.h> header file. */
+#undef HAVE_LIBELF_LIBELF_H
+
+/* Define 1 if off64 is defined via libelf with GNU_SOURCE. */
+#undef HAVE_LIBELF_OFF64_OK
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define 1 if need nonstandard printf format for 64bit */
+#undef HAVE_NONSTANDARD_PRINTF_64_FORMAT
+
+/* Define 1 if plain libelf builds. */
+#undef HAVE_RAW_LIBELF_OK
+
+/* Define 1 if regex seems to be defined */
+#undef HAVE_REGEX
+
+/* Define to 1 if you have the <sgidefs.h> header file. */
+#undef HAVE_SGIDEFS_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* See if __uint32_t is predefined in the compiler. */
+#undef HAVE___UINT32_T
+
+/* Define 1 if sys/types.h defines __uint32_t. */
+#undef HAVE___UINT32_T_IN_SYS_TYPES_H
+
+/* See if __uint64_t is predefined in the compiler. */
+#undef HAVE___UINT64_T
+
+/* Define to header that first defines elf. */
+#undef LOCATION_OF_LIBELFHEADER
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
diff --git a/dwarfdump2/configure b/dwarfdump2/configure
new file mode 100755
index 0000000..15c06f1
--- /dev/null
+++ b/dwarfdump2/configure
@@ -0,0 +1,5354 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.68.
+#
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+# Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ # We cannot yet assume a decent shell, so we have to provide a
+ # neutralization value for shells without unset; and this also
+ # works around shells that cannot unset nonexistent variables.
+ # Preserve -v and -x to the replacement shell.
+ BASH_ENV=/dev/null
+ ENV=/dev/null
+ (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+ export CONFIG_SHELL
+ case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+ esac
+ exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -p'
+ fi
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+PACKAGE_URL=
+
+ac_unique_file="dwarfdump.cc"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+AR
+RANLIB
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+EGREP
+GREP
+CPP
+ac_ct_CXX
+CXXFLAGS
+CXX
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_nonstandardprintf
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CXX
+CXXFLAGS
+CCC
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used" >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-option-checking ignore unrecognized --enable/--with options
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --enable-nonstandardprintf
+ Use a special printf format for 64bit (default is
+ NO)
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CXX C++ compiler command
+ CXXFLAGS C++ compiler flags
+ CPP C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.68
+
+Copyright (C) 2010 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_cxx_try_compile LINENO
+# ----------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if eval \${$3+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_header_compiler=yes
+else
+ ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ ac_header_preproc=yes
+else
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+ yes:no: )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+ no:yes:* )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: program exited with status $ac_status" >&5
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=$ac_status
+fi
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ $as_test_x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.68. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+if test -z "$ac_file"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+ if test -n "$CCC"; then
+ CXX=$CCC
+ else
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CXX+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+$as_echo "$CXX" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CXX" && break
+ done
+fi
+if test -z "$CXX"; then
+ ac_ct_CXX=$CXX
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CXX+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CXX"; then
+ ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CXX="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+$as_echo "$ac_ct_CXX" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CXX" && break
+done
+
+ if test "x$ac_ct_CXX" = x; then
+ CXX="g++"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CXX=$ac_ct_CXX
+ fi
+fi
+
+ fi
+fi
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
+$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
+if ${ac_cv_cxx_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GXX=yes
+else
+ GXX=
+fi
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+$as_echo_n "checking whether $CXX accepts -g... " >&6; }
+if ${ac_cv_prog_cxx_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ ac_cxx_werror_flag=yes
+ ac_cv_prog_cxx_g=no
+ CXXFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_prog_cxx_g=yes
+else
+ CXXFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+else
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+ CXXFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_prog_cxx_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+$as_echo "$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if ${ac_cv_prog_CPP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+if test $ac_cv_c_compiler_gnu = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC needs -traditional" >&5
+$as_echo_n "checking whether $CC needs -traditional... " >&6; }
+if ${ac_cv_prog_gcc_traditional+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_pattern="Autoconf.*'x'"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sgtty.h>
+Autoconf TIOCGETP
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "$ac_pattern" >/dev/null 2>&1; then :
+ ac_cv_prog_gcc_traditional=yes
+else
+ ac_cv_prog_gcc_traditional=no
+fi
+rm -f conftest*
+
+
+ if test $ac_cv_prog_gcc_traditional = no; then
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <termio.h>
+Autoconf TCGETA
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "$ac_pattern" >/dev/null 2>&1; then :
+ ac_cv_prog_gcc_traditional=yes
+fi
+rm -f conftest*
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_gcc_traditional" >&5
+$as_echo "$ac_cv_prog_gcc_traditional" >&6; }
+ if test $ac_cv_prog_gcc_traditional = yes; then
+ CC="$CC -traditional"
+ fi
+fi
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if ${ac_cv_path_install+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+ ./ | .// | /[cC]/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ rm -rf conftest.one conftest.two conftest.dir
+ echo one > conftest.one
+ echo two > conftest.two
+ mkdir conftest.dir
+ if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+ test -s conftest.one && test -s conftest.two &&
+ test -s conftest.dir/conftest.one &&
+ test -s conftest.dir/conftest.two
+ then
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+
+ done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+ ac_ct_AR=$AR
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_AR="ar"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_AR" = x; then
+ AR=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ AR=$ac_ct_AR
+ fi
+else
+ AR="$ac_cv_prog_AR"
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_stdc=yes
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then :
+ :
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in elf.h getopt.h libelf.h libelf/libelf.h sgidefs.h sys/types.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for elf64_getehdr in -lelf" >&5
+$as_echo_n "checking for elf64_getehdr in -lelf... " >&6; }
+if ${ac_cv_lib_elf_elf64_getehdr+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lelf $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char elf64_getehdr ();
+int
+main ()
+{
+return elf64_getehdr ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_elf_elf64_getehdr=yes
+else
+ ac_cv_lib_elf_elf64_getehdr=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_elf_elf64_getehdr" >&5
+$as_echo "$ac_cv_lib_elf_elf64_getehdr" >&6; }
+if test "x$ac_cv_lib_elf_elf64_getehdr" = xyes; then :
+
+$as_echo "#define HAVE_ELF64_GETEHDR 1" >>confdefs.h
+
+fi
+
+
+if test "$ac_cv_header_elf_h" = yes; then
+
+$as_echo "#define LOCATION_OF_LIBELFHEADER <elf.h>" >>confdefs.h
+
+elif test "$ac_cv_header_libelf_h" = yes; then
+
+$as_echo "#define LOCATION_OF_LIBELFHEADER <libelf.h>" >>confdefs.h
+
+elif test "$ac_cv_header_libelf_libelf_h" = yes; then
+
+$as_echo "#define LOCATION_OF_LIBELFHEADER <libelf/libelf.h>" >>confdefs.h
+
+fi
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include LOCATION_OF_LIBELFHEADER
+int
+main ()
+{
+Elf64_Rel *p; int i; i = p->r_info;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE_ELF64_R_INFO 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+__uint32_t p; p = 3;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE___UINT32_T 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+__uint64_t p; p = 3;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE___UINT64_T 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+int
+main ()
+{
+ __uint32_t p; p = 3;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE___UINT32_T_IN_SYS_TYPES_H 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <regex.h>
+int
+main ()
+{
+ int i;
+ regex_t r;
+ int cflags = REG_EXTENDED;
+ const char *s = "abc";
+ i = regcomp(&r,s,cflags);
+ regfree(&r);
+ ;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE_REGEX 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+# Check whether --enable-nonstandardprintf was given.
+if test "${enable_nonstandardprintf+set}" = set; then :
+ enableval=$enable_nonstandardprintf;
+$as_echo "#define HAVE_NONSTANDARD_PRINTF_64_FORMAT 1" >>confdefs.h
+
+fi
+
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <libelf.h>
+
+int
+main ()
+{
+ int p; p = 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE_RAW_LIBELF_OK 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#define _GNU_SOURCE
+#include <libelf.h>
+
+int
+main ()
+{
+ off64_t p; p = 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE_LIBELF_OFF64_OK 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+
+ac_config_files="$ac_config_files Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -p'
+ fi
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.68. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.68,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2010 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+ --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+ ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+ if test -z "$ac_tt"; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any. Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[ ]*#[ ]*define[ ][ ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ for (key in D) D_is_set[key] = 1
+ FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+ line = \$ 0
+ split(line, arg, " ")
+ if (arg[1] == "#") {
+ defundef = arg[2]
+ mac1 = arg[3]
+ } else {
+ defundef = substr(arg[1], 2)
+ mac1 = arg[2]
+ }
+ split(mac1, mac2, "(") #)
+ macro = mac2[1]
+ prefix = substr(line, 1, index(line, defundef) - 1)
+ if (D_is_set[macro]) {
+ # Preserve the white space surrounding the "#".
+ print prefix "define", macro P[macro] D[macro]
+ next
+ } else {
+ # Replace #undef with comments. This is necessary, for example,
+ # in the case of _POSIX_SOURCE, which is predefined and required
+ # on some systems where configure will not decide to define it.
+ if (defundef == "undef") {
+ print "/*", prefix defundef, macro, "*/"
+ next
+ }
+ }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS "
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+ if test x"$ac_file" != x-; then
+ {
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+ } >"$ac_tmp/config.h" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f "$ac_file"
+ mv "$ac_tmp/config.h" "$ac_file" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ fi
+ else
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+ || as_fn_error $? "could not create -" "$LINENO" 5
+ fi
+ ;;
+
+
+ esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/dwarfdump2/configure.in b/dwarfdump2/configure.in
new file mode 100644
index 0000000..b6b2256
--- /dev/null
+++ b/dwarfdump2/configure.in
@@ -0,0 +1,70 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(dwarfdump.cc)
+AC_CONFIG_HEADER(config.h)
+
+AC_PROG_CC
+AC_PROG_CXX
+AC_GCC_TRADITIONAL
+AC_PROG_INSTALL
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+AC_CHECK_TOOL(AR, ar)
+dnl AC_ARFLAGS
+
+AC_CHECK_HEADERS(elf.h getopt.h libelf.h libelf/libelf.h sgidefs.h sys/types.h)
+AC_CHECK_LIB(elf,elf64_getehdr,
+ AC_DEFINE(HAVE_ELF64_GETEHDR,1,
+ [Define to 1 if the elf64_getehdr function is in libelf.a.]))
+
+dnl Find out where the elf header is.
+if test "$ac_cv_header_elf_h" = yes; then
+ AC_DEFINE(LOCATION_OF_LIBELFHEADER,[<elf.h>], [Define to header that first defines elf])
+elif test "$ac_cv_header_libelf_h" = yes; then
+ AC_DEFINE(LOCATION_OF_LIBELFHEADER, [<libelf.h>],
+ [Define to header that first defines elf.])
+elif test "$ac_cv_header_libelf_libelf_h" = yes; then
+ AC_DEFINE(LOCATION_OF_LIBELFHEADER,[<libelf/libelf.h>],
+ [Define to header that first defines elf.])
+fi
+
+AC_TRY_COMPILE([#include LOCATION_OF_LIBELFHEADER], Elf64_Rel *p; int i; i = p->r_info; ,AC_DEFINE(HAVE_ELF64_R_INFO,1,
+ [Define to 1 if the Elf64_Rel structure has r_info field.]))
+AC_TRY_COMPILE([], __uint32_t p; p = 3; ,AC_DEFINE(HAVE___UINT32_T,
+ 1,[See if __uint32_t is predefined in the compiler. ]))
+AC_TRY_COMPILE([], __uint64_t p; p = 3; ,AC_DEFINE(HAVE___UINT64_T,
+ 1,[See if __uint64_t is predefined in the compiler. ]))
+AC_TRY_COMPILE([#include <sys/types.h>],[ __uint32_t p; p = 3]; ,
+ AC_DEFINE(HAVE___UINT32_T_IN_SYS_TYPES_H,1,
+ [Define 1 if sys/types.h defines __uint32_t.]))
+
+AC_TRY_COMPILE([#include <sys/types.h>
+ #include <regex.h>],[ int i;
+ regex_t r;
+ int cflags = REG_EXTENDED;
+ const char *s = "abc";
+ i = regcomp(&r,s,cflags);
+ regfree(&r);
+ ]; ,
+ AC_DEFINE(HAVE_REGEX,1,
+ [Define 1 if regex seems to be defined]))
+
+AC_ARG_ENABLE(nonstandardprintf,AC_HELP_STRING([--enable-nonstandardprintf],
+ [Use a special printf format for 64bit (default is NO)]),
+ [ AC_DEFINE([HAVE_NONSTANDARD_PRINTF_64_FORMAT],[1],
+ [Define 1 if need nonstandard printf format for 64bit] )],
+ [])
+
+AC_TRY_COMPILE([
+#include <libelf.h>
+],[ int p; p = 0; ] ,
+ AC_DEFINE(HAVE_RAW_LIBELF_OK,1,
+ [Define 1 if plain libelf builds.]))
+AC_TRY_COMPILE([
+#define _GNU_SOURCE
+#include <libelf.h>
+],[ off64_t p; p = 0;] ,
+ AC_DEFINE(HAVE_LIBELF_OFF64_OK,1,
+ [Define 1 if off64 is defined via libelf with GNU_SOURCE.]))
+
+
+
+AC_OUTPUT(Makefile)
diff --git a/dwarfdump2/dieholder.h b/dwarfdump2/dieholder.h
new file mode 100644
index 0000000..9f6a77a
--- /dev/null
+++ b/dwarfdump2/dieholder.h
@@ -0,0 +1,80 @@
+/*
+ Copyright (C) 2009-2011 David Anderson All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+*/
+
+#ifndef DIEHOLDER_H
+#define DIEHOLDER_H
+// Reference counting eliminates confusion and bugs
+// when deciding when to do dealloc.
+class DieHolder {
+public:
+ DieHolder():dbg_(0),die_(0),refcount_(new int(1)),die_printed_(false) { };
+ DieHolder(Dwarf_Debug dbg, Dwarf_Die die):
+ dbg_(dbg),die_(die),refcount_(new int(1)),die_printed_(false) { };
+ ~DieHolder() {
+ (*refcount_)--;
+ if( (*refcount_) == 0) {
+ delete refcount_;
+ if(die_) dwarf_dealloc(dbg_,die_,DW_DLA_DIE);
+ }
+ };
+ DieHolder(const DieHolder & d):dbg_(d.dbg_),die_(d.die_),
+ refcount_(d.refcount_),die_printed_(d.die_printed_) {
+ (*refcount_)++;
+ };
+ DieHolder & operator=(const DieHolder & d) {
+ if(this != &d) {
+ (*d.refcount_)++;
+ (*refcount_)--;
+ if( (*refcount_) == 0) {
+ delete refcount_;
+ if(die_) dwarf_dealloc(dbg_,die_,DW_DLA_DIE);
+ }
+ refcount_ = d.refcount_;
+ die_ = d.die_;
+ dbg_ = d.dbg_;
+ die_printed_ = d.die_printed_;
+ }
+ return *this;
+ };
+ Dwarf_Die die() { return die_; };
+ Dwarf_Debug dbg() { return dbg_; };
+ bool die_printed() { return die_printed_; };
+ void mark_die_printed() { die_printed_ = true; };
+private:
+ Dwarf_Debug dbg_;
+ Dwarf_Die die_;
+ int *refcount_;
+ bool die_printed_;
+};
+#endif // DIEHOLDER_H
diff --git a/dwarfdump2/dwarfdump.1 b/dwarfdump2/dwarfdump.1
new file mode 100644
index 0000000..bb7ee37
--- /dev/null
+++ b/dwarfdump2/dwarfdump.1
@@ -0,0 +1,523 @@
+.TH DWARFDUMP
+.SH NAME
+dwarfdump \- dumps DWARF debug information of an ELF object
+.SH SYNOPSIS
+.B dwarfdump [options] \f2objectfilename\fP
+.SH DESCRIPTION
+The
+.B dwarfdump
+command prints or checks DWARF sections as requested by specific options.
+With no options (but with the required \f2objectfilename\fP )
+all sections print (but some sections cannot be printed independently
+safely, so those are only printed at offsets where the .debug_info section
+refers to those sections).
+.PP
+As of June 2011 the printing options and the checking options
+are mutually exclusive (if checking options are selected
+the section details are not printed). When errors are encountered
+dwarfdump does attempt to print sufficient context so that
+one can understand exactly where the error is in the DWARF.
+This change makes checking really large object files
+much easier.
+.PP
+The format is intended to be human readable.
+If a script is to parse the output, the
+.B \-d
+option is useful.
+.PP
+Not all sections actually exist in any given object file.
+.PP
+The format may change from release to release, so it is
+unwise to depend too heavily on the format.
+.PP
+Frame information (.debug_frame and .eh_frame) is heavily
+dependent on the ABI/ISA of the object file.
+By default we use a generic set of register names
+handling up to 100 registers named r0-100.
+The '-R' option uses a built-in generic register name set
+handling up to 1200 registers named r0-r1199.
+The '-x abi=<abi>'
+description below shows how to name an abi and use that to guide
+the -f or -F processing.
+Unless the cpu for the object file being dumped has many registers,
+do not use -R or -x abi=generic as those can be needlessly
+slow dumping frame sections. Instead, use the correct
+abi (if it exists in dwarfdump.conf) or a generic such
+as -x abi=generic100 or -x abi=generic500.
+To get MIPS/IRIX register names names and call the old version 2 libdwarf
+frame interface use the option '-x abi=mips'.
+Without '-R' or '-x abi=<abi>' dwarfdump ignores
+the dwarfdump.conf file and uses compiled-in generic set of
+register names.
+If no '-x name=<path>' is given, dwarfdump
+looks for "./dwarfdump.conf", "$HOME/.dwarfdump.conf", "<install-prefix>/lib/dwarfdump.conf" and takes the first it finds.
+If one or more '-x name=<path>' is given the last of these is
+used and all other such files are ignored.
+.PP
+Some -k (checking) options print so-called harmless errors.
+These are compiler errors that do not cause any
+known problem and are only detected inside libdwarf itself.
+These are difficult to properly report in dwarfdump and
+any error strings may not appear close to the time the
+error was encountered.
+.SH URI STYLE INPUT STRINGS
+.PP
+The <objectfilename> and the options taking name strings look for URIs and
+translate the URI strings to characters by default
+(see -x, -c<compiler name>, -S, -u).
+So any single % character is treated as if the following two
+characters are hex digits representing the underlying true character.
+Various characters are meaningful to shells (such as bash or sh)
+and to getopt (such as the space character)
+If the URI translation does anything it prints the before and after
+of the URI translation on standard output, so inspection of the first
+lines of output will show if URI did anything.
+The actual options themselves are assumed to be non-URI.
+So in the option '-cS&T' the -c portion must be non-URI, but the
+& character might cause input issues so '-cS%26T' could be used instead.
+To actually input a single % character (in a name, for example),
+double it to %% on the command line.
+.PP
+Options -U (turning off URI interpretation) and -q (making finding
+URI sequences silent) give finer control of URI interpretation.
+PP
+As an example, to get a string'a b' make the string 'a%20b'
+(here the quote (') is for exposition not part of the string, though
+quote is certainly problematic in a name).
+Instead of escaping " quotes in the string, type %25, as in
+ 'a "b' should be typed 'a%20%25b'
+Any characters can be typed in URI style, not just characters
+which are problematic to the shell or getopt.
+We strongly suggest you not type URI-style characters where
+such are not needed or use
+the % character itself in command line strings unless you must.
+.SH PRINTING OPTIONS
+.TP
+.B \-a
+Print each section as independently as possible. Sections that
+can safely be printed independently (like .debug_abbrev)
+have relevant info printed in the report (sometimes dependent
+on -v).
+
+.TP
+.B \-b
+Print the .debug_abbrev section. Because the DWARF specfications
+do not rule out garbage data areas in .debug_abbrev (if they are not
+referenced from .debug_info) any garbage bytes can result in
+this print failing.
+
+.TP
+.B \-c
+Print locations lists.
+
+.TP
+.B \-f
+Print the .debug_frame section.
+.TP
+.B \-F
+Print the .eh_frame section.
+
+.TP
+.B \-i
+Print the .debug_info section.
+
+.TP
+.B \-l
+Print the .debug_info section and the associated line section data.
+
+.TP
+.B \-m
+Print the .debug_macinfo section.
+
+.TP
+.B \-N
+Print .debug_ranges section. Because the DWARF specfications
+do not rule out garbage data areas in .debug_ranges (if they are not
+referenced from .debug_info) any garbage bytes can result in
+this print failing.
+
+.TP
+.B \-p
+Print the .debug_pubnames section.
+
+.TP
+.B \-r
+Print the .debug_aranges section.
+.TP
+.B \-s
+Print .debug_string section.
+
+.TP
+.B \-ta
+Print the IRIX only sections .debug_static_funcs and .debug_static_vars.
+
+.TP
+.B \-tf
+Print the IRIX only section .debug_static_funcs.
+.TP
+.B \-tv
+Print the IRIX only section .debug_static_vars.
+
+.TP
+.B \-w
+Print the IRIX-only .debug_weaknames section.
+
+.TP
+.B \-y
+Print the .debug_pubtypes section (and .debug_typenames,
+an SGI IRIX-only section).
+
+.PP
+Having dwarfdump print relocations may help establish whether
+dwarfdump understands any relocations that might exist.
+
+.TP
+.B \-o
+Print all relocation records as well as we can manage.
+.TP
+.B \-oi
+Print .rel*debug_info relocations.
+.TP
+.B \-ol
+Print .rel*debug_line relocation.
+.TP
+.B \-op
+Print .rel*debug_pubnames relocation.
+.TP
+.B \-oa
+Has no effect.
+.TP
+.B \-or
+Print .rel*debug_aranges relocations.
+.TP
+.B \-of
+Print .rel*debug_frame relocations.
+.TP
+.B \-oo
+Print .rel*debug_loc relocations.
+.TP
+.B \-oR
+Print .rel*debug_ranges relocations.
+
+.TP
+.B \-g
+Normally used only for testing libdwarf, this tells dwarfdump to
+print .debug_info and use an older dwarf_loclist() interface
+function (a function that cannot handle all current
+location lists).
+.TP
+.B \-V
+Print a dwarfdump date/version string and stop.
+
+.SH CHECKING OPTIONS
+.TP
+.B \-cg
+Restricts checking to compilers whose
+producer string starts with 'GNU'
+and turns off -cs .
+
+.TP
+.B \-cs
+Restricts checking to compilers whose
+producer string starts with 'SN'
+and turns off -cg .
+.TP
+.B \-cname
+Restricts checking to compilers whose
+producer string contains 'name' (not case sensitive).
+The 'name' is read as a URI string.
+
+.TP
+.B \
+-ka : Turns on all checking options except -kxe (-kxe might
+ be slow enough one mignt not want to use it routinely.)
+
+.TP
+.B \
+-kb : Checks for certain abbreviations section errors when reading
+ DIEs.
+.TP
+.B \-kc
+Checks for errors in constants in debug_info.
+.TP
+.B \-kd
+Turns on full reporting of error totals per producer.
+(the default shows less detail).
+.TP
+.B \-ke
+Turns on reading pubnames and checking for fde errors.
+.TP
+.B \-kf
+Turns on checking for FDE errors.
+.TP
+.B \-kF
+Turns on checking for line table errors.
+.TP
+.B \-kg
+Turns on checking for unused gaps in .debug_info (these
+gaps are not an error, just a waste of space).
+
+.TP
+.B \-ki
+Causes a summary of checking results per compiler (producer)
+to be printed at the end.
+.TP
+.B \-kl
+Turns on locations list checking.
+.TP
+.B \-km
+Turns on checking of ranges.
+.TP
+.B \-kM
+Turns on checking of aranges.
+.TP
+.B \-kr
+Turns on DIE tag-attr combinations checking.
+.TP
+.B \-kR
+Turns on reading DIEs and checking for forward declarations
+rom DW_AT_specification attributes.
+(which are not an error but can be a source of inefficiency
+for debuggers).
+.TP
+.B \-ks
+Turns on extra reporting for some DIE errors checking detects .
+.TP
+.B \-kS
+Turns on checking DIE references for circular references.
+.TP
+.B \-kt
+Turns on tag-tag combinations checking.
+.TP
+.B \-kx
+Turns on check_frames.
+.TP
+.B \-kxe
+Turns off basic check_frames and turns on extended frame checking.
+.TP
+.B \-ky
+Turns on type_offset, decl_file checking,
+
+.SH OPTION MODIFIERS
+
+.TP
+.B \-C
+Normally when checking for tag-tag or tag-attribute combinations
+both the standard combinations and some common extensions are allowed.
+With -C the extensions are taken out of the allowed class of combinations.
+
+.TP
+.B \-d
+When printing DIEs, put all the attributes for each DIE on the same (long)
+line as the TAG. This makes searching for DIE information
+(as with grep) much simpler as the entire DIE is on one line.
+
+.TP
+.B \-D
+Turns off the display of section offsets and attribute values in printed output.
+So the .debug_info output isjust TAGs and Attributes.
+For pubnames (and the like) it removes offsets from the output.
+For locations lists it removes offsets from the output, but that
+is useless since the attribute values don't show so neither does
+the location data.
+
+.TP
+.B \-e
+Turns on truncation of attribute and tag names. For example
+DW_TAG_foo becomes foo . Not compatible with
+checking, only useful for printing DIEs.
+
+.TP
+.B \-G
+When printing, add global offsets to the offsets printed.
+
+.TP
+.B \-H number
+When printing or checking .debug_info, this terminates
+the search after 'number' compilation units. When printing
+frame information this terminates the FDE reporting
+after 'number' FDEs and the CIE reporting (which occurs if one adds -v)
+after 'number' CIEs. Example '-H 1'
+
+.TP
+.B \-M
+When printing, this means one want to have the FORM show for each attribute.
+If a -v is also added (or more than one) then details of any form indirection
+are also shown.
+
+.TP
+.B \-n
+When printing frames, this turns off the search for function names.
+In a really large object the search can take more time than
+one wants to wait, so this avoids the search.
+
+.TP
+.B \-Q
+Suppresses section data printing (set automatically with a checking option).
+
+.TP
+.B \-R
+When printing frames for ABIs with lots of registers, this allows
+up to 1200 registers to be named (like R999) without choosing an ABI
+with, for example '-x abi=ppc'
+
+.TP
+.B \-v
+Increases the detail shown when printing.
+In some sections, using more -v options
+will increase the detail (one to three are useful) or may
+change the report to show, for example, the actual
+line-data-commands instead of the resultant line-table.
+
+.SH SELECTIVE ENTRY PRINTING
+
+.PP
+These -S options stand alone and basic print information about the compilation
+unit and DIE where the string(s) appear.
+At most one of each of the following is effective (so for example
+one can only have one 'match', but one can
+have a 'match', an 'any', and a 'regex').
+Any -S causes the .debug_info section to be inspected.
+No checking options or printing options should be supplied with -S.
+
+.TP
+.B \-S match=string
+When printing DIEs
+for each tag value or attribute name that matches 'string' exactly
+print the compilation unit information and its section offset.
+Any CU with no match is not printed.
+The 'string' is read as a URI string.
+.TP
+.B \-S any=string
+When printing DIEs
+for each tag value or attribute name that contains 'string'
+somewhere in the tag or attribute (case insensitive)
+print the compilation unit information and its section offset.
+Any CU with no match is not printed.
+The 'string' is read as a URI string.
+.TP
+.B \-S regex=string
+When printing DIEs
+for each tag value or attribute name where the 'string' reqular
+expression matches print the compilation unit information
+and its section offset.
+Any CU with no match is not printed.
+The 'string' is read as a URI string.
+
+.PP
+The string cannot have spaces or other characters which are
+meaningful to getopt(3) and the shell will strip off quotes and
+other characters.
+So the string is assumed to be in URI style and is translated.
+In other words, to match 'a b' make the -S string 'a%20b'
+Instead of escaping " quotes in the string, type %25, as in
+ 'a "b' should be typed 'a%20%25b'
+(the ' are for exposition here, not part of the strings).
+Any characters can be typed in URI style, not just characters
+which are problematic to the shell or getopt.
+.PP
+The -S any= and -S regex= options are only usable
+if the library functions required are found at configure time.
+.PP
+The -W option is a modifier to the -S option, and
+increases the amount of output -W prints.
+Now we show the -W in context with a -S option.
+
+.TP
+.B \-S match=string1 -W
+Prints the parent tree and the children tree for the
+DIEs that -S matches.
+
+.TP
+.B \-S match=string2 -Wp
+Prints the parent tree for the DIEs that -S matches.
+
+.TP
+.B \-S match=string3 -Wc
+Prints the parent tree for the DIEs that -S matches.
+
+.SH OTHER OPTIONS
+
+.TP
+.B \-# number
+This option controls internal debugging output,
+higher numbers mean more debug actions. See the source code.
+
+
+.TP
+.B \-x name=/p/a/t/h.conf
+The file path given is the name of a file assumed to be
+a dwarfdump.conf-like file.
+The file path is read as a URI string.
+
+.TP
+.B \-x abi=ppc
+Selects the abi (from a dwarfdump.conf file) to be used in
+printing frame information (here using ppc as an example).
+The abi is read as a URI string.
+
+.TP
+.B \-P
+When checking this adds the list of compilation-unit names
+seen for each producer-compiler to the printed checking results.
+.TP
+.B \-q
+When a URI is found and translated while reading
+the command line, be quiet about
+the URI translation. That is, don't print the
+original and translated option strings.
+
+.TP
+.B \-E
+Turns on printing object-internal header data for some
+systems (for Unix/Linux does nothing).
+
+.TP
+.B \-u cuname
+Turns on selective printing of DIEs (printing like -i).
+Only the DIEs for a compilation unit that match the
+name provided are printed.
+If the compilation unit is ./a/b/c.c
+the 'cuname' you provide should be c.c as the characters
+through the final path-separating / are ignored.
+If 'cuname' begins with a / then the entire name string
+of a compilation unit must match 'cuname'.
+The 'cuname' is read as a URI string.
+
+.TP
+.B \-U
+Turn off the URI interpretation of the command line
+strings entirely. Must be be on the command line before
+any URI strings encountered to be fully effective.
+
+.TP
+.B \-z
+No longer suported.
+
+
+.SH FILES
+dwarfdump
+
+dwarfdump.conf
+
+./dwarfdump.conf
+
+$(HOME)/.dwarfdump.conf
+
+$(HOME)/dwarfdump.conf
+
+<install-prefix>/lib/dwarfdump.conf
+.SH NOTES
+In some cases compilers use DW_FORM_data1 (for example)
+and in such cases the signedness of the value must be taken
+from context. Rather than attempt to determine the
+context, dwarfdump prints the value with both signednesses
+whenever there is ambiguity about the correct interpretation.
+For example,
+"DW_AT_const_value 176(as signed = -80)".
+For normal DWARF consumers that correctly and fully
+evaluate all attributes there is no ambiguity of signedness:
+the ambiguity for dwarfdump is due to dwarfdump evaluating
+DIEs in a simple order and not keeping track of much context.
+.SH BUGS
+Support for DWARF3 is being completed but may not be complete.
diff --git a/dwarfdump2/dwarfdump.cc b/dwarfdump2/dwarfdump.cc
new file mode 100644
index 0000000..cbec341
--- /dev/null
+++ b/dwarfdump2/dwarfdump.cc
@@ -0,0 +1,2258 @@
+/*
+ Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/dwarfdump.c,v 1.48 2006/04/18 18:05:57 davea Exp $ */
+
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+
+
+#include "globals.h"
+#include <vector>
+#include <algorithm> // for sort
+#include <iomanip>
+
+/* for 'open' */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h> /* For getopt. */
+#include "dwconf.h"
+#include "common.h"
+#include "naming.h"
+#include "uri.h"
+#define DWARFDUMP_VERSION " Tue Apr 10 11:43:32 PDT 2012 "
+
+using std::string;
+using std::cout;
+using std::cerr;
+using std::endl;
+
+#define OKAY 0
+#define BYTES_PER_INSTRUCTION 4
+
+extern char *optarg;
+static string process_args(int argc, char *argv[]);
+static void increment_compilers_detected(bool beyond);
+static void increment_compilers_targeted(bool beyond);
+
+static const char *usage_text[] = {
+"options:\t-a\tprint all .debug_* sections",
+"\t\t-b\tprint abbrev section",
+"\t\t-c\tprint loc section",
+"\t\t-c<str>\tcheck only specific compiler objects",
+"\t\t \t <str> is described by 'DW_AT_producer'. Examples:",
+"\t\t \t -cg check only GCC compiler objects",
+"\t\t \t -cs check only SNC compiler objects",
+"\t\t \t -c'350.1' check only compiler objects with 350.1 in the CU name",
+"\t\t-C\tactivate printing (with -i) of warnings about",
+"\t\t\tcertain common extensions of DWARF.",
+"\t\t-d\tdense: one line per entry (info section only)",
+"\t\t-D\tdo not show offsets", /* Do not show any offsets */
+"\t\t-e\tellipsis: short names for tags, attrs etc.",
+"\t\t-E\tprint object Header information",
+"\t\t-f\tprint dwarf frame section",
+"\t\t-F\tprint gnu .eh_frame section",
+"\t\t-g\t(use incomplete loclist support)",
+"\t\t-G\tshow global die offsets",
+"\t\t-h\tprint IRIX exception tables (unsupported)",
+"\t\t-H <num>\tlimit output to the first <num> major units",
+"\t\t\t example: to stop after <num> compilation units",
+"\t\t-i\tprint info section",
+"\t\t-k[abcdeEfFgilmMnrRsStx[e]y] check dwarf information",
+"\t\t a\tdo all checks",
+"\t\t b\tcheck abbreviations", /* Check abbreviations */
+"\t\t c\texamine DWARF constants", /* Check for valid DWARF constants */
+"\t\t d\tshow check results", /* Show check results */
+"\t\t e\texamine attributes of pubnames",
+"\t\t E\tignore DWARF extensions", /* Ignore DWARF extensions */
+"\t\t f\texamine frame information (use with -f or -F)",
+"\t\t F\texamine integrity of files-lines attributes", /* Files-Lines integrity */
+"\t\t g\tcheck debug info gaps", /* Check for debug info gaps */
+"\t\t i\tdisplay summary for all compilers", /* Summary all compilers */
+"\t\t l\tcheck location list (.debug_loc)", /* Location list integrity */
+"\t\t m\tcheck ranges list (.debug_ranges)", /* Ranges list integrity */
+"\t\t M\tcheck ranges list (.debug_aranges)",/* Aranges list integrity */
+"\t\t n\texamine names in attributes", /* Check for valid names */
+"\t\t r\texamine tag-attr relation",
+"\t\t R\tcheck forward references to DIEs (declarations)", /* Check DW_AT_specification references */
+"\t\t s\tperform checks in silent mode",
+"\t\t S\tcheck self references to DIEs",
+"\t\t t\texamine tag-tag relations",
+"\t\t x\tbasic frames check (.eh_frame, .debug_frame)",
+"\t\t xe\textensive frames check (.eh_frame, .debug_frame)",
+"\t\t y\texamine type info",
+"\t\t\tUnless -C option given certain common tag-attr and tag-tag",
+"\t\t\textensions are assumed to be ok (not reported).",
+"\t\t-l\tprint line section",
+"\t\t-m\tprint macinfo section",
+"\t\t-M\tprint the form name for each attribute",
+"\t\t-n\tsuppress frame information function name lookup",
+"\t\t \t(when printing frame information from multi-gigabyte",
+"\t\t \tobject files this option may save significant time).",
+"\t\t-N\tprint ranges section",
+"\t\t-o[liaprfoR]\tprint relocation info",
+"\t\t \tl=line,i=info,a=abbrev,p=pubnames,r=aranges,f=frames,o=loc,R=Ranges",
+"\t\t-p\tprint pubnames section",
+"\t\t-P\tprint list of compile units per producer", /* List of CUs per compiler */
+"\t\t-Q\tsuppress printing section data",
+"\t\t-r\tprint aranges section",
+"\t\t-R\tPrint frame register names as r33 etc",
+"\t\t \t and allow up to 1200 registers.",
+"\t\t \t Print using a 'generic' register set.",
+"\t\t-s\tprint string section",
+"\t\t-S <option>=<text>\tsearch for <text> in attributes",
+"\t\t \twith <option>:",
+"\t\t \t-S any=<text>\tany <text>",
+"\t\t \t-S match=<text>\tmatching <text>",
+#ifdef HAVE_REGEX
+"\t\t \t-S regex=<text>\tuse regular expression matching",
+#endif
+"\t\t \t (only one -S option allowed, any= and regex= ",
+"\t\t \t only usable if the functions required are ",
+"\t\t \t found at configure time)",
+"\t\t-t[afv] static: ",
+"\t\t a\tprint both sections",
+"\t\t f\tprint static func section",
+"\t\t v\tprint static var section",
+"\t\t-u<file> print sections only for specified file",
+"\t\t-v\tverbose: show more information",
+"\t\t-vv verbose: show even more information",
+"\t\t-V print version information",
+"\t\t-x name=<path>\tname dwarfdump.conf",
+"\t\t-x abi=<abi>\tname abi in dwarfdump.conf",
+"\t\t-w\tprint weakname section",
+"\t\t-W\tprint parent and children tree (wide format) with the -S option",
+"\t\t-Wp\tprint parent tree (wide format) with the -S option",
+"\t\t-Wc\tprint children tree (wide format) with the -S option",
+"\t\t-y\tprint type section",
+"",
+
+0};
+
+
+
+std::string program_name;
+int check_error = 0;
+LinkOnceData *pLinkOnceData;
+AddressRangesData *pAddressRangesData;
+VisitedOffsetData *pVisitedOffsetData;
+
+/* Options to enable debug tracing */
+int nTrace[MAX_TRACE_LEVEL + 1];
+
+/* Build section information */
+void build_linkonce_info(Dwarf_Debug dbg);
+static string do_uri_translation(const string &s, const std::string &context);
+static void reset_overall_CU_error_data();
+
+bool info_flag = false;
+
+/* This so both dwarf_loclist()
+ and dwarf_loclist_n() can be
+ tested. Defaults to new
+ dwarf_loclist_n() */
+bool use_old_dwarf_loclist = false;
+
+bool line_flag = false;
+static bool abbrev_flag = false;
+static bool frame_flag = false; /* .debug_frame section. */
+static bool eh_frame_flag = false; /* GNU .eh_frame section. */
+static bool pubnames_flag = false;
+static bool macinfo_flag = false;
+static bool loc_flag = false;
+static bool aranges_flag = false;
+static bool ranges_flag = false; /* .debug_ranges section. */
+static bool string_flag = false;
+static bool reloc_flag = false;
+static bool static_func_flag = false;
+static bool static_var_flag = false;
+static bool type_flag = false;
+static bool weakname_flag = false;
+static bool header_flag = false; /* Control printing of Elf header. */
+bool producer_children_flag = false; /* List of CUs per compiler */
+
+// Bitmap for relocations. See globals.h for DW_SECTION_REL_DEBUG_RANGES etc.
+static unsigned reloc_map = 0;
+
+// Start verbose at zero. verbose can
+// be incremented with -v but not decremented.
+int verbose = 0;
+bool dense = false;
+bool ellipsis = false;
+bool show_global_offsets = false;
+bool show_form_used = false;
+bool display_offsets = true; /* Emit offsets */
+
+bool check_abbrev_code = false;
+bool check_pubname_attr = false;
+bool check_reloc_offset = false;
+bool check_attr_tag = false;
+bool check_tag_tree = false;
+bool check_type_offset = false;
+bool check_decl_file = false;
+bool check_lines = false;
+bool check_fdes = false;
+bool check_ranges = false;
+bool check_aranges = false;
+bool check_harmless = false;
+bool check_abbreviations = false;
+bool check_dwarf_constants = false;
+bool check_di_gaps = false;
+bool check_forward_decl = false;
+bool check_self_references = false;
+bool generic_1200_regs = false;
+bool suppress_check_extensions_tables = false;
+// suppress_nested_name_search is a band-aid.
+// A workaround. A real fix for N**2 behavior is needed.
+bool suppress_nested_name_search = false;
+static bool uri_options_translation = true;
+static bool do_print_uri_in_input = true;
+
+/* break_after_n_units is mainly for testing.
+ It enables easy limiting of output size/running time
+ when one wants the output limited.
+ For example,
+ -H 2
+ limits the -i output to 2 compilation units and
+ the -f or -F output to 2 FDEs and 2 CIEs. */
+int break_after_n_units = INT_MAX;
+
+bool check_names = false;
+bool check_verbose_mode = true; /* During '-k' mode, display errors */
+bool check_frames = false;
+bool check_frames_extended = false; /* Extensive frames check */
+bool check_locations = false; /* Location list check */
+
+static bool check_all_compilers = true;
+static bool check_snc_compiler = false; /* Check SNC compiler */
+static bool check_gcc_compiler = false;
+static bool print_summary_all = false;
+
+
+/* Records information about compilers (producers) found in the
+ debug information, including the check results for several
+ categories (see -k option). */
+struct Compiler {
+ Compiler():verified_(false) { results_.resize((int)LAST_CATEGORY); };
+ ~Compiler() {};
+ std::string name_;
+ bool verified_;
+ std::vector<std::string> cu_list_;
+ std::vector<Dwarf_Check_Result> results_;
+};
+
+/* Record compilers whose CU names have been seen.
+ Full CU names recorded here, though only a portion
+ of the name may have been checked to cause the
+ compiler data to be entered here.
+*/
+
+static std::vector<Compiler> compilers_detected;
+
+/* compilers_targeted is a list of indications of compilers
+ on which we wish error checking (and the counts
+ of checks made and errors found). We do substring
+ comparisons, so the compilers_targeted name might be simply a
+ compiler version number or a short substring of a
+ CU producer name.
+*/
+static std::vector<Compiler> compilers_targeted;
+static int current_compiler = 0;
+
+static void PRINT_CHECK_RESULT(const std::string &str,
+ Compiler *pCompiler, Dwarf_Check_Categories category);
+
+
+/* The check and print flags here make it easy to
+ allow check-only or print-only. We no longer support
+ check-and-print in a single run. */
+bool do_check_dwarf = false;
+bool do_print_dwarf = false;
+bool check_show_results = false; /* Display checks results. */
+bool record_dwarf_error = false; /* A test has failed, this
+ is normally set false shortly after being set TRUE, it is
+ a short-range hint we should print something we might not
+ otherwise print (under the circumstances). */
+struct Error_Message_Data error_message_data;
+
+bool display_parent_tree = false;
+bool display_children_tree = false;
+int stop_indent_level = 0;
+
+/* Print search results in wide format? */
+bool search_wide_format = false;
+
+
+
+
+
+
+
+
+
+
+bool search_is_on;
+std::string search_any_text;
+std::string search_match_text;
+std::string search_regex_text;
+#ifdef HAVE_REGEX
+regex_t search_re;
+#endif
+
+
+/* These configure items are for the
+ frame data. */
+static string config_file_path;
+static string config_file_abi;
+static const char * config_file_defaults[] = {
+ "dwarfdump.conf",
+ "./dwarfdump.conf",
+ /* Note: HOME location uses .dwarfdump.conf or dwarfdump.conf . */
+ "HOME/.dwarfdump.conf",
+ "HOME/dwarfdump.conf",
+#ifdef CONFPREFIX
+/* See Makefile.in "libdir" and CFLAGS */
+/* We need 2 levels of macro to get the name turned into
+ the string we want. */
+#define STR2(s) # s
+#define STR(s) STR2(s)
+ STR(CONFPREFIX)
+ "/dwarfdump.conf",
+#else
+ "/usr/lib/dwarfdump.conf",
+#endif
+ 0
+};
+static struct dwconf_s config_file_data;
+
+string cu_name;
+bool cu_name_flag = false;
+Dwarf_Unsigned cu_offset = 0;
+
+Dwarf_Error err;
+
+static void suppress_check_dwarf()
+{
+ do_print_dwarf = true;
+ if(do_check_dwarf) {
+ cerr <<"Warning: check flag turned off, "
+ "checking and printing are separate." <<
+ endl;
+ }
+ do_check_dwarf = false;
+}
+static void suppress_print_dwarf()
+{
+ do_print_dwarf = false;
+ do_check_dwarf = true;
+}
+
+
+static int process_one_file(Elf * elf, const string &file_name, int archive,
+ struct dwconf_s *conf);
+static int
+open_a_file(const string &name)
+{
+ int f = 0;
+
+#ifdef __CYGWIN__
+ f = open(name.c_str(), O_RDONLY | O_BINARY);
+#else
+ f = open(name.c_str(), O_RDONLY);
+#endif
+ return f;
+
+}
+
+/* Iterate through dwarf and print all info. */
+int
+main(int argc, char *argv[])
+{
+ int archive = 0;
+
+ print_version_details(argv[0],false);
+
+ // Ensure we have the zero entry of the vectors in
+ // these three data structures.
+ pAddressRangesData = new AddressRangesData;
+ pLinkOnceData = new LinkOnceData;
+ pVisitedOffsetData = new VisitedOffsetData;
+
+ increment_compilers_detected(false);
+ increment_compilers_targeted(false);
+ (void) elf_version(EV_NONE);
+ if (elf_version(EV_CURRENT) == EV_NONE) {
+ cerr << "dwarfdump: libelf.a out of date." << endl;
+ exit(1);
+ }
+ /* Because LibDwarf now generates some new warnings,
+ allow the user to hide them by using command line options */
+ {
+ Dwarf_Cmdline_Options cmd;
+ cmd.check_verbose_mode = check_verbose_mode;
+ dwarf_record_cmdline_options(cmd);
+ }
+
+ print_args(argc,argv);
+ string file_name = process_args(argc, argv);
+ int f = open_a_file(file_name);
+ if (f == -1) {
+ cerr << program_name << " ERROR: can't open " <<
+ file_name << endl;
+ return (FAILED);
+ }
+
+ Elf_Cmd cmd = ELF_C_READ;
+ Elf *arf = elf_begin(f, cmd, (Elf *) 0);
+ if (elf_kind(arf) == ELF_K_AR) {
+ archive = 1;
+ }
+ Elf *elf = 0;
+ while ((elf = elf_begin(f, cmd, arf)) != 0) {
+ Elf32_Ehdr *eh32;
+
+#ifdef HAVE_ELF64_GETEHDR
+ Elf64_Ehdr *eh64;
+#endif /* HAVE_ELF64_GETEHDR */
+ eh32 = elf32_getehdr(elf);
+ if (!eh32) {
+#ifdef HAVE_ELF64_GETEHDR
+ /* not a 32-bit obj */
+ eh64 = elf64_getehdr(elf);
+ if (!eh64) {
+ /* not a 64-bit obj either! */
+ /* dwarfdump is quiet when not an object */
+ } else {
+ process_one_file(elf, file_name, archive,
+ &config_file_data);
+ }
+#endif /* HAVE_ELF64_GETEHDR */
+ } else {
+ process_one_file(elf, file_name, archive,
+ &config_file_data);
+ }
+ cmd = elf_next(elf);
+ elf_end(elf);
+ }
+ elf_end(arf);
+ /* Trivial malloc space cleanup. */
+ clean_up_syms_malloc_data();
+ delete pAddressRangesData;
+ delete pLinkOnceData;
+ delete pVisitedOffsetData;
+#ifdef HAVE_REGEX
+ if(!search_regex_text.empty()) {
+ regfree(&search_re);
+ }
+#endif
+
+
+ if (check_error)
+ return FAILED;
+ else
+ return OKAY;
+}
+
+void
+print_any_harmless_errors(Dwarf_Debug dbg)
+{
+#define LOCAL_PTR_ARY_COUNT 50
+ /* We do not need to initialize the local array,
+ libdwarf does it. */
+ const char *buf[LOCAL_PTR_ARY_COUNT];
+ unsigned totalcount = 0;
+ unsigned i = 0;
+ unsigned printcount = 0;
+ int res = dwarf_get_harmless_error_list(dbg,LOCAL_PTR_ARY_COUNT,buf,
+ &totalcount);
+ if(res == DW_DLV_NO_ENTRY) {
+ return;
+ }
+ if(totalcount > 0) {
+ cout << endl;
+ cout << "*** HARMLESS ERROR COUNT: " << IToDec(totalcount) <<
+ " ***" << endl;
+ }
+ for(i = 0 ; buf[i]; ++i) {
+ ++printcount;
+ DWARF_CHECK_COUNT(harmless_result,1);
+ DWARF_CHECK_ERROR(harmless_result,buf[i]);
+ }
+ if(totalcount > printcount) {
+ DWARF_CHECK_COUNT(harmless_result,(totalcount - printcount));
+ DWARF_ERROR_COUNT(harmless_result,(totalcount - printcount));
+ }
+}
+
+static void
+print_object_header(Elf *elf,Dwarf_Debug dbg)
+{
+#ifdef WIN32
+ /* Standard libelf has no function generating the names of the
+ encodings, but this libelf apparently does. */
+ Elf_Ehdr_Literal eh_literals;
+ Elf32_Ehdr *eh32;
+#ifdef HAVE_ELF64_GETEHDR
+ Elf64_Ehdr *eh64;
+#endif /* HAVE_ELF64_GETEHDR */
+
+ eh32 = elf32_getehdr(elf);
+ if (eh32) {
+ /* Get literal strings for header fields */
+ elf32_gethdr_literals(eh32,&eh_literals);
+ /* Print 32-bit obj header */
+ cout << endl;
+ cout << "Object Header:" << endl;
+ cout << "e_ident:" << endl;
+ cout <<" File ID = " << eh_literals.e_ident_file_id <<endl;
+ cout <<" File class = " <<
+ IToHex0N(eh32->e_ident[EI_CLASS],4)<<
+ eh_literals.e_ident_file_class << endl;
+ cout <<" Data encoding = " <<
+ IToHex0N(eh32->e_ident[EI_DATA],4)<<
+ eh_literals.e_ident_data_encoding << endl;
+ cout <<" File version = "<<
+ IToHex0N(eh32->e_ident[EI_VERSION],4)<<
+ eh_literals.e_ident_file_version << endl;
+ cout <<" OS ABI = " <<
+ IToHex0N(eh32->e_ident[EI_VERSION],4)<<
+ " (" <<eh_literals.e_ident_os_abi_s <<
+ ") (" <<eh_literals.e_ident_os_abi_l <<
+ ")" <<endl;
+ //printf(" ABI version = %02x (%s)\n",
+ // eh32->e_ident[EI_ABIVERSION], eh_literals.e_ident_abi_version);
+ cout <<"e_type : " <<
+ << IToHex(eh32->e_type)<<
+ " ("<< eh_literals.e_type << ")" << endl;
+ cout <<"e_machine: " <<
+ << IToHex(eh32->e_machine)<<
+ " (" << eh_literals.e_machine_s <<
+ ") (" << eh_literals.e_machine_l << ")" << endl;
+ cout <<"e_version: " << IToHex(eh32->e_version) << endl;
+ //printf("e_entry = 0x%I64x\n", eh32->e_entry);
+ cout <<"e_flags : " << IToHex(eh32->e_version);
+ cout <<"e_flags : "<< IToHex(eh32->e_flags) << endl;
+ cout <<"e_phnum : "<<IToHex( eh32->e_phnum) << endl;
+ cout <<"e_shnum : " <<IToHex(eh32->e_shnum) << endl;
+ }
+ else {
+#ifdef HAVE_ELF64_GETEHDR
+ /* not a 32-bit obj */
+ eh64 = elf64_getehdr(elf);
+ if (eh64) {
+ /* Get literal strings for header fields */
+ elf64_gethdr_literals(eh64,&eh_literals);
+ /* Print 64-bit obj header */
+ cout << endl;
+ cout << "Object Header:" << endl;
+ cout << "e_ident:" << endl;
+ cout <<" File ID = " << eh_literals.e_ident_file_id <<endl;
+ cout <<" File class = " <<
+ IToHex0N(eh64->e_ident[EI_CLASS],4)<<
+ eh_literals.e_ident_file_class << endl;
+ cout <<" Data encoding = " <<
+ IToHex0N(eh64->e_ident[EI_DATA],4)<<
+ eh_literals.e_ident_data_encoding << endl;
+ cout <<" File version = "<<
+ IToHex0N(eh64->e_ident[EI_VERSION],4)<<
+ eh_literals.e_ident_file_version << endl;
+ cout <<" OS ABI = " <<
+ IToHex0N(eh64->e_ident[EI_VERSION],4)<<
+ " (" <<eh_literals.e_ident_os_abi_s <<
+ ") (" <<eh_literals.e_ident_os_abi_l <<
+ ")" <<endl;
+ //printf(" ABI version = %02x (%s)\n",
+ // eh64->e_ident[EI_ABIVERSION], eh_literals.e_ident_abi_version);
+ cout <<"e_type : " <<
+ << IToHex(eh64->e_type)<<
+ " ("<< eh_literals.e_type << ")" << endl;
+ cout <<"e_machine: " <<
+ << IToHex(eh64->e_machine)<<
+ " (" << eh_literals.e_machine_s <<
+ ") (" << eh_literals.e_machine_l << ")" << endl;
+ cout <<"e_version: " << IToHex(eh64->e_version) << endl;
+ //printf("e_entry = 0x%I64x\n", eh64->e_entry);
+ cout <<"e_flags : " << IToHex(eh64->e_version);
+ cout <<"e_flags : "<< IToHex(eh64->e_flags) << endl;
+ cout <<"e_phnum : "<<IToHex( eh64->e_phnum) << endl;
+ cout <<"e_shnum : " <<IToHex(eh64->e_shnum) << endl;
+ }
+#endif /* HAVE_ELF64_GETEHDR */
+ }
+#endif /* WIN32 */
+}
+
+
+/* Print checks and errors for a specific compiler */
+static void
+print_specific_checks_results(Compiler *pCompiler)
+{
+ cerr << endl;
+ cerr << "DWARF CHECK RESULT" << endl;
+ cerr << "<item> <checks> <errors>" << endl;
+ if (check_pubname_attr) {
+ PRINT_CHECK_RESULT("pubname_attr", pCompiler, pubname_attr_result);
+ }
+ if (check_attr_tag) {
+ PRINT_CHECK_RESULT("attr_tag", pCompiler, attr_tag_result);
+ }
+ if (check_tag_tree) {
+ PRINT_CHECK_RESULT("tag_tree", pCompiler, tag_tree_result);
+ }
+ if (check_type_offset) {
+ PRINT_CHECK_RESULT("type_offset", pCompiler, type_offset_result);
+ }
+ if (check_decl_file) {
+ PRINT_CHECK_RESULT("decl_file", pCompiler, decl_file_result);
+ }
+ if (check_ranges) {
+ PRINT_CHECK_RESULT("ranges", pCompiler, ranges_result);
+ }
+ if (check_lines) {
+ PRINT_CHECK_RESULT("line_table", pCompiler, lines_result);
+ }
+ if (check_fdes) {
+ PRINT_CHECK_RESULT("fde table", pCompiler, fde_duplication);
+ }
+ if (check_aranges) {
+ PRINT_CHECK_RESULT("aranges", pCompiler, aranges_result);
+ }
+
+ if (check_names) {
+ PRINT_CHECK_RESULT("names",pCompiler, names_result);
+ }
+ if (check_frames) {
+ PRINT_CHECK_RESULT("frames",pCompiler, frames_result);
+ }
+ if (check_locations) {
+ PRINT_CHECK_RESULT("locations",pCompiler, locations_result);
+ }
+
+ if(check_harmless) {
+ PRINT_CHECK_RESULT("harmless_errors", pCompiler, harmless_result);
+ }
+
+ if (check_abbreviations) {
+ PRINT_CHECK_RESULT("abbreviations", pCompiler, abbreviations_result);
+ }
+
+ if (check_dwarf_constants) {
+ PRINT_CHECK_RESULT("dwarf_constants",
+ pCompiler, dwarf_constants_result);
+ }
+
+ if (check_di_gaps) {
+ PRINT_CHECK_RESULT("debug_info_gaps", pCompiler, di_gaps_result);
+ }
+
+ if (check_forward_decl) {
+ PRINT_CHECK_RESULT("forward_declarations",
+ pCompiler, forward_decl_result);
+ }
+
+ if (check_self_references) {
+ PRINT_CHECK_RESULT("self_references",
+ pCompiler, self_references_result);
+ }
+
+ PRINT_CHECK_RESULT("** Summarize **",pCompiler, total_check_result);
+}
+
+// StrictWeakOrdering, like LessThanComparable.
+// But reversed... !!
+static bool
+sort_compare_compiler(const Compiler &cmp1,const Compiler &cmp2)
+{
+ int cnt1 = cmp1.results_[total_check_result].errors_;
+ int cnt2 = cmp2.results_[total_check_result].errors_;
+
+ if (cnt1 > cnt2) {
+ return true;
+ }
+ /* When error counts match, sort on name. */
+ if(cnt1 == cnt2) {
+ if (cmp1.name_ > cmp2.name_) {
+ return true;
+ }
+ }
+ return false;
+}
+/* Print a summary of checks and errors */
+static void
+print_checks_results()
+{
+
+ cerr.flush();
+ cout.flush();
+
+ if(compilers_detected.size() > 1) {
+ std::stable_sort(compilers_detected.begin()+ 1,
+ compilers_detected.end(),sort_compare_compiler);
+ }
+
+ /* Print list of CUs for each compiler detected */
+ if (producer_children_flag) {
+
+ unsigned count = 0;
+ unsigned total = 0;
+
+ cerr << endl;
+ cerr << "*** CU NAMES PER COMPILER ***"<< endl;
+ for (unsigned index = 1; index < compilers_detected.size(); ++index) {
+ const Compiler& c = compilers_detected[index];
+ cerr << endl;
+ cerr << IToDec0N(index,2) << ": " << c.name_;
+ cerr << endl;
+ count = 0;
+ for (unsigned nc = 0;
+ nc < c.cu_list_.size();
+ ++nc ) {
+
+ ++count;
+ cerr << endl;
+ cerr << " " << IToDec0N(count,2) <<": '" <<
+ c.cu_list_[nc]<< "'" ;
+ }
+ total += count;
+ cerr << endl;
+ }
+ cerr << endl;
+ cerr<< "Detected " << total << " CU names" << endl;
+ }
+
+ /* Print error report only if errors have been detected */
+ /* Print error report if the -kd option */
+ if ((do_check_dwarf && check_error) || check_show_results) {
+ int compilers_not_detected = 0;
+ int compilers_verified = 0;
+
+ /* Find out how many compilers have been verified. */
+ for (unsigned index = 1; index < compilers_detected.size(); ++index) {
+ if (compilers_detected[index].verified_) {
+ ++compilers_verified;
+ }
+ }
+ /* Find out how many compilers have been not detected. */
+ for (unsigned index = 1; index < compilers_targeted.size(); ++index) {
+ if (!compilers_targeted[index].verified_) {
+ ++compilers_not_detected;
+ }
+ }
+
+ /* Print compilers detected list */
+ cerr << endl;
+ cerr << compilers_detected.size() -1 << " Compilers detected:"
+ << endl;
+ for (unsigned index = 1; index < compilers_detected.size(); ++index) {
+ cerr << IToDec0N(index,2) << ": " <<
+ compilers_detected[index].name_<< endl;
+ }
+
+ /* Print compiler list specified by the user with the
+ '-c<str>', that were not detected. */
+ if (compilers_not_detected) {
+ unsigned count = 0;
+ cerr << endl;
+ cerr << compilers_not_detected << " Compilers not detected:"
+ << endl;
+ for (unsigned index = 1; index < compilers_targeted.size(); ++index) {
+ Compiler *pCompiler = &compilers_targeted[index];
+ if (!pCompiler->verified_) {
+ ++count;
+ cerr << IToDec0N(count,2) << ": '" <<
+ pCompiler->name_ << "'" << endl;
+ }
+ }
+ }
+
+ unsigned count2 = 0;
+ cerr << endl;
+ cerr << compilers_verified << " Compilers verified:"
+ << endl;
+ for (unsigned index = 1; index < compilers_detected.size(); ++index) {
+ if (compilers_detected[index].verified_) {
+ ++count2;
+ Compiler *pCompiler = &compilers_detected[index];
+ cerr << IToDec0N(count2,2) << ": errors = "<<
+ IToDec(pCompiler->results_[total_check_result].errors_,5)
+ << ", " <<
+ pCompiler->name_ <<
+ endl;
+ }
+ }
+
+ /* Print summary if we have verified compilers or
+ if the -kd option used. */
+ if (compilers_verified || check_show_results) {
+ /* Print compilers detected summary*/
+ if (print_summary_all) {
+ int count = 0;
+ cerr << endl;
+ cerr << "*** ERRORS PER COMPILER ***" << endl;
+ for (unsigned index = 1; index < compilers_detected.size(); ++index) {
+ Compiler *pCompiler = &compilers_detected[index];
+ if (pCompiler->verified_) {
+ ++count;
+ cerr << IToDec0N(count,2) << ": " <<
+ pCompiler->name_ << endl;
+ print_specific_checks_results(pCompiler);
+ }
+ }
+ }
+
+ /* Print general summary (all compilers checked) */
+ cerr << endl;
+ cerr <<"*** TOTAL ERRORS FOR ALL COMPILERS ***" << endl;
+ print_specific_checks_results(&compilers_detected[0]);
+ }
+ }
+}
+
+
+/*
+ Given a file which we know is an elf file, process
+ the dwarf data.
+
+*/
+static int
+process_one_file(Elf * elf,const string & file_name, int archive,
+ struct dwconf_s *config_file_data)
+{
+ Dwarf_Debug dbg;
+ int dres = 0;
+
+ dres = dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL, &dbg, &err);
+ if (dres == DW_DLV_NO_ENTRY) {
+ cout <<"No DWARF information present in " << file_name <<endl;
+ return 0;
+ }
+ if (dres != DW_DLV_OK) {
+ print_error(dbg, "dwarf_elf_init", dres, err);
+ }
+
+ if (archive) {
+ Elf_Arhdr *mem_header = elf_getarhdr(elf);
+
+ cout << endl;
+ cout << "archive member \t" <<
+ (mem_header ? mem_header->ar_name : "") << endl;
+ }
+ dwarf_set_frame_rule_initial_value(dbg,
+ config_file_data->cf_initial_rule_value);
+ dwarf_set_frame_rule_table_size(dbg,
+ config_file_data->cf_table_entry_count);
+ dwarf_set_frame_cfa_value(dbg,
+ config_file_data->cf_cfa_reg);
+ dwarf_set_frame_same_value(dbg,
+ config_file_data->cf_same_val);
+ dwarf_set_frame_undefined_value(dbg,
+ config_file_data->cf_undefined_val);
+ if(config_file_data->cf_address_size) {
+ dwarf_set_default_address_size(dbg, config_file_data->cf_address_size);
+ }
+ dwarf_set_harmless_error_list_size(dbg,50);
+
+ dres = dwarf_get_address_size(dbg,
+ &error_message_data.elf_address_size,&err);
+ if (dres != DW_DLV_OK) {
+ print_error(dbg, "get_location_list", dres, err);
+ }
+ error_message_data.elf_max_address =
+ (error_message_data.elf_address_size == 8 ) ?
+ 0xffffffffffffffffULL : 0xffffffff;
+
+ /* Get .text and .debug_ranges info if in check mode */
+ if (do_check_dwarf) {
+ Dwarf_Addr lower = 0;
+ Dwarf_Addr upper = 0;
+ Dwarf_Unsigned size = 0;
+ int res = 0;
+ res = dwarf_get_section_info_by_name(dbg,".text",&lower,&size,&err);
+ if (DW_DLV_OK == res) {
+ upper = lower + size;
+ }
+
+ /* Set limits for Ranges Information */
+ pAddressRangesData->SetLimitsAddressRange(lower,upper);
+
+ /* Build section information */
+ build_linkonce_info(dbg);
+ }
+
+ if (header_flag) {
+ print_object_header(elf,dbg);
+ }
+ reset_overall_CU_error_data();
+ if (info_flag || line_flag || cu_name_flag || search_is_on ||
+ producer_children_flag) {
+ print_infos(dbg,true);
+ reset_overall_CU_error_data();
+ print_infos(dbg,false);
+ }
+ if (pubnames_flag) {
+ reset_overall_CU_error_data();
+ print_pubnames(dbg);
+ }
+ if (macinfo_flag) {
+ reset_overall_CU_error_data();
+ print_macinfo(dbg);
+ }
+ if (loc_flag) {
+ reset_overall_CU_error_data();
+ print_locs(dbg);
+ }
+ if (abbrev_flag) {
+ reset_overall_CU_error_data();
+ print_abbrevs(dbg);
+ }
+ if (string_flag) {
+ reset_overall_CU_error_data();
+ print_strings(dbg);
+ }
+ if (aranges_flag) {
+ reset_overall_CU_error_data();
+ print_aranges(dbg);
+ }
+ if (ranges_flag) {
+ reset_overall_CU_error_data();
+ print_ranges(dbg);
+ }
+ if (frame_flag || eh_frame_flag) {
+ reset_overall_CU_error_data();
+ print_frames(dbg, frame_flag, eh_frame_flag, config_file_data);
+ }
+ if (static_func_flag) {
+ reset_overall_CU_error_data();
+ print_static_funcs(dbg);
+ }
+ if (static_var_flag) {
+ reset_overall_CU_error_data();
+ print_static_vars(dbg);
+ }
+ /* DWARF_PUBTYPES is the standard typenames dwarf section.
+ SGI_TYPENAME is the same concept but is SGI specific ( it was
+ defined 10 years before dwarf pubtypes). */
+
+ if (type_flag) {
+ reset_overall_CU_error_data();
+ print_types(dbg, DWARF_PUBTYPES);
+ reset_overall_CU_error_data();
+ print_types(dbg, SGI_TYPENAME);
+ }
+ if (weakname_flag) {
+ reset_overall_CU_error_data();
+ print_weaknames(dbg);
+ }
+ if (reloc_flag) {
+ reset_overall_CU_error_data();
+ print_relocinfo(dbg,reloc_map);
+ }
+ // The right time to do this is unclear, but we
+ // need to do it.
+ print_any_harmless_errors(dbg);
+
+ print_checks_results();
+
+ dres = dwarf_finish(dbg, &err);
+ if (dres != DW_DLV_OK) {
+ print_error(dbg, "dwarf_finish", dres, err);
+ }
+ cout << endl;
+ cerr.flush();
+ return 0;
+
+}
+
+static void do_all()
+{
+ info_flag = line_flag = frame_flag = true;
+ pubnames_flag = macinfo_flag = true;
+ aranges_flag = true;
+ /* Do not do
+ loc_flag = TRUE
+ abbrev_flag = TRUE;
+ ranges_flag = true;
+ because nothing in
+ the DWARF spec guarantees the sections are free of random bytes
+ in areas not referenced by .debug_info */
+
+ string_flag = true;
+ /* Do not do
+ reloc_flag = TRUE;
+ as print_relocs makes no sense for non-elf dwarfdump users. */
+ static_func_flag = static_var_flag = true;
+ type_flag = weakname_flag = true;
+ header_flag = true;
+}
+
+/* Remove matching leading/trailing quotes.
+ Does not alter the passed in string.
+ If quotes removed does a makename on a modified string. */
+static string
+remove_quotes_pair(char *text)
+{
+ static char single_quote = '\'';
+ static char double_quote = '\"';
+ string out;
+ char quote = 0;
+ char *p = text;
+ int len = strlen(text);
+
+ if (len < 2) {
+ return p;
+ }
+
+ /* Compare first character with ' or " */
+ if (p[0] == single_quote) {
+ quote = single_quote;
+ } else {
+ if (p[0] == double_quote) {
+ quote = double_quote;
+ }
+ else {
+ return p;
+ }
+ }
+ {
+ if (p[len - 1] == quote) {
+ out = string(p+1,p+len-1);
+ return out;
+ }
+ }
+ return p;
+}
+
+
+/* process arguments and return object filename */
+static string
+process_args(int argc, char *argv[])
+{
+ extern int optind;
+ int c = 0;
+ bool usage_error = false;
+ int oarg = 0;
+
+ program_name = argv[0];
+
+ suppress_check_dwarf();
+ /* j q unused */
+ if (argv[1] != NULL && argv[1][0] != '-') {
+ do_all();
+ }
+
+ while ((c =
+ getopt(argc, argv,
+ "#:abc::CdDeEfFgGhH:ik:lmMnNo::pPqQrRsS:t:u:UvVwW::x:yz")) != EOF) {
+
+ switch (c) {
+ case '#':
+ {
+ int nTraceLevel = atoi(optarg);
+ if (nTraceLevel > 0 && nTraceLevel <= MAX_TRACE_LEVEL) {
+ nTrace[nTraceLevel] = 1;
+ }
+ break;
+ }
+ case 'M':
+ show_form_used = true;
+ break;
+ case 'x': /* Select abi/path to use */
+ {
+ string path;
+ string abi;
+
+ /* -x name=<path> meaning name dwarfdump.conf file -x
+ abi=<abi> meaning select abi from dwarfdump.conf
+ file. Must always select abi to use dwarfdump.conf */
+ if (strncmp(optarg, "name=", 5) == 0) {
+ path = do_uri_translation(&optarg[5],"-x name=");
+ if (path.empty())
+ goto badopt;
+ config_file_path = path;
+ } else if (strncmp(optarg, "abi=", 4) == 0) {
+ abi = do_uri_translation(&optarg[4],"-x abi=");
+ if (abi.empty())
+ goto badopt;
+ config_file_abi = abi;
+ break;
+ } else {
+
+ badopt:
+ cerr << "-x name=<path-to-conf>" <<endl;
+ cerr << " and " << endl;
+ cerr << "-x abi=<abi-in-conf> " << endl;
+ cerr << "are legal, not -x " << optarg<< endl;
+ usage_error = true;
+ break;
+ }
+ }
+ break;
+ case 'C':
+ suppress_check_extensions_tables = true;
+ break;
+ case 'g':
+ use_old_dwarf_loclist = true;
+ info_flag = true;
+ suppress_check_dwarf();
+ break;
+ case 'i':
+ info_flag = true;
+ suppress_check_dwarf();
+ break;
+ case 'n':
+ suppress_nested_name_search = true;
+ break;
+ case 'l':
+ line_flag = true;
+ suppress_check_dwarf();
+ break;
+ case 'f':
+ frame_flag = true;
+ suppress_check_dwarf();
+ break;
+ case 'H':
+ {
+ int break_val = atoi(optarg);
+ if(break_val > 0) {
+ break_after_n_units = break_val;
+ }
+ }
+ break;
+ case 'F':
+ eh_frame_flag = true;
+ suppress_check_dwarf();
+ break;
+ case 'b':
+ abbrev_flag = true;
+ suppress_check_dwarf();
+ break;
+ case 'p':
+ pubnames_flag = true;
+ suppress_check_dwarf();
+ break;
+ case 'P':
+ /* List of CUs per compiler */
+ producer_children_flag = true;
+ break;
+ case 'r':
+ aranges_flag = true;
+ suppress_check_dwarf();
+ break;
+ case 'N':
+ ranges_flag = true;
+ suppress_check_dwarf();
+ break;
+ case 'R':
+ generic_1200_regs = true;
+ break;
+ case 'm':
+ macinfo_flag = true;
+ suppress_check_dwarf();
+ break;
+ case 'c':
+ // Specify compiler name.
+ if (optarg) {
+ if ('s' == optarg[0]) {
+ /* -cs : Check SNC compiler */
+ check_snc_compiler = true;
+ check_all_compilers = false;
+ }
+ else {
+ if ('g' == optarg[0]) {
+ /* -cg : Check GCC compiler */
+ check_gcc_compiler = true;
+ check_all_compilers = false;
+ }
+ else {
+ check_all_compilers = false;
+ increment_compilers_targeted(true);
+ unsigned cc = compilers_targeted.size() -1;
+ compilers_targeted[cc].name_ =
+ do_uri_translation(optarg,"-c<compiler name>");
+ // Assume a compiler version to check,
+ // most likely a substring of a compiler name.
+ }
+ }
+ } else {
+ loc_flag = true;
+ suppress_check_dwarf();
+ }
+ break;
+ case 'Q':
+ // Q suppresses section data printing.
+ do_print_dwarf = false;
+ break;
+ case 'q':
+ // suppress uri-did-translate notification.
+ do_print_uri_in_input = false;
+ break;
+ case 's':
+ string_flag = true;
+ suppress_check_dwarf();
+ break;
+ case 'S':
+ /* -S option: strings for 'any' and 'match' */
+ {
+ bool err = true;
+ search_is_on = true;
+ /* -S text */
+ if (strncmp(optarg,"match=",6) == 0) {
+ string noquotes = remove_quotes_pair(&optarg[6]);
+ search_match_text = do_uri_translation(noquotes,"-S match=");
+ if (search_match_text.size() > 0) {
+ err = false;
+ }
+ }
+ else {
+ if (strncmp(optarg,"any=",4) == 0) {
+ string noquotes = remove_quotes_pair(&optarg[4]);
+ search_any_text=do_uri_translation(noquotes,"-S any=");
+ if (search_any_text.size() > 0) {
+ err = false;
+ }
+ }
+#ifdef HAVE_REGEX
+ else {
+ if (strncmp(optarg,"regex=",6) == 0) {
+ string noquotes = remove_quotes_pair(&optarg[6]);
+ search_regex_text = do_uri_translation(noquotes,"-S regex=");
+ if (search_regex_text.size() > 0) {
+ if (regcomp(&search_re,
+ search_regex_text.c_str(),
+ REG_EXTENDED)) {
+ cerr <<
+ "regcomp: unable to compile " <<
+ search_regex_text << endl;
+ }
+ else {
+ err = false;
+ }
+ }
+ }
+ }
+#endif /* HAVE_REGEX */
+ }
+ if (err) {
+ cerr <<
+ "-S any=<text> or -S match=<text> or -S regex=<text>"
+ << endl;
+ cerr << "is allowed, not -S " <<optarg << endl;
+ usage_error = true;
+ }
+ }
+ break;
+ case 'a':
+ suppress_check_dwarf();
+ do_all();
+ break;
+ case 'v':
+ verbose++;
+ break;
+ case 'V':
+ {
+ cout << DWARFDUMP_VERSION << endl;
+ exit(0);
+ }
+ break;
+ case 'd':
+ /* This is sort of useless unless printing,
+ but harmless, so we do not insist we
+ are printing with suppress_check_dwarf(). */
+ dense = true;
+ break;
+ case 'D':
+ /* Do not emit offset in output */
+ display_offsets = false;
+ break;
+ case 'e':
+ suppress_check_dwarf();
+ ellipsis = true;
+ break;
+ case 'E':
+ // Object Header information (but maybe really print).
+ header_flag = true;
+ break;
+ case 'o':
+ reloc_flag = true;
+ if (optarg) {
+ switch (optarg[0]) {
+ case 'i':
+ reloc_map |= (1 <<DW_SECTION_REL_DEBUG_INFO);
+ reloc_map |= (1 <<DW_SECTION_REL_DEBUG_TYPES);
+ break;
+ case 'l': reloc_map |= (1 <<DW_SECTION_REL_DEBUG_LINE); break;
+ case 'p': reloc_map |= (1 <<DW_SECTION_REL_DEBUG_PUBNAMES); break;
+ /* Case a has no effect, no relocations can point out
+ of the abbrev section. */
+ case 'a': reloc_map |= (1 <<DW_SECTION_REL_DEBUG_ABBREV); break;
+ case 'r': reloc_map |= (1 <<DW_SECTION_REL_DEBUG_ARANGES); break;
+ case 'f': reloc_map |= (1 <<DW_SECTION_REL_DEBUG_FRAME); break;
+ case 'o': reloc_map |= (1 <<DW_SECTION_REL_DEBUG_LOC); break;
+ case 'R': reloc_map |= (1 <<DW_SECTION_REL_DEBUG_RANGES); break;
+ default: usage_error = true; break;
+ }
+ } else {
+ /* Display all relocs */
+ reloc_map = 0x00ff;
+ }
+ break;
+ case 'k':
+ suppress_print_dwarf();
+ oarg = optarg[0];
+ switch (oarg) {
+ case 'a':
+ check_pubname_attr = true;
+ check_attr_tag = true;
+ check_tag_tree = check_type_offset = true;
+ check_names = true;
+ pubnames_flag = info_flag = true;
+ check_decl_file = true;
+ check_frames = true;
+ // check_frames_extended = false;
+ check_locations = true;
+ frame_flag = eh_frame_flag = true;
+ check_ranges = true;
+ check_lines = true;
+ check_fdes = true;
+ check_harmless = true;
+ check_aranges = true;
+ aranges_flag = true; /* Aranges section */
+ check_abbreviations = true;
+ check_dwarf_constants = true;
+ check_di_gaps = true; /* Check debug info gaps */
+ check_forward_decl = true; /* Check forward declarations */
+ check_self_references = true; /* Check self references */
+ break;
+ /* Abbreviations */
+ case 'b':
+ check_abbreviations = true;
+ info_flag = true;
+ break;
+ /* DWARF constants */
+ case 'c':
+ check_dwarf_constants = true;
+ info_flag = true;
+ break;
+ /* Display check results */
+ case 'd':
+ check_show_results = true;
+ break;
+ case 'e':
+ check_pubname_attr = true;
+ pubnames_flag = true;
+ check_harmless = true;
+ check_fdes = true;
+ break;
+ case 'f':
+ check_harmless = true;
+ check_fdes = true;
+ break;
+ /* files-lines */
+ case 'F':
+ check_decl_file = true;
+ check_lines = true;
+ info_flag = true;
+ break;
+ /* Check debug info gaps */
+ case 'g':
+ check_di_gaps = true;
+ info_flag = true;
+ break;
+ /* Locations list */
+ case 'l':
+ check_locations = true;
+ info_flag = true;
+ loc_flag = true;
+ break;
+ /* Ranges */
+ case 'm':
+ check_ranges = true;
+ info_flag = true;
+ break;
+ /* Aranges */
+ case 'M':
+ check_aranges = true;
+ aranges_flag = true;
+ break;
+ /* invalid names */
+ case 'n':
+ check_names = true;
+ info_flag = true;
+ break;
+
+ case 'r':
+ check_attr_tag = true;
+ info_flag = true;
+ check_harmless = true;
+ break;
+ /* forward declarations in DW_AT_specification */
+ case 'R':
+ check_forward_decl = true;
+ info_flag = true;
+ break;
+ /* Check verbose mode */
+ case 's':
+ check_verbose_mode = false;
+ break;
+ /* self references in:
+ DW_AT_specification, DW_AT_type, DW_AT_abstract_origin */
+ case 'S':
+ check_self_references = true;
+ info_flag = true;
+ break;
+
+ case 't':
+ check_tag_tree = true;
+ check_harmless = true;
+ info_flag = true;
+ break;
+ case 'y':
+ check_type_offset = true;
+ check_harmless = true;
+ check_decl_file = true;
+ info_flag = true;
+ check_ranges = true;
+ check_aranges = true;
+ break;
+ /* Summary for each compiler */
+ case 'i':
+ print_summary_all = true;
+ break;
+ /* Frames check */
+ case 'x':
+ check_frames = true;
+ frame_flag = true;
+ eh_frame_flag = true;
+ if (optarg[1]) {
+ if ('e' == optarg[1]) {
+ /* -xe : Extended frames check */
+ check_frames = false;
+ check_frames_extended = true;
+ } else {
+ usage_error = true;
+ }
+ }
+ break;
+
+ default:
+ usage_error = true;
+ break;
+ }
+ break;
+ case 'u': /* compile unit */
+ cu_name_flag = true;
+ cu_name = do_uri_translation(optarg,"-u<cu name>");
+ break;
+ case 'U': /* Suppress URI translation. */
+ uri_options_translation = false;
+ break;
+ case 't':
+ oarg = optarg[0];
+ switch (oarg) {
+ case 'a':
+ /* all */
+ static_func_flag = static_var_flag = true;
+ suppress_check_dwarf();
+ break;
+ case 'f':
+ /* .debug_static_func */
+ static_func_flag = true;
+ suppress_check_dwarf();
+ break;
+ case 'v':
+ /* .debug_static_var */
+ static_var_flag = true;
+ suppress_check_dwarf();
+ break;
+ default:
+ usage_error = true;
+ break;
+ }
+ break;
+ case 'y': /* .debug_types */
+ suppress_check_dwarf();
+ type_flag = true;
+ break;
+ case 'w': /* .debug_weaknames */
+ weakname_flag = true;
+ suppress_check_dwarf();
+ break;
+ case 'z':
+ cerr << "-z is no longer supported:ignored" << endl;
+ break;
+ case 'G':
+ show_global_offsets = true;
+ break;
+ case 'W':
+ /* Search results in wide format */
+ search_wide_format = true;
+ if (optarg) {
+ if ('c' == optarg[0]) {
+ /* -Wc : Display children tree */
+ display_children_tree = true;
+ } else {
+ if ('p' == optarg[0]) {
+ /* -Wp : Display parent tree */
+ display_parent_tree = true;
+ } else {
+ usage_error = true;
+ }
+ }
+ }
+ else {
+ /* -W : Display parent and children tree */
+ display_children_tree = true;
+ display_parent_tree = true;
+ }
+ break;
+ default:
+ usage_error = true;
+ break;
+ }
+ }
+
+ init_conf_file_data(&config_file_data);
+ if ((!config_file_abi.empty()) && generic_1200_regs) {
+ cout << "Specifying both -R and -x abi= is not allowed. Use one "
+ "or the other. -x abi= ignored." <<endl;
+ config_file_abi = "";
+ }
+ if(generic_1200_regs) {
+ init_generic_config_1200_regs(&config_file_data);
+ }
+ if ((!config_file_abi.empty()) && (frame_flag || eh_frame_flag)) {
+ int res = find_conf_file_and_read_config(config_file_path,
+ config_file_abi,
+ config_file_defaults,
+ &config_file_data);
+ if (res > 0) {
+ cout <<
+ "Frame not configured due to error(s). Giving up."<<endl;
+ eh_frame_flag = false;
+ frame_flag = false;
+ }
+ }
+ if (usage_error || (optind != (argc - 1))) {
+ print_usage_message(program_name,usage_text);
+ exit(FAILED);
+ }
+ if(do_check_dwarf) {
+ /* Reduce verbosity when checking (checking means checking-only). */
+ verbose = 1;
+ }
+ return do_uri_translation(argv[optind],"file-to-process");
+}
+
+/* ARGSUSED */
+void
+print_error(Dwarf_Debug dbg, const string & msg, int dwarf_code,
+ Dwarf_Error err)
+{
+ print_error_and_continue(dbg,msg,dwarf_code,err);
+ exit(FAILED);
+}
+/* ARGSUSED */
+void
+print_error_and_continue(Dwarf_Debug dbg, const string & msg, int dwarf_code,
+ Dwarf_Error err)
+{
+ cout.flush();
+ cerr.flush();
+ cerr << endl;
+ if (dwarf_code == DW_DLV_ERROR) {
+ string errmsg = dwarf_errmsg(err);
+ Dwarf_Unsigned myerr = dwarf_errno(err);
+ cerr << program_name <<
+ " ERROR: " << msg << ": " << errmsg << " (" << myerr<<
+ ")" << endl;
+ } else if (dwarf_code == DW_DLV_NO_ENTRY) {
+ cerr << program_name <<
+ " NO ENTRY: " << msg << ": " << endl;
+ } else if (dwarf_code == DW_DLV_OK) {
+ cerr << program_name<< ": " << msg << endl;
+ } else {
+ cerr << program_name<< " InternalError: "<< msg <<
+ ": code " << dwarf_code << endl;
+ }
+ cerr.flush();
+
+ // Display compile unit name.
+ PRINT_CU_INFO();
+}
+
+/* Predicate function. Returns 'true' if the CU should
+ be skipped as the DW_AT_name of the CU
+ does not match the command-line-supplied
+ cu name. Else returns false.*/
+bool
+should_skip_this_cu(DieHolder& hcu_die, Dwarf_Error err)
+{
+ Dwarf_Half tag = 0;
+ Dwarf_Attribute attrib;
+ Dwarf_Half theform = 0;
+ Dwarf_Die cu_die = hcu_die.die();
+ Dwarf_Debug dbg = hcu_die.dbg();
+
+ int tres = dwarf_tag(cu_die, &tag, &err);
+ if (tres != DW_DLV_OK) {
+ print_error(dbg, "dwarf_tag when checking if cu skippable ",
+ tres, err);
+ }
+ int dares = dwarf_attr(cu_die, DW_AT_name, &attrib, &err);
+ if (dares != DW_DLV_OK) {
+ print_error(dbg,
+ "dwarf cu_die has no name, when checking if cu skippable",
+ dares, err);
+ }
+ int fres = dwarf_whatform(attrib, &theform, &err);
+ if (fres == DW_DLV_OK) {
+ if (theform == DW_FORM_string
+ || theform == DW_FORM_strp) {
+ char * temps = 0;
+ int sres = dwarf_formstring(attrib, &temps,
+ &err);
+ if (sres == DW_DLV_OK) {
+ char *p = temps;
+ if (cu_name[0] != '/') {
+ p = strrchr(temps, '/');
+ if (p == NULL) {
+ p = temps;
+ } else {
+ p++;
+ }
+ }
+ if (strcmp(cu_name.c_str(), p)) {
+ // skip this cu.
+ return true;
+ }
+ } else {
+ print_error(dbg,
+ "arange: string missing",
+ sres, err);
+ }
+ }
+ } else {
+ print_error(dbg,
+ "dwarf_whatform unexpected value",
+ fres, err);
+ }
+ dwarf_dealloc(dbg, attrib, DW_DLA_ATTR);
+ return false;
+}
+
+
+/* Returns the DW_AT_name of the CU */
+string
+old_get_cu_name(Dwarf_Debug dbg, Dwarf_Die cu_die, Dwarf_Error err)
+{
+ Dwarf_Half tag = 0;
+ Dwarf_Attribute attrib = 0;
+ Dwarf_Half theform = 0;
+ string attr_name;
+
+ int tres = dwarf_tag(cu_die, &tag, &err);
+ if (tres != DW_DLV_OK) {
+ print_error(dbg, "dwarf_tag in aranges",
+ tres, err);
+ }
+ int dares = dwarf_attr(cu_die, DW_AT_name, &attrib,
+ &err);
+ if (dares != DW_DLV_OK) {
+ print_error(dbg, "dwarf_attr arange"
+ " derived die has no name",
+ dares, err);
+ }
+ int fres = dwarf_whatform(attrib, &theform, &err);
+ if (fres == DW_DLV_OK) {
+ if (theform == DW_FORM_string
+ || theform == DW_FORM_strp) {
+ char * temps = 0;
+ int sres = dwarf_formstring(attrib, &temps,
+ &err);
+ if (sres == DW_DLV_OK) {
+ char *p = temps;
+ if (cu_name[0] != '/') {
+ p = strrchr(temps, '/');
+ if (p == NULL) {
+ p = temps;
+ } else {
+ p++;
+ }
+ }
+ attr_name.append(p);
+ } else {
+ print_error(dbg,
+ "arange: string missing",
+ sres, err);
+ }
+ }
+ } else {
+ print_error(dbg,
+ "dwarf_whatform unexpected value",
+ fres, err);
+ }
+ dwarf_dealloc(dbg, attrib, DW_DLA_ATTR);
+
+ return attr_name;
+}
+
+/* Returns the cu name of the CU */
+int get_cu_name(DieHolder &hcu_die,
+ Dwarf_Error err, string &short_name, string &long_name)
+{
+ Dwarf_Attribute name_attr = 0;
+
+ int ares = dwarf_attr(hcu_die.die(),DW_AT_name, &name_attr, &err);
+ if (ares == DW_DLV_ERROR) {
+ print_error(hcu_die.dbg(), "hassattr on DW_AT_name", ares, err);
+ } else {
+ if (ares == DW_DLV_NO_ENTRY) {
+ short_name = "<unknown name>";
+ long_name = "<unknown name>";
+ } else {
+ /* DW_DLV_OK */
+
+ SrcfilesHolder srcfiles;
+ get_attr_value(hcu_die.dbg(), DW_TAG_compile_unit,
+ hcu_die.die(), name_attr,
+ srcfiles,
+ long_name,
+ false /*show_form_used*/,0 /* verbose */);
+ /* Generate the short name (filename) */
+ const char * filename = strrchr(long_name.c_str(),'/');
+ if (!filename) {
+ filename = strrchr(long_name.c_str(),'\\');
+ }
+ if (filename) {
+ ++filename;
+ } else {
+ filename = long_name.c_str();
+ }
+ short_name = filename;
+ }
+ }
+ dwarf_dealloc(hcu_die.dbg(), name_attr, DW_DLA_ATTR);
+ return ares;
+}
+
+/* Returns the producer of the CU */
+int get_producer_name(DieHolder &hcu_die,
+ Dwarf_Error err, string &producer_name)
+{
+ Dwarf_Attribute producer_attr = 0;
+
+ int ares = dwarf_attr(hcu_die.die(), DW_AT_producer, &producer_attr, &err);
+ if (ares == DW_DLV_ERROR) {
+ print_error(hcu_die.dbg(), "hassattr on DW_AT_producer", ares, err);
+ } else {
+ if (ares == DW_DLV_NO_ENTRY) {
+ /* We add extra quotes so it looks more like
+ the names for real producers that get_attr_value
+ produces. */
+ producer_name = "\"<CU-missing-DW_AT_producer>\"";
+ } else {
+ /* DW_DLV_OK */
+ /* The string return is valid until the next call to this
+ function; so if the caller needs to keep the returned
+ string, the string must be copied (makename()). */
+ string esb_producer;
+ SrcfilesHolder srcfiles;
+ get_attr_value(hcu_die.dbg(), DW_TAG_compile_unit,
+ hcu_die.die(), producer_attr,
+ srcfiles,producer_name,
+ false /*show_form_used*/,
+ 0 /* verbose */);
+ }
+ }
+
+ dwarf_dealloc(hcu_die.dbg(), producer_attr, DW_DLA_ATTR);
+ return ares;
+}
+
+/* GCC linkonce names */
+const char *lo_text = ".text."; /*".gnu.linkonce.t.";*/
+const char *lo_debug_abbr = ".gnu.linkonce.wa.";
+const char *lo_debug_aranges = ".gnu.linkonce.wr.";
+const char *lo_debug_frame_1 = ".gnu.linkonce.wf.";
+const char *lo_debug_frame_2 = ".gnu.linkonce.wF.";
+const char *lo_debug_info = ".gnu.linkonce.wi.";
+const char *lo_debug_line = ".gnu.linkonce.wl.";
+const char *lo_debug_macinfo = ".gnu.linkonce.wm.";
+const char *lo_debug_loc = ".gnu.linkonce.wo.";
+const char *lo_debug_pubnames = ".gnu.linkonce.wp.";
+const char *lo_debug_ranges = ".gnu.linkonce.wR.";
+const char *lo_debug_str = ".gnu.linkonce.ws.";
+
+/* SNC compiler/linker linkonce names */
+const char *nlo_text = ".text.";
+const char *nlo_debug_abbr = ".debug.wa.";
+const char *nlo_debug_aranges = ".debug.wr.";
+const char *nlo_debug_frame_1 = ".debug.wf.";
+const char *nlo_debug_frame_2 = ".debug.wF.";
+const char *nlo_debug_info = ".debug.wi.";
+const char *nlo_debug_line = ".debug.wl.";
+const char *nlo_debug_macinfo = ".debug.wm.";
+const char *nlo_debug_loc = ".debug.wo.";
+const char *nlo_debug_pubnames = ".debug.wp.";
+const char *nlo_debug_ranges = ".debug.wR.";
+const char *nlo_debug_str = ".debug.ws.";
+
+/* Build linkonce section information */
+void
+build_linkonce_info(Dwarf_Debug dbg)
+{
+ int nCount = 0;
+ int section_index = 0;
+ int res = 0;
+
+ static const char **linkonce_names[] = {
+ &lo_text, /* .text */
+ &nlo_text, /* .text */
+ &lo_debug_abbr, /* .debug_abbr */
+ &nlo_debug_abbr, /* .debug_abbr */
+ &lo_debug_aranges, /* .debug_aranges */
+ &nlo_debug_aranges, /* .debug_aranges */
+ &lo_debug_frame_1, /* .debug_frame */
+ &nlo_debug_frame_1, /* .debug_frame */
+ &lo_debug_frame_2, /* .debug_frame */
+ &nlo_debug_frame_2, /* .debug_frame */
+ &lo_debug_info, /* .debug_info */
+ &nlo_debug_info, /* .debug_info */
+ &lo_debug_line, /* .debug_line */
+ &nlo_debug_line, /* .debug_line */
+ &lo_debug_macinfo, /* .debug_macinfo */
+ &nlo_debug_macinfo, /* .debug_macinfo */
+ &lo_debug_loc, /* .debug_loc */
+ &nlo_debug_loc, /* .debug_loc */
+ &lo_debug_pubnames, /* .debug_pubnames */
+ &nlo_debug_pubnames, /* .debug_pubnames */
+ &lo_debug_ranges, /* .debug_ranges */
+ &nlo_debug_ranges, /* .debug_ranges */
+ &lo_debug_str, /* .debug_str */
+ &nlo_debug_str, /* .debug_str */
+ NULL
+ };
+
+ const char *section_name = NULL;
+ Dwarf_Addr section_addr = 0;
+ Dwarf_Unsigned section_size = 0;
+ Dwarf_Error error = 0;
+ int nIndex = 0;
+
+ nCount = dwarf_get_section_count(dbg);
+
+ /* Ignore section with index=0 */
+ for (section_index = 1; section_index < nCount; ++section_index) {
+ res = dwarf_get_section_info_by_index(dbg,section_index,
+ &section_name,
+ &section_addr,
+ &section_size,
+ &error);
+
+ if (res == DW_DLV_OK) {
+ for (nIndex = 0; linkonce_names[nIndex]; ++nIndex) {
+ if (section_name == strstr(section_name,
+ *linkonce_names[nIndex])) {
+
+ /* Insert only linkonce sections */
+ pLinkOnceData->AddLinkOnceEntry(
+ LinkOnceEntry(
+ section_index,
+ section_addr,
+ section_addr + section_size,
+ section_name));
+ break;
+ }
+ }
+ }
+ }
+
+ if (dump_linkonce_info) {
+ pLinkOnceData->PrintLinkOnceData();
+ }
+}
+
+/* Check for specific TAGs and initialize some
+ information used by '-k' options */
+void
+tag_specific_checks_setup(Dwarf_Half val,int die_indent_level)
+{
+ switch (val) {
+ case DW_TAG_compile_unit:
+ /* To help getting the compile unit name */
+ error_message_data.seen_CU = true;
+ /* If we are checking line information, build
+ the table containing the pairs LowPC and HighPC */
+ if (check_decl_file || check_ranges || check_locations) {
+ pAddressRangesData->ResetRangesList();
+ }
+ /* The following flag indicate that only low_pc and high_pc
+ values found in DW_TAG_subprograms are going to be considered when
+ building the address table used to check ranges, lines, etc */
+ error_message_data.need_PU_valid_code = true;
+ break;
+
+ case DW_TAG_subprogram:
+ /* Keep track of a PU */
+ if (die_indent_level == 1) {
+ /* A DW_TAG_subprogram can be nested, when is used to
+ declare a member function for a local class; process the DIE
+ only if we are at level zero in the DIEs tree */
+ error_message_data.seen_PU = true;
+ error_message_data.seen_PU_base_address = false;
+ error_message_data.seen_PU_high_address = false;
+ error_message_data.PU_name = "";
+ error_message_data.need_PU_valid_code = true;
+ }
+ break;
+ }
+}
+
+/* Indicates if the current CU is a target */
+static bool current_cu_is_checked_compiler = true;
+
+/* Are we checking for errors from the
+ compiler of the current compilation unit?
+*/
+bool
+checking_this_compiler()
+{
+ /* This flag has been update by 'update_compiler_target()'
+ and indicates if the current CU is in a targeted compiler
+ specified by the user. Default value is tRUE, which
+ means test all compilers until a CU is detected. */
+ return current_cu_is_checked_compiler || check_all_compilers;
+}
+
+static int
+hasprefix(const char *sample, const char *prefix)
+{
+ unsigned prelen = strlen(prefix);
+ if ( strncmp(sample,prefix,prelen) == 0) {
+ return true;
+ }
+ return false;
+}
+
+static void
+increment_compilers_detected(bool beyond)
+{
+ if( compilers_detected.empty()) {
+ // For the standard 'all' entry [0].
+ Compiler c;
+ compilers_detected.push_back(c);
+ }
+ if (beyond) {
+ Compiler c;
+ compilers_detected.push_back(c);
+ }
+}
+static void
+increment_compilers_targeted(bool beyond)
+{
+ if( compilers_targeted.empty()) {
+ // For the standard 'all' entry [0].
+ Compiler c;
+ compilers_targeted.push_back(c);
+ }
+ if (beyond) {
+ Compiler c;
+ compilers_targeted.push_back(c);
+ }
+}
+
+
+/* Record which compiler was used (or notice we saw
+ it before) and set a couple variables as
+ a side effect (which are used all over):
+ current_cu_is_checked_compiler (used in checking_this_compiler() )
+ current_compiler
+ The compiler name is from DW_AT_producer.
+*/
+void
+update_compiler_target(const string &producer_name)
+{
+ unsigned index = 0;
+
+ error_message_data.CU_producer = producer_name;
+ current_cu_is_checked_compiler = false;
+
+ /* This list of compilers is just a start:
+ GCC id : "GNU"
+ SNC id : "SN Systems" */
+
+ /* Find a compiler version to check */
+ if (!compilers_targeted.empty()) {
+ for (index = 1; index < compilers_targeted.size(); ++index) {
+ if (is_strstrnocase(error_message_data.CU_producer.c_str(),
+ compilers_targeted[index].name_.c_str())) {
+ compilers_targeted[index].verified_ = true;
+ current_cu_is_checked_compiler = true;
+ break;
+ }
+ }
+ } else {
+ /* Take into account that internally all strings are double quoted */
+ bool snc_compiler = hasprefix(
+ error_message_data.CU_producer.c_str(),
+ "\"SN")? true : false;
+ bool gcc_compiler = hasprefix(
+ error_message_data.CU_producer.c_str(),
+ "\"GNU")?true : false;
+ current_cu_is_checked_compiler = check_all_compilers ||
+ (snc_compiler && check_snc_compiler) ||
+ (gcc_compiler && check_gcc_compiler) ;
+ }
+
+ /* Check for already detected compiler */
+ bool cFound = false;
+ for (index = 1; index < compilers_detected.size(); ++index) {
+ if (
+#if WIN32
+ !stricmp(compilers_detected[index].name_.c_str(),
+ error_message_data.CU_producer.c_str())
+#else
+ compilers_detected[index].name_ == error_message_data.CU_producer
+#endif
+ ) {
+ /* Set current compiler index */
+ current_compiler = index;
+ cFound = true;
+ break;
+ }
+ }
+ if (!cFound) {
+ /* Record a new detected compiler name. */
+ increment_compilers_detected(true);
+ current_compiler = compilers_detected.size()-1;
+ compilers_detected[current_compiler].name_ =
+ error_message_data.CU_producer;
+ }
+}
+
+/* Add a CU name to the current compiler entry, specified by the
+ 'current_compiler'; the name is added to the 'compilers_detected'
+ table and is printed if the '-P' option is specified in the
+ command line. */
+void
+add_cu_name_compiler_target(const string & name)
+{
+ if (current_compiler < 1) {
+ cerr << "Current compiler set to " << current_compiler <<
+ "cannot add Compilation unit name. Giving up." << endl;
+ exit(1);
+ }
+ compilers_detected[current_compiler].cu_list_.push_back(name);
+}
+
+/* Making this a named string makes it simpler to change
+ what the reset,or 'I do not know' value is for
+ CU name or producer name for PRINT_CU_INFO. */
+static string default_cu_producer("<unknown>");
+static void
+reset_overall_CU_error_data()
+{
+ error_message_data.CU_name = default_cu_producer;
+ error_message_data.CU_producer = default_cu_producer;
+ error_message_data.DIE_offset = 0;
+ error_message_data.DIE_overall_offset = 0;
+ error_message_data.DIE_CU_offset = 0;
+ error_message_data.DIE_CU_overall_offset = 0;
+ error_message_data.CU_base_address = 0;
+ error_message_data.CU_high_address = 0;
+}
+
+static bool
+cu_data_is_set()
+{
+ if(error_message_data.CU_name != default_cu_producer ||
+ error_message_data.CU_producer != default_cu_producer) {
+ return true;
+ }
+ if(error_message_data.DIE_offset ||
+ error_message_data.DIE_overall_offset) {
+ return true;
+ }
+ if(error_message_data.CU_base_address ||
+ error_message_data.CU_high_address) {
+ return true;
+ }
+ return false;
+}
+
+/* Print CU basic information */
+void PRINT_CU_INFO()
+{
+ cerr.flush();
+ cout.flush();
+ if (error_message_data.current_section_id == DEBUG_LINE ||
+ error_message_data.current_section_id == DEBUG_ARANGES) {
+ /* Only in the DEBUG_LINE/ARANGES case is DIE_CU_offset or
+ DIE_CU_overall_offset what we want to print here.
+ In other cases DIE_CU_offset is not really a CU
+ offset at all. */
+ error_message_data.DIE_offset = error_message_data.DIE_CU_offset;
+ error_message_data.DIE_overall_offset =
+ error_message_data.DIE_CU_overall_offset;
+ }
+ if(!cu_data_is_set()) {
+ return;
+ }
+ cout << endl;
+ cout <<"CU Name = " <<error_message_data.CU_name << endl;
+ cout << "CU Producer = " <<error_message_data.CU_producer << endl;
+ cout <<"DIE OFF = "<< IToHex0N(error_message_data.DIE_offset,10) <<
+ " GOFF = "<< IToHex0N(error_message_data.DIE_overall_offset,10);
+ cout <<", Low PC = " <<
+ IToHex0N(error_message_data.CU_base_address,10) <<
+ ", High PC = " <<
+ IToHex0N(error_message_data.CU_high_address,10);
+ cout << endl;
+ cout.flush();
+}
+
+void DWARF_CHECK_COUNT(Dwarf_Check_Categories category, int inc)
+{
+ compilers_detected[0].results_[category].checks_ += inc;
+ compilers_detected[0].results_[total_check_result].checks_ += inc;
+ if(current_compiler > 0) {
+ compilers_detected[current_compiler].results_[category].checks_ += inc;
+ compilers_detected[current_compiler].results_[total_check_result].checks_
+ += inc;
+ compilers_detected[current_compiler].verified_ = true;
+ }
+}
+
+void DWARF_ERROR_COUNT(Dwarf_Check_Categories category, int inc)
+{
+ compilers_detected[0].results_[category].errors_ += inc;
+ compilers_detected[0].results_[total_check_result].errors_ += inc;
+ if(current_compiler > 0) {
+ compilers_detected[current_compiler].results_[category].errors_ += inc;
+ compilers_detected[current_compiler].results_[total_check_result].errors_
+ += inc;
+ }
+}
+
+static void
+PRINT_CHECK_RESULT(const string &str,
+ Compiler *pCompiler, Dwarf_Check_Categories category)
+{
+ Dwarf_Check_Result result = pCompiler->results_[category];
+ cerr << std::setw(24) << std::left << str <<
+ IToDec(result.checks_,10) <<
+ " " <<
+ IToDec(result.errors_,10) << endl;
+}
+
+void DWARF_CHECK_ERROR_PRINT_CU()
+{
+ if (check_verbose_mode) {
+ PRINT_CU_INFO();
+ }
+ check_error++;
+ record_dwarf_error = true;
+}
+
+void DWARF_CHECK_ERROR(Dwarf_Check_Categories category,
+ const std::string& str)
+{
+ if (checking_this_compiler()) {
+ DWARF_ERROR_COUNT(category,1);
+ if (check_verbose_mode) {
+ cout << endl;
+ cout << "*** DWARF CHECK: " << str << " ***" <<
+ endl;
+ }
+ DWARF_CHECK_ERROR_PRINT_CU();
+ }
+}
+
+void DWARF_CHECK_ERROR2(Dwarf_Check_Categories category,
+ const std::string & str1, const std::string & str2)
+{
+ if (checking_this_compiler()) {
+ DWARF_ERROR_COUNT(category,1);
+ if (check_verbose_mode) {
+ cout << endl;
+ cout << "*** DWARF CHECK: " << str1 << ": " <<
+ str2 << " ***" <<
+ endl;
+ }
+ DWARF_CHECK_ERROR_PRINT_CU();
+ }
+}
+
+void DWARF_CHECK_ERROR3(Dwarf_Check_Categories category,
+ const std::string &str1, const std::string &str2,
+ const std::string &strexpl)
+{
+ if (checking_this_compiler()) {
+ DWARF_ERROR_COUNT(category,1);
+ if (check_verbose_mode) {
+ cout << endl;
+ cout << "*** DWARF CHECK: " << str1 << " -> " <<
+ str2 << ": " <<
+ strexpl << " ***" <<
+ endl;
+ }
+ DWARF_CHECK_ERROR_PRINT_CU();
+ }
+}
+
+static string
+do_uri_translation(const string &s,const string&context)
+{
+ string out;
+ if (!uri_options_translation) {
+ return s;
+ }
+ translate_from_uri(s.c_str(),out);
+ if (do_print_uri_in_input) {
+ if(s != out) {
+ cout << "Uri Translation on option " << context << endl;
+ cout << " \'" << s << "\'"<< endl;
+ cout << " \'" << out << "\'"<< endl;
+ }
+ }
+ return out;
+}
+
diff --git a/dwarfdump2/dwarfdump.conf b/dwarfdump2/dwarfdump.conf
new file mode 100644
index 0000000..d70bab8
--- /dev/null
+++ b/dwarfdump2/dwarfdump.conf
@@ -0,0 +1,810 @@
+# MIPS/IRIX ISA/ABI
+# Used to configure dwarfdump printing of .debug_frame and
+# .eh_frame.
+
+# Any number of abi's can be described. Only one can be selected
+# in a given dwarfdump run (see dwarfdump options)
+# Available commands are
+# beginabi: <abiname>
+# reg: <regname> <dwarf regnumber>
+# frame_interface: <integer value 2 or 3>
+# cfa_reg: <number>
+# initial_reg_value: <number: often 1034 or 1035 >
+# same_val_reg: 1035
+# undefined_val_reg: 1034
+# reg_table_size: <size of table>
+# address_size: <4 or 8, Rarely needed, see example below. >
+# includeabi: <abiname Inserts the referenced abi as if its text was
+# directly inserted at this point.>
+# endabi: <abiname>
+#
+# Symbolic names do not work here, use literal numbers
+# where applicable (in C standard decimal, octal (leading 0) or
+# hexadecimal <leading 0x>).
+#
+# Whitespace is required to separate command: from operands and
+# operands from each other on a line.
+#
+# There is no ordering required within a beginabi/endabi pair.
+# As many ABIs as required may be listed.
+# dwarfdump will choose exactly one abi to dump frame information.
+#
+
+
+# MIPS abi,the old IRIX form, not to be used on modern objects.
+# Begin with abi name (use here and on dwarfdump command line).
+beginabi: mips-irix
+
+# Instructs dwarfdump to default to the older frame interface.
+# Use value 3 to use the newer interface.
+# The '2' interface is supported but deprecated (deprecated
+# because it cannot work with all popular ABIs: mixing
+# the cfa-rule into the table column set was not a good idea
+# but it is part of the MIPS/IRIX standard usage).
+frame_interface: 2
+
+# If (and only if) using frame_interface: 2 tell dwarfdump
+# what table colum that DW_FRAME_CFA_COL is.
+# If using frame_interface: 3 cfa_reg: should be
+# DW_FRAME_CFA_COL3 (1436)
+cfa_reg: 0
+
+# For MIPS, the same as DW_FRAME_SAME_VAL (1035).
+# For other ISA/ABIs 1034 (DW_FRAME_UNDEFINED_VAL) might be better.
+# Depends on the ABI convention, if set wrong way too many
+# regs will be listed in the frame output.
+# This instructs dwarfdump to set libdwarf to this value,
+# overriding the libdwarf default.
+# If initial_reg_value not set the libdwarf default is used
+# (see libdwarf.h DW_FRAME_REG_INITIAL_VALUE).
+initial_reg_value: 1035 # DW_FRAME_SAME_VAL
+same_val_reg: 1035
+undefined_val_reg: 1034
+
+# Built in to frame_interface: 2 as 66.
+reg_table_size: 66
+
+
+# Only name registers for wich a r4 (for example) is not what you
+# want to see
+# No particular order of the reg: lines required.
+reg: cfa 0 # Used with MIPS/IRIX original DWARF2 interface
+reg: r1/at 1
+reg: r2/v0 2
+reg: r3/v1 3
+reg: r4/a0 4
+reg: r5/a1 5
+reg: r6/a2 6
+reg: r7/a3 7
+reg: r8/t0 8
+reg: r9/t1 9
+reg: r10/t2 10
+reg: r11/t3 11
+reg: r12/t4 12
+reg: r13/t5 13
+reg: r14/t6 14
+reg: r15/t7 15
+reg: r16/s0 16
+reg: r17/s1 17
+reg: r18/s2 18
+reg: r19/s3 19
+reg: r20/s4 20
+reg: r21/s5 21
+reg: r22/s6 22
+reg: r23/s7 23
+reg: r24/t8 24
+reg: r25/t9 25
+reg: r26/k0 26
+reg: r27/k1 27
+reg: r28/gp 28
+reg: r29/sp 29
+reg: r30/s8 30
+reg: r31 31
+
+reg: $f0 32
+reg: $f1 33
+reg: $f2 34
+reg: $f3 35
+reg: $f4 36
+reg: $f5 37
+reg: $f6 38
+reg: $f7 39
+reg: $f8 40
+reg: $f9 41
+reg: $f10 42
+reg: $f11 43
+reg: $f12 44
+reg: $f13 45
+reg: $f14 46
+reg: $f15 47
+reg: $f16 48
+reg: $f17 49
+reg: $f18 50
+reg: $f19 51
+reg: $f20 52
+reg: $f21 53
+reg: $f22 54
+reg: $f23 55
+reg: $f24 56
+reg: $f25 57
+reg: $f26 58
+reg: $f27 59
+reg: $f28 60
+reg: $f29 61
+reg: $f30 62
+reg: $f31 63
+reg: ra 64
+reg: slk 65
+
+
+# End of abi definition.
+endabi: mips-irix
+
+
+# Make 'mips' abi be a modern MIPS, not an old IRIX version.
+beginabi: mips
+includeabi: mips-simple3
+endabi: mips
+
+
+# MIPS/IRIX ISA/ABI for testing libdwarf.
+beginabi: mips-irix2
+frame_interface: 2
+reg_table_size: 66
+cfa_reg: 0
+same_val_reg: 1035
+undefined_val_reg: 1034
+initial_reg_value: 1035
+
+reg: cfa 0 # Used with MIPS/IRIX original DWARF2 interface
+reg: ra 64
+reg: slk 65
+
+# End of abi definition.
+endabi: mips-irix2
+
+# MIPS/IRIX ISA/ABI for testing the new frame interface
+# with libdwarf.
+beginabi: mips-simple3
+frame_interface: 3
+
+# When using frame_interface: 3 the size of the register table
+# is not fixed. It can be as large as needed.
+reg_table_size: 66
+cfa_reg: 1436 # DW_FRAME_CFA_COL3
+initial_reg_value: 1035
+same_val_reg: 1035
+undefined_val_reg: 1034
+
+# No cfa as a 'normal' register.
+# Rule 0 is just register 0, which is not used
+# in frame descriptions.
+# (so cfa does not have a number here, and dwarfdump gives
+# it the name 'cfa' automatically).
+reg: ra 64
+reg: slk 65
+# End of abi definition.
+endabi: mips-simple3
+
+
+beginabi: ia64
+frame_interface: 3
+initial_reg_value: 1034 # DW_FRAME_UNDEFINED_VAL
+cfa_reg: 1436 # DW_FRAME_CFA_COL3
+reg_table_size: 695
+same_val_reg: 1035
+undefined_val_reg: 1034
+
+# The following register names are not necessarily correct...
+# Register indexes r32-r127 not used.
+reg: f0 128
+# ...
+reg: f127 255
+reg: b0 321
+reg: b1 322
+reg: b2 323
+reg: b3 324
+reg: b4 325
+reg: b5 326
+reg: b6 327
+reg: b7 328
+reg: vfp 329
+reg: vrap 330
+reg: pr 331
+reg: ip 332
+reg: psr 333
+reg: cfm 334
+reg: k0 335
+reg: k1 336
+reg: k2 337
+reg: k3 338
+reg: k4 339
+reg: k5 340
+reg: k6 341
+reg: k7 342
+reg: rsc 350
+reg: bsp 351
+reg: bspstore 352
+reg: rnat 353
+reg: fcr 355
+reg: eflag 358
+reg: csd 359
+reg: ssd 360
+reg: cflg 361
+reg: fsr 362
+reg: fir 363
+reg: fdr 364
+reg: pfs 398
+reg: lc 399
+reg: ec 400
+
+endabi: ia64
+
+
+beginabi: x86
+frame_interface: 3
+initial_reg_value: 1035 # DW_FRAME_SAME_VAL
+reg_table_size: 66 # more than large enough, hopefully.
+cfa_reg: 1436 # DW_FRAME_CFA_COL3
+same_val_reg: 1035
+undefined_val_reg: 1034
+
+# The following register names are not necessarily correct...
+reg: eax 0
+reg: ecx 1
+reg: edx 2
+reg: ebx 3
+reg: esp 4
+reg: ebp 5
+reg: esi 6
+reg: edi 7
+reg: eip 8
+reg: eflags 9
+
+reg: trapno 10
+reg: st0 11
+reg: st1 12
+reg: st2 13
+reg: st3 14
+reg: st4 15
+reg: st5 16
+reg: st6 17
+reg: st7 18
+# 19 is ? 20 is ?
+reg: xmm0 21
+reg: xmm1 22
+reg: xmm2 23
+reg: xmm3 24
+reg: xmm4 25
+reg: xmm5 26
+reg: xmm6 27
+reg: xmm7 28
+
+reg: mm0 29
+reg: mm1 30
+reg: mm2 31
+reg: mm3 32
+reg: mm4 33
+reg: mm5 34
+reg: mm6 35
+reg: mm7 36
+
+reg: fcw 37
+reg: fsw 38
+reg: mxcsr 39
+
+reg: es 40
+reg: cs 41
+reg: ss 42
+reg: ds 43
+reg: fs 44
+reg: gs 45
+# 46 47 are ?
+reg: tr 48
+reg: ldtr 49
+
+
+endabi: x86
+
+
+beginabi: x86_64
+frame_interface: 3
+initial_reg_value: 1035 # DW_FRAME_SAME_VAL
+reg_table_size: 66 # more than large enough, hopefully.
+cfa_reg: 1436 # DW_FRAME_CFA_COL3
+same_val_reg: 1035
+undefined_val_reg: 1034
+
+# The following register names are not necessarily correct...
+reg: rax 0
+reg: rdx 1
+reg: rcx 2
+reg: rbx 3
+reg: rsi 4
+reg: rdi 5
+reg: rbp 6
+reg: rsp 7
+reg: r8 8
+reg: r9 9
+reg: r10 10
+reg: r11 11
+reg: r12 12
+reg: r13 13
+reg: r14 14
+reg: r15 15
+reg: rip 16
+reg: xmm0 17
+reg: xmm1 18
+reg: xmm2 19
+reg: xmm3 20
+reg: xmm4 21
+reg: xmm5 22
+reg: xmm6 23
+reg: xmm7 24
+reg: xmm8 25
+reg: xmm9 26
+reg: xmm10 27
+reg: xmm11 28
+reg: xmm12 29
+reg: xmm13 30
+reg: xmm14 31
+reg: xmm15 32
+
+reg: st0 33
+reg: st1 34
+reg: st2 35
+reg: st3 36
+reg: st4 37
+reg: st5 38
+reg: st6 39
+reg: st7 40
+
+reg: mm0 41
+reg: mm1 42
+reg: mm2 43
+reg: mm3 44
+reg: mm4 45
+reg: mm5 46
+reg: mm6 47
+reg: mm7 48
+
+reg: rflags 49
+reg: es 50
+reg: cs 51
+reg: ss 52
+reg: ds 53
+reg: fs 54
+reg: gs 55
+# 56, 57 are ?
+reg: fs.base 58
+reg: gs.base 59
+# 60 61 are ?
+reg: tr 62
+reg: ldtr 63
+
+endabi: x86_64
+
+beginabi: m68k
+frame_interface: 3
+initial_reg_value: 1035 # DW_FRAME_SAME_VAL
+reg_table_size: 66 # more than large enough, hopefully.
+cfa_reg: 1436 # DW_FRAME_CFA_COL3
+same_val_reg: 1035
+undefined_val_reg: 1034
+
+reg: d0 0
+reg: d1 1
+reg: d2 2
+reg: d3 3
+reg: d4 4
+reg: d5 5
+reg: d6 6
+reg: d7 7
+
+reg: a0 8
+reg: a1 9
+reg: a2 10
+reg: a3 11
+reg: a4 12
+reg: a5 13
+reg: a6 14
+reg: sp 15
+
+reg: fp0 16
+reg: fp1 17
+reg: fp2 18
+reg: fp3 19
+reg: fp4 20
+reg: fp5 21
+reg: fp6 22
+reg: pc 23
+
+endabi: m68k
+
+# Demonstrates use of address_size and includeabi keywords.
+# address_size is useful when an Elf64 object has DWARF2
+# 32bit (4 byte) address-size frame data (which has no address_size field)
+# and no .debug_info section to provide the 32bit address size.
+beginabi: ppc32bitaddress
+address_size: 4
+includeabi: ppc
+endabi: ppc32bitaddress
+
+beginabi: ppc
+# This abi defined Oct 2008 based on:
+# http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html
+frame_interface: 3
+# abi dwarf table uses up thru 1155.
+# As of Oct 2008, the only ABI requiring a higher
+# DW_FRAME_SAME_VAL and DW_FRAME_CFA_COL3.
+initial_reg_value: 1235 # DW_FRAME_SAME_VAL
+cfa_reg: 1436 # DW_FRAME_CFA_COL3
+same_val_reg: 1235
+undefined_val_reg: 1234
+reg_table_size: 1200
+
+reg: r0 0
+reg: f0 32
+reg: f1 33
+reg: f2 34
+reg: f3 35
+reg: f4 36
+reg: f5 37
+reg: f6 38
+reg: f7 39
+reg: f8 40
+reg: f9 41
+reg: f10 42
+reg: f11 43
+reg: f12 44
+reg: f13 45
+reg: f14 46
+reg: f16 47
+reg: f17 48
+reg: f18 49
+reg: f19 50
+reg: f20 51
+reg: f21 52
+reg: f22 53
+reg: f23 54
+reg: f24 55
+reg: f25 56
+reg: f26 57
+reg: f27 58
+reg: f28 59
+reg: f29 60
+reg: f30 62
+reg: f31 63
+reg: cr 64
+reg: fpcsr 65
+# spr0 is also called MQ
+reg: spr0 100
+# spr1 is also called XER
+reg: spr1 101
+# spr4 also called rtcu
+reg: spr4 104
+# spr5 also called rtcl
+reg: spr5 105
+#spr8 also called LR
+reg: spr8 108
+# spr9 also called ctr
+reg: spr9 109
+reg: msr 66
+reg: sr0 70
+reg: sr1 71
+reg: sr2 72
+reg: sr3 73
+reg: sr4 74
+reg: sr5 75
+reg: sr6 76
+reg: sr7 77
+reg: sr8 78
+reg: sr9 79
+
+#dsisr also called spr18
+reg: spr18 118
+# dar also called spr19
+reg: spr19 119
+#dec also called spr22
+reg: spr22 122
+#sdr1 also called spr25
+reg: spr25 125
+#srr0 also called spr26
+reg: spr26 126
+#srr1 also called spr27
+reg: spr27 127
+
+#vrsave also called spr256
+reg: spr256 356
+#sprg0 also called spr272
+reg: spr272 372
+#sprg1 also called spr273
+reg: spr273 373
+#sprg2 also called spr274
+reg: spr274 374
+#sprg3 also called spr275
+reg: spr275 375
+#asr also called spr280
+reg: spr280 380
+#ear also called spr282
+reg: spr282 382
+#tb also called spr284
+reg: spr284 384
+#tbu also called spr285
+reg: spr285 385
+#pvr also called spr287
+reg: spr287 387
+#ibat0u also called spr528
+reg: spr528 628
+#ibat0l also called spr529
+reg: spr529 629
+#ibat1u also called spr530
+reg: spr530 630
+#ibat1l also called spr531
+reg: spr531 631
+#ibat2u also called spr532
+reg: spr532 632
+#ibat2l also called spr533
+reg: spr533 633
+#ibat3u also called spr534
+reg: spr534 634
+#ibat3l also called spr535
+reg: spr535 635
+#dbat0u also called spr536
+reg: spr536 636
+#dbat0l also called spr537
+reg: spr537 637
+#dbat1u also called spr538
+reg: spr538 638
+#dbat1l also called spr539
+reg: spr539 639
+#dbat2u also called spr540
+reg: spr540 640
+#dbat2l also called spr541
+reg: spr541 641
+#dbat3u also called spr542
+reg: spr542 642
+#dbat3l also called spr543
+reg: spr543 643
+
+#hid0 also called spr1008
+reg: spr1008 1108
+#hid1 also called spr1009
+reg: spr1009 1109
+#hid2 also called iabr or spr1010
+reg: spr1010 1110
+#hid5 also called dabr or spr1013
+reg: spr1013 1113
+#hid15 also called pir or spr1023
+reg: spr1023 1123
+
+# vector registers 0-31
+reg: vr0 1124
+reg: vr1 1125
+reg: vr2 1126
+reg: vr3 1127
+reg: vr4 1128
+reg: vr5 1129
+reg: vr6 1130
+reg: vr7 1131
+reg: vr8 1132
+reg: vr9 1133
+reg: vr10 1134
+reg: vr11 1135
+reg: vr12 1136
+reg: vr13 1137
+reg: vr14 1138
+reg: vr15 1130
+reg: vr16 1140
+reg: vr17 1141
+reg: vr18 1142
+reg: vr19 1143
+reg: vr20 1144
+reg: vr21 1145
+reg: vr22 1146
+reg: vr23 1147
+reg: vr24 1148
+reg: vr25 1149
+reg: vr26 1150
+reg: vr27 1151
+reg: vr28 1152
+reg: vr29 1153
+reg: vr30 1154
+reg: vr31 1155
+endabi: ppc
+
+# 'Generic 1000 register abi'.
+# This is useful as a 'general' ABI settings for
+# cpus using up to 1000 registers. The register names
+# show as a number, like 'r991'.
+beginabi: generic
+frame_interface: 3
+initial_reg_value: 1035 # DW_FRAME_SAME_VAL
+cfa_reg: 1436 # DW_FRAME_CFA_COL3
+reg_table_size: 1000
+same_val_reg: 1035
+undefined_val_reg: 1034
+reg: r0 0
+endabi: generic
+
+# 'Generic 500 register abi'.
+# This is useful as a 'general' ABI settings for
+# cpus using up to 500 registers. The register names
+# show as a number, like 'r91'.
+beginabi: generic500
+frame_interface: 3
+initial_reg_value: 1035 # DW_FRAME_SAME_VAL
+cfa_reg: 1436 # DW_FRAME_CFA_COL3
+reg_table_size: 500
+same_val_reg: 1035
+undefined_val_reg: 1034
+reg: r0 0
+endabi: generic500
+
+# 'Generic 100 register abi'.
+# This is useful as a 'general' ABI settings for
+# cpus using up to 100 registers. The register names
+# show as a number, like 'r91'.
+beginabi: generic100
+frame_interface: 3
+initial_reg_value: 1035 # DW_FRAME_SAME_VAL
+cfa_reg: 1436 # DW_FRAME_CFA_COL3
+reg_table_size: 100
+same_val_reg: 1035
+undefined_val_reg: 1034
+reg: r0 0
+endabi: generic100
+
+
+beginabi: arm
+frame_interface: 3
+# When using frame_interface: 3 the size of the register
+# table is not fixed. It can be as large as needed.
+reg_table_size: 288
+cfa_reg: 1436 # DW_FRAME_CFA_COL3
+initial_reg_value: 1034
+same_val_reg: 1035
+undefined_val_reg: 1034
+# If the vendor co-processor registers are allowed
+# or other numbers above 287 used then
+# the reg_table_size must be increased and (possibly)
+# the cfa, same_value, undefined_value reg values changed
+# here.
+# r0-r15 are 0 through 15.
+# Numbers 16 through 63 had meaning
+# in some ARM DWARF register mappings.
+reg: s0 64
+reg: s1 65
+reg: s2 66
+reg: s3 67
+reg: s4 68
+reg: s5 69
+reg: s6 70
+reg: s7 71
+reg: s8 72
+reg: s9 73
+reg: s10 74
+reg: s11 75
+reg: s12 76
+reg: s13 77
+reg: s14 78
+reg: s15 79
+reg: s16 80
+reg: s17 81
+reg: s18 82
+reg: s19 83
+reg: s20 84
+reg: s21 85
+reg: s22 86
+reg: s23 87
+reg: s24 88
+reg: s25 89
+reg: s26 90
+reg: s27 91
+reg: s28 92
+reg: s29 93
+reg: s30 94
+reg: s31 95
+reg: f0 96
+reg: f1 97
+reg: f2 98
+reg: f3 99
+reg: f4 100
+reg: f5 101
+reg: f6 102
+reg: f7 103
+reg: wcgr0 104
+reg: wcgr0 105
+reg: wcgr0 106
+reg: wcgr0 107
+reg: wcgr0 108
+reg: wcgr0 109
+reg: wcgr0 110
+reg: wcgr0 111
+reg: wr0 112
+reg: wr1 113
+reg: wr2 114
+reg: wr3 115
+reg: wr4 116
+reg: wr5 117
+reg: wr6 118
+reg: wr7 119
+reg: wr8 120
+reg: wr9 121
+reg: wr10 122
+reg: wr11 123
+reg: wr12 124
+reg: wr13 125
+reg: wr14 126
+reg: wr15 127
+reg: spsr 128
+reg: spsr_fiq 129
+reg: spsr_irq 130
+reg: spsr_abt 131
+reg: spsr_und 132
+reg: spsr_svc 133
+reg: r8_usr 144
+reg: r9_usr 145
+reg: r10_usr 146
+reg: r11_usr 147
+reg: r12_usr 148
+reg: r13_usr 149
+reg: r14_usr 150
+reg: r8_fiq 151
+reg: r9_fiq 152
+reg: r10_fiq 153
+reg: r11_fiq 154
+reg: r12_fiq 155
+reg: r13_fiq 156
+reg: r14_fiq 157
+reg: r13_riq 158
+reg: r14_riq 159
+reg: r14_abt 160
+reg: r13_abt 161
+reg: r14_und 162
+reg: r13_und 163
+reg: r14_svc 164
+reg: r13_svc 165
+reg: wc0 192
+reg: wc1 193
+reg: wc2 192
+reg: wc3 192
+reg: wc4 192
+reg: wc5 197
+reg: wc6 198
+reg: wc7 199
+reg: d0 256
+reg: d1 257
+reg: d2 258
+reg: d3 259
+reg: d4 260
+reg: d5 261
+reg: d6 262
+reg: d7 263
+reg: d8 264
+reg: d9 265
+reg: d10 266
+reg: d11 267
+reg: d12 268
+reg: d13 269
+reg: d14 270
+reg: d15 271
+reg: d16 272
+reg: d17 273
+reg: d18 274
+reg: d19 275
+reg: d20 266
+reg: d21 277
+reg: d22 278
+reg: d23 279
+reg: d24 280
+reg: d25 281
+reg: d26 282
+reg: d27 283
+reg: d28 284
+reg: d29 285
+reg: d30 286
+reg: d31 287
+# End of abi definition.
+endabi: arm
+
diff --git a/dwarfdump2/dwconf.cc b/dwarfdump2/dwconf.cc
new file mode 100644
index 0000000..b484a93
--- /dev/null
+++ b/dwarfdump2/dwconf.cc
@@ -0,0 +1,1291 @@
+/*
+ Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2009-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/dwconf.c,v 1.4 2006/04/18 18:05:57 davea Exp $ */
+
+
+#include "globals.h"
+#include <vector>
+#include <ctype.h>
+#include "dwconf.h"
+using std::string;
+using std::cerr;
+using std::cout;
+using std::endl;
+
+// The nesting level is arbitrary, 2 should suffice.
+// But at least this prevents an infinite loop.
+#define MAX_NEST_LEVEL 3
+
+
+
+struct token_s {
+ token_s() {};
+ ~token_s() {};
+ const char *c_str() { return tk_data.c_str(); };
+ string tk_data;
+};
+enum linetype_e {
+ LT_ERROR,
+ LT_COMMENT,
+ LT_BLANK,
+ LT_BEGINABI,
+ LT_REG,
+ LT_FRAME_INTERFACE,
+ LT_CFA_REG,
+ LT_INITIAL_REG_VALUE,
+ LT_SAME_VAL_REG,
+ LT_UNDEFINED_VAL_REG,
+ LT_REG_TABLE_SIZE,
+ LT_ADDRESS_SIZE,
+ LT_INCLUDEABI,
+ LT_ENDABI
+};
+
+struct comtable_s {
+ enum linetype_e type;
+ string name;
+};
+
+/* Count errors found in this scan of the configuration file. */
+static int errcount = 0;
+
+static string name_begin_abi("beginabi:");
+static string name_reg("reg:");
+static string name_frame_interface("frame_interface:");
+static string name_cfa_reg("cfa_reg:");
+static string name_initial_reg_value("initial_reg_value:");
+static string name_same_val_reg("same_val_reg:");
+static string name_undefined_val_reg("undefined_val_reg:");
+static string name_reg_table_size("reg_table_size:");
+static string name_address_size("address_size:");
+static string name_includeabi("includeabi:");
+static string name_endabi("endabi:");
+
+static struct comtable_s comtable[] = {
+ {LT_BEGINABI, name_begin_abi},
+ {LT_REG, name_reg},
+ {LT_FRAME_INTERFACE, name_frame_interface},
+ {LT_CFA_REG, name_cfa_reg},
+ {LT_INITIAL_REG_VALUE, name_initial_reg_value},
+ {LT_SAME_VAL_REG,name_same_val_reg},
+ {LT_UNDEFINED_VAL_REG,name_undefined_val_reg},
+ {LT_REG_TABLE_SIZE, name_reg_table_size},
+ {LT_ADDRESS_SIZE, name_address_size},
+ {LT_INCLUDEABI, name_includeabi},
+ {LT_ENDABI, name_endabi},
+};
+static unsigned size_of_comtable = sizeof(comtable) / sizeof(comtable[0]);
+
+struct conf_internal_s {
+ conf_internal_s(struct dwconf_s *out): beginabi_lineno(0),
+ frame_interface_lineno(0), initial_reg_value_lineno(0),
+ reg_table_size_lineno(0),address_size_lineno(0),
+ same_val_reg_lineno(0),
+ undefined_val_reg_lineno(0), cfa_reg_lineno(0),
+ regcount(0),
+ conf_out(out),conf_defaults(0) {};
+ ~conf_internal_s() {};
+ unsigned long beginabi_lineno;
+ unsigned long frame_interface_lineno;
+ unsigned long initial_reg_value_lineno;
+ unsigned long reg_table_size_lineno;
+ unsigned long address_size_lineno;
+ unsigned long same_val_reg_lineno;
+ unsigned long undefined_val_reg_lineno;
+ unsigned long cfa_reg_lineno;
+ unsigned long regcount;
+ std::string conf_name_used;
+ struct dwconf_s *conf_out;
+ std::string conf_named_used;
+ const char ** conf_defaults;
+private:
+ // Do not use this, not implemented.
+ conf_internal_s();
+};
+
+
+
+static FILE *find_a_file(const string &named_file, const char **defaults,
+ string & name_used);
+static bool find_abi_start(FILE * stream, const string &abi_name, long *offset,
+ unsigned long *lineno_out);
+static bool parse_abi(FILE * stream, const std::string &fname,
+ const std::string &abiname,
+ struct conf_internal_s *out, unsigned long lineno,unsigned nestlevel);
+static char * get_token(char *cp, token_s *tok);
+
+
+
+
+
+/* This finds a dwarfdump.conf file and
+ then parses it. It updates
+ conf_out as appropriate.
+
+ This finds the first file (looking in a set of places)
+ with that name. It then looks for the right ABI entry.
+ If the first file it finds does not have that ABI entry it
+ gives up.
+
+ It would also be reasonable to search every 'dwarfdump.conf'
+ it finds for the abi. But we stop at the first dwarfdump.conf
+ we find.
+
+ This is the internal call to read the configure file.
+ Implements a crude 'includeabi' feature.
+
+ Returns the number of errors found.
+*/
+int
+find_conf_file_and_read_config_inner(const string &named_file,
+ const string &named_abi,
+ struct conf_internal_s *conf_internal,
+ unsigned nest_level)
+{
+
+ errcount = 0;
+
+ string name_used;
+ FILE *conf_stream = find_a_file(named_file,
+ conf_internal->conf_defaults, name_used);
+ if (!conf_stream) {
+ ++errcount;
+ cout << "dwarfdump found no file \"" <<
+ named_file << "\"!"<< endl;
+ cout << "(add options -v -v to see what file names tried)"<<
+ endl;
+ return errcount;
+ }
+ if (verbose > 1) {
+ cout << "dwarfdump using configuration file " <<
+ name_used << endl;
+ }
+ conf_internal->conf_name_used = name_used;
+
+ long offset = 0;
+ unsigned long lineno = 0;
+ bool res = find_abi_start(conf_stream, named_abi, &offset, &lineno);
+ if (!res) {
+ ++errcount;
+ cout << "dwarfdump found no ABI " <<
+ named_abi << " in file " <<
+ name_used << "." <<endl;
+ return errcount;
+ }
+ int seekres = fseek(conf_stream, offset, SEEK_SET);
+ if (seekres != 0) {
+ ++errcount;
+ cout << "dwarfdump seek to " <<
+ offset << " offset in " <<
+ name_used <<
+ " failed!" << endl;
+ return errcount;
+ }
+ parse_abi(conf_stream, name_used, named_abi, conf_internal, lineno,
+ nest_level);
+ fclose(conf_stream);
+ return errcount;
+}
+
+// This is the exteral-facing call to read the configure file.
+int
+find_conf_file_and_read_config(const string &named_file,
+ const string &named_abi,
+ const char **defaults,
+ struct dwconf_s *conf_out)
+{
+ // The cf_regs are to be set below, not from
+ // the default set, so clear the exsting data out.
+ conf_out->cf_regs.clear();
+ // Ensure a reasonable minimum vector size.
+ conf_out->cf_regs.resize(100);
+ conf_internal_s conf_internal(conf_out);
+ conf_internal.conf_defaults = defaults;
+
+ int res = find_conf_file_and_read_config_inner(named_file,
+ named_abi,
+ &conf_internal,0);
+ return res;
+}
+
+/* Given path strings, attempt to make a canonical file name:
+ that is, avoid superfluous '/' so that no
+ '//' (or worse) is created in the output. The path components
+ are to be separated so at least one '/'
+ is to appear between the two 'input strings' when
+ creating the output. */
+static bool
+canonical_append(string &target,
+ const string &first_string, const string &second_string)
+{
+ // Do not take any ending /
+ size_t firstlen = first_string.size();
+ for (; firstlen > 0 && first_string[firstlen - 1] == '/';
+ --firstlen) {
+ }
+
+ // Do not take any leading /
+ unsigned secondskipto = 0;
+ for (; second_string[secondskipto] == '/'; ++secondskipto) {
+ }
+
+ target = first_string.substr(0,firstlen) + string("/") +
+ second_string.substr(secondskipto);
+ return true;
+}
+
+#ifdef BUILD_FOR_TEST
+struct canap_s {
+ const char *res_exp;
+ const char *first;
+ const char *second;
+} canap[] = {
+ {
+ "ab/c", "ab", "c"}, {
+ "ab/c", "ab/", "c"}, {
+ "ab/c", "ab", "/c"}, {
+ "ab/c", "ab////", "/////c"}, {
+ "ab/", "ab", ""}, {
+ "ab/", "ab////", ""}, {
+ "ab/", "ab////", ""}, {
+ "/a", "", "a"}, {
+ 0, "/abcdefgbijkl", "pqrstuvwxyzabcd"}, {
+ 0, 0, 0}
+};
+static void
+test_canonical_append(void)
+{
+ unsigned failcount = 0;
+
+ cout <<"Entry test_canonical_append" << endl;
+ for (unsigned i = 0;; ++i) {
+
+ if (canap[i].first == 0 && canap[i].second == 0)
+ break;
+
+ string targ;
+ bool ok = canonical_append(targ, canap[i].first,
+ canap[i].second);
+ if (ok) {
+ if (canap[i].res_exp == 0) {
+ /* GOOD */
+ cout <<"PASS " << i <<endl;
+ } else {
+ ++failcount;
+ cout << "FAIL: entry " << i <<
+ " wrong, expected " << canap[i].res_exp <<
+ " got NULL " << endl;
+ }
+ } else {
+ // Impossible now.
+ ++failcount;
+ cout << "FAIL: entry " << i <<
+ " wrong, expected an ok result " << endl;
+ }
+ }
+ cout << "FAIL count " << failcount << endl;
+
+}
+#endif /* BUILD_FOR_TEST */
+/* Try to find a file as named and open for read.
+ We treat each name as a full name, we are not
+ combining separate name and path components.
+ This is an arbitrary choice...
+
+ The defaults are listed in dwarfdump.c in the array
+ config_file_defaults[].
+*/
+static FILE *
+find_a_file(const std::string &named_file, const char **defaults,
+ string & name_used_out)
+{
+ string lname = named_file;
+ const char *type = "rw";
+
+#ifdef BUILD_FOR_TEST
+ test_canonical_append();
+#endif /* BUILD_FOR_TEST */
+
+ if (!lname.empty()) {
+ /* Name given, just assume it is fully correct, try no other. */
+ if (verbose > 1) {
+ cout << "dwarfdump looking for configuration as " <<
+ lname << endl;
+ }
+ FILE *fin = fopen(lname.c_str(), type);
+ if (fin) {
+ name_used_out = lname;
+ return fin;
+ }
+ return 0;
+ }
+ /* No name given, find a default, if we can. */
+ for (unsigned i = 0; defaults[i]; ++i) {
+ string lname2 = defaults[i];
+ if (strncmp(lname2.c_str(), "HOME/", 5) == 0) {
+ char *homedir = getenv("HOME");
+ if (homedir) {
+ string tname;
+ canonical_append(tname,homedir, lname2.substr(5));
+ lname2 = tname;
+ }
+ }
+ if (verbose > 1) {
+ cout << "dwarfdump looking for configuration as " <<
+ lname2 << endl;
+ }
+ FILE *fin = fopen(lname2.c_str(), type);
+ if (fin) {
+ name_used_out = lname2;
+ return fin;
+ }
+ }
+ return 0;
+}
+
+/* Start at a token begin, see how long it is,
+ return length. */
+unsigned
+find_token_len(char *cp)
+{
+ unsigned len = 0;
+ for (; *cp; ++cp) {
+ if (isspace(*cp)) {
+ return len;
+ }
+ if (*cp == '#') {
+ return len; /* begins comment */
+ }
+ ++len;
+ }
+ return len;
+}
+
+/*
+ Skip past all whitespace: the only code that even knows
+ what whitespace is.
+*/
+static char *
+skipwhite(char *cp)
+{
+ for (; *cp; ++cp) {
+ if (!isspace(*cp)) {
+ return cp;
+ }
+ }
+ return cp;
+}
+
+/* Return TRUE if ok. FALSE if find more tokens.
+ Emit error message if error. */
+static bool
+ensure_has_no_more_tokens(char *cp, const string &fname, unsigned long lineno)
+{
+ token_s tok ;
+ get_token(cp, &tok);
+ if (!tok.tk_data.empty() ) {
+ cout << "dwarfdump.conf error: " <<
+ "extra characters after command operands, found " <<
+ "\"" << tok.tk_data << "\" in " << fname <<
+ " line " << lineno << endl;
+ ++errcount;
+ return false;
+ }
+ return true;
+}
+
+
+/* There may be many beginabi: lines in a dwarfdump.conf file,
+ find the one we want and return its file offset. */
+static bool
+find_abi_start(FILE * stream, const string &abi_name,
+ long *offset, unsigned long *lineno_out)
+{
+ char buf[100];
+ unsigned long lineno = 0;
+
+ for (; !feof(stream);) {
+
+ long loffset = ftell(stream);
+
+ char *line = fgets(buf, sizeof(buf), stream);
+ ++lineno;
+ if (!line) {
+ ++errcount;
+ return false;
+ }
+
+ token_s tok;
+ line = get_token(buf, &tok);
+
+ if (tok.tk_data != name_begin_abi ) {
+ continue;
+ }
+ token_s tok2;
+ get_token(line,&tok2);
+ if (tok2.tk_data != abi_name) {
+ continue;
+ }
+
+ *offset = loffset;
+ *lineno_out = lineno;
+ return true;
+ }
+
+ ++errcount;
+ return false;
+}
+
+/* The tokenizer for our simple parser. */
+static char *
+get_token(char *cp, token_s *outtok)
+{
+ char *lcp = skipwhite(cp);
+ unsigned tlen = find_token_len(lcp);
+
+ if (tlen > 0) {
+ string s(lcp);
+ outtok->tk_data = s.substr(0,tlen);
+ } else {
+ outtok->tk_data = "";
+ }
+ return lcp + tlen;
+
+}
+
+/* Given a line of the table, determine if it is a command
+ or not, and if a command, which one is it.
+ Return LT_ERROR if it's not recognized. */
+static enum linetype_e
+which_command(char *cp, struct comtable_s **tableentry)
+{
+
+ if (*cp == '#') {
+ return LT_COMMENT;
+ }
+ if (!*cp) {
+ return LT_BLANK;
+ }
+ token_s tok;
+ get_token(cp, &tok);
+ for (unsigned i = 0; i < size_of_comtable; ++i) {
+ if (tok.tk_data == comtable[i].name) {
+ *tableentry = &comtable[i];
+ return comtable[i].type;
+ }
+ }
+ return LT_ERROR;
+}
+
+/* We are promised it's an abiname: command
+ find the name on the line. */
+static bool
+parsebeginabi(char *cp, const string &fname, const string &abiname,
+ unsigned long lineno, struct comtable_s *comtab)
+{
+ size_t clen = comtab->name.size();
+ size_t abinamelen = abiname.size();
+
+ cp = cp + clen + 1;
+ cp = skipwhite(cp);
+ token_s tok;
+ get_token(cp, &tok);
+ if (tok.tk_data.size() != abinamelen ||
+ strncmp(cp, abiname.c_str(), abinamelen) != 0) {
+ ++errcount;
+ cout << "dwarfdump internal error: mismatch " <<
+ cp << " with " << tok.tk_data << " " <<
+ fname << " line " << lineno <<endl;
+ return false;
+ }
+ bool res = ensure_has_no_more_tokens(cp + tok.tk_data.size(),
+ fname, lineno);
+ return res;
+}
+
+/* This expands register names as required, but does not
+ ensure no names duplicated. */
+static void
+add_to_reg_table(struct dwconf_s *conf,
+ const string &rname, unsigned long rval,
+ const string &fname,
+ unsigned long lineno)
+{
+ if( rval >= conf->cf_regs.size()) {
+ conf->cf_regs.resize(rval+1);
+ }
+ conf->cf_regs[rval] = rname;
+ return;
+}
+
+/* Our input is supposed to be a number.
+ Determine the value (and return it) or generate an error message. */
+static int
+make_a_number(const string &cmd, const string &filename,
+ unsigned long lineno, struct token_s *tok, unsigned long *val_out)
+{
+ char *endnum = 0;
+ unsigned long val = 0;
+ const char *begin = tok->tk_data.c_str();
+ val = strtoul(begin, &endnum, 0);
+ if (val == 0 && endnum == begin) {
+ ++errcount;
+ cout << "dwarfdump.conf error: " <<
+ cmd << " missing register number (\"" <<
+ tok->tk_data << "\" not valid) " <<
+ filename << " line " << lineno <<endl;
+ return false;
+ }
+ if (endnum != (begin + tok->tk_data.size())) {
+ ++errcount;
+ cout << "dwarfdump.conf error: " <<
+ cmd << " Missing register number (\"" <<
+ tok->tk_data << "\" not valid) " <<
+ filename << " line " << lineno <<endl;
+ return false;
+ }
+ *val_out = val;
+ return true;
+
+
+
+}
+
+/* We are guaranteed it's a reg: command, so parse that command
+ and record the interesting data. */
+static bool
+parsereg(char *cp, const string &fname, unsigned long lineno,
+ struct conf_internal_s *conf, struct comtable_s *comtab)
+{
+ size_t clen = comtab->name.size();
+ token_s regnum;
+ token_s tokreg;
+
+ cp = cp + clen + 1;
+ cp = get_token(cp, &tokreg);
+ cp = get_token(cp, &regnum);
+ if (tokreg.tk_data.empty()) {
+ ++errcount;
+ cout << "dwarfdump.conf error: reg: missing register name " <<
+ fname << " line " << lineno <<endl;
+ return false;
+
+ }
+ if (regnum.tk_data.empty()) {
+ ++errcount;
+ cout << "dwarfdump.conf error: reg: Missing register name " <<
+ fname << " line " << lineno <<endl;
+ return false;
+ }
+
+ unsigned long val = 0;
+ bool ok = make_a_number(comtab->name, fname, lineno, &regnum, &val);
+
+ if (!ok) {
+ ++errcount;
+ return false;
+ }
+
+ add_to_reg_table(conf->conf_out, tokreg.tk_data, val, fname, lineno);
+
+ {
+ bool res = ensure_has_no_more_tokens(cp, fname, lineno);
+
+ return res;
+ }
+}
+
+/* We are guaranteed it's an frame_interface: command.
+ Parse it and record the value data. */
+static bool
+parseframe_interface(char *cp, const string &fname, unsigned long lineno,
+ struct conf_internal_s *conf, struct comtable_s *comtab)
+{
+ size_t clen = comtab->name.size();
+ cp = cp + clen + 1;
+ token_s tok;
+ cp = get_token(cp, &tok);
+ if (tok.tk_data.empty()) {
+ ++errcount;
+ cout << "dwarfdump.conf error: " <<
+ comtab->name <<
+ " missing interface number " <<
+ fname << " line " << lineno << endl;
+ return false;
+ }
+
+ unsigned long val = 0;
+ bool ok = make_a_number(comtab->name, fname, lineno, &tok, &val);
+
+ if (!ok) {
+ ++errcount;
+ return false;
+ }
+ if (val != 2 && val != 3) {
+ ++errcount;
+ cout << "dwarfdump.conf error: " <<
+ comtab->name <<
+ " only interface numbers 2 or 3 are allowed, not " <<
+ val <<
+ ". " <<
+ fname << " line " << lineno << endl;
+ return false;
+ }
+
+ conf->conf_out->cf_interface_number = (int) val;
+ bool res = ensure_has_no_more_tokens(cp, fname, lineno);
+ return res;
+}
+
+/* We are guaranteed it's a cfa_reg: command. Parse it
+ and record the important data. */
+static bool
+parsecfa_reg(char *cp, const string &fname, unsigned long lineno,
+ struct conf_internal_s *conf, struct comtable_s *comtab)
+{
+ size_t clen = comtab->name.size();
+ token_s tok;
+ unsigned long val = 0;
+ bool ok = false;
+
+ cp = cp + clen + 1;
+ cp = get_token(cp, &tok);
+ if (tok.tk_data.empty()) {
+ ++errcount;
+ cout << "dwarfdump.conf error: " <<
+ comtab->name <<
+ " missing cfa_reg number " <<
+ fname << " line " << lineno << endl;
+ return false;
+ }
+
+ ok = make_a_number(comtab->name, fname, lineno, &tok, &val);
+
+ if (!ok) {
+ ++errcount;
+ return false;
+ }
+ conf->conf_out->cf_cfa_reg = (int) val;
+ bool res = ensure_has_no_more_tokens(cp, fname, lineno);
+ return res;
+}
+
+
+/* We are guaranteed it's an initial_reg_value: command,
+ parse it and put the reg value where it will be remembered.
+*/
+static bool
+parseinitial_reg_value(char *cp, const string &fname,
+ unsigned long lineno,
+ struct conf_internal_s *conf, struct comtable_s *comtab)
+{
+ size_t clen = comtab->name.size();
+ cp = cp + clen + 1;
+ struct token_s tok;
+ cp = get_token(cp, &tok);
+ if (tok.tk_data.empty()) {
+ ++errcount;
+ cout << "dwarfdump.conf error: " <<
+ comtab->name <<
+ " missing initial reg value " <<
+ fname << " line " << lineno << endl;
+ return false;
+ }
+
+ unsigned long val = 0;
+ bool ok = make_a_number(comtab->name, fname, lineno, &tok, &val);
+
+ if (!ok) {
+ ++errcount;
+ return false;
+ }
+ conf->conf_out->cf_initial_rule_value = (int) val;
+ bool res = ensure_has_no_more_tokens(cp, fname, lineno);
+ return res;
+}
+/* We are guaranteed it's an initial_reg_value: command,
+ parse it and put the reg value where it will be remembered. */
+static bool
+parsesame_val_reg(char *cp, const string &fname,
+ unsigned long lineno,
+ struct conf_internal_s *conf, struct comtable_s *comtab)
+{
+ size_t clen = comtab->name.size();
+ cp = cp + clen + 1;
+ struct token_s tok;
+ cp = get_token(cp, &tok);
+ if (tok.tk_data.empty()) {
+ ++errcount;
+ cout << "dwarfdump.conf error: " <<
+ comtab->name <<
+ " missing same_val_reg value " <<
+ fname << " line " << lineno << endl;
+ return false;
+ }
+
+ unsigned long val = 0;
+ bool ok = make_a_number(comtab->name, fname, lineno, &tok, &val);
+
+ if (!ok) {
+ ++errcount;
+ return false;
+ }
+ conf->conf_out->cf_same_val = (int) val;
+ bool res = ensure_has_no_more_tokens(cp, fname, lineno);
+ return res;
+}
+/* We are guaranteed it's an initial_reg_value: command,
+ parse it and put the reg value where it will be remembered. */
+static bool
+parseundefined_val_reg(char *cp, const string &fname,
+ unsigned long lineno,
+ struct conf_internal_s *conf, struct comtable_s *comtab)
+{
+ size_t clen = comtab->name.size();
+ cp = cp + clen + 1;
+ struct token_s tok;
+ cp = get_token(cp, &tok);
+ if (tok.tk_data.empty()) {
+ ++errcount;
+ cout << "dwarfdump.conf error: " <<
+ comtab->name <<
+ " missing undefined_val_reg value " <<
+ fname << " line " << lineno << endl;
+ return false;
+ }
+
+ unsigned long val = 0;
+ bool ok = make_a_number(comtab->name, fname, lineno, &tok, &val);
+
+ if (!ok) {
+ ++errcount;
+ return false;
+ }
+ conf->conf_out->cf_undefined_val = (int) val;
+ bool res = ensure_has_no_more_tokens(cp, fname, lineno);
+ return res;
+}
+
+
+
+
+/* We are guaranteed it's a table size command, parse it
+ and record the table size.
+*/
+static bool
+parsereg_table_size(char *cp, const string &fname, unsigned long lineno,
+ struct conf_internal_s *conf, struct comtable_s *comtab)
+{
+ size_t clen = comtab->name.size();
+ token_s tok;
+
+ cp = cp + clen + 1;
+ cp = get_token(cp, &tok);
+ if (tok.tk_data.empty()) {
+ ++errcount;
+ cout << "dwarfdump.conf error: " <<
+ comtab->name <<
+ " missing reg table size value " <<
+ fname << " line " << lineno << endl;
+ return false;
+ }
+
+ unsigned long val = 0;
+ bool ok = make_a_number(comtab->name, fname, lineno, &tok, &val);
+
+ if (!ok) {
+ ++errcount;
+ return false;
+ }
+ conf->conf_out->cf_table_entry_count = (unsigned long) val;
+ bool res = ensure_has_no_more_tokens(cp, fname, lineno);
+ return res;
+}
+/* We are guaranteed it's an address size command, parse it
+ and record the address size.
+*/
+static bool
+parseaddress_size(char *cp, const string &fname, unsigned long lineno,
+ struct conf_internal_s *conf, struct comtable_s *comtab)
+{
+ size_t clen = comtab->name.size();
+ token_s tok;
+
+ cp = cp + clen + 1;
+ cp = get_token(cp, &tok);
+ if (tok.tk_data.empty()) {
+ ++errcount;
+ cout << "dwarfdump.conf error: " <<
+ comtab->name <<
+ " missing address size value " <<
+ fname << " line " << lineno << endl;
+ return false;
+ }
+
+ unsigned long val = 0;
+ bool ok = make_a_number(comtab->name, fname, lineno, &tok, &val);
+
+ if (!ok) {
+ ++errcount;
+ return false;
+ }
+ conf->conf_out->cf_address_size = (unsigned long) val;
+ bool res = ensure_has_no_more_tokens(cp, fname, lineno);
+ return res;
+}
+
+
+
+/* We are guaranteed it's an endabi: command, parse it and
+ check we have the right abi.
+*/
+static bool
+parseendabi(char *cp, const string &fname,
+ const string &abiname, unsigned long lineno,
+ struct comtable_s *comtab)
+{
+ size_t clen = comtab->name.size();
+
+
+ cp = cp + clen + 1;
+ struct token_s tok;
+ cp = get_token(cp, &tok);
+ if (abiname != tok.tk_data) {
+ ++errcount;
+ cout << comtab->name <<
+ " error: mismatch abi name " <<
+ tok.tk_data << " (here) vs. " <<
+ abiname <<
+ " (beginabi:) " <<
+ fname << " line " << lineno << endl;
+ return false;
+ }
+ bool res = ensure_has_no_more_tokens(cp, fname, lineno);
+ return res;
+}
+
+static int
+parseincludeabi(char *cp,const string &fname,unsigned long lineno,
+ std::string &abiname_out,struct comtable_s *comtab)
+{
+ size_t clen = comtab->name.size();
+ struct token_s tok;
+ cp = cp + clen + 1;
+ cp = get_token(cp,&tok);
+ abiname_out = tok.tk_data;
+ bool res = ensure_has_no_more_tokens(cp, fname, lineno);
+ return res;
+}
+
+
+
+
+
+/* Return TRUE if we succeeded and filed in *out.
+ Return FALSE if we failed (and fill in nothing).
+ beginabi: <abiname>
+ reg: <regname> <dwarf regnumber>
+ frame_interface: <integer value 2 or 3>
+ cfa_reg: <number>
+ initial_reg_value: <number: normally 1034 or 1035 >
+ same_value 'reg number' : <number: normally 1034 >
+ undefined_value 'reg number' : <number: normally 1035 >
+ reg_table_size: <size of table>
+ endabi: <abiname>
+
+ We are positioned at the start of a beginabi: line when
+ called.
+
+*/
+static bool
+parse_abi(FILE * stream, const string &fname, const string &abiname,
+ struct conf_internal_s *conf_internal, unsigned long lineno,
+ unsigned int nest_level)
+{
+ struct dwconf_s *localconf = conf_internal->conf_out;
+
+ if( nest_level > MAX_NEST_LEVEL) {
+ ++errcount;
+ cout <<"dwarfdump.conf: includeabi nest too deep in " <<
+ fname << " at line " << lineno<<endl;
+ return false;
+ }
+
+ for (; !feof(stream);) {
+
+ char *line = 0;
+ char buf[1000];
+ /* long loffset = ftell(stream); */
+ line = fgets(buf, sizeof(buf), stream);
+ if (!line) {
+ ++errcount;
+ cout << "dwarfdump: end of file or error before endabi: in "<<
+ fname << ", line " << lineno << endl;
+ return false;
+ }
+ ++lineno;
+ line = skipwhite(line);
+ // comtabp points to the table entry
+ // of interest (identified by which_command()).
+ struct comtable_s *comtabp = 0;
+ int comtype = which_command(line, &comtabp);
+ switch (comtype) {
+ case LT_ERROR:
+ ++errcount;
+ cout << "dwarfdump: Unknown text in "<<
+ fname << " is \"" <<
+ line << "\" at line " << lineno << endl;
+ break;
+ case LT_COMMENT:
+ break;
+ case LT_BLANK:
+ break;
+ case LT_BEGINABI:
+ if (conf_internal->beginabi_lineno > 0 &&
+ nest_level == 0) {
+ ++errcount;
+ cout << "dwarfdump: Encountered beginabi: when not expected. "
+ << fname <<
+ " line " << lineno <<
+ " previous beginabi line " <<
+ conf_internal->beginabi_lineno << endl;
+ }
+ conf_internal->beginabi_lineno = lineno;
+ parsebeginabi(line, fname, abiname, lineno, comtabp);
+ break;
+
+ case LT_REG:
+ parsereg(line, fname, lineno, conf_internal, comtabp);
+ conf_internal->regcount++;
+ break;
+ case LT_FRAME_INTERFACE:
+ if (conf_internal->frame_interface_lineno > 0) {
+ ++errcount;
+ cout << "dwarfdump: Encountered duplicate frame_interface: "
+ << fname <<
+ " line " << lineno <<
+ " previous frame_interface: line " <<
+ conf_internal->frame_interface_lineno << endl;
+ }
+ conf_internal->frame_interface_lineno = lineno;
+ parseframe_interface(line, fname,
+ lineno, conf_internal, comtabp);
+ break;
+ case LT_CFA_REG:
+ if (conf_internal->cfa_reg_lineno > 0) {
+ ++errcount;
+ cout << "dwarfdump: Encountered duplicate cfa_reg: "
+ << fname <<
+ " line " << lineno <<
+ " previous cfa_reg line " <<
+ conf_internal->cfa_reg_lineno << endl;
+ }
+ conf_internal->cfa_reg_lineno = lineno;
+ parsecfa_reg(line, fname, lineno, conf_internal, comtabp);
+ break;
+ case LT_INITIAL_REG_VALUE:
+ if (conf_internal->initial_reg_value_lineno > 0) {
+ ++errcount;
+ cout <<
+ "dwarfdump: Encountered duplicate " <<
+ "initial_reg_value: " <<
+ fname <<
+ " line " << lineno <<
+ " previous initial_reg_value: line " <<
+ conf_internal->initial_reg_value_lineno<< endl;
+ }
+ conf_internal->initial_reg_value_lineno = lineno;
+ parseinitial_reg_value(line, fname,
+ lineno,conf_internal, comtabp);
+ break;
+ case LT_SAME_VAL_REG:
+ if (conf_internal->same_val_reg_lineno > 0) {
+ ++errcount;
+ cout <<
+ "dwarfdump: Encountered duplicate " <<
+ "same_val_reg: " <<
+ fname <<
+ " line " << lineno <<
+ " previous same_reg_value: line " <<
+ conf_internal->same_val_reg_lineno << endl;
+ }
+ conf_internal->same_val_reg_lineno = lineno;
+ parsesame_val_reg(line, fname,
+ lineno, conf_internal, comtabp);
+ break;
+ case LT_UNDEFINED_VAL_REG:
+ if (conf_internal->undefined_val_reg_lineno > 0) {
+ ++errcount;
+ cout <<
+ "dwarfdump: Encountered duplicate " <<
+ "undefined_val_reg: " <<
+ fname <<
+ " line " << lineno <<
+ " previous same_val_reg: line " <<
+ conf_internal->same_val_reg_lineno << endl;
+ }
+ conf_internal->undefined_val_reg_lineno = lineno;
+ parseundefined_val_reg(line, fname,
+ lineno, conf_internal, comtabp);
+ break;
+
+ case LT_REG_TABLE_SIZE:
+ if (conf_internal->reg_table_size_lineno > 0) {
+ ++errcount;
+ cout << "dwarfdump: duplicate reg_table_size: "
+ << fname <<
+ " line " << lineno <<
+ " previous reg_table_size: line " <<
+ conf_internal->reg_table_size_lineno << endl;
+ }
+ conf_internal->reg_table_size_lineno = lineno;
+ parsereg_table_size(line, fname,
+ lineno, conf_internal, comtabp);
+ break;
+ case LT_ENDABI:
+ parseendabi(line, fname, abiname, lineno, comtabp);
+
+ if (conf_internal->regcount > localconf->cf_table_entry_count) {
+ ++errcount;
+ cout << "dwarfdump: more registers named than in "
+ << abiname <<
+ " ( " << conf_internal->regcount <<
+ " named vs " << name_reg_table_size <<
+ " " << localconf->cf_table_entry_count <<
+ ") " <<
+ fname << " line " << lineno << endl;
+ }
+
+ return true;
+ case LT_ADDRESS_SIZE:
+ if (conf_internal->address_size_lineno > 0) {
+ ++errcount;
+ cout << "dwarfdump: duplicate address_size:: "
+ << fname <<
+ " line " << lineno <<
+ " previous address_size: line " <<
+ conf_internal->address_size_lineno << endl;
+ }
+ conf_internal->address_size_lineno = lineno;
+ parseaddress_size(line, fname,
+ lineno, conf_internal, comtabp);
+ break;
+ case LT_INCLUDEABI: {
+ std::string abiname_inner;
+ unsigned long abilno = conf_internal->beginabi_lineno;
+ bool ires = parseincludeabi(line,fname,lineno,abiname_inner,
+ comtabp);
+ if (ires == false) {
+ return ires;
+ }
+ // For the nested abi read, the abi line number must be
+ // set as if not-yet-read, and then restored.
+ conf_internal->beginabi_lineno = 0;
+ find_conf_file_and_read_config_inner(conf_internal->conf_name_used,
+ abiname_inner,conf_internal,nest_level+1);
+ conf_internal->beginabi_lineno = abilno;
+ }
+ break;
+ default:
+ cout << "dwarfdump internal error, impossible line type " <<
+ comtype << " " << fname << " " << lineno <<endl;
+ exit(1);
+
+ }
+ }
+ ++errcount;
+ cout << "End of file, no endabi: found. " <<
+ fname << ", line " << lineno << endl;
+ return false;
+}
+
+/* MIPS/IRIX frame register names.
+ For alternate name sets, use dwarfdump.conf or
+ revise dwarf.h and libdwarf.h and this table.
+*/
+static const char *mipsregnames[] = {
+ "cfa",
+ "r1/at", "r2/v0", "r3/v1",
+ "r4/a0", "r5/a1", "r6/a2", "r7/a3",
+ "r8/t0", "r9/t1", "r10/t2", "r11/t3",
+ "r12/t4", "r13/t5", "r14/t6", "r15/t7",
+ "r16/s0", "r17/s1", "r18/s2", "r19/s3",
+ "r20/s4", "r21/s5", "r22/s6", "r23/s7",
+ "r24/t8", "r25/t9", "r26/k0", "r27/k1",
+ "r28/gp", "r29/sp", "r30/s8", "r31",
+
+ "$f0", "$f1",
+ "$f2", "$f3",
+ "$f4", "$f5",
+ "$f6", "$f7",
+ "$f8", "$f9",
+ "$f10", "$f11",
+ "$f12", "$f13",
+ "$f14", "$f15",
+ "$f16", "$f17",
+ "$f18", "$f19",
+ "$f20", "$f21",
+ "$f22", "$f23",
+ "$f24", "$f25",
+ "$f26", "$f27",
+ "$f28", "$f29",
+ "$f30", "$f31",
+ "ra", "slk",
+};
+
+/* Naming a few registers makes printing these just
+ a little bit faster.
+*/
+static const char *genericregnames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
+ "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19",
+ "r20"
+};
+
+/* This is a simple generic set of registers. The
+ table entry count is pretty arbitrary.
+*/
+void
+init_conf_file_data(struct dwconf_s *config_file_data)
+{
+ config_file_data->cf_interface_number = 3;
+ config_file_data->cf_table_entry_count = 100;
+ config_file_data->cf_initial_rule_value = DW_FRAME_UNDEFINED_VAL;
+ config_file_data->cf_cfa_reg = DW_FRAME_CFA_COL3;
+ config_file_data->cf_address_size = 0;
+ config_file_data->cf_same_val = DW_FRAME_SAME_VAL;
+ config_file_data->cf_undefined_val = DW_FRAME_UNDEFINED_VAL;
+ unsigned generic_table_count =
+ sizeof(genericregnames) / sizeof(genericregnames[0]);
+ config_file_data->cf_regs.clear();
+ config_file_data->cf_regs.reserve(generic_table_count);
+ for(unsigned i = 0; i < generic_table_count; ++i) {
+ config_file_data->cf_regs.push_back(genericregnames[i]);
+ }
+}
+
+/* These defaults match MIPS/IRIX ABI defaults, but this
+ function is not actually used.
+ For a 'generic' ABI, see -R or init_conf_file_data().
+ To really get the old MIPS, use '-x abi=mips'.
+ For other ABIs, see -x abi=<whatever>
+ to configure dwarfdump (and libdwarf) frame
+ data reporting at runtime.
+*/
+void
+init_mips_conf_file_data(struct dwconf_s *config_file_data)
+{
+ /* Interface 2 is deprecated, but for testing purposes
+ is acceptable. */
+ config_file_data->cf_interface_number = 2;
+ config_file_data->cf_table_entry_count = DW_REG_TABLE_SIZE;
+ config_file_data->cf_initial_rule_value =
+ DW_FRAME_REG_INITIAL_VALUE;
+ config_file_data->cf_cfa_reg = DW_FRAME_CFA_COL;
+ config_file_data->cf_address_size = 0;
+ config_file_data->cf_same_val = DW_FRAME_SAME_VAL;
+ config_file_data->cf_undefined_val = DW_FRAME_UNDEFINED_VAL;
+ unsigned mips_table_count =
+ sizeof(mipsregnames) / sizeof(mipsregnames[0]);
+ config_file_data->cf_regs.clear();
+ config_file_data->cf_regs.reserve(mips_table_count);
+ for(unsigned i = 0; i < mips_table_count; ++i) {
+ config_file_data->cf_regs.push_back(mipsregnames[i]);
+ }
+ return;
+}
+
+
+/* A 'generic' ABI. For up to 1200 registers.
+*/
+void
+init_generic_config_1200_regs(struct dwconf_s *config_file_data)
+{
+ config_file_data->cf_interface_number = 3;
+ config_file_data->cf_table_entry_count = 1200;
+ /* There is no defined name for cf_initial_rule_value,
+ cf_same_val, or cf_undefined_val in libdwarf.h,
+ these must just be high enough to be higher than
+ any real register number.
+ DW_FRAME_CFA_COL3 must also be higher than any
+ real register number. */
+ config_file_data->cf_initial_rule_value = 1235; /* SAME VALUE */
+ config_file_data->cf_cfa_reg = DW_FRAME_CFA_COL3;
+ config_file_data->cf_address_size = 0;
+ config_file_data->cf_same_val = 1235;
+ config_file_data->cf_undefined_val = 1234;
+ unsigned generic_table_count =
+ sizeof(genericregnames) / sizeof(genericregnames[0]);
+ config_file_data->cf_regs.clear();
+ config_file_data->cf_regs.reserve(generic_table_count);
+ for(unsigned i = 0; i < generic_table_count; ++i) {
+ config_file_data->cf_regs.push_back(genericregnames[i]);
+ }
+}
+
+/* Print the 'right' string for the register we are given.
+ Deal sensibly with the special regs as well as numbers
+ we know and those we have not been told about.
+*/
+void
+print_reg_from_config_data(Dwarf_Signed reg,
+ struct dwconf_s *config_data)
+{
+
+ if (reg == config_data->cf_cfa_reg) {
+ cout << "cfa";
+ return;
+ }
+ if (reg == config_data->cf_undefined_val) {
+ cout << "u";
+ return;
+ }
+ if (reg == config_data->cf_same_val) {
+ cout << "s";
+ return;
+ }
+ if ( reg < 0 ||
+ reg >= config_data->cf_regs.size()) {
+ cout << "r" << reg;
+ return;
+ }
+ const string &name = config_data->cf_regs[reg];
+ if (name.empty()) {
+ /* Can happen, the reg names table can be sparse. */
+ cout << "r" << reg;
+ return;
+ }
+ cout << name;
+ return;
+}
diff --git a/dwarfdump2/dwconf.h b/dwarfdump2/dwconf.h
new file mode 100644
index 0000000..e4f567d
--- /dev/null
+++ b/dwarfdump2/dwconf.h
@@ -0,0 +1,109 @@
+/*
+ Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/dwconf.h,v 1.2 2006/04/18 04:29:39 davea Exp $ */
+
+
+/* Declarations helping configure the frame reader.
+*/
+struct dwconf_s {
+ dwconf_s():cf_interface_number(0),
+ cf_table_entry_count(0),cf_initial_rule_value(0),
+ cf_same_val(0),cf_undefined_val(0), cf_cfa_reg(0),
+ cf_address_size(0) {};
+ ~dwconf_s() {};
+
+ std::string cf_config_file_path;
+ std::string cf_abi_name;
+
+ // 2 for old, 3 for frame interface 3. 2 means use the old
+ // mips-abi-oriented frame interface. 3 means use the new
+ // DWARF3-capable and configureable-abi interface.
+
+ // Now, anyone who revises dwarf.h and libdwarf.h to match their
+ // abi-of-interest will still be able to use cf_interface_number 2
+ // as before. But most folks don't update those header files and
+ // instead of making *them* configurable we make dwarfdump (and
+ // libdwarf) configurable sufficiently to print frame information
+ // sensibly.
+ unsigned cf_interface_number;
+
+ // The number of table rules , aka columns. For MIPS/IRIX is 66.
+ unsigned long cf_table_entry_count;
+
+ // Array of cf_table_entry_count reg names. Names not filled in
+ // from dwarfdump.conf have empty value.
+
+ std::vector<std::string> cf_regs;
+
+ // The 'default initial value' when intializing a table. for MIPS
+ // is DW_FRAME_SAME_VAL(1035). For other ISA/ABIs may be
+ // DW_FRAME_UNDEFINED_VAL(1034).
+ unsigned cf_initial_rule_value;
+ unsigned cf_same_val;
+ unsigned cf_undefined_val;
+
+ // The number of the cfa 'register'. For cf_interface_number 2 of
+ // MIPS this is 0. For other architectures (and anytime using
+ // cf_interface_number 3) this should be outside the table, a
+ // special value such as 1036, not a table column at all).
+ unsigned cf_cfa_reg;
+
+ /* If non-zero it is the number of bytes in an address
+ for the frame data. Normally it will be zero because
+ there are usually other sources for the correct address size.
+ However, with DWARF2 frame data there is no explicit address
+ size in the frame data and the object file might not have
+ other .debug_ sections to work with.
+ If zero, no address size was supplied, and that is normal and
+ the already-set (or defaulted) address size is to be used.
+ Only an exceptional frame configure will specify address
+ size here. This won't work at all if the object needing
+ this setting has different address size in different CUs. */
+ unsigned cf_address_size;
+
+};
+
+
+// Returns DW_DLV_OK if works. DW_DLV_ERROR if cannot do what is asked.
+int find_conf_file_and_read_config(const std::string & named_file,
+ const std::string &named_abi,
+ const char **defaults,
+ struct dwconf_s *conf_out);
+void init_conf_file_data(struct dwconf_s *config_file_data);
+void init_mips_conf_file_data(struct dwconf_s *config_file_data);
+
+void print_reg_from_config_data(Dwarf_Signed reg,
+ struct dwconf_s *config_data);
+
+void init_generic_config_1200_regs(struct dwconf_s *conf);
diff --git a/dwarfdump2/fderegs.h b/dwarfdump2/fderegs.h
new file mode 100644
index 0000000..fcfc77b
--- /dev/null
+++ b/dwarfdump2/fderegs.h
@@ -0,0 +1,136 @@
+/*
+ Copyright (C) 2009-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+// Abstracts out calling dwarf to get fde register values
+// at a pc value.
+
+// Assumes libdwarf.h etc already included.
+//
+// Should speed up printing a frame by nearly N times
+// where N is the number of register rules (columns).
+
+class FdeRegs {
+public:
+ FdeRegs(Dwarf_Fde fde,struct dwconf_s *config_data):
+ fde_(fde),interfaceNumber_(config_data->cf_interface_number),
+ confData_(*config_data),pcAddr_(0),rowPc_(0) {
+ // regTable_ is a C struct from libdwarf.h
+ memset(&regTable_,0,sizeof(regTable_));
+ unsigned count = confData_.cf_table_entry_count;
+ regTable_.rt3_reg_table_size = count;
+ regTable_.rt3_rules = new Dwarf_Regtable_Entry3_s[count];
+ tableByteCount_ = sizeof(Dwarf_Regtable_Entry3_s) *count;
+ zeroRegTab();
+ };
+ ~FdeRegs() { delete [] regTable_.rt3_rules;};
+
+ int getInterfaceNumber() { return interfaceNumber_; };
+
+ void setPc(Dwarf_Addr pcval) { pcAddr_ = pcval;};
+ int preliminaryRead(Dwarf_Error *err) {
+ zeroRegTab();
+ if(interfaceNumber_ == 2) {
+ // Interface 2 is deprecated. Ok to use for testing.
+ static Dwarf_Regtable t;
+ Dwarf_Regtable regtab2;
+ regtab2 = t;
+ int res = dwarf_get_fde_info_for_all_regs(fde_,
+ pcAddr_, &regtab2 ,&rowPc_,err);
+ if(res == DW_DLV_OK) {
+ // Transform to form 3.
+ for(unsigned i = 0; i < confData_.cf_table_entry_count; ++i) {
+ Dwarf_Regtable_Entry3 *out =
+ regTable_.rt3_rules+i;
+ Dwarf_Regtable_Entry *in =
+ &regtab2.rules[i];
+ out->dw_offset_relevant = in->dw_offset_relevant;
+ out->dw_value_type = in->dw_value_type;
+ out->dw_regnum = in->dw_regnum;
+ out->dw_offset_or_block_len = in->dw_offset;
+ out->dw_block_ptr = 0;
+ }
+ }
+ return res;
+ } else if(interfaceNumber_ == 3) {
+ //int rulecount = confData_.cf_table_entry_count;
+ int res = dwarf_get_fde_info_for_all_regs3(fde_,
+ pcAddr_, &regTable_,&rowPc_,err);
+ return res;
+ } else {
+ return DW_DLV_ERROR;
+ }
+ };
+
+ // Interface number 3 only.
+ int getCfaRegdata( Dwarf_Regtable_Entry3 * entry_out,
+ Dwarf_Addr * rowpc_out,
+ Dwarf_Error *err) {
+ if (interfaceNumber_ != 3) {
+ // Really a programmer botch here.
+ return DW_DLV_NO_ENTRY;
+ };
+ *rowpc_out = rowPc_;
+ *entry_out = regTable_.rt3_cfa_rule;
+ return DW_DLV_OK;
+ };
+ // Interfaces 2 and 3.
+ int getRegdata(unsigned table_col,
+ Dwarf_Regtable_Entry3 * entry_out, Dwarf_Addr * rowpc_out,
+ Dwarf_Error *err) {
+ if ( table_col >= confData_.cf_table_entry_count) {
+ return DW_DLV_ERROR;
+ }
+ *rowpc_out = rowPc_;
+ *entry_out = regTable_.rt3_rules[table_col];
+ return DW_DLV_OK;
+ };
+
+private:
+ Dwarf_Fde fde_;
+ int interfaceNumber_;
+ struct dwconf_s confData_;
+ Dwarf_Addr pcAddr_;
+ Dwarf_Addr rowPc_;
+ Dwarf_Regtable3_s regTable_;
+ unsigned tableByteCount_;
+
+ void zeroRegTab() {
+ memset( regTable_.rt3_rules,0, tableByteCount_);
+ memset( &regTable_.rt3_cfa_rule,0, sizeof(Dwarf_Regtable_Entry3_s));
+ // Do not set rt3_reg_table_size here. Set already.
+ }
+
+ // Unimplemented.
+ FdeRegs();
+};
diff --git a/dwarfdump2/globals.h b/dwarfdump2/globals.h
new file mode 100644
index 0000000..11aa961
--- /dev/null
+++ b/dwarfdump2/globals.h
@@ -0,0 +1,587 @@
+/*
+ Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
+ Portions Copyright (C) 2011 SN Systems Ltd. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/globals.h,v 1.25 2006/04/17 00:09:56 davea Exp $ */
+
+#ifndef globals_INCLUDED
+#define globals_INCLUDED
+
+#include "config.h"
+#if (!defined(HAVE_RAW_LIBELF_OK) && defined(HAVE_LIBELF_OFF64_OK) )
+/* At a certain point libelf.h requires _GNU_SOURCE.
+ here we assume the criteria in configure determine that
+ usefully.
+*/
+#define _GNU_SOURCE 1
+#endif
+
+
+/* We want __uint32_t and __uint64_t and __int32_t __int64_t
+ properly defined but not duplicated, since duplicate typedefs
+ are not legal C.
+*/
+/*
+ HAVE___UINT32_T
+ HAVE___UINT64_T will be set by configure if
+ our 4 types are predefined in compiler
+*/
+
+
+#if (!defined(HAVE___UINT32_T)) && defined(HAVE_SGIDEFS_H)
+#include <sgidefs.h> /* sgidefs.h defines them */
+#define HAVE___UINT32_T 1
+#define HAVE___UINT64_T 1
+#endif
+
+
+
+#if (!defined(HAVE___UINT32_T)) && defined(HAVE_SYS_TYPES_H) && defined(HAVE___UINT32_T_IN_SYS_TYPES_H)
+# include <sys/types.h>
+/* We assume __[u]int32_t and __[u]int64_t defined
+ since __uint32_t defined in the sys/types.h in use */
+#define HAVE___UINT32_T 1
+#define HAVE___UINT64_T 1
+#endif
+
+#ifndef HAVE___UINT32_T
+typedef int __int32_t;
+typedef unsigned __uint32_t;
+#define HAVE___UINT32_T 1
+#endif
+#ifndef HAVE___UINT64_T
+typedef long long __int64_t;
+typedef unsigned long long __uint64_t;
+#define HAVE___UINT64_T 1
+#endif
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+#include <iostream>
+#include <sstream> // For IToDec
+#include <iomanip> // For setw
+#include <list>
+#include <map>
+#include <set>
+#include <string.h>
+#ifdef HAVE_ELF_H
+#include <elf.h>
+#endif
+#ifdef HAVE_LIBELF_H
+#include <libelf.h>
+#else
+#ifdef HAVE_LIBELF_LIBELF_H
+#include <libelf/libelf.h>
+#endif
+#endif
+#include <dwarf.h>
+#include <libdwarf.h>
+#ifdef HAVE_REGEX
+#include <regex.h>
+#endif
+
+#ifndef FAILED
+#define FAILED 1
+#endif
+
+#include "dieholder.h"
+#include "srcfilesholder.h"
+#include "checkutil.h"
+
+struct Dwarf_Check_Result {
+ Dwarf_Check_Result ():checks_(0),errors_(0) {};
+ ~Dwarf_Check_Result() {};
+ int checks_;
+ int errors_;
+};
+
+extern bool search_is_on;
+extern std::string search_any_text;
+extern std::string search_match_text;
+extern std::string search_regex_text;
+#ifdef HAVE_REGEX
+extern regex_t search_re;
+#endif
+extern bool is_strstrnocase(const char * container, const char * contained);
+
+
+extern bool do_check_dwarf;
+extern bool do_print_dwarf;
+extern bool record_dwarf_error; /* A test has failed, this
+ is normally set FALSE shortly after being set TRUE, it is
+ a short-range hint we should print something we might not
+ otherwise print (under the circumstances). */
+
+// Compilation Unit information for improved error messages.
+struct Error_Message_Data {
+ Error_Message_Data():
+ seen_PU(false),
+ seen_CU(false),
+ need_CU_name(false),
+ need_CU_base_address(false),
+ need_CU_high_address(false),
+ need_PU_valid_code(false),
+ seen_PU_base_address(false),
+ seen_PU_high_address(false),
+ PU_base_address(0),
+ PU_high_address(0),
+ DIE_offset(0),
+ DIE_overall_offset(0),
+ DIE_CU_offset(0),
+ DIE_CU_overall_offset(0),
+ current_section_id(0),
+ CU_base_address(0),
+ CU_high_address(0),
+ elf_max_address(0),
+ elf_address_size(0)
+ {};
+ ~Error_Message_Data() {};
+ std::string PU_name;
+ std::string CU_name;
+ std::string CU_producer;
+ bool seen_PU; // Detected a PU.
+ bool seen_CU; // Detected a CU.
+ bool need_CU_name;
+ bool need_CU_base_address; // Need CU Base address.
+ bool need_CU_high_address; // Need CU High address.
+ bool need_PU_valid_code; // Need PU valid code.
+
+ bool seen_PU_base_address; // Detected a Base address for PU
+ bool seen_PU_high_address; // Detected a High address for PU
+ Dwarf_Addr PU_base_address;// PU Base address
+ Dwarf_Addr PU_high_address;// PU High address
+
+ Dwarf_Off DIE_offset; // DIE offset in compile unit.
+ Dwarf_Off DIE_overall_offset; // DIE offset in .debug_info.
+
+ Dwarf_Off DIE_CU_offset; // CU DIE offset in compile unit
+ Dwarf_Off DIE_CU_overall_offset; // CU DIE offset in .debug_info
+ int current_section_id; // Section being process.
+
+ Dwarf_Addr CU_base_address;// CU Base address.
+ Dwarf_Addr CU_high_address;// CU High address.
+
+ Dwarf_Addr elf_max_address;// Largest representable address offset.
+ Dwarf_Half elf_address_size;// Target pointer size.
+};
+extern struct Error_Message_Data error_message_data;
+
+// Display parent/children when in wide format.
+extern bool display_parent_tree;
+extern bool display_children_tree;
+extern int stop_indent_level;
+
+// Print search results when in wide format.
+extern bool search_wide_format;
+extern bool search_is_on;
+
+extern std::string search_any_text;
+extern std::string search_match_text;
+extern std::string search_regex_text;
+#ifdef HAVE_REGEX
+extern regex_t search_re;
+#endif
+extern bool is_strstrnocase(const char *data, const char *pattern);
+
+// Options to enable debug tracing.
+#define MAX_TRACE_LEVEL 10
+extern int nTrace[MAX_TRACE_LEVEL + 1];
+#define DUMP_RANGES_INFO 1 // Dump RangesInfo Table.
+#define DUMP_LOCATION_SECTION_INFO 2 // Dump Location (.debug_loc) Info.
+#define DUMP_RANGES_SECTION_INFO 3 // Dump Ranges (.debug_ranges) Info.
+#define DUMP_LINKONCE_INFO 4 // Dump Linkonce Table.
+#define DUMP_VISITED_INFO 5 // Dump Visited Info.
+
+#define dump_ranges_info nTrace[DUMP_RANGES_INFO]
+#define dump_location_section_info nTrace[DUMP_LOCATION_SECTION_INFO]
+#define dump_ranges_section_info nTrace[DUMP_RANGES_SECTION_INFO]
+#define dump_linkonce_info nTrace[DUMP_LINKONCE_INFO]
+#define dump_visited_info nTrace[DUMP_VISITED_INFO]
+
+/* Section IDs */
+#define DEBUG_ABBREV 1
+#define DEBUG_ARANGES 2
+#define DEBUG_FRAME 3
+#define DEBUG_INFO 4
+#define DEBUG_LINE 5
+#define DEBUG_LOC 6
+#define DEBUG_MACINFO 7
+#define DEBUG_PUBNAMES 8
+#define DEBUG_RANGES 9
+#define DEBUG_STATIC_VARS 10
+#define DEBUG_STATIC_FUNC 11
+#define DEBUG_STR 12
+#define DEBUG_WEAKNAMES 13
+#define DEBUG_TYPES 14
+
+extern int verbose;
+extern bool dense;
+extern bool ellipsis;
+extern bool use_mips_regnames;
+extern bool show_global_offsets;
+extern bool show_form_used;
+extern bool display_offsets;
+
+extern bool check_pubname_attr;
+extern bool check_attr_tag;
+extern bool check_tag_tree;
+extern bool check_type_offset;
+extern bool check_decl_file;
+extern bool check_lines;
+extern bool check_ranges;
+extern bool check_fdes;
+extern bool check_aranges;
+extern bool check_harmless;
+extern bool check_abbreviations;
+extern bool check_dwarf_constants;
+extern bool check_di_gaps;
+extern bool check_forward_decl;
+extern bool check_self_references;
+extern bool suppress_nested_name_search;
+extern bool suppress_check_extensions_tables;
+
+extern int break_after_n_units;
+
+extern bool check_names; // Check for invalid names.
+extern bool check_verbose_mode; // During '-k' mode, display errors.
+extern bool check_frames; // Frames check.
+extern bool check_frames_extended;// Extensive frames check.
+extern bool check_locations; // Location list check.
+
+
+// Check categories corresponding to the -k option
+enum Dwarf_Check_Categories{ // Dwarf_Check_Categories
+ abbrev_code_result, // 0
+ pubname_attr_result,
+ reloc_offset_result,
+ attr_tag_result,
+ tag_tree_result,
+ type_offset_result, // 5
+ decl_file_result,
+ ranges_result,
+ lines_result, //8
+ aranges_result,
+ // Harmless errors are errors detected inside libdwarf but
+ // not reported via DW_DLE_ERROR returns because the errors
+ // won't really affect client code. The 'harmless' errors
+ // are reported and otherwise ignored. It is difficult to report
+ // the error when the error is noticed by libdwarf, the error
+ // is reported at a later time.
+ // The other errors dwarfdump reports are also generally harmless
+ // but are detected by dwarfdump so it's possble to report the
+ // error as soon as the error is discovered.
+ harmless_result, //10
+ fde_duplication,
+ frames_result,
+ locations_result,
+ names_result,
+ abbreviations_result, // 15
+ dwarf_constants_result,
+ di_gaps_result,
+ forward_decl_result,
+ self_references_result,
+ total_check_result, //20
+ LAST_CATEGORY // Must be last.
+} ;
+
+
+extern bool info_flag;
+extern bool line_flag;
+extern bool use_old_dwarf_loclist;
+extern bool producer_children_flag; // List of CUs per compiler
+
+extern std::string cu_name;
+extern bool cu_name_flag;
+extern Dwarf_Unsigned cu_offset;
+extern Dwarf_Off fde_offset_for_cu_low;
+extern Dwarf_Off fde_offset_for_cu_high;
+
+/* Process TAGs for checking mode and reset pRangesInfo table
+ if appropriate. */
+extern void tag_specific_checks_setup(Dwarf_Half val,int die_indent_level);
+
+extern std::string program_name;
+extern Dwarf_Error err;
+
+extern void print_error_and_continue (Dwarf_Debug dbg, const std::string& msg,int res, Dwarf_Error err);
+extern void print_error (Dwarf_Debug dbg, const std::string& msg,int res, Dwarf_Error err);
+
+// The dwarf_names_print_on_error is so other apps (tag_tree.cc)
+// can use the generated code in dwarf_names.cc (etc) easily.
+// It is not ever set false in dwarfdump.
+extern bool dwarf_names_print_on_error;
+
+extern void print_line_numbers_this_cu (DieHolder &hdie);
+struct dwconf_s;
+extern void print_frames (Dwarf_Debug dbg, int print_debug_frame,
+ int print_eh_frame,struct dwconf_s *);
+extern void print_ranges (Dwarf_Debug dbg);
+extern void print_pubnames (Dwarf_Debug dbg);
+extern void print_macinfo (Dwarf_Debug dbg);
+extern void print_infos (Dwarf_Debug dbg,bool is_info);
+extern void print_locs (Dwarf_Debug dbg);
+extern void print_abbrevs (Dwarf_Debug dbg);
+extern void print_strings (Dwarf_Debug dbg);
+extern void print_aranges (Dwarf_Debug dbg);
+extern void print_relocinfo (Dwarf_Debug dbg, unsigned reloc_map);
+extern void print_static_funcs(Dwarf_Debug dbg);
+extern void print_static_vars(Dwarf_Debug dbg);
+enum type_type_e {SGI_TYPENAME, DWARF_PUBTYPES} ;
+extern void print_types(Dwarf_Debug dbg,enum type_type_e type_type);
+extern void print_weaknames(Dwarf_Debug dbg);
+extern void print_exception_tables(Dwarf_Debug dbg);
+struct esb_s;
+extern std::string print_ranges_list_to_extra(Dwarf_Debug dbg,
+ Dwarf_Unsigned off,
+ Dwarf_Ranges *rangeset,
+ Dwarf_Signed rangecount,
+ Dwarf_Unsigned bytecount);
+extern bool should_skip_this_cu(DieHolder &cu_die, Dwarf_Error err);
+
+int get_cu_name(DieHolder &hcu_die,
+ Dwarf_Error err,std::string &short_name_out,std::string &long_name_out);
+int get_producer_name(DieHolder &hcu_die,
+ Dwarf_Error err,std::string &producer_name_out);
+
+/* Get number of abbreviations for a CU */
+extern void get_abbrev_array_info(Dwarf_Debug dbg,Dwarf_Unsigned offset);
+/* Validate an abbreviation */
+extern void validate_abbrev_code(Dwarf_Debug dbg,Dwarf_Unsigned abbrev_code);
+
+extern void print_die_and_children(
+ DieHolder &in_die,
+ Dwarf_Bool is_info,
+ SrcfilesHolder &srcfiles);
+extern bool print_one_die(
+ DieHolder &hdie_in,
+ bool print_information,
+ int indent_level,
+ SrcfilesHolder &srcfiles,
+ bool ignore_die_printed_flag);
+
+// Check for specific compiler.
+extern bool checking_this_compiler();
+extern void update_compiler_target(const std::string & producer_name);
+extern void add_cu_name_compiler_target(const std::string &name);
+
+
+/* General error reporting routines. These were
+ macros for a short time and when changed into functions
+ they kept (for now) their capitalization.
+ The capitalization will likely change. */
+extern void PRINT_CU_INFO();
+extern void DWARF_CHECK_COUNT(Dwarf_Check_Categories category, int inc);
+extern void DWARF_ERROR_COUNT(Dwarf_Check_Categories category, int inc);
+extern void DWARF_CHECK_ERROR_PRINT_CU();
+extern void DWARF_CHECK_ERROR(Dwarf_Check_Categories category,
+ const std::string &str);
+extern void DWARF_CHECK_ERROR2(Dwarf_Check_Categories category,
+ const std::string &str1,
+ const std::string &str2);
+extern void DWARF_CHECK_ERROR3(Dwarf_Check_Categories category,
+ const std::string & str1,
+ const std::string & str2,
+ const std::string & strexpl);
+
+
+extern void printreg(Dwarf_Signed reg,struct dwconf_s *config_data);
+extern void print_frame_inst_bytes(Dwarf_Debug dbg,
+ Dwarf_Ptr cie_init_inst, Dwarf_Signed len,
+ Dwarf_Signed data_alignment_factor,
+ int code_alignment_factor, Dwarf_Half addr_size,
+ struct dwconf_s *config_data);
+
+bool
+get_proc_name(Dwarf_Debug dbg, Dwarf_Die die,
+ std::string & proc_name, Dwarf_Addr & low_pc_out);
+
+
+void get_attr_value(Dwarf_Debug dbg, Dwarf_Half tag,
+ Dwarf_Die die,
+ Dwarf_Attribute attrib,
+ SrcfilesHolder &srcfiles,
+ std::string &str_out,bool show_form,
+ int local_verbose);
+
+
+
+extern Dwarf_Unsigned local_dwarf_decode_u_leb128(unsigned char *leb128,
+ unsigned int *leb128_length);
+
+extern Dwarf_Signed local_dwarf_decode_s_leb128(unsigned char *leb128,
+ unsigned int *leb128_length);
+
+extern void dump_block(const std::string &prefix, char *data, Dwarf_Signed len);
+
+extern void format_sig8_string(Dwarf_Sig8 *data,std::string &out);
+
+int
+dwarfdump_print_one_locdesc(Dwarf_Debug dbg,
+ Dwarf_Locdesc * llbuf,
+ int skip_locdesc_header,
+ std::string &string_out);
+void clean_up_syms_malloc_data();
+
+void print_any_harmless_errors(Dwarf_Debug dbg);
+
+/* Definitions for printing relocations. */
+#define DW_SECTION_REL_DEBUG_INFO 0
+#define DW_SECTION_REL_DEBUG_LINE 1
+#define DW_SECTION_REL_DEBUG_PUBNAMES 2
+#define DW_SECTION_REL_DEBUG_ABBREV 3
+#define DW_SECTION_REL_DEBUG_ARANGES 4
+#define DW_SECTION_REL_DEBUG_FRAME 5
+#define DW_SECTION_REL_DEBUG_LOC 6
+#define DW_SECTION_REL_DEBUG_RANGES 7
+#define DW_SECTION_REL_DEBUG_TYPES 8
+
+template <typename T >
+std::string IToDec(T v,unsigned l=0)
+{
+ std::ostringstream s;
+ if (l > 0) {
+ s << std::setw(l) << v;
+ } else {
+ s << v ;
+ }
+ return s.str();
+};
+template <typename T >
+std::string IToHex(T v,unsigned l=0)
+{
+ if(v == 0) {
+ // For a zero value, above does not insert 0x.
+ // So we do zeroes here.
+ std::string out = "0x0";
+ if(l > 3) {
+ out.append(l-3,'0');
+ }
+ return out;
+ }
+ std::ostringstream s;
+ s.setf(std::ios::hex,std::ios::basefield);
+ s.setf(std::ios::showbase);
+ if (l > 0) {
+ s << std::setw(l);
+ }
+ s << v ;
+ return s.str();
+};
+
+inline std::string IToHex02(unsigned v)
+{
+ std::ostringstream s;
+ // NO showbase here.
+ s.setf(std::ios::hex,std::ios::basefield);
+ s << std::setfill('0');
+ s << std::setw(2) << (0xff & v);
+ return s.str();
+}
+template <typename T>
+std::string IToHex0N(T v,unsigned len=0)
+{
+ std::ostringstream s;
+ s.setf(std::ios::hex,std::ios::basefield);
+ //s.setf(std::ios::showbase);
+ s << std::setfill('0');
+ if(len > 2 ) {
+ s << std::setw(len-2) << v;
+ } else {
+ s << v;
+ }
+ return std::string("0x") + s.str();
+}
+template <typename T>
+std::string IToDec0N(T v,unsigned len=0)
+{
+ std::ostringstream s;
+ if (v < 0 && len > 2 ) {
+ // Special handling for negatives:
+ // 000-27 is not what we want for example.
+ s << v;
+ // ASSERT: s.str().size() >= 1
+ if( len > ((s.str().size()))) {
+ // Ignore the leading - and take the rest.
+ std::string rest = s.str().substr(1);
+ std::string::size_type zeroscount = len - (rest.size()+1);
+ std::string final;
+ if(zeroscount > 0) {
+ final.append(zeroscount,'0');
+ final.append(rest);
+ } else {
+ final = rest;
+ }
+ return std::string("-") + final;
+ }
+ return s.str();
+ }
+ s << std::setfill('0');
+ if(len > 0) {
+ s << std::setw(len) << v;
+ } else {
+ s << v;
+ }
+ return s.str();
+}
+inline std::string LeftAlign(unsigned minlen,const std::string &s)
+{
+ if(minlen <= s.size()) {
+ return s;
+ }
+ std::string out = s;
+ std::string::size_type spaces = minlen - out.size();
+ out.append(spaces,' ');
+ return out;
+}
+
+inline std::string SpaceSurround(const std::string &s)
+{
+ std::string out(" ");
+ out.append(s);
+ out.append(" ");
+ return out;
+};
+inline std::string BracketSurround(const std::string &s)
+{
+ std::string out("<");
+ out.append(s);
+ out.append(">");
+ return out;
+};
+
+
+#endif /* globals_INCLUDED */
+
diff --git a/dwarfdump2/install.sh b/dwarfdump2/install.sh
new file mode 100755
index 0000000..0ff4b6a
--- /dev/null
+++ b/dwarfdump2/install.sh
@@ -0,0 +1,119 @@
+#!/bin/sh
+
+#
+# install - install a program, script, or datafile
+# This comes from X11R5; it is not part of GNU.
+#
+# $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+
+instcmd="$mvprog"
+chmodcmd=""
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+fi
+
+if [ x"$dst" = x ]
+then
+ echo "install: no destination specified"
+ exit 1
+fi
+
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+if [ -d $dst ]
+then
+ dst="$dst"/`basename $src`
+fi
+
+# Make a temp file name in the proper directory.
+
+dstdir=`dirname $dst`
+dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+$doit $instcmd $src $dsttmp
+
+# and set any options; do chmod last to preserve setuid bits
+
+if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi
+if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi
+if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi
+if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi
+
+# Now rename the file to the real destination.
+
+$doit $rmcmd $dst
+$doit $mvcmd $dsttmp $dst
+
+
+exit 0
diff --git a/dwarfdump2/naming.cc b/dwarfdump2/naming.cc
new file mode 100644
index 0000000..4526538
--- /dev/null
+++ b/dwarfdump2/naming.cc
@@ -0,0 +1,264 @@
+
+/*
+ Copyright (C) 2000,2002,2004,2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
+
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+
+#include "globals.h"
+#include "dwarf.h"
+#include "libdwarf.h"
+
+using std::string;
+using std::cerr;
+using std::endl;
+
+static const char *
+skipunder(const char *v)
+{
+ const char *cp = v;
+ int undercount = 0;
+ for( ; *cp ; ++cp) {
+ if( *cp == '_') {
+ ++undercount;
+ if(undercount == 2) {
+ return cp+1;
+ }
+ }
+ }
+ return "";
+};
+
+static string
+ellipname(int res, unsigned int val_in, const char *v,const char *ty,bool printonerr)
+{
+#ifndef TRIVIAL_NAMING
+ if (check_dwarf_constants && checking_this_compiler()) {
+ DWARF_CHECK_COUNT(dwarf_constants_result,1);
+ }
+#endif
+ if(res != DW_DLV_OK) {
+ if(printonerr) {
+#ifndef TRIVIAL_NAMING
+ if(printonerr && check_dwarf_constants && checking_this_compiler()) {
+ if (check_verbose_mode) {
+ std::cerr << ty << " of " << val_in << " (" <<
+ IToHex(val_in) <<
+ ") is unknown to dwarfdump. " <<
+ "Continuing. " << endl;
+ }
+ DWARF_ERROR_COUNT(dwarf_constants_result,1);
+ DWARF_CHECK_ERROR_PRINT_CU();
+ }
+#else
+ /* This is for the tree-generation, not dwarfdump itself. */
+ if(printonerr) {
+ std::cerr << ty << " of " << val_in <<
+ " (" << IToHex(val_in,0) <<
+ ") is unknown to dwarfdump. Continuing. " << std::endl;
+ }
+#endif
+ }
+ return "<Unknown " + string(ty) + " value " +
+ IToHex(val_in,0) + ">";
+ }
+ if(ellipsis) {
+ return skipunder(v);
+ }
+ return v;
+};
+
+std::string get_TAG_name(unsigned int val_in,bool printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_TAG_name(val_in,&v);
+ return ellipname(res,val_in,v,"TAG",printonerr);
+}
+std::string get_children_name(unsigned int val_in,bool printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_children_name(val_in,&v);
+ return ellipname(res,val_in,v,"children",printonerr);
+}
+std::string get_FORM_name(unsigned int val_in,bool printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_FORM_name(val_in,&v);
+ return ellipname(res,val_in,v,"FORM",printonerr);
+}
+std::string get_AT_name(unsigned int val_in,bool printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_AT_name(val_in,&v);
+ return ellipname(res,val_in,v,"AT",printonerr);
+}
+std::string get_OP_name(unsigned int val_in,bool printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_OP_name(val_in,&v);
+ return ellipname(res,val_in,v,"OP",printonerr);
+}
+std::string get_ATE_name(unsigned int val_in,bool printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_ATE_name(val_in,&v);
+ return ellipname(res,val_in,v,"ATE",printonerr);
+}
+std::string get_DS_name(unsigned int val_in,bool printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_DS_name(val_in,&v);
+ return ellipname(res,val_in,v,"DS",printonerr);
+}
+std::string get_END_name(unsigned int val_in,bool printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_END_name(val_in,&v);
+ return ellipname(res,val_in,v,"END",printonerr);
+}
+std::string get_ATCF_name(unsigned int val_in,bool printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_ATCF_name(val_in,&v);
+ return ellipname(res,val_in,v,"ATCF",printonerr);
+}
+std::string get_ACCESS_name(unsigned int val_in,bool printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_ACCESS_name(val_in,&v);
+ return ellipname(res,val_in,v,"ACCESS",printonerr);
+}
+std::string get_VIS_name(unsigned int val_in,bool printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_VIS_name(val_in,&v);
+ return ellipname(res,val_in,v,"VIS",printonerr);
+}
+std::string get_VIRTUALITY_name(unsigned int val_in,bool printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_VIRTUALITY_name(val_in,&v);
+ return ellipname(res,val_in,v,"VIRTUALITY",printonerr);
+}
+std::string get_LANG_name(unsigned int val_in,bool printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_LANG_name(val_in,&v);
+ return ellipname(res,val_in,v,"LANG",printonerr);
+}
+std::string get_ID_name(unsigned int val_in,bool printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_ID_name(val_in,&v);
+ return ellipname(res,val_in,v,"ID",printonerr);
+}
+std::string get_CC_name(unsigned int val_in,bool printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_CC_name(val_in,&v);
+ return ellipname(res,val_in,v,"CC",printonerr);
+}
+std::string get_INL_name(unsigned int val_in,bool printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_INL_name(val_in,&v);
+ return ellipname(res,val_in,v,"INL",printonerr);
+}
+std::string get_ORD_name(unsigned int val_in,bool printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_ORD_name(val_in,&v);
+ return ellipname(res,val_in,v,"ORD",printonerr);
+}
+std::string get_DSC_name(unsigned int val_in,bool printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_DSC_name(val_in,&v);
+ return ellipname(res,val_in,v,"DSC",printonerr);
+}
+std::string get_LNS_name(unsigned int val_in,bool printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_LNS_name(val_in,&v);
+ return ellipname(res,val_in,v,"LNS",printonerr);
+}
+std::string get_LNE_name(unsigned int val_in,bool printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_LNE_name(val_in,&v);
+ return ellipname(res,val_in,v,"LNE",printonerr);
+}
+std::string get_MACINFO_name(unsigned int val_in,bool printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_MACINFO_name(val_in,&v);
+ return ellipname(res,val_in,v,"MACINFO",printonerr);
+}
+std::string get_CFA_name(unsigned int val_in,bool printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_CFA_name(val_in,&v);
+ return ellipname(res,val_in,v,"CFA",printonerr);
+}
+std::string get_EH_name(unsigned int val_in,bool printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_EH_name(val_in,&v);
+ return ellipname(res,val_in,v,"EH",printonerr);
+}
+std::string get_FRAME_name(unsigned int val_in,bool printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_FRAME_name(val_in,&v);
+ return ellipname(res,val_in,v,"FRAME",printonerr);
+}
+std::string get_CHILDREN_name(unsigned int val_in,bool printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_CHILDREN_name(val_in,&v);
+ return ellipname(res,val_in,v,"CHILDREN",printonerr);
+}
+std::string get_ADDR_name(unsigned int val_in,bool printonerr)
+{
+ const char *v = 0;
+ int res = dwarf_get_ADDR_name(val_in,&v);
+ return ellipname(res,val_in,v,"ADDR",printonerr);
+}
+
+
diff --git a/dwarfdump2/naming.h b/dwarfdump2/naming.h
new file mode 100644
index 0000000..1314ab4
--- /dev/null
+++ b/dwarfdump2/naming.h
@@ -0,0 +1,71 @@
+/*
+ Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
+
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+/* naming.h */
+
+extern std::string get_TAG_name(unsigned int val_in,bool printonerr);
+extern std::string get_children_name(unsigned int val_in,bool printonerr);
+extern std::string get_FORM_name(unsigned int val_in,bool printonerr);
+extern std::string get_AT_name(unsigned int val_in,bool printonerr);
+extern std::string get_OP_name(unsigned int val_in,bool printonerr);
+extern std::string get_ATE_name(unsigned int val_in,bool printonerr);
+extern std::string get_DS_name(unsigned int val_in,bool printonerr);
+extern std::string get_END_name(unsigned int val_in,bool printonerr);
+extern std::string get_ATCF_name(unsigned int val_in,bool printonerr);
+extern std::string get_ACCESS_name(unsigned int val_in,bool printonerr);
+extern std::string get_VIS_name(unsigned int val_in,bool printonerr);
+extern std::string get_VIRTUALITY_name(unsigned int val_in,bool printonerr);
+extern std::string get_LANG_name(unsigned int val_in,bool printonerr);
+extern std::string get_ID_name(unsigned int val_in,bool printonerr);
+extern std::string get_CC_name(unsigned int val_in,bool printonerr);
+extern std::string get_INL_name(unsigned int val_in,bool printonerr);
+extern std::string get_ORD_name(unsigned int val_in,bool printonerr);
+extern std::string get_DSC_name(unsigned int val_in,bool printonerr);
+extern std::string get_LNS_name(unsigned int val_in,bool printonerr);
+extern std::string get_LNE_name(unsigned int val_in,bool printonerr);
+extern std::string get_MACINFO_name(unsigned int val_in,bool printonerr);
+extern std::string get_CFA_name(unsigned int val_in,bool printonerr);
+extern std::string get_EH_name(unsigned int val_in,bool printonerr);
+extern std::string get_FRAME_name(unsigned int val_in,bool printonerr);
+extern std::string get_CHILDREN_name(unsigned int val_in,bool printonerr);
+extern std::string get_ADDR_name(unsigned int val_in,bool printonerr);
+
+
diff --git a/dwarfdump2/print_abbrevs.cc b/dwarfdump2/print_abbrevs.cc
new file mode 100644
index 0000000..b0ed7f0
--- /dev/null
+++ b/dwarfdump2/print_abbrevs.cc
@@ -0,0 +1,307 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include "globals.h"
+#include <vector>
+#include "naming.h"
+#include "dwconf.h"
+
+#include "print_sections.h"
+#include "print_frames.h"
+
+using std::string;
+using std::cout;
+using std::cerr;
+using std::endl;
+
+/* print data in .debug_abbrev */
+extern void
+print_abbrevs(Dwarf_Debug dbg)
+{
+ Dwarf_Abbrev ab;
+ Dwarf_Unsigned offset = 0;
+ Dwarf_Unsigned length = 0;
+ Dwarf_Unsigned attr_count = 0;
+ Dwarf_Half attr = 0;
+ Dwarf_Signed form = 0;
+ Dwarf_Off off = 0;
+ string child_name;
+ Dwarf_Unsigned abbrev_num = 1;
+ Dwarf_Signed child_flag = 0;
+ int abres = 0;
+
+ error_message_data.current_section_id = DEBUG_ABBREV;
+ if (do_print_dwarf) {
+ cout << endl;
+ cout << ".debug_abbrev" << endl;
+ }
+ while ((abres = dwarf_get_abbrev(dbg, offset, &ab,
+ &length, &attr_count,
+ &err)) == DW_DLV_OK) {
+
+ if (attr_count == 0) {
+ /* Simple innocuous zero : null abbrev entry */
+ if (dense) {
+ cout << BracketSurround(IToDec(abbrev_num));
+ cout << BracketSurround(IToHex0N(offset,10));
+ // 0 is abbrev_code.
+ cout << BracketSurround(IToDec(0));
+ cout << BracketSurround("null .debug_abbrev entry") << endl;
+ } else {
+ cout << BracketSurround(IToDec(abbrev_num,5));
+ cout << BracketSurround(IToHex0N(offset,10));
+ // 0 is abbrev_code.
+ cout << BracketSurround(string("code: ") +IToDec(0,3));
+ cout << " null .debug_abbrev entry" << endl;
+ }
+
+ offset += length;
+ ++abbrev_num;
+ dwarf_dealloc(dbg, ab, DW_DLA_ABBREV);
+ continue;
+ }
+ Dwarf_Half tag = 0;
+ int tres = dwarf_get_abbrev_tag(ab, &tag, &err);
+ if (tres != DW_DLV_OK) {
+ dwarf_dealloc(dbg, ab, DW_DLA_ABBREV);
+ print_error(dbg, "dwarf_get_abbrev_tag", tres, err);
+ }
+ Dwarf_Unsigned abbrev_code = 0;
+ tres = dwarf_get_abbrev_code(ab, &abbrev_code, &err);
+ if (tres != DW_DLV_OK) {
+ dwarf_dealloc(dbg, ab, DW_DLA_ABBREV);
+ print_error(dbg, "dwarf_get_abbrev_code", tres, err);
+ }
+ if (dense) {
+ cout << BracketSurround(IToDec(abbrev_num));
+ cout << BracketSurround(IToHex0N(offset,10));
+ cout << BracketSurround(IToDec(abbrev_code));
+ cout << BracketSurround(get_TAG_name(tag,
+ dwarf_names_print_on_error));
+ }
+ else {
+ cout << BracketSurround(IToDec(abbrev_num,5));
+ cout << BracketSurround(IToHex0N(offset,10));
+ cout << BracketSurround(string("code: ") +IToDec(abbrev_code,3));
+ cout << " ";
+ cout << LeftAlign(20,get_TAG_name(tag,
+ dwarf_names_print_on_error));
+ }
+ ++abbrev_num;
+ int acres = dwarf_get_abbrev_children_flag(ab, &child_flag, &err);
+ if (acres == DW_DLV_ERROR) {
+ dwarf_dealloc(dbg, ab, DW_DLA_ABBREV);
+ print_error(dbg, "dwarf_get_abbrev_children_flag", acres,
+ err);
+ }
+ if (acres == DW_DLV_NO_ENTRY) {
+ child_flag = 0;
+ }
+ child_name = get_children_name(child_flag,
+ dwarf_names_print_on_error);
+ if (dense) {
+ cout << " " << child_name;
+ } else {
+ cout << " " << child_name << endl;
+ }
+ /* Abbrev just contains the format of a die, which debug_info
+ then points to with the real data. So here we just print the
+ given format. */
+ for (Dwarf_Unsigned i = 0; i < attr_count; i++) {
+ int aeres =
+ dwarf_get_abbrev_entry(ab, i, &attr, &form, &off, &err);
+ if (aeres == DW_DLV_ERROR) {
+ dwarf_dealloc(dbg, ab, DW_DLA_ABBREV);
+ print_error(dbg, "dwarf_get_abbrev_entry", aeres, err);
+ }
+ if (aeres == DW_DLV_NO_ENTRY) {
+ attr = -1LL;
+ form = -1LL;
+ }
+ if (dense) {
+ cout << " " << BracketSurround(IToDec(off));
+ cout << get_AT_name(attr,dwarf_names_print_on_error);
+ cout << BracketSurround(get_FORM_name((Dwarf_Half) form,
+ dwarf_names_print_on_error));
+ } else {
+ cout << " " << BracketSurround(IToHex0N(off,10));
+ cout << " ";
+ cout << LeftAlign(28,get_AT_name(
+ attr,dwarf_names_print_on_error));
+ cout << get_FORM_name(form,
+ dwarf_names_print_on_error);
+ cout << endl;
+ }
+ }
+ dwarf_dealloc(dbg, ab, DW_DLA_ABBREV);
+ offset += length;
+ if (dense) {
+ cout << endl;
+ }
+ }
+ if (abres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_abbrev", abres, err);
+ }
+}
+
+
+/* Abbreviations array info for checking abbrev tags.
+ The [zero] entry is not used.
+ We never shrink the array, but it never grows beyond
+ the largest abbreviation count of all the CUs.
+
+
+*/
+
+static std::vector<Dwarf_Signed>abbrev_vec;
+#define ABBREV_ARRAY_INITIAL_SIZE 64
+/* Number of abbreviations for current CU */
+static Dwarf_Unsigned CU_high_abbrev_code;
+static Dwarf_Unsigned CU_abbrev_count;
+
+static void
+increaseTo(unsigned nsize)
+{
+ unsigned csize = abbrev_vec.size();
+ if(nsize < csize) {
+ // Nothing to do here.
+ return;
+ }
+ abbrev_vec.resize(nsize);
+ for(unsigned i = csize; i < nsize; ++i) {
+ abbrev_vec[i] = 0;
+ }
+
+}
+
+/* Calculate the number of abbreviations for the
+ current CU and set up a basic abbreviations array info,
+ storing the number of attributes per abbreviation.
+*/
+void
+get_abbrev_array_info(Dwarf_Debug dbg, Dwarf_Unsigned offset_in)
+{
+ Dwarf_Unsigned offset = offset_in;
+ if (check_abbreviations) {
+ Dwarf_Abbrev ab;
+ Dwarf_Unsigned length = 0;
+ Dwarf_Unsigned abbrev_entry_count = 0;
+ Dwarf_Unsigned abbrev_code;
+ int abres = DW_DLV_OK;
+ Dwarf_Error err;
+
+ bool bMore = true;
+ CU_abbrev_count = 0;
+ CU_high_abbrev_code = 0;
+
+ if (!abbrev_vec.empty()) {
+ for(unsigned i = 0; i < abbrev_vec.size(); ++i) {
+ abbrev_vec[i] = 0;
+ }
+ }
+
+ while (bMore && (abres = dwarf_get_abbrev(dbg, offset, &ab,
+ &length, &abbrev_entry_count,
+ &err)) == DW_DLV_OK) {
+ dwarf_get_abbrev_code(ab,&abbrev_code,&err);
+ if (abbrev_code == 0) {
+ /* End of abbreviation table for this CU */
+ ++offset; /* Skip abbreviation code */
+ bMore = false;
+ } else {
+ /* Valid abbreviation code */
+ if (abbrev_code > 0) {
+ increaseTo(abbrev_code+1);
+ abbrev_vec[abbrev_code] = abbrev_entry_count;
+ if(abbrev_code > CU_high_abbrev_code) {
+ CU_high_abbrev_code = abbrev_code;
+ }
+ ++CU_abbrev_count;
+ offset += length;
+ } else {
+ /* Invalid abbreviation code */
+ print_error(dbg, "get_abbrev_array_info", abres, err);
+ }
+ }
+ dwarf_dealloc(dbg, ab, DW_DLA_ABBREV);
+ }
+ }
+}
+
+
+
+/* The following relevent for one specific Linker. */
+#define SNLINKER_MAX_ATTRIB_COUNT 16
+
+/* Validate an abbreviation for the current CU. */
+void
+validate_abbrev_code(Dwarf_Debug dbg,Dwarf_Unsigned abbrev_code)
+{
+ char buf[128];
+
+ DWARF_CHECK_COUNT(abbreviations_result,1);
+ if (abbrev_code < 0 || (abbrev_code && abbrev_code > CU_high_abbrev_code)) {
+ snprintf(buf, sizeof(buf),
+ "Abbrev code %" DW_PR_DUu
+ " outside valid range of [0-%" DW_PR_DUu "]",
+ abbrev_code,CU_high_abbrev_code);
+ DWARF_CHECK_ERROR2(abbreviations_result,buf,
+ "Invalid abbreviation code.");
+ } else {
+ Dwarf_Signed abbrev_entry_count =
+ abbrev_vec[abbrev_code];
+ if (abbrev_entry_count < 0 ||
+ abbrev_entry_count > SNLINKER_MAX_ATTRIB_COUNT) {
+ snprintf(buf, sizeof(buf),
+ "Abbrev code %" DW_PR_DUu
+ ", with %" DW_PR_DUu " attributes: "
+ "outside valid range.",
+ abbrev_code,
+ abbrev_entry_count);
+ DWARF_CHECK_ERROR2(abbreviations_result,buf,
+ "Invalid number of attributes.");
+ }
+ }
+}
+
+
diff --git a/dwarfdump2/print_aranges.cc b/dwarfdump2/print_aranges.cc
new file mode 100644
index 0000000..1265624
--- /dev/null
+++ b/dwarfdump2/print_aranges.cc
@@ -0,0 +1,266 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include "globals.h"
+#include <vector>
+#include "naming.h"
+#include "dwconf.h"
+
+#include "print_sections.h"
+#include "print_frames.h"
+
+using std::string;
+using std::cout;
+using std::cerr;
+using std::endl;
+
+
+static void
+do_checking(Dwarf_Debug dbg, Dwarf_Arange *arange_buf,Dwarf_Signed i,
+ Dwarf_Off cu_die_offset,Dwarf_Bool first_cu,
+ Dwarf_Off cu_die_offset_prev, Dwarf_Die cu_die )
+{
+ Dwarf_Off cuhdroff = 0;
+ Dwarf_Off cudieoff3 = 0;
+ int dres = dwarf_get_arange_cu_header_offset(
+ arange_buf[i],&cuhdroff,&err);
+ if(dres == DW_DLV_OK) {
+ Dwarf_Off cudieoff2 = 0;
+
+ /* Get the CU offset for easy error reporting */
+ if (first_cu || cu_die_offset != cu_die_offset_prev) {
+ cu_die_offset_prev = cu_die_offset;
+ dres = dwarf_die_offsets(cu_die,
+ &error_message_data.DIE_overall_offset,
+ &error_message_data.DIE_offset,&err);
+ if (dres != DW_DLV_OK) {
+ print_error(dbg, "dwarf_die_offsets", dres, err);
+ }
+ }
+ dres = dwarf_get_cu_die_offset_given_cu_header_offset(
+ dbg,cuhdroff,&cudieoff2,&err);
+ if(dres == DW_DLV_OK) {
+ /* Get the CU offset for easy error reporting */
+ dwarf_die_offsets(cu_die,
+ &error_message_data.DIE_overall_offset,
+ &error_message_data.DIE_offset,&err);
+ DWARF_CHECK_COUNT(aranges_result,1);
+ if(cudieoff2 != cu_die_offset) {
+ cout << "Error, cu_die offsets mismatch, " <<
+ IToHex(cu_die_offset) << " != " <<
+ IToHex(cudieoff2) << " from arange data";
+ DWARF_CHECK_ERROR(aranges_result,
+ " dwarf_get_cu_die_offset_given_cu..."
+ " gets wrong offset");
+ }
+ } else {
+ print_error(dbg, "dwarf_get_cu_die_offset_given...", dres, err);
+ }
+ } else {
+ print_error(dbg, "dwarf_get_arange_cu_header_offset", dres, err);
+ }
+ dres = dwarf_get_cu_die_offset(arange_buf[i],&cudieoff3,
+ &err);
+ if(dres == DW_DLV_OK) {
+ DWARF_CHECK_COUNT(aranges_result,1);
+ if(cudieoff3 != cu_die_offset) {
+ cout << "Error, cu_die offsets (b) mismatch , "<<
+ IToHex(cu_die_offset) << " != " <<
+ IToHex(cudieoff3) << " from arange data";
+ DWARF_CHECK_ERROR(aranges_result,
+ " dwarf_get_cu_die_offset "
+ " gets wrong offset");
+ }
+ } else {
+ print_error(dbg, "dwarf_get_cu_die_offset failed ",
+ dres,err);
+ }
+}
+
+/* get all the data in .debug_aranges */
+extern void
+print_aranges(Dwarf_Debug dbg)
+{
+ Dwarf_Signed count = 0;
+ Dwarf_Arange *arange_buf = NULL;
+ Dwarf_Off prev_off = 0; /* Holds previous CU offset */
+ bool first_cu = true;
+ Dwarf_Off cu_die_offset_prev = 0;
+
+ /* Reset the global state, so we can traverse the debug_info */
+ error_message_data.seen_CU = false;
+ error_message_data.need_CU_name = true;
+ error_message_data.need_CU_base_address = true;
+ error_message_data.need_CU_high_address = true;
+
+
+ error_message_data.current_section_id = DEBUG_ARANGES;
+ if (do_print_dwarf) {
+ cout << endl;
+ cout << ".debug_aranges" << endl;
+ }
+ int ares = dwarf_get_aranges(dbg, &arange_buf, &count, &err);
+ if (ares == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_aranges", ares, err);
+ } else if (ares == DW_DLV_NO_ENTRY) {
+ /* no arange is included */
+ } else {
+ Dwarf_Unsigned segment = 0;
+ Dwarf_Unsigned segment_entry_size = 0;
+ Dwarf_Addr start = 0;
+ Dwarf_Unsigned length = 0;
+ Dwarf_Off cu_die_offset = 0;
+ Dwarf_Die cu_die = 0;
+ for (Dwarf_Signed i = 0; i < count; i++) {
+ int aires = dwarf_get_arange_info_b(arange_buf[i],
+ &segment,&segment_entry_size,
+ &start, &length,
+ &cu_die_offset, &err);
+ if (aires != DW_DLV_OK) {
+ print_error(dbg, "dwarf_get_arange_info", aires, err);
+ } else {
+ int dres;
+ string producer_name;
+ /* Get basic locations for error reporting */
+ dres = dwarf_offdie(dbg, cu_die_offset, &cu_die, &err);
+ if (dres != DW_DLV_OK) {
+ print_error(dbg, "dwarf_offdie", dres, err);
+ }
+ DieHolder hcu_die(dbg,cu_die);
+
+ if (cu_name_flag) {
+ if(should_skip_this_cu(hcu_die,err)) {
+ continue;
+ }
+ }
+ /* Get producer name for this CU and update compiler list */
+ get_producer_name(hcu_die,err,producer_name);
+ update_compiler_target(producer_name);
+ if (!checking_this_compiler()) {
+ continue;
+ }
+
+
+ if (check_aranges) {
+ do_checking(dbg,arange_buf,i,cu_die_offset,first_cu,
+ cu_die_offset_prev,cu_die);
+ }
+
+ if(start || length) {
+ Dwarf_Off off = 0;
+ int cures3 = dwarf_get_arange_cu_header_offset(
+ arange_buf[i], &off, &err);
+ if (cures3 != DW_DLV_OK) {
+ print_error(dbg, "dwarf_get_cu_hdr_offset",
+ cures3, err);
+ }
+
+ /* Print the CU information if different. */
+ if (prev_off != off || first_cu) {
+ first_cu = false;
+ prev_off = off;
+ /* We are faking the indent level. We do not know
+ what level it is, really.
+
+ If do_check_dwarf we do not want to do
+ the die print call as it will do
+ check/print we may not have asked for.
+ And if we did ask for debug_info checks
+ this will do the checks a second time!
+ So only call print_one_die if printing.
+ */
+ if(do_print_dwarf){
+ /* There is no die if its a set-end entry */
+ SrcfilesHolder hsrcfiles;
+ print_one_die(hcu_die,
+ /* print_information= */ 1,
+ /* indent_level = */0,
+ hsrcfiles,
+ /* ignore_die_printed_flag= */true);
+ }
+ /* Reset the state, so we can traverse the debug_info */
+ error_message_data.seen_CU = false;
+ error_message_data.need_CU_name = true;
+ if (do_print_dwarf) {
+ cout << endl;
+ }
+ }
+
+ if (do_print_dwarf) {
+ /* Print current aranges record */
+ if(segment_entry_size) {
+ cout << endl;
+ cout <<
+ "arange starts at seg,off " <<
+ IToHex0N(segment,10) <<
+ "," << IToHex0N(start,10);
+ } else {
+ cout << endl;
+ cout <<
+ "arange starts at " <<
+ IToHex0N(start,10);
+ }
+ cout << ", length of " << IToHex0N(length,10) <<
+ ", cu_die_offset = "<< IToHex0N(cu_die_offset,10);
+ }
+ if (verbose && do_print_dwarf) {
+ cout << " cuhdr "<< IToHex0N(off,10) << endl;
+ }
+ } else {
+ /* Must be a range end. We really do want to print
+ this as there is a real record here, an
+ 'arange end' record. */
+ if (do_print_dwarf) {
+ cout << endl;
+ cout << "arange end";
+ }
+ }/* end start||length test */
+
+ } // End aires DW_DLV_OK test
+ /* print associated die too? */
+ dwarf_dealloc(dbg, arange_buf[i], DW_DLA_ARANGE);
+ }
+ dwarf_dealloc(dbg, arange_buf, DW_DLA_LIST);
+ }
+}
+
diff --git a/dwarfdump2/print_die.cc b/dwarfdump2/print_die.cc
new file mode 100644
index 0000000..61e1844
--- /dev/null
+++ b/dwarfdump2/print_die.cc
@@ -0,0 +1,3281 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2007-2010 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+$ Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_die.c,v 1.51 2006/04/01 16:20:21 davea Exp $ */
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+
+#include "globals.h"
+#include "naming.h"
+#include "tag_common.h"
+#include "print_frames.h"
+#include <vector>
+using std::string;
+using std::cout;
+using std::cerr;
+using std::endl;
+using std::vector;
+
+
+static bool traverse_one_die(Dwarf_Debug dbg,
+ Dwarf_Attribute attrib, Dwarf_Die die,
+ SrcfilesHolder & hsrcfiles,
+ int die_indent_level);
+
+/* Is this a PU has been invalidated by the SN Systems linker? */
+#define IsInvalidCode(low,high) ((low == error_message_data.elf_max_address) || (low == 0 && high == 0))
+
+static int get_form_values(Dwarf_Attribute attrib,
+ Dwarf_Half & theform, Dwarf_Half & directform);
+static void show_form_itself(bool show_form,
+ int local_verbose,
+ int theform, int directform, string *str_out);
+static bool print_attribute(Dwarf_Debug dbg, Dwarf_Die die,
+ Dwarf_Half attr,
+ Dwarf_Attribute actual_addr,
+ bool print_information,
+ int die_indent_level,
+ SrcfilesHolder &srcfiles);
+static void get_location_list(Dwarf_Debug dbg,
+ Dwarf_Die die,
+ Dwarf_Attribute attr, string &str_out );
+static void print_exprloc_content(Dwarf_Debug dbg,Dwarf_Die die,
+ Dwarf_Attribute attrib,
+ bool showhextoo, string &str_out);
+static int legal_tag_attr_combination(Dwarf_Half tag, Dwarf_Half attr);
+static bool legal_tag_tree_combination(Dwarf_Half parent_tag,
+ Dwarf_Half child_tag);
+static int _dwarf_print_one_expr_op(Dwarf_Debug dbg,Dwarf_Loc* expr,int index, string &string_out);
+
+
+static int formxdata_print_value(Dwarf_Debug dbg,
+ Dwarf_Attribute attrib, string &str_out,
+ Dwarf_Error * err,bool hexout);
+
+// This following variable is weird. ???
+static bool local_symbols_already_began = false;
+
+typedef string(*encoding_type_func) (unsigned int val,bool doprintingonerr);
+
+Dwarf_Off fde_offset_for_cu_low = DW_DLV_BADOFFSET;
+Dwarf_Off fde_offset_for_cu_high = DW_DLV_BADOFFSET;
+
+/* Indicators to record a pair [low,high], these
+ are used in printing DIEs to accumulate the high
+ and low pc across attributes and to record the pair
+ as soon as both are known. Probably would be better to
+ use variables as arguments to
+ print_attribute(). */
+static Dwarf_Addr lowAddr = 0;
+static Dwarf_Addr highAddr = 0;
+static bool bSawLow = false;
+static bool bSawHigh = false;
+
+/* The following too is related to high and low pc
+attributes of a function. It's misnamed, it really means
+'yes, we have high and low pc' if it is TRUE. Defaulting to TRUE
+seems bogus. */
+static Dwarf_Bool in_valid_code = true;
+
+
+struct operation_descr_s {
+ int op_code;
+ int op_count;
+ string op_1type;
+};
+struct operation_descr_s opdesc[]= {
+ {DW_OP_addr,1,"addr" },
+ {DW_OP_deref,0 },
+ {DW_OP_const1u,1,"1u" },
+ {DW_OP_const1s,1,"1s" },
+ {DW_OP_const2u,1,"2u" },
+ {DW_OP_const2s,1,"2s" },
+ {DW_OP_const4u,1,"4u" },
+ {DW_OP_const4s,1,"4s" },
+ {DW_OP_const8u,1,"8u" },
+ {DW_OP_const8s,1,"8s" },
+ {DW_OP_constu,1,"uleb" },
+ {DW_OP_consts,1,"sleb" },
+ {DW_OP_dup,0,""},
+ {DW_OP_drop,0,""},
+ {DW_OP_over,0,""},
+ {DW_OP_pick,1,"1u"},
+ {DW_OP_swap,0,""},
+ {DW_OP_rot,0,""},
+ {DW_OP_xderef,0,""},
+ {DW_OP_abs,0,""},
+ {DW_OP_and,0,""},
+ {DW_OP_div,0,""},
+ {DW_OP_minus,0,""},
+ {DW_OP_mod,0,""},
+ {DW_OP_mul,0,""},
+ {DW_OP_neg,0,""},
+ {DW_OP_not,0,""},
+ {DW_OP_or,0,""},
+ {DW_OP_plus,0,""},
+ {DW_OP_plus_uconst,1,"uleb"},
+ {DW_OP_shl,0,""},
+ {DW_OP_shr,0,""},
+ {DW_OP_shra,0,""},
+ {DW_OP_xor,0,""},
+ {DW_OP_skip,1,"2s"},
+ {DW_OP_bra,1,"2s"},
+ {DW_OP_eq,0,""},
+ {DW_OP_ge,0,""},
+ {DW_OP_gt,0,""},
+ {DW_OP_le,0,""},
+ {DW_OP_lt,0,""},
+ {DW_OP_ne,0,""},
+ /* lit0 thru reg31 handled specially, no operands */
+ /* breg0 thru breg31 handled specially, 1 operand */
+ {DW_OP_regx,1,"uleb"},
+ {DW_OP_fbreg,1,"sleb"},
+ {DW_OP_bregx,2,"uleb"},
+ {DW_OP_piece,1,"uleb"},
+ {DW_OP_deref_size,1,"1u"},
+ {DW_OP_xderef_size,1,"1u"},
+ {DW_OP_nop,0,""},
+ {DW_OP_push_object_address,0,""},
+ {DW_OP_call2,1,"2u"},
+ {DW_OP_call4,1,"4u"},
+ {DW_OP_call_ref,1,"off"},
+ {DW_OP_form_tls_address,0,""},
+ {DW_OP_call_frame_cfa,0,""},
+ {DW_OP_bit_piece,2,"uleb"},
+ {DW_OP_implicit_value,2,"uleb"},
+ {DW_OP_stack_value,0,""},
+ {DW_OP_GNU_uninit,0,""},
+ {DW_OP_GNU_encoded_addr,1,"addr"},
+ {DW_OP_GNU_implicit_pointer,1,"addr" },
+ {DW_OP_GNU_entry_value,1,"val" },
+ /* terminator */
+ {0,0,""}
+};
+
+static void
+print_die_and_children_internal(DieHolder &die_in,
+ Dwarf_Bool is_info,
+ vector<DieHolder> &dieVec,
+ int &indent_level,
+ SrcfilesHolder & srcfiles);
+
+static bool
+print_as_info_or_cu()
+{
+ return (info_flag || cu_name_flag);
+}
+
+static int
+print_one_die_section(Dwarf_Debug dbg,bool is_info);
+
+/* process each compilation unit in .debug_info */
+void
+print_infos(Dwarf_Debug dbg,bool is_info)
+{
+ int nres = 0;
+ if(is_info) {
+ error_message_data.current_section_id = DEBUG_INFO;
+ nres = print_one_die_section(dbg,true);
+ if (nres == DW_DLV_ERROR) {
+ string errmsg = dwarf_errmsg(err);
+ Dwarf_Unsigned myerr = dwarf_errno(err);
+
+ cerr << program_name << " ERROR: " <<
+ "attempting to print .debug_info: " <<
+ errmsg << " (" << myerr << ")" << endl;
+ cerr << "attempting to continue." << endl;
+ }
+ return;
+ }
+ error_message_data.current_section_id = DEBUG_TYPES;
+ nres = print_one_die_section(dbg,false);
+ if (nres == DW_DLV_ERROR) {
+ string errmsg = dwarf_errmsg(err);
+ Dwarf_Unsigned myerr = dwarf_errno(err);
+
+ cerr << program_name << " ERROR: " <<
+ "attempting to print .debug_types: " <<
+ errmsg << " (" << myerr << ")" << endl;
+ cerr << "attempting to continue." << endl;
+ }
+}
+
+static void
+print_std_cu_hdr( Dwarf_Unsigned cu_header_length,
+ Dwarf_Unsigned abbrev_offset,
+ Dwarf_Half version_stamp,
+ Dwarf_Half address_size)
+{
+ if(dense) {
+ cout << " cu_header_length" <<
+ BracketSurround(IToHex0N(cu_header_length,10));
+ cout << " version_stamp" <<
+ BracketSurround(IToHex0N(version_stamp,6));
+ cout << " abbrev_offset" <<
+ BracketSurround(IToHex0N(abbrev_offset,10));
+ cout << " address_size" <<
+ BracketSurround(IToHex0N(address_size,4));
+ } else {
+ cout << " cu_header_length = " <<
+ IToHex0N(cu_header_length,10) <<
+ " " << IToDec(cu_header_length) << endl;
+ cout << " version_stamp = " <<
+ IToHex0N(version_stamp,6) <<
+ " " <<
+ " " << IToDec(version_stamp) << endl;
+ cout << " abbrev_offset = " <<
+ IToHex0N(abbrev_offset,10) <<
+ " " << IToDec(abbrev_offset) << endl;
+ cout << " address_size = " <<
+ IToHex0N(address_size,4) <<
+ " " <<
+ " " << IToDec(address_size) << endl;
+ }
+}
+static void
+print_std_cu_signature( Dwarf_Sig8 *signature,Dwarf_Unsigned typeoffset)
+{
+ if(dense) {
+ string sig8str;
+ format_sig8_string(signature,sig8str);
+ cout << " signature" <<
+ BracketSurround(sig8str);
+ cout << " typeoffset" <<
+ BracketSurround(IToHex0N(typeoffset,10));
+ } else {
+ string sig8str;
+ format_sig8_string(signature,sig8str);
+ cout << " signature = " <<
+ sig8str << endl;
+ cout << " typeoffset = " <<
+ IToHex0N(typeoffset,10) <<
+ " " << IToDec(typeoffset) << endl;
+ }
+}
+
+static int
+print_one_die_section(Dwarf_Debug dbg,bool is_info)
+{
+ Dwarf_Unsigned cu_header_length = 0;
+ Dwarf_Unsigned abbrev_offset = 0;
+ Dwarf_Half version_stamp = 0;
+ Dwarf_Half address_size = 0;
+ Dwarf_Half extension_size = 0;
+ Dwarf_Half length_size = 0;
+ Dwarf_Sig8 signature;
+ Dwarf_Unsigned typeoffset = 0;
+ Dwarf_Unsigned next_cu_offset = 0;
+ int nres = DW_DLV_OK;
+ int cu_count = 0;
+ unsigned loop_count = 0;
+ Dwarf_Bool local_is_info = (is_info)?true:false;
+ if (print_as_info_or_cu() && do_print_dwarf) {
+ if(is_info) {
+ cout << endl;
+ cout << ".debug_info" << endl;
+ }
+ }
+ /* Loop until it fails. */
+ for (;;++loop_count) {
+ nres = dwarf_next_cu_header_c(dbg, is_info,
+ &cu_header_length, &version_stamp,
+ &abbrev_offset, &address_size,
+ &length_size, &extension_size,
+ &signature, &typeoffset,
+ &next_cu_offset, &err);
+ if(nres == DW_DLV_NO_ENTRY) {
+ return nres;
+ }
+ if(loop_count == 0 && !is_info &&
+ // Do not print this string unless we really have debug_types
+ // for consistency with dwarf2/3 output.
+ // Looks a bit messy here in the code, but few objects have
+ // this section so far.
+ print_as_info_or_cu() && do_print_dwarf) {
+ cout << endl;
+ cout << ".debug_types" << endl;
+ }
+ if(nres != DW_DLV_OK) {
+ return nres;
+ }
+ if(cu_count >= break_after_n_units) {
+ cout << "Break at " << cu_count << endl;
+ break;
+ }
+ Dwarf_Die cu_die = 0;
+ int sres = dwarf_siblingof_b(dbg, NULL,is_info, &cu_die, &err);
+ if (sres != DW_DLV_OK) {
+ print_error(dbg, "siblingof cu header", sres, err);
+ }
+ /* Get the CU offset for easy error reporting */
+ dwarf_die_offsets(cu_die,
+ &error_message_data.DIE_overall_offset,
+ &error_message_data.DIE_offset,&err);
+ DieHolder thcu_die(dbg,cu_die);
+ if (cu_name_flag) {
+ if(should_skip_this_cu(thcu_die,err)) {
+ ++cu_count;
+ cu_offset = next_cu_offset;
+ continue;
+ }
+ }
+ string producer_name;
+ get_producer_name(thcu_die,err,producer_name);
+
+ update_compiler_target(producer_name);
+ if (producer_children_flag) {
+ string cu_short_name;
+ string cu_long_name;
+ get_cu_name(thcu_die,err,cu_short_name,cu_long_name);
+ add_cu_name_compiler_target(cu_long_name);
+ }
+ if(!checking_this_compiler()) {
+ ++cu_count;
+ cu_offset = next_cu_offset;
+ continue;
+ }
+ error_message_data.seen_CU = false;
+ error_message_data.need_CU_name = true;
+ error_message_data.need_CU_base_address = true;
+ error_message_data.need_CU_high_address = true;
+ error_message_data.seen_PU_base_address = false;
+ error_message_data.seen_PU_high_address = false;
+
+ if (info_flag && do_print_dwarf ) {
+ if(verbose){
+ if (dense) {
+ cout << BracketSurround("cu_header");
+ } else {
+ cout << endl;
+ cout << "CU_HEADER:" << endl;
+ }
+ print_std_cu_hdr(cu_header_length, abbrev_offset,
+ version_stamp,address_size);
+ if(! is_info) {
+ print_std_cu_signature(&signature,typeoffset);
+ }
+ if(dense) {
+ cout <<endl;
+ }
+ } else {
+ // For debug_types we really need some header info
+ // to make sense of this.
+ if(!is_info) {
+ if(dense) {
+ cout << BracketSurround("cu_header");
+ } else {
+ cout << endl;
+ cout << "CU_HEADER:" << endl;
+ }
+ print_std_cu_signature(&signature,typeoffset);
+ if(dense) {
+ cout <<endl;
+ }
+ }
+ }
+ }
+ get_abbrev_array_info(dbg,abbrev_offset);
+
+ Dwarf_Die cu_die2 = 0;
+ sres = dwarf_siblingof_b(dbg, NULL,is_info, &cu_die2, &err);
+ if (sres == DW_DLV_OK) {
+ DieHolder hcu_die2(dbg,cu_die2);
+ if (print_as_info_or_cu() || search_is_on) {
+ Dwarf_Signed cnt = 0;
+ char **srcfiles = 0;
+ int srcf = dwarf_srcfiles(hcu_die2.die(),
+ &srcfiles,&cnt, &err);
+ if (srcf != DW_DLV_OK) {
+ srcfiles = 0;
+ cnt = 0;
+ }
+ SrcfilesHolder hsrcfiles(dbg,srcfiles,cnt);
+ /* Get the CU offset for easy error reporting */
+ dwarf_die_offsets(hcu_die2.die(),
+ &error_message_data.DIE_CU_overall_offset,
+ &error_message_data.DIE_CU_offset,
+ &err);
+ print_die_and_children(hcu_die2,is_info, hsrcfiles);
+ }
+ if (dump_ranges_info) {
+ pAddressRangesData->PrintRangesData();
+ }
+
+ if (line_flag || check_decl_file) {
+ print_line_numbers_this_cu(hcu_die2);
+ }
+ } else if (sres == DW_DLV_NO_ENTRY) {
+ /* do nothing I guess. */
+ } else {
+ print_error(dbg, "Regetting cu_die", sres, err);
+ }
+ ++cu_count;
+ cu_offset = next_cu_offset;
+ }
+ return nres;
+}
+
+
+static void
+print_a_die_stack(Dwarf_Debug dbg,SrcfilesHolder & hsrcfiles,int lev,
+ vector<DieHolder> &dieVec)
+{
+ bool ignore_die_stack = false;
+ bool print_information = true;
+ print_one_die(dieVec[lev],print_information,lev,hsrcfiles,
+ ignore_die_stack);
+}
+
+void
+print_die_and_children(DieHolder & in_die_in,
+ Dwarf_Bool is_info,
+ SrcfilesHolder &hsrcfiles)
+{
+ int indent_level = 0;
+
+ vector<DieHolder> dieVec;
+ print_die_and_children_internal(in_die_in,
+ is_info,
+ dieVec,
+ indent_level, hsrcfiles);
+ return;
+}
+
+static void
+print_die_stack(DieHolder &curdie, vector<DieHolder> &dieVec,
+ SrcfilesHolder & hsrcfiles)
+{
+ unsigned lev = 0;
+ bool print_information = true;
+ bool ignore_die_stack = false;
+
+ for(lev = 0; lev < dieVec.size(); ++lev)
+ {
+ print_one_die(dieVec[lev],print_information,lev,hsrcfiles,
+ /* ignore_die_printed_flag= */ignore_die_stack);
+ }
+}
+
+
+// Recursively follow the die tree
+static void
+print_die_and_children_internal(DieHolder & hin_die_in,
+ Dwarf_Bool is_info,
+ vector<DieHolder> &dieVec,
+ int &indent_level,
+ SrcfilesHolder & hsrcfiles)
+{
+ Dwarf_Die child;
+ Dwarf_Error err;
+ int tres;
+ int cdres;
+ DieHolder hin_die(hin_die_in);
+ Dwarf_Debug dbg = hin_die_in.dbg();
+
+ for (;;) {
+ // We loop on siblings, this is the sibling loop.
+ dieVec.push_back(hin_die);
+ Dwarf_Die in_die = hin_die.die();
+ /* Get the CU offset for easy error reporting */
+ dwarf_die_offsets(in_die,
+ &error_message_data.DIE_overall_offset,
+ &error_message_data.DIE_offset,
+ &err);
+ if (check_tag_tree) {
+ DWARF_CHECK_COUNT(tag_tree_result,1);
+ if (indent_level == 0) {
+ Dwarf_Half tag;
+
+ tres = dwarf_tag(in_die, &tag, &err);
+ if (tres != DW_DLV_OK) {
+ DWARF_CHECK_ERROR(tag_tree_result,
+ "Tag-tree root is not DW_TAG_compile_unit");
+ } else if (tag == DW_TAG_compile_unit) {
+ /* OK */
+ } else {
+ DWARF_CHECK_ERROR(tag_tree_result,
+ "tag-tree root is not DW_TAG_compile_unit");
+ }
+ } else {
+ Dwarf_Half tag_parent = 0;
+ Dwarf_Half tag_child = 0;
+ string ctagname("<child tag invalid>");
+ string ptagname("<parent tag invalid>");
+
+ Dwarf_Die tp = dieVec[indent_level - 1].die();
+ int pres = dwarf_tag(tp, &tag_parent, &err);
+ int cres = dwarf_tag(in_die, &tag_child, &err);
+ if (pres != DW_DLV_OK)
+ tag_parent = 0;
+ if (cres != DW_DLV_OK)
+ tag_child = 0;
+ /* Check for specific compiler */
+ if (checking_this_compiler()) {
+ /* Process specific TAGs. */
+ tag_specific_checks_setup(tag_child, indent_level);
+
+ if (cres != DW_DLV_OK || pres != DW_DLV_OK) {
+ if (cres == DW_DLV_OK) {
+ ctagname = get_TAG_name(tag_child,
+ dwarf_names_print_on_error);
+ }
+ if (pres == DW_DLV_OK) {
+ ptagname = get_TAG_name(tag_parent,
+ dwarf_names_print_on_error);
+ }
+ DWARF_CHECK_ERROR3(tag_tree_result,ptagname,
+ ctagname,
+ "Tag-tree relation is not standard..");
+ } else if (legal_tag_tree_combination(tag_parent,
+ tag_child)) {
+ /* OK */
+ } else {
+ DWARF_CHECK_ERROR3(tag_tree_result,
+ get_TAG_name(tag_parent,
+ dwarf_names_print_on_error),
+ get_TAG_name(tag_child,
+ dwarf_names_print_on_error),
+ "tag-tree relation is not standard.");
+ }
+ }
+ }
+ }
+ if (record_dwarf_error && check_verbose_mode) {
+ record_dwarf_error = false;
+ }
+
+ /* here to pre-descent processing of the die */
+ bool retry_print_on_match =
+ print_one_die(hin_die, print_as_info_or_cu(),
+ indent_level, hsrcfiles,
+ /* ignore_die_printed_flag= */ false);
+ if(!print_as_info_or_cu() && retry_print_on_match) {
+ if(display_parent_tree) {
+ print_die_stack(hin_die,dieVec,hsrcfiles);
+ } else {
+ if(display_children_tree) {
+ print_a_die_stack(dbg,hsrcfiles,indent_level,dieVec);
+ }
+ }
+ if(display_children_tree) {
+ stop_indent_level = indent_level;
+ info_flag = true;
+ }
+ }
+ cdres = dwarf_child(in_die, &child, &err);
+
+ /* Check for specific compiler */
+ if (check_abbreviations && checking_this_compiler()) {
+ Dwarf_Half ab_has_child;
+ bool berror = false;
+ Dwarf_Half tag = 0;
+ tres = dwarf_die_abbrev_children_flag(in_die,&ab_has_child);
+ if (tres == DW_DLV_OK) {
+ DWARF_CHECK_COUNT(abbreviations_result,1);
+ tres = dwarf_tag(in_die, &tag, &err);
+ if (tres == DW_DLV_OK) {
+ switch (tag) {
+ case DW_TAG_array_type:
+ case DW_TAG_class_type:
+ case DW_TAG_compile_unit:
+ case DW_TAG_enumeration_type:
+ case DW_TAG_lexical_block:
+ case DW_TAG_namespace:
+ case DW_TAG_structure_type:
+ case DW_TAG_subprogram:
+ case DW_TAG_subroutine_type:
+ case DW_TAG_union_type:
+ case DW_TAG_entry_point:
+ case DW_TAG_inlined_subroutine:
+ break;
+ default:
+ berror = (cdres == DW_DLV_OK && !ab_has_child) ||
+ (cdres == DW_DLV_NO_ENTRY && ab_has_child);
+ if (berror) {
+ DWARF_CHECK_ERROR(abbreviations_result,
+ "check 'dw_children' flag combination.");
+ }
+ break;
+ }
+ }
+ }
+ }
+
+
+ /* child first: we are doing depth-first walk */
+ if (cdres == DW_DLV_OK) {
+ DieHolder hchild(dbg,child);
+ indent_level++;
+ print_die_and_children_internal(hchild,
+ is_info,
+ dieVec,indent_level,hsrcfiles);
+ indent_level--;
+ if (indent_level == 0) {
+ local_symbols_already_began = false;
+ }
+ } else if (cdres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_child", cdres, err);
+ }
+
+ /* Stop the display of all children */
+ if (display_children_tree && info_flag &&
+ stop_indent_level == indent_level) {
+ info_flag = false;
+ }
+
+ Dwarf_Die sibling = 0;
+ cdres = dwarf_siblingof_b(dbg, in_die,is_info, &sibling, &err);
+ if (cdres == DW_DLV_OK) {
+ /* print_die_and_children_internal(); We
+ loop around to actually print this, rather than
+ recursing. Recursing is horribly wasteful of stack
+ space. */
+ } else if (cdres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_siblingof", cdres, err);
+ }
+ DieHolder hsibling(dbg,sibling);
+ /* If we have a sibling, verify that its offset
+ is next to the last processed DIE;
+ An incorrect sibling chain is a nasty bug. */
+ if (cdres == DW_DLV_OK && sibling && check_di_gaps &&
+ checking_this_compiler()) {
+
+ Dwarf_Off glb_off;
+ DWARF_CHECK_COUNT(di_gaps_result,1);
+ if (dwarf_validate_die_sibling(sibling,&glb_off) == DW_DLV_ERROR) {
+ static char msg[128];
+ Dwarf_Off sib_off;
+ dwarf_dieoffset(sibling,&sib_off,&err);
+ sprintf(msg,
+ "GSIB = 0x%" DW_PR_XZEROS DW_PR_DUx
+ " GOFF = 0x%" DW_PR_XZEROS DW_PR_DUx
+ " Gap = %" DW_PR_DUu " bytes",
+ sib_off,glb_off,sib_off-glb_off);
+ DWARF_CHECK_ERROR2(di_gaps_result,
+ "Incorrect sibling chain",msg);
+ }
+ }
+
+
+ /* Here do any post-descent (ie post-dwarf_child) processing of
+ the in_die (just pop stack). */
+ dieVec.pop_back();
+ if (cdres == DW_DLV_OK) {
+ /* Set to process the sibling, loop again. */
+ hin_die = hsibling;
+ } else {
+ /* We are done, no more siblings at this level. */
+ break;
+ }
+ } /* end for loop on siblings */
+ return;
+}
+
+/* Print one die on error and verbose or non check mode */
+#define PRINTING_DIES (do_print_dwarf || (record_dwarf_error && check_verbose_mode))
+
+/* This is called from the debug_line printing and the DIE
+ passed in is a CU DIE.
+ In other cases the DIE passed in is not a CU die.
+ */
+
+bool
+print_one_die(DieHolder & hdie,
+ bool print_information,
+ int die_indent_level,
+ SrcfilesHolder &hsrcfiles,
+ bool ignore_die_printed_flag)
+{
+ Dwarf_Die die = hdie.die();
+ Dwarf_Debug dbg = hdie.dbg();
+ int abbrev_code = dwarf_die_abbrev_code(die);
+ bool attribute_matched = false;
+
+ /* Print using indentation
+ < 1><0x000854ff GOFF=0x00546047> DW_TAG_pointer_type -> 34
+ < 1><0x000854ff> DW_TAG_pointer_type -> 18
+ DW_TAG_pointer_type -> 2
+ */
+ /* Attribute indent. */
+ int nColumn = show_global_offsets ? 34 : 18;
+
+ if (check_abbreviations && checking_this_compiler()) {
+ validate_abbrev_code(dbg,abbrev_code);
+ }
+
+
+ if(!ignore_die_printed_flag && hdie.die_printed()) {
+ /* Seems arbitrary as a return, but ok. */
+ return false;
+ }
+ /* Reset indentation column if no offsets */
+ if (!display_offsets) {
+ nColumn = 2;
+ }
+
+ Dwarf_Half tag = 0;
+ int tres = dwarf_tag(die, &tag, &err);
+ if (tres != DW_DLV_OK) {
+ print_error(dbg, "accessing tag of die!", tres, err);
+ }
+ string tagname = get_TAG_name(tag,dwarf_names_print_on_error);
+
+ tag_specific_checks_setup(tag,die_indent_level);
+ Dwarf_Off overall_offset = 0;
+ int ores = dwarf_dieoffset(die, &overall_offset, &err);
+ if (ores != DW_DLV_OK) {
+ print_error(dbg, "dwarf_dieoffset", ores, err);
+ }
+ Dwarf_Off offset = 0;
+ ores = dwarf_die_CU_offset(die, &offset, &err);
+ if (ores != DW_DLV_OK) {
+ print_error(dbg, "dwarf_die_CU_offset", ores, err);
+ }
+ if (dump_visited_info && check_self_references) {
+ unsigned space = die_indent_level * 2 + 2;
+ cout << BracketSurround(IToDec(die_indent_level,2)) <<
+ BracketSurround(IToHex0N(offset,10)) <<
+ " GOFF=" << IToHex0N(overall_offset,10) <<
+ std::setw(space) << " " << tagname << endl;
+ }
+
+
+ if (PRINTING_DIES && print_information) {
+ if(!ignore_die_printed_flag) {
+ hdie.mark_die_printed();
+ }
+ if (die_indent_level == 0) {
+ if (dense) {
+ cout << endl;
+ } else {
+ cout << endl;
+ cout << "COMPILE_UNIT<header overall offset = "
+ << IToHex0N((overall_offset - offset),10) << ">:" << endl;
+ }
+ } else if (local_symbols_already_began == false &&
+ die_indent_level == 1 && !dense) {
+ cout << endl;
+ // This prints once per top-level DIE.
+ cout <<"LOCAL_SYMBOLS:" << endl;
+ local_symbols_already_began = true;
+ }
+ if (!display_offsets) {
+ /* Print using indentation */
+ unsigned w = die_indent_level * 2 + 2;
+ cout << std::setw(w) << " " << tagname << endl;
+ } else {
+ if (dense) {
+ if (show_global_offsets) {
+ if (die_indent_level == 0) {
+ cout << BracketSurround(IToDec(die_indent_level)) <<
+ BracketSurround(
+ IToHex(overall_offset - offset) +
+ string("+") +
+ IToHex(offset) +
+ string(" GOFF=") +
+ IToHex(overall_offset));
+ } else {
+ cout << BracketSurround(IToDec(die_indent_level)) <<
+ BracketSurround(
+ IToHex(offset) +
+ string(" GOFF=") +
+ IToHex(overall_offset));
+ }
+ } else {
+ if (die_indent_level == 0) {
+ cout << BracketSurround(IToDec(die_indent_level)) <<
+ BracketSurround(
+ IToHex(overall_offset - offset) +
+ string("+") +
+ IToHex(offset));
+ } else {
+ cout << BracketSurround(IToDec(die_indent_level)) <<
+ BracketSurround(IToHex(offset));
+ }
+ }
+ cout << BracketSurround(tagname);
+ if(verbose) {
+ cout << " " << BracketSurround(string("abbrev ") +
+ IToDec(abbrev_code));
+ }
+ } else {
+ if (show_global_offsets) {
+ cout << BracketSurround(IToDec(die_indent_level,2)) <<
+ BracketSurround(
+ IToHex0N(offset,10) +
+ string(" GOFF=") +
+ IToHex0N(overall_offset,10));
+ } else {
+ cout << BracketSurround(IToDec(die_indent_level,2)) <<
+ BracketSurround(IToHex0N(offset,10));
+ }
+ unsigned fldwidth = die_indent_level * 2 + 2;
+ cout << std::setw(fldwidth)<< " " << tagname;
+ if(verbose) {
+ cout << " " << BracketSurround(string("abbrev ") +
+ IToDec(abbrev_code));
+ }
+ cout << endl;
+ }
+ }
+ }
+
+ Dwarf_Signed atcnt = 0;
+ Dwarf_Attribute *atlist = 0;
+ int atres = dwarf_attrlist(die, &atlist, &atcnt, &err);
+ if (atres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_attrlist", atres, err);
+ } else if (atres == DW_DLV_NO_ENTRY) {
+ /* indicates there are no attrs. It is not an error. */
+ atcnt = 0;
+ }
+
+ /* Reset any loose references to low or high PC */
+ bSawLow = false;
+ bSawHigh = false;
+
+ /* Get the CU offset for easy error reporting */
+ dwarf_die_offsets(hdie.die(),
+ &error_message_data.DIE_CU_overall_offset,
+ &error_message_data.DIE_CU_offset,
+ &err);
+
+ for (Dwarf_Signed i = 0; i < atcnt; i++) {
+ Dwarf_Half attr;
+ int ares;
+
+ ares = dwarf_whatattr(atlist[i], &attr, &err);
+ if (ares == DW_DLV_OK) {
+ /* Print using indentation */
+ if (!dense && PRINTING_DIES && print_information) {
+ unsigned fldwidth = die_indent_level * 2 + 2 +nColumn;
+ cout << std::setw(fldwidth)<< " " ;
+ }
+
+ bool attr_match = print_attribute(dbg, die, attr,
+ atlist[i],
+ print_information,die_indent_level, hsrcfiles);
+ if(print_information == false && attr_match) {
+ attribute_matched = true;
+ }
+ if (record_dwarf_error && check_verbose_mode) {
+ record_dwarf_error = false;
+ }
+ } else {
+ print_error(dbg, "dwarf_whatattr entry missing", ares, err);
+ }
+ }
+
+ for (Dwarf_Signed i = 0; i < atcnt; i++) {
+ dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);
+ }
+ if (atres == DW_DLV_OK) {
+ dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
+ }
+
+ if (PRINTING_DIES && dense && print_information) {
+ cout << endl ;
+ }
+ return attribute_matched;
+}
+
+/* Encodings have undefined signedness. Accept either
+ signedness. The values are small (they are defined
+ in the DWARF specification), so the
+ form the compiler uses (as long as it is
+ a constant value) is a non-issue.
+
+ If string_out is non-NULL, construct a string output, either
+ an error message or the name of the encoding.
+ The function pointer passed in is to code generated
+ by a script at dwarfdump build time. The code for
+ the val_as_string function is generated
+ from dwarf.h. See <build dir>/dwarf_names.c
+
+ If string_out is non-NULL then attr_name and val_as_string
+ must also be non-NULL.
+
+*/
+static int
+get_small_encoding_integer_and_name(Dwarf_Debug dbg,
+ Dwarf_Attribute attrib,
+ Dwarf_Unsigned * uval_out,
+ const string &attr_name,
+ string * string_out,
+ encoding_type_func val_as_string,
+ Dwarf_Error * err,
+ bool show_form)
+{
+ Dwarf_Unsigned uval = 0;
+ int vres = dwarf_formudata(attrib, &uval, err);
+ if (vres != DW_DLV_OK) {
+ Dwarf_Signed sval = 0;
+ vres = dwarf_formsdata(attrib, &sval, err);
+ if (vres != DW_DLV_OK) {
+ vres = dwarf_global_formref(attrib,&uval,err);
+ if (vres != DW_DLV_OK) {
+ if (string_out != 0) {
+ string b = attr_name + " has a bad form.";
+ *string_out = b;
+ }
+ return vres;
+ }
+ *uval_out = uval;
+ } else {
+ *uval_out = (Dwarf_Unsigned) sval;
+ }
+ } else {
+ *uval_out = uval;
+ }
+ if (string_out) {
+ *string_out = val_as_string((unsigned) uval,
+ dwarf_names_print_on_error);
+ Dwarf_Half theform = 0;
+ Dwarf_Half directform = 0;
+ get_form_values(attrib,theform,directform);
+ show_form_itself(show_form,verbose, theform, directform,string_out);
+ }
+ return DW_DLV_OK;
+}
+
+
+
+
+/* We need a 32-bit signed number here, but there's no portable
+ way of getting that. So use __uint32_t instead. It's supplied
+ in a reliable way by the autoconf infrastructure. */
+static string
+get_FLAG_BLOCK_string(Dwarf_Debug dbg, Dwarf_Attribute attrib)
+{
+ int fres = 0;
+ Dwarf_Block *tempb = 0;
+ __uint32_t * array = 0;
+ Dwarf_Unsigned array_len = 0;
+ __uint32_t * array_ptr;
+ Dwarf_Unsigned array_remain = 0;
+
+ /* first get compressed block data */
+ fres = dwarf_formblock (attrib,&tempb, &err);
+ if (fres != DW_DLV_OK) {
+ string msg("DW_FORM_blockn cannot get block");
+ print_error(dbg,msg,fres,err);
+ return msg;
+ }
+
+ /* uncompress block into int array */
+ void *vd = dwarf_uncompress_integer_block(dbg,
+ 1, /* 'true' (meaning signed ints)*/
+ 32, /* bits per unit */
+ reinterpret_cast<void *>(tempb->bl_data),
+ tempb->bl_len,
+ &array_len, /* len of out array */
+ &err);
+ if (vd == reinterpret_cast<void *>(DW_DLV_BADADDR)) {
+ string msg("DW_AT_SUN_func_offsets cannot uncompress data");
+ print_error(dbg,msg,0,err);
+ return msg;
+ }
+ array = reinterpret_cast<__uint32_t *>(vd);
+ if (array_len == 0) {
+ string msg("DW_AT_SUN_func_offsets has no data");
+ print_error(dbg,msg,0,err);
+ return msg;
+ }
+
+ /* fill in string buffer */
+ array_remain = array_len;
+ array_ptr = array;
+ const unsigned array_lim = 8;
+ string blank(" ");
+ string out_str;
+ while (array_remain > array_lim) {
+ out_str.append("\n");
+ for(unsigned j = 0; j < array_lim; ++j) {
+ out_str.append(blank + IToHex0N(array_ptr[0],10));
+ }
+ array_ptr += array_lim;
+ array_remain -= array_lim;
+ }
+
+ /* now do the last line */
+ if (array_remain > 0) {
+ out_str.append("\n ");
+ while (array_remain > 0) {
+ out_str.append(blank + IToHex0N(*array_ptr,10));
+ array_remain--;
+ array_ptr++;
+ }
+ }
+ /* free array buffer */
+ dwarf_dealloc_uncompressed_block(dbg, array);
+ return out_str;
+}
+
+static const char *
+get_rangelist_type_descr(Dwarf_Ranges *r)
+{
+ switch(r->dwr_type) {
+ case DW_RANGES_ENTRY: return "range entry";
+ case DW_RANGES_ADDRESS_SELECTION: return "addr selection";
+ case DW_RANGES_END: return "range end";
+ }
+ /* Impossible. */
+ return "Unknown";
+}
+
+
+string
+print_ranges_list_to_extra(Dwarf_Debug dbg,
+ Dwarf_Unsigned off,
+ Dwarf_Ranges *rangeset,
+ Dwarf_Signed rangecount,
+ Dwarf_Unsigned bytecount)
+{
+ string out;
+ if(dense) {
+ out.append("< ranges: ");
+ } else {
+ out.append("\t\tranges: ");
+ }
+ out.append(IToDec(rangecount));
+ if(dense) {
+ // This is a goofy difference. Historical.
+ out.append(" ranges at .debug_ranges offset ");
+ } else {
+ out.append(" at .debug_ranges offset ");
+ }
+ out.append(IToDec(off));
+ out.append(" (");
+ out.append(IToHex0N(off,10));
+ out.append(") (");
+ out.append(IToDec(bytecount));
+ out.append(" bytes)");
+ if(dense) {
+ out.append(">");
+ } else {
+ out.append("\n");
+ }
+ for(Dwarf_Signed i = 0; i < rangecount; ++i) {
+ Dwarf_Ranges * r = rangeset +i;
+ const char *type = get_rangelist_type_descr(r);
+ if(dense) {
+ out.append("<[");
+ } else {
+ out.append("\t\t\t[");
+ }
+ out.append(IToDec(i,2));
+ out.append("] ");
+ if(dense) {
+ out.append(type);
+ } else {
+ out.append(LeftAlign(14,type));
+ }
+ out.append(" ");
+ out.append(IToHex0N(r->dwr_addr1,10));
+ out.append(" ");
+ out.append(IToHex0N(r->dwr_addr2,10));
+ if(dense) {
+ out.append(">");
+ } else {
+ out.append("\n");
+ }
+ }
+ return out;
+}
+
+/* This is a slightly simplistic rendering of the FORM
+ issue, it is not precise. However it is really only
+ here so we can detect and report an error (producing
+ incorrect DWARF) by a particular compiler (a quite unusual error,
+ noticed in April 2010).
+ So this simplistic form suffices. See the libdwarf get_loclist_n()
+ function source for the precise test.
+*/
+static bool
+is_location_form(int form)
+{
+ if(form == DW_FORM_block1 ||
+ form == DW_FORM_block2 ||
+ form == DW_FORM_block4 ||
+ form == DW_FORM_block ||
+ form == DW_FORM_data4 ||
+ form == DW_FORM_data8 ||
+ form == DW_FORM_sec_offset) {
+ return true;
+ }
+ return false;
+}
+
+static void
+show_attr_form_error(Dwarf_Debug dbg,unsigned attr,unsigned form,string *out)
+{
+ const char *n = 0;
+ int res;
+ out->append("ERROR: Attribute ");
+ out->append(IToDec(attr));
+ out->append(" (");
+ res = dwarf_get_AT_name(attr,&n);
+ if(res != DW_DLV_OK) {
+ n = "UknownAttribute";
+ }
+ out->append(n);
+ out->append(") ");
+ out->append(" has form ");
+ out->append(IToDec(form));
+ out->append(" (");
+ res = dwarf_get_FORM_name(form,&n);
+ if(res != DW_DLV_OK) {
+ n = "UknownForm";
+ }
+ out->append(n);
+ out->append("), a form which is not appropriate");
+ print_error_and_continue(dbg, out->c_str(), DW_DLV_OK, err);
+}
+
+
+/* Traverse an attribute and following any reference
+ in order to detect self references to DIES (loop). */
+static bool
+traverse_attribute(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Half attr,
+ Dwarf_Attribute attr_in,
+ bool print_information,
+ SrcfilesHolder & hsrcfiles,
+ int die_indent_level)
+{
+ Dwarf_Attribute attrib = 0;
+ string atname;
+ string valname;
+ int tres = 0;
+ Dwarf_Half tag = 0;
+ bool circular_reference = false;
+ Dwarf_Bool is_info = true;
+
+ is_info=dwarf_get_die_infotypes_flag(die);
+
+ atname = get_AT_name(attr,dwarf_names_print_on_error);
+
+ /* The following gets the real attribute, even in the face of an
+ incorrect doubling, or worse, of attributes. */
+ attrib = attr_in;
+ /* Do not get attr via dwarf_attr: if there are (erroneously)
+ multiple of an attr in a DIE, dwarf_attr will not get the
+ second, erroneous one and dwarfdump will print the first one
+ multiple times. Oops. */
+
+ tres = dwarf_tag(die, &tag, &err);
+ if (tres == DW_DLV_ERROR) {
+ tag = 0;
+ } else if (tres == DW_DLV_NO_ENTRY) {
+ tag = 0;
+ } else {
+ /* ok */
+ }
+
+ switch (attr) {
+ case DW_AT_specification:
+ case DW_AT_abstract_origin:
+ case DW_AT_type: {
+ int res = 0;
+ Dwarf_Off die_off = 0;
+ Dwarf_Off ref_off = 0;
+ Dwarf_Die ref_die = 0;
+
+ ++die_indent_level;
+ get_attr_value(dbg, tag, die, attrib, hsrcfiles, valname,
+ show_form_used,verbose);
+ /* Get the global offset for reference */
+ res = dwarf_global_formref(attrib, &ref_off, &err);
+ if (res != DW_DLV_OK) {
+ int errno = dwarf_errno(err);
+ if (errno == DW_DLE_REF_SIG8_NOT_HANDLED ) {
+ // No need to stop, ref_sig8 refers out of
+ // the current section.
+ break;
+ } else {
+ print_error(dbg, "dwarf_global_formref fails in traversal",
+ res, err);
+ }
+ }
+ res = dwarf_dieoffset(die, &die_off, &err);
+ if (res != DW_DLV_OK) {
+ int errno = dwarf_errno(err);
+ if (errno == DW_DLE_REF_SIG8_NOT_HANDLED ) {
+ // No need to stop, ref_sig8 refers out of
+ // the current section.
+ break;
+ } else {
+ print_error(dbg, "dwarf_dieoffset fails in traversal",
+ res, err);
+ }
+ }
+
+ /* Follow reference chain, looking for self references */
+ res = dwarf_offdie_b(dbg,ref_off,is_info,&ref_die,&err);
+ if (res == DW_DLV_OK) {
+ DieHolder hdie(dbg,ref_die);
+ ++die_indent_level;
+ /* Dump visited information */
+ if (dump_visited_info) {
+ Dwarf_Off off = 0;
+ dwarf_die_CU_offset(die, &off, &err);
+ /* Check above call return status? FIXME */
+ cout << BracketSurround(IToDec(die_indent_level,2)) <<
+ "<" << IToHex0N(off,10) <<
+ " GOFF=" << IToHex0N(die_off,10) << "> ";
+ unsigned myindent= die_indent_level * 2 + 2;
+ cout << std::setw(myindent) << " " << atname <<
+ " -> " << valname << endl;
+ }
+ circular_reference = traverse_one_die(dbg,attrib,ref_die,
+ hsrcfiles,die_indent_level);
+ pVisitedOffsetData->DeleteVisitedOffset(die_off);
+ --die_indent_level;
+ }
+ }
+ break;
+ } /* End switch. */
+ return circular_reference;
+}
+
+/* Traverse one DIE in order to detect self references to DIES. */
+static bool
+traverse_one_die(Dwarf_Debug dbg, Dwarf_Attribute attrib, Dwarf_Die die,
+ SrcfilesHolder & hsrcfiles,
+ int die_indent_level)
+{
+ Dwarf_Half tag = 0;
+ Dwarf_Off overall_offset = 0;
+ bool circular_reference = false;
+ bool print_information = false;
+
+ int res = dwarf_tag(die, &tag, &err);
+ if (res != DW_DLV_OK) {
+ print_error(dbg, "accessing tag of die!", res, err);
+ }
+
+ res = dwarf_dieoffset(die, &overall_offset, &err);
+ if (res != DW_DLV_OK) {
+ print_error(dbg, "dwarf_dieoffset", res, err);
+ }
+
+ /* Print visited information */
+ if (dump_visited_info) {
+ Dwarf_Off offset = 0;
+ string tagname;
+ res = dwarf_die_CU_offset(die, &offset, &err);
+ if (res != DW_DLV_OK) {
+ print_error(dbg, "dwarf_die_CU_offsetC", res, err);
+ }
+ tagname = get_TAG_name(tag,dwarf_names_print_on_error);
+ cout << BracketSurround(IToDec(die_indent_level,2)) <<
+ "<" << IToHex0N(offset,10) <<
+ " GOFF=" << IToHex0N(overall_offset,10) << "> ";
+ unsigned myindent= die_indent_level * 2 + 2;
+ cout << std::setw(myindent) << " " << tagname;
+ }
+
+ DWARF_CHECK_COUNT(self_references_result,1);
+ if (pVisitedOffsetData->IsKnownOffset(overall_offset) ) {
+ string valname;
+ Dwarf_Half attr = 0;
+ string atname;
+ get_attr_value(dbg, tag, die, attrib, hsrcfiles,
+ valname, show_form_used,verbose);
+ dwarf_whatattr(attrib, &attr, &err);
+ atname = get_AT_name(attr,dwarf_names_print_on_error);
+
+ /* We have a self reference */
+ DWARF_CHECK_ERROR3(self_references_result,
+ "Invalid self reference to DIE: ",atname,valname);
+ circular_reference = true;
+ } else {
+ Dwarf_Attribute *atlist = 0;
+
+ /* Add current DIE */
+ pVisitedOffsetData->AddVisitedOffset(overall_offset);
+
+ Dwarf_Signed atcnt = 0;
+ res = dwarf_attrlist(die, &atlist, &atcnt, &err);
+ if (res == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_attrlist", res, err);
+ } else if (res == DW_DLV_NO_ENTRY) {
+ /* indicates there are no attrs. It is not an error. */
+ atcnt = 0;
+ }
+
+ for (Dwarf_Signed i = 0; i < atcnt; i++) {
+ Dwarf_Half attr = 0;
+ int ares = dwarf_whatattr(atlist[i], &attr, &err);
+ if (ares == DW_DLV_OK) {
+ circular_reference = traverse_attribute(dbg, die, attr,
+ atlist[i],
+ print_information, hsrcfiles,
+ die_indent_level);
+ } else {
+ print_error(dbg, "dwarf_whatattr entry missing",
+ ares, err);
+ }
+ }
+
+ for (Dwarf_Signed i = 0; i < atcnt; i++) {
+ dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);
+ }
+ if (res == DW_DLV_OK) {
+ dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
+ }
+
+ /* Delete current DIE */
+ pVisitedOffsetData->DeleteVisitedOffset(overall_offset);
+ }
+ return circular_reference;
+}
+
+
+
+/* Extracted this from print_attribute()
+ to get tolerable indents.
+ In other words to make it readable.
+ It uses global data fields excessively, but so does
+ print_attribute().
+ The majority of the code here is checking for
+ compiler errors. */
+static void
+print_range_attribute(Dwarf_Debug dbg,
+ Dwarf_Die die,
+ Dwarf_Half attr,
+ Dwarf_Attribute attr_in,
+ Dwarf_Half theform,
+ int dwarf_names_print_on_error,
+ bool print_information,
+ string &extra)
+{
+ Dwarf_Error err = 0;
+ Dwarf_Unsigned original_off = 0;
+ int fres = 0;
+
+ fres = dwarf_global_formref(attr_in, &original_off, &err);
+ if( fres == DW_DLV_OK) {
+ Dwarf_Ranges *rangeset = 0;
+ Dwarf_Signed rangecount = 0;
+ Dwarf_Unsigned bytecount = 0;
+ int rres = dwarf_get_ranges_a(dbg,original_off,
+ die,
+ &rangeset,
+ &rangecount,&bytecount,&err);
+ if(rres == DW_DLV_OK) {
+ /* Ignore ranges inside a stripped function */
+ if (check_ranges &&
+ in_valid_code && checking_this_compiler()) {
+ Dwarf_Unsigned off = original_off;
+
+ Dwarf_Signed index = 0;
+ Dwarf_Addr base_address = error_message_data.CU_base_address;
+ Dwarf_Addr lopc = 0;
+ Dwarf_Addr hipc = 0;
+ bool bError = false;
+
+ /* Ignore last entry, is the end-of-list */
+ for (index = 0; index < rangecount - 1; index++) {
+ Dwarf_Ranges *r = rangeset + index;
+
+ if (r->dwr_addr1 == error_message_data.elf_max_address) {
+ /* (0xffffffff,addr), use specific address (current PU address) */
+ base_address = r->dwr_addr2;
+ } else {
+ /* (offset,offset), update using CU address */
+ lopc = r->dwr_addr1 + base_address;
+ hipc = r->dwr_addr2 + base_address;
+ DWARF_CHECK_COUNT(ranges_result,1);
+
+ /* Check the low_pc and high_pc
+ are within a valid range in
+ the .text section */
+ if( pAddressRangesData->IsAddressInAddressRange(lopc)
+ &&
+ pAddressRangesData->IsAddressInAddressRange(hipc)){
+ /* Valid values; do nothing */
+ } else {
+ /* At this point may be we
+ are dealing with a
+ linkonce symbol */
+ if (pLinkOnceData->FindLinkOnceEntry(
+ error_message_data.PU_name,lopc,hipc)) {
+ /* Valid values; do nothing */
+ } else {
+ bError = true;
+ DWARF_CHECK_ERROR(ranges_result,
+ ".debug_ranges: Address outside a "
+ "valid .text range");
+ if (check_verbose_mode) {
+ cout << "Offset = " << IToHex0N(off,10) <<
+ ", Base = " << IToHex0N(base_address,10) <<
+ ", " <<
+ "Low = " << IToHex0N(lopc,10) <<
+ " (" << IToHex0N(r->dwr_addr1,10) <<
+ "), High = " << IToHex0N(hipc,10) <<
+ " (" << IToHex0N(r->dwr_addr2,10) <<
+ ")" << endl;
+ }
+ }
+ }
+ }
+ /* Each entry holds 2 addresses (offsets) */
+ off += error_message_data.elf_address_size * 2;
+ }
+ if (bError && check_verbose_mode) {
+ printf("\n");
+ }
+ }
+ if(print_information) {
+ extra = print_ranges_list_to_extra(dbg,original_off,
+ rangeset,rangecount,bytecount);
+ }
+ dwarf_ranges_dealloc(dbg,rangeset,rangecount);
+ } else if (rres == DW_DLV_ERROR) {
+ if (do_print_dwarf) {
+ printf("\ndwarf_get_ranges() "
+ "cannot find DW_AT_ranges at offset 0x%"
+ DW_PR_XZEROS DW_PR_DUx
+ " (0x%" DW_PR_XZEROS DW_PR_DUx ").",
+ original_off,
+ original_off);
+ } else {
+ DWARF_CHECK_COUNT(ranges_result,1);
+ DWARF_CHECK_ERROR2(ranges_result,
+ get_AT_name(attr,
+ dwarf_names_print_on_error),
+ " cannot find DW_AT_ranges at offset");
+ }
+ } else {
+ /* NO ENTRY */
+ if (do_print_dwarf) {
+ cout << endl;
+ cout << "dwarf_get_ranges() "
+ "finds no DW_AT_ranges at offset 0x% (" <<
+ IToHex0N(original_off,10) <<
+ " " <<
+ IToDec(original_off) <<
+ ").";
+ } else {
+ DWARF_CHECK_COUNT(ranges_result,1);
+ DWARF_CHECK_ERROR2(ranges_result,
+ get_AT_name(attr,
+ dwarf_names_print_on_error),
+ " fails to find DW_AT_ranges at offset");
+ }
+ }
+ } else {
+ if (do_print_dwarf) {
+ char tmp[100];
+
+ snprintf(tmp,sizeof(tmp)," attr 0x%x form 0x%x ",
+ (unsigned)attr,(unsigned)theform);
+ string local(" fails to find DW_AT_ranges offset");
+ local.append(tmp);
+ cout << " " << local << " ";
+ } else {
+ DWARF_CHECK_COUNT(ranges_result,1);
+ DWARF_CHECK_ERROR2(ranges_result,
+ get_AT_name(attr,
+ dwarf_names_print_on_error),
+ " fails to find DW_AT_ranges offset");
+ }
+ }
+}
+
+
+
+
+/* A DW_AT_name in a CU DIE will likely have dots
+ and be entirely sensible. So lets
+ not call things a possible error when they are not.
+ Some assemblers allow '.' in an identifier too.
+ We should check for that, but we don't yet.
+
+ We should check the compiler before checking
+ for 'altabi.' too (FIXME).
+
+ This is a heuristic, not all that reliable.
+
+ Return 0 if it is a vaguely standard identifier.
+ Else return 1, meaning 'it might be a file name
+ or have '.' in it quite sensibly.'
+
+ If we don't do the TAG check we might report "t.c"
+ as a questionable DW_AT_name. Which would be silly.
+*/
+static int
+dot_ok_in_identifier(int tag,Dwarf_Die die, const std::string val)
+{
+ if (strncmp(val.c_str(),"altabi.",7)) {
+ /* Ignore the names of the form 'altabi.name',
+ which apply to one specific compiler. */
+ return 1;
+ }
+ if(tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit ||
+ tag == DW_TAG_imported_unit || tag == DW_TAG_type_unit) {
+ return 1;
+ }
+ return 0;
+}
+
+static string
+trim_quotes(const string &val)
+{
+ if(val[0] == '"') {
+ size_t l = val.size();
+ if(l > 2 && val[l-1] == '"') {
+ string outv = val.substr(1,l-2);
+ return outv;
+ }
+ }
+ return val;
+}
+
+static int
+have_a_search_match(const string &valname,const string &atname)
+{
+ /* valname may have had quotes inserted, but search_match_text
+ will not. So we need to use a new copy, not valname here.
+ */
+ string match;
+ string s2;
+
+ match = trim_quotes(valname);
+ if (!search_match_text.empty()) {
+ if( (match == search_match_text) ||
+ (atname == search_match_text)) {
+ return true;
+ }
+ }
+ if (!search_any_text.empty()) {
+ if(is_strstrnocase(match.c_str(),search_any_text.c_str()) ||
+ is_strstrnocase(atname.c_str(),search_any_text.c_str())) {
+ return true;
+ }
+ }
+#ifdef HAVE_REGEX
+ if (!search_regex_text.empty()) {
+ if(!regexec(&search_re,match.c_str(),0,NULL,0) ||
+ !regexec(&search_re,atname.c_str(),0,NULL,0)) {
+
+ return true;
+ }
+ }
+#endif
+ return false;
+}
+
+
+
+static bool
+print_attribute(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Half attr,
+ Dwarf_Attribute attr_in,
+ bool print_information,
+ int die_indent_level,
+ SrcfilesHolder & hsrcfiles)
+{
+ Dwarf_Attribute attrib = 0;
+ Dwarf_Unsigned uval = 0;
+ string atname;
+ string valname;
+ string extra;
+ Dwarf_Half tag = 0;
+ bool found_search_attr = false;
+ bool bTextFound = false;
+ Dwarf_Bool is_info = true;
+
+ is_info=dwarf_get_die_infotypes_flag(die);
+ atname = get_AT_name(attr,dwarf_names_print_on_error);
+
+ /* The following gets the real attribute, even in the face of an
+ incorrect doubling, or worse, of attributes. */
+ attrib = attr_in;
+ /* Do not get attr via dwarf_attr: if there are (erroneously)
+ multiple of an attr in a DIE, dwarf_attr will not get the
+ second, erroneous one and dwarfdump will print the first one
+ multiple times. Oops. */
+
+ int tres = dwarf_tag(die, &tag, &err);
+ if (tres == DW_DLV_ERROR) {
+ tag = 0;
+ } else if (tres == DW_DLV_NO_ENTRY) {
+ tag = 0;
+ } else {
+ /* ok */
+ }
+ if (check_attr_tag && checking_this_compiler()) {
+ string tagname = "<tag invalid>";
+ DWARF_CHECK_COUNT(attr_tag_result,1);
+ if (tres == DW_DLV_ERROR) {
+ DWARF_CHECK_ERROR3(attr_tag_result,tagname,
+ get_AT_name(attr,dwarf_names_print_on_error),
+ "check the tag-attr combination, dwarf_tag failed.");
+ } else if (tres == DW_DLV_NO_ENTRY) {
+ DWARF_CHECK_ERROR3(attr_tag_result,tagname,
+ get_AT_name(attr,dwarf_names_print_on_error),
+ "check the tag-attr combination, dwarf_tag NO ENTRY?.");
+ } else if (legal_tag_attr_combination(tag, attr)) {
+ /* OK */
+ } else {
+ tagname = get_TAG_name(tag,dwarf_names_print_on_error);
+ tag_specific_checks_setup(tag,die_indent_level);
+ DWARF_CHECK_ERROR3(attr_tag_result,tagname,
+ get_AT_name(attr,dwarf_names_print_on_error),
+ "check the tag-attr combination");
+ }
+ }
+
+ switch (attr) {
+ case DW_AT_language:
+ get_small_encoding_integer_and_name(dbg, attrib, &uval,
+ "DW_AT_language", &valname,
+ get_LANG_name, &err,
+ show_form_used);
+ break;
+ case DW_AT_accessibility:
+ get_small_encoding_integer_and_name(dbg, attrib, &uval,
+ "DW_AT_accessibility",
+ &valname, get_ACCESS_name,
+ &err,
+ show_form_used);
+ break;
+ case DW_AT_visibility:
+ get_small_encoding_integer_and_name(dbg, attrib, &uval,
+ "DW_AT_visibility",
+ &valname, get_VIS_name,
+ &err,
+ show_form_used);
+ break;
+ case DW_AT_virtuality:
+ get_small_encoding_integer_and_name(dbg, attrib, &uval,
+ "DW_AT_virtuality",
+ &valname,
+ get_VIRTUALITY_name, &err,
+ show_form_used);
+ break;
+ case DW_AT_identifier_case:
+ get_small_encoding_integer_and_name(dbg, attrib, &uval,
+ "DW_AT_identifier",
+ &valname, get_ID_name,
+ &err,
+ show_form_used);
+ break;
+ case DW_AT_inline:
+ get_small_encoding_integer_and_name(dbg, attrib, &uval,
+ "DW_AT_inline", &valname,
+ get_INL_name, &err,
+ show_form_used);
+ break;
+ case DW_AT_encoding:
+ get_small_encoding_integer_and_name(dbg, attrib, &uval,
+ "DW_AT_encoding", &valname,
+ get_ATE_name, &err,
+ show_form_used);
+ break;
+ case DW_AT_ordering:
+ get_small_encoding_integer_and_name(dbg, attrib, &uval,
+ "DW_AT_ordering", &valname,
+ get_ORD_name, &err,
+ show_form_used);
+ break;
+ case DW_AT_calling_convention:
+ get_small_encoding_integer_and_name(dbg, attrib, &uval,
+ "DW_AT_calling_convention",
+ &valname, get_CC_name,
+ &err,
+ show_form_used);
+ break;
+ case DW_AT_discr_list: /* DWARF3 */
+ get_small_encoding_integer_and_name(dbg, attrib, &uval,
+ "DW_AT_discr_list",
+ &valname, get_DSC_name,
+ &err,
+ show_form_used);
+ break;
+ case DW_AT_data_member_location:
+ {
+ // Value is a constant or a location
+ // description or location list.
+ // If a constant, it could be signed or
+ // unsigned. Telling whether a constant
+ // or a reference is nontrivial
+ // since DW_FORM_data{4,8}
+ // could be either in DWARF{2,3} */
+ Dwarf_Half theform = 0;
+ Dwarf_Half directform = 0;
+ Dwarf_Half version = 0;
+ Dwarf_Half offset_size = 0;
+
+ get_form_values(attrib,theform,directform);
+ int wres = dwarf_get_version_of_die(die ,
+ &version,&offset_size);
+ if(wres != DW_DLV_OK) {
+ print_error(dbg,"Cannot get DIE context version number",wres,err);
+ break;
+ }
+ Dwarf_Form_Class fc = dwarf_get_form_class(version,attr,
+ offset_size,theform);
+ if(fc == DW_FORM_CLASS_CONSTANT) {
+ wres = formxdata_print_value(dbg,attrib,valname,
+ &err,false);
+ show_form_itself(show_form_used,verbose,
+ theform, directform,&valname);
+ if(wres == DW_DLV_OK){
+ /* String appended already. */
+ break;
+ } else if (wres == DW_DLV_NO_ENTRY) {
+ print_error(dbg,"Cannot get DW_AT_data_member_location, how can it be NO_ENTRY? ",wres,err);
+ break;
+ } else {
+ print_error(dbg,"Cannot get DW_AT_data_member_location ",wres,err);
+ break;
+ }
+ }
+ /* FALL THRU, this is a
+ a location description, or a reference
+ to one, or a mistake. */
+ }
+ /* FALL THRU to location description */
+ case DW_AT_location:
+ case DW_AT_vtable_elem_location:
+ case DW_AT_string_length:
+ case DW_AT_return_addr:
+ case DW_AT_use_location:
+ case DW_AT_static_link:
+ case DW_AT_frame_base: {
+ /* value is a location description or location list */
+ Dwarf_Half theform = 0;
+ Dwarf_Half directform = 0;
+ get_form_values(attrib,theform,directform);
+ if(is_location_form(theform)) {
+ get_location_list(dbg, die, attrib, valname);
+ show_form_itself(show_form_used,verbose,
+ theform, directform,&valname);
+ } else if (theform == DW_FORM_exprloc) {
+ bool showhextoo = true;
+ print_exprloc_content(dbg,die,attrib,showhextoo,valname);
+ } else {
+ show_attr_form_error(dbg,attr,theform,&valname);
+ }
+ }
+ break;
+ case DW_AT_SUN_func_offsets: {
+ Dwarf_Half theform = 0;
+ Dwarf_Half directform = 0;
+ get_form_values(attrib,theform,directform);
+ valname = get_FLAG_BLOCK_string(dbg, attrib);
+ show_form_itself(show_form_used,verbose,
+ theform, directform,&valname);
+ }
+ break;
+ case DW_AT_SUN_cf_kind:
+ {
+ Dwarf_Half kind;
+ Dwarf_Unsigned tempud;
+ Dwarf_Error err;
+ Dwarf_Half theform = 0;
+ Dwarf_Half directform = 0;
+ get_form_values(attrib,theform,directform);
+ int wres;
+ wres = dwarf_formudata (attrib,&tempud, &err);
+ if(wres == DW_DLV_OK) {
+ kind = tempud;
+ valname = get_ATCF_name(kind,dwarf_names_print_on_error);
+ } else if (wres == DW_DLV_NO_ENTRY) {
+ valname = "?";
+ } else {
+ print_error(dbg,"Cannot get formudata....",wres,err);
+ valname = "??";
+ }
+ show_form_itself(show_form_used,verbose,
+ theform, directform,&valname);
+ }
+ break;
+ case DW_AT_upper_bound:
+ {
+ Dwarf_Half theform;
+ int rv;
+ rv = dwarf_whatform(attrib,&theform,&err);
+ /* depending on the form and the attribute, process the form */
+ if(rv == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_whatform cannot find attr form",
+ rv, err);
+ } else if (rv == DW_DLV_NO_ENTRY) {
+ break;
+ }
+
+ switch (theform) {
+ case DW_FORM_block1: {
+ Dwarf_Half theform = 0;
+ Dwarf_Half directform = 0;
+ get_form_values(attrib,theform,directform);
+ get_location_list(dbg, die, attrib, valname);
+ show_form_itself(show_form_used,verbose,
+ theform, directform,&valname);
+ }
+ break;
+ default:
+ get_attr_value(dbg, tag, die,
+ attrib, hsrcfiles, valname,show_form_used,
+ verbose);
+ break;
+ }
+ break;
+ }
+ case DW_AT_low_pc:
+ case DW_AT_high_pc:
+ {
+ Dwarf_Half theform;
+ int rv;
+ rv = dwarf_whatform(attrib,&theform,&err);
+ /* Depending on the form and the attribute, process the form */
+ if(rv == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_whatform cannot find attr form",
+ rv, err);
+ } else if (rv == DW_DLV_NO_ENTRY) {
+ break;
+ }
+ if( theform != DW_FORM_addr) {
+ /* New in DWARF4: other forms are not an address
+ but are instead offset from pc.
+ One could test for DWARF4 here before adding
+ this string, but that seems unnecessary as this
+ could not happen with DWARF3 or earlier.
+ A normal consumer would have to add this value to
+ DW_AT_low_pc to get a true pc. */
+ valname.append("<offset-from-lowpc>");
+ }
+ get_attr_value(dbg, tag, die, attrib, hsrcfiles, valname,
+ show_form_used,verbose);
+ /* Update base and high addresses for CU */
+ if (error_message_data.seen_CU &&
+ (error_message_data.need_CU_base_address ||
+ error_message_data.need_CU_high_address)) {
+
+ /* Update base address for CU */
+ if (error_message_data.need_CU_base_address &&
+ attr == DW_AT_low_pc) {
+ dwarf_formaddr(attrib,
+ &error_message_data.CU_base_address, &err);
+ error_message_data.need_CU_base_address = false;
+ }
+
+ /* Update high address for CU */
+ if (error_message_data.need_CU_high_address &&
+ attr == DW_AT_high_pc) {
+ dwarf_formaddr(attrib,
+ &error_message_data.CU_high_address, &err);
+ error_message_data.need_CU_high_address = false;
+ }
+ }
+ /* Record the low and high addresses as we have them */
+ if ((check_decl_file || check_ranges ||
+ check_locations) && theform == DW_FORM_addr) {
+ Dwarf_Addr addr = 0;
+ dwarf_formaddr(attrib, &addr, &err);
+ if (attr == DW_AT_low_pc) {
+ lowAddr = addr;
+ bSawLow = true;
+ /* Record the base address of the last seen PU
+ to be used when checking line information */
+ if (error_message_data.seen_PU && !error_message_data.seen_PU_base_address) {
+ error_message_data.seen_PU_base_address = true;
+ error_message_data.PU_base_address = addr;
+ }
+ } else {
+ highAddr = addr;
+ bSawHigh = true;
+ /* Record the high address of the last seen PU
+ to be used when checking line information */
+ if (error_message_data.seen_PU && !error_message_data.seen_PU_high_address) {
+ error_message_data.seen_PU_high_address = true;
+ error_message_data.PU_high_address = addr;
+ }
+ }
+ /* We have now both low_pc and high_pc values */
+ if (bSawLow && bSawHigh) {
+
+ /* We need to decide if this PU is
+ valid, as the SN Linker marks a stripped
+ function by setting lowpc to -1;
+ also for discarded comdat, both lowpc
+ and highpc are zero */
+ if (error_message_data.need_PU_valid_code) {
+ error_message_data.need_PU_valid_code = false;
+
+ /* To ignore a PU as invalid code,
+ only consider the lowpc and
+ highpc values associated with the
+ DW_TAG_subprogram; other
+ instances of lowpc and highpc,
+ must be ignore (lexical blocks) */
+ in_valid_code = true;
+ if (IsInvalidCode(lowAddr,highAddr) &&
+ tag == DW_TAG_subprogram) {
+ in_valid_code = false;
+ }
+ }
+
+ /* We have a low_pc/high_pc pair;
+ check if they are valid */
+ if (in_valid_code) {
+ DWARF_CHECK_COUNT(ranges_result,1);
+ if (lowAddr != error_message_data.elf_max_address &&
+ lowAddr > highAddr) {
+ DWARF_CHECK_ERROR(ranges_result,
+ ".debug_info: Incorrect values "
+ "for low_pc/high_pc");
+ if (check_verbose_mode) {
+ cout << "Low = " <<
+ IToHex0N(lowAddr,10) <<
+ cout << "High = " <<
+ IToHex0N(highAddr,10) << endl;
+ }
+ }
+ if (check_decl_file || check_ranges ||
+ check_locations) {
+ pAddressRangesData->AddAddressRange(lowAddr,
+ highAddr);
+ }
+ }
+ bSawLow = false;
+ bSawHigh = false;
+ }
+ }
+ }
+ break;
+ case DW_AT_ranges:
+ {
+ Dwarf_Half theform = 0;
+ int rv;
+
+ rv = dwarf_whatform(attrib,&theform,&err);
+ if(rv == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_whatform cannot find attr form",
+ rv, err);
+ } else if (rv == DW_DLV_NO_ENTRY) {
+ break;
+ }
+
+ get_attr_value(dbg, tag,die, attrib, hsrcfiles, valname,
+ show_form_used,verbose);
+ print_range_attribute(dbg,die,attr,attr_in,
+ theform,dwarf_names_print_on_error,print_information,extra);
+ }
+ break;
+ case DW_AT_MIPS_linkage_name:
+ get_attr_value(dbg, tag, die, attrib, hsrcfiles,
+ valname, show_form_used,verbose);
+
+ if (check_locations || check_ranges) {
+ string lname;
+ bool local_show_form = false;
+ int local_verbose = 0;
+ get_attr_value(dbg,tag,die,attrib,hsrcfiles,lname,local_show_form,
+ local_verbose);
+ error_message_data.PU_name = lname;
+ }
+ break;
+ case DW_AT_name:
+ case DW_AT_GNU_template_name:
+ get_attr_value(dbg, tag, die, attrib, hsrcfiles,
+ valname, show_form_used,verbose);
+ if (check_names && checking_this_compiler()) {
+ /* Look for specific name forms, attempting to
+ notice and report 'odd' identifiers. */
+ string lname;
+ bool local_show_form = false;
+ int local_verbose = 0;
+ get_attr_value(dbg,tag,die,attrib,hsrcfiles,lname,local_show_form,
+ local_verbose);
+ DWARF_CHECK_COUNT(names_result,1);
+ if (!strcmp("\"(null)\"",lname.c_str())) {
+ DWARF_CHECK_ERROR(names_result,
+ "string attribute is \"(null)\".");
+ } else {
+ if (!dot_ok_in_identifier(tag,die,valname)
+ && !error_message_data.need_CU_name &&
+ strchr(valname.c_str(),'.')) {
+ /* This is a suggestion there 'might' be
+ a surprising name, not a guarantee of an
+ error. */
+ DWARF_CHECK_ERROR(names_result,
+ "string attribute is invalid.");
+ }
+ }
+ }
+
+ /* If we are in checking mode and we do not have a PU name */
+ if ((check_locations || check_ranges) &&
+ error_message_data.seen_PU && error_message_data.PU_name.empty()) {
+ string lname;
+ bool local_show_form = false;
+ int local_verbose = 0;
+ get_attr_value(dbg,tag,die,attrib,hsrcfiles,lname,
+ local_show_form, local_verbose);
+ error_message_data.PU_name = lname;
+ }
+
+ /* If we are processing the compile unit, record the name */
+ if (error_message_data.seen_CU && error_message_data.need_CU_name) {
+ // Lets not get the form name included.
+ bool local_show_form_used = false;
+ int local_verbose = 0;
+ string localname;
+ get_attr_value(dbg, tag, die, attrib, hsrcfiles,
+ localname, local_show_form_used,local_verbose);
+ error_message_data.CU_name = localname;
+ error_message_data.need_CU_name = false;
+ }
+ break;
+ case DW_AT_producer:
+ get_attr_value(dbg, tag, die, attrib, hsrcfiles,
+ valname, show_form_used,verbose);
+ /* If we are in checking mode, identify the compiler */
+ if (do_check_dwarf || search_is_on) {
+ bool local_show_form = false;
+ int local_verbose = 0;
+ string local_producer;
+ get_attr_value(dbg, tag, die, attrib, hsrcfiles,
+ local_producer, local_show_form,local_verbose);
+ /* Check if this compiler version is a target */
+ update_compiler_target(local_producer);
+ }
+ break;
+
+ /* When dealing with linkonce symbols, the low_pc and high_pc
+ are associated with a specific symbol; SNC always generate a name in
+ the for of DW_AT_MIPS_linkage_name; GCC does not; instead it generates
+ DW_AT_abstract_origin or DW_AT_specification; in that case we have to
+ traverse this attribute in order to get the name for the linkonce */
+ case DW_AT_specification:
+ case DW_AT_abstract_origin:
+ case DW_AT_type:
+ get_attr_value(dbg, tag, die, attrib, hsrcfiles ,
+ valname, show_form_used,verbose);
+ if (check_forward_decl || check_self_references) {
+ Dwarf_Off die_off = 0;
+ Dwarf_Off ref_off = 0;
+ int res = 0;
+ int suppress_check = 0;
+
+ /* Get the global offset for reference */
+ res = dwarf_global_formref(attrib, &ref_off, &err);
+ if (res != DW_DLV_OK) {
+ int myerr = dwarf_errno(err);
+ if(myerr == DW_DLE_REF_SIG8_NOT_HANDLED) {
+ /* DW_DLE_REF_SIG8_NOT_HANDLED */
+ /* No offset available, it makes little sense
+ to delve into this sort of reference unless
+ we think a graph of self-refs *across*
+ type-units is possible. Hmm. FIXME? */
+ suppress_check = 1 ;
+ dwarf_dealloc(dbg,err,DW_DLA_ERROR);
+ err = 0;
+ } else {
+ print_error(dbg, "dwarf_die_CU_offsetD", res, err);
+ }
+ }
+ res = dwarf_dieoffset(die, &die_off, &err);
+ if (res != DW_DLV_OK) {
+ print_error(dbg, "ref formwith no ref?!", res, err);
+ }
+
+ if (!suppress_check && check_self_references) {
+ Dwarf_Die ref_die = 0;
+
+ pVisitedOffsetData->reset();
+ pVisitedOffsetData->AddVisitedOffset(die_off);
+
+ /* Follow reference chain, looking for self references */
+ res = dwarf_offdie_b(dbg,ref_off,is_info,&ref_die,&err);
+ if (res == DW_DLV_OK) {
+ DieHolder hdie(dbg,ref_die);
+ ++die_indent_level;
+
+ if (dump_visited_info) {
+ Dwarf_Off off;
+ dwarf_die_CU_offset(die, &off, &err);
+ cout << BracketSurround(IToDec(die_indent_level,2)) <<
+ "<" << IToHex0N(off,10) <<
+ " GOFF=" << IToHex0N(die_off,10) << "> ";
+ unsigned w = die_indent_level * 2 + 2;
+ cout << std::setw(w)<< atname << " -> " << valname << endl ;
+ }
+ traverse_one_die(dbg,attrib,ref_die,hsrcfiles,die_indent_level);
+ --die_indent_level;
+ }
+ pVisitedOffsetData->DeleteVisitedOffset(die_off);
+ }
+
+ if (!suppress_check && check_forward_decl) {
+ if (attr == DW_AT_specification) {
+ /* Check the DW_AT_specification does not make forward
+ references to DIEs.
+ DWARF4 specifications, section 2.13.2,
+ but really they are legal,
+ this test is probably wrong. */
+ DWARF_CHECK_COUNT(forward_decl_result,1);
+ if (ref_off > die_off) {
+ DWARF_CHECK_ERROR2(forward_decl_result,
+ "Invalid forward reference to DIE: ",valname);
+ }
+ }
+ }
+ }
+ /* If we are in checking mode and we do not have a PU name */
+ if ((check_locations || check_ranges) &&
+ error_message_data.seen_PU &&
+ error_message_data.PU_name.empty()) {
+ if (tag == DW_TAG_subprogram) {
+ /* This gets the DW_AT_name if this DIE has one. */
+ Dwarf_Addr low_pc = 0;
+ string proc_name;
+ get_proc_name(dbg,die,proc_name,low_pc);
+ if (!proc_name.empty()) {
+ error_message_data.PU_name = proc_name;
+ }
+ }
+ }
+ break;
+ default:
+ get_attr_value(dbg, tag,die, attrib, hsrcfiles, valname,
+ show_form_used,verbose);
+ break;
+ }
+ if (!print_information) {
+ if (have_a_search_match(valname,atname) ) {
+ if (search_wide_format) {
+ found_search_attr = true;
+ } else {
+ PRINT_CU_INFO();
+ bTextFound = true;
+ }
+ }
+ }
+ if ((PRINTING_DIES && print_information) || bTextFound) {
+ if(!display_offsets) {
+ cout << LeftAlign(28,atname) << endl;
+ } else {
+ if (dense) {
+ cout << " " << atname << BracketSurround(valname);
+ cout << extra;
+ } else {
+ cout << LeftAlign(28,atname) << valname << endl;
+ cout << extra;
+ }
+ }
+ cout.flush();
+ bTextFound = false;
+ }
+ return found_search_attr;
+}
+
+
+// Appends the locdesc to string_out.
+// Does not print.
+int
+dwarfdump_print_one_locdesc(Dwarf_Debug dbg,
+ Dwarf_Locdesc * llbuf,
+ int skip_locdesc_header,
+ string &string_out)
+{
+
+
+ if (!skip_locdesc_header && (verbose || llbuf->ld_from_loclist)) {
+ string_out.append(BracketSurround(
+ string("lowpc=") + IToHex0N(llbuf->ld_lopc,10)));
+ string_out.append(BracketSurround(
+ string("highpc=") + IToHex0N(llbuf->ld_hipc,10)));
+ if (display_offsets && verbose) {
+ string s("from ");
+ s.append(llbuf->ld_from_loclist ?
+ ".debug_loc" : ".debug_info");
+ s.append(" offset ");
+ s.append(IToHex0N(llbuf->ld_section_offset,10));
+ string_out.append(BracketSurround(s));
+ }
+ }
+
+
+ Dwarf_Locdesc *locd = llbuf;
+ int no_of_ops = llbuf->ld_cents;
+ for (int i = 0; i < no_of_ops; i++) {
+ Dwarf_Loc * op = &locd->ld_s[i];
+
+ int res = _dwarf_print_one_expr_op(dbg,op,i,string_out);
+ if(res == DW_DLV_ERROR) {
+ return res;
+ }
+ }
+ return DW_DLV_OK;
+}
+
+static bool
+op_has_no_operands(int op)
+{
+ unsigned i = 0;
+ if(op >= DW_OP_lit0 && op <= DW_OP_reg31) {
+ return true;
+ }
+ for( ; ; ++i) {
+ struct operation_descr_s *odp = opdesc+i;
+ if(odp->op_code == 0) {
+ break;
+ }
+ if(odp->op_code != op) {
+ continue;
+ }
+ if (odp->op_count == 0) {
+ return true;
+ }
+ return false;
+ }
+ return false;
+}
+
+int
+_dwarf_print_one_expr_op(Dwarf_Debug dbg,Dwarf_Loc* expr,int index,
+ string &string_out)
+{
+ if (index > 0) {
+ string_out.append(" ");
+ }
+
+ Dwarf_Small op = expr->lr_atom;
+ string op_name = get_OP_name(op,dwarf_names_print_on_error);
+ string_out.append(op_name);
+
+ Dwarf_Unsigned opd1 = expr->lr_number;
+ if (op_has_no_operands(op)) {
+ /* Nothing to add. */
+ } else if (op >= DW_OP_breg0 && op <= DW_OP_breg31) {
+ char small_buf[40];
+ snprintf(small_buf, sizeof(small_buf),
+ "%+" DW_PR_DSd , (Dwarf_Signed) opd1);
+ string_out.append(small_buf);
+ } else {
+ switch (op) {
+ case DW_OP_addr:
+ string_out.append(" ");
+ string_out.append(IToHex0N(opd1,10));
+ break;
+ case DW_OP_const1s:
+ case DW_OP_const2s:
+ case DW_OP_const4s:
+ case DW_OP_const8s:
+ case DW_OP_consts:
+ case DW_OP_skip:
+ case DW_OP_bra:
+ case DW_OP_fbreg:
+ {
+ Dwarf_Signed si = opd1;
+ string_out.append(" ");
+ string_out.append(IToDec(si));
+ }
+ break;
+ case DW_OP_const1u:
+ case DW_OP_const2u:
+ case DW_OP_const4u:
+ case DW_OP_const8u:
+ case DW_OP_constu:
+ case DW_OP_pick:
+ case DW_OP_plus_uconst:
+ case DW_OP_regx:
+ case DW_OP_piece:
+ case DW_OP_deref_size:
+ case DW_OP_xderef_size:
+ string_out.append(" ");
+ string_out.append(IToDec(opd1));
+ break;
+ case DW_OP_bregx:
+ {
+ string_out.append(IToHex0N(opd1,10));
+ string_out.append("+");
+ Dwarf_Unsigned opd2 = expr->lr_number2;
+ string_out.append(IToDec(opd2));
+ }
+ break;
+ case DW_OP_call2:
+ string_out.append(IToHex0N(opd1));
+
+ break;
+ case DW_OP_call4:
+ string_out.append(IToHex(opd1));
+
+ break;
+ case DW_OP_call_ref:
+ string_out.append(IToHex0N(opd1,8));
+ break;
+ case DW_OP_bit_piece:
+ {
+ string_out.append(IToHex0N(opd1,8));
+ string_out.append(" offset ");
+ Dwarf_Unsigned opd2 = expr->lr_number2;
+ string_out.append(IToHex0N(opd2,8));
+ }
+ break;
+ case DW_OP_implicit_value:
+ {
+#define IMPLICIT_VALUE_PRINT_MAX 12
+ string_out.append(" ");
+ string_out.append(IToHex0N(opd1,10));
+ // The other operand is a block of opd1 bytes.
+ // FIXME
+ unsigned int print_len = opd1;
+ if(print_len > IMPLICIT_VALUE_PRINT_MAX) {
+ print_len = IMPLICIT_VALUE_PRINT_MAX;
+ }
+#undef IMPLICIT_VALUE_PRINT_MAX
+ if(print_len > 0) {
+ unsigned int i = 0;
+ Dwarf_Unsigned opd2 = expr->lr_number2;
+ const unsigned char *bp =
+ reinterpret_cast<const unsigned char *>(opd2);
+ string_out.append(" contents 0x");
+ for( ; i < print_len; ++i,++bp) {
+ char small_buf[40];
+ snprintf(small_buf, sizeof(small_buf),
+ "%02x", *bp);
+ string_out.append(small_buf);
+ }
+ }
+ }
+ case DW_OP_stack_value:
+ break;
+ case DW_OP_GNU_uninit: /* DW_OP_APPLE_uninit */
+ /* No operands. */
+ break;
+ case DW_OP_GNU_encoded_addr:
+ string_out.append(" ");
+ string_out.append(IToHex0N(opd1,10));
+ break;
+ case DW_OP_GNU_implicit_pointer:
+ string_out.append(" ");
+ string_out.append(IToHex0N(opd1,10));
+ break;
+ case DW_OP_GNU_entry_value:
+ string_out.append(" ");
+ string_out.append(IToHex0N(opd1,10));
+ break;
+ /* We do not know what the operands, if any, are. */
+ case DW_OP_HP_unknown:
+ case DW_OP_HP_is_value:
+ case DW_OP_HP_fltconst4:
+ case DW_OP_HP_fltconst8:
+ case DW_OP_HP_mod_range:
+ case DW_OP_HP_unmod_range:
+ case DW_OP_HP_tls:
+ case DW_OP_INTEL_bit_piece:
+ break;
+ default:
+ string_out.append(string(" dwarf_op unknown: ") +
+ IToHex((unsigned)op));
+ break;
+ }
+ }
+ return DW_DLV_OK;
+}
+
+/* Fill buffer with location lists
+ Return DW_DLV_OK if no errors.
+*/
+/*ARGSUSED*/ static void
+get_location_list(Dwarf_Debug dbg,
+ Dwarf_Die die, Dwarf_Attribute attr,
+ string &locstr)
+{
+ Dwarf_Locdesc *llbuf = 0;
+ Dwarf_Locdesc **llbufarray = 0;
+ Dwarf_Signed no_of_elements;
+ Dwarf_Error err;
+ int i;
+ int lres = 0;
+ int llent = 0;
+ int skip_locdesc_header = 0;
+ Dwarf_Addr base_address = error_message_data.CU_base_address;
+ Dwarf_Addr lopc = 0;
+ Dwarf_Addr hipc = 0;
+ bool bError = false;
+
+
+
+ if (use_old_dwarf_loclist) {
+ lres = dwarf_loclist(attr, &llbuf, &no_of_elements, &err);
+ if (lres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_loclist", lres, err);
+ } else if (lres == DW_DLV_NO_ENTRY) {
+ return;
+ }
+ dwarfdump_print_one_locdesc(dbg, llbuf,skip_locdesc_header,locstr);
+ dwarf_dealloc(dbg, llbuf->ld_s, DW_DLA_LOC_BLOCK);
+ dwarf_dealloc(dbg, llbuf, DW_DLA_LOCDESC);
+ return;
+ }
+
+ lres = dwarf_loclist_n(attr, &llbufarray, &no_of_elements, &err);
+ if (lres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_loclist", lres, err);
+ } else if (lres == DW_DLV_NO_ENTRY) {
+ return;
+ }
+
+ for (llent = 0; llent < no_of_elements; ++llent) {
+ llbuf = llbufarray[llent];
+ Dwarf_Off offset = 0;
+
+ /* If we have a location list refering to the .debug_loc
+ Check for specific compiler we are validating. */
+ if (check_locations && in_valid_code &&
+ llbuf->ld_from_loclist && checking_this_compiler()) {
+ /* To calculate the offset, we use:
+ sizeof(Dwarf_Half) -> number of expression list
+ 2 * address_size -> low_pc and high_pc */
+ offset = llbuf->ld_section_offset -
+ llbuf->ld_cents * sizeof(Dwarf_Half) -
+ 2 * error_message_data.elf_address_size;
+
+ if (llbuf->ld_lopc == error_message_data.elf_max_address) {
+ /* (0xffffffff,addr), use specific address
+ (current PU address) */
+ base_address = llbuf->ld_hipc;
+ } else {
+ /* (offset,offset), update using CU address */
+ lopc = llbuf->ld_lopc + base_address;
+ hipc = llbuf->ld_hipc + base_address;
+
+ DWARF_CHECK_COUNT(locations_result,1);
+
+ /* Check the low_pc and high_pc are within
+ a valid range in the .text section */
+ if(pAddressRangesData->IsAddressInAddressRange(lopc) &&
+ pAddressRangesData->IsAddressInAddressRange(hipc)) {
+ /* Valid values; do nothing */
+ } else {
+ /* At this point may be we are dealing with
+ a linkonce symbol */
+ if (pLinkOnceData->FindLinkOnceEntry(
+ error_message_data.PU_name,lopc,hipc)) {
+ /* Valid values; do nothing */
+ } else {
+ bError = true;
+ DWARF_CHECK_ERROR(locations_result,
+ ".debug_loc: Address outside a "
+ "valid .text range");
+ if (check_verbose_mode) {
+ cout << "Offset = " << IToHex0N(offset,10) <<
+ ", Base = " << IToHex0N(base_address,10) <<
+ ", " <<
+ "Low = " << IToHex0N(lopc,10) <<
+ " (" << IToHex0N(llbuf->ld_lopc,10) <<
+ "), High = " << IToHex0N(hipc,10) <<
+ " (" << IToHex0N(llbuf->ld_hipc,10) <<
+ ")" << endl;
+ }
+ }
+ }
+ }
+ }
+ if (!dense && llbuf->ld_from_loclist) {
+ if (llent == 0) {
+ locstr.append("<loclist with ");
+ locstr.append(IToDec(no_of_elements));
+ locstr.append(" entries follows>");
+ }
+ locstr.append("\n\t\t\t");
+ locstr.append("[");
+ locstr.append(IToDec(llent,2));
+ locstr.append("]");
+ }
+ lres = dwarfdump_print_one_locdesc(dbg,
+ llbuf,
+ skip_locdesc_header,
+ locstr);
+ if (lres == DW_DLV_ERROR) {
+ return;
+ } else {
+ /* DW_DLV_OK so we add follow-on at end, else is
+ DW_DLV_NO_ENTRY (which is impossible, treat like
+ DW_DLV_OK). */
+ }
+ }
+ if (bError && check_verbose_mode) {
+ cout << endl;
+ }
+
+ for (i = 0; i < no_of_elements; ++i) {
+ dwarf_dealloc(dbg, llbufarray[i]->ld_s, DW_DLA_LOC_BLOCK);
+ dwarf_dealloc(dbg, llbufarray[i], DW_DLA_LOCDESC);
+ }
+ dwarf_dealloc(dbg, llbufarray, DW_DLA_LIST);
+}
+
+/* We think this is an integer. Figure out how to print it.
+ In case the signedness is ambiguous (such as on
+ DW_FORM_data1 (ie, unknown signedness) print two ways.
+*/
+static int
+formxdata_print_value(Dwarf_Debug dbg,
+ Dwarf_Attribute attrib, string &str_out,
+ Dwarf_Error * err,
+ bool hexout)
+{
+ Dwarf_Signed tempsd = 0;
+ Dwarf_Unsigned tempud = 0;
+ Dwarf_Error serr = 0;
+ int ures = dwarf_formudata(attrib, &tempud, err);
+ int sres = dwarf_formsdata(attrib, &tempsd, &serr);
+
+ if(ures == DW_DLV_OK) {
+ if(sres == DW_DLV_OK) {
+ if(tempud == static_cast<Dwarf_Unsigned>(tempsd)
+ && tempsd >= 0) {
+ /* Data is the same value, and not negative
+ so makes no difference which we print. */
+ if(hexout) {
+ str_out.append(IToHex0N(tempud,10));
+ } else {
+ str_out.append(IToDec(tempud));
+ }
+ } else {
+ if(hexout) {
+ str_out.append(IToHex0N(tempud,10));
+ } else {
+ str_out.append(IToDec(tempud));
+ }
+ str_out.append("(as signed = ");
+ str_out.append(IToDec(tempsd));
+ str_out.append(")");
+ }
+ } else if (sres == DW_DLV_NO_ENTRY) {
+ if(hexout) {
+ str_out.append(IToHex0N(tempud,10));
+ } else {
+ str_out.append(IToDec(tempud));
+ }
+ } else /* DW_DLV_ERROR */{
+ if(hexout) {
+ str_out.append(IToHex0N(tempud,10));
+ } else {
+ str_out.append(IToDec(tempud));
+ }
+ }
+ goto cleanup;
+ } else {
+ /* ures == DW_DLV_ERROR */
+ if(sres == DW_DLV_OK) {
+ str_out.append(IToDec(tempsd));
+ } else {
+ /* Neither worked. */
+ }
+
+ }
+ cleanup:
+ if(sres == DW_DLV_OK || ures == DW_DLV_OK) {
+ if(sres == DW_DLV_ERROR) {
+ dwarf_dealloc(dbg,serr,DW_DLA_ERROR);
+ }
+ if(ures == DW_DLV_ERROR) {
+ dwarf_dealloc(dbg,*err,DW_DLA_ERROR);
+ *err = 0;
+ }
+ return DW_DLV_OK;
+ }
+ if(sres == DW_DLV_ERROR || ures == DW_DLV_ERROR) {
+ if(sres == DW_DLV_ERROR && ures == DW_DLV_ERROR) {
+ dwarf_dealloc(dbg,serr,DW_DLA_ERROR);
+ return DW_DLV_ERROR;
+ }
+ if(sres == DW_DLV_ERROR) {
+ *err = serr;
+ }
+ return DW_DLV_ERROR;
+ }
+ /* Both are DW_DLV_NO_ENTRY which is crazy, impossible. */
+ return DW_DLV_NO_ENTRY;
+}
+
+static void
+print_exprloc_content(Dwarf_Debug dbg,Dwarf_Die die,
+ Dwarf_Attribute attrib,
+ bool showhextoo, string &str_out)
+{
+ Dwarf_Ptr x = 0;
+ Dwarf_Unsigned tempud = 0;
+ char small_buf[80];
+ Dwarf_Error err = 0;
+ int wres = 0;
+ wres = dwarf_formexprloc(attrib,&tempud,&x,&err);
+ if(wres == DW_DLV_NO_ENTRY) {
+ /* Show nothing? Impossible. */
+ } else if(wres == DW_DLV_ERROR) {
+ print_error(dbg, "Cannot get a DW_FORM_exprbloc....", wres, err);
+ } else {
+ int ares = 0;
+ unsigned u = 0;
+ snprintf(small_buf, sizeof(small_buf),
+ "len 0x%04" DW_PR_DUx ": ",tempud);
+ str_out.append( small_buf);
+ if(showhextoo) {
+ for (u = 0; u < tempud; u++) {
+ snprintf(small_buf, sizeof(small_buf), "%02x",
+ *(u + (unsigned char *) x));
+ str_out.append(small_buf);
+ }
+ str_out.append(": ");
+ }
+ Dwarf_Half address_size = 0;
+ ares = dwarf_get_die_address_size(die,&address_size,&err);
+ if(wres == DW_DLV_NO_ENTRY) {
+ print_error(dbg,"Cannot get die address size for exprloc",
+ ares,err);
+ } else if(wres == DW_DLV_ERROR) {
+ print_error(dbg,"Cannot Get die address size for exprloc",
+ ares,err);
+ } else {
+ string v;
+ get_string_from_locs(dbg,x,tempud,address_size, v);
+ str_out.append(v);
+ }
+ }
+}
+
+
+/* Fill buffer with attribute value.
+ We pass in tag so we can try to do the right thing with
+ broken compiler DW_TAG_enumerator
+
+ We append to str_out. */
+void
+get_attr_value(Dwarf_Debug dbg, Dwarf_Half tag,
+ Dwarf_Die die, Dwarf_Attribute attrib,
+ SrcfilesHolder &hsrcfiles, string &str_out,
+ bool show_form,int local_verbose)
+{
+ Dwarf_Signed tempsd = 0;
+ Dwarf_Unsigned tempud = 0;
+ Dwarf_Half attr = 0;
+ Dwarf_Off off = 0;
+ Dwarf_Off goff = 0;
+ Dwarf_Die die_for_check = 0;
+ Dwarf_Half tag_for_check = 0;
+ Dwarf_Addr addr = 0;
+ int bres = DW_DLV_ERROR;
+ int wres = DW_DLV_ERROR;
+ int dres = DW_DLV_ERROR;
+ Dwarf_Half direct_form = 0;
+ Dwarf_Half theform = 0;
+ Dwarf_Bool is_info = true;
+
+ is_info=dwarf_get_die_infotypes_flag(die);
+ int fres = get_form_values(attrib,theform,direct_form);
+ if (fres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_whatform cannot find attr form", fres,
+ err);
+ } else if (fres == DW_DLV_NO_ENTRY) {
+ return;
+ }
+
+ switch (theform) {
+ case DW_FORM_addr:
+ bres = dwarf_formaddr(attrib, &addr, &err);
+ if (bres == DW_DLV_OK) {
+ str_out.append(IToHex0N(addr,10));
+ } else {
+ print_error(dbg, "addr formwith no addr?!", bres, err);
+ }
+ break;
+ case DW_FORM_ref_addr:
+ /* DW_FORM_ref_addr is not accessed thru formref: ** it is an
+ address (global section offset) in ** the .debug_info
+ section. */
+ bres = dwarf_global_formref(attrib, &off, &err);
+ if (bres == DW_DLV_OK) {
+ str_out.append(BracketSurround(
+ string("global die offset ") +
+ IToHex0N(off,10)));
+ } else {
+ print_error(dbg,
+ "DW_FORM_ref_addr form with no reference?!",
+ bres, err);
+ }
+ wres = dwarf_whatattr(attrib, &attr, &err);
+ if (wres == DW_DLV_ERROR) {
+ } else if (wres == DW_DLV_NO_ENTRY) {
+ } else {
+ if (attr == DW_AT_sibling) {
+ /* The value had better be inside the current CU
+ else there is a nasty error here, as a sibling
+ has to be in the same CU, it seems. */
+ Dwarf_Off cuoff = 0;
+ Dwarf_Off culen = 0;
+ DWARF_CHECK_COUNT(tag_tree_result,1);
+ int res = dwarf_die_CU_offset_range(die,&cuoff,
+ &culen,&err);
+ if(res != DW_DLV_OK) {
+ } else {
+ Dwarf_Off cuend = cuoff+culen;
+ if(off < cuoff || off >= cuend) {
+ DWARF_CHECK_ERROR(tag_tree_result,
+ "DW_AT_sibling DW_FORM_ref_addr offset points "
+ "outside of current CU");
+ }
+ }
+ }
+ }
+
+ break;
+ case DW_FORM_ref1:
+ case DW_FORM_ref2:
+ case DW_FORM_ref4:
+ case DW_FORM_ref8:
+ case DW_FORM_ref_udata:
+ bres = dwarf_formref(attrib, &off, &err);
+ if (bres != DW_DLV_OK) {
+ /* Report incorrect offset */
+ string msg = "reference form with no valid local ref?!";
+ msg.append(", offset=");
+ msg.append(BracketSurround(IToHex0N(off,10)));
+ print_error(dbg, msg, bres, err);
+ }
+ /* Convert the local offset into a relative section offset */
+ if (show_global_offsets) {
+ bres = dwarf_convert_to_global_offset(attrib,
+ off, &goff, &err);
+ if (bres != DW_DLV_OK) {
+ /* Report incorrect offset */
+ string msg = "invalid offset";
+ msg.append(", global die offset=");
+ msg.append(BracketSurround(IToHex0N(goff,10)));
+ print_error(dbg, msg, bres, err);
+ }
+ }
+
+ /* Do references inside <> to distinguish them ** from
+ constants. In dense form this results in <<>>. Ugly for
+ dense form, but better than ambiguous. davea 9/94 */
+ if (show_global_offsets) {
+ str_out.append("<");
+ str_out.append(IToHex0N(off,10));
+ str_out.append(" GOFF=");
+ str_out.append(IToHex0N(goff,10));
+ str_out.append(">");
+ } else {
+ str_out.append(BracketSurround(IToHex0N(off,10)));
+ }
+ if (check_type_offset) {
+ wres = dwarf_whatattr(attrib, &attr, &err);
+ if (wres == DW_DLV_ERROR) {
+
+ } else if (wres == DW_DLV_NO_ENTRY) {
+ }
+ if (attr == DW_AT_type) {
+ dres = dwarf_offdie_b(dbg, cu_offset + off,is_info,
+ &die_for_check, &err);
+ DWARF_CHECK_COUNT(type_offset_result,1);
+ if (dres != DW_DLV_OK) {
+ string msg("DW_AT_type offset does not point to a DIE");
+ msg.append(" for global offset ");
+ msg.append(IToHex(cu_offset + off));
+ msg.append(" cu off ");
+ msg.append(IToHex(cu_offset));
+ msg.append(" local offset ");
+ msg.append(IToHex( off));
+ DWARF_CHECK_ERROR(type_offset_result,msg);
+ } else {
+ int tres2;
+
+ tres2 =
+ dwarf_tag(die_for_check, &tag_for_check, &err);
+ if (tres2 == DW_DLV_OK) {
+ switch (tag_for_check) {
+ case DW_TAG_array_type:
+ case DW_TAG_class_type:
+ case DW_TAG_enumeration_type:
+ case DW_TAG_pointer_type:
+ case DW_TAG_reference_type:
+ case DW_TAG_string_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_subroutine_type:
+ case DW_TAG_typedef:
+ case DW_TAG_union_type:
+ case DW_TAG_ptr_to_member_type:
+ case DW_TAG_set_type:
+ case DW_TAG_subrange_type:
+ case DW_TAG_base_type:
+ case DW_TAG_const_type:
+ case DW_TAG_file_type:
+ case DW_TAG_packed_type:
+ case DW_TAG_thrown_type:
+ case DW_TAG_volatile_type:
+ case DW_TAG_template_type_parameter:
+ case DW_TAG_template_value_parameter:
+ case DW_TAG_unspecified_type:
+ /* OK */
+ break;
+ default:
+ {
+ string msg("DW_AT_type offset does not point to Type info");
+ msg.append(" we got tag ");
+ msg.append(IToHex(tag_for_check));
+ msg.append(" ");
+ msg.append(get_TAG_name(tag_for_check,
+ dwarf_names_print_on_error));
+ DWARF_CHECK_ERROR(type_offset_result, msg);
+ }
+ break;
+ }
+ dwarf_dealloc(dbg, die_for_check, DW_DLA_DIE);
+ } else {
+ DWARF_CHECK_ERROR(type_offset_result,
+ "DW_AT_type offset does not exist");
+ }
+ }
+ }
+ }
+ break;
+ case DW_FORM_block:
+ case DW_FORM_block1:
+ case DW_FORM_block2:
+ case DW_FORM_block4:
+ {
+ Dwarf_Block *tempb;
+ fres = dwarf_formblock(attrib, &tempb, &err);
+ if (fres == DW_DLV_OK) {
+ for (unsigned i = 0; i < tempb->bl_len; i++) {
+ str_out.append(IToHex02(
+ *(i + (unsigned char *) tempb->bl_data)));
+ }
+ dwarf_dealloc(dbg, tempb, DW_DLA_BLOCK);
+ } else {
+ print_error(dbg, "DW_FORM_blockn cannot get block\n", fres,
+ err);
+ }
+ }
+ break;
+ case DW_FORM_data1:
+ case DW_FORM_data2:
+ case DW_FORM_data4:
+ case DW_FORM_data8:
+ fres = dwarf_whatattr(attrib, &attr, &err);
+ if (fres == DW_DLV_ERROR) {
+ print_error(dbg, "FORM_datan cannot get attr", fres, err);
+ } else if (fres == DW_DLV_NO_ENTRY) {
+ print_error(dbg, "FORM_datan cannot get attr", fres, err);
+ } else {
+ switch (attr) {
+ case DW_AT_ordering:
+ case DW_AT_byte_size:
+ case DW_AT_bit_offset:
+ case DW_AT_bit_size:
+ case DW_AT_inline:
+ case DW_AT_language:
+ case DW_AT_visibility:
+ case DW_AT_virtuality:
+ case DW_AT_accessibility:
+ case DW_AT_address_class:
+ case DW_AT_calling_convention:
+ case DW_AT_discr_list: /* DWARF3 */
+ case DW_AT_encoding:
+ case DW_AT_identifier_case:
+ case DW_AT_MIPS_loop_unroll_factor:
+ case DW_AT_MIPS_software_pipeline_depth:
+ case DW_AT_decl_column:
+ case DW_AT_decl_file:
+ case DW_AT_decl_line:
+ case DW_AT_call_column:
+ case DW_AT_call_file:
+ case DW_AT_call_line:
+ case DW_AT_start_scope:
+ case DW_AT_byte_stride:
+ case DW_AT_bit_stride:
+ case DW_AT_count:
+ case DW_AT_stmt_list:
+ case DW_AT_MIPS_fde:
+ {
+ string emptyattrname;
+ bool show_form_here = false;
+ wres = get_small_encoding_integer_and_name(dbg,
+ attrib,
+ &tempud,
+ emptyattrname,
+ /* err_string */ NULL,
+ (encoding_type_func) 0,
+ &err,show_form_here);
+ if (wres == DW_DLV_OK) {
+ str_out.append(IToHex0N(tempud,10));
+ if (attr == DW_AT_decl_file || attr == DW_AT_call_file) {
+ Dwarf_Unsigned srccount = hsrcfiles.count();
+ char **srcfiles = hsrcfiles.srcfiles();
+ if (srcfiles && tempud > 0 && tempud <= srccount) {
+ /* added by user request */
+ /* srcfiles is indexed starting at 0, but
+ DW_AT_decl_file defines that 0 means no
+ file, so tempud 1 means the 0th entry in
+ srcfiles, thus tempud-1 is the correct
+ index into srcfiles. */
+ string fname = srcfiles[tempud - 1];
+ str_out.append(" ");
+ str_out.append(fname);
+ }
+ /* Validate integrity of files
+ referenced in .debug_line */
+ if(check_decl_file) {
+ DWARF_CHECK_COUNT(decl_file_result,1);
+ /* Zero is always a legal index, it means
+ no source name provided. */
+ if(tempud != 0 && tempud > srccount) {
+ string msg;
+ if(!srcfiles) {
+ msg = "There is a file number=";
+ msg.append(IToDec(tempud));
+ msg.append(" but no source files are known.");
+ } else {
+ msg = "Does not point to valid file info ";
+ msg.append(" filenum=");
+ msg.append(IToDec(tempud));
+ msg.append(" filecount=");
+ msg.append(IToDec(srccount));
+ msg.append(".");
+ }
+ DWARF_CHECK_ERROR2(decl_file_result,
+ get_AT_name(attr,
+ dwarf_names_print_on_error),
+ msg);
+ }
+ }
+ }
+ } else {
+ print_error(dbg, "Cannot get encoding attribute ..",
+ wres, err);
+ }
+ }
+ break;
+ case DW_AT_const_value:
+ wres = formxdata_print_value(dbg,attrib,str_out, &err,
+ false);
+ if(wres == DW_DLV_OK){
+ /* String appended already. */
+ } else if (wres == DW_DLV_NO_ENTRY) {
+ /* nothing? */
+ } else {
+ print_error(dbg,"Cannot get DW_AT_const_value ",wres,err);
+ }
+ break;
+ case DW_AT_upper_bound:
+ case DW_AT_lower_bound:
+ default:
+ wres = formxdata_print_value(dbg,attrib,str_out, &err,
+ (DW_AT_ranges == attr));
+ if (wres == DW_DLV_OK) {
+ /* String appended already. */
+ } else if (wres == DW_DLV_NO_ENTRY) {
+ /* nothing? */
+ } else {
+ print_error(dbg, "Cannot get form data..", wres,
+ err);
+ }
+ break;
+ }
+ }
+ if (cu_name_flag) {
+ if (attr == DW_AT_MIPS_fde) {
+ if (fde_offset_for_cu_low == DW_DLV_BADOFFSET) {
+ fde_offset_for_cu_low
+ = fde_offset_for_cu_high = tempud;
+ } else if (tempud < fde_offset_for_cu_low) {
+ fde_offset_for_cu_low = tempud;
+ } else if (tempud > fde_offset_for_cu_high) {
+ fde_offset_for_cu_high = tempud;
+ }
+ }
+ }
+ break;
+ case DW_FORM_sdata:
+ wres = dwarf_formsdata(attrib, &tempsd, &err);
+ if (wres == DW_DLV_OK) {
+ str_out.append(IToHex0N(tempsd,10));
+ } else if (wres == DW_DLV_NO_ENTRY) {
+ /* nothing? */
+ } else {
+ print_error(dbg, "Cannot get formsdata..", wres, err);
+ }
+ break;
+ case DW_FORM_udata:
+ wres = dwarf_formudata(attrib, &tempud, &err);
+ if (wres == DW_DLV_OK) {
+ str_out.append(IToHex0N(tempud,10));
+ } else if (wres == DW_DLV_NO_ENTRY) {
+ /* nothing? */
+ } else {
+ print_error(dbg, "Cannot get formudata....", wres, err);
+ }
+ break;
+ case DW_FORM_string:
+ case DW_FORM_strp:
+ { char *temps = 0;
+ wres = dwarf_formstring(attrib, &temps, &err);
+ if (wres == DW_DLV_OK) {
+ str_out.append("\"");
+ str_out.append(temps);
+ str_out.append("\"");
+ } else if (wres == DW_DLV_NO_ENTRY) {
+ /* nothing? */
+ } else {
+ print_error(dbg, "Cannot get a formstr (or a formstrp)....",
+ wres, err);
+ }
+ }
+
+ break;
+ case DW_FORM_flag:
+ {
+ Dwarf_Bool tempbool;
+ wres = dwarf_formflag(attrib, &tempbool, &err);
+ if (wres == DW_DLV_OK) {
+ if (tempbool) {
+ str_out.append("yes(");
+ str_out.append(IToDec(tempbool));
+ str_out.append(")");
+ } else {
+ str_out.append("no");
+ }
+ } else if (wres == DW_DLV_NO_ENTRY) {
+ /* nothing? */
+ } else {
+ print_error(dbg, "Cannot get formflag/p....", wres, err);
+ }
+ }
+ break;
+ case DW_FORM_indirect:
+ /* We should not ever get here, since the true form was
+ determined and direct_form has the DW_FORM_indirect if it is
+ used here in this attr. */
+ str_out.append( get_FORM_name(theform,
+ dwarf_names_print_on_error));
+ break;
+ case DW_FORM_exprloc: { /* DWARF4 */
+ int showhextoo = true;
+ print_exprloc_content(dbg,die,attrib,showhextoo,str_out);
+ }
+ break;
+
+ case DW_FORM_sec_offset:{ /* DWARF4 */
+ string emptyattrname;
+ bool show_form_here = false;
+ wres = get_small_encoding_integer_and_name(dbg,
+ attrib,
+ &tempud,
+ emptyattrname,
+ /* err_string */ NULL,
+ (encoding_type_func) 0,
+ &err,show_form_here);
+ if(wres == DW_DLV_NO_ENTRY) {
+ /* Show nothing? */
+ } else if(wres == DW_DLV_ERROR) {
+ print_error(dbg,
+ "Cannot get a DW_FORM_sec_offset....",
+ wres, err);
+ } else {
+ str_out.append(IToHex0N(tempud,10));
+ }
+ }
+
+ break;
+ case DW_FORM_flag_present: /* DWARF4 */
+ str_out.append("yes(1)");
+ break;
+ case DW_FORM_ref_sig8: { /* DWARF4 */
+ Dwarf_Sig8 sig8data;
+ wres = dwarf_formsig8(attrib,&sig8data,&err);
+ if(wres != DW_DLV_OK) {
+ /* Show nothing? */
+ print_error(dbg,
+ "Cannot get a DW_FORM_ref_sig8 ....",
+ wres, err);
+ } else {
+ string sig8str;
+ format_sig8_string(&sig8data,sig8str);
+ str_out.append(sig8str);
+ }
+ }
+ break;
+ default:
+ print_error(dbg, "dwarf_whatform unexpected value", DW_DLV_OK,
+ err);
+ }
+ show_form_itself(show_form,local_verbose,theform, direct_form,&str_out);
+}
+
+void
+format_sig8_string(Dwarf_Sig8 *data,string &out)
+{
+ char small_buf[40];
+ out.append("0x");
+ for( unsigned i = 0; i < sizeof(data->signature); ++i) {
+ if (i == 4) {
+ out.append(" 0x");
+ }
+ snprintf(small_buf,sizeof(small_buf), "%02x",
+ (unsigned char)(data->signature[i]));
+ out.append(small_buf);
+ }
+}
+
+static int
+get_form_values(Dwarf_Attribute attrib,
+ Dwarf_Half & theform, Dwarf_Half & directform)
+{
+ Dwarf_Error err = 0;
+ int res = dwarf_whatform(attrib, &theform, &err);
+ dwarf_whatform_direct(attrib, &directform, &err);
+ return res;
+}
+static void
+show_form_itself(bool local_show_form,
+ int local_verbose,
+ int theform,
+ int directform, string *str_out)
+{
+ if ( local_show_form
+ && directform && directform == DW_FORM_indirect) {
+ str_out->append(" (used DW_FORM_indirect");
+ if(local_verbose) {
+ str_out->append(" ");
+ str_out->append(IToDec(DW_FORM_indirect));
+ }
+ str_out->append( ") ");
+ }
+ if(local_show_form) {
+ str_out->append(" <form ");
+ str_out->append(get_FORM_name(theform,
+ dwarf_names_print_on_error));
+ if(local_verbose) {
+ str_out->append(" ");
+ str_out->append(IToDec(theform));
+ }
+ str_out->append(">");
+ }
+}
+
+
+#include "tmp-ta-table.cc"
+#include "tmp-ta-ext-table.cc"
+
+static int
+legal_tag_attr_combination(Dwarf_Half tag, Dwarf_Half attr)
+{
+ if(tag <= 0) {
+ return false;
+ }
+ if(tag < ATTR_TREE_ROW_COUNT) {
+ int index = attr / BITS_PER_WORD;
+ if ( index < ATTR_TREE_COLUMN_COUNT) {
+ unsigned bitflag = 1 << (attr % BITS_PER_WORD);
+ int known = (
+ (tag_attr_combination_table[tag][index] & bitflag)
+ > 0 ? true : false);
+ if(known) {
+ return true;
+ }
+ }
+ }
+ /* DW_AT_MIPS_fde used to return true as that was
+ convenient for SGI/MIPS users. */
+ if(!suppress_check_extensions_tables) {
+ int r = 0;
+ for ( ; r < ATTR_TREE_EXT_ROW_COUNT; ++r ) {
+ int c = 1;
+ if(tag != tag_attr_combination_ext_table[r][0]) {
+ continue;
+ }
+ for( ; c < ATTR_TREE_EXT_COLUMN_COUNT ; ++c) {
+ if (tag_attr_combination_ext_table[r][c] == attr) {
+ return true;
+ }
+ }
+ }
+ }
+ return (false);
+}
+#include "tmp-tt-table.cc"
+#include "tmp-tt-ext-table.cc"
+
+/* Look only at valid table entries
+ The check here must match the building-logic in
+ tag_tree.cc
+ And must match the tags defined in dwarf.h
+ The tag_tree_combination_table is a table of bit flags. */
+static bool
+legal_tag_tree_combination(Dwarf_Half tag_parent, Dwarf_Half tag_child)
+{
+ if(tag_parent <= 0) {
+ return false;
+ }
+ if ( tag_parent < TAG_TREE_ROW_COUNT) {
+ int index = tag_child / BITS_PER_WORD;
+ if ( index < TAG_TREE_COLUMN_COUNT) {
+ unsigned bitflag = 1 << (tag_child % BITS_PER_WORD);
+ int known = (
+ (tag_tree_combination_table[tag_parent] [index] & bitflag)
+ > 0 ? true : false);
+ if(known) {
+ return true;
+ }
+ }
+ }
+ if(!suppress_check_extensions_tables) {
+ int r = 0;
+ for ( ; r < TAG_TREE_EXT_ROW_COUNT; ++r ) {
+ int c = 1;
+ if(tag_parent != tag_tree_combination_ext_table[r][0]) {
+ continue;
+ }
+ for( ; c < TAG_TREE_EXT_COLUMN_COUNT ; ++c) {
+ if (tag_tree_combination_ext_table[r][c] == tag_child) {
+ return true;
+ }
+ }
+ }
+ }
+ return (false);
+}
+
+
diff --git a/dwarfdump2/print_frames.cc b/dwarfdump2/print_frames.cc
new file mode 100644
index 0000000..291b681
--- /dev/null
+++ b/dwarfdump2/print_frames.cc
@@ -0,0 +1,1621 @@
+/*
+ Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_frames.c,v 1.5 2006/06/14 20:34:02 davea Exp $ */
+
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+
+
+#include "globals.h"
+#include <vector>
+#include <map>
+#include <set>
+#include "print_frames.h"
+#include "dwconf.h"
+#include "fderegs.h"
+
+
+
+using std::string;
+using std::cout;
+using std::cerr;
+using std::endl;
+using std::map;
+using std::set;
+
+static void
+print_one_frame_reg_col(Dwarf_Debug dbg,
+ Dwarf_Unsigned rule_id,
+ Dwarf_Small value_type,
+ Dwarf_Unsigned reg_used,
+ Dwarf_Half address_size,
+ struct dwconf_s *config_data,
+ Dwarf_Signed offset_relevant,
+ Dwarf_Signed offset, Dwarf_Ptr block_ptr);
+
+typedef map<Dwarf_Addr,string> LowpcToNameMaptype;
+typedef set<Dwarf_Addr> LowpcUsedSettype;
+
+
+
+/* For inlined or class mem functions, try to find name */
+static int
+get_abstract_origin_or_spec_funcname(Dwarf_Debug dbg,
+ Dwarf_Attribute attr,
+ string &name_out)
+{
+ Dwarf_Off off = 0;
+ Dwarf_Die origin_die = 0;
+ Dwarf_Attribute *atlist = NULL;
+ Dwarf_Signed atcnt = 0;
+ bool name_found = false;
+ int res = dwarf_global_formref(attr,&off,&err);
+ if(res != DW_DLV_OK) {
+ return DW_DLV_NO_ENTRY;
+ }
+ int dres = dwarf_offdie(dbg,off,&origin_die,&err);
+ if(dres != DW_DLV_OK) {
+ return DW_DLV_NO_ENTRY;
+ }
+ int atres = dwarf_attrlist(origin_die, &atlist, &atcnt, &err);
+ if (atres != DW_DLV_OK) {
+ dwarf_dealloc(dbg,origin_die,DW_DLA_DIE);
+ return DW_DLV_NO_ENTRY;
+ }
+ for (Dwarf_Signed i = 0; i < atcnt; i++) {
+ Dwarf_Half lattr;
+ int ares;
+ ares = dwarf_whatattr(atlist[i], &lattr, &err);
+ if (ares == DW_DLV_ERROR) {
+ break;
+ } else if (ares == DW_DLV_OK) {
+ if(lattr == DW_AT_name) {
+ int sres = 0;
+ char* temps = 0;
+ sres = dwarf_formstring(atlist[i], &temps, &err);
+ if (sres == DW_DLV_OK) {
+ name_out = temps;
+ name_found = true;
+ break;
+ }
+ }
+ }
+ }
+ for (Dwarf_Signed i = 0; i < atcnt; i++) {
+ dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);
+ }
+ dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
+ dwarf_dealloc(dbg,origin_die,DW_DLA_DIE);
+ if(!name_found) {
+ return DW_DLV_NO_ENTRY;
+ }
+ return DW_DLV_OK;
+}
+
+
+/* Returns true this is a procedure with a name, and sets
+ the name in proc_name and the low pc in low_pc_out.
+ Else returns false. */
+bool
+get_proc_name(Dwarf_Debug dbg, Dwarf_Die die,
+ string & proc_name, Dwarf_Addr & low_pc_out)
+{
+ Dwarf_Signed atcnt = 0;
+ Dwarf_Signed i = 0;
+ Dwarf_Attribute *atlist = NULL;
+ bool funcpcfound = false;
+ bool funcnamefound = false;
+
+ int atres = dwarf_attrlist(die, &atlist, &atcnt, &err);
+ if (atres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_attrlist", atres, err);
+ return false;
+ }
+ if (atres == DW_DLV_NO_ENTRY) {
+ return false;
+ }
+ for (i = 0; i < atcnt; i++) {
+ Dwarf_Half attr;
+ int ares;
+ char *temps;
+ int sres;
+ int dres;
+
+ if (funcnamefound == true && funcpcfound == true) {
+ /* stop as soon as both found */
+ break;
+ }
+ ares = dwarf_whatattr(atlist[i], &attr, &err);
+ if (ares == DW_DLV_ERROR) {
+ print_error(dbg, "get_proc_name whatattr error", ares, err);
+ } else if (ares == DW_DLV_OK) {
+ switch (attr) {
+ case DW_AT_specification:
+ case DW_AT_abstract_origin:
+ {
+ if(!funcnamefound) {
+ string aotemp;
+ /* Only use this if we have not seen DW_AT_name
+ yet .*/
+ int aores = get_abstract_origin_or_spec_funcname(dbg,
+ atlist[i], aotemp);
+ if(aores == DW_DLV_OK) {
+ /* FOUND THE NAME */
+ proc_name = aotemp;
+ funcnamefound = 1;
+ }
+ }
+ }
+ break;
+ case DW_AT_name:
+ sres = dwarf_formstring(atlist[i], &temps, &err);
+ if (sres == DW_DLV_ERROR) {
+ print_error(dbg,
+ "formstring in get_proc_name failed",
+ sres, err);
+ /* 50 is safe wrong length since is bigger than the
+ actual string */
+ proc_name = "ERROR in dwarf_formstring!";
+ } else if (sres == DW_DLV_NO_ENTRY) {
+ /* 50 is safe wrong length since is bigger than the
+ actual string */
+ proc_name = "NO ENTRY on dwarf_formstring?!";
+ } else {
+ proc_name = temps;
+ }
+ funcnamefound = 1; /* FOUND THE NAME */
+ break;
+ case DW_AT_low_pc:
+ dres = dwarf_formaddr(atlist[i], &low_pc_out, &err);
+ if (dres == DW_DLV_ERROR) {
+ print_error(dbg, "formaddr in get_proc_name failed",
+ dres, err);
+ } else if (dres == DW_DLV_OK) {
+ funcpcfound = true;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ for (i = 0; i < atcnt; i++) {
+ dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);
+ }
+ dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
+ if (funcnamefound == 0 || funcpcfound == 0 ) {
+ return false;
+ }
+ return true;
+}
+
+/* Nested search since some languages, including SGI MP Fortran,
+ have nested functions.
+
+ Loads all the subprogram names it can find in the current
+ sibling/child chain into the pcMap.
+ Do not stop except on error. */
+static void
+load_nested_proc_names(Dwarf_Debug dbg, Dwarf_Die die,
+ string &proc_name, LowpcToNameMaptype & pcMap)
+{
+ Dwarf_Die curdie = die;
+ int die_locally_gotten = 0;
+ Dwarf_Half tag;
+ Dwarf_Error err = 0;
+ int chres = DW_DLV_OK;
+ while (chres == DW_DLV_OK) {
+ int tres = dwarf_tag(curdie, &tag, &err);
+ err = 0;
+ if (tres == DW_DLV_OK) {
+ int lchres;
+
+ if (tag == DW_TAG_subprogram) {
+ Dwarf_Addr proc_low_pc = 0;
+ bool proc_name_v = get_proc_name(dbg, curdie, proc_name,
+ proc_low_pc);
+ if (proc_name_v) {
+ pcMap[proc_low_pc] = proc_name;
+ }
+ /* Check children of subprograms recursively. Should
+ this really be checking children of anything,
+ or just children of subprograms? */
+ Dwarf_Die newchild = 0;
+ lchres = dwarf_child(curdie, &newchild, &err);
+ if (lchres == DW_DLV_OK) {
+ /* Look for inner subprogram. */
+ load_nested_proc_names(dbg, newchild,
+ proc_name, pcMap);
+ dwarf_dealloc(dbg, newchild, DW_DLA_DIE);
+ } else if (lchres == DW_DLV_NO_ENTRY) {
+ /* nothing to do */
+ } else {
+ print_error(dbg,
+ "load_nested_proc_names dwarf_child() failed ",
+ chres, err);
+ }
+ } /* end if TAG_subprogram */
+ } else {
+ print_error(dbg, "no tag on child read ", tres, err);
+ break;
+ }
+ /* Try next sibling */
+ Dwarf_Die newsibling = 0;
+ chres = dwarf_siblingof(dbg, curdie, &newsibling, &err);
+ if (chres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_cu_header On Child read ", chres,
+ err);
+ break;
+ } else if (chres == DW_DLV_NO_ENTRY) {
+ // At the end of sibling chain of this nesting level.
+ break;
+ } else { /* DW_DLV_OK */
+ if (die_locally_gotten) {
+ /* If we got this die from the parent, we do not want
+ to dealloc here! */
+ dwarf_dealloc(dbg, curdie, DW_DLA_DIE);
+ }
+ curdie = newsibling;
+ die_locally_gotten = 1;
+ }
+
+ }
+ if (die_locally_gotten) {
+ /* If we got this die from the parent, we do not want to
+ dealloc here! */
+ dwarf_dealloc(dbg, curdie, DW_DLA_DIE);
+ }
+ return;
+}
+
+/* For SGI MP Fortran and other languages, functions
+ nest! As a result, we must dig thru all functions,
+ not just the top level.
+
+ This remembers the CU die and restarts each search at the start
+ of the current cu.
+ If we find nothing we return an empty string. */
+static string
+get_fde_proc_name(Dwarf_Debug dbg, Dwarf_Addr low_pc,
+ LowpcToNameMaptype & pcMap,
+ bool & all_cus_seen)
+{
+ Dwarf_Unsigned cu_header_length = 0;
+ Dwarf_Unsigned abbrev_offset = 0;
+ Dwarf_Half version_stamp = 0;
+ Dwarf_Half address_size = 0;
+ Dwarf_Unsigned next_cu_offset = 0;
+ int cures = DW_DLV_ERROR;
+ int chres = DW_DLV_ERROR;
+ string proc_name;
+
+ LowpcToNameMaptype::const_iterator it = pcMap.find(low_pc);
+ if(it != pcMap.end()) {
+ string s = it->second;
+ return s;
+ }
+ if(all_cus_seen) {
+ return "";
+ }
+
+ // Loop through the CUs
+ for (;;) {
+ cures = dwarf_next_cu_header(dbg, &cu_header_length,
+ &version_stamp, &abbrev_offset,
+ &address_size, &next_cu_offset,
+ &err);
+
+ if (cures == DW_DLV_NO_ENTRY) {
+ all_cus_seen = true;
+ break;
+ } else if (cures == DW_DLV_ERROR) {
+ // Nothing much we can do here.
+ all_cus_seen = true;
+ break;
+ }
+
+ Dwarf_Die current_cu_die_for_print_frames(0);
+ int dres = dwarf_siblingof(dbg, NULL,
+ &current_cu_die_for_print_frames, &err);
+ if (dres == DW_DLV_ERROR) {
+ print_error(dbg,
+ "dwarf_cu_header Child Read finding proc name for .debug_frame",
+ chres, err);
+ continue;
+ } else if (dres == DW_DLV_NO_ENTRY) {
+ continue;
+ }
+ /* DW_DLV_OK */
+ Dwarf_Die child = 0;
+ int chres = dwarf_child(current_cu_die_for_print_frames, &child,
+ &err);
+ if (chres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf Child Read ", chres, err);
+ } else if (chres == DW_DLV_NO_ENTRY) {
+
+ ; /* do nothing, loop on cu */
+ } else {
+ /* DW_DLV_OK */
+ // find All the subprograms for this CU and use
+ // pcMap to associate each name with its low_pc!
+ load_nested_proc_names(dbg, child, proc_name,
+ pcMap);
+ dwarf_dealloc(dbg, child, DW_DLA_DIE);
+ }
+ dwarf_dealloc(dbg, current_cu_die_for_print_frames, DW_DLA_DIE);
+ LowpcToNameMaptype::const_iterator it = pcMap.find(low_pc);
+ if(it != pcMap.end()) {
+ // If we need more CUs later we will process
+ // them as needed (later), but we have done enough
+ // CUs to satisfy this low_pc.
+ string s = it->second;
+ return s;
+ }
+ }
+ return "";
+}
+
+
+/*
+ Gather the fde print logic here so the control logic
+ determining what FDE to print is clearer.
+*/
+int
+print_one_fde(Dwarf_Debug dbg, Dwarf_Fde fde,
+ Dwarf_Unsigned fde_index,
+ Dwarf_Cie * cie_data,
+ Dwarf_Signed cie_element_count,
+ Dwarf_Half address_size, int is_eh,
+ struct dwconf_s *config_data,
+ LowpcToNameMaptype & pcMap,
+ LowpcUsedSettype &lowpcSet,
+ bool &all_cus_seen)
+{
+ Dwarf_Addr low_pc = 0;
+ Dwarf_Unsigned func_length = 0;
+ Dwarf_Ptr fde_bytes = NULL;
+ Dwarf_Unsigned fde_bytes_length = 0;
+ Dwarf_Off cie_offset = 0;
+ Dwarf_Signed cie_index = 0;
+ Dwarf_Off fde_offset = 0;
+ Dwarf_Signed eh_table_offset = 0;
+ Dwarf_Error err = 0;
+ bool printed_intro_addr = false;
+
+ int fres = dwarf_get_fde_range(fde,
+ &low_pc, &func_length,
+ &fde_bytes,
+ &fde_bytes_length,
+ &cie_offset, &cie_index,
+ &fde_offset, &err);
+ if (fres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_fde_range", fres, err);
+ }
+ if (fres == DW_DLV_NO_ENTRY) {
+ return DW_DLV_NO_ENTRY;
+ }
+ if (cu_name_flag &&
+ fde_offset_for_cu_low != DW_DLV_BADOFFSET &&
+ (fde_offset < fde_offset_for_cu_low ||
+ fde_offset > fde_offset_for_cu_high)) {
+ return DW_DLV_NO_ENTRY;
+ }
+ /* eh_table_offset is IRIX ONLY. */
+ fres = dwarf_get_fde_exception_info(fde, &eh_table_offset, &err);
+ if (fres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_fde_exception_info", fres, err);
+ }
+ string temps;
+ if(!suppress_nested_name_search) {
+ temps = get_fde_proc_name(dbg, low_pc,
+ pcMap,all_cus_seen);
+ LowpcUsedSettype::const_iterator it = lowpcSet.find(low_pc);
+ if(check_frames || check_frames_extended) {
+ DWARF_CHECK_COUNT(fde_duplication,1);
+ }
+ if (it != lowpcSet.end()) {
+ if(check_frames || check_frames_extended ) {
+ string msg = string("An fde low pc of ") + IToHex(low_pc) +
+ string(" is not the first fde with that pc. ");
+ if(temps.empty()) {
+ msg.append("The first is not named.");
+ } else {
+ msg.append(string("The first is named \"")+
+ temps + string("\"") );
+ }
+ DWARF_CHECK_ERROR(fde_duplication,msg);
+ }
+ } else {
+ lowpcSet.insert(low_pc);
+ }
+ }
+ if(!check_frames_extended) {
+ cout << BracketSurround(IToDec(cie_index,5));
+ cout << BracketSurround(IToHex0N(low_pc,10) + string(":")+
+ IToHex0N(low_pc + func_length,10));
+ cout << BracketSurround(temps);
+ cout << BracketSurround(string("fde offset ") +
+ IToHex0N(fde_offset,10) + string(" length: ") +
+ IToHex0N(fde_bytes_length,10));
+ }
+
+ if (!is_eh) {
+ /* IRIX uses eh_table_offset. */
+ if(!check_frames_extended) {
+ if (eh_table_offset == DW_DLX_NO_EH_OFFSET) {
+ cout << BracketSurround(
+ string("eh offset none")) << endl;
+ } else if (eh_table_offset == DW_DLX_EH_OFFSET_UNAVAILABLE) {
+ cout << BracketSurround(
+ string("eh offset unknown")) << endl;
+ } else {
+ cout << BracketSurround(
+ string("eh offset ") + IToHex(eh_table_offset)) << endl;
+ }
+ }
+ } else {
+ int ares = 0;
+ Dwarf_Small *data = 0;
+ Dwarf_Unsigned len = 0;
+
+ ares = dwarf_get_fde_augmentation_data(fde, &data, &len, &err);
+ if (ares == DW_DLV_NO_ENTRY) {
+ /* do nothing. */
+ } else if (ares == DW_DLV_OK) {
+ if(!check_frames_extended) {
+ cout << "<eh aug data len " << IToHex(len);
+ for (unsigned k2 = 0; k2 < len; ++k2) {
+ if (k2 == 0) {
+ cout <<" bytes 0x";
+ }
+ cout << IToHex02(data[k2])<< " ";
+ }
+ cout << ">";
+ }
+ } /* else DW_DLV_ERROR, do nothing */
+ if(!check_frames_extended) {
+ cout << endl;
+ }
+ }
+
+ for (Dwarf_Addr j = low_pc; j < low_pc + func_length; j++) {
+ FdeRegs fder(fde,config_data);
+ fder.setPc(j);
+ int fires = fder.preliminaryRead(&err);
+ if (fires == DW_DLV_ERROR) {
+ print_error(dbg,
+ "dwarf_get_fde_info_for_reg", fires, err);
+ }
+ if (fires == DW_DLV_NO_ENTRY) {
+ continue;
+ }
+ if (config_data->cf_interface_number == 3) {
+ Dwarf_Addr row_pc = 0;
+ Dwarf_Regtable_Entry3 cfadata;
+ // cfdata is a plain-C struct from libdwarf.
+ memset(&cfadata,0,sizeof(cfadata));
+ int fires2 = fder.getCfaRegdata(&cfadata,&row_pc,&err);
+ if (fires2 == DW_DLV_ERROR) {
+ print_error(dbg,
+ "dwarf_get_fde_info_for_reg", fires, err);
+ }
+ if (fires2 == DW_DLV_NO_ENTRY) {
+ continue;
+ }
+ if (row_pc != j) {
+ /* duplicate row */
+ continue;
+ }
+ if (!printed_intro_addr & !check_frames_extended) {
+ cout <<" ";
+ cout << IToHex0N(j,10);
+ cout <<": ";
+ printed_intro_addr = true;
+ }
+ print_one_frame_reg_col(dbg, config_data->cf_cfa_reg,
+ cfadata.dw_value_type,
+ cfadata.dw_regnum,
+ address_size,
+ config_data,
+ cfadata.dw_offset_relevant,
+ cfadata.dw_offset_or_block_len,
+ cfadata.dw_block_ptr);
+ }
+ for (unsigned k = 0; k < config_data->cf_table_entry_count; k++) {
+ Dwarf_Addr row_pc = 0;
+ Dwarf_Regtable_Entry3 cfadata;
+ memset(&cfadata,0, sizeof(cfadata));
+
+ int fires3 = fder.getRegdata(k,&cfadata,&row_pc,&err);
+
+ if (fires3 == DW_DLV_ERROR) {
+ cout << endl;
+ print_error(dbg,
+ "dwarf_get_fde_info_for_reg", fires, err);
+ }
+ if (fires == DW_DLV_NO_ENTRY) {
+ continue;
+ }
+ if (row_pc != j) {
+ /* duplicate row */
+ break;
+ }
+ if (!printed_intro_addr && !check_frames_extended) {
+ cout << " " << IToHex0N(j,10) << ": ";
+ printed_intro_addr = true;
+ }
+ print_one_frame_reg_col(dbg,k,
+ cfadata.dw_value_type,
+ cfadata.dw_regnum,
+ address_size,
+ config_data,
+ cfadata.dw_offset_relevant,
+ cfadata.dw_offset_or_block_len,
+ cfadata.dw_block_ptr);
+ }
+ if (printed_intro_addr) {
+ cout << endl;
+ printed_intro_addr = false;
+ }
+ }
+ if (verbose > 1) {
+ Dwarf_Off fde_off;
+ Dwarf_Off cie_off;
+
+ /* Get the fde instructions and print them in raw form, just
+ like cie instructions */
+ Dwarf_Ptr instrs;
+ Dwarf_Unsigned ilen;
+ int res;
+
+ res = dwarf_get_fde_instr_bytes(fde, &instrs, &ilen, &err);
+ int offres =
+ dwarf_fde_section_offset(dbg, fde, &fde_off, &cie_off,
+ &err);
+ if (offres == DW_DLV_OK) {
+ if(!check_frames_extended) {
+ cout << " fde section offset " << IToDec(fde_off) <<
+ " " <<
+ IToHex0N(fde_off,10);
+ cout << " cie offset for fde: " << IToDec(cie_off) <<
+ " " <<
+ IToHex0N(cie_off,10);
+ cout << endl;
+ }
+ }
+
+ if (res == DW_DLV_OK) {
+ int cires = 0;
+ Dwarf_Unsigned cie_length = 0;
+ Dwarf_Small version = 0;
+ Dwarf_Unsigned code_alignment_factor = 0;
+ Dwarf_Signed data_alignment_factor = 0;
+ Dwarf_Half return_address_register_rule = 0;
+ Dwarf_Ptr initial_instructions = 0;
+ Dwarf_Unsigned initial_instructions_length = 0;
+
+ if (cie_index >= cie_element_count) {
+ cout << "Bad cie index " << IToDec(cie_index);
+ cout << " with fde index " << IToDec(fde_index);
+ cout << "! (table entry max " << IToDec(cie_element_count);
+ cout << ")" << endl;
+ exit(1);
+ }
+
+ char *augmenter_arg = 0;
+ cires = dwarf_get_cie_info(cie_data[cie_index],
+ &cie_length,
+ &version,
+ &augmenter_arg,
+ &code_alignment_factor,
+ &data_alignment_factor,
+ &return_address_register_rule,
+ &initial_instructions,
+ &initial_instructions_length,
+ &err);
+ if (cires == DW_DLV_ERROR) {
+ cout << "Bad cie index " << IToDec(cie_index);
+ cout << " with fde index " << IToDec(fde_index);
+ cout << "!" << endl;
+ print_error(dbg, "dwarf_get_cie_info", cires, err);
+ }
+ if (cires == DW_DLV_NO_ENTRY) {
+ ; /* ? */
+ } else {
+ if(!check_frames_extended) {
+ print_frame_inst_bytes(dbg, instrs,
+ (Dwarf_Signed) ilen,
+ data_alignment_factor,
+ (int) code_alignment_factor,
+ address_size, config_data);
+ }
+ }
+ } else if (res == DW_DLV_NO_ENTRY) {
+ cout <<"Impossible: no instr bytes for fde index " <<
+ IToDec(fde_index) << endl;
+ } else {
+ /* DW_DLV_ERROR */
+ cout << "Error: on gettinginstr bytes for fde index " <<
+ IToDec(fde_index) << endl;
+ print_error(dbg, "dwarf_get_fde_instr_bytes", res, err);
+ }
+
+ }
+ return DW_DLV_OK;
+}
+
+
+/* Print a cie. Gather the print logic here so the
+ control logic deciding what to print
+ is clearer.
+*/
+int
+print_one_cie(Dwarf_Debug dbg, Dwarf_Cie cie,
+ Dwarf_Unsigned cie_index, Dwarf_Half address_size,
+ struct dwconf_s *config_data)
+{
+ int cires = 0;
+ Dwarf_Unsigned cie_length = 0;
+ Dwarf_Small version = 0;
+ Dwarf_Unsigned code_alignment_factor = 0;
+ Dwarf_Signed data_alignment_factor = 0;
+ Dwarf_Half return_address_register_rule = 0;
+ Dwarf_Ptr initial_instructions = 0;
+ Dwarf_Unsigned initial_instructions_length = 0;
+ Dwarf_Off cie_off = 0;
+ Dwarf_Error err = 0;
+
+ char *augmenter_arg = 0;
+ cires = dwarf_get_cie_info(cie,
+ &cie_length,
+ &version,
+ &augmenter_arg,
+ &code_alignment_factor,
+ &data_alignment_factor,
+ &return_address_register_rule,
+ &initial_instructions,
+ &initial_instructions_length, &err);
+ if (cires == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_cie_info", cires, err);
+ }
+ if (cires == DW_DLV_NO_ENTRY) {
+ cout << "Impossible DW_DLV_NO_ENTRY on cie " <<
+ IToDec(cie_index) << endl;
+ return DW_DLV_NO_ENTRY;
+ }
+ {
+ if(!check_frames_extended) {
+ string augmenter = augmenter_arg;
+ cout << BracketSurround(IToDec(cie_index,5));
+ cout << "\tversion\t\t\t\t" << static_cast<int>(version) << endl;
+ cires = dwarf_cie_section_offset(dbg, cie, &cie_off, &err);
+ if (cires == DW_DLV_OK) {
+ cout << "\tcie section offset\t\t" << IToDec(cie_off);
+ cout << " " << IToHex0N(cie_off,10) << endl;
+ }
+
+ cout << "\taugmentation\t\t\t" << augmenter << endl;
+ cout << "\tcode_alignment_factor\t\t" <<
+ code_alignment_factor << endl;
+ cout << "\tdata_alignment_factor\t\t" <<
+ data_alignment_factor << endl;
+ cout << "\treturn_address_register\t\t" <<
+ return_address_register_rule << endl;
+ }
+ {
+ int ares = 0;
+ Dwarf_Small *data = 0;
+ Dwarf_Unsigned len = 0;
+
+ ares =
+ dwarf_get_cie_augmentation_data(cie, &data, &len, &err);
+ if (ares == DW_DLV_NO_ENTRY) {
+ /* do nothing. */
+ } else if (ares == DW_DLV_OK && len > 0) {
+ if(!check_frames_extended) {
+ cout << " eh aug data len " <<
+ IToHex(len);
+ for (unsigned k2 = 0; data && k2 < len; ++k2) {
+ if (k2 == 0) {
+ cout <<" bytes 0x";
+ }
+ cout << IToHex02(data[k2]) << " ";
+ }
+ cout << endl;
+ }
+ } /* else DW_DLV_ERROR or no data, do nothing */
+ }
+
+ if(!check_frames_extended) {
+ cout <<
+ "\tbytes of initial instructions\t" <<
+ IToDec(initial_instructions_length) << endl;
+ cout <<"\tcie length\t\t\t" <<IToDec(cie_length) << endl;
+ cout << "\tinitial instructions" << endl;
+ print_frame_inst_bytes(dbg, initial_instructions,
+ (Dwarf_Signed) initial_instructions_length,
+ data_alignment_factor,
+ (int) code_alignment_factor,
+ address_size, config_data);
+ }
+ }
+ return DW_DLV_OK;
+}
+
+void
+get_string_from_locs(Dwarf_Debug dbg,
+ Dwarf_Ptr bytes_in,
+ Dwarf_Unsigned block_len,
+ Dwarf_Half addr_size,
+ string &out_string)
+{
+
+ Dwarf_Locdesc *locdescarray = 0;
+ Dwarf_Signed listlen = 0;
+ Dwarf_Error err2 =0;
+ int skip_locdesc_header=1;
+ int res = 0;
+ int res2 = dwarf_loclist_from_expr_a(dbg,
+ bytes_in,block_len,
+ addr_size,
+ &locdescarray,
+ &listlen,&err2);
+ if (res2 == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_loclist_from_expr_a",
+ res2, err2);
+ }
+ if(res2==DW_DLV_NO_ENTRY) {
+ return;
+ }
+ /* lcnt is always 1 */
+
+ /* Use locdescarray here.*/
+ res = dwarfdump_print_one_locdesc(dbg,
+ locdescarray,
+ skip_locdesc_header,
+ out_string);
+ if(res != DW_DLV_OK) {
+ cout <<"Bad status from _dwarf_print_one_locdesc " <<
+ res << endl;
+ exit(1);
+ }
+ dwarf_dealloc(dbg, locdescarray->ld_s, DW_DLA_LOC_BLOCK);
+ dwarf_dealloc(dbg, locdescarray, DW_DLA_LOCDESC);
+ return ;
+}
+
+/* Print the frame instructions in detail for a glob of instructions.
+*/
+
+/*ARGSUSED*/ void
+print_frame_inst_bytes(Dwarf_Debug dbg,
+ Dwarf_Ptr cie_init_inst, Dwarf_Signed len,
+ Dwarf_Signed data_alignment_factor,
+ int code_alignment_factor, Dwarf_Half addr_size,
+ struct dwconf_s *config_data)
+{
+ unsigned char *instp = (unsigned char *) cie_init_inst;
+ Dwarf_Unsigned uval = 0;
+ Dwarf_Unsigned uval2 = 0;
+ unsigned int uleblen = 0;
+ unsigned int off = 0;
+ unsigned int loff = 0;
+ unsigned short u16 = 0;
+ unsigned int u32 = 0;
+ unsigned long long u64 = 0;
+
+ for (; len > 0;) {
+ unsigned char ibyte = *instp;
+ int top = ibyte & 0xc0;
+ int bottom = ibyte & 0x3f;
+ int delta = 0;
+ int reg = 0;
+ const char *cfa_name_x = 0;
+ string cfa_name("Unknown-frame-operator");
+ int res = dwarf_get_CFA_name(top,&cfa_name_x);
+ // The odd character of DFA symbols because of
+ // the packing means DW_CFA_extended and DW_CFA_nop
+ // conflict.
+ if(res == DW_DLV_OK) {
+ cfa_name = cfa_name_x;
+ }
+ switch (top) {
+ case DW_CFA_advance_loc:
+ delta = ibyte & 0x3f;
+ cout << "\t" << IToDec(off,2);
+ cout << " DW_CFA_advance_loc " <<
+ (delta * code_alignment_factor);
+ if (verbose) {
+ cout <<" (" << delta << " * " <<
+ code_alignment_factor << ")";
+ }
+ cout << endl;
+ break;
+ case DW_CFA_offset:
+ loff = off;
+ reg = ibyte & 0x3f;
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ cout << "\t" << IToDec(loff,2);
+ cout << " DW_CFA_offset " ;
+ printreg((Dwarf_Signed) reg, config_data);
+ cout << " " << (((Dwarf_Signed) uval) * data_alignment_factor);
+ if (verbose) {
+ cout << " (" << uval << " * " << data_alignment_factor <<
+ ")";
+ }
+ cout << endl;
+ break;
+
+ case DW_CFA_restore:
+ reg = ibyte & 0x3f;
+ cout << "\t" << IToDec(off,2) << SpaceSurround(cfa_name);
+ printreg((Dwarf_Signed) reg, config_data);
+ cout << endl;
+ break;
+
+ default:
+ res = dwarf_get_CFA_name(bottom,&cfa_name_x);
+ if(res == DW_DLV_OK) {
+ cfa_name = cfa_name_x;
+ }
+ loff = off;
+ switch (bottom) {
+ case DW_CFA_set_loc:
+ /* operand is address, so need address size */
+ /* which will be 4 or 8. */
+ switch (addr_size) {
+ case 4:
+ {
+ __uint32_t v32 = 0;
+ memcpy(&v32, instp + 1, addr_size);
+ uval = v32;
+ }
+ break;
+ case 8:
+ {
+ __uint64_t v64 = 0;
+ memcpy(&v64, instp + 1, addr_size);
+ uval = v64;
+ }
+ break;
+ default:
+ cout <<
+ "Error: Unexpected address size " <<
+ addr_size << " in DW_CFA_set_loc!" << endl;
+ uval = 0;
+ }
+
+ instp += addr_size;
+ len -= (Dwarf_Signed) addr_size;
+ off += addr_size;
+ cout << "\t" << IToDec(loff,2);
+ cout << " DW_CFA_set_loc " << uval << endl;
+ break;
+ case DW_CFA_advance_loc1:
+ delta = (unsigned char) *(instp + 1);
+ uval2 = delta;
+ instp += 1;
+ len -= 1;
+ off += 1;
+ cout << "\t" << IToDec(loff,2);
+ cout << SpaceSurround(cfa_name) << uval2 << endl;
+ break;
+ case DW_CFA_advance_loc2:
+ memcpy(&u16, instp + 1, 2);
+ uval2 = u16;
+ instp += 2;
+ len -= 2;
+ off += 2;
+ cout << "\t" << IToDec(loff,2);
+ cout << SpaceSurround(cfa_name) << uval2 << endl;
+ break;
+ case DW_CFA_advance_loc4:
+ memcpy(&u32, instp + 1, 4);
+ uval2 = u32;
+ instp += 4;
+ len -= 4;
+ off += 4;
+ cout << "\t" << IToDec(loff,2);
+ cout << SpaceSurround(cfa_name) << uval2 << endl;
+ break;
+ case DW_CFA_MIPS_advance_loc8:
+ memcpy(&u64, instp + 1, 8);
+ uval2 = u64;
+ instp += 8;
+ len -= 8;
+ off += 8;
+ cout << "\t" << IToDec(loff,2);
+ cout << SpaceSurround(cfa_name) << uval2 << endl;
+ break;
+ case DW_CFA_offset_extended:
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ uval2 =
+ local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ cout << "\t" << IToDec(loff,2);
+ cout << SpaceSurround(cfa_name);
+ printreg((Dwarf_Signed) uval, config_data);
+ cout << " " << (Dwarf_Signed) (((Dwarf_Signed) uval2) *
+ data_alignment_factor);
+ if (verbose) {
+ cout << " (" << uval2 << " * " <<
+ data_alignment_factor << ")";
+ }
+ cout << endl;
+ break;
+
+ case DW_CFA_restore_extended:
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ cout << "\t" << IToDec(loff,2);
+ cout << SpaceSurround(cfa_name);
+ printreg((Dwarf_Signed) uval, config_data);
+ cout << endl;
+ break;
+ case DW_CFA_undefined:
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ cout << "\t" << IToDec(loff,2);
+ cout << SpaceSurround(cfa_name);
+ printreg((Dwarf_Signed) uval, config_data);
+ cout << endl;
+ break;
+ case DW_CFA_same_value:
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ cout << "\t" << IToDec(loff,2);
+ cout << SpaceSurround(cfa_name);
+ printreg((Dwarf_Signed) uval, config_data);
+ cout << endl;
+ break;
+ case DW_CFA_register:
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ uval2 =
+ local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ cout << "\t" << IToDec(loff,2);
+ cout << SpaceSurround(cfa_name);
+ printreg((Dwarf_Signed) uval, config_data);
+ cout <<" = ";
+ printreg((Dwarf_Signed) uval2, config_data);
+ cout << endl;
+ break;
+ case DW_CFA_remember_state:
+ cout << "\t" << IToDec(loff,2);
+ cout << " " << cfa_name;
+ cout << endl;
+ break;
+ case DW_CFA_restore_state:
+ cout << "\t" << IToDec(loff,2);
+ cout << " " << cfa_name;
+ cout << endl;
+ break;
+ case DW_CFA_def_cfa:
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ uval2 =
+ local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ cout << "\t" << IToDec(loff,2);
+ cout << SpaceSurround(cfa_name);
+ printreg((Dwarf_Signed) uval, config_data);
+ cout << " " << uval2;
+ cout << endl;
+ break;
+ case DW_CFA_def_cfa_register:
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ cout << "\t" << IToDec(loff,2);
+ cout << SpaceSurround(cfa_name);
+ printreg((Dwarf_Signed) uval, config_data);
+ cout << endl;
+ break;
+ case DW_CFA_def_cfa_offset:
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ cout << "\t" << IToDec(loff,2);
+ cout << SpaceSurround(cfa_name) << uval;
+ cout << endl;
+ break;
+
+ case DW_CFA_nop:
+ cout << "\t" << IToDec(loff,2);
+ // cfa name is wrong here due to
+ // cfa operation value conflict
+ cout << " " << "DW_CFA_nop";
+ cout << endl;
+ break;
+
+ case DW_CFA_def_cfa_expression: /* DWARF3 */
+ {
+ Dwarf_Unsigned block_len =
+ local_dwarf_decode_u_leb128(instp + 1,
+ &uleblen);
+
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ cout << "\t" << IToDec(loff,2);
+ cout <<
+ " " << cfa_name << " expr block len " <<
+ block_len << endl;
+ dump_block("\t\t", (char *) instp+1,
+ (Dwarf_Signed) block_len);
+ cout << endl;
+ if(verbose) {
+ string exprstring;
+ get_string_from_locs(dbg,
+ instp+1,block_len, addr_size,exprstring);
+ cout << "\t\t" << exprstring << endl;
+ }
+ instp += block_len;
+ len -= block_len;
+ off += block_len;
+ }
+ break;
+ case DW_CFA_expression: /* DWARF3 */
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ {
+ /* instp is always 1 byte back, so we need +1
+ when we use it. See the final increment
+ of this for loop. */
+ Dwarf_Unsigned block_len =
+ local_dwarf_decode_u_leb128(instp + 1,
+ &uleblen);
+
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ cout << "\t" << IToDec(loff,2);
+ cout << SpaceSurround(cfa_name) << uval ;
+ cout << " expr block len " << block_len << endl;
+ dump_block("\t\t", (char *) instp+1,
+ (Dwarf_Signed) block_len);
+ cout << endl;
+ if(verbose) {
+ string exprstring;
+ get_string_from_locs(dbg,
+ instp+1,block_len, addr_size,exprstring);
+ cout<< "\t\t" <<exprstring << endl;
+ }
+ instp += block_len;
+ len -= block_len;
+ off += block_len;
+ }
+
+ break;
+ case DW_CFA_offset_extended_sf: /* DWARF3 */
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ {
+ /* instp is always 1 byte back, so we need +1
+ when we use it. See the final increment
+ of this for loop. */
+ Dwarf_Signed sval2 =
+ local_dwarf_decode_s_leb128(instp + 1,
+ &uleblen);
+
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ cout << "\t" << IToDec(loff,2);
+ cout << SpaceSurround(cfa_name);
+ printreg((Dwarf_Signed) uval, config_data);
+ cout << " " << ((Dwarf_Signed)
+ ((sval2) * data_alignment_factor));
+ if (verbose) {
+ cout << " (" << sval2 << " * "<<
+ data_alignment_factor << ")";
+ }
+ }
+ cout << endl;
+ break;
+ case DW_CFA_def_cfa_sf: /* DWARF3 */
+ /* instp is always 1 byte back, so we need +1
+ when we use it. See the final increment
+ of this for loop. */
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ {
+ Dwarf_Signed sval2 =
+ local_dwarf_decode_s_leb128(instp + 1,
+ &uleblen);
+
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ cout << "\t" << IToDec(loff,2);
+ cout << SpaceSurround(cfa_name);
+ printreg((Dwarf_Signed) uval, config_data);
+ cout << " "<< sval2 ;
+ cout << " (*data alignment factor=>" <<
+ ((Dwarf_Signed)(sval2*data_alignment_factor)) <<
+ ")";
+ }
+ cout << endl;
+ break;
+ case DW_CFA_def_cfa_offset_sf: /* DWARF3 */
+ {
+ /* instp is always 1 byte back, so we need +1
+ when we use it. See the final increment
+ of this for loop. */
+ Dwarf_Signed sval =
+ local_dwarf_decode_s_leb128(instp + 1,
+ &uleblen);
+
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ cout << "\t" << IToDec(loff,2);
+ cout << SpaceSurround(cfa_name) << sval;
+ cout << " (*data alignment factor=> "<<
+ ((Dwarf_Signed)(sval*data_alignment_factor)) <<
+ ")" << endl;
+ }
+ break;
+ case DW_CFA_val_offset: /* DWARF3 */
+ /* instp is always 1 byte back, so we need +1
+ when we use it. See the final increment
+ of this for loop. */
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ {
+ Dwarf_Signed sval2 =
+ local_dwarf_decode_s_leb128(instp + 1,
+ &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ cout << "\t" << IToDec(loff,2);
+ cout << SpaceSurround(cfa_name);
+ printreg((Dwarf_Signed)uval, config_data);
+ cout << " " <<
+ ((Dwarf_Signed) (sval2 *
+ data_alignment_factor));
+ if (verbose) {
+ cout <<" ("<< sval2 <<
+ " * " << data_alignment_factor;
+ }
+ }
+ cout << endl;
+ break;
+ case DW_CFA_val_offset_sf: /* DWARF3 */
+ /* instp is always 1 byte back, so we need +1
+ when we use it. See the final increment
+ of this for loop. */
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ {
+ Dwarf_Signed sval2 =
+ local_dwarf_decode_s_leb128(instp + 1,
+ &uleblen);
+
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ cout << "\t" << IToDec(loff,2);
+ cout << SpaceSurround(cfa_name);
+ printreg((Dwarf_Signed) uval, config_data);
+ cout << " " << ((sval2) * data_alignment_factor);
+ if (verbose) {
+ cout << " (" << sval2<< " * " <<
+ data_alignment_factor << ")";
+ }
+ }
+ cout << endl;
+ break;
+ case DW_CFA_val_expression: /* DWARF3 */
+ /* instp is always 1 byte back, so we need +1
+ when we use it. See the final increment
+ of this for loop. */
+ uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ {
+ Dwarf_Unsigned block_len =
+ local_dwarf_decode_u_leb128(instp + 1,
+ &uleblen);
+
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ cout << "\t" << IToDec(loff,2);
+ cout << SpaceSurround(cfa_name) << uval;
+ cout << " expr block len " << block_len << endl;
+ dump_block("\t\t", (char *) instp+1,
+ (Dwarf_Signed) block_len);
+ cout << endl;
+ if(verbose) {
+ string exprstring;
+ get_string_from_locs(dbg,
+ instp+1,block_len, addr_size,exprstring);
+ cout<< "\t\t" <<exprstring << endl;
+ }
+ instp += block_len;
+ len -= block_len;
+ off += block_len;
+ }
+
+
+ break;
+
+
+#ifdef DW_CFA_GNU_window_save
+ case DW_CFA_GNU_window_save:{
+ /* No information: this just tells unwinder to
+ the window registers from the previous
+ frame's window save area */
+ cout << "\t" << IToDec(loff,2);
+ cout << SpaceSurround(cfa_name) << endl;
+ }
+ break;
+#endif
+#ifdef DW_CFA_GNU_negative_offset_extended
+ case DW_CFA_GNU_negative_offset_extended:{
+ cout << "\t" << IToDec(loff,2);
+ cout << SpaceSurround(cfa_name) <<
+ endl;
+ }
+ break;
+#endif
+#ifdef DW_CFA_GNU_args_size
+ /* Single uleb128 is the current arg area size in
+ bytes. no register exists yet to save this in */
+ case DW_CFA_GNU_args_size:{
+ Dwarf_Unsigned lreg;
+
+ /* instp is always 1 byte back, so we need +1
+ when we use it. See the final increment
+ of this for loop. */
+ lreg = local_dwarf_decode_u_leb128(instp + 1,
+ &uleblen);
+ cout << "\t" << IToDec(loff,2);
+ cout << " " << cfa_name << " arg size: " <<
+ lreg << endl;
+ instp += uleblen;
+ len -= uleblen;
+ off += uleblen;
+ }
+ break;
+#endif
+
+ default:
+ cout << "\t" << IToDec(loff,2);
+ cout << " Unexpected op " <<
+ IToHex(bottom) << ":" << endl;
+ len = 0;
+ break;
+ }
+ }
+ instp++;
+ len--;
+ off++;
+ }
+}
+
+/* Print our register names for the cases we have a name.
+ Delegate to the configure code to actually do the print.
+*/
+void
+printreg(Dwarf_Signed reg, struct dwconf_s *config_data)
+{
+ print_reg_from_config_data(reg, config_data);
+}
+
+
+/* Actually does the printing of a rule in the table.
+ This may print something or may print nothing!
+*/
+
+static void
+print_one_frame_reg_col(Dwarf_Debug dbg,
+ Dwarf_Unsigned rule_id,
+ Dwarf_Small value_type,
+ Dwarf_Unsigned reg_used,
+ Dwarf_Half address_size,
+ struct dwconf_s *config_data,
+ Dwarf_Signed offset_relevant,
+ Dwarf_Signed offset,
+ Dwarf_Ptr block_ptr)
+{
+ string type_title = "";
+ int print_type_title = 1;
+ if (check_frames_extended) {
+ return;
+ }
+
+ if (config_data->cf_interface_number == 2)
+ print_type_title = 0;
+
+ switch (value_type) {
+ case DW_EXPR_OFFSET:
+ type_title = "off";
+ goto preg2;
+ case DW_EXPR_VAL_OFFSET:
+ type_title = "valoff";
+
+ preg2:
+ if (reg_used == config_data->cf_initial_rule_value) {
+ break;
+ }
+ if (print_type_title)
+ cout << "<" << type_title << " ";
+ printreg((Dwarf_Signed) rule_id, config_data);
+ cout << "=";
+ if (offset_relevant == 0) {
+ printreg((Dwarf_Signed) reg_used, config_data);
+ cout << " ";
+ } else {
+ cout << IToDec0N(offset,2);
+ cout << "(";
+ printreg((Dwarf_Signed) reg_used, config_data);
+ cout << ") ";
+ }
+ if (print_type_title)
+ cout << "> ";
+ break;
+ case DW_EXPR_EXPRESSION:
+ type_title = "expr";
+ goto pexp2;
+ case DW_EXPR_VAL_EXPRESSION:
+ type_title = "valexpr";
+
+ pexp2:
+ if (print_type_title)
+ cout << "<" << type_title << " ";
+ printreg((Dwarf_Signed) rule_id, config_data);
+ cout << "=";
+ cout << "expr-block-len=" << offset;
+ if (print_type_title)
+ cout << "> ";
+ if (verbose) {
+ if(block_ptr == 0) {
+ // Wrong (old) register access used.
+ // -R being just one way to request the 'reg3'
+ // register interfaces.
+ cout << "<Use -R to see content>";
+ } else {
+ string pref("<");
+ pref.append(type_title);
+ pref.append("bytes:");
+ dump_block(pref, reinterpret_cast<char *>(block_ptr), offset);
+ cout << "> ";
+ if(verbose) {
+ string exprstring;
+ get_string_from_locs(dbg,
+ block_ptr,offset, address_size,exprstring);
+ cout<< BracketSurround(string("expr:") +
+ exprstring);
+ }
+ }
+ }
+ break;
+ default:
+ cout <<"Internal error in libdwarf, value type " <<
+ value_type << endl;
+ exit(1);
+ }
+ return;
+
+}
+
+/* get all the data in .debug_frame (or .eh_frame).
+ The '3' versions mean print using the dwarf3 new interfaces.
+ The non-3 mean use the old interfaces.
+ All combinations of requests are possible. */
+extern void
+print_frames(Dwarf_Debug dbg, int print_debug_frame, int print_eh_frame,
+ struct dwconf_s *config_data)
+{
+ Dwarf_Half address_size = 0;
+ LowpcToNameMaptype map_lowpc_to_name;
+
+
+ error_message_data.current_section_id = DEBUG_FRAME;
+
+ // The address size here will not be right for all frames.
+ // Only in DWARF4 is there a real address size known
+ // in the frame data itself. If any DIE
+ // is known then a real address size can be gotten from
+ // dwarf_get_die_address_size().
+ int fres = dwarf_get_address_size(dbg, &address_size, &err);
+ if (fres != DW_DLV_OK) {
+ print_error(dbg, "dwarf_get_address_size", fres, err);
+ }
+ for (int framed = 0; framed < 2; ++framed) {
+ Dwarf_Cie *cie_data = NULL;
+ Dwarf_Signed cie_element_count = 0;
+ Dwarf_Fde *fde_data = NULL;
+ Dwarf_Signed fde_element_count = 0;
+ Dwarf_Signed i;
+ int frame_count = 0;
+ int cie_count = 0;
+ bool all_cus_seen(false);
+ LowpcUsedSettype lowpcSet;
+ string framename;
+ int silent_if_missing = 0;
+ int is_eh = 0;
+
+ if (framed == 0) {
+ if (!print_debug_frame) {
+ continue;
+ }
+ framename = ".debug_frame";
+ /* Big question here is how to print all the info?
+ Can print the logical matrix, but that is huge,
+ though could skip lines that don't change.
+ Either that, or print the instruction statement program
+ that describes the changes. */
+ fres = dwarf_get_fde_list(dbg, &cie_data, &cie_element_count,
+ &fde_data, &fde_element_count, &err);
+ if(check_harmless) {
+ print_any_harmless_errors(dbg);
+ }
+ } else {
+ if (!print_eh_frame) {
+ continue;
+ }
+ is_eh = 1;
+ /* This is gnu g++ exceptions in a .eh_frame section. Which
+ is just like .debug_frame except that the empty, or
+ 'special' CIE_id is 0, not -1 (to distinguish fde from
+ cie). And the augmentation is "eh". As of egcs-1.1.2
+ anyway. A non-zero cie_id is in a fde and is the
+ difference between the fde address and the beginning of
+ the cie it belongs to. This makes sense as this is
+ intended to be referenced at run time, and is part of
+ the running image. For more on augmentation strings, see
+ libdwarf/dwarf_frame.c. */
+
+ /* Big question here is how to print all the info?
+ Can print the logical matrix, but that is huge,
+ though could skip lines that don't change.
+ Either that, or print the instruction statement program
+ that describes the changes. */
+ silent_if_missing = 1;
+ framename = ".eh_frame";
+ fres = dwarf_get_fde_list_eh(dbg, &cie_data,
+ &cie_element_count, &fde_data,
+ &fde_element_count, &err);
+ if(check_harmless) {
+ print_any_harmless_errors(dbg);
+ }
+ }
+ /* Do not print any frame info if in check mode */
+ if (check_frames) {
+ continue;
+ }
+
+ if (fres == DW_DLV_ERROR) {
+ cout << endl;
+ cout << framename;
+ cout << endl;
+ print_error(dbg, "dwarf_get_fde_list", fres, err);
+ } else if (fres == DW_DLV_NO_ENTRY) {
+ if (!silent_if_missing) {
+ cout << endl;
+ cout << framename;
+ cout << endl;
+ }
+ /* no frame information */
+ } else { /* DW_DLV_OK */
+
+ if( !check_frames_extended) {
+ cout << endl;
+ cout << framename;
+ cout << endl;
+ cout << endl;
+ cout << "fde:";
+ cout << endl;
+ }
+
+ for (i = 0; i < fde_element_count; i++) {
+ print_one_fde(dbg, fde_data[i],
+ i, cie_data, cie_element_count,
+ address_size, is_eh, config_data,
+ map_lowpc_to_name,
+ lowpcSet,
+ all_cus_seen);
+ ++frame_count;
+ if(frame_count >= break_after_n_units) {
+ break;
+ }
+ }
+ /* Print the cie set. */
+ if (verbose) {
+ /* Do not print if in check mode */
+ if (!check_frames_extended) {
+ cout << endl;
+ cout << "cie:";
+ cout << endl;
+ }
+ for (i = 0; i < cie_element_count; i++) {
+ print_one_cie(dbg, cie_data[i], i, address_size,
+ config_data);
+ ++cie_count;
+ if(cie_count >= break_after_n_units) {
+ break;
+ }
+ }
+ }
+ dwarf_fde_cie_list_dealloc(dbg, cie_data, cie_element_count,
+ fde_data, fde_element_count);
+ }
+ }
+}
+
diff --git a/dwarfdump2/print_frames.h b/dwarfdump2/print_frames.h
new file mode 100644
index 0000000..5bdc27d
--- /dev/null
+++ b/dwarfdump2/print_frames.h
@@ -0,0 +1,59 @@
+/*
+ Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_frames.h,v 1.2 2006/04/17 00:09:56 davea Exp $ */
+
+int
+print_one_fde(Dwarf_Debug dbg, Dwarf_Fde fde,
+ Dwarf_Unsigned fde_index,
+ Dwarf_Cie * cie_data,
+ Dwarf_Signed cie_element_count,
+ Dwarf_Half address_size,
+ int is_eh,
+ struct dwconf_s * config_data);
+
+int
+print_one_cie(Dwarf_Debug dbg, Dwarf_Cie cie,
+ Dwarf_Unsigned cie_index,
+ Dwarf_Half address_size,
+ struct dwconf_s * config_data);
+
+void
+get_string_from_locs(Dwarf_Debug dbg,
+ Dwarf_Ptr bytes_in,
+ Dwarf_Unsigned block_len,
+ Dwarf_Half addr_size,
+ std::string &out_string);
+
+
diff --git a/dwarfdump2/print_lines.cc b/dwarfdump2/print_lines.cc
new file mode 100644
index 0000000..ce965ce
--- /dev/null
+++ b/dwarfdump2/print_lines.cc
@@ -0,0 +1,435 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include "globals.h"
+#include <vector>
+#include "naming.h"
+#include "uri.h"
+#include "dwconf.h"
+
+#include "print_frames.h"
+
+using std::string;
+using std::cout;
+using std::cerr;
+using std::endl;
+
+static void
+print_source_intro(Dwarf_Die cu_die)
+{
+ Dwarf_Off off = 0;
+ int ores = dwarf_dieoffset(cu_die, &off, &err);
+
+ if (ores == DW_DLV_OK) {
+ cout << "Source lines (from CU-DIE at .debug_info offset ";
+ cout << IToHex0N(off,10);
+ cout << "):" << endl;
+ } else {
+ cout <<"Source lines (for the CU-DIE at unknown location):" <<
+ endl;
+ }
+}
+
+static void
+record_line_error(const std::string &where, Dwarf_Error err)
+{
+ if(check_lines && checking_this_compiler()) {
+ string msg("Error getting line details calling ");
+ msg.append(where);
+ msg.append(" dwarf error is ");
+
+ const char *estring = dwarf_errmsg(err);
+
+ msg.append(estring);
+ DWARF_CHECK_ERROR(lines_result,msg);
+ }
+}
+
+/* Print line number information:
+
+ filename
+ new basic-block
+ [line] [address] <new statement>
+*/
+
+void
+print_line_numbers_this_cu(DieHolder & hcudie)
+{
+ Dwarf_Die cu_die = hcudie.die();
+ Dwarf_Debug dbg = hcudie.dbg();
+
+ bool SkipRecord = false;
+
+ error_message_data.current_section_id = DEBUG_LINE;
+ if(do_print_dwarf) {
+ cout << endl;
+ cout << ".debug_line: line number info for a single cu"<< endl;
+ }
+ if ( verbose > 1) {
+ int errcount = 0;
+ print_source_intro(cu_die);
+ SrcfilesHolder hsrcfiles;
+ print_one_die(hcudie, /* print_information= */ 1,
+ /* indent_level= */ 0,
+ hsrcfiles,
+ /* ignore_die_printed_flag= */true);
+ DWARF_CHECK_COUNT(lines_result,1);
+ int lres = dwarf_print_lines(cu_die, &err,&errcount);
+ if(errcount > 0) {
+ DWARF_ERROR_COUNT(lines_result,errcount);
+ DWARF_CHECK_COUNT(lines_result,(errcount-1));
+ }
+ if (lres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_srclines details", lres, err);
+ }
+ return;
+ }
+ if(check_lines && checking_this_compiler()) {
+ DWARF_CHECK_COUNT(lines_result,1);
+ int line_errs = 0;
+ dwarf_check_lineheader(cu_die,&line_errs);
+ if(line_errs > 0) {
+ DWARF_CHECK_ERROR_PRINT_CU();
+ DWARF_ERROR_COUNT(lines_result,line_errs);
+ DWARF_CHECK_COUNT(lines_result,(line_errs-1));
+ }
+ }
+ Dwarf_Signed linecount = 0;
+ Dwarf_Line *linebuf = NULL;
+ int lres = dwarf_srclines(cu_die, &linebuf, &linecount, &err);
+ if (lres == DW_DLV_ERROR) {
+ /* Do not terminate processing. */
+ if (check_decl_file) {
+ DWARF_CHECK_COUNT(decl_file_result,1);
+ DWARF_CHECK_ERROR2(decl_file_result,"dwarf_srclines",
+ dwarf_errmsg(err));
+ record_dwarf_error = false; /* Clear error condition */
+ } else {
+ print_error(dbg, "dwarf_srclines", lres, err);
+ }
+ } else if (lres == DW_DLV_NO_ENTRY) {
+ /* no line information is included */
+ } else {
+ if(do_print_dwarf) {
+ print_source_intro(cu_die);
+ if (verbose) {
+ SrcfilesHolder hsrcfiles;
+ print_one_die(hcudie, /* print_information= */ 1,
+ /* indent_level= */ 0,
+ hsrcfiles,
+ /* ignore_die_printed_flag= */true);
+ }
+ cout << endl;
+ cout <<
+ "<pc> [row,col] NS BB ET PE EB IS= DI= uri: \"filepath\""
+ << endl;
+ cout <<
+ "NS new statement, BB new basic block, ET end of text sequence"
+ << endl;
+ cout <<
+ "PE prologue end, EB epilogue begin"
+ << endl;
+ cout <<
+ "IA=val ISA number, DI=val discriminator value"
+ << endl;
+ }
+ string lastsrc = "";
+ for (Dwarf_Signed i = 0; i < linecount; i++) {
+ Dwarf_Line line = linebuf[i];
+ char *filenamearg = 0;
+ bool found_line_error = false;
+ Dwarf_Bool has_is_addr_set = 0;
+ string where;
+
+ if (check_decl_file && checking_this_compiler()) {
+ /* A line record with addr=0 was detected */
+ if (SkipRecord) {
+ /* Skip records that do not have ís_addr_set' */
+ int ares1 = dwarf_line_is_addr_set(line, &has_is_addr_set, &err);
+ if (ares1 == DW_DLV_OK && has_is_addr_set) {
+ SkipRecord = false;
+ } else {
+ /* Keep ignoring records until we have
+ one with 'is_addr_set' */
+ continue;
+ }
+ }
+ }
+
+
+ if (check_lines && checking_this_compiler()) {
+ DWARF_CHECK_COUNT(lines_result,1);
+ }
+ string filename("<unknown>");
+ int sres = dwarf_linesrc(line, &filenamearg, &err);
+ if (sres == DW_DLV_ERROR) {
+ where = "dwarf_linesrc()";
+ found_line_error = true;
+ record_line_error(where,err);
+ }
+ if (sres == DW_DLV_OK) {
+ filename = filenamearg;
+ dwarf_dealloc(dbg, filenamearg, DW_DLA_STRING);
+ filenamearg = 0;
+ }
+ Dwarf_Addr pc = 0;
+ int ares = dwarf_lineaddr(line, &pc, &err);
+ if (ares == DW_DLV_ERROR) {
+ where = "dwarf_lineaddr()";
+ found_line_error = true;
+ record_line_error(where,err);
+ }
+ if (ares == DW_DLV_NO_ENTRY) {
+ pc = 0;
+ }
+ Dwarf_Unsigned lineno = 0;
+ int lires = dwarf_lineno(line, &lineno, &err);
+ if (lires == DW_DLV_ERROR) {
+ where = "dwarf_lineno()";
+ found_line_error = true;
+ record_line_error(where,err);
+ }
+ if (lires == DW_DLV_NO_ENTRY) {
+ lineno = -1LL;
+ }
+ Dwarf_Unsigned column = 0;
+ int cores = dwarf_lineoff_b(line, &column, &err);
+ if (cores == DW_DLV_ERROR) {
+ where = "dwarf_lineoff()";
+ found_line_error = true;
+ record_line_error(where,err);
+ }
+ if (cores == DW_DLV_NO_ENTRY) {
+ /* Zero was always the correct default, meaning
+ the left edge. DWARF2/3/4 spec sec 6.2.2 */
+ column = 0;
+ }
+
+ /* Process any possible error condition, though
+ we won't be at the first such error. */
+ if (check_decl_file && checking_this_compiler()) {
+ DWARF_CHECK_COUNT(decl_file_result,1);
+ if (found_line_error) {
+ DWARF_CHECK_ERROR2(decl_file_result,where,dwarf_errmsg(err));
+ } else if (do_check_dwarf) {
+ /* Check the address lies with a valid [lowPC:highPC]
+ in the .text section*/
+ if (pAddressRangesData->IsAddressInAddressRange(pc)) {
+ /* Valid values; do nothing */
+ } else {
+ /* At this point may be we are dealing with
+ a linkonce symbol. The problem we have here
+ is we have consumed the deug_info section
+ and we are dealing just with the records
+ from the .debug_line, so no PU_name is
+ available and no high_pc. Traverse the linkonce
+ table if try to match the pc value with
+ one of those ranges.
+ */
+ if (check_lines && checking_this_compiler()) {
+ DWARF_CHECK_COUNT(lines_result,1);
+ }
+ if (pLinkOnceData->FindLinkOnceEntry(pc)){
+ /* Valid values; do nothing */
+ } else {
+ /* The SN Systems Linker generates
+ line records
+ with addr=0, when dealing with linkonce
+ symbols and no stripping */
+ if (pc) {
+ char addr_tmp[100];
+ if(check_lines && checking_this_compiler()) {
+ snprintf(addr_tmp,sizeof(addr_tmp),
+ ".debug_line: Address"
+ " 0x%" DW_PR_XZEROS DW_PR_DUx
+ " outside a valid .text range",pc);
+ DWARF_CHECK_ERROR(lines_result,
+ addr_tmp);
+ }
+ } else {
+ SkipRecord = true;
+ }
+ }
+ }
+ /* Check the last record for the .debug_line,
+ the one created by DW_LNE_end_sequence,
+ is the same as the high_pc
+ address for the last known user program
+ unit (PU) */
+ if ((i + 1 == linecount) &&
+ error_message_data.seen_PU_high_address) {
+ /* Ignore those PU that have been stripped
+ by the linker; their low_pc values are
+ set to -1 (snc linker only) */
+ /* It is perfectly sensible for a compiler
+ to leave a few bytes of NOP or other stuff
+ after the last instruction in a subprogram,
+ for cache-alignment or other purposes, so
+ a mismatch here is not necessarily
+ an error. */
+
+ if (check_lines && checking_this_compiler()) {
+ DWARF_CHECK_COUNT(lines_result,1);
+ if ((pc != error_message_data.PU_high_address) &&
+ (error_message_data.PU_base_address !=
+ error_message_data.elf_max_address)) {
+ char addr_tmp[100];
+ snprintf(addr_tmp,sizeof(addr_tmp),
+ ".debug_line: Address"
+ " 0x%" DW_PR_XZEROS DW_PR_DUx
+ " may be incorrect"
+ " as DW_LNE_end_sequence address",pc);
+ DWARF_CHECK_ERROR(lines_result,
+ addr_tmp);
+ }
+ }
+ }
+ }
+ }
+
+ /* Display the error information */
+ if (found_line_error || record_dwarf_error) {
+ if (check_verbose_mode) {
+ /* Print the record number for better error description */
+ cout << "Record = " <<
+ i << " Addr = " << IToHex0N(pc,10) <<
+ " [" << IToDec(lineno,4) <<
+ ","<< IToDec(column,2) <<
+ "] '" << filename << "'" << endl;
+ /* Flush due to the redirection of stderr */
+ cout.flush();
+ /* The compilation unit was already printed */
+ if (!check_decl_file) {
+ PRINT_CU_INFO();
+ }
+ }
+ record_dwarf_error = false;
+ /* Due to a fatal error, skip current record */
+ if (found_line_error) {
+ continue;
+ }
+ }
+
+ if(do_print_dwarf) {
+ cout << IToHex0N(pc,10) << " [" <<
+ IToDec(lineno,4) << "," <<
+ IToDec(column,2) <<
+ "]" ;
+ }
+
+ Dwarf_Bool newstatement = 0;
+ int nsres = dwarf_linebeginstatement(line, &newstatement, &err);
+ if (nsres == DW_DLV_OK) {
+ if (do_print_dwarf && newstatement) {
+ cout <<" NS";
+ }
+ } else if (nsres == DW_DLV_ERROR) {
+ print_error(dbg, "linebeginstatment failed", nsres,
+ err);
+ }
+ Dwarf_Bool new_basic_block = 0;
+ nsres = dwarf_lineblock(line, &new_basic_block, &err);
+ if (nsres == DW_DLV_OK) {
+ if (do_print_dwarf && new_basic_block) {
+ cout <<" BB";
+ }
+ } else if (nsres == DW_DLV_ERROR) {
+ print_error(dbg, "lineblock failed", nsres, err);
+ }
+ Dwarf_Bool lineendsequence = 0;
+ nsres = dwarf_lineendsequence(line, &lineendsequence, &err);
+ if (nsres == DW_DLV_OK) {
+ if (do_print_dwarf && lineendsequence) {
+ cout <<" ET";
+ }
+ } else if (nsres == DW_DLV_ERROR) {
+ print_error(dbg, "lineblock failed", nsres, err);
+ }
+ if (do_print_dwarf) {
+ Dwarf_Bool prologue_end = 0;
+ Dwarf_Bool epilogue_begin = 0;
+ Dwarf_Unsigned isa = 0;
+ Dwarf_Unsigned discriminator = 0;
+ int disres = dwarf_prologue_end_etc(line,
+ &prologue_end,&epilogue_begin,
+ &isa,&discriminator,&err);
+ if (disres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_prologue_end_etc() failed",
+ disres, err);
+ }
+ if(prologue_end) {
+ cout <<" PE";
+ }
+ if(epilogue_begin) {
+ cout <<" EB";
+ }
+ if(isa) {
+ cout <<" IS=";
+ cout << IToHex(isa);
+ }
+ if(discriminator) {
+ cout <<" DI=";
+ cout << IToHex(discriminator);
+ }
+ }
+
+ // Here avoid so much duplication of long file paths.
+ if (i > 0 && verbose < 3 && filename == lastsrc ){
+ /* print no name, leave blank. */
+ } else {
+ string urs(" uri: \"");
+ translate_to_uri(filename.c_str(),urs);
+ urs.append("\"");
+ if (do_print_dwarf) {
+ cout << urs ;
+ }
+ lastsrc = filename;
+ }
+ if(do_print_dwarf) {
+ cout << endl;
+ }
+ }
+ dwarf_srclines_dealloc(dbg, linebuf, linecount);
+ }
+}
+
diff --git a/dwarfdump2/print_locs.cc b/dwarfdump2/print_locs.cc
new file mode 100644
index 0000000..b4c5edc
--- /dev/null
+++ b/dwarfdump2/print_locs.cc
@@ -0,0 +1,131 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2008-2010 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include "globals.h"
+#include <vector>
+#include "naming.h"
+#include "dwconf.h"
+
+#include "print_frames.h"
+
+using std::string;
+using std::cout;
+using std::cerr;
+using std::endl;
+
+/* print data in .debug_loc
+ There is no guarantee this will work because we are assuming
+ that all bytes are valid loclist data, that there are no
+ odd padding or garbage bytes. In normal use one gets
+ into here via an offset from .debug_info, so it could be
+ that bytes not referenced from .debug_info are garbage
+ or even zero padding. So this can fail (error off) as such bytes
+ can lead dwarf_get_loclist_entry() astray.
+
+ It is also broken because we do not know what CU is involved
+ so if address_size varies by CU we cannot know that here.
+*/
+
+void
+print_locs(Dwarf_Debug dbg)
+{
+ Dwarf_Unsigned offset = 0;
+ Dwarf_Addr hipc_offset = 0;
+ Dwarf_Addr lopc_offset = 0;
+ Dwarf_Ptr data = 0;
+ Dwarf_Unsigned entry_len = 0;
+ Dwarf_Unsigned next_entry = 0;
+ int index = 0;
+ int lres = 0;
+ Dwarf_Half address_size = 0;
+
+ error_message_data.current_section_id = DEBUG_LOC;
+ if(!do_print_dwarf) {
+ return;
+ }
+
+ /* This is sometimes wrong, we need a frame-specific size. */
+ int fres = dwarf_get_address_size(dbg, &address_size, &err);
+ if (fres != DW_DLV_OK) {
+ print_error(dbg, "dwarf_get_address_size", fres, err);
+ }
+
+
+ cout << endl;
+ cout << ".debug_loc" << endl;
+ cout <<"Format <i o b e l>: "
+ "index section-offset begin-addr end-addr length-of-block-entry";
+ cout << endl;
+ while ((lres = dwarf_get_loclist_entry(dbg, offset,
+ &hipc_offset, &lopc_offset,
+ &data, &entry_len,
+ &next_entry,
+ &err)) == DW_DLV_OK) {
+
+ string exprstring;
+ get_string_from_locs(dbg,data,entry_len,address_size,exprstring);
+ if( display_offsets) {
+ ++index;
+ cout <<" <iobel> [" << IToDec(index,8);
+ cout <<"] " << IToHex0N(offset,10);
+ // We print this offset so it matches what the debug_info
+ // loclist offset shows (so we can relate them).
+ // This offset is the offset of the expression byte blob.
+ if(verbose) {
+ cout << string(" ") <<
+ BracketSurround(string("expr-off ") +
+ IToHex0N(next_entry - entry_len,10));
+ }
+ }
+ cout <<" "<< IToHex0N(lopc_offset,10);
+ cout <<" "<< IToHex0N(hipc_offset,10);
+ cout <<" "<< IToDec(entry_len,8);
+ cout <<" "<< exprstring;
+ cout << endl;
+ offset = next_entry;
+ }
+ if (lres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_loclist_entry", lres, err);
+ }
+}
+
diff --git a/dwarfdump2/print_macros.cc b/dwarfdump2/print_macros.cc
new file mode 100644
index 0000000..b79c281
--- /dev/null
+++ b/dwarfdump2/print_macros.cc
@@ -0,0 +1,208 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include "globals.h"
+#include <vector>
+#include "naming.h"
+#include "dwconf.h"
+
+#include "print_frames.h"
+
+using std::string;
+using std::cout;
+using std::cerr;
+using std::endl;
+struct macro_counts_s {
+ long mc_start_file;
+ long mc_end_file;
+ long mc_define;
+ long mc_undef;
+ long mc_extension;
+ long mc_code_zero;
+ long mc_unknown;
+};
+
+static void
+print_one_macro_entry_detail(long i,
+ const std::string&type,
+ struct Dwarf_Macro_Details_s *mdp)
+{
+ /* "DW_MACINFO_*: section-offset file-index [line] string\n" */
+ cout << IToDec(i,3);
+ cout <<" " << type;
+ cout <<": " << IToDec(mdp->dmd_offset,6);
+ cout <<" " << IToDec(mdp->dmd_fileindex,2);
+ cout <<" [" << IToDec(mdp->dmd_lineno,4);
+ if (mdp->dmd_macro) {
+ cout <<"] \"" << mdp->dmd_macro << "\" " << endl;
+ } else {
+ cout <<"] 0" << endl;
+ }
+}
+
+
+
+static void
+print_one_macro_entry(long i,
+ struct Dwarf_Macro_Details_s *mdp,
+ struct macro_counts_s *counts)
+{
+
+ switch (mdp->dmd_type) {
+ case 0:
+ counts->mc_code_zero++;
+ print_one_macro_entry_detail(i, "DW_MACINFO_type-code-0", mdp);
+ break;
+
+ case DW_MACINFO_start_file:
+ counts->mc_start_file++;
+ print_one_macro_entry_detail(i, "DW_MACINFO_start_file", mdp);
+ break;
+
+ case DW_MACINFO_end_file:
+ counts->mc_end_file++;
+ print_one_macro_entry_detail(i, "DW_MACINFO_end_file ", mdp);
+ break;
+
+ case DW_MACINFO_vendor_ext:
+ counts->mc_extension++;
+ print_one_macro_entry_detail(i, "DW_MACINFO_vendor_ext", mdp);
+ break;
+
+ case DW_MACINFO_define:
+ counts->mc_define++;
+ print_one_macro_entry_detail(i, "DW_MACINFO_define ", mdp);
+ break;
+
+ case DW_MACINFO_undef:
+ counts->mc_undef++;
+ print_one_macro_entry_detail(i, "DW_MACINFO_undef ", mdp);
+ break;
+
+ default:
+ {
+ char create_type[50]; /* More than large enough. */
+
+ counts->mc_unknown++;
+ snprintf(create_type, sizeof(create_type),
+ "DW_MACINFO_0x%x", mdp->dmd_type);
+ print_one_macro_entry_detail(i, create_type, mdp);
+ }
+ break;
+ }
+}
+
+/* print data in .debug_macinfo */
+/* FIXME: should print name of file whose index is in macro data
+ here -- somewhere.
+*/
+/*ARGSUSED*/ extern void
+print_macinfo(Dwarf_Debug dbg)
+{
+ Dwarf_Off offset = 0;
+ Dwarf_Unsigned max = 0;
+ Dwarf_Signed count = 0;
+ long group = 0;
+ Dwarf_Macro_Details *maclist = NULL;
+ int lres = 0;
+
+ error_message_data.current_section_id = DEBUG_MACINFO;
+ if(!do_print_dwarf) {
+ return;
+ }
+ cout << endl;
+ cout << ".debug_macinfo" << endl;
+
+ while ((lres = dwarf_get_macro_details(dbg, offset,
+ max, &count, &maclist,
+ &err)) == DW_DLV_OK) {
+ long i;
+ struct macro_counts_s counts;
+
+
+ memset(&counts, 0, sizeof(counts));
+
+ cout << endl;
+ cout << "compilation-unit .debug_macinfo # " << group << endl;
+ cout <<
+ "num name section-offset file-index [line] \"string\"" << endl;
+ for (i = 0; i < count; i++) {
+ struct Dwarf_Macro_Details_s *mdp = &maclist[i];
+
+ print_one_macro_entry(i, mdp, &counts);
+ }
+
+ if (counts.mc_start_file == 0) {
+ cout <<
+ "DW_MACINFO file count of zero is invalid DWARF2/3" <<endl;
+ }
+ if (counts.mc_start_file != counts.mc_end_file) {
+ cout << "Counts of DW_MACINFO file (" << counts.mc_start_file;
+ cout << ") end_file (" << counts.mc_end_file;
+ cout << ") do not match!." << endl;
+ }
+ if (counts.mc_code_zero < 1) {
+ cout <<"Count of zeros in macro group should be non-zero "
+ "(1 preferred), count is " <<
+ counts.mc_code_zero << endl;
+ }
+ cout << "Macro counts: start file " << counts.mc_start_file;
+ cout << ", end file " << counts.mc_end_file;
+ cout << ", define " << counts.mc_define;
+ cout << ", undef " << counts.mc_undef;
+ cout << ", ext " << counts.mc_extension;
+ cout << ", code-zero " << counts.mc_code_zero;
+ cout << ", unknown " << counts.mc_unknown << endl;
+
+ /* int type= maclist[count - 1].dmd_type; */
+ /* ASSERT: type is zero */
+
+ offset = maclist[count - 1].dmd_offset + 1;
+ dwarf_dealloc(dbg, maclist, DW_DLA_STRING);
+ ++group;
+ }
+ if (lres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_macro_details", lres, err);
+ }
+}
+
diff --git a/dwarfdump2/print_pubnames.cc b/dwarfdump2/print_pubnames.cc
new file mode 100644
index 0000000..18d2f9e
--- /dev/null
+++ b/dwarfdump2/print_pubnames.cc
@@ -0,0 +1,277 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include "globals.h"
+#include <vector>
+#include "naming.h"
+#include "dwconf.h"
+
+#include "print_sections.h"
+#include "print_frames.h"
+
+using std::string;
+using std::cout;
+using std::cerr;
+using std::endl;
+
+/* This unifies the code for some error checks to
+ avoid code duplication.
+*/
+void
+check_info_offset_sanity(const string & sec,
+ const string &field,
+ const string &global,
+ Dwarf_Unsigned offset, Dwarf_Unsigned maxoff)
+{
+ if (maxoff == 0) {
+ /* Lets make a heuristic check. */
+ if (offset > 0xffffffff) {
+ cout << "Warning: section " << sec << " " <<
+ field << " " << global;
+ cout << " offset" << IToHex(offset);
+ cout << " exceptionally large" << endl;
+ }
+ return;
+ }
+ if (offset >= maxoff) {
+ cout << "Warning: section " << sec << " " <<
+ field << " " << global;
+ cout << " offset "<< IToHex(offset);
+ cout << " larger than max of " << IToHex(maxoff) << endl;
+ }
+}
+
+
+
+/* Unified pubnames style output.
+ The error checking here against maxoff may be useless
+ (in that libdwarf may return an error if the offset is bad
+ and we will not get called here).
+ But we leave it in nonetheless as it looks sensible.
+ In at least one gigantic executable such offsets turned out wrong.
+*/
+void
+print_pubname_style_entry(Dwarf_Debug dbg,
+ const string & line_title,
+ const string & name,
+ Dwarf_Unsigned die_off,
+ Dwarf_Unsigned cu_off,
+ Dwarf_Unsigned global_cu_offset,
+ Dwarf_Unsigned maxoff)
+{
+ Dwarf_Die die = NULL;
+ Dwarf_Die cu_die = NULL;
+ Dwarf_Off die_CU_off = 0;
+
+ /* get die at die_off */
+ int dres = dwarf_offdie(dbg, die_off, &die, &err);
+ if (dres != DW_DLV_OK) {
+ string details = string(line_title) + string(" dwarf_offdie : "
+ "die offset does not reference valid DIE. ")
+ + IToHex(die_off) +
+ string(".");
+ print_error(dbg, details.c_str(), dres, err);
+ }
+ DieHolder(dbg,die);
+
+
+ /* get offset of die from its cu-header */
+ int ddres = dwarf_die_CU_offset(die, &die_CU_off, &err);
+ if (ddres != DW_DLV_OK) {
+ string details = string(line_title) + " cannot get CU die offset";
+ print_error(dbg, details.c_str(), ddres, err);
+ }
+
+ /* get die at offset cu_off */
+ int cudres = dwarf_offdie(dbg, cu_off, &cu_die, &err);
+ if (cudres != DW_DLV_OK) {
+ string details = string(line_title) + string(" dwarf_offdie: "
+ "die offset does not reference valid CU DIE. ")
+ + IToHex(cu_off) +
+ string(".");
+ dwarf_dealloc(dbg, die, DW_DLA_DIE);
+ print_error(dbg, details.c_str(), cudres, err);
+ }
+ if( display_offsets) {
+ /* Print 'name'at the end for better layout */
+ cout << line_title ;
+ cout << " die-in-sect " << IToHex0N(die_off,10);
+ cout << ", cu-in-sect " << IToHex0N(cu_off,10);
+ cout << ", die-in-cu " << IToHex0N(die_CU_off,10);
+ /* Following is absolute offset of the ** beginning of the
+ cu */
+ cout << ", cu-header-in-sect " <<
+ IToHex0N((die_off - die_CU_off),10);
+ }
+
+ if ((die_off - die_CU_off) != global_cu_offset) {
+ cout << line_title << " error: real cuhdr "<< global_cu_offset << endl;
+ exit(1);
+ }
+ if (display_offsets && verbose) {
+ cout << " cuhdr " << IToHex0N(global_cu_offset,10);
+ }
+ cout << " '" << name << "'" << endl;
+
+
+ dwarf_dealloc(dbg, die, DW_DLA_DIE);
+ dwarf_dealloc(dbg, cu_die, DW_DLA_DIE);
+
+ check_info_offset_sanity(line_title,
+ "die offset", name, die_off, maxoff);
+ check_info_offset_sanity(line_title,
+ "die cu offset", name, die_CU_off, maxoff);
+ check_info_offset_sanity(line_title,
+ "cu offset", name,
+ (die_off - die_CU_off), maxoff);
+}
+
+
+/* get all the data in .debug_pubnames */
+extern void
+print_pubnames(Dwarf_Debug dbg)
+{
+ Dwarf_Global *globbuf = NULL;
+ Dwarf_Signed count = 0;
+ Dwarf_Signed i = 0;
+ Dwarf_Off die_off = 0;
+ Dwarf_Off cu_off = 0;
+ char *name = 0;
+ /* Offset to previous CU */
+ Dwarf_Off prev_cu_off = error_message_data.elf_max_address;
+
+ error_message_data.current_section_id = DEBUG_PUBNAMES;
+ if (do_print_dwarf) {
+ cout << endl;
+ cout << ".debug_pubnames" << endl;
+ }
+ int res = dwarf_get_globals(dbg, &globbuf, &count, &err);
+ if (res == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_globals", res, err);
+ } else if (res == DW_DLV_NO_ENTRY) {
+ /* (err == 0 && count == DW_DLV_NOCOUNT) means there are no
+ pubnames. */
+ } else {
+ Dwarf_Unsigned maxoff = get_info_max_offset(dbg);
+
+ for (i = 0; i < count; i++) {
+ int nres;
+ int cures3;
+ Dwarf_Off global_cu_off = 0;
+
+ nres = dwarf_global_name_offsets(globbuf[i],
+ &name, &die_off, &cu_off, &err);
+ deal_with_name_offset_err(dbg, "pubnames dwarf_global_name_offsets",
+ name, die_off, nres, err);
+ cures3 = dwarf_global_cu_offset(globbuf[i],
+ &global_cu_off, &err);
+ if (cures3 != DW_DLV_OK) {
+ print_error(dbg, "pubnames dwarf_global_cu_offset",
+ cures3, err);
+ }
+ if (check_pubname_attr) {
+ Dwarf_Bool has_attr;
+ int ares;
+ int dres;
+ Dwarf_Die die;
+
+ /* We are processing a new set of pubnames
+ for a different CU; get the producer ID, at 'cu_off'
+ to see if we need to skip these pubnames */
+ if (cu_off != prev_cu_off) {
+ string producer_name;
+
+ /* Record offset for previous CU */
+ prev_cu_off = cu_off;
+
+ dres = dwarf_offdie(dbg, cu_off, &die, &err);
+ if (dres != DW_DLV_OK) {
+ print_error(dbg, "print pubnames: dwarf_offdie a", dres,err);
+ }
+
+ DieHolder hdie(dbg,die);
+ /* Get producer name for this CU and update compiler list */
+ get_producer_name(hdie,err,producer_name);
+ update_compiler_target(producer_name);
+ }
+
+ /* get die at die_off */
+ dres = dwarf_offdie(dbg, die_off, &die, &err);
+ if (dres != DW_DLV_OK) {
+ print_error(dbg, "print pubnames: dwarf_offdie b", dres, err);
+ }
+
+
+ ares =
+ dwarf_hasattr(die, DW_AT_external, &has_attr, &err);
+ if (ares == DW_DLV_ERROR) {
+ print_error(dbg, "hassattr on DW_AT_external", ares,
+ err);
+ }
+
+ /* Check for specific compiler */
+ if (checking_this_compiler()) {
+ DWARF_CHECK_COUNT(pubname_attr_result,1);
+ if (ares == DW_DLV_OK && has_attr) {
+ /* Should the value of flag be examined? */
+ } else {
+ DWARF_CHECK_ERROR2(pubname_attr_result,name,
+ "pubname does not have DW_AT_external");
+ }
+ }
+ dwarf_dealloc(dbg, die, DW_DLA_DIE);
+ }
+
+ /* Now print pubname, after the test */
+ if (do_print_dwarf || (record_dwarf_error && check_verbose_mode)) {
+ print_pubname_style_entry(dbg,
+ "global",
+ name, die_off, cu_off,
+ global_cu_off, maxoff);
+ record_dwarf_error = false; // Clear error condition.
+ }
+ }
+ dwarf_globals_dealloc(dbg, globbuf, count);
+ }
+} /* print_pubnames() */
+
diff --git a/dwarfdump2/print_ranges.cc b/dwarfdump2/print_ranges.cc
new file mode 100644
index 0000000..338cd31
--- /dev/null
+++ b/dwarfdump2/print_ranges.cc
@@ -0,0 +1,121 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include "globals.h"
+#include <vector>
+#include "naming.h"
+#include "dwconf.h"
+
+#include "print_sections.h"
+#include "print_frames.h"
+
+using std::string;
+using std::cout;
+using std::cerr;
+using std::endl;
+
+
+/* Get all the data in .debug_ranges
+ Nothing in the DWARF standard guarantees just reading the
+ bytes in the section really works, but it will probably
+ normally work fine.
+ Here we don't have a DW_AT_ranges offset to get us
+ started.
+
+ Because we do not know what DIE is involved, if the
+ object being printed has different address sizes
+ in different compilation units this will not work
+ properly: anything could happen.
+*/
+
+extern void
+print_ranges(Dwarf_Debug dbg)
+{
+ Dwarf_Unsigned off = 0;
+ int group_number = 0;
+ int wasdense = 0;
+
+ error_message_data.current_section_id = DEBUG_RANGES;
+ if (!do_print_dwarf) {
+ return;
+ }
+
+ cout << endl;
+ cout << ".debug_ranges" << endl;
+ /* Turn off dense, we do not want print_ranges_list_to_extra
+ to use dense form here. */
+ wasdense = dense;
+ dense = 0;
+ for(;;) {
+ Dwarf_Ranges *rangeset = 0;
+ Dwarf_Signed rangecount = 0;
+ Dwarf_Unsigned bytecount = 0;
+
+ // We do not know what DIE is involved, we use the
+ // older call here.
+ int rres = dwarf_get_ranges(dbg,off,&rangeset,
+ &rangecount,&bytecount,&err);
+ if(rres == DW_DLV_OK) {
+ cout <<" Ranges group " << group_number << ":" << endl;
+ string exprstring =
+ print_ranges_list_to_extra(dbg,off,
+ rangeset,rangecount,bytecount);
+ dwarf_ranges_dealloc(dbg,rangeset,rangecount);
+ cout << exprstring;
+ ++group_number;
+ } else if (rres == DW_DLV_NO_ENTRY) {
+ cout << "End of .debug_ranges." << endl;
+ break;
+ } else {
+ /* ERROR, which does not quite mean a real error,
+ as we might just be misaligned reading things without
+ a DW_AT_ranges offset.*/
+ cout << "End of .debug_ranges.." << endl;
+ break;
+ }
+ off += bytecount;
+ }
+ dense = wasdense;
+}
+
+
diff --git a/dwarfdump2/print_reloc.cc b/dwarfdump2/print_reloc.cc
new file mode 100644
index 0000000..c95d3ce
--- /dev/null
+++ b/dwarfdump2/print_reloc.cc
@@ -0,0 +1,1146 @@
+/*
+ Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_reloc.c,v 1.11 2005/08/04 05:09:37 davea Exp $ */
+
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+
+
+
+#include "globals.h"
+using std::string;
+using std::cout;
+using std::cerr;
+using std::endl;
+
+#define DW_SECTION_REL_DEBUG_NUM 9 /* Number of sections */
+/* .debug_abbrev should never have a relocation applied to it as it
+ never refers to another section! (other sections refer to
+ .debug_abbrev) */
+
+#define DW_SECTNAME_RELA_DEBUG ".rela.debug_"
+#define DW_SECTNAME_RELA_DEBUG_INFO ".rela.debug_info"
+#define DW_SECTNAME_RELA_DEBUG_LINE ".rela.debug_line"
+#define DW_SECTNAME_RELA_DEBUG_PUBNAMES ".rela.debug_pubnames"
+#define DW_SECTNAME_RELA_DEBUG_ABBREV ".rela.debug_abbrev"
+#define DW_SECTNAME_RELA_DEBUG_ARANGES ".rela.debug_aranges"
+#define DW_SECTNAME_RELA_DEBUG_FRAME ".rela.debug_frame"
+#define DW_SECTNAME_RELA_DEBUG_LOC ".rela.debug_loc"
+#define DW_SECTNAME_RELA_DEBUG_RANGES ".rela.debug_ranges"
+#define DW_SECTNAME_RELA_DEBUG_TYPES ".rela.debug_types"
+
+#define DW_SECTNAME_REL_DEBUG ".rel.debug_"
+#define DW_SECTNAME_REL_DEBUG_INFO ".rel.debug_info"
+#define DW_SECTNAME_REL_DEBUG_LINE ".rel.debug_line"
+#define DW_SECTNAME_REL_DEBUG_PUBNAMES ".rel.debug_pubnames"
+#define DW_SECTNAME_REL_DEBUG_ABBREV ".rel.debug_abbrev"
+#define DW_SECTNAME_REL_DEBUG_ARANGES ".rel.debug_aranges"
+#define DW_SECTNAME_REL_DEBUG_FRAME ".rel.debug_frame"
+#define DW_SECTNAME_REL_DEBUG_LOC ".rel.debug_loc"
+#define DW_SECTNAME_REL_DEBUG_RANGES ".rel.debug_ranges"
+#define DW_SECTNAME_REL_DEBUG_TYPES ".rel.debug_types"
+
+
+#define STRING_FOR_DUPLICATE " duplicate"
+#define STRING_FOR_NULL " null"
+
+static const char *sectnames[] = {
+ DW_SECTNAME_REL_DEBUG_INFO,
+ DW_SECTNAME_REL_DEBUG_LINE,
+ DW_SECTNAME_REL_DEBUG_PUBNAMES,
+ DW_SECTNAME_REL_DEBUG_ABBREV,
+ DW_SECTNAME_REL_DEBUG_ARANGES,
+ DW_SECTNAME_REL_DEBUG_FRAME,
+ DW_SECTNAME_REL_DEBUG_LOC,
+ DW_SECTNAME_REL_DEBUG_RANGES,
+ DW_SECTNAME_REL_DEBUG_TYPES,
+};
+static const char *sectnamesa[] = {
+ DW_SECTNAME_RELA_DEBUG_INFO,
+ DW_SECTNAME_RELA_DEBUG_LINE,
+ DW_SECTNAME_RELA_DEBUG_PUBNAMES,
+ DW_SECTNAME_RELA_DEBUG_ABBREV,
+ DW_SECTNAME_RELA_DEBUG_ARANGES,
+ DW_SECTNAME_RELA_DEBUG_FRAME,
+ DW_SECTNAME_RELA_DEBUG_LOC,
+ DW_SECTNAME_RELA_DEBUG_RANGES,
+ DW_SECTNAME_RELA_DEBUG_TYPES,
+};
+
+static const char *error_msg_duplicate[] = {
+ DW_SECTNAME_REL_DEBUG_INFO STRING_FOR_DUPLICATE,
+ DW_SECTNAME_REL_DEBUG_LINE STRING_FOR_DUPLICATE,
+ DW_SECTNAME_REL_DEBUG_PUBNAMES STRING_FOR_DUPLICATE,
+ DW_SECTNAME_REL_DEBUG_ABBREV STRING_FOR_DUPLICATE,
+ DW_SECTNAME_REL_DEBUG_ARANGES STRING_FOR_DUPLICATE,
+ DW_SECTNAME_REL_DEBUG_FRAME STRING_FOR_DUPLICATE,
+ DW_SECTNAME_REL_DEBUG_LOC STRING_FOR_DUPLICATE,
+ DW_SECTNAME_REL_DEBUG_RANGES STRING_FOR_DUPLICATE,
+ DW_SECTNAME_REL_DEBUG_TYPES STRING_FOR_DUPLICATE,
+};
+
+static const char *error_msg_null[] = {
+ DW_SECTNAME_REL_DEBUG_INFO STRING_FOR_NULL,
+ DW_SECTNAME_REL_DEBUG_LINE STRING_FOR_NULL,
+ DW_SECTNAME_REL_DEBUG_PUBNAMES STRING_FOR_NULL,
+ DW_SECTNAME_REL_DEBUG_ABBREV STRING_FOR_NULL,
+ DW_SECTNAME_REL_DEBUG_ARANGES STRING_FOR_NULL,
+ DW_SECTNAME_REL_DEBUG_FRAME STRING_FOR_NULL,
+ DW_SECTNAME_REL_DEBUG_LOC STRING_FOR_NULL,
+ DW_SECTNAME_REL_DEBUG_RANGES STRING_FOR_NULL,
+ DW_SECTNAME_REL_DEBUG_TYPES STRING_FOR_NULL,
+};
+
+/* Include Section type, to be able to deal with all the
+ Elf32_Rel, Elf32_Rela, Elf64_Rel, Elf64_Rela relocation types */
+#define SECT_DATA_SET(x,t,n) { \
+ if (sect_data[(x)].buf != NULL) { \
+ print_error(dbg, error_msg_duplicate[(x)],DW_DLV_OK, err); \
+ } \
+ if ((data = elf_getdata(scn, 0)) == NULL || data->d_size == 0) { \
+ print_error(dbg, error_msg_null[(x)],DW_DLV_OK, err); \
+ } \
+ sect_data[(x)].buf = reinterpret_cast<Dwarf_Small *>(data -> d_buf); \
+ sect_data[(x)].size = data -> d_size; \
+ sect_data[(x)].type = t; \
+ sect_data[(x)].name = n; \
+ }
+
+
+/* PowerPC relocations defined by the ABIs */
+static const char *reloc_type_names_PPC[] = {
+ "R_PPC_NONE", /* 00 */
+ "R_PPC_ADDR32", /* 01 */
+ "R_PPC_ADDR24", /* 02 */
+ "R_PPC_ADDR16", /* 03 */
+ "R_PPC_ADDR16_LO", /* 04 */
+ "R_PPC_ADDR16_HI", /* 05 */
+ "R_PPC_ADDR16_HA", /* 06 */
+ "R_PPC_ADDR14", /* 07 */
+ "R_PPC_ADDR14_BRTAKEN", /* 08 */
+ "R_PPC_ADDR14_BRNTAKEN", /* 09 */
+ "R_PPC_REL24", /* 10 */
+ "R_PPC_REL14", /* 11 */
+ "R_PPC_REL14_BRTAKEN", /* 12 */
+ "R_PPC_REL14_BRNTAKEN", /* 13 */
+ "R_PPC_GOT16", /* 14 */
+ "R_PPC_GOT16_LO", /* 15 */
+ "R_PPC_GOT16_HI", /* 16 */
+ "R_PPC_GOT16_HA", /* 17 */
+ "R_PPC_PLTREL24", /* 18 */
+ "R_PPC_COPY", /* 19 */
+ "R_PPC_GLOB_DAT", /* 20 */
+ "R_PPC_JMP_SLOT", /* 21 */
+ "R_PPC_RELATIVE", /* 22 */
+ "R_PPC_LOCAL24PC", /* 23 */
+ "R_PPC_UADDR32", /* 24 */
+ "R_PPC_UADDR16", /* 25 */
+ "R_PPC_REL32", /* 26 */
+ "R_PPC_PLT32", /* 27 */
+ "R_PPC_PLTREL32", /* 28 */
+ "R_PPC_PLT16_LO", /* 29 */
+ "R_PPC_PLT16_HI", /* 30 */
+ "R_PPC_PLT16_HA", /* 31 */
+ "R_PPC_SDAREL16", /* 32 */
+ "R_PPC_SECTOFF", /* 33 */
+ "R_PPC_SECTOFF_LO", /* 34 */
+ "R_PPC_SECTOFF_HI", /* 35 */
+ "R_PPC_SECTOFF_HA", /* 36 */
+ "R_PPC_37", /* 37 */
+ "R_PPC_38", /* 38 */
+ "R_PPC_39", /* 39 */
+ "R_PPC_40", /* 40 */
+ "R_PPC_41", /* 41 */
+ "R_PPC_42", /* 42 */
+ "R_PPC_43", /* 43 */
+ "R_PPC_44", /* 44 */
+ "R_PPC_45", /* 45 */
+ "R_PPC_46", /* 46 */
+ "R_PPC_47", /* 47 */
+ "R_PPC_48", /* 48 */
+ "R_PPC_49", /* 49 */
+ "R_PPC_50", /* 50 */
+ "R_PPC_51", /* 51 */
+ "R_PPC_52", /* 52 */
+ "R_PPC_53", /* 53 */
+ "R_PPC_54", /* 54 */
+ "R_PPC_55", /* 55 */
+ "R_PPC_56", /* 56 */
+ "R_PPC_57", /* 57 */
+ "R_PPC_58", /* 58 */
+ "R_PPC_59", /* 59 */
+ "R_PPC_60", /* 60 */
+ "R_PPC_61", /* 61 */
+ "R_PPC_62", /* 62 */
+ "R_PPC_63", /* 63 */
+ "R_PPC_64", /* 64 */
+ "R_PPC_65", /* 65 */
+ "R_PPC_66", /* 66 */
+ "R_PPC_TLS", /* 67 */
+ "R_PPC_DTPMOD32", /* 68 */
+ "R_PPC_TPREL16", /* 69 */
+ "R_PPC_TPREL16_LO", /* 70 */
+ "R_PPC_TPREL16_HI", /* 71 */
+ "R_PPC_TPREL16_HA", /* 72 */
+ "R_PPC_TPREL32", /* 73 */
+ "R_PPC_DTPREL16", /* 74 */
+ "R_PPC_DTPREL16_LO", /* 75 */
+ "R_PPC_DTPREL16_HI", /* 76 */
+ "R_PPC_DTPREL16_HA", /* 77 */
+ "R_PPC_DTPREL64", /* 78 */
+ "R_PPC_GOT_TLSGD16", /* 79 */
+ "R_PPC_GOT_TLSGD16_LO", /* 80 */
+ "R_PPC_GOT_TLSGD16_HI", /* 81 */
+ "R_PPC_GOT_TLSGD16_HA", /* 82 */
+ "R_PPC_GOT_TLSLD16", /* 83 */
+ "R_PPC_GOT_TLSLD16_LO", /* 84 */
+ "R_PPC_GOT_TLSLD16_HI", /* 85 */
+ "R_PPC_GOT_TLSLD16_HA", /* 86 */
+ "R_PPC_GOT_TPREL16_DS", /* 87 */
+ "R_PPC_GOT_TPREL16_LO", /* 88 */
+ "R_PPC_GOT_TPREL16_HI", /* 89 */
+ "R_PPC_GOT_TPREL16_HA", /* 90 */
+ "R_PPC_GOT_DTPREL16", /* 91 */
+ "R_PPC_GOT_DTPREL16_LO", /* 92 */
+ "R_PPC_GOT_DTPREL16_HI", /* 93 */
+ "R_PPC_GOT_DTPREL16_HA", /* 94 */
+};
+
+/* PowerPC64 relocations defined by the ABIs */
+static const char *reloc_type_names_PPC64[] = {
+ "R_PPC64_NONE", /* 00 */
+ "R_PPC64_ADDR32", /* 01 */
+ "R_PPC64_ADDR24", /* 02 */
+ "R_PPC64_ADDR16", /* 03 */
+ "R_PPC64_ADDR16_LO", /* 04 */
+ "R_PPC64_ADDR16_HI", /* 05 */
+ "R_PPC64_ADDR16_HA", /* 06 */
+ "R_PPC64_ADDR14", /* 07 */
+ "R_PPC64_ADDR14_BRTAKEN", /* 08 */
+ "R_PPC64_ADDR14_BRNTAKEN", /* 09 */
+ "R_PPC64_REL24", /* 10 */
+ "R_PPC64_REL14", /* 11 */
+ "R_PPC64_REL14_BRTAKEN", /* 12 */
+ "R_PPC64_REL14_BRNTAKEN", /* 13 */
+ "R_PPC64_GOT16", /* 14 */
+ "R_PPC64_GOT16_LO", /* 15 */
+ "R_PPC64_GOT16_HI", /* 16 */
+ "R_PPC64_GOT16_HA", /* 17 */
+ "R_PPC64_PLTREL24", /* 18 */
+ "R_PPC64_COPY", /* 19 */
+ "R_PPC64_GLOB_DAT", /* 20 */
+ "R_PPC64_JMP_SLOT", /* 21 */
+ "R_PPC64_RELATIVE", /* 22 */
+ "R_PPC64_LOCAL24PC", /* 23 */
+ "R_PPC64_UADDR32", /* 24 */
+ "R_PPC64_UADDR16", /* 25 */
+ "R_PPC64_REL32", /* 26 */
+ "R_PPC64_PLT32", /* 27 */
+ "R_PPC64_PLTREL32", /* 28 */
+ "R_PPC64_PLT16_LO", /* 29 */
+ "R_PPC64_PLT16_HI", /* 30 */
+ "R_PPC64_PLT16_HA", /* 31 */
+ "R_PPC64_SDAREL16", /* 32 */
+ "R_PPC64_SECTOFF", /* 33 */
+ "R_PPC64_SECTOFF_LO", /* 34 */
+ "R_PPC64_SECTOFF_HI", /* 35 */
+ "R_PPC64_SECTOFF_HA", /* 36 */
+ "R_PPC64_REL30", /* 37 */
+ "R_PPC64_ADDR64", /* 38 */
+ "R_PPC64_ADDR16_HIGHER", /* 39 */
+ "R_PPC64_ADDR16_HIGHERA", /* 40 */
+ "R_PPC64_ADDR16_HIGHEST", /* 41 */
+ "R_PPC64_ADDR16_HIGHESTA", /* 42 */
+ "R_PPC64_UADDR64", /* 43 */
+ "R_PPC64_REL64", /* 44 */
+ "R_PPC64_PLT64", /* 45 */
+ "R_PPC64_PLTREL64", /* 46 */
+ "R_PPC64_TOC16", /* 47 */
+ "R_PPC64_TOC16_LO", /* 48 */
+ "R_PPC64_TOC16_HI", /* 49 */
+ "R_PPC64_TOC16_HA", /* 50 */
+ "R_PPC64_TOC", /* 51 */
+ "R_PPC64_PLTGOT16", /* 52 */
+ "R_PPC64_PLTGOT16_LO", /* 53 */
+ "R_PPC64_PLTGOT16_HI", /* 54 */
+ "R_PPC64_PLTGOT16_HA", /* 55 */
+ "R_PPC64_ADDR16_DS", /* 56 */
+ "R_PPC64_ADDR16_LO_DS", /* 57 */
+ "R_PPC64_GOT16_DS", /* 58 */
+ "R_PPC64_GOT16_LO_DS", /* 59 */
+ "R_PPC64_PLT16_LO_DS", /* 60 */
+ "R_PPC64_SECTOFF_DS", /* 61 */
+ "R_PPC64_SECTOFF_LO_DS", /* 62 */
+ "R_PPC64_TOC16_DS", /* 63 */
+ "R_PPC64_TOC16_LO_DS", /* 64 */
+ "R_PPC64_PLTGOT16_DS", /* 65 */
+ "R_PPC64_PLTGOT16_LO_DS", /* 66 */
+ "R_PPC64_TLS", /* 67 */
+ "R_PPC64_DTPMOD32", /* 68 */
+ "R_PPC64_TPREL16", /* 69 */
+ "R_PPC64_TPREL16_LO", /* 70 */
+ "R_PPC64_TPREL16_HI", /* 71 */
+ "R_PPC64_TPREL16_HA", /* 72 */
+ "R_PPC64_TPREL32", /* 73 */
+ "R_PPC64_DTPREL16", /* 74 */
+ "R_PPC64_DTPREL16_LO", /* 75 */
+ "R_PPC64_DTPREL16_HI", /* 76 */
+ "R_PPC64_DTPREL16_HA", /* 77 */
+ "R_PPC64_DTPREL64", /* 78 */
+ "R_PPC64_GOT_TLSGD16", /* 79 */
+ "R_PPC64_GOT_TLSGD16_LO", /* 80 */
+ "R_PPC64_GOT_TLSGD16_HI", /* 81 */
+ "R_PPC64_GOT_TLSGD16_HA", /* 82 */
+ "R_PPC64_GOT_TLSLD16", /* 83 */
+ "R_PPC64_GOT_TLSLD16_LO", /* 84 */
+ "R_PPC64_GOT_TLSLD16_HI", /* 85 */
+ "R_PPC64_GOT_TLSLD16_HA", /* 86 */
+ "R_PPC64_GOT_TPREL16_DS", /* 87 */
+ "R_PPC64_GOT_TPREL16_LO", /* 88 */
+ "R_PPC64_GOT_TPREL16_HI", /* 89 */
+ "R_PPC64_GOT_TPREL16_HA", /* 90 */
+ "R_PPC64_GOT_DTPREL16", /* 91 */
+ "R_PPC64_GOT_DTPREL16_LO", /* 92 */
+ "R_PPC64_GOT_DTPREL16_HI", /* 93 */
+ "R_PPC64_GOT_DTPREL16_HA", /* 94 */
+ "R_PPC64_TPREL16_DS", /* 95 */
+ "R_PPC64_TPREL16_LO_DS", /* 96 */
+ "R_PPC64_TPREL16_HIGHER", /* 97 */
+ "R_PPC64_TPREL16_HIGHERA", /* 98 */
+ "R_PPC64_TPREL16_HIGHEST", /* 99 */
+ "R_PPC64_TPREL16_HIGHESTA", /* 100 */
+ "R_PPC64_DTPREL16_DS", /* 101 */
+ "R_PPC64_DTPREL16_LO_DS", /* 102 */
+ "R_PPC64_DTPREL16_HIGHER", /* 103 */
+ "R_PPC64_DTPREL16_HIGHERA", /* 104 */
+ "R_PPC64_DTPREL16_HIGHEST", /* 105 */
+ "R_PPC64_DTPREL16_HIGHESTA", /* 106 */
+ "R_PPC64_TOC32", /* 107 */
+ "R_PPC64_DTPMOD32", /* 108 */
+ "R_PPC64_TPREL32", /* 109 */
+ "R_PPC64_DTPREL32", /* 110 */
+};
+
+/* Relocation types for MIPS */
+static const char *reloc_type_names_MIPS[] = {
+ "R_MIPS_NONE", "R_MIPS_16", "R_MIPS_32", "R_MIPS_REL32",
+ "R_MIPS_26", "R_MIPS_HI16", "R_MIPS_LO16", "R_MIPS_GPREL16",
+ "R_MIPS_LITERAL", "R_MIPS_GOT16", "R_MIPS_PC16", "R_MIPS_CALL16",
+ "R_MIPS_GPREL32", /* 12 */
+ "reloc type 13?", "reloc type 14?", "reloc type 15?",
+ "R_MIPS_SHIFT5", /* 16 */
+ "R_MIPS_SHIFT6", /* 17 */
+ "R_MIPS_64", /* 18 */
+ "R_MIPS_GOT_DISP", /* 19 */
+ "R_MIPS_GOT_PAGE", /* 20 */
+ "R_MIPS_GOT_OFST", /* 21 */
+ "R_MIPS_GOT_HI16", /* 22 */
+ "R_MIPS_GOT_LO16", /* 23 */
+ "R_MIPS_SUB", /* 24 */
+ "R_MIPS_INSERT_A", /* 25 */
+ "R_MIPS_INSERT_B", /* 26 */
+ "R_MIPS_DELETE", /* 27 */
+ "R_MIPS_HIGHER", /* 28 */
+ "R_MIPS_HIGHEST", /* 29 */
+ "R_MIPS_CALL_HI16", /* 30 */
+ "R_MIPS_CALL_LO16", /* 31 */
+ "R_MIPS_SCN_DISP", /* 32 */
+ "R_MIPS_REL16", /* 33 */
+ "R_MIPS_ADD_IMMEDIATE", /* 34 */
+};
+
+/* ARM relocations defined by the ABIs */
+static const char *reloc_type_names_ARM[] = {
+ "R_ARM_NONE", /* 00 */
+ "R_ARM_PC24", /* 01 */
+ "R_ARM_ABS32", /* 02 */
+ "R_ARM_REL32", /* 03 */
+ "R_ARM_LDR_PC_G0", /* 04 */
+ "R_ARM_ABS16", /* 05 */
+ "R_ARM_ABS12", /* 06 */
+ "R_ARM_THM_ABS5", /* 07 */
+ "R_ARM_ABS8", /* 08 */
+ "R_ARM_SBREL32", /* 09 */
+ "R_ARM_THM_CALL", /* 10 */
+ "R_ARM_THM_PC8", /* 11 */
+ "R_ARM_BREL_ADJ", /* 12 */
+ "R_ARM_TLS_DESC", /* 13 */
+ "R_ARM_THM_SWI8", /* 14 */
+ "R_ARM_XPC25", /* 15 */
+ "R_ARM_THM_XPC22", /* 16 */
+ "R_ARM_TLS_DTPMOD32", /* 17 */
+ "R_ARM_TLS_DTPOFF32", /* 18 */
+ "R_ARM_TLS_TPOFF32", /* 19 */
+ "R_ARM_COPY", /* 20 */
+ "R_ARM_GLOB_DAT", /* 21 */
+ "R_ARM_JUMP_SLOT", /* 22 */
+ "R_ARM_RELATIVE", /* 23 */
+ "R_ARM_GOTOFF32", /* 24 */
+ "R_ARM_BASE_PREL", /* 25 */
+ "R_ARM_GOT_BREL", /* 26 */
+ "R_ARM_PLT32", /* 27 */
+ "R_ARM_CALL", /* 28 */
+ "R_ARM_JUMP24", /* 29 */
+ "R_ARM_THM_JUMP24", /* 30 */
+ "R_ARM_BASE_ABS", /* 31 */
+ "R_ARM_ALU_PCREL_7_0", /* 32 */
+ "R_ARM_ALU_PCREL_15_8", /* 33 */
+ "R_ARM_ALU_PCREL_23_15", /* 34 */
+ "R_ARM_LDR_SBREL_11_0_NC", /* 35 */
+ "R_ARM_ALU_SBREL_19_12_NC", /* 36 */
+ "R_ARM_ALU_SBREL_27_20_CK", /* 37 */
+ "R_ARM_TARGET1", /* 38 */
+ "R_ARM_SBREL31", /* 39 */
+ "R_ARM_V4BX", /* 40 */
+ "R_ARM_TARGET2", /* 41 */
+ "R_ARM_PREL31", /* 42 */
+ "R_ARM_MOVW_ABS_NC", /* 43 */
+ "R_ARM_MOVT_ABS", /* 44 */
+ "R_ARM_MOVW_PREL_NC", /* 45 */
+ "R_ARM_MOVT_PREL", /* 46 */
+ "R_ARM_THM_MOVW_ABS_NC", /* 47 */
+ "R_ARM_THM_MOVT_ABS", /* 48 */
+ "R_ARM_THM_MOVW_PREL_NC", /* 49 */
+ "R_ARM_THM_MOVT_PREL", /* 50 */
+ "R_ARM_THM_JUMP19", /* 51 */
+ "R_ARM_THM_JUMP6", /* 52 */
+ "R_ARM_THM_ALU_PREL_11_0", /* 53 */
+ "R_ARM_THM_PC12", /* 54 */
+ "R_ARM_ABS32_NOI", /* 55 */
+ "R_ARM_REL32_NOI", /* 56 */
+ "R_ARM_ALU_PC_G0_NC", /* 57 */
+ "R_ARM_ALU_PC_G0", /* 58 */
+ "R_ARM_ALU_PC_G1_NC", /* 59 */
+ "R_ARM_ALU_PC_G1", /* 60 */
+ "R_ARM_ALU_PC_G2", /* 61 */
+ "R_ARM_LDR_PC_G1", /* 62 */
+ "R_ARM_LDR_PC_G2", /* 63 */
+ "R_ARM_LDRS_PC_G0", /* 64 */
+ "R_ARM_LDRS_PC_G1", /* 65 */
+ "R_ARM_LDRS_PC_G2", /* 66 */
+ "R_ARM_LDC_PC_G0", /* 67 */
+ "R_ARM_LDC_PC_G1", /* 68 */
+ "R_ARM_LDC_PC_G2", /* 69 */
+ "R_ARM_ALU_SB_G0_NC", /* 70 */
+ "R_ARM_ALU_SB_G0", /* 71 */
+ "R_ARM_ALU_SB_G1_NC", /* 72 */
+ "R_ARM_ALU_SB_G1", /* 73 */
+ "R_ARM_ALU_SB_G2", /* 74 */
+ "R_ARM_LDR_SB_G0", /* 75 */
+ "R_ARM_LDR_SB_G1", /* 76 */
+ "R_ARM_LDR_SB_G2", /* 77 */
+ "R_ARM_LDRS_SB_G0", /* 78 */
+ "R_ARM_LDRS_SB_G1", /* 79 */
+ "R_ARM_LDRS_SB_G2", /* 80 */
+ "R_ARM_LDC_SB_G0", /* 81 */
+ "R_ARM_LDC_SB_G1", /* 82 */
+ "R_ARM_LDC_SB_G2", /* 83 */
+ "R_ARM_MOVW_BREL_NC", /* 84 */
+ "R_ARM_MOVT_BREL", /* 85 */
+ "R_ARM_MOVW_BREL", /* 86 */
+ "R_ARM_THM_MOVW_BREL_NC", /* 87 */
+ "R_ARM_THM_MOVT_BREL", /* 88 */
+ "R_ARM_THM_MOVW_BREL", /* 89 */
+ "R_ARM_TLS_GOTDESC", /* 90 */
+ "R_ARM_TLS_CALL", /* 91 */
+ "R_ARM_TLS_DESCSEQ", /* 92 */
+ "R_ARM_THM_TLS_CALL", /* 93 */
+ "R_ARM_PLT32_ABS", /* 94 */
+ "R_ARM_GOT_ABS", /* 95 */
+ "R_ARM_GOT_PREL", /* 96 */
+ "R_ARM_GOT_BREL12", /* 97 */
+ "R_ARM_GOTOFF12", /* 98 */
+ "R_ARM_GOTRELAX", /* 99 */
+ "R_ARM_GNU_VTENTRY", /* 100 */
+ "R_ARM_GNU_VTINHERIT", /* 101 */
+ "R_ARM_THM_JUMP11", /* 102 */
+ "R_ARM_THM_JUMP8", /* 103 */
+ "R_ARM_TLS_GD32", /* 104 */
+ "R_ARM_TLS_LDM32", /* 105 */
+ "R_ARM_TLS_LDO32", /* 106 */
+ "R_ARM_TLS_IE32", /* 107 */
+ "R_ARM_TLS_LE32", /* 108 */
+ "R_ARM_TLS_LDO12", /* 109 */
+ "R_ARM_TLS_LE12", /* 110 */
+ "R_ARM_TLS_IE12GP", /* 111 */
+ "R_ARM_TLS_MOVT_TPOFF32", /* 112 */ /* "R_ARM_PRIVATE_0" */
+ "R_ARM_TLS_MOVW_TPOFF32", /* 113 */ /* "R_ARM_PRIVATE_1" */
+ "R_ARM_THM_TLS_MOVT_TPOFF32", /* 114 */ /* "R_ARM_PRIVATE_2" */
+ "R_ARM_THM_TLS_MOVT_TPOFF32", /* 115 */ /* "R_ARM_PRIVATE_3" */
+ "R_ARM_PRIVATE_4", /* 116 */
+ "R_ARM_PRIVATE_5", /* 117 */
+ "R_ARM_PRIVATE_6", /* 118 */
+ "R_ARM_PRIVATE_7", /* 119 */
+ "R_ARM_PRIVATE_8", /* 120 */
+ "R_ARM_PRIVATE_9", /* 121 */
+ "R_ARM_PRIVATE_10", /* 122 */
+ "R_ARM_PRIVATE_11", /* 123 */
+ "R_ARM_PRIVATE_12", /* 124 */
+ "R_ARM_PRIVATE_13", /* 125 */
+ "R_ARM_PRIVATE_14", /* 126 */
+ "R_ARM_PRIVATE_15", /* 127 */
+ "R_ARM_ME_TOO", /* 128 */
+ "R_ARM_THM_TLS_DESCSEQ16", /* 129 */
+ "R_ARM_THM_TLS_DESCSEQ32", /* 130 */
+};
+
+/* Record the relocation table name information */
+static const char **reloc_type_names = NULL;
+static Dwarf_Small number_of_reloc_type_names = 0;
+
+/* Set the relocation names based on the machine type */
+static void
+set_relocation_table_names(Dwarf_Small machine_type)
+{
+ switch (machine_type) {
+ case EM_MIPS:
+ reloc_type_names = reloc_type_names_MIPS;
+ number_of_reloc_type_names =
+ sizeof(reloc_type_names_MIPS) / sizeof(char *);
+ break;
+ case EM_PPC:
+ reloc_type_names = reloc_type_names_PPC;
+ number_of_reloc_type_names =
+ sizeof(reloc_type_names_PPC) / sizeof(char *);
+ break;
+ case EM_PPC64:
+ reloc_type_names = reloc_type_names_PPC64;
+ number_of_reloc_type_names =
+ sizeof(reloc_type_names_PPC64) / sizeof(char *);
+ break;
+ case EM_ARM:
+ reloc_type_names = reloc_type_names_ARM;
+ number_of_reloc_type_names =
+ sizeof(reloc_type_names_ARM) / sizeof(char *);
+ break;
+ default:
+ /* We don't have others covered. */
+ reloc_type_names = 0;
+ number_of_reloc_type_names = 0;
+ break;
+ }
+}
+
+
+
+/* return valid reloc type names.
+ if buf is used, it is static, so beware it
+ will be overrwritten by the next call.
+*/
+static string
+get_reloc_type_names(int index)
+{
+ string retval;
+
+ if (index < 0 || index >= number_of_reloc_type_names) {
+ retval = "reloc type ";
+ retval.append(IToDec(index));
+ retval.append(" unknown");
+ } else {
+ retval = reloc_type_names[index];
+ }
+ return retval;
+}
+
+#ifndef HAVE_ELF64_GETEHDR
+#define Elf64_Addr long
+#define Elf64_Word unsigned long
+#define Elf64_Xword unsigned long
+#define Elf64_Sym long
+#endif
+
+static struct {
+ Dwarf_Small *buf;
+ Dwarf_Unsigned size;
+ Dwarf_Bool display; // Display reloc if TRUE
+ const char *name; // Section name.
+ Elf64_Xword type; // To cover 32 and 64 records types.
+} sect_data[DW_SECTION_REL_DEBUG_NUM];
+
+
+typedef size_t indx_type;
+
+typedef struct {
+ indx_type indx;
+ char *name;
+ Elf32_Addr value;
+ Elf32_Word size;
+ int type;
+ int bind;
+ unsigned char other;
+ Elf32_Half shndx;
+} SYM;
+
+
+typedef struct {
+ indx_type indx;
+ char *name;
+ Elf64_Addr value;
+ Elf64_Xword size;
+ int type;
+ int bind;
+ unsigned char other;
+ unsigned short shndx;
+} SYM64;
+
+static void print_reloc_information_64(int section_no,
+ Dwarf_Small * buf,
+ Dwarf_Unsigned size,
+ Elf64_Xword type,
+ const char **scn_names, int scn_names_cnt);
+static void print_reloc_information_32(int section_no,
+ Dwarf_Small * buf,
+ Dwarf_Unsigned size,
+ Elf64_Xword type,
+ const char **scn_names, int scn_names_cnt);
+static SYM *readsyms(Elf32_Sym * data, size_t num, Elf * elf,
+ Elf32_Word link);
+static SYM64 *read_64_syms(Elf64_Sym * data, size_t num, Elf * elf,
+ Elf64_Word link);
+static void *get_scndata(Elf_Scn * fd_scn, size_t * scn_size);
+static void print_relocinfo_64(Dwarf_Debug dbg, Elf * elf);
+static void print_relocinfo_32(Dwarf_Debug dbg, Elf * elf);
+
+static SYM *sym_data;
+static SYM64 *sym_data_64;
+static unsigned long sym_data_entry_count;
+static unsigned long sym_data_64_entry_count;
+
+
+typedef struct {
+ indx_type index;
+ const char *name_rel; /* .rel.debug_* names */
+ const char *name_rela; /* .rela.debug_* names */
+} REL_INFO;
+
+
+/* If the incoming scn_name is known, record the name
+ in our reloc section names table.
+ For a given (debug) section there can be a .rel or a .rela,
+ not both.
+ The name-to-index in this table is fixed, invariant.
+ It has to match other tables like
+*/
+static bool
+get_reloc_section(Dwarf_Debug dbg,
+ Elf_Scn *scn,
+ const char *scn_name,
+ Elf64_Word sh_type)
+{
+ static REL_INFO rel_info[DW_SECTION_REL_DEBUG_NUM] = {
+ {/*0*/ DW_SECTION_REL_DEBUG_INFO,
+ DW_SECTNAME_REL_DEBUG_INFO,
+ DW_SECTNAME_RELA_DEBUG_INFO},
+
+ {/*1*/ DW_SECTION_REL_DEBUG_LINE,
+ DW_SECTNAME_REL_DEBUG_LINE,
+ DW_SECTNAME_RELA_DEBUG_LINE},
+
+ {/*2*/ DW_SECTION_REL_DEBUG_PUBNAMES,
+ DW_SECTNAME_REL_DEBUG_PUBNAMES,
+ DW_SECTNAME_RELA_DEBUG_PUBNAMES},
+
+ {/*3*/ DW_SECTION_REL_DEBUG_ABBREV,
+ DW_SECTNAME_REL_DEBUG_ABBREV,
+ DW_SECTNAME_RELA_DEBUG_ABBREV},
+
+ {/*4*/ DW_SECTION_REL_DEBUG_ARANGES,
+ DW_SECTNAME_REL_DEBUG_ARANGES,
+ DW_SECTNAME_RELA_DEBUG_ARANGES},
+
+ {/*5*/ DW_SECTION_REL_DEBUG_FRAME,
+ DW_SECTNAME_REL_DEBUG_FRAME,
+ DW_SECTNAME_RELA_DEBUG_FRAME},
+
+ {/*6*/ DW_SECTION_REL_DEBUG_LOC,
+ DW_SECTNAME_REL_DEBUG_LOC,
+ DW_SECTNAME_RELA_DEBUG_LOC},
+
+ {/*7*/ DW_SECTION_REL_DEBUG_RANGES,
+ DW_SECTNAME_REL_DEBUG_RANGES,
+ DW_SECTNAME_RELA_DEBUG_RANGES},
+
+ {/*8*/ DW_SECTION_REL_DEBUG_TYPES,
+ DW_SECTNAME_REL_DEBUG_TYPES,
+ DW_SECTNAME_RELA_DEBUG_TYPES},
+ };
+
+ Elf_Data *data;
+ int index;
+ for (index = 0; index < DW_SECTION_REL_DEBUG_NUM; ++index) {
+ const char *n = rel_info[index].name_rel;
+ const char *na = rel_info[index].name_rela;
+ if (strcmp(scn_name, n) == 0) {
+ SECT_DATA_SET(rel_info[index].index,sh_type,n)
+ return true;
+ }
+ if (strcmp(scn_name, na) == 0) {
+ SECT_DATA_SET(rel_info[index].index,sh_type,na)
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+void
+print_relocinfo(Dwarf_Debug dbg, unsigned reloc_map)
+{
+ Elf *elf;
+ char *endr_ident;
+ int is_64bit;
+ int res;
+ int i;
+
+ for (i = 0; i < DW_SECTION_REL_DEBUG_NUM; i++) {
+ sect_data[i].display = reloc_map & (1 << i);
+ sect_data[i].buf = 0;
+ sect_data[i].size = 0;
+ sect_data[i].type = SHT_NULL;
+ }
+ res = dwarf_get_elf(dbg, &elf, &err);
+ if (res != DW_DLV_OK) {
+ print_error(dbg, "dwarf_get_elf error", res, err);
+ }
+ if ((endr_ident = elf_getident(elf, NULL)) == NULL) {
+ print_error(dbg, "DW_ELF_GETIDENT_ERROR", res, err);
+ }
+ is_64bit = (endr_ident[EI_CLASS] == ELFCLASS64);
+ if (is_64bit) {
+ print_relocinfo_64(dbg, elf);
+ } else {
+ print_relocinfo_32(dbg, elf);
+ }
+}
+
+static void
+print_relocinfo_64(Dwarf_Debug dbg, Elf * elf)
+{
+#ifdef HAVE_ELF64_GETEHDR
+ Elf_Scn *scn = NULL;
+ Elf64_Ehdr *ehdr64 = 0;
+ Elf64_Shdr *shdr64 = 0;
+ const char *scn_name = 0;
+ const char **scn_names = 0;
+ int i = 0;
+ Elf64_Sym *sym_64 = 0;
+ int scn_names_cnt = 0;
+
+ ehdr64 = elf64_getehdr(elf);
+ if (ehdr64 == NULL) {
+ print_error(dbg, "DW_ELF_GETEHDR_ERROR", DW_DLV_OK, err);
+ }
+ scn_names = (const char **)calloc(ehdr64->e_shnum + 1, sizeof(char *));
+
+ while ((scn = elf_nextscn(elf, scn)) != NULL) {
+
+ shdr64 = elf64_getshdr(scn);
+ if (shdr64 == NULL) {
+ print_error(dbg, "DW_ELF_GETSHDR_ERROR", DW_DLV_OK, err);
+ }
+ scn_name = elf_strptr(elf, ehdr64->e_shstrndx, shdr64->sh_name);
+ if (scn_name == NULL) {
+ print_error(dbg, "DW_ELF_STRPTR_ERROR", DW_DLV_OK, err);
+ }
+ if(scn_names) {
+ /* elf_nextscn() skips section with index '0' */
+ scn_names[++scn_names_cnt] = scn_name;
+ }
+ if (shdr64->sh_type == SHT_SYMTAB) {
+ size_t sym_size = 0;
+ size_t count = 0;
+
+ sym_64 = (Elf64_Sym *) get_scndata(scn, &sym_size);
+ if (sym_64 == NULL) {
+ print_error(dbg, "no symbol table data", DW_DLV_OK,
+ err);
+ }
+ count = sym_size / sizeof(Elf64_Sym);
+ sym_64++;
+ free(sym_data_64);
+ sym_data_64 = read_64_syms(sym_64, count, elf, shdr64->sh_link);
+ sym_data_64_entry_count = count;
+ if (sym_data_64 == NULL) {
+ print_error(dbg, "problem reading symbol table data",
+ DW_DLV_OK, err);
+ }
+ } else if (!get_reloc_section(dbg,scn,scn_name,shdr64->sh_type)) {
+ continue;
+ }
+ } /* while */
+ /* Set the relocation names based on the machine type */
+ set_relocation_table_names(ehdr64->e_machine);
+ for (i = 0; i < DW_SECTION_REL_DEBUG_NUM; i++) {
+ if (sect_data[i].display &&
+ sect_data[i].buf != NULL &&
+ sect_data[i].size > 0) {
+ print_reloc_information_64(i, sect_data[i].buf,
+ sect_data[i].size, sect_data[i].type,scn_names,
+ scn_names_cnt);
+ }
+ }
+
+ if (scn_names) {
+ free(scn_names);
+ scn_names = 0;
+ scn_names_cnt = 0;
+ }
+#endif
+}
+
+static void
+print_relocinfo_32(Dwarf_Debug dbg, Elf * elf)
+{
+ Elf_Scn *scn = NULL;
+ Elf32_Ehdr *ehdr32 = 0;
+ Elf32_Shdr *shdr32 = 0;
+ char *scn_name = 0;
+ int i = 0;
+ Elf32_Sym *sym = 0;
+ const char **scn_names = 0;
+ int scn_names_cnt = 0;
+
+
+ ehdr32 = elf32_getehdr(elf);
+ if (ehdr32 == NULL) {
+ print_error(dbg, "DW_ELF_GETEHDR_ERROR", DW_DLV_OK, err);
+ }
+ /* Make the section name array big enough
+ that we don't need to check for overrun in the loop. */
+ scn_names = (const char **)calloc(ehdr32->e_shnum + 1, sizeof(char *));
+ while ((scn = elf_nextscn(elf, scn)) != NULL) {
+ shdr32 = elf32_getshdr(scn);
+ if (shdr32 == NULL) {
+ print_error(dbg, "DW_ELF_GETSHDR_ERROR", DW_DLV_OK, err);
+ }
+ scn_name = elf_strptr(elf, ehdr32->e_shstrndx, shdr32->sh_name);
+ if (scn_name == NULL) {
+ print_error(dbg, "DW_ELF_STRPTR_ERROR", DW_DLV_OK, err);
+ }
+ if (scn_names) {
+ /* elf_nextscn() skips section with index '0' */
+ scn_names[++scn_names_cnt] = scn_name;
+ }
+ if (shdr32->sh_type == SHT_SYMTAB) {
+ size_t sym_size = 0;
+ size_t count = 0;
+
+ sym = (Elf32_Sym *) get_scndata(scn, &sym_size);
+ if (sym == NULL) {
+ print_error(dbg, "no symbol table data", DW_DLV_OK,
+ err);
+ }
+ sym = (Elf32_Sym *) get_scndata(scn, &sym_size);
+ count = sym_size / sizeof(Elf32_Sym);
+ sym++;
+ free(sym_data);
+ sym_data = readsyms(sym, count, elf, shdr32->sh_link);
+ sym_data_entry_count = count;
+ if (sym_data == NULL) {
+ print_error(dbg, "problem reading symbol table data",
+ DW_DLV_OK, err);
+ }
+ } else if (!get_reloc_section(dbg,scn,scn_name,shdr32->sh_type)) {
+ continue;
+ }
+ } /* while */
+ /* Set the relocation names based on the machine type */
+ set_relocation_table_names(ehdr32->e_machine);
+
+ for (i = 0; i < DW_SECTION_REL_DEBUG_NUM; i++) {
+ if (sect_data[i].display &&
+ sect_data[i].buf != NULL &&
+ sect_data[i].size > 0) {
+ print_reloc_information_32(i, sect_data[i].buf,
+ sect_data[i].size,sect_data[i].type,scn_names,
+ scn_names_cnt);
+ }
+ }
+
+ if (scn_names) {
+ free(scn_names);
+ scn_names = 0;
+ scn_names_cnt = 0;
+ }
+
+}
+
+#if HAVE_ELF64_R_INFO
+#ifndef ELF64_R_TYPE
+#define ELF64_R_TYPE(x) 0 /* FIXME */
+#endif
+#ifndef ELF64_R_SYM
+#define ELF64_R_SYM(x) 0 /* FIXME */
+#endif
+#ifndef ELF64_ST_TYPE
+#define ELF64_ST_TYPE(x) 0 /* FIXME */
+#endif
+#ifndef ELF64_ST_BIND
+#define ELF64_ST_BIND(x) 0 /* FIXME */
+#endif
+#endif /* HAVE_ELF64_R_INFO */
+
+
+static void
+print_reloc_information_64(int section_no, Dwarf_Small * buf,
+ Dwarf_Unsigned size, Elf64_Xword type,
+ const char **scn_names, int scn_names_count)
+{
+ /* Include support for Elf64_Rel and Elf64_Rela */
+ Dwarf_Unsigned add = 0;
+ Dwarf_Half rel_size = SHT_RELA == type ?
+ sizeof(Elf64_Rela) : sizeof(Elf64_Rel);
+ Dwarf_Unsigned off = 0;
+
+ cout << endl;
+ cout << ((type == SHT_RELA)?sectnamesa[section_no]:
+ sectnames[section_no]) << ":" << endl;;
+ /* Print some headers and change the order for better reading */
+ printf("Offset Addend %-26s Index Symbol Name\n","Reloc Type");
+#if HAVE_ELF64_GETEHDR
+ for (off = 0; off < size; off += rel_size) {
+#if HAVE_ELF64_R_INFO
+ /* This works for the Elf64_Rel in linux */
+ Elf64_Rel *p = (Elf64_Rel *) (buf + off);
+ string name;
+ if(sym_data ) {
+ size_t index = ELF64_R_SYM(p->r_info) - 1;
+ if(index < sym_data_entry_count) {
+ name = sym_data[index].name;
+ }
+ } else if (sym_data_64) {
+ size_t index = ELF64_R_SYM(p->r_info) - 1;
+ if(index < sym_data_64_entry_count) {
+ name = sym_data_64[index].name;
+ }
+ }
+ /* When the name is not available, use the
+ section name as a reference for the name.*/
+ if (name.empty()) {
+ size_t index = ELF64_R_SYM(p->r_info) - 1;
+ if (index < sym_data_64_entry_count) {
+ SYM64 *sym_64 = &sym_data_64[index];
+ if (sym_64->type == STT_SECTION &&
+ sym_64->shndx < scn_names_count) {
+ name = scn_names[sym_64->shndx];
+ }
+ }
+ }
+ if (name.empty()) {
+ name = "<no name>";
+ }
+
+ if (SHT_RELA == type) {
+ Elf64_Rela *pa = (Elf64_Rela *)p;
+ add = pa->r_addend;
+ }
+
+
+ cout << IToHex0N(p->r_offset,10);
+ cout << " " << IToHex0N(add,10);
+ cout << " " <<LeftAlign(26,get_reloc_type_names(ELF64_R_TYPE(p->r_info)));
+ cout << " " << BracketSurround(IToDec(ELF64_R_SYM(p->r_info),5));
+ cout << " " << name;
+ cout << endl;
+#else
+ /* sgi/mips -64 does not have r_info in the 64bit relocations,
+ but seperate fields, with 3 types, actually. Only one of
+ which prints here, as only one really used with dwarf */
+ Elf64_Rel *p = (Elf64_Rel *) (buf + off);
+ string name;
+ if(sym_data ) {
+ size_t index = p->r_sym - 1;
+ if(index < sym_data_entry_count) {
+ name = sym_data[index].name;
+ }
+ } else if (sym_data_64) {
+ size_t index = p->r_sym - 1;
+ if(index < sym_data_64_entry_count) {
+ name = sym_data_64[index].name;
+ }
+ }
+ if (name.empty()) {
+ name = "<no name>";
+ }
+ cout << IToHex0N(p->r_offset,10);
+ cout << " " << IToHex0N(add,10);
+ cout << " " << LeftAlign(26,get_reloc_type_names(ELF64_R_TYPE(p->r_info)));
+ cout << " " << BracketSurround(IToDec(ELF64_R_SYM(p->r_info),3))
+ cout << " " << name;
+ cout << endl;
+#endif
+ }
+#endif /* HAVE_ELF64_GETEHDR */
+}
+
+static void
+print_reloc_information_32(int section_no, Dwarf_Small * buf,
+ Dwarf_Unsigned size, Elf64_Xword type,
+ const char **scn_names, int scn_names_count)
+{
+/* Include support for Elf32_Rel and Elf32_Rela */
+ Dwarf_Unsigned add = 0;
+ Dwarf_Half rel_size = SHT_RELA == type ?
+ sizeof(Elf32_Rela) : sizeof(Elf32_Rel);
+ Dwarf_Unsigned off = 0;
+
+ cout << endl;
+ cout << ((type == SHT_RELA)?sectnamesa[section_no]:
+ sectnames[section_no]) << ":" << endl;
+ printf("Offset Addend %-26s Index Symbol Name\n","Reloc Type");
+ for (off = 0; off < size; off += rel_size) {
+ Elf32_Rel *p = (Elf32_Rel *) (buf + off);
+ string name;
+ if(sym_data) {
+ size_t index = ELF32_R_SYM(p->r_info) - 1;
+ if(index < sym_data_entry_count) {
+ name = sym_data[index].name;
+ }
+ }
+ /* When the name is not available, use the
+ section name as a reference for the name.*/
+ if (name.empty()) {
+ size_t index = ELF32_R_SYM(p->r_info) - 1;
+ if(index < sym_data_entry_count) {
+ SYM *sym_32 = &sym_data[index];
+ if (sym_32->type == STT_SECTION &&
+ sym_32->shndx < scn_names_count) {
+ name = scn_names[sym_32->shndx];
+ }
+ }
+ }
+ if (name.empty()) {
+ name = "<no name>";
+ }
+
+ if (SHT_RELA == type) {
+ Elf32_Rela *pa = (Elf32_Rela *)p;
+ add = pa->r_addend;
+ }
+ cout << IToHex0N(p->r_offset,10);
+ cout << " " << IToHex0N(add,10);
+ cout << " " << LeftAlign(26,
+ get_reloc_type_names(ELF32_R_TYPE(p->r_info)));
+ cout << " " << BracketSurround(IToDec(ELF32_R_SYM(p->r_info),5));
+ cout << " " << name;
+ cout << endl;
+ }
+}
+
+static SYM *
+readsyms(Elf32_Sym * data, size_t num, Elf * elf, Elf32_Word link)
+{
+ SYM *s, *buf;
+ indx_type i;
+
+ buf = (SYM *) calloc(num, sizeof(SYM));
+ if (buf == NULL) {
+ return NULL;
+ }
+ s = buf; /* save pointer to head of array */
+ for (i = 1; i < num; i++, data++, buf++) {
+ buf->indx = i;
+ buf->name = (char *) elf_strptr(elf, link, data->st_name);
+ buf->value = data->st_value;
+ buf->size = data->st_size;
+ buf->type = ELF32_ST_TYPE(data->st_info);
+ buf->bind = ELF32_ST_BIND(data->st_info);
+ buf->other = data->st_other;
+ buf->shndx = data->st_shndx;
+ } /* end for loop */
+ return (s);
+}
+
+static SYM64 *
+read_64_syms(Elf64_Sym * data, size_t num, Elf * elf, Elf64_Word link)
+{
+#ifdef HAVE_ELF64_GETEHDR
+
+ SYM64 *s, *buf;
+ indx_type i;
+
+ buf = (SYM64 *) calloc(num, sizeof(SYM64));
+ if (buf == NULL) {
+ return NULL;
+ }
+ s = buf; /* save pointer to head of array */
+ for (i = 1; i < num; i++, data++, buf++) {
+ buf->indx = i;
+ buf->name = (char *) elf_strptr(elf, link, data->st_name);
+ buf->value = data->st_value;
+ buf->size = data->st_size;
+ buf->type = ELF64_ST_TYPE(data->st_info);
+ buf->bind = ELF64_ST_BIND(data->st_info);
+ buf->other = data->st_other;
+ buf->shndx = data->st_shndx;
+ } /* end for loop */
+ return (s);
+#else
+ return 0;
+#endif /* HAVE_ELF64_GETEHDR */
+}
+
+static void *
+get_scndata(Elf_Scn * fd_scn, size_t * scn_size)
+{
+ Elf_Data *p_data;
+
+ p_data = 0;
+ if ((p_data = elf_getdata(fd_scn, p_data)) == 0 ||
+ p_data->d_size == 0) {
+ return NULL;
+ }
+ *scn_size = p_data->d_size;
+ return (p_data->d_buf);
+}
+
+/* Cleanup of malloc space (some of the pointers will be 0 here)
+ so dwarfdump looks 'clean' to a malloc checker.
+*/
+void
+clean_up_syms_malloc_data()
+{
+ free(sym_data);
+ sym_data = 0;
+ free(sym_data_64);
+ sym_data_64 = 0;
+ sym_data_64_entry_count = 0;
+ sym_data_entry_count = 0;
+}
diff --git a/dwarfdump2/print_sections.cc b/dwarfdump2/print_sections.cc
new file mode 100644
index 0000000..07cfb0e
--- /dev/null
+++ b/dwarfdump2/print_sections.cc
@@ -0,0 +1,216 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2008-2010 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+// Contains functions that support printing.
+// Actual section-print code is in other print_*.cc files.
+#include "globals.h"
+#include <vector>
+#include "naming.h"
+#include "dwconf.h"
+
+#include "print_frames.h"
+#include "print_sections.h"
+
+using std::string;
+using std::cout;
+using std::cerr;
+using std::endl;
+
+bool dwarf_names_print_on_error = true;
+
+
+/* If an offset is bad, libdwarf will notice it and
+ return an error.
+ If it does the error checking in
+ print_pubname_style_entry()
+ will be useless as we give up here on an error.
+
+ This intended for checking pubnames-style call return
+ values (for all the pubnames-style interfaces).
+
+ In at least one gigantic executable die_off turned out wrong.
+*/
+
+
+void
+deal_with_name_offset_err(Dwarf_Debug dbg,
+ const string &err_loc,
+ const string &name,
+ Dwarf_Unsigned die_off,
+ int nres, Dwarf_Error err)
+{
+ if (nres == DW_DLV_ERROR) {
+ Dwarf_Unsigned myerr = dwarf_errno(err);
+ if (myerr == DW_DLE_OFFSET_BAD) {
+ cout << "Error: bad offset ";
+ cout << err_loc;
+ cout << " ";
+ cout << name;
+ cout << die_off;
+ cout << " (";
+ cout << IToHex0N(die_off,10);
+ cout << ")" << endl;
+ }
+ print_error(dbg, err_loc, nres, err);
+ }
+}
+/* The new (April 2005) dwarf_get_section_max_offsets()
+ in libdwarf returns all max-offsets, but we only
+ want one of those offsets. This function returns
+ the one we want from that set,
+ making functions needing this offset as readable as possible.
+ (avoiding code duplication).
+*/
+Dwarf_Unsigned
+get_info_max_offset(Dwarf_Debug dbg)
+{
+ Dwarf_Unsigned debug_info_size = 0;
+ Dwarf_Unsigned debug_abbrev_size = 0;
+ Dwarf_Unsigned debug_line_size = 0;
+ Dwarf_Unsigned debug_loc_size = 0;
+ Dwarf_Unsigned debug_aranges_size = 0;
+ Dwarf_Unsigned debug_macinfo_size = 0;
+ Dwarf_Unsigned debug_pubnames_size = 0;
+ Dwarf_Unsigned debug_str_size = 0;
+ Dwarf_Unsigned debug_frame_size = 0;
+ Dwarf_Unsigned debug_ranges_size = 0;
+ Dwarf_Unsigned debug_pubtypes_size = 0;
+
+ dwarf_get_section_max_offsets(dbg,
+ &debug_info_size,
+ &debug_abbrev_size,
+ &debug_line_size,
+ &debug_loc_size,
+ &debug_aranges_size,
+ &debug_macinfo_size,
+ &debug_pubnames_size,
+ &debug_str_size,
+ &debug_frame_size,
+ &debug_ranges_size,
+ &debug_pubtypes_size);
+ return debug_info_size;
+}
+
+
+/*
+ decode ULEB
+*/
+Dwarf_Unsigned
+local_dwarf_decode_u_leb128(unsigned char *leb128,
+ unsigned int *leb128_length)
+{
+ unsigned char byte = 0;
+ Dwarf_Unsigned number = 0;
+ unsigned int shift = 0;
+ unsigned int byte_length = 1;
+
+ byte = *leb128;
+ for (;;) {
+ number |= (byte & 0x7f) << shift;
+ shift += 7;
+
+ if ((byte & 0x80) == 0) {
+ if (leb128_length != NULL)
+ *leb128_length = byte_length;
+ return (number);
+ }
+
+ byte_length++;
+ byte = *(++leb128);
+ }
+}
+
+#define BITSINBYTE 8
+Dwarf_Signed
+local_dwarf_decode_s_leb128(unsigned char *leb128,
+ unsigned int *leb128_length)
+{
+ Dwarf_Signed number = 0;
+ Dwarf_Bool sign = 0;
+ Dwarf_Signed shift = 0;
+ unsigned char byte = *leb128;
+ Dwarf_Signed byte_length = 1;
+
+ /* byte_length being the number of bytes of data absorbed so far in
+ turning the leb into a Dwarf_Signed. */
+
+ for (;;) {
+ sign = byte & 0x40;
+ number |= ((Dwarf_Signed) ((byte & 0x7f))) << shift;
+ shift += 7;
+
+ if ((byte & 0x80) == 0) {
+ break;
+ }
+ ++leb128;
+ byte = *leb128;
+ byte_length++;
+ }
+
+ if ((shift < sizeof(Dwarf_Signed) * BITSINBYTE) && sign) {
+ number |= -((Dwarf_Signed) 1 << shift);
+ }
+
+ if (leb128_length != NULL)
+ *leb128_length = byte_length;
+ return (number);
+}
+
+
+/* Dumping a dwarf-expression as a byte stream. */
+void
+dump_block(const string &prefix, char *data, Dwarf_Signed len)
+{
+ char *end_data = data + len;
+ char *cur = data;
+ int i = 0;
+
+ cout << prefix;
+ for (; cur < end_data; ++cur, ++i) {
+ if (i > 0 && i % 4 == 0){
+ cout << " ";
+ }
+ cout << IToHex02(*cur);
+ }
+}
+
diff --git a/dwarfdump2/print_sections.h b/dwarfdump2/print_sections.h
new file mode 100644
index 0000000..ccb6bbe
--- /dev/null
+++ b/dwarfdump2/print_sections.h
@@ -0,0 +1,55 @@
+/*
+ Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+*/
+
+
+
+void deal_with_name_offset_err(Dwarf_Debug dbg,
+ const std::string &err_loc,
+ const std::string &name,
+ Dwarf_Unsigned die_off,
+ int nres,
+ Dwarf_Error err);
+
+Dwarf_Unsigned get_info_max_offset(Dwarf_Debug dbg);
+
+void print_pubname_style_entry(Dwarf_Debug dbg,
+ const std::string &line_title,
+ const std::string &name,
+ Dwarf_Unsigned die_off,
+ Dwarf_Unsigned cu_off,
+ Dwarf_Unsigned global_cu_off,
+ Dwarf_Unsigned maxoff);
+
+
diff --git a/dwarfdump2/print_static_funcs.cc b/dwarfdump2/print_static_funcs.cc
new file mode 100644
index 0000000..1231e7c
--- /dev/null
+++ b/dwarfdump2/print_static_funcs.cc
@@ -0,0 +1,135 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include "globals.h"
+#include <vector>
+#include "naming.h"
+#include "dwconf.h"
+
+#include "print_sections.h"
+#include "print_frames.h"
+
+using std::string;
+using std::cout;
+using std::cerr;
+using std::endl;
+
+/* Get all the data in .debug_static_funcs
+ On error, this allows some dwarf memory leaks.
+*/
+extern void
+print_static_funcs(Dwarf_Debug dbg)
+{
+ Dwarf_Func *funcbuf = NULL;
+ Dwarf_Signed count = 0;
+ Dwarf_Signed i = 0;
+ Dwarf_Off die_off = 0;
+ Dwarf_Off cu_off = 0;
+ int gfres = 0;
+
+ error_message_data.current_section_id = DEBUG_STATIC_FUNC;
+ if (!do_print_dwarf) {
+ return;
+ }
+ cout << endl;
+ cout << ".debug_static_func" << endl;
+ gfres = dwarf_get_funcs(dbg, &funcbuf, &count, &err);
+ if (gfres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_funcs", gfres, err);
+ } else if (gfres == DW_DLV_NO_ENTRY) {
+ /* no static funcs */
+ } else {
+ Dwarf_Unsigned maxoff = get_info_max_offset(dbg);
+
+ for (i = 0; i < count; i++) {
+ int fnres;
+ int cures3;
+ Dwarf_Unsigned global_cu_off = 0;
+ char *name = 0;
+
+ fnres = dwarf_func_name_offsets(funcbuf[i], &name, &die_off,
+ &cu_off, &err);
+ deal_with_name_offset_err(dbg, "dwarf_func_name_offsets",
+ name, die_off, fnres, err);
+
+ cures3 = dwarf_func_cu_offset(funcbuf[i], &global_cu_off, &err);
+ if (cures3 != DW_DLV_OK) {
+ print_error(dbg, "dwarf_global_cu_offset", cures3, err);
+ }
+
+ print_pubname_style_entry(dbg,
+ "static-func", name, die_off,
+ cu_off, global_cu_off, maxoff);
+
+
+ /* print associated die too? */
+ if (check_pubname_attr) {
+ Dwarf_Bool has_attr;
+ int ares;
+ int dres;
+ Dwarf_Die die;
+
+ /* get die at die_off */
+ dres = dwarf_offdie(dbg, die_off, &die, &err);
+ if (dres != DW_DLV_OK) {
+ print_error(dbg, "dwarf_offdie", dres, err);
+ }
+ ares = dwarf_hasattr(die, DW_AT_external, &has_attr, &err);
+ if (ares == DW_DLV_ERROR) {
+ print_error(dbg, "hassattr on DW_AT_external", ares,
+ err);
+ }
+ DWARF_CHECK_COUNT(pubname_attr_result,1);
+ if (ares == DW_DLV_OK && has_attr) {
+ /* Should the value of flag be examined? */
+ } else {
+ DWARF_CHECK_ERROR2(pubname_attr_result,name,
+ "pubname (in static funcs section) does not have DW_AT_external");
+ }
+ dwarf_dealloc(dbg, die, DW_DLA_DIE);
+ }
+ }
+ dwarf_funcs_dealloc(dbg, funcbuf, count);
+ }
+} /* print_static_funcs() */
+
diff --git a/dwarfdump2/print_static_vars.cc b/dwarfdump2/print_static_vars.cc
new file mode 100644
index 0000000..72f83ea
--- /dev/null
+++ b/dwarfdump2/print_static_vars.cc
@@ -0,0 +1,106 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include "globals.h"
+#include <vector>
+#include "naming.h"
+#include "dwconf.h"
+
+#include "print_sections.h"
+#include "print_frames.h"
+
+using std::string;
+using std::cout;
+using std::cerr;
+using std::endl;
+
+/* get all the data in .debug_static_vars */
+extern void
+print_static_vars(Dwarf_Debug dbg)
+{
+ Dwarf_Var *varbuf = NULL;
+ Dwarf_Off die_off = 0;
+ Dwarf_Off cu_off = 0;
+ Dwarf_Signed count = 0;
+ error_message_data.current_section_id = DEBUG_STATIC_VARS;
+ if (!do_print_dwarf) {
+ return;
+ }
+
+ cout << endl;
+ cout << ".debug_static_vars" << endl;
+ int gvres = dwarf_get_vars(dbg, &varbuf, &count, &err);
+ if (gvres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_vars", gvres, err);
+ } else if (gvres == DW_DLV_NO_ENTRY) {
+ /* no static vars */
+ } else {
+ Dwarf_Unsigned maxoff = get_info_max_offset(dbg);
+
+ for (Dwarf_Signed i = 0; i < count; i++) {
+ Dwarf_Off global_cu_off = 0;
+ char *namearg = 0;
+
+ int vnres = dwarf_var_name_offsets(varbuf[i],
+ &namearg, &die_off, &cu_off, &err);
+ deal_with_name_offset_err(dbg,
+ "dwarf_var_name_offsets",
+ namearg, die_off, vnres, err);
+ string name = namearg;
+
+ int cures3 = dwarf_var_cu_offset(varbuf[i],
+ &global_cu_off, &err);
+ if (cures3 != DW_DLV_OK) {
+ print_error(dbg, "dwarf_global_cu_offset", cures3, err);
+ }
+
+ print_pubname_style_entry(dbg,
+ "static-var",
+ name, die_off, cu_off,
+ global_cu_off, maxoff);
+ /* print associated die too? */
+ }
+ dwarf_vars_dealloc(dbg, varbuf, count);
+ }
+} /* print_static_vars */
+
diff --git a/dwarfdump2/print_strings.cc b/dwarfdump2/print_strings.cc
new file mode 100644
index 0000000..9c94206
--- /dev/null
+++ b/dwarfdump2/print_strings.cc
@@ -0,0 +1,88 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include "globals.h"
+#include <vector>
+#include "naming.h"
+#include "dwconf.h"
+
+#include "print_sections.h"
+#include "print_frames.h"
+
+using std::string;
+using std::cout;
+using std::cerr;
+using std::endl;
+
+/* print data in .debug_string */
+extern void
+print_strings(Dwarf_Debug dbg)
+{
+ Dwarf_Signed length = 0;
+ char * name = 0;
+ Dwarf_Off offset = 0;
+ int sres = 0;
+
+ error_message_data.current_section_id = DEBUG_STR;
+ cout << endl;
+ cout << ".debug_string" << endl;
+ while ((sres = dwarf_get_str(dbg, offset, &name, &length, &err))
+ == DW_DLV_OK) {
+ if(display_offsets) {
+ cout << "name at offset " << IToHex0N(offset,10) <<
+ ", length " << IToDec(length,4) <<
+ " is " << "'" << name <<"'" << endl;
+ } else {
+ cout << "name: length " << IToDec(length,4) <<
+ " is '" << name << "'" << endl;
+ }
+ offset += length + 1;
+ }
+ /* An inability to find the section is not necessarily
+ a real error, so do not report error unless we've
+ seen a real record. */
+ if(sres == DW_DLV_ERROR && offset != 0) {
+ print_error(dbg, "dwarf_get_str failure", sres, err);
+ }
+}
+
diff --git a/dwarfdump2/print_types.cc b/dwarfdump2/print_types.cc
new file mode 100644
index 0000000..8595813
--- /dev/null
+++ b/dwarfdump2/print_types.cc
@@ -0,0 +1,142 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include "globals.h"
+#include <vector>
+#include "naming.h"
+#include "dwconf.h"
+
+#include "print_sections.h"
+#include "print_frames.h"
+
+using std::string;
+using std::cout;
+using std::cerr;
+using std::endl;
+
+/* get all the data in .debug_types */
+extern void
+print_types(Dwarf_Debug dbg, enum type_type_e type_type)
+{
+ string section_name;
+ string offset_err_name;
+ string section_open_name;
+ string print_name_prefix;
+ int (*get_types) (Dwarf_Debug, Dwarf_Type **, Dwarf_Signed *,
+ Dwarf_Error *) = 0;
+ int (*get_offset) (Dwarf_Type, char **, Dwarf_Off *, Dwarf_Off *,
+ Dwarf_Error *) = 0;
+ int (*get_cu_offset) (Dwarf_Type, Dwarf_Off *, Dwarf_Error *) =
+ 0;
+ void (*dealloctype) (Dwarf_Debug, Dwarf_Type *, Dwarf_Signed) =
+ 0;
+
+ if(!do_print_dwarf) {
+ return;
+ }
+
+ if (type_type == DWARF_PUBTYPES) {
+ section_name = ".debug_pubtypes";
+ offset_err_name = "dwarf_pubtype_name_offsets";
+ section_open_name = "dwarf_get_pubtypes";
+ print_name_prefix = "pubtype";
+ get_types = dwarf_get_pubtypes;
+ get_offset = dwarf_pubtype_name_offsets;
+ get_cu_offset = dwarf_pubtype_cu_offset;
+ dealloctype = dwarf_pubtypes_dealloc;
+ } else {
+ /* SGI_TYPENAME */
+ section_name = ".debug_typenames";
+ offset_err_name = "dwarf_type_name_offsets";
+ section_open_name = "dwarf_get_types";
+ print_name_prefix = "type";
+ get_types = dwarf_get_types;
+ get_offset = dwarf_type_name_offsets;
+ get_cu_offset = dwarf_type_cu_offset;
+ dealloctype = dwarf_types_dealloc;
+ }
+
+
+
+ Dwarf_Signed count = 0;
+ Dwarf_Type *typebuf = NULL;
+ int gtres = get_types(dbg, &typebuf, &count, &err);
+ if (gtres == DW_DLV_ERROR) {
+ print_error(dbg, section_open_name, gtres, err);
+ } else if (gtres == DW_DLV_NO_ENTRY) {
+ /* no types */
+ } else {
+ Dwarf_Unsigned maxoff = get_info_max_offset(dbg);
+
+ /* Before July 2005, the section name was printed
+ unconditionally, now only prints if non-empty section really
+ exists. */
+ cout << endl;
+ cout << section_name << endl;
+
+ for (Dwarf_Signed i = 0; i < count; i++) {
+ char *name = NULL;
+ Dwarf_Off die_off = 0;
+ Dwarf_Off cu_off = 0;
+ Dwarf_Off global_cu_off = 0;
+
+ int tnres =
+ get_offset(typebuf[i], &name, &die_off, &cu_off, &err);
+ deal_with_name_offset_err(dbg, offset_err_name, name,
+ die_off, tnres, err);
+
+ int cures3 = get_cu_offset(typebuf[i], &global_cu_off, &err);
+
+ if (cures3 != DW_DLV_OK) {
+ print_error(dbg, "dwarf_var_cu_offset", cures3, err);
+ }
+ print_pubname_style_entry(dbg,
+ print_name_prefix,
+ name, die_off, cu_off,
+ global_cu_off, maxoff);
+
+ /* print associated die too? */
+ }
+ dealloctype(dbg, typebuf, count);
+ }
+} /* print_types() */
diff --git a/dwarfdump2/print_weaknames.cc b/dwarfdump2/print_weaknames.cc
new file mode 100644
index 0000000..e73ae47
--- /dev/null
+++ b/dwarfdump2/print_weaknames.cc
@@ -0,0 +1,113 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include "globals.h"
+#include <vector>
+#include "naming.h"
+#include "dwconf.h"
+
+#include "print_sections.h"
+#include "print_frames.h"
+
+using std::string;
+using std::cout;
+using std::cerr;
+using std::endl;
+
+/* Get all the data in .debug_weaknames */
+extern void
+print_weaknames(Dwarf_Debug dbg)
+{
+ Dwarf_Weak *weaknamebuf = NULL;
+ Dwarf_Signed count = 0;
+ Dwarf_Signed i = 0;
+ Dwarf_Off die_off = 0;
+ Dwarf_Off cu_off = 0;
+ int wkres = 0;
+
+ error_message_data.current_section_id = DEBUG_WEAKNAMES;
+ if (!do_print_dwarf) {
+ return;
+ }
+ cout << endl;
+ cout << ".debug_weaknames" << endl;
+ wkres = dwarf_get_weaks(dbg, &weaknamebuf, &count, &err);
+ if (wkres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_weaks", wkres, err);
+ } else if (wkres == DW_DLV_NO_ENTRY) {
+ /* no weaknames */
+ } else {
+ Dwarf_Unsigned maxoff = get_info_max_offset(dbg);
+
+ for (i = 0; i < count; i++) {
+ int tnres;
+ int cures3;
+ char *name = NULL;
+
+ Dwarf_Unsigned global_cu_off = 0;
+
+ tnres = dwarf_weak_name_offsets(weaknamebuf[i],
+ &name, &die_off, &cu_off,
+ &err);
+ deal_with_name_offset_err(dbg,
+ "dwarf_weak_name_offsets",
+ name, die_off, tnres, err);
+
+ cures3 = dwarf_weak_cu_offset(weaknamebuf[i],
+ &global_cu_off, &err);
+
+ if (cures3 != DW_DLV_OK) {
+ print_error(dbg, "dwarf_weakname_cu_offset",
+ cures3, err);
+ }
+ print_pubname_style_entry(dbg,
+ "weakname",
+ name, die_off, cu_off,
+ global_cu_off, maxoff);
+
+ /* print associated die too? */
+ }
+ dwarf_weaks_dealloc(dbg, weaknamebuf, count);
+ }
+} /* print_weaknames() */
+
diff --git a/dwarfdump2/srcfilesholder.h b/dwarfdump2/srcfilesholder.h
new file mode 100644
index 0000000..0594c07
--- /dev/null
+++ b/dwarfdump2/srcfilesholder.h
@@ -0,0 +1,89 @@
+/*
+ Copyright (C) 2009-2011 David Anderson All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+*/
+
+#ifndef SRCFILESHOLDER_H
+#define SRCFILESHOLDER_H
+// Reference counting eliminates confusion and bugs
+// when deciding when to do dealloc.
+// It might be nice to store a vector of string here and
+// dealloc the dwarf data on construction.
+// But for now we store the libdwarf strings.
+class SrcfilesHolder {
+public:
+ SrcfilesHolder():dbg_(0),srcfiles_(0),cnt_(0),refcount_(new int(1)) { };
+ SrcfilesHolder(Dwarf_Debug dbg, char **srcfiles, Dwarf_Signed cnt):
+ dbg_(dbg),srcfiles_(srcfiles),cnt_(cnt),refcount_(new int(1)) { };
+ ~SrcfilesHolder() {
+ (*refcount_)--;
+ if( (*refcount_) == 0) {
+ delete refcount_;
+ if(srcfiles_) do_delete();
+ }
+ };
+ SrcfilesHolder(const SrcfilesHolder & d):dbg_(d.dbg_),
+ srcfiles_(d.srcfiles_),cnt_(d.cnt_),
+ refcount_(d.refcount_) {
+ (*refcount_)++;
+ };
+ SrcfilesHolder & operator=(const SrcfilesHolder & d) {
+ if(this != &d) {
+ (*d.refcount_)++;
+ (*refcount_)--;
+ if( (*refcount_) == 0) {
+ delete refcount_;
+ if(srcfiles_) do_delete();
+ }
+ refcount_ = d.refcount_;
+ srcfiles_ = d.srcfiles_;
+ cnt_ = d.cnt_;
+ dbg_ = d.dbg_;
+ }
+ return *this;
+ };
+ Dwarf_Signed count() { return cnt_; };
+ char ** srcfiles() { return srcfiles_; };
+ Dwarf_Debug dbg() { return dbg_; };
+private:
+ void do_delete() {
+ for (Dwarf_Signed si = 0; si < cnt_; ++si) {
+ dwarf_dealloc(dbg_, srcfiles_[si], DW_DLA_STRING);
+ }
+ dwarf_dealloc(dbg_, srcfiles_, DW_DLA_LIST);
+ };
+ Dwarf_Debug dbg_;
+ char **srcfiles_;
+ Dwarf_Signed cnt_;
+ int *refcount_;
+};
+#endif // SRCFILESHOLDER_H
diff --git a/dwarfdump2/strstrnocase.cc b/dwarfdump2/strstrnocase.cc
new file mode 100755
index 0000000..7d68ba9
--- /dev/null
+++ b/dwarfdump2/strstrnocase.cc
@@ -0,0 +1,115 @@
+/*
+ Copyright (C) 2009-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+
+/*
+This tries to find the string 'contained' in the
+string 'container'. it returns true if found, else false.
+The comparisons are independent of case.
+
+Regrettably there is no generally accepted version that
+does this job, though GNU Linux has strcasestr() which
+does what we need.
+
+There is a public domain stristr(). But given that dwarfdump is GPL,
+it would seem (IANAL) that we cannot mix public domain code
+into the release.
+
+The software here is independently written and indeed trivial.
+
+The POSIX function tolower() is only properly defined on unsigned char, hence
+the ugly casts.
+
+strstrnocase.cc
+
+*/
+#include <ctype.h>
+#include <stdio.h>
+#include <globals.h>
+
+bool
+is_strstrnocase(const char * container, const char * contained)
+{
+ const unsigned char *ct = (const unsigned char *)container;
+ for( ; *ct; ++ct )
+ {
+ const unsigned char * cntnd = (const unsigned char *)contained;
+ bool innerwrong = true;
+ for( ; *cntnd; ++cntnd,++ct)
+ {
+ unsigned char lct = tolower(*ct);
+ unsigned char tlc = tolower(*cntnd);
+ if(lct != tlc) {
+ innerwrong=true;
+ break; /* Go to outer loop */
+ }
+ innerwrong=false;
+ }
+ if(!innerwrong) {
+ return true;
+ }
+ }
+ return false;
+}
+
+#ifdef TEST
+static void
+test(const char *t1, const char *t2,int resexp)
+{
+ bool res = is_strstrnocase(t1,t2);
+ if (res == resexp) {
+ return;
+ }
+ printf("Error,mismatch %s and %s. Expected %d got %d\n",
+ t1,t2,resexp,res);
+}
+
+int main()
+{
+ test("aaaaa","a",1);
+ test("aaaaa","b",0);
+ test("abaaba","ba",1);
+ test("abaabA","Ba",1);
+ test("a","ab",0);
+ test("b","c",0);
+ test("b","",0);
+ test("","c",0);
+ test("","",0);
+ test("aaaaa","aaaaaaaa",0);
+}
+#endif
diff --git a/dwarfdump2/tag_attr.cc b/dwarfdump2/tag_attr.cc
new file mode 100644
index 0000000..e4a633c
--- /dev/null
+++ b/dwarfdump2/tag_attr.cc
@@ -0,0 +1,278 @@
+/*
+ Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2009-2010 SN Systems Ltd. All Rights Reserved.
+ Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/tag_attr.c,v 1.8 2005/12/01 17:34:59 davea Exp $ */
+#include <dwarf.h>
+#include <stdio.h>
+#include <stdlib.h> /* For exit() declaration etc. */
+#include <errno.h> /* For errno declaration. */
+#include <unistd.h> /* For getopt. */
+
+#include "globals.h"
+#include "naming.h"
+#include "common.h"
+#include "tag_common.h"
+using std::string;
+using std::cerr;
+using std::cout;
+using std::endl;
+
+bool ellipsis = true; /* So we can use naming.cc */
+
+/* Expected input format
+
+0xffffffff
+value of a tag
+value of a standard attribute that follows that tag
+...
+0xffffffff
+value of a tag
+value of a standard attribute that follows that tag
+...
+0xffffffff
+...
+
+No blank lines or commentary allowed, no symbols, just numbers.
+
+
+*/
+
+unsigned int tag_attr_combination_table[ATTR_TABLE_ROW_MAXIMUM][ATTR_TABLE_COLUMN_MAXIMUM];
+
+
+static const char *usage[] = {
+ "Usage: tag_attr_build <options>\n",
+ " -i input-table-path\n",
+ " -o output-table-path\n",
+ " -s (Generate standard attribute table)\n",
+ " -e (Generate extended attribute table (common extensions))\n",
+ ""
+};
+
+string input_name;
+string output_name;
+bool standard_flag = false;
+bool extended_flag = false;
+
+/* process arguments */
+void
+process_args(int argc,char *argv[])
+{
+ int c = 0;
+ bool usage_error = false;
+
+ while ((c = getopt(argc, const_cast<char **>(argv), "i:o:se")) != EOF) {
+ switch (c) {
+ case 'i':
+ input_name = optarg;
+ break;
+ case 'o':
+ output_name = optarg;
+ break;
+ case 'e':
+ extended_flag = true;
+ break;
+ case 's':
+ standard_flag = true;
+ break;
+ default:
+ usage_error = true;
+ break;
+ }
+ }
+
+ if (usage_error || 1 == optind || optind != argc) {
+ print_usage_message(argv[0],usage);
+ exit(FAILED);
+ }
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+ print_version_details(argv[0],false);
+ process_args(argc,argv);
+ print_args(argc,argv);
+
+ if (input_name.empty()) {
+ cerr << "Input name required, not supplied." << endl;
+ print_usage_message(argv[0],usage);
+ exit(FAILED);
+ }
+ FILE *fileInp = fopen(input_name.c_str(),"r");
+ if (!fileInp) {
+ cerr << "Invalid input filename, could not open '" <<
+ input_name << "'." << endl;
+ print_usage_message(argv[0],usage);
+ exit(FAILED);
+ }
+
+
+ if (output_name.empty()) {
+ cerr << "Output name required, not supplied." << endl;
+ print_usage_message(argv[0],usage);
+ exit(FAILED);
+ }
+ FILE *fileOut = fopen(output_name.c_str(),"w");
+ if (!fileOut) {
+ cerr << "Invalid output filename, could not open: '" <<
+ output_name << "'." << endl;
+ print_usage_message(argv[0],usage);
+ exit(FAILED);
+ }
+ if ((standard_flag && extended_flag) ||
+ (!standard_flag && !extended_flag)) {
+ cerr << "Invalid table type" << endl;
+ cerr << "Choose -e or -s ." << endl;
+ print_usage_message(argv[0],usage);
+ exit(FAILED);
+ }
+
+
+ unsigned table_rows = 0;
+ unsigned table_columns = 0;
+ if(standard_flag) {
+ table_rows = STD_ATTR_TABLE_ROWS;
+ table_columns = STD_ATTR_TABLE_COLUMNS;
+ } else {
+ table_rows = EXT_ATTR_TABLE_ROWS;
+ table_columns = EXT_ATTR_TABLE_COLS;
+ }
+
+ unsigned int num = 0;
+ int input_eof = read_value(&num,fileInp); /* 0xffffffff */
+ if (IS_EOF == input_eof) {
+ bad_line_input("Empty input file");
+ }
+ if (num != MAGIC_TOKEN_VALUE) {
+ bad_line_input("Expected 0xffffffff");
+ }
+ unsigned int current_row = 0;
+ while (!feof(stdin)) {
+ unsigned int tag;
+ unsigned int curcol = 0;
+
+ input_eof = read_value(&tag,fileInp);
+ if (IS_EOF == input_eof) {
+ /* Reached normal eof */
+ break;
+ }
+ if(standard_flag) {
+ if (tag >= table_rows ) {
+ bad_line_input("tag value exceeds standard table size");
+ }
+ } else {
+ if(current_row >= table_rows) {
+ bad_line_input("too many extended table rows.");
+ }
+ tag_attr_combination_table[current_row][0] = tag;
+ }
+
+ input_eof = read_value(&num,fileInp);
+ if (IS_EOF == input_eof) {
+ bad_line_input("Not terminated correctly..");
+ }
+ curcol = 1;
+ while (num != MAGIC_TOKEN_VALUE) {
+ if(standard_flag) {
+ unsigned idx = num / BITS_PER_WORD;
+ unsigned bit = num % BITS_PER_WORD;
+
+ if (idx >= table_columns) {
+ bad_line_input
+ ("too many attributes: table incomplete.");
+ }
+ tag_attr_combination_table[tag][idx] |= (1 << bit);
+ } else {
+ if (curcol >= table_columns) {
+ bad_line_input("too many attributes: table incomplete.");
+ }
+ tag_attr_combination_table[current_row][curcol] = num;
+ curcol++;
+
+ }
+ input_eof = read_value(&num,fileInp);
+ if (IS_EOF == input_eof) {
+ bad_line_input("Not terminated correctly.");
+ }
+ }
+ ++current_row;
+ }
+ fprintf(fileOut,"/* Generated code, do not edit. */\n");
+ fprintf(fileOut,"/* Generated on %s %s */\n",__DATE__,__TIME__);
+ if (standard_flag) {
+ fprintf(fileOut,"#define ATTR_TREE_ROW_COUNT %u\n\n",table_rows);
+ fprintf(fileOut,"#define ATTR_TREE_COLUMN_COUNT %u\n\n",table_columns);
+ fprintf(fileOut,
+ "static unsigned int tag_attr_combination_table"
+ "[ATTR_TREE_ROW_COUNT][ATTR_TREE_COLUMN_COUNT] = {\n");
+ }
+ else {
+ fprintf(fileOut,"/* Common extensions */\n");
+ fprintf(fileOut,"#define ATTR_TREE_EXT_ROW_COUNT %u\n\n",table_rows);
+ fprintf(fileOut,"#define ATTR_TREE_EXT_COLUMN_COUNT %d\n\n",
+ table_columns);
+ fprintf(fileOut,
+ "static unsigned int tag_attr_combination_ext_table"
+ "[ATTR_TREE_EXT_ROW_COUNT][ATTR_TREE_EXT_COLUMN_COUNT] = {\n");
+ }
+
+ for (unsigned int i = 0; i < table_rows; i++) {
+ bool printonerr = false;
+ if(standard_flag) {
+ fprintf(fileOut,"/* %d %-37s*/\n",i,
+ get_TAG_name(i,printonerr).c_str());
+ } else {
+ fprintf(fileOut,"/* %u %-37s*/\n",
+ tag_attr_combination_table[i][0],
+ get_TAG_name(
+ tag_attr_combination_table[i][0],printonerr).c_str());
+ }
+ fprintf(fileOut," { ");
+ for(unsigned j = 0; j < table_columns; ++j ) {
+ fprintf(fileOut,"0x%08x,",tag_attr_combination_table[i][j]);
+ }
+ fprintf(fileOut,"},\n");
+ }
+ fprintf(fileOut,"};\n");
+ return (0);
+}
+/* A fake so we can use dwarf_names.cc */
+void print_error (Dwarf_Debug dbg, const string &msg,int res, Dwarf_Error err)
+{
+}
+
diff --git a/dwarfdump2/tag_attr.list b/dwarfdump2/tag_attr.list
new file mode 100644
index 0000000..813ae18
--- /dev/null
+++ b/dwarfdump2/tag_attr.list
@@ -0,0 +1,880 @@
+/*
+ Copyright (C) 2000-2010 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+ $Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/tag_attr.list,v 1.7 2005/12/01 17:34:59 davea Exp $
+*/
+#include <dwarf.h>
+
+/*
+ list for semantic check of tag-attr relation.
+
+ 0xffffffff is a "punctuation." The final line of this file
+ must be 0xffffffff. The next line after each 0xffffffff
+ (except the final line) is a tag. The lines after this line
+ before the next 0xffffffff are the attributes that can be given
+ to the tag."
+
+ For example,
+
+ 0xffffffff
+ DW_TAG_access_declaration
+ DW_AT_decl_column
+ DW_AT_decl_file
+ DW_AT_decl_line
+ DW_AT_accessibility
+ DW_AT_name
+ DW_AT_sibling
+ 0xffffffff
+
+ means "only DW_AT_decl_column, DW_AT_decl_file, DW_AT_decl_line,
+ DW_AT_accessibility, DW_AT_name and DW_AT_sibling can be given to
+ DW_TAG_access_declaration."
+
+ This file is applied to the preprocessor, thus any C comment and
+ preprocessor control line is available.
+*/
+
+0xffffffff
+DW_TAG_access_declaration
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_accessibility
+DW_AT_name
+DW_AT_sibling
+0xffffffff
+DW_TAG_array_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_accessibility
+DW_AT_allocated
+DW_AT_associated
+DW_AT_bit_stride
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 */
+DW_AT_data_location
+DW_AT_declaration
+DW_AT_description
+DW_AT_name
+DW_AT_ordering
+DW_AT_sibling
+DW_AT_specification
+DW_AT_start_scope
+DW_AT_type
+DW_AT_visibility
+0xffffffff
+DW_TAG_base_type
+DW_AT_allocated
+DW_AT_associated
+DW_AT_binary_scale
+DW_AT_bit_offset
+DW_AT_bit_size
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 */
+DW_AT_data_bit_offset
+DW_AT_data_location
+DW_AT_decimal_scale
+DW_AT_decimal_sign
+DW_AT_description
+DW_AT_digit_count
+DW_AT_encoding
+DW_AT_endianity
+DW_AT_name
+DW_AT_name
+DW_AT_picture_string
+DW_AT_sibling
+DW_AT_small
+0xffffffff
+DW_TAG_catch_block
+DW_AT_abstract_origin
+DW_AT_high_pc
+DW_AT_low_pc
+DW_AT_ranges
+DW_AT_segment
+DW_AT_sibling
+0xffffffff
+DW_TAG_class_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_accessibility
+DW_AT_allocated
+DW_AT_associated
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 */
+DW_AT_data_location
+DW_AT_declaration
+DW_AT_description
+DW_AT_name
+DW_AT_sibling
+DW_AT_signature
+DW_AT_specification
+DW_AT_start_scope
+DW_AT_visibility
+0xffffffff
+DW_TAG_common_block
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_declaration
+DW_AT_location
+DW_AT_name
+DW_AT_segment
+DW_AT_sibling
+DW_AT_visibility
+0xffffffff
+DW_TAG_common_inclusion
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_common_reference
+DW_AT_declaration
+DW_AT_sibling
+DW_AT_visibility
+0xffffffff
+DW_TAG_compile_unit
+DW_AT_base_types
+DW_AT_comp_dir
+DW_AT_identifier_case
+DW_AT_high_pc
+DW_AT_language
+DW_AT_low_pc
+DW_AT_macro_info
+DW_AT_main_subprogram
+DW_AT_name
+DW_AT_producer
+DW_AT_ranges
+DW_AT_segment
+DW_AT_sibling
+DW_AT_stmt_list
+DW_AT_use_UTF8
+DW_AT_entry_pc
+0xffffffff
+DW_TAG_condition
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_name
+DW_AT_sibling
+0xffffffff
+DW_TAG_const_type
+DW_AT_allocated
+DW_AT_associated
+DW_AT_data_location
+DW_AT_name
+DW_AT_sibling
+DW_AT_type
+0xffffffff
+DW_TAG_constant
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_accessibility
+DW_AT_const_value
+DW_AT_declaration
+DW_AT_description
+DW_AT_endianity
+DW_AT_external
+DW_AT_linkage_name
+DW_AT_name
+DW_AT_sibling
+DW_AT_start_scope
+DW_AT_type
+DW_AT_visibility
+0xffffffff
+DW_TAG_dwarf_procedure
+DW_AT_location
+0xffffffff
+DW_TAG_entry_point
+DW_AT_address_class
+DW_AT_description
+DW_AT_linkage_name
+DW_AT_low_pc
+DW_AT_name
+DW_AT_return_addr
+DW_AT_segment
+DW_AT_sibling
+DW_AT_static_link
+DW_AT_type
+0xffffffff
+DW_TAG_enumeration_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_accessibility
+DW_AT_allocated
+DW_AT_associated
+DW_AT_bit_stride
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 */
+DW_AT_byte_stride
+DW_AT_data_location
+DW_AT_declaration
+DW_AT_description
+DW_AT_enum_class
+DW_AT_name
+DW_AT_sibling
+DW_AT_signature
+DW_AT_specification
+DW_AT_start_scope
+DW_AT_type
+DW_AT_visibility
+0xffffffff
+DW_TAG_enumerator
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_const_value
+DW_AT_description
+DW_AT_name
+DW_AT_sibling
+0xffffffff
+DW_TAG_file_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_allocated
+DW_AT_associated
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 */
+DW_AT_data_location
+DW_AT_description
+DW_AT_name
+DW_AT_sibling
+DW_AT_start_scope
+DW_AT_type
+DW_AT_visibility
+0xffffffff
+DW_TAG_formal_parameter
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_artificial
+DW_AT_const_value
+DW_AT_default_value
+DW_AT_description
+DW_AT_endianity
+DW_AT_is_optional
+DW_AT_location
+DW_AT_name
+DW_AT_segment
+DW_AT_sibling
+DW_AT_type
+DW_AT_variable_parameter
+0xffffffff
+DW_TAG_friend
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_friend
+DW_AT_sibling
+0xffffffff
+DW_TAG_imported_declaration
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_accessibility
+DW_AT_description
+DW_AT_import
+DW_AT_name
+DW_AT_sibling
+DW_AT_start_scope
+0xffffffff
+DW_TAG_imported_module
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_import
+DW_AT_sibling
+DW_AT_start_scope
+0xffffffff
+DW_TAG_imported_unit
+DW_AT_import
+0xffffffff
+DW_TAG_inheritance
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_accessibility
+DW_AT_data_member_location
+DW_AT_sibling
+DW_AT_type
+DW_AT_virtuality
+0xffffffff
+DW_TAG_inlined_subroutine
+DW_AT_abstract_origin
+DW_AT_call_column
+DW_AT_call_file
+DW_AT_call_line
+DW_AT_const_expr
+DW_AT_entry_pc
+DW_AT_high_pc
+DW_AT_low_pc
+DW_AT_ranges
+DW_AT_return_addr
+DW_AT_segment
+DW_AT_sibling
+DW_AT_start_scope
+DW_AT_trampoline
+0xffffffff
+DW_TAG_interface_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_accessibility
+DW_AT_description
+DW_AT_name
+DW_AT_sibling
+DW_AT_start_scope
+0xffffffff
+DW_TAG_label
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_description
+DW_AT_low_pc
+DW_AT_name
+DW_AT_segment
+DW_AT_start_scope
+DW_AT_sibling
+0xffffffff
+DW_TAG_lexical_block
+DW_AT_abstract_origin
+DW_AT_description
+DW_AT_high_pc
+DW_AT_low_pc
+DW_AT_name
+DW_AT_ranges
+DW_AT_segment
+DW_AT_sibling
+0xffffffff
+DW_TAG_member
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_accessibility
+DW_AT_bit_offset
+DW_AT_bit_size
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 */
+DW_AT_data_bit_offset
+DW_AT_data_member_location
+DW_AT_declaration
+DW_AT_description
+DW_AT_mutable
+DW_AT_name
+DW_AT_sibling
+DW_AT_type
+DW_AT_visibility
+DW_AT_artificial
+0xffffffff
+DW_TAG_module
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_accessibility
+DW_AT_declaration
+DW_AT_description
+DW_AT_entry_pc
+DW_AT_high_pc
+DW_AT_low_pc
+DW_AT_name
+DW_AT_priority
+DW_AT_segment
+DW_AT_sibling
+DW_AT_specification
+DW_AT_visibility
+0xffffffff
+DW_TAG_namelist
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_accessibility
+DW_AT_abstract_origin
+DW_AT_declaration
+DW_AT_name
+DW_AT_sibling
+DW_AT_visibility
+0xffffffff
+DW_TAG_namelist_item
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_namelist_item
+DW_AT_sibling
+0xffffffff
+DW_TAG_namespace
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_description
+DW_AT_extension
+DW_AT_name
+DW_AT_sibling
+DW_AT_start_scope
+0xffffffff
+DW_TAG_packed_type
+DW_AT_allocated
+DW_AT_associated
+DW_AT_data_location
+DW_AT_name
+DW_AT_sibling
+DW_AT_type
+0xffffffff
+DW_TAG_partial_unit
+DW_AT_base_types
+DW_AT_comp_dir
+DW_AT_description
+DW_AT_identifier_case
+DW_AT_high_pc
+DW_AT_language
+DW_AT_low_pc
+DW_AT_macro_info
+DW_AT_main_subprogram
+DW_AT_name
+DW_AT_producer
+DW_AT_ranges
+DW_AT_segment
+DW_AT_sibling
+DW_AT_stmt_list
+DW_AT_use_UTF8
+0xffffffff
+DW_TAG_pointer_type
+DW_AT_address_class
+DW_AT_allocated
+DW_AT_associated
+DW_AT_data_location
+DW_AT_name
+DW_AT_sibling
+DW_AT_specification
+DW_AT_type
+/* Comment from 1993:
+ "Though DWARF spec doesn't refer to DW_AT_byte_size, it may well be
+ given to DW_TAG_pointer_type."
+ Comment 31 January 2009:
+ Discussed in the dwarf-workgroup mailing list Jan 5 2009, that
+ DW_AT_byte_size is allowed.
+*/
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 (if DW_AT_byte_size allowed) */
+0xffffffff
+DW_TAG_ptr_to_member_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_address_class
+DW_AT_allocated
+DW_AT_associated
+DW_AT_containing_type
+DW_AT_data_location
+DW_AT_declaration
+DW_AT_description
+DW_AT_name
+DW_AT_sibling
+DW_AT_type
+DW_AT_use_location
+DW_AT_visibility
+0xffffffff
+DW_TAG_rvalue_reference_type
+DW_AT_address_class
+DW_AT_allocated
+DW_AT_associated
+DW_AT_data_location
+DW_AT_name
+DW_AT_sibling
+DW_AT_type
+0xffffffff
+DW_TAG_reference_type
+DW_AT_address_class
+DW_AT_allocated
+DW_AT_associated
+DW_AT_data_location
+DW_AT_name
+DW_AT_sibling
+DW_AT_type
+/* Comment from 1993:
+ "Though DWARF spec doesn't refer to DW_AT_byte_size, it may well be
+ given to DW_TAG_pointer_type."
+ Comment 31 January 2009:
+ Discussed in the dwarf-workgroup mailing list Jan 5 2009, that
+ DW_AT_byte_size is allowed.
+*/
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 */
+0xffffffff
+DW_TAG_template_alias
+DW_AT_abstract_origin
+DW_AT_accessibility
+DW_AT_allocated
+DW_AT_associated
+DW_AT_data_location
+DW_AT_declaration
+DW_AT_description
+DW_AT_name
+DW_AT_sibling
+DW_AT_signature
+DW_AT_start_scope
+DW_AT_type
+DW_AT_visibility
+0xffffffff
+DW_TAG_restrict_type
+DW_AT_allocated
+DW_AT_associated
+DW_AT_data_location
+DW_AT_name
+DW_AT_sibling
+DW_AT_type
+0xffffffff
+DW_TAG_set_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_accessibility
+DW_AT_allocated
+DW_AT_associated
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 */
+DW_AT_data_location
+DW_AT_declaration
+DW_AT_description
+DW_AT_name
+DW_AT_start_scope
+DW_AT_sibling
+DW_AT_type
+DW_AT_visibility
+0xffffffff
+DW_TAG_shared_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_count
+DW_AT_name
+DW_AT_sibling
+DW_AT_type
+0xffffffff
+DW_TAG_string_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_accessibility
+DW_AT_allocated
+DW_AT_associated
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 */
+DW_AT_data_location
+DW_AT_declaration
+DW_AT_description
+DW_AT_name
+DW_AT_segment
+DW_AT_sibling
+DW_AT_start_scope
+DW_AT_string_length
+DW_AT_visibility
+0xffffffff
+DW_TAG_structure_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_accessibility
+DW_AT_allocated
+DW_AT_associated
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 */
+DW_AT_containing_type
+DW_AT_data_location
+DW_AT_declaration
+DW_AT_description
+DW_AT_name
+DW_AT_sibling
+DW_AT_signature
+DW_AT_specification
+DW_AT_start_scope
+DW_AT_visibility
+0xffffffff
+DW_TAG_subprogram
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_accessibility
+DW_AT_address_class
+DW_AT_artificial
+DW_AT_calling_convention
+DW_AT_containing_type
+DW_AT_declaration
+DW_AT_description
+DW_AT_elemental
+DW_AT_entry_pc
+DW_AT_explicit
+DW_AT_external
+DW_AT_frame_base
+DW_AT_high_pc
+DW_AT_inline
+DW_AT_linkage_name
+DW_AT_low_pc
+DW_AT_main_subprogram
+DW_AT_name
+DW_AT_object_pointer
+DW_AT_prototyped
+DW_AT_pure
+DW_AT_ranges
+DW_AT_recursive
+DW_AT_return_addr
+DW_AT_segment
+DW_AT_sibling
+DW_AT_specification
+DW_AT_start_scope
+DW_AT_static_link
+DW_AT_trampoline
+DW_AT_type
+DW_AT_visibility
+DW_AT_virtuality
+DW_AT_vtable_elem_location
+0xffffffff
+DW_TAG_subrange_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_accessibility
+DW_AT_allocated
+DW_AT_associated
+DW_AT_bit_stride
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 */
+DW_AT_byte_stride
+DW_AT_count
+DW_AT_data_location
+DW_AT_declaration
+DW_AT_description
+DW_AT_lower_bound
+DW_AT_name
+DW_AT_sibling
+DW_AT_threads_scaled
+DW_AT_type
+DW_AT_upper_bound
+DW_AT_visibility
+0xffffffff
+DW_TAG_subroutine_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_accessibility
+DW_AT_address_class
+DW_AT_allocated
+DW_AT_associated
+DW_AT_data_location
+DW_AT_declaration
+DW_AT_description
+DW_AT_name
+DW_AT_prototyped
+DW_AT_sibling
+DW_AT_start_scope
+DW_AT_type
+DW_AT_visibility
+0xffffffff
+DW_TAG_template_type_parameter
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_description
+DW_AT_name
+DW_AT_sibling
+DW_AT_type
+0xffffffff
+DW_TAG_template_value_parameter
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_const_value
+DW_AT_description
+DW_AT_name
+DW_AT_sibling
+DW_AT_type
+0xffffffff
+DW_TAG_thrown_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_allocated
+DW_AT_associated
+DW_AT_data_location
+DW_AT_sibling
+DW_AT_type
+0xffffffff
+DW_TAG_try_block
+DW_AT_abstract_origin
+DW_AT_high_pc
+DW_AT_low_pc
+DW_AT_ranges
+DW_AT_segment
+DW_AT_sibling
+0xffffffff
+DW_TAG_typedef
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_accessibility
+DW_AT_allocated
+DW_AT_associated
+DW_AT_data_location
+DW_AT_declaration
+DW_AT_description
+DW_AT_name
+DW_AT_sibling
+DW_AT_start_scope
+DW_AT_type
+DW_AT_visibility
+0xffffffff
+DW_TAG_union_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_accessibility
+DW_AT_allocated
+DW_AT_associated
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 */
+DW_AT_data_location
+DW_AT_declaration
+DW_AT_description
+DW_AT_name
+DW_AT_sibling
+DW_AT_signature
+DW_AT_specification
+DW_AT_start_scope
+DW_AT_visibility
+0xffffffff
+DW_TAG_unspecified_parameters
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_artificial
+DW_AT_sibling
+0xffffffff
+DW_TAG_unspecified_type
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_description
+DW_AT_sibling
+0xffffffff
+DW_TAG_variable
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_abstract_origin
+DW_AT_accessibility
+DW_AT_byte_size
+DW_AT_bit_size /* Allowed in DWARF4 */
+DW_AT_const_expr
+DW_AT_const_value
+DW_AT_declaration
+DW_AT_description
+DW_AT_endianity
+DW_AT_external
+DW_AT_linkage_name
+DW_AT_location
+DW_AT_name
+DW_AT_segment
+DW_AT_sibling
+DW_AT_specification
+DW_AT_start_scope
+DW_AT_type
+DW_AT_visibility
+DW_AT_artificial
+0xffffffff
+DW_TAG_variant
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_accessibility
+DW_AT_abstract_origin
+DW_AT_declaration
+DW_AT_discr_list
+DW_AT_discr_value
+DW_AT_sibling
+0xffffffff
+DW_TAG_variant_part
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_accessibility
+DW_AT_abstract_origin
+DW_AT_declaration
+DW_AT_discr
+DW_AT_sibling
+DW_AT_type
+0xffffffff
+DW_TAG_volatile_type
+DW_AT_allocated
+DW_AT_associated
+DW_AT_data_location
+DW_AT_name
+DW_AT_sibling
+DW_AT_type
+0xffffffff
+DW_TAG_with_stmt
+DW_AT_accessibility
+DW_AT_address_class
+DW_AT_declaration
+DW_AT_high_pc
+DW_AT_location
+DW_AT_low_pc
+DW_AT_ranges
+DW_AT_segment
+DW_AT_sibling
+DW_AT_type
+DW_AT_visibility
+0xffffffff
+DW_TAG_type_unit
+DW_AT_language
+0xffffffff
+
diff --git a/dwarfdump2/tag_attr_ext.list b/dwarfdump2/tag_attr_ext.list
new file mode 100644
index 0000000..ce6d8b0
--- /dev/null
+++ b/dwarfdump2/tag_attr_ext.list
@@ -0,0 +1,78 @@
+/*
+ Copyright (C) 2000-2010 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2008-2010 SN Systems Ltd. All Rights Reserved.
+ Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+ $Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/tag_attr.list,v 1.7 2005/12/01 17:34:59 davea Exp $
+*/
+#include <dwarf.h>
+
+/* list for semantic check of tag-attr relation.
+ See tag_attr.list for details.
+*/
+
+/* Common DWARF extensions */
+
+0xffffffff
+DW_TAG_member
+DW_AT_GNU_guarded_by /* gcc.gnu.org/wiki/ThreadSafetyAnnotationsInDWARF */
+DW_AT_GNU_pt_guarded_by /* gcc.gnu.org/wiki/ThreadSafetyAnnotationsInDWARF */
+DW_AT_GNU_guarded /* gcc.gnu.org/wiki/ThreadSafetyAnnotationsInDWARF */
+DW_AT_GNU_pt_guarded /* gcc.gnu.org/wiki/ThreadSafetyAnnotationsInDWARF */
+0xffffffff
+DW_TAG_array_type
+DW_AT_GNU_vector
+0xffffffff
+DW_TAG_subprogram
+DW_AT_MIPS_linkage_name /* Used by GNU, SGI-IRIX, and others. */
+DW_AT_MIPS_fde /* SGI-IRIX uses this */
+DW_AT_GNU_locks_excluded /* gcc.gnu.org/wiki/ThreadSafetyAnnotationsInDWARF */
+DW_AT_GNU_exclusive_locks_required
+DW_AT_GNU_shared_locks_required
+0xffffffff
+DW_TAG_variable
+DW_AT_MIPS_linkage_name /* Used by GNU, SGI-IRIX, and others. */
+DW_AT_GNU_guarded_by
+DW_AT_GNU_pt_guarded_by
+DW_AT_GNU_guarded
+DW_AT_GNU_pt_guarded
+0xffffffff
+DW_TAG_GNU_template_template_parameter
+DW_AT_decl_column
+DW_AT_decl_file
+DW_AT_decl_line
+DW_AT_name
+DW_AT_GNU_template_name
+DW_AT_GNU_guarded_by /* GNU changed the name of 0x2108! */
+0xffffffff
+
diff --git a/dwarfdump2/tag_common.cc b/dwarfdump2/tag_common.cc
new file mode 100644
index 0000000..6cdc738
--- /dev/null
+++ b/dwarfdump2/tag_common.cc
@@ -0,0 +1,150 @@
+/*
+ Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2009-2010 SN Systems Ltd. All Rights Reserved.
+ Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/tag_common.c,v 1.8 2008/01/23 09:47:59 davea Exp $ */
+
+#include <dwarf.h>
+#include <stdio.h>
+#include <stdlib.h> /* For exit() declaration etc. */
+#include <errno.h> /* For errno declaration. */
+#include <ctype.h> /* For isspace() declaration */
+#include <string>
+#include <iostream>
+
+#include "globals.h"
+#include "naming.h"
+#include "tag_common.h"
+using std::string;
+using std::cout;
+using std::cerr;
+using std::endl;
+
+static int linecount = 0;
+static char line_in[MAX_LINE_SIZE];
+
+
+void
+bad_line_input(const std::string &msg)
+{
+ cerr << "tag_(tree,attr) table build failed " <<
+ msg << ", line "<< linecount << ": \"" << line_in << "\"" <<
+ endl;
+ exit(FAILED);
+}
+
+void
+trim_newline(char *line, int max)
+{
+ char *end = line + max - 1;
+ for (; *line && (line < end); ++line) {
+ if (*line == '\n') {
+ /* Found newline, drop it */
+ *line = 0;
+ return;
+ }
+ }
+ return;
+}
+
+/* Detect empty lines (and other lines we do not want to read) */
+bool
+is_skippable_line(char *pLine)
+{
+ bool empty = true;
+
+ if(pLine[0] == '#') {
+ // Preprocessor lines are of no interest.
+ return true;
+ }
+ if (pLine[0] == '}') {
+ // The } is from an 'extern "C"' and not interesting.
+ return true;
+ }
+ if(strncmp(&pLine[0],"extern \"C\"",10) == 0) {
+ // It is an 'extern "C"' and not interesting.
+ return true;
+ }
+ for (; *pLine && empty; ++pLine) {
+ empty = isspace(*pLine);
+ }
+ return empty;
+}
+
+/* Reads a value from the text table.
+ Exits with non-zero status
+ if the table is erroneous in some way.
+*/
+int
+read_value(unsigned int *outval, FILE*file)
+{
+ char *res = 0;
+ unsigned long lval;
+ char *strout = 0;
+ bool bBlankLine = true;
+
+ ++linecount;
+ *outval = 0;
+
+ while (bBlankLine) {
+ res = fgets(line_in, sizeof(line_in), file);
+ if (res == 0) {
+ if (ferror(file)) {
+ cerr << "tag_attr: Error reading table, " <<
+ linecount << " lines read" << endl;
+ exit(FAILED);
+ }
+ if (feof(file)) {
+ return IS_EOF;
+ }
+ /* impossible */
+ cerr << "tag_attr: Impossible error reading table, " <<
+ linecount << " lines read" << endl;
+ exit(FAILED);
+ }
+ bBlankLine = is_skippable_line(line_in);
+ }
+ trim_newline(line_in, sizeof(line_in));
+ errno = 0;
+ lval = strtoul(line_in, &strout, 0);
+
+ if (strout == line_in) {
+ bad_line_input("bad number input!");
+ }
+ if (errno != 0) {
+ int myerr = errno;
+ cerr << "tag_attr errno " << myerr << endl;
+ bad_line_input("invalid number on line");
+ }
+ *outval = (int) lval;
+ return NOT_EOF;
+}
diff --git a/dwarfdump2/tag_common.h b/dwarfdump2/tag_common.h
new file mode 100644
index 0000000..d7e6d99
--- /dev/null
+++ b/dwarfdump2/tag_common.h
@@ -0,0 +1,125 @@
+/*
+ Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2009-2010 SN Systems Ltd. All Rights Reserved.
+ Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/tag_common.h,v 1.8 2008/01/23 09:47:59 davea Exp $ */
+
+#ifndef tag_common_INCLUDED
+#define tag_common_INCLUDED
+
+
+
+/* The following is the magic token used to
+ distinguish real tags/attrs from group-delimiters.
+ Blank lines have been eliminated by an awk script.
+*/
+#define MAGIC_TOKEN_VALUE 0xffffffff
+
+/* TAG_TREE.LIST Expected input format
+
+0xffffffff
+value of a tag
+value of a standard tag that may be a child of that tag
+...
+0xffffffff
+value of a tag
+value of a standard tag that may be a child of that tag
+...
+0xffffffff
+...
+
+No blank lines or commentary allowed, no symbols, just numbers.
+
+*/
+
+/* TAG_ATTR.LIST Expected input format
+
+0xffffffff
+value of a tag
+value of a standard attribute that follows that tag
+...
+0xffffffff
+value of a tag
+value of a standard attribute that follows that tag
+...
+0xffffffff
+...
+
+No blank lines or commentary allowed, no symbols, just numbers.
+
+*/
+
+/* We don't need really long lines: the input file is simple. */
+#define MAX_LINE_SIZE 1000
+
+/* 1 more than the highest number in the DW_TAG defines,
+ this is for standard TAGs. Number of rows. */
+#define STD_TAG_TABLE_ROWS 0x44
+/* Enough entries to have a bit for each standard legal tag. */
+#define STD_TAG_TABLE_COLUMNS 7
+
+/* TAG tree common extension maximums. */
+#define EXT_TAG_TABLE_ROWS 7
+#define EXT_TAG_TABLE_COLS 7
+
+/* The following 2 used in tag_tree.c only. */
+#define TAG_TABLE_ROW_MAXIMUM STD_TAG_TABLE_ROWS
+#define TAG_TABLE_COLUMN_MAXIMUM EXT_TAG_TABLE_COLS
+
+
+
+/* Number of attributes columns per tag. The array is bit fields,
+ BITS_PER_WORD fields per word. Dense and quick to inspect */
+#define COUNT_ATTRIBUTE_STD 7
+
+#define STD_ATTR_TABLE_ROWS STD_TAG_TABLE_ROWS
+#define STD_ATTR_TABLE_COLUMNS 7
+/* tag/attr tree common extension maximums. */
+#define EXT_ATTR_TABLE_ROWS 7
+#define EXT_ATTR_TABLE_COLS 7
+
+/* The following 2 used in tag_attr.c only. */
+#define ATTR_TABLE_ROW_MAXIMUM STD_ATTR_TABLE_ROWS
+#define ATTR_TABLE_COLUMN_MAXIMUM EXT_ATTR_TABLE_COLS
+
+/* Bits per 'int' to mark legal attrs. */
+#define BITS_PER_WORD 32
+
+#define IS_EOF 1
+#define NOT_EOF 0
+
+extern void bad_line_input(const std::string &msg);
+extern void trim_newline(std::string &line, int max);
+extern bool is_blank_line(const std::string &pLine);
+extern int read_value(unsigned int *outval,FILE *f);
+
+#endif /* tag_common_INCLUDED */
diff --git a/dwarfdump2/tag_tree.cc b/dwarfdump2/tag_tree.cc
new file mode 100644
index 0000000..93ea464
--- /dev/null
+++ b/dwarfdump2/tag_tree.cc
@@ -0,0 +1,282 @@
+/*
+ Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2009-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/tag_tree.c,v 1.8 2005/12/01 17:34:59 davea Exp $ */
+#include <dwarf.h>
+#include <stdio.h>
+#include <stdlib.h> /* For exit() declaration etc. */
+#include <errno.h> /* For errno declaration. */
+#include <unistd.h> /* For getopt. */
+
+#include "globals.h"
+#include "naming.h"
+#include "common.h"
+#include "tag_common.h"
+using std::cout;
+using std::cerr;
+using std::endl;
+using std::string;
+
+unsigned int tag_tree_combination_table[TAG_TABLE_ROW_MAXIMUM][TAG_TABLE_COLUMN_MAXIMUM];
+
+bool ellipsis = false; /* So we can use dwarf_names.c */
+
+/* Expected input format
+
+0xffffffff
+value of a tag
+value of a standard tag that may be a child ofthat tag
+...
+0xffffffff
+value of a tag
+value of a standard tag that may be a child ofthat tag
+...
+0xffffffff
+...
+
+No commentary allowed, no symbols, just numbers.
+Blank lines are allowed and are dropped.
+
+*/
+
+static const char *usage[] = {
+ "Usage: tag_tree_build <options>\n",
+ "options:\t-t\tGenerate Tags table\n",
+ " -i Input-file-path\n",
+ " -o Output-table-path\n",
+ " -e (Want Extended table (common extensions))\n",
+ " -s (Want Standard table)\n",
+ ""
+};
+
+static std::string input_name;
+static std::string output_name;
+bool extended_flag = false;
+bool standard_flag = false;
+
+static void
+process_args(int argc, char *argv[])
+{
+ int c = 0;
+ bool usage_error = false;
+
+ while ((c = getopt(argc, argv, "i:o:es")) != EOF) {
+ switch (c) {
+ case 'i':
+ input_name = optarg;
+ break;
+ case 'o':
+ output_name = optarg;
+ break;
+ case 'e':
+ extended_flag = true;
+ break;
+ case 's':
+ standard_flag = true;
+ break;
+ default:
+ usage_error = true;
+ break;
+ }
+ }
+
+ if (usage_error || 1 == optind || optind != argc) {
+ print_usage_message(argv[0],usage);
+ exit(FAILED);
+ }
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+
+
+ print_version_details(argv[0],false);
+ process_args(argc,argv);
+ print_args(argc,argv);
+
+ if (input_name.empty() ) {
+ cerr << "Input name required, not supplied." << endl;
+ print_usage_message(argv[0],usage);
+ exit(FAILED);
+ }
+ FILE *fileInp = fopen(input_name.c_str(),"r");
+ if (!fileInp) {
+ cerr << "Invalid input filename, could not open '" <<
+ input_name << "'" << endl;
+ print_usage_message(argv[0],usage);
+ exit(FAILED);
+ }
+
+
+ if (output_name.empty() ) {
+ cerr << "Output name required, not supplied." << endl;
+ print_usage_message(argv[0],usage);
+ exit(FAILED);
+ }
+ FILE *fileOut = fopen(output_name.c_str(),"w");
+ if (!fileOut) {
+ cerr << "Invalid output filename, could not open: '" <<
+ output_name << "'" << endl;
+ print_usage_message(argv[0],usage);
+ exit(FAILED);
+ }
+ if ((standard_flag && extended_flag) || (!standard_flag && !extended_flag)) {
+ cerr <<"Invalid table type" << endl;
+ cerr << "Choose -e or -s ." << endl;
+ print_usage_message(argv[0],usage);
+ exit(FAILED);
+ }
+ unsigned int table_rows = 0;
+ unsigned int table_columns = 0;
+ if(standard_flag) {
+ table_rows = STD_TAG_TABLE_ROWS;
+ table_columns = STD_TAG_TABLE_COLUMNS;
+ } else {
+ table_rows = EXT_TAG_TABLE_ROWS;
+ table_columns = EXT_TAG_TABLE_COLS;
+ }
+
+ unsigned int num = 0;
+ int input_eof = read_value(&num,fileInp); /* 0xffffffff */
+ if (IS_EOF == input_eof) {
+ bad_line_input("Empty input file");
+ }
+ if (num != MAGIC_TOKEN_VALUE) {
+ bad_line_input("Expected 0xffffffff");
+ }
+
+ unsigned int current_row = 0;
+ while (!feof(stdin)) {
+ unsigned int tag = 0;
+ unsigned int nTagLoc = 0;
+
+ input_eof = read_value(&tag,fileInp);
+ if (IS_EOF == input_eof) {
+ /* Reached normal eof */
+ break;
+ }
+ if(standard_flag) {
+ if (tag >= table_rows ) {
+ bad_line_input("tag value exceeds standard table size");
+ }
+ } else {
+ if(current_row >= table_rows) {
+ bad_line_input("too many extended table rows.");
+ }
+ tag_tree_combination_table[current_row][0] = tag;
+ }
+ input_eof = read_value(&num,fileInp);
+ if (IS_EOF == input_eof) {
+ bad_line_input("Not terminated correctly..");
+ }
+ nTagLoc = 1;
+ while (num != 0xffffffff) {
+ if(standard_flag) {
+ unsigned idx = num / BITS_PER_WORD;
+ unsigned bit = num % BITS_PER_WORD;
+
+ if (idx >= table_columns) {
+ cout << "Want column " << idx << ", have only " <<
+ table_columns << endl;
+ bad_line_input("too many TAGs: table incomplete.");
+ }
+ tag_tree_combination_table[tag][idx] |= (1 << bit);
+ } else {
+ if(nTagLoc >= table_columns) {
+ cout << "Attempting to use column " << nTagLoc <<
+ ", max is " << table_columns << endl;
+ bad_line_input("too many subTAGs, table incomplete.");
+ }
+ tag_tree_combination_table[current_row][nTagLoc] = num;
+ nTagLoc++;
+ }
+ input_eof = read_value(&num,fileInp);
+ if (IS_EOF == input_eof) {
+ bad_line_input("Not terminated correctly.");
+ }
+ }
+ ++current_row; /* for extended table */
+ }
+ fprintf(fileOut,"/* Generated code, do not edit. */\n");
+ fprintf(fileOut,"/* Generated on %s %s */\n",__DATE__,__TIME__);
+ if (standard_flag) {
+ fprintf(fileOut,"#define TAG_TREE_COLUMN_COUNT %d\n\n",table_columns);
+ fprintf(fileOut,"#define TAG_TREE_ROW_COUNT %d\n\n",table_rows);
+ fprintf(fileOut,
+ "static unsigned int tag_tree_combination_table"
+ "[TAG_TREE_ROW_COUNT][TAG_TREE_COLUMN_COUNT] = {\n");
+ } else {
+ fprintf(fileOut,"#define TAG_TREE_EXT_COLUMN_COUNT %d\n\n",
+ table_columns);
+ fprintf(fileOut,"#define TAG_TREE_EXT_ROW_COUNT %d\n\n",table_rows);
+ fprintf(fileOut,"/* Common extensions */\n");
+ fprintf(fileOut,
+ "static unsigned int tag_tree_combination_ext_table"
+ "[TAG_TREE_EXT_ROW_COUNT][TAG_TREE_EXT_COLUMN_COUNT] = {\n");
+ }
+
+ for (unsigned i = 0; i < table_rows; i++) {
+ bool printonerr=false;
+ if (standard_flag) {
+ fprintf(fileOut,"/* %d %-37s*/\n",i,
+ get_TAG_name(i,printonerr).c_str());
+ } else {
+ fprintf(fileOut,"/* %u %-37s*/\n",
+ tag_tree_combination_table[i][0],
+ get_TAG_name(
+ tag_tree_combination_table[i][0],printonerr).c_str());
+ }
+ fprintf(fileOut," { ");
+ for(unsigned j = 0; j < table_columns; ++j ) {
+ fprintf(fileOut,"0x%08x,",tag_tree_combination_table[i][j]);
+ }
+ fprintf(fileOut,"},\n");
+
+ }
+ fprintf(fileOut,"\n#define MAX_CHECKED_TAG_ID 0x%2x\n",STD_TAG_TABLE_ROWS);
+ fprintf(fileOut,"};\n");
+ fclose(fileInp);
+ fclose(fileOut);
+ return (0);
+}
+
+/* A fake so we can use dwarf_names.c */
+void print_error (Dwarf_Debug dbg, const string& msg,int res, Dwarf_Error err)
+{
+}
+
diff --git a/dwarfdump2/tag_tree.list b/dwarfdump2/tag_tree.list
new file mode 100644
index 0000000..ebad794
--- /dev/null
+++ b/dwarfdump2/tag_tree.list
@@ -0,0 +1,486 @@
+/*
+ Copyright (C) 2000-2010 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+ $Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/tag_tree.list,v 1.6 2005/12/01 17:34:59 davea Exp $
+*/
+#include <dwarf.h>
+
+/*
+ list for semantic check of tag-tree.
+
+ 0xffffffff is a "punctuation." The final line of this file
+ must be 0xffffffff. The next line after each 0xffffffff
+ (except the final line) stands for "parent-tag." The lines
+ after this line before the next 0xffffffff are the tags that
+ can be children of the "parent-tag."
+
+ For example,
+
+ 0xffffffff
+ DW_TAG_array_type
+ DW_TAG_subrange_type
+ DW_TAG_enumeration_type
+ 0xffffffff
+
+ means "only DW_TAG_subrange_type and DW_TAG_enumeration_type can
+ be children of DW_TAG_array_type.
+
+ This file is applied to the preprocessor, thus any C comment and
+ preprocessor control line is available.
+*/
+
+0xffffffff
+DW_TAG_access_declaration
+0xffffffff
+DW_TAG_array_type
+DW_TAG_subrange_type
+DW_TAG_enumeration_type
+0xffffffff
+DW_TAG_base_type
+0xffffffff
+DW_TAG_catch_block
+DW_TAG_formal_parameter
+DW_TAG_unspecified_parameters
+DW_TAG_array_type
+DW_TAG_class_type
+DW_TAG_enumeration_type
+DW_TAG_pointer_type
+DW_TAG_reference_type
+DW_TAG_string_type
+DW_TAG_structure_type
+DW_TAG_subroutine_type
+DW_TAG_typedef
+DW_TAG_union_type
+DW_TAG_ptr_to_member_type
+DW_TAG_set_type
+DW_TAG_subrange_type
+DW_TAG_base_type
+DW_TAG_const_type
+DW_TAG_constant
+DW_TAG_file_type
+DW_TAG_packed_type
+DW_TAG_subprogram
+DW_TAG_variable
+DW_TAG_volatile_type
+0xffffffff
+DW_TAG_class_type
+DW_TAG_member
+DW_TAG_inheritance
+DW_TAG_access_declaration
+DW_TAG_friend
+DW_TAG_ptr_to_member_type
+DW_TAG_subprogram
+DW_TAG_template_type_parameter /* template instantiations */
+DW_TAG_template_value_parameter /* template instantiations */
+DW_TAG_typedef
+DW_TAG_base_type
+DW_TAG_pointer_type
+DW_TAG_union_type
+DW_TAG_const_type
+DW_TAG_class_type /* Nested classes */
+DW_TAG_structure_type /* Nested structures */
+DW_TAG_enumeration_type /* Nested enums */
+DW_TAG_imported_declaration
+DW_TAG_template_alias /* C++ 2010 template alias */
+0xffffffff
+DW_TAG_common_block
+DW_TAG_variable
+0xffffffff
+DW_TAG_common_inclusion
+0xffffffff
+DW_TAG_compile_unit
+DW_TAG_array_type
+DW_TAG_class_type
+DW_TAG_enumeration_type
+DW_TAG_imported_declaration
+DW_TAG_pointer_type
+DW_TAG_reference_type
+DW_TAG_string_type
+DW_TAG_structure_type
+DW_TAG_subroutine_type
+DW_TAG_typedef
+DW_TAG_union_type
+DW_TAG_common_block
+DW_TAG_inlined_subroutine
+DW_TAG_module
+DW_TAG_ptr_to_member_type
+DW_TAG_set_type
+DW_TAG_subrange_type
+DW_TAG_base_type
+DW_TAG_const_type
+DW_TAG_constant
+DW_TAG_file_type
+DW_TAG_namelist
+DW_TAG_namespace
+DW_TAG_packed_type
+DW_TAG_subprogram
+DW_TAG_variable
+DW_TAG_volatile_type
+DW_TAG_imported_module
+DW_TAG_template_alias /* C++ 2010 template alias */
+0xffffffff
+DW_TAG_type_unit
+DW_TAG_array_type
+DW_TAG_class_type
+DW_TAG_enumeration_type
+DW_TAG_imported_declaration
+DW_TAG_pointer_type
+DW_TAG_reference_type
+DW_TAG_string_type
+DW_TAG_structure_type
+DW_TAG_subroutine_type
+DW_TAG_typedef
+DW_TAG_union_type
+DW_TAG_common_block
+DW_TAG_inlined_subroutine
+DW_TAG_module
+DW_TAG_ptr_to_member_type
+DW_TAG_set_type
+DW_TAG_subrange_type
+DW_TAG_base_type
+DW_TAG_const_type
+DW_TAG_constant
+DW_TAG_file_type
+DW_TAG_namelist
+DW_TAG_namespace
+DW_TAG_packed_type
+DW_TAG_subprogram
+DW_TAG_variable
+DW_TAG_volatile_type
+DW_TAG_imported_module
+DW_TAG_template_alias /* C++ 2010 template alias */
+0xffffffff
+DW_TAG_condition /* COBOL */
+DW_TAG_constant
+DW_TAG_subrange_type
+0xffffffff
+DW_TAG_const_type
+0xffffffff
+DW_TAG_constant
+0xffffffff
+DW_TAG_dwarf_procedure
+0xffffffff
+DW_TAG_entry_point
+DW_TAG_formal_parameter
+DW_TAG_unspecified_parameters
+DW_TAG_common_inclusion
+0xffffffff
+DW_TAG_enumeration_type
+DW_TAG_enumerator
+0xffffffff
+DW_TAG_enumerator
+0xffffffff
+DW_TAG_file_type
+0xffffffff
+DW_TAG_formal_parameter
+0xffffffff
+DW_TAG_friend
+0xffffffff
+DW_TAG_imported_declaration
+0xffffffff
+DW_TAG_imported_module
+0xffffffff
+DW_TAG_imported_unit
+0xffffffff
+DW_TAG_inheritance
+0xffffffff
+DW_TAG_inlined_subroutine
+DW_TAG_formal_parameter
+DW_TAG_unspecified_parameters
+DW_TAG_array_type
+DW_TAG_class_type
+DW_TAG_enumeration_type
+DW_TAG_pointer_type
+DW_TAG_reference_type
+DW_TAG_string_type
+DW_TAG_structure_type
+DW_TAG_subroutine_type
+DW_TAG_lexical_block
+DW_TAG_typedef
+DW_TAG_union_type
+DW_TAG_inlined_subroutine
+DW_TAG_ptr_to_member_type
+DW_TAG_set_type
+DW_TAG_subrange_type
+DW_TAG_base_type
+DW_TAG_const_type
+DW_TAG_constant
+DW_TAG_file_type
+DW_TAG_namelist
+DW_TAG_packed_type
+DW_TAG_subprogram
+DW_TAG_variable
+DW_TAG_volatile_type
+0xffffffff
+DW_TAG_interface_type
+DW_TAG_member
+DW_TAG_subprogram
+0xffffffff
+DW_TAG_label
+0xffffffff
+DW_TAG_lexical_block
+DW_TAG_array_type
+DW_TAG_class_type
+DW_TAG_enumeration_type
+DW_TAG_imported_declaration
+DW_TAG_pointer_type
+DW_TAG_reference_type
+DW_TAG_string_type
+DW_TAG_structure_type
+DW_TAG_subroutine_type
+DW_TAG_typedef
+DW_TAG_union_type
+DW_TAG_inlined_subroutine
+DW_TAG_lexical_block
+DW_TAG_module
+DW_TAG_ptr_to_member_type
+DW_TAG_set_type
+DW_TAG_subrange_type
+DW_TAG_base_type
+DW_TAG_const_type
+DW_TAG_constant
+DW_TAG_namelist
+DW_TAG_packed_type
+DW_TAG_subprogram
+DW_TAG_variable
+DW_TAG_volatile_type
+DW_TAG_formal_parameter
+0xffffffff
+DW_TAG_member
+0xffffffff
+DW_TAG_module
+0xffffffff
+DW_TAG_namelist
+DW_TAG_namelist_item
+0xffffffff
+DW_TAG_namelist_item
+0xffffffff
+DW_TAG_namespace
+DW_TAG_array_type
+DW_TAG_class_type
+DW_TAG_enumeration_type
+DW_TAG_imported_declaration
+DW_TAG_pointer_type
+DW_TAG_reference_type
+DW_TAG_string_type
+DW_TAG_structure_type
+DW_TAG_subroutine_type
+DW_TAG_typedef
+DW_TAG_union_type
+DW_TAG_common_block
+DW_TAG_inlined_subroutine
+DW_TAG_module
+DW_TAG_ptr_to_member_type
+DW_TAG_set_type
+DW_TAG_subrange_type
+DW_TAG_base_type
+DW_TAG_const_type
+DW_TAG_constant
+DW_TAG_namelist
+DW_TAG_packed_type
+DW_TAG_subprogram
+DW_TAG_variable
+DW_TAG_volatile_type
+DW_TAG_namespace /* Allow a nested namespace */
+DW_TAG_imported_module /* Allow imported module */
+0xffffffff
+DW_TAG_packed_type
+0xffffffff
+DW_TAG_partial_unit
+DW_TAG_array_type
+DW_TAG_class_type
+DW_TAG_enumeration_type
+DW_TAG_imported_declaration
+DW_TAG_pointer_type
+DW_TAG_reference_type
+DW_TAG_string_type
+DW_TAG_structure_type
+DW_TAG_subroutine_type
+DW_TAG_typedef
+DW_TAG_union_type
+DW_TAG_common_block
+DW_TAG_inlined_subroutine
+DW_TAG_module
+DW_TAG_ptr_to_member_type
+DW_TAG_set_type
+DW_TAG_subrange_type
+DW_TAG_base_type
+DW_TAG_const_type
+DW_TAG_constant
+DW_TAG_file_type
+DW_TAG_namelist
+DW_TAG_packed_type
+DW_TAG_subprogram
+DW_TAG_variable
+DW_TAG_volatile_type
+0xffffffff
+DW_TAG_pointer_type
+DW_TAG_rvalue_reference_type
+DW_TAG_reference_type
+DW_TAG_restrict_type
+DW_TAG_ptr_to_member_type
+0xffffffff
+DW_TAG_ptr_to_member_type
+DW_TAG_rvalue_reference_type
+DW_TAG_reference_type
+DW_TAG_pointer_type
+DW_TAG_restrict_type
+0xffffffff
+DW_TAG_reference_type
+DW_TAG_rvalue_reference_type
+DW_TAG_reference_type
+DW_TAG_pointer_type
+DW_TAG_restrict_type
+DW_TAG_ptr_to_member_type
+0xffffffff
+DW_TAG_rvalue_reference_type
+DW_TAG_pointer_type
+DW_TAG_restrict_type
+DW_TAG_ptr_to_member_type
+DW_TAG_reference_type
+0xffffffff
+DW_TAG_restrict_type
+DW_TAG_pointer_type
+DW_TAG_ptr_to_member_type
+DW_TAG_rvalue_reference_type
+0xffffffff
+DW_TAG_set_type
+0xffffffff
+DW_TAG_shared_type
+0xffffffff
+DW_TAG_string_type
+0xffffffff
+DW_TAG_structure_type
+DW_TAG_member
+DW_TAG_inheritance
+DW_TAG_access_declaration
+DW_TAG_friend
+DW_TAG_ptr_to_member_type
+DW_TAG_variant_part
+DW_TAG_subprogram
+DW_TAG_template_type_parameter /* template instantiations */
+DW_TAG_template_value_parameter /* template instantiations */
+DW_TAG_typedef
+DW_TAG_base_type
+DW_TAG_pointer_type
+DW_TAG_union_type
+DW_TAG_const_type
+DW_TAG_structure_type /* nested structures */
+DW_TAG_enumeration_type /* nested enums */
+DW_TAG_class_type /* nested classes */
+DW_TAG_imported_declaration /* References to namespaces */
+DW_TAG_template_alias /* C++ 2010 template alias */
+0xffffffff
+DW_TAG_subprogram
+DW_TAG_formal_parameter
+DW_TAG_unspecified_parameters
+DW_TAG_thrown_type
+DW_TAG_template_type_parameter
+DW_TAG_template_value_parameter
+DW_TAG_common_inclusion
+DW_TAG_common_block
+DW_TAG_array_type
+DW_TAG_class_type
+DW_TAG_enumeration_type
+DW_TAG_pointer_type
+DW_TAG_reference_type
+DW_TAG_string_type
+DW_TAG_lexical_block
+DW_TAG_structure_type
+DW_TAG_subroutine_type
+DW_TAG_typedef
+DW_TAG_union_type
+DW_TAG_inlined_subroutine
+DW_TAG_ptr_to_member_type
+DW_TAG_set_type
+DW_TAG_subrange_type
+DW_TAG_base_type
+DW_TAG_const_type
+DW_TAG_constant
+DW_TAG_file_type
+DW_TAG_namelist
+DW_TAG_packed_type
+DW_TAG_subprogram
+DW_TAG_variable
+DW_TAG_volatile_type
+DW_TAG_label
+DW_TAG_imported_module /* References to namespaces */
+DW_TAG_imported_declaration /* References to namespaces */
+0xffffffff
+DW_TAG_subrange_type
+0xffffffff
+DW_TAG_subroutine_type
+DW_TAG_formal_parameter
+DW_TAG_unspecified_parameters
+0xffffffff
+DW_TAG_template_type_parameter
+0xffffffff
+DW_TAG_template_value_parameter
+0xffffffff
+DW_TAG_thrown_type
+0xffffffff
+DW_TAG_try_block
+0xffffffff
+DW_TAG_typedef
+0xffffffff
+DW_TAG_union_type
+DW_TAG_friend
+DW_TAG_member
+DW_TAG_class_type /* Nested classes */
+DW_TAG_enumeration_type /* Nested enums */
+DW_TAG_structure_type /* Nested structures */
+DW_TAG_typedef /* Nested typedef */
+DW_TAG_subprogram
+DW_TAG_template_type_parameter /* template instantiations */
+DW_TAG_template_value_parameter /* template instantiations */
+0xffffffff
+DW_TAG_template_alias
+DW_TAG_template_type_parameter
+DW_TAG_template_value_parameter
+0xffffffff
+DW_TAG_unspecified_parameters
+0xffffffff
+DW_TAG_unspecified_type
+0xffffffff
+DW_TAG_variable
+0xffffffff
+DW_TAG_variant
+DW_TAG_variant_part
+0xffffffff
+DW_TAG_variant_part
+0xffffffff
+DW_TAG_volatile_type
+0xffffffff
+DW_TAG_with_stmt
+0xffffffff
diff --git a/dwarfdump2/tag_tree_ext.list b/dwarfdump2/tag_tree_ext.list
new file mode 100644
index 0000000..e671373
--- /dev/null
+++ b/dwarfdump2/tag_tree_ext.list
@@ -0,0 +1,63 @@
+/*
+ Copyright (C) 2000-2010 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved.
+ Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/tag_attr.list,v 1.7 2005/12/01 17:34:59 davea Exp $
+*/
+#include <dwarf.h>
+
+/* list for semantic check of tag-tree relation.
+ See tag_tree.list for details.
+
+*/
+
+/* Common DWARF extensions */
+
+0xffffffff
+DW_TAG_structure_type
+DW_TAG_variable /* GNU gcc usage. */
+0xffffffff
+DW_TAG_class_type
+DW_TAG_variable /* GNU gcc usage. */
+DW_TAG_GNU_template_template_parameter /* template instantiations */
+0xffffffff
+DW_TAG_structure_type
+DW_TAG_GNU_template_template_parameter /* template instantiations */
+0xffffffff
+DW_TAG_subprogram
+DW_TAG_GNU_template_template_parameter /* template instantiations */
+0xffffffff
+DW_TAG_union_type
+DW_TAG_GNU_template_template_parameter /* template instantiations */
+0xffffffff
diff --git a/dwarfdump2/uri.cc b/dwarfdump2/uri.cc
new file mode 100644
index 0000000..545bad7
--- /dev/null
+++ b/dwarfdump2/uri.cc
@@ -0,0 +1,477 @@
+/*
+ Copyright 2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include "globals.h"
+#include <iostream> //* for error and debug output.
+#include <string>
+#include "uri.h"
+#include <stdio.h>
+#include <ctype.h>
+using std::string;
+
+
+/* dwarfdump_ctype table. See dwarfdump/uritablebuild.c */
+static char dwarfdump_ctype_table[256] = {
+0, /* NUL 0x00 */
+0, /* control 0x01 */
+0, /* control 0x02 */
+0, /* control 0x03 */
+0, /* control 0x04 */
+0, /* control 0x05 */
+0, /* control 0x06 */
+0, /* control 0x07 */
+0, /* control 0x08 */
+0, /* whitespace 0x09 */
+0, /* whitespace 0x0a */
+0, /* whitespace 0x0b */
+0, /* whitespace 0x0c */
+0, /* whitespace 0x0d */
+0, /* control 0x0e */
+0, /* control 0x0f */
+0, /* control 0x10 */
+0, /* control 0x11 */
+0, /* control 0x12 */
+0, /* control 0x13 */
+0, /* control 0x14 */
+0, /* control 0x15 */
+0, /* control 0x16 */
+0, /* control 0x17 */
+0, /* control 0x18 */
+0, /* control 0x19 */
+0, /* control 0x1a */
+0, /* control 0x1b */
+0, /* control 0x1c */
+0, /* control 0x1d */
+0, /* control 0x1e */
+0, /* control 0x1f */
+1, /* ' ' 0x20 */
+1, /* '!' 0x21 */
+0, /* '"' 0x22 */
+1, /* '#' 0x23 */
+1, /* '$' 0x24 */
+0, /* '%' 0x25 */
+1, /* '&' 0x26 */
+0, /* ''' 0x27 */
+1, /* '(' 0x28 */
+1, /* ')' 0x29 */
+1, /* '*' 0x2a */
+1, /* '+' 0x2b */
+1, /* ',' 0x2c */
+1, /* '-' 0x2d */
+1, /* '.' 0x2e */
+1, /* '/' 0x2f */
+1, /* '0' 0x30 */
+1, /* '1' 0x31 */
+1, /* '2' 0x32 */
+1, /* '3' 0x33 */
+1, /* '4' 0x34 */
+1, /* '5' 0x35 */
+1, /* '6' 0x36 */
+1, /* '7' 0x37 */
+1, /* '8' 0x38 */
+1, /* '9' 0x39 */
+1, /* ':' 0x3a */
+0, /* ';' 0x3b */
+1, /* '<' 0x3c */
+1, /* '=' 0x3d */
+1, /* '>' 0x3e */
+1, /* '?' 0x3f */
+1, /* '@' 0x40 */
+1, /* 'A' 0x41 */
+1, /* 'B' 0x42 */
+1, /* 'C' 0x43 */
+1, /* 'D' 0x44 */
+1, /* 'E' 0x45 */
+1, /* 'F' 0x46 */
+1, /* 'G' 0x47 */
+1, /* 'H' 0x48 */
+1, /* 'I' 0x49 */
+1, /* 'J' 0x4a */
+1, /* 'K' 0x4b */
+1, /* 'L' 0x4c */
+1, /* 'M' 0x4d */
+1, /* 'N' 0x4e */
+1, /* 'O' 0x4f */
+1, /* 'P' 0x50 */
+1, /* 'Q' 0x51 */
+1, /* 'R' 0x52 */
+1, /* 'S' 0x53 */
+1, /* 'T' 0x54 */
+1, /* 'U' 0x55 */
+1, /* 'V' 0x56 */
+1, /* 'W' 0x57 */
+1, /* 'X' 0x58 */
+1, /* 'Y' 0x59 */
+1, /* 'Z' 0x5a */
+1, /* '[' 0x5b */
+1, /* '\' 0x5c */
+1, /* ']' 0x5d */
+1, /* '^' 0x5e */
+1, /* '_' 0x5f */
+0, /* '`' 0x60 */
+1, /* 'a' 0x61 */
+1, /* 'b' 0x62 */
+1, /* 'c' 0x63 */
+1, /* 'd' 0x64 */
+1, /* 'e' 0x65 */
+1, /* 'f' 0x66 */
+1, /* 'g' 0x67 */
+1, /* 'h' 0x68 */
+1, /* 'i' 0x69 */
+1, /* 'j' 0x6a */
+1, /* 'k' 0x6b */
+1, /* 'l' 0x6c */
+1, /* 'm' 0x6d */
+1, /* 'n' 0x6e */
+1, /* 'o' 0x6f */
+1, /* 'p' 0x70 */
+1, /* 'q' 0x71 */
+1, /* 'r' 0x72 */
+1, /* 's' 0x73 */
+1, /* 't' 0x74 */
+1, /* 'u' 0x75 */
+1, /* 'v' 0x76 */
+1, /* 'w' 0x77 */
+1, /* 'x' 0x78 */
+1, /* 'y' 0x79 */
+1, /* 'z' 0x7a */
+1, /* '{' 0x7b */
+1, /* '|' 0x7c */
+1, /* '}' 0x7d */
+1, /* '~' 0x7e */
+0, /* DEL 0x7f */
+1, /* 0x80 */
+1, /* 0x81 */
+1, /* 0x82 */
+1, /* 0x83 */
+1, /* 0x84 */
+1, /* 0x85 */
+1, /* 0x86 */
+1, /* 0x87 */
+1, /* 0x88 */
+1, /* 0x89 */
+1, /* 0x8a */
+1, /* 0x8b */
+1, /* 0x8c */
+1, /* 0x8d */
+1, /* 0x8e */
+1, /* 0x8f */
+1, /* 0x90 */
+1, /* 0x91 */
+1, /* 0x92 */
+1, /* 0x93 */
+1, /* 0x94 */
+1, /* 0x95 */
+1, /* 0x96 */
+1, /* 0x97 */
+1, /* 0x98 */
+1, /* 0x99 */
+1, /* 0x9a */
+1, /* 0x9b */
+1, /* 0x9c */
+1, /* 0x9d */
+1, /* 0x9e */
+1, /* 0x9f */
+0, /* other: 0xa0 */
+1, /* 0xa1 */
+1, /* 0xa2 */
+1, /* 0xa3 */
+1, /* 0xa4 */
+1, /* 0xa5 */
+1, /* 0xa6 */
+1, /* 0xa7 */
+1, /* 0xa8 */
+1, /* 0xa9 */
+1, /* 0xaa */
+1, /* 0xab */
+1, /* 0xac */
+1, /* 0xad */
+1, /* 0xae */
+1, /* 0xaf */
+1, /* 0xb0 */
+1, /* 0xb1 */
+1, /* 0xb2 */
+1, /* 0xb3 */
+1, /* 0xb4 */
+1, /* 0xb5 */
+1, /* 0xb6 */
+1, /* 0xb7 */
+1, /* 0xb8 */
+1, /* 0xb9 */
+1, /* 0xba */
+1, /* 0xbb */
+1, /* 0xbc */
+1, /* 0xbd */
+1, /* 0xbe */
+1, /* 0xbf */
+1, /* 0xc0 */
+1, /* 0xc1 */
+1, /* 0xc2 */
+1, /* 0xc3 */
+1, /* 0xc4 */
+1, /* 0xc5 */
+1, /* 0xc6 */
+1, /* 0xc7 */
+1, /* 0xc8 */
+1, /* 0xc9 */
+1, /* 0xca */
+1, /* 0xcb */
+1, /* 0xcc */
+1, /* 0xcd */
+1, /* 0xce */
+1, /* 0xcf */
+1, /* 0xd0 */
+1, /* 0xd1 */
+1, /* 0xd2 */
+1, /* 0xd3 */
+1, /* 0xd4 */
+1, /* 0xd5 */
+1, /* 0xd6 */
+1, /* 0xd7 */
+1, /* 0xd8 */
+1, /* 0xd9 */
+1, /* 0xda */
+1, /* 0xdb */
+1, /* 0xdc */
+1, /* 0xdd */
+1, /* 0xde */
+1, /* 0xdf */
+1, /* 0xe0 */
+1, /* 0xe1 */
+1, /* 0xe2 */
+1, /* 0xe3 */
+1, /* 0xe4 */
+1, /* 0xe5 */
+1, /* 0xe6 */
+1, /* 0xe7 */
+1, /* 0xe8 */
+1, /* 0xe9 */
+1, /* 0xea */
+1, /* 0xeb */
+1, /* 0xec */
+1, /* 0xed */
+1, /* 0xee */
+1, /* 0xef */
+1, /* 0xf0 */
+1, /* 0xf1 */
+1, /* 0xf2 */
+1, /* 0xf3 */
+1, /* 0xf4 */
+1, /* 0xf5 */
+1, /* 0xf6 */
+1, /* 0xf7 */
+1, /* 0xf8 */
+1, /* 0xf9 */
+1, /* 0xfa */
+1, /* 0xfb */
+1, /* 0xfc */
+1, /* 0xfd */
+1, /* 0xfe */
+0, /* other: 0xff */
+};
+static char *
+xchar(int c, char *buf, int size)
+{
+ snprintf(buf, size,"%%%02x",c);
+ return buf;
+}
+
+/* Translate dangerous and some other characters to safe
+ %xx form.
+*/
+void
+translate_to_uri(const string &s, string &out)
+{
+ const char *cp = s.c_str();
+ for( ; *cp; ++cp) {
+ int c = 0xff & (unsigned char)*cp;
+ if(dwarfdump_ctype_table[c]) {
+ out.push_back((char)c);
+ } else {
+ char buf[8];
+ string b = xchar(c,buf,sizeof(buf));
+ out.append(b);
+ }
+ }
+}
+
+/* This is not very efficient, but it is seldom called. */
+static char
+hexdig(char c)
+{
+ char ochar = 0;
+ if(c >= 0 && c <= '9') {
+ ochar = (c - '0');
+ return ochar;
+ }
+ if(c >= 'a' && c <= 'f') {
+ ochar = (c - 'a')+10;
+ return ochar;
+ }
+ if(c >= 'A' && c <= 'F') {
+ ochar = (c - 'A')+10;
+ return ochar;
+ }
+ // We have an input botch here.
+ fprintf(stderr,"Translating from uri: "
+ "A supposed hexadecimal input character is "
+ "not 0-9 or a-f or A-F, it is (shown as hex here): %x\n",c);
+ return ochar;
+}
+
+static char tohex(char c1, char c2)
+{
+ char out = (hexdig(c1) << 4) | hexdig(c2);
+ return out;
+}
+
+static int
+hexpairtochar(const char *cp, char *myochar)
+{
+ char ochar = 0;
+ int olen = 0;
+ char c = cp[0];
+ if(c) {
+ char c2 = cp[1];
+ if(c2) {
+ ochar = tohex(c,c2);
+ olen = 2;
+ } else {
+ std::cerr << "Translating from uri: "
+ "A supposed hexadecimal input character pair "
+ "runs off the end of the input after 1 hex digit."<<
+ std::endl;
+ /* botched input. */
+ ochar = c;
+ olen = 1;
+ }
+ } else {
+ /* botched input. */
+ std::cerr << "Translating from uri: "
+ "A supposed hexadecimal input character pair "
+ "runs off the end of the input." << std::endl;
+ ochar = '%';
+ olen = 0;
+ }
+ *myochar = ochar;
+ return olen;
+}
+void
+translate_from_uri(const std::string & input, string &out)
+{
+ const char *cp = input.c_str();
+ for(; *cp; ++cp) {
+ char c = *cp;
+ if(c == '%') {
+ char c2 = cp[1];
+ // hexpairtochar deals with c2 being NUL.
+ if ( c2 == '%') {
+ out.push_back(c);
+ ++cp;
+ continue;
+ }
+ int increment = hexpairtochar(cp+1,&c);
+ out.push_back(c);
+ cp += increment;
+ continue;
+ }
+ out.push_back(c);
+ }
+}
+
+#ifdef TEST
+
+unsigned errcnt = 0;
+static void
+mytestfrom(const std::string & in,const std::string & expected,int testnum)
+{
+ string out;
+ translate_from_uri(in, out);
+ if(expected != out) {
+ printf(" Fail test %d expected \"%s\" got \"%s\"\n",
+ testnum,expected.c_str(),out.c_str());
+ ++errcnt;
+ }
+}
+
+static void
+mytest(const std::string & in,const std::string & expected,int testnum)
+{
+ string out;
+ translate_to_uri(in.c_str(), out);
+ if(expected != out) {
+ printf(" Fail test %d expected \"%s\" got \"%s\"\n",
+ testnum,expected.c_str(),out.c_str());
+ ++errcnt;
+ }
+}
+
+
+int
+main()
+{
+ /* We no longer translate space to %20, that
+ turns out not to help all that much. */
+ mytest("aaa","aaa",1);
+ mytest(" bc"," bc",2);
+ mytest(";bc","%3bbc",3);
+ mytest(" bc\n"," bc%0a",4);
+ mytest(";bc\n","%3bbc%0a",5);
+ mytest(" bc\r"," bc%0d",6);
+ mytest(";bc\r","%3bbc%0d",7);
+ mytest(" \x01"," %01",8);
+ mytest(";\x01","%3b%01",9);
+ mytestfrom("abc","abc",10);
+ mytestfrom("a%20bc","a bc",11);
+ mytestfrom("a%%20bc","a%20bc",12);
+ mytestfrom("a%%%20bc","a% bc",13);
+ mytestfrom("a%%%%20bc","a%%20bc",14);
+ mytestfrom("a%20","a ",15);
+ /* The following is mistaken input. */
+ mytestfrom("a%2","a2",16);
+ mytestfrom("a%","a%",17);
+ mytest("%bc","%25bc",18);
+
+ if(errcnt) {
+ printf("uri errcount ",errcnt);
+ }
+ return errcnt? 1:0;
+}
+#endif
+
diff --git a/dwarfdump2/uri.h b/dwarfdump2/uri.h
new file mode 100644
index 0000000..397a6c5
--- /dev/null
+++ b/dwarfdump2/uri.h
@@ -0,0 +1,37 @@
+/*
+ Copyright 2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+void translate_to_uri(const std::string &inname, std::string &out);
+void translate_from_uri(const std::string &input, std::string &out);
+
diff --git a/dwarfexample/ChangeLog b/dwarfexample/ChangeLog
new file mode 100644
index 0000000..e635b2f
--- /dev/null
+++ b/dwarfexample/ChangeLog
@@ -0,0 +1,5 @@
+2011-06-04 DavidAnderson <davea42@earthlink.net>
+ * frame1.c, simplereader.c: Altered indentation to
+ multiples of 4 spaces, no tabs. No substantive change.
+2011-01-13 DavidAnderson <davea42@earthlink.net>
+ * New year starts.
diff --git a/dwarfexample/ChangeLog2009 b/dwarfexample/ChangeLog2009
new file mode 100644
index 0000000..e65d29b
--- /dev/null
+++ b/dwarfexample/ChangeLog2009
@@ -0,0 +1,8 @@
+August 7, 2009 David Anderson <davea42@earthlink.net>
+ * frame1.c: This is a new example that uses frame functions.
+July 21, 2009 David Anderson <davea42@earthlink.net>
+ * simplereader.c: After cur_die = sib_die; nothing was printing
+ cur_die, so added a print call after the assignment.
+July 8, 2009 David Anderson <davea42@earthlink.net>
+ * Makefile: New trivial Makefile to build the example.
+ * simplereader.c: New trivial example using libdwarf.
diff --git a/dwarfexample/ChangeLog2010 b/dwarfexample/ChangeLog2010
new file mode 100644
index 0000000..76ebe69
--- /dev/null
+++ b/dwarfexample/ChangeLog2010
@@ -0,0 +1,11 @@
+April 26, 2010 David Anderson <davea42@earthlink.net>
+ * simplereader.c: Now prints all TAGs regardless of
+ whether a DIE has a DW_AT_name attribute. All names
+ print an "" pair so it's easy to recognize empty names
+ and names with embedded spaces.
+March 31, 2010 David Anderson <davea42@earthlink.net>
+ * simplereader.c: Added a new option --names which
+ shows additional detail on getting attributes and source
+ file information.
+January 3, 2010 David Anderson <davea42@earthlink.net>
+ * frame1.c, simplereader.c: Update copyright year.
diff --git a/dwarfexample/Makefile b/dwarfexample/Makefile
new file mode 100644
index 0000000..0fb18d2
--- /dev/null
+++ b/dwarfexample/Makefile
@@ -0,0 +1,18 @@
+
+
+LIBDIR= -L../libdwarf
+LIBS= -ldwarf -lelf
+CFLAGS= -Wall -I../libdwarf
+
+all: simplereader frame1
+
+simplereader: simplereader.c
+ $(CC) $(CFLAGS) simplereader.c -o simplereader $(LIBDIR) $(LIBS)
+frame1: frame1.c
+ $(CC) $(CFLAGS) frame1.c -o frame1 $(LIBDIR) $(LIBS)
+
+clean:
+ rm -f simplereader.o
+ rm -f simplereader
+ rm -f frame1
+ rm -f frame1.o
diff --git a/dwarfexample/NEWS b/dwarfexample/NEWS
new file mode 100644
index 0000000..c9ad467
--- /dev/null
+++ b/dwarfexample/NEWS
@@ -0,0 +1,6 @@
+July 21, 2009
+ Roni Simonian noticed a call to print_die_data(dbg,cur_die,in_level);
+ was missing so not all DIEs would print. Good Catch!
+July 8, 2009
+ Created a sample libdwarf consumer. Using BSD license so
+ anyone can use it. And a trivial Makefile.
diff --git a/dwarfexample/frame1.c b/dwarfexample/frame1.c
new file mode 100644
index 0000000..80d3430
--- /dev/null
+++ b/dwarfexample/frame1.c
@@ -0,0 +1,408 @@
+/*
+ Copyright (c) 2009-2010 David Anderson.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the example nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY David Anderson ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL David Anderson BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+/* simplereader.c
+ This is an example of code reading dwarf .debug_frame.
+ It is kept as simple as possible to expose essential features.
+ It does not do all possible error reporting or error handling.
+
+ It specifically calls dwarf_expand_frame_instructions()
+ to verify that works without crashing!
+
+ To use, try
+ make
+ ./frame1 frame1
+*/
+#include <sys/types.h> /* For open() */
+#include <sys/stat.h> /* For open() */
+#include <fcntl.h> /* For open() */
+#include <stdlib.h> /* For exit() */
+#include <unistd.h> /* For close() */
+#include <string.h> /* For strcmp* */
+#include <stdio.h>
+#include <errno.h>
+#include "dwarf.h"
+#include "libdwarf.h"
+
+
+static void read_frame_data(Dwarf_Debug dbg);
+static void print_fde_instrs(Dwarf_Debug dbg, Dwarf_Fde fde,
+ int fdenum, Dwarf_Error *error);
+static void print_regtable(Dwarf_Fde fde,Dwarf_Regtable3 *tab3,int oldrulecount,
+ Dwarf_Debug dbg,Dwarf_Error *error);
+static void
+print_cie_instrs(Dwarf_Debug dbg,Dwarf_Cie cie,Dwarf_Error *error);
+
+
+#define UNDEF_VAL 2000
+#define SAME_VAL 2001
+#define CFA_VAL 2002
+
+
+int
+main(int argc, char **argv)
+{
+
+ Dwarf_Debug dbg = 0;
+ int fd = -1;
+ const char *filepath = "<stdin>";
+ int res = DW_DLV_ERROR;
+ Dwarf_Error error;
+ Dwarf_Handler errhand = 0;
+ Dwarf_Ptr errarg = 0;
+ int regtabrulecount = 0;
+
+ if(argc < 2) {
+ fd = 0; /* stdin */
+ } else {
+ filepath = argv[1];
+ fd = open(filepath,O_RDONLY);
+ }
+ if(fd < 0) {
+ printf("Failure attempting to open %s\n",filepath);
+ }
+ res = dwarf_init(fd,DW_DLC_READ,errhand,errarg, &dbg,&error);
+ if(res != DW_DLV_OK) {
+ printf("Giving up, dwarf_init failed, cannot do DWARF processing\n");
+ exit(1);
+ }
+ /* Do this setting after init before any real operations.
+ These return the old values, but here we do not
+ need to know the old values. The sizes and
+ values here are higher than most ABIs and entirely
+ arbitrary.
+
+ The setting of initial_value to
+ the same as undefined-value (the other possible choice being
+ same-value) is arbitrary, different ABIs do differ, and
+ you have to know which is right. */
+ regtabrulecount=1999;
+ dwarf_set_frame_undefined_value(dbg, UNDEF_VAL);
+ dwarf_set_frame_rule_initial_value(dbg, UNDEF_VAL);
+ dwarf_set_frame_same_value(dbg,SAME_VAL);
+ dwarf_set_frame_cfa_value(dbg,CFA_VAL);
+ dwarf_set_frame_rule_table_size(dbg,regtabrulecount);
+
+ read_frame_data(dbg);
+ res = dwarf_finish(dbg,&error);
+ if(res != DW_DLV_OK) {
+ printf("dwarf_finish failed!\n");
+ }
+ close(fd);
+ return 0;
+}
+
+static void
+read_frame_data(Dwarf_Debug dbg)
+{
+ Dwarf_Error error;
+ Dwarf_Signed cie_element_count = 0;
+ Dwarf_Signed fde_element_count = 0;
+ Dwarf_Cie *cie_data = 0;
+ Dwarf_Fde *fde_data = 0;
+ int res = DW_DLV_ERROR;
+ Dwarf_Signed fdenum = 0;
+
+
+ res = dwarf_get_fde_list(dbg,&cie_data,&cie_element_count,
+ &fde_data,&fde_element_count,&error);
+ if(res == DW_DLV_NO_ENTRY) {
+ printf("No frame data present ");
+ exit(0);
+ }
+ if( res == DW_DLV_ERROR) {
+ printf("Error reading frame data ");
+ exit(1);
+ }
+ printf( "%" DW_PR_DSd " cies present. "
+ "%" DW_PR_DSd " fdes present. \n",
+ cie_element_count,fde_element_count);
+ /*if(fdenum >= fde_element_count) {
+ printf("Want fde %d but only %" DW_PR_DSd " present\n",fdenum,
+ fde_element_count);
+ exit(1);
+ }*/
+
+ for(fdenum = 0; fdenum < fde_element_count; ++fdenum) {
+ Dwarf_Cie cie = 0;
+ printf("Print cie of fde %" DW_PR_DSd "\n",fdenum);
+ res = dwarf_get_cie_of_fde(fde_data[fdenum],&cie,&error);
+ if(res != DW_DLV_OK) {
+ printf("Error accessing fdenum %" DW_PR_DSd
+ " to get its cie\n",fdenum);
+ exit(1);
+ }
+ print_cie_instrs(dbg,cie,&error);
+ printf("Print fde %" DW_PR_DSd "\n",fdenum);
+ print_fde_instrs(dbg,fde_data[fdenum],fdenum,&error);
+ }
+
+ /* Done with the data. */
+ dwarf_fde_cie_list_dealloc(dbg,cie_data,cie_element_count,
+ fde_data, fde_element_count);
+ return;
+}
+static void
+print_cie_instrs(Dwarf_Debug dbg,Dwarf_Cie cie,Dwarf_Error *error)
+{
+ int res = DW_DLV_ERROR;
+ Dwarf_Unsigned bytes_in_cie = 0;
+ Dwarf_Small version = 0;
+ char *augmentation = 0;
+ Dwarf_Unsigned code_alignment_factor = 0;
+ Dwarf_Signed data_alignment_factor = 0;
+ Dwarf_Half return_address_register_rule = 0;
+ Dwarf_Ptr instrp = 0;
+ Dwarf_Unsigned instr_len = 0;
+
+ res = dwarf_get_cie_info(cie,&bytes_in_cie,
+ &version, &augmentation, &code_alignment_factor,
+ &data_alignment_factor, &return_address_register_rule,
+ &instrp,&instr_len,error);
+ if(res != DW_DLV_OK) {
+ printf("Unable to get cie info!\n");
+ exit(1);
+ }
+}
+
+static void
+print_frame_instrs(Dwarf_Debug dbg,Dwarf_Frame_Op *frame_op_list,
+ Dwarf_Signed frame_op_count)
+{
+ Dwarf_Signed i = 0;
+ printf("Base op. Ext op. Reg. Offset. Instr-offset.\n");
+ for(i = 0; i < frame_op_count; ++i) {
+ printf("[%" DW_PR_DSd "]", i);
+ printf(" %d. ", frame_op_list[i].fp_base_op);
+ printf(" %d. ", frame_op_list[i].fp_extended_op);
+ printf(" %" DW_PR_DSd ". ", frame_op_list[i].fp_offset);
+ printf(" 0x%" DW_PR_DUx ". ", frame_op_list[i].fp_instr_offset);
+ printf("\n");
+ }
+}
+
+static void
+print_fde_instrs(Dwarf_Debug dbg,
+ Dwarf_Fde fde,int fdenum, Dwarf_Error *error)
+{
+ int res;
+ Dwarf_Addr lowpc = 0;
+ Dwarf_Unsigned func_length = 0;
+ Dwarf_Ptr fde_bytes;
+ Dwarf_Unsigned fde_byte_length = 0;
+ Dwarf_Off cie_offset = 0;
+ Dwarf_Signed cie_index = 0;
+ Dwarf_Off fde_offset = 0;
+ Dwarf_Addr arbitrary_addr = 0;
+ Dwarf_Addr actual_pc = 0;
+ Dwarf_Regtable3 tab3;
+ int oldrulecount = 0;
+ Dwarf_Ptr outinstrs = 0;
+ Dwarf_Unsigned instrslen = 0;
+ Dwarf_Frame_Op * frame_op_list = 0;
+ Dwarf_Signed frame_op_count = 0;
+ Dwarf_Cie cie = 0;
+
+
+ res = dwarf_get_fde_range(fde,&lowpc,&func_length,&fde_bytes,
+ &fde_byte_length,&cie_offset,&cie_index,&fde_offset,error);
+ if(res != DW_DLV_OK) {
+ printf("Problem getting fde range \n");
+ exit(1);
+ }
+
+ arbitrary_addr = lowpc + (func_length/2);
+ printf("function low pc 0x%" DW_PR_DUx
+ " and length 0x%" DW_PR_DUx
+ " and addr we choose 0x%" DW_PR_DUx
+ "\n",
+ lowpc,func_length,arbitrary_addr);
+
+ /* 1 is arbitrary. We are winding up getting the
+ rule count here while leaving things unchanged. */
+ oldrulecount = dwarf_set_frame_rule_table_size(dbg,1);
+ dwarf_set_frame_rule_table_size(dbg,oldrulecount);
+
+ tab3.rt3_reg_table_size = oldrulecount;
+ tab3.rt3_rules = (struct Dwarf_Regtable_Entry3_s *) malloc(
+ sizeof(struct Dwarf_Regtable_Entry3_s)* oldrulecount);
+ if (!tab3.rt3_rules) {
+ printf("Unable to malloc for %d rules\n",oldrulecount);
+ exit(1);
+ }
+
+ res = dwarf_get_fde_info_for_all_regs3(fde,arbitrary_addr ,
+ &tab3,&actual_pc,error);
+
+ if(res != DW_DLV_OK) {
+ printf("dwarf_get_fde_info_for_all_regs3 failed!\n");
+ exit(1);
+ }
+ print_regtable(fde,&tab3,oldrulecount,dbg,error);
+
+ res = dwarf_get_fde_instr_bytes(fde,&outinstrs,&instrslen,error);
+ if(res != DW_DLV_OK) {
+ printf("dwarf_get_fde_instr_bytes failed!\n");
+ exit(1);
+ }
+ res = dwarf_get_cie_of_fde(fde,&cie,error);
+ if(res != DW_DLV_OK) {
+ printf("Error getting cie from fde\n");
+ exit(1);
+ }
+
+ res = dwarf_expand_frame_instructions(cie,
+ outinstrs,instrslen,&frame_op_list,
+ &frame_op_count,error);
+ if(res != DW_DLV_OK) {
+ printf("dwarf_expand_frame_instructions failed!\n");
+ exit(1);
+ }
+ printf("Frame op count: %" DW_PR_DUu "\n",frame_op_count);
+ print_frame_instrs(dbg,frame_op_list,frame_op_count);
+
+ dwarf_dealloc(dbg,frame_op_list, DW_DLA_FRAME_BLOCK);
+ free(tab3.rt3_rules);
+}
+
+static void
+print_reg(int r)
+{
+ switch(r) {
+ case SAME_VAL:
+ printf(" %d SAME_VAL ",r);
+ break;
+ case UNDEF_VAL:
+ printf(" %d UNDEF_VAL ",r);
+ break;
+ case CFA_VAL:
+ printf(" %d (CFA) ",r);
+ break;
+ default:
+ printf(" r%d ",r);
+ break;
+ }
+}
+
+static void
+print_one_regentry(const char *prefix,Dwarf_Fde fde,Dwarf_Debug dbg,
+ int oldrulecount,struct Dwarf_Regtable_Entry3_s *entry,
+ Dwarf_Error * error)
+{
+ int is_cfa = !strcmp("cfa",prefix);
+ printf("%s ",prefix);
+ printf("type: %d %s ",
+ entry->dw_value_type,
+ (entry->dw_value_type == DW_EXPR_OFFSET)? "DW_EXPR_OFFSET":
+ (entry->dw_value_type == DW_EXPR_VAL_OFFSET)? "DW_EXPR_VAL_OFFSET":
+ (entry->dw_value_type == DW_EXPR_EXPRESSION)? "DW_EXPR_EXPRESSION":
+ (entry->dw_value_type == DW_EXPR_VAL_EXPRESSION)?
+ "DW_EXPR_VAL_EXPRESSION":
+ "Unknown");
+ switch(entry->dw_value_type) {
+ case DW_EXPR_OFFSET:
+ print_reg(entry->dw_regnum);
+ printf(" offset_rel? %d ",entry->dw_offset_relevant);
+ if(entry->dw_offset_relevant) {
+ printf(" offset %" DW_PR_DSd " " ,
+ entry->dw_offset_or_block_len);
+ if(is_cfa) {
+ printf("defines cfa value");
+ } else {
+ printf("address of value is CFA plus signed offset");
+ }
+ if(!is_cfa && entry->dw_regnum != CFA_VAL) {
+ printf(" compiler botch, regnum != CFA_VAL");
+ }
+ } else {
+ printf("value in register");
+ }
+ break;
+ case DW_EXPR_VAL_OFFSET:
+ print_reg(entry->dw_regnum);
+ printf(" offset %" DW_PR_DSd " " ,
+ entry->dw_offset_or_block_len);
+ if(is_cfa) {
+ printf("does this make sense? No?");
+ } else {
+ printf("value at CFA plus signed offset");
+ }
+ if(!is_cfa && entry->dw_regnum != CFA_VAL) {
+ printf(" compiler botch, regnum != CFA_VAL");
+ }
+ break;
+ case DW_EXPR_EXPRESSION:
+ print_reg(entry->dw_regnum);
+ printf(" offset_rel? %d ",entry->dw_offset_relevant);
+ printf(" offset %" DW_PR_DSd " " ,
+ entry->dw_offset_or_block_len);
+ printf("Block ptr set? %s ",entry->dw_block_ptr?"yes":"no");
+ printf(" Value is at address given by expr val ");
+ /* printf(" block-ptr 0x%" DW_PR_DUx " ",
+ (Dwarf_Unsigned)entry->dw_block_ptr); */
+ break;
+ case DW_EXPR_VAL_EXPRESSION:
+ printf(" expression byte len %" DW_PR_DSd " " ,
+ entry->dw_offset_or_block_len);
+ printf("Block ptr set? %s ",entry->dw_block_ptr?"yes":"no");
+ printf(" Value is expr val ");
+ if(!entry->dw_block_ptr) {
+ printf("Compiler botch. ");
+ }
+ /* printf(" block-ptr 0x%" DW_PR_DUx " ",
+ (Dwarf_Unsigned)entry->dw_block_ptr); */
+ break;
+ }
+ printf("\n");
+}
+
+static void
+print_regtable(Dwarf_Fde fde,Dwarf_Regtable3 *tab3,int oldrulecount,
+ Dwarf_Debug dbg,Dwarf_Error *error)
+{
+ int r;
+ /* We won't print too much. A bit arbitrary. */
+ int max = 10;
+ if(max > tab3->rt3_reg_table_size) {
+ max = tab3->rt3_reg_table_size;
+ }
+ print_one_regentry("cfa",fde,dbg,oldrulecount,&tab3->rt3_cfa_rule,
+ error);
+
+ for(r = 0; r < max; r++) {
+ char rn[30];
+ snprintf(rn,sizeof(rn),"reg %d",r);
+ print_one_regentry(rn, fde,dbg,oldrulecount,tab3->rt3_rules+r,
+ error);
+ }
+
+
+}
+
+
+
+
diff --git a/dwarfexample/simplereader.c b/dwarfexample/simplereader.c
new file mode 100644
index 0000000..da21b65
--- /dev/null
+++ b/dwarfexample/simplereader.c
@@ -0,0 +1,384 @@
+/*
+ Copyright (c) 2009-2010 David Anderson. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the example nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY David Anderson ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL David Anderson BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+/* simplereader.c
+ This is an example of code reading dwarf .debug_info.
+ It is kept as simple as possible to expose essential features.
+ It does not do all possible error reporting or error handling.
+
+ The --names
+ option adds some extra printing.
+
+ To use, try
+ make
+ ./simplereader simplereader
+*/
+#include <sys/types.h> /* For open() */
+#include <sys/stat.h> /* For open() */
+#include <fcntl.h> /* For open() */
+#include <stdlib.h> /* For exit() */
+#include <unistd.h> /* For close() */
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include "dwarf.h"
+#include "libdwarf.h"
+
+struct srcfilesdata {
+ char ** srcfiles;
+ Dwarf_Signed srcfilescount;
+ int srcfilesres;
+};
+
+static void read_cu_list(Dwarf_Debug dbg);
+static void print_die_data(Dwarf_Debug dbg, Dwarf_Die print_me,int level,
+ struct srcfilesdata *sf);
+static void get_die_and_siblings(Dwarf_Debug dbg, Dwarf_Die in_die,int in_level,
+ struct srcfilesdata *sf);
+static void resetsrcfiles(Dwarf_Debug dbg,struct srcfilesdata *sf);
+
+static int namesoptionon = 0;
+
+int
+main(int argc, char **argv)
+{
+
+ Dwarf_Debug dbg = 0;
+ int fd = -1;
+ const char *filepath = "<stdin>";
+ int res = DW_DLV_ERROR;
+ Dwarf_Error error;
+ Dwarf_Handler errhand = 0;
+ Dwarf_Ptr errarg = 0;
+
+ if(argc < 2) {
+ fd = 0; /* stdin */
+ } else {
+ int i = 0;
+ for(i = 1; i < (argc-1) ; ++i) {
+ if(strcmp(argv[i],"--names") == 0) {
+ namesoptionon=1;
+ } else {
+ printf("Unknown argument \"%s\" ignored\n",argv[i]);
+ }
+ }
+ filepath = argv[i];
+ fd = open(filepath,O_RDONLY);
+ }
+ if(argc > 2) {
+ }
+ if(fd < 0) {
+ printf("Failure attempting to open \"%s\"\n",filepath);
+ }
+ res = dwarf_init(fd,DW_DLC_READ,errhand,errarg, &dbg,&error);
+ if(res != DW_DLV_OK) {
+ printf("Giving up, cannot do DWARF processing\n");
+ exit(1);
+ }
+
+ read_cu_list(dbg);
+ res = dwarf_finish(dbg,&error);
+ if(res != DW_DLV_OK) {
+ printf("dwarf_finish failed!\n");
+ }
+ close(fd);
+ return 0;
+}
+
+static void
+read_cu_list(Dwarf_Debug dbg)
+{
+ Dwarf_Unsigned cu_header_length = 0;
+ Dwarf_Half version_stamp = 0;
+ Dwarf_Unsigned abbrev_offset = 0;
+ Dwarf_Half address_size = 0;
+ Dwarf_Unsigned next_cu_header = 0;
+ Dwarf_Error error;
+ int cu_number = 0;
+
+ for(;;++cu_number) {
+ struct srcfilesdata sf;
+ sf.srcfilesres = DW_DLV_ERROR;
+ sf.srcfiles = 0;
+ sf.srcfilescount = 0;
+ Dwarf_Die no_die = 0;
+ Dwarf_Die cu_die = 0;
+ int res = DW_DLV_ERROR;
+ res = dwarf_next_cu_header(dbg,&cu_header_length,
+ &version_stamp, &abbrev_offset, &address_size,
+ &next_cu_header, &error);
+ if(res == DW_DLV_ERROR) {
+ printf("Error in dwarf_next_cu_header\n");
+ exit(1);
+ }
+ if(res == DW_DLV_NO_ENTRY) {
+ /* Done. */
+ return;
+ }
+ /* The CU will have a single sibling, a cu_die. */
+ res = dwarf_siblingof(dbg,no_die,&cu_die,&error);
+ if(res == DW_DLV_ERROR) {
+ printf("Error in dwarf_siblingof on CU die \n");
+ exit(1);
+ }
+ if(res == DW_DLV_NO_ENTRY) {
+ /* Impossible case. */
+ printf("no entry! in dwarf_siblingof on CU die \n");
+ exit(1);
+ }
+ get_die_and_siblings(dbg,cu_die,0,&sf);
+ dwarf_dealloc(dbg,cu_die,DW_DLA_DIE);
+ resetsrcfiles(dbg,&sf);
+ }
+}
+
+static void
+get_die_and_siblings(Dwarf_Debug dbg, Dwarf_Die in_die,int in_level,
+ struct srcfilesdata *sf)
+{
+ int res = DW_DLV_ERROR;
+ Dwarf_Die cur_die=in_die;
+ Dwarf_Die child = 0;
+ Dwarf_Error error;
+
+ print_die_data(dbg,in_die,in_level,sf);
+
+ for(;;) {
+ Dwarf_Die sib_die = 0;
+ res = dwarf_child(cur_die,&child,&error);
+ if(res == DW_DLV_ERROR) {
+ printf("Error in dwarf_child , level %d \n",in_level);
+ exit(1);
+ }
+ if(res == DW_DLV_OK) {
+ get_die_and_siblings(dbg,child,in_level+1,sf);
+ }
+ /* res == DW_DLV_NO_ENTRY */
+ res = dwarf_siblingof(dbg,cur_die,&sib_die,&error);
+ if(res == DW_DLV_ERROR) {
+ printf("Error in dwarf_siblingof , level %d \n",in_level);
+ exit(1);
+ }
+ if(res == DW_DLV_NO_ENTRY) {
+ /* Done at this level. */
+ break;
+ }
+ /* res == DW_DLV_OK */
+ if(cur_die != in_die) {
+ dwarf_dealloc(dbg,cur_die,DW_DLA_DIE);
+ }
+ cur_die = sib_die;
+ print_die_data(dbg,cur_die,in_level,sf);
+ }
+ return;
+}
+static void
+get_addr(Dwarf_Attribute attr,Dwarf_Addr *val)
+{
+ Dwarf_Error error = 0;
+ int res;
+ Dwarf_Addr uval = 0;
+ res = dwarf_formaddr(attr,&uval,&error);
+ if(res == DW_DLV_OK) {
+ *val = uval;
+ return;
+ }
+ return;
+}
+static void
+get_number(Dwarf_Attribute attr,Dwarf_Unsigned *val)
+{
+ Dwarf_Error error = 0;
+ int res;
+ Dwarf_Signed sval = 0;
+ Dwarf_Unsigned uval = 0;
+ res = dwarf_formudata(attr,&uval,&error);
+ if(res == DW_DLV_OK) {
+ *val = uval;
+ return;
+ }
+ res = dwarf_formsdata(attr,&sval,&error);
+ if(res == DW_DLV_OK) {
+ *val = sval;
+ return;
+ }
+ return;
+}
+static void
+print_subprog(Dwarf_Debug dbg,Dwarf_Die die, int level,
+ struct srcfilesdata *sf)
+{
+ int res;
+ Dwarf_Error error = 0;
+ Dwarf_Attribute *attrbuf = 0;
+ Dwarf_Addr lowpc = 0;
+ Dwarf_Addr highpc = 0;
+ Dwarf_Signed attrcount = 0;
+ Dwarf_Unsigned i;
+ Dwarf_Unsigned filenum = 0;
+ Dwarf_Unsigned linenum = 0;
+ char *filename = 0;
+ res = dwarf_attrlist(die,&attrbuf,&attrcount,&error);
+ if(res != DW_DLV_OK) {
+ return;
+ }
+ for(i = 0; i < attrcount ; ++i) {
+ Dwarf_Half aform;
+ res = dwarf_whatattr(attrbuf[i],&aform,&error);
+ if(res == DW_DLV_OK) {
+ if(aform == DW_AT_decl_file) {
+ get_number(attrbuf[i],&filenum);
+ if((filenum > 0) && (sf->srcfilescount > (filenum-1))) {
+ filename = sf->srcfiles[filenum-1];
+ }
+ }
+ if(aform == DW_AT_decl_line) {
+ get_number(attrbuf[i],&linenum);
+ }
+ if(aform == DW_AT_low_pc) {
+ get_addr(attrbuf[i],&lowpc);
+ }
+ if(aform == DW_AT_high_pc) {
+ get_addr(attrbuf[i],&highpc);
+ }
+ }
+ dwarf_dealloc(dbg,attrbuf[i],DW_DLA_ATTR);
+ }
+ if(filenum || linenum) {
+ printf("<%3d> file: %" DW_PR_DUu " %s line %"
+ DW_PR_DUu "\n",level,filenum,filename?filename:"",linenum);
+ }
+ if(lowpc) {
+ printf("<%3d> low_pc : 0x%" DW_PR_DUx "\n",
+ level, (Dwarf_Unsigned)lowpc);
+ }
+ if(highpc) {
+ printf("<%3d> high_pc: 0x%" DW_PR_DUx "\n",
+ level, (Dwarf_Unsigned)highpc);
+ }
+ dwarf_dealloc(dbg,attrbuf,DW_DLA_LIST);
+}
+
+static void
+print_comp_dir(Dwarf_Debug dbg,Dwarf_Die die,int level, struct srcfilesdata *sf)
+{
+ int res;
+ Dwarf_Error error = 0;
+ Dwarf_Attribute *attrbuf = 0;
+ Dwarf_Signed attrcount = 0;
+ Dwarf_Unsigned i;
+ res = dwarf_attrlist(die,&attrbuf,&attrcount,&error);
+ if(res != DW_DLV_OK) {
+ return;
+ }
+ sf->srcfilesres = dwarf_srcfiles(die,&sf->srcfiles,&sf->srcfilescount,
+ &error);
+ for(i = 0; i < attrcount ; ++i) {
+ Dwarf_Half aform;
+ res = dwarf_whatattr(attrbuf[i],&aform,&error);
+ if(res == DW_DLV_OK) {
+ if(aform == DW_AT_comp_dir) {
+ char *name = 0;
+ res = dwarf_formstring(attrbuf[i],&name,&error);
+ if(res == DW_DLV_OK) {
+ printf( "<%3d> compilation directory : \"%s\"\n",
+ level,name);
+ }
+ }
+ if(aform == DW_AT_stmt_list) {
+ /* Offset of stmt list for this CU in .debug_line */
+ }
+ }
+ dwarf_dealloc(dbg,attrbuf[i],DW_DLA_ATTR);
+ }
+ dwarf_dealloc(dbg,attrbuf,DW_DLA_LIST);
+}
+
+static void
+resetsrcfiles(Dwarf_Debug dbg,struct srcfilesdata *sf)
+{
+ Dwarf_Signed sri = 0;
+ for (sri = 0; sri < sf->srcfilescount; ++sri) {
+ dwarf_dealloc(dbg, sf->srcfiles[sri], DW_DLA_STRING);
+ }
+ dwarf_dealloc(dbg, sf->srcfiles, DW_DLA_LIST);
+ sf->srcfilesres = DW_DLV_ERROR;
+ sf->srcfiles = 0;
+ sf->srcfilescount = 0;
+}
+
+static void
+print_die_data(Dwarf_Debug dbg, Dwarf_Die print_me,int level,
+ struct srcfilesdata *sf)
+{
+ char *name = 0;
+ Dwarf_Error error = 0;
+ Dwarf_Half tag = 0;
+ const char *tagname = 0;
+ int localname = 0;
+
+ int res = dwarf_diename(print_me,&name,&error);
+
+ if(res == DW_DLV_ERROR) {
+ printf("Error in dwarf_diename , level %d \n",level);
+ exit(1);
+ }
+ if(res == DW_DLV_NO_ENTRY) {
+ name = "<no DW_AT_name attr>";
+ localname = 1;
+ }
+ res = dwarf_tag(print_me,&tag,&error);
+ if(res != DW_DLV_OK) {
+ printf("Error in dwarf_tag , level %d \n",level);
+ exit(1);
+ }
+ res = dwarf_get_TAG_name(tag,&tagname);
+ if(res != DW_DLV_OK) {
+ printf("Error in dwarf_get_TAG_name , level %d \n",level);
+ exit(1);
+ }
+ if(namesoptionon) {
+ if( tag == DW_TAG_subprogram) {
+ printf( "<%3d> subprogram : \"%s\"\n",level,name);
+ print_subprog(dbg,print_me,level,sf);
+ } else if (tag == DW_TAG_compile_unit ||
+ tag == DW_TAG_partial_unit ||
+ tag == DW_TAG_type_unit) {
+
+ resetsrcfiles(dbg,sf);
+ printf( "<%3d> source file : \"%s\"\n",level,name);
+ print_comp_dir(dbg,print_me,level,sf);
+ }
+ } else {
+ printf("<%d> tag: %d %s name: \"%s\"\n",level,tag,tagname,name);
+ }
+ if(!localname) {
+ dwarf_dealloc(dbg,name,DW_DLA_STRING);
+ }
+}
+
+
+
diff --git a/dwarfgen/COPYING b/dwarfgen/COPYING
new file mode 100644
index 0000000..e6e8795
--- /dev/null
+++ b/dwarfgen/COPYING
@@ -0,0 +1,30 @@
+Files here are copyrighted by David Anderson
+(and possibly others, see the copyright notices in individual
+files) by the GPL version 2.
+A typical notice is:
+
+ Copyright (C) 2010 David Anderson.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+
+See GPL.txt in this directory for an original copy of the GPL version 2.
+(GPL.txt contains an obsolete address for the Free Software Foundation,
+51 Franklin Street is the correct address.)
+
+David Anderson is at
+libdwarf-list -at- earthlink =dot= net
+
+280 Bella Vista Drive
+Hillsborough, California 94010
+USA.
diff --git a/dwarfgen/ChangeLog b/dwarfgen/ChangeLog
new file mode 100644
index 0000000..f8eea52
--- /dev/null
+++ b/dwarfgen/ChangeLog
@@ -0,0 +1,6 @@
+2011-04-10 DavidAnderson <davea42@earthlink.net>
+ * config.h.in: Add HAVE_INTPTR_T
+ * configure.in: Test for intptr_t
+ * configure: Regenerated
+ * irepattrtodbg.cc: Add typedef and test for INTPTR_T
+
diff --git a/dwarfgen/GPL.txt b/dwarfgen/GPL.txt
new file mode 100644
index 0000000..d511905
--- /dev/null
+++ b/dwarfgen/GPL.txt
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/dwarfgen/Makefile.in b/dwarfgen/Makefile.in
new file mode 100644
index 0000000..8998f3d
--- /dev/null
+++ b/dwarfgen/Makefile.in
@@ -0,0 +1,89 @@
+#
+# Makefile.in uses very simple make rules.
+# There are no restrictions on copying this file.
+#
+
+# Standard Makefile.in stuff:
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = $(exec_prefix)/bin
+libdir = $(exec_prefix)/lib
+mandir = $(exec_prefix)/share/man
+man1dir = $(mandir)/man1
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+DATAROOT = @datarootdir@
+SHELL = /bin/sh
+CXX = @CXX@
+AR = @AR@
+#ARFLAGS = @ARFLAGS@
+RM = rm
+RANLIB = @RANLIB@
+DEFS = @DEFS@
+LIBS = @LIBS@ -L ../libdwarf -ldwarf -lelf
+INCLUDES = -I. -I$(srcdir) -I$(srcdir)/../libdwarf
+CXXFLAGS = @CXXFLAGS@ $(INCLUDES)
+LDFLAGS = @LDFLAGS@ $(LIBS)
+
+
+DIRINC = $(srcdir)/../libdwarf
+INSTALL = cp
+
+binprefix =
+
+DGOBJECTS = \
+ createirepformfrombinary.o \
+ createirepfrombinary.o \
+ dwarfgen.o \
+ irepattrtodbg.o \
+ ireptodbg.o
+
+HEADERS = \
+ createirepfrombinary.h\
+ general.h \
+ irepattrtodbg.h \
+ irepdie.h \
+ irepframe.h \
+ irepform.h \
+ irepmacro.h \
+ irepresentation.h \
+ ireptodbg.h \
+ strtabdata.h
+
+all: dwarfgen
+
+default: $(TARGETS)
+
+dwarfgen: $(HEADERS) $(DGOBJECTS)
+ $(CXX) $(CXXFLAGS) -o $@ $(DGOBJECTS) $(LDFLAGS)
+
+test:
+
+install: all
+ $(INSTALL) $(srcdir)/dwarfgen.conf $(libdir)/dwarfgen.conf
+ $(INSTALL) $(srcdir)/dwarfgen.1 $(man1dir)/dwarfgen.1
+ $(INSTALL) dwarfgen $(bindir)/dwarfgen
+
+clean:
+ -rm -f *.o dwarfgen
+
+uninstall:
+ -rm -f $(libdir)/dwarfgen.conf
+ -rm -f $(man1dir)/dwarfgen.1
+ -rm -f $(bindir)/dwarfgen
+
+distclean: clean
+ -rm -f config.log config.h config.cache config.status
+ rm -rf autom4te.cache
+ rm -f Makefile
+
+shar:
+ @echo "shar not set up."
+
+dist:
+ @echo "dist not set up."
diff --git a/dwarfgen/README b/dwarfgen/README
new file mode 100644
index 0000000..f1d4814
--- /dev/null
+++ b/dwarfgen/README
@@ -0,0 +1,20 @@
+
+David Anderson, September 20, 2010
+
+The dwarfgen application is intended as both a vehicle
+for testing dwarf-generation by libdwarf and as an example
+of how one uses libdwarf to generate DWARF.
+In addition, it should be useful as a test vehicle for
+evaluating future changes to the DWARF standard.
+
+It is necessary as a test-vehicle so that the libdwarf
+producer code can be updated to allow more recent features
+of DWARF to be supported while trying to guarantee current
+producer code users are correctly supported.
+
+By default dwarfgen produces a fake a.out. By that we mean
+that no relocation sections are written. Instead, relocations
+are processed directly by dwarfgen.
+Perhaps at some point a more a.out-like output will be optionally
+supported.
+
diff --git a/dwarfgen/config.h.in b/dwarfgen/config.h.in
new file mode 100644
index 0000000..75d2f40
--- /dev/null
+++ b/dwarfgen/config.h.in
@@ -0,0 +1,85 @@
+/* config.h.in. Generated from configure.in by autoheader. */
+
+/* Define if building universal (internal helper macro) */
+#undef AC_APPLE_UNIVERSAL_BUILD
+
+/* Define to 1 if you have the <elf.h> header file. */
+#undef HAVE_ELF_H
+
+/* Define to 1 if you have the <getopt.h> header file. */
+#undef HAVE_GETOPT_H
+
+/* Define 1 if intptr_t defined in C99 stdint.h */
+#undef HAVE_INTPTR_T
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <libelf.h> header file. */
+#undef HAVE_LIBELF_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <sgidefs.h> header file. */
+#undef HAVE_SGIDEFS_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define 1 if __uint32_t is in sgidefs.h. */
+#undef HAVE___UINT32_T_IN_SGIDEFS_H
+
+/* Define 1 if is in sgidefs.h. */
+#undef HAVE___UINT64_T_IN_SGIDEFS_H
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+ significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+# define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+# undef WORDS_BIGENDIAN
+# endif
+#endif
diff --git a/dwarfgen/configure b/dwarfgen/configure
new file mode 100755
index 0000000..2e26d1b
--- /dev/null
+++ b/dwarfgen/configure
@@ -0,0 +1,5445 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.68.
+#
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+# Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ # We cannot yet assume a decent shell, so we have to provide a
+ # neutralization value for shells without unset; and this also
+ # works around shells that cannot unset nonexistent variables.
+ # Preserve -v and -x to the replacement shell.
+ BASH_ENV=/dev/null
+ ENV=/dev/null
+ (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+ export CONFIG_SHELL
+ case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+ esac
+ exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -p'
+ fi
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+PACKAGE_URL=
+
+ac_unique_file="dwarfgen.cc"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+AR
+RANLIB
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+EGREP
+GREP
+CPP
+ac_ct_CXX
+CXXFLAGS
+CXX
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CXX
+CXXFLAGS
+CCC
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used" >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CXX C++ compiler command
+ CXXFLAGS C++ compiler flags
+ CPP C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.68
+
+Copyright (C) 2010 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_cxx_try_compile LINENO
+# ----------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_compile
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: program exited with status $ac_status" >&5
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=$ac_status
+fi
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if eval \${$3+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_header_compiler=yes
+else
+ ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ ac_header_preproc=yes
+else
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+ yes:no: )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+ no:yes:* )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_mongrel
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.68. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+if test -z "$ac_file"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+ if test -n "$CCC"; then
+ CXX=$CCC
+ else
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CXX+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+$as_echo "$CXX" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CXX" && break
+ done
+fi
+if test -z "$CXX"; then
+ ac_ct_CXX=$CXX
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CXX+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CXX"; then
+ ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CXX="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+$as_echo "$ac_ct_CXX" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CXX" && break
+done
+
+ if test "x$ac_ct_CXX" = x; then
+ CXX="g++"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CXX=$ac_ct_CXX
+ fi
+fi
+
+ fi
+fi
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
+$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
+if ${ac_cv_cxx_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GXX=yes
+else
+ GXX=
+fi
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+$as_echo_n "checking whether $CXX accepts -g... " >&6; }
+if ${ac_cv_prog_cxx_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ ac_cxx_werror_flag=yes
+ ac_cv_prog_cxx_g=no
+ CXXFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_prog_cxx_g=yes
+else
+ CXXFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+else
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+ CXXFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_prog_cxx_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+$as_echo "$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if ${ac_cv_prog_CPP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_stdc=yes
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then :
+ :
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
+$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
+if ${ac_cv_c_bigendian+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_c_bigendian=unknown
+ # See if we're dealing with a universal compiler.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifndef __APPLE_CC__
+ not a universal capable compiler
+ #endif
+ typedef int dummy;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ # Check for potential -arch flags. It is not universal unless
+ # there are at least two -arch flags with different values.
+ ac_arch=
+ ac_prev=
+ for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
+ if test -n "$ac_prev"; then
+ case $ac_word in
+ i?86 | x86_64 | ppc | ppc64)
+ if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then
+ ac_arch=$ac_word
+ else
+ ac_cv_c_bigendian=universal
+ break
+ fi
+ ;;
+ esac
+ ac_prev=
+ elif test "x$ac_word" = "x-arch"; then
+ ac_prev=arch
+ fi
+ done
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ if test $ac_cv_c_bigendian = unknown; then
+ # See if sys/param.h defines the BYTE_ORDER macro.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/param.h>
+
+int
+main ()
+{
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
+ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
+ && LITTLE_ENDIAN)
+ bogus endian macros
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ # It does; now see whether it defined to BIG_ENDIAN or not.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_bigendian=yes
+else
+ ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ if test $ac_cv_c_bigendian = unknown; then
+ # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+
+int
+main ()
+{
+#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
+ bogus endian macros
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ # It does; now see whether it defined to _BIG_ENDIAN or not.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+
+int
+main ()
+{
+#ifndef _BIG_ENDIAN
+ not big endian
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_bigendian=yes
+else
+ ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ if test $ac_cv_c_bigendian = unknown; then
+ # Compile a test program.
+ if test "$cross_compiling" = yes; then :
+ # Try to guess by grepping values from an object file.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+short int ascii_mm[] =
+ { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+ short int ascii_ii[] =
+ { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+ int use_ascii (int i) {
+ return ascii_mm[i] + ascii_ii[i];
+ }
+ short int ebcdic_ii[] =
+ { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+ short int ebcdic_mm[] =
+ { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+ int use_ebcdic (int i) {
+ return ebcdic_mm[i] + ebcdic_ii[i];
+ }
+ extern int foo;
+
+int
+main ()
+{
+return use_ascii (foo) == use_ebcdic (foo);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
+ ac_cv_c_bigendian=yes
+ fi
+ if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+ if test "$ac_cv_c_bigendian" = unknown; then
+ ac_cv_c_bigendian=no
+ else
+ # finding both strings is unlikely to happen, but who knows?
+ ac_cv_c_bigendian=unknown
+ fi
+ fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+
+ /* Are we little or big endian? From Harbison&Steele. */
+ union
+ {
+ long int l;
+ char c[sizeof (long int)];
+ } u;
+ u.l = 1;
+ return u.c[sizeof (long int) - 1] == 1;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_c_bigendian=no
+else
+ ac_cv_c_bigendian=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
+$as_echo "$ac_cv_c_bigendian" >&6; }
+ case $ac_cv_c_bigendian in #(
+ yes)
+ $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h
+;; #(
+ no)
+ ;; #(
+ universal)
+
+$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
+
+ ;; #(
+ *)
+ as_fn_error $? "unknown endianness
+ presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
+ esac
+
+if test $ac_cv_c_compiler_gnu = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC needs -traditional" >&5
+$as_echo_n "checking whether $CC needs -traditional... " >&6; }
+if ${ac_cv_prog_gcc_traditional+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_pattern="Autoconf.*'x'"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sgtty.h>
+Autoconf TIOCGETP
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "$ac_pattern" >/dev/null 2>&1; then :
+ ac_cv_prog_gcc_traditional=yes
+else
+ ac_cv_prog_gcc_traditional=no
+fi
+rm -f conftest*
+
+
+ if test $ac_cv_prog_gcc_traditional = no; then
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <termio.h>
+Autoconf TCGETA
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "$ac_pattern" >/dev/null 2>&1; then :
+ ac_cv_prog_gcc_traditional=yes
+fi
+rm -f conftest*
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_gcc_traditional" >&5
+$as_echo "$ac_cv_prog_gcc_traditional" >&6; }
+ if test $ac_cv_prog_gcc_traditional = yes; then
+ CC="$CC -traditional"
+ fi
+fi
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if ${ac_cv_path_install+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+ ./ | .// | /[cC]/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ rm -rf conftest.one conftest.two conftest.dir
+ echo one > conftest.one
+ echo two > conftest.two
+ mkdir conftest.dir
+ if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+ test -s conftest.one && test -s conftest.two &&
+ test -s conftest.dir/conftest.one &&
+ test -s conftest.dir/conftest.two
+ then
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+
+ done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+ ac_ct_AR=$AR
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_AR="ar"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_AR" = x; then
+ AR=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ AR=$ac_ct_AR
+ fi
+else
+ AR="$ac_cv_prog_AR"
+fi
+
+
+for ac_header in elf.h getopt.h libelf.h sgidefs.h sys/types.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sgidefs.h>
+int
+main ()
+{
+ __uint32_t p; p = 27;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE___UINT32_T_IN_SGIDEFS_H 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sgidefs.h>
+int
+main ()
+{
+ __uint64_t p; p = 27;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE___UINT64_T_IN_SGIDEFS_H 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sgidefs.h>
+int
+main ()
+{
+ __uint64_t p; p = 27;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE___UINT64_T_IN_SGIDEFS_H 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sgidefs.h>
+int
+main ()
+{
+ __uint32_t p; p = 27;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE___UINT32_T_IN_SGIDEFS_H 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdint.h>
+int
+main ()
+{
+intptr_t p; p = 27;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE_INTPTR_T 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sgidefs.h>
+int
+main ()
+{
+ __uint64_t p; p = 27;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE___UINT64_T_IN_SGIDEFS_H 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sgidefs.h>
+int
+main ()
+{
+ __uint64_t p; p = 27;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE___UINT64_T_IN_SGIDEFS_H 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+ac_config_files="$ac_config_files Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -p'
+ fi
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.68. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.68,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2010 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+ --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+ ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+ if test -z "$ac_tt"; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any. Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[ ]*#[ ]*define[ ][ ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ for (key in D) D_is_set[key] = 1
+ FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+ line = \$ 0
+ split(line, arg, " ")
+ if (arg[1] == "#") {
+ defundef = arg[2]
+ mac1 = arg[3]
+ } else {
+ defundef = substr(arg[1], 2)
+ mac1 = arg[2]
+ }
+ split(mac1, mac2, "(") #)
+ macro = mac2[1]
+ prefix = substr(line, 1, index(line, defundef) - 1)
+ if (D_is_set[macro]) {
+ # Preserve the white space surrounding the "#".
+ print prefix "define", macro P[macro] D[macro]
+ next
+ } else {
+ # Replace #undef with comments. This is necessary, for example,
+ # in the case of _POSIX_SOURCE, which is predefined and required
+ # on some systems where configure will not decide to define it.
+ if (defundef == "undef") {
+ print "/*", prefix defundef, macro, "*/"
+ next
+ }
+ }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS "
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+ if test x"$ac_file" != x-; then
+ {
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+ } >"$ac_tmp/config.h" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f "$ac_file"
+ mv "$ac_tmp/config.h" "$ac_file" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ fi
+ else
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+ || as_fn_error $? "could not create -" "$LINENO" 5
+ fi
+ ;;
+
+
+ esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/dwarfgen/configure.in b/dwarfgen/configure.in
new file mode 100644
index 0000000..d7bb8cd
--- /dev/null
+++ b/dwarfgen/configure.in
@@ -0,0 +1,41 @@
+dnl This is input to autoconf, producing a configure script.
+AC_INIT(dwarfgen.cc)
+AC_CONFIG_HEADER(config.h)
+
+AC_PROG_CC
+AC_PROG_CXX
+AC_C_BIGENDIAN
+AC_GCC_TRADITIONAL
+AC_PROG_INSTALL
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+AC_CHECK_TOOL(AR, ar)
+
+AC_CHECK_HEADERS(elf.h getopt.h libelf.h sgidefs.h sys/types.h)
+
+dnl Attempt to determine if it is really IRIX/SGI or 'other'.
+AC_TRY_COMPILE([#include <sgidefs.h>],[ __uint32_t p; p = 27;] ,
+ AC_DEFINE(HAVE___UINT32_T_IN_SGIDEFS_H,1,
+ [Define 1 if __uint32_t is in sgidefs.h.]))
+AC_TRY_COMPILE([#include <sgidefs.h>],[ __uint64_t p; p = 27;] ,
+ AC_DEFINE(HAVE___UINT64_T_IN_SGIDEFS_H,1,
+ [Define 1 if __uint64_t is in sgidefs.h.]))
+AC_TRY_COMPILE([#include <sgidefs.h>],[ __uint64_t p; p = 27;] ,
+ AC_DEFINE(HAVE___UINT64_T_IN_SGIDEFS_H,1,
+ [Define 1 if is in sgidefs.h.]))
+dnl the existence of sgidefs.h does not prove it's truly SGI, nor
+dnl prove that __uint32_t or __uint64_t is defined therein.
+AC_TRY_COMPILE([#include <sgidefs.h>],[ __uint32_t p; p = 27;] ,
+ AC_DEFINE(HAVE___UINT32_T_IN_SGIDEFS_H,1,
+ [Define 1 if __uint32_t is in sgidefs.h.]))
+AC_TRY_COMPILE([#include <stdint.h>],[intptr_t p; p = 27;] ,
+ AC_DEFINE(HAVE_INTPTR_T,1,
+ [Define 1 if intptr_t defined in C99 stdint.h]))
+AC_TRY_COMPILE([#include <sgidefs.h>],[ __uint64_t p; p = 27;] ,
+ AC_DEFINE(HAVE___UINT64_T_IN_SGIDEFS_H,1,
+ [Define 1 if __uint64_t is in sgidefs.h.]))
+AC_TRY_COMPILE([#include <sgidefs.h>],[ __uint64_t p; p = 27;] ,
+ AC_DEFINE(HAVE___UINT64_T_IN_SGIDEFS_H,1,
+ [Define 1 if is in sgidefs.h.]))
+
+
+AC_OUTPUT(Makefile)
diff --git a/dwarfgen/createirepformfrombinary.cc b/dwarfgen/createirepformfrombinary.cc
new file mode 100644
index 0000000..f9381cf
--- /dev/null
+++ b/dwarfgen/createirepformfrombinary.cc
@@ -0,0 +1,357 @@
+/*
+ Copyright (C) 2010-2011 David Anderson.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+*/
+// createirepfrombinary.cc
+// Reads an object and inserts its dwarf data into
+// an object intended to hold all the dwarf data.
+
+#include "config.h"
+#include <unistd.h>
+#include <stdlib.h> // for exit
+#include <iostream>
+#include <string>
+#include <list>
+#include <vector>
+#include <string.h> // For memset etc
+#include <sys/stat.h> //open
+#include <fcntl.h> //open
+#include "elf.h"
+#include "gelf.h"
+#include "strtabdata.h"
+#include "dwarf.h"
+#include "libdwarf.h"
+#include "irepresentation.h"
+#include "createirepfrombinary.h"
+
+using std::string;
+using std::cout;
+using std::cerr;
+using std::endl;
+using std::vector;
+using std::list;
+
+// THis should instantiated only locally, not with 'new'.
+// It should not bt copied.
+class IRFormInterface {
+public:
+ IRFormInterface(Dwarf_Debug dbg,
+ Dwarf_Attribute attr,IRCUdata &cudata,IRAttr & irattr):
+ dbg_(dbg),attr_(attr),cudata_(cudata),irattr_(irattr) {};
+ // Do not free anything we did not create here.
+ ~IRFormInterface() {};
+ Dwarf_Debug dbg_;
+ Dwarf_Attribute attr_;
+ IRCUdata &cudata_;
+ IRAttr &irattr_;
+private:
+
+ // Do not instantiate.
+ IRFormInterface();
+ IRFormInterface& operator= (const IRFormInterface &ir);
+
+};
+
+
+IRForm *formFactory(Dwarf_Debug dbg,
+ Dwarf_Attribute attr,IRCUdata &cudata,IRAttr & irattr)
+{
+ Dwarf_Error err = 0;
+ IRFormInterface interface(dbg,attr,cudata,irattr);
+ enum Dwarf_Form_Class cl = irattr.getFormClass();
+ switch(cl) {
+ case DW_FORM_CLASS_UNKNOWN:
+ break;
+ case DW_FORM_CLASS_ADDRESS:
+ {
+ IRFormAddress *f = new IRFormAddress(&interface);
+ // FIXME: do we need to do anything about the symbol here?
+ return f;
+ }
+ break;
+ case DW_FORM_CLASS_BLOCK:
+ {
+ IRFormBlock *f = new IRFormBlock(&interface);
+ //FIXME
+ return f;
+ }
+ break;
+ case DW_FORM_CLASS_CONSTANT:
+ {
+ IRFormConstant *f = new IRFormConstant(&interface);
+ //FIXME
+ return f;
+ }
+ break;
+ case DW_FORM_CLASS_EXPRLOC:
+ {
+ IRFormExprloc *f = new IRFormExprloc(&interface);
+ //FIXME
+ return f;
+ }
+ break;
+ case DW_FORM_CLASS_FLAG:
+ {
+ IRFormFlag *f = new IRFormFlag(&interface);
+ //FIXME
+ return f;
+ }
+ break;
+ case DW_FORM_CLASS_LINEPTR:
+ {
+ IRFormLinePtr *f = new IRFormLinePtr(&interface);
+ //FIXME
+ return f;
+ }
+ break;
+ case DW_FORM_CLASS_LOCLISTPTR:
+ {
+ IRFormLoclistPtr *f = new IRFormLoclistPtr(&interface);
+ //FIXME
+ return f;
+ }
+ break;
+ case DW_FORM_CLASS_MACPTR:
+ {
+ IRFormMacPtr *f = new IRFormMacPtr(&interface);
+ //FIXME
+ return f;
+ }
+ break;
+ case DW_FORM_CLASS_RANGELISTPTR:
+ {
+ IRFormRangelistPtr *f = new IRFormRangelistPtr(&interface);
+ //FIXME
+ return f;
+ }
+ break;
+ case DW_FORM_CLASS_REFERENCE:
+ {
+ IRFormReference *f = new IRFormReference(&interface);
+ //FIXME
+ return f;
+ }
+ break;
+ case DW_FORM_CLASS_STRING:
+ {
+ IRFormString *f = new IRFormString(&interface);
+ return f;
+ }
+ break;
+ case DW_FORM_CLASS_FRAMEPTR: /* SGI/IRIX extension. */
+ {
+ IRFormFramePtr *f = new IRFormFramePtr(&interface);
+ //FIXME
+ return f;
+ }
+ break;
+ default:
+ break;
+ }
+ return new IRFormUnknown();
+}
+
+IRFormAddress::IRFormAddress(IRFormInterface * interface)
+{
+ Dwarf_Addr val = 0;
+ Dwarf_Error error = 0;
+ int res = dwarf_formaddr(interface->attr_,&val, &error);
+ if(res != DW_DLV_OK) {
+ cerr << "Unable to read flag value. Impossible error.\n" << endl;
+ exit(1);
+ }
+ // FIXME do we need to do anything about the symbol here?
+ address_ = val;
+}
+IRFormBlock::IRFormBlock(IRFormInterface * interface)
+{
+ Dwarf_Block *blockptr = 0;
+ Dwarf_Error error = 0;
+ int res = dwarf_formblock(interface->attr_,&blockptr, &error);
+ if(res != DW_DLV_OK) {
+ cerr << "Unable to read flag value. Impossible error.\n" << endl;
+ exit(1);
+ }
+ insertBlock(blockptr);
+ dwarf_dealloc(interface->dbg_,blockptr,DW_DLA_BLOCK);
+}
+IRFormConstant::IRFormConstant(IRFormInterface * interface)
+{
+ enum Signedness oursign = SIGN_NOT_SET;
+ Dwarf_Unsigned uval = 0;
+ Dwarf_Signed sval = 0;
+ Dwarf_Error error = 0;
+ int ress = dwarf_formsdata(interface->attr_, &sval,&error);
+ int resu = dwarf_formudata(interface->attr_, &uval,&error);
+ if(resu == DW_DLV_OK ) {
+ if(ress == DW_DLV_OK) {
+ oursign = SIGN_UNKNOWN;
+ } else {
+ oursign = UNSIGNED;
+ sval = static_cast<Dwarf_Signed>(uval);
+ }
+ } else {
+ if(ress == DW_DLV_OK) {
+ oursign = SIGNED;
+ uval = static_cast<Dwarf_Unsigned>(sval);
+ } else {
+ cerr << "Unable to read constant value. Impossible error.\n"
+ << endl;
+ exit(1);
+ }
+ }
+ setValues(sval, uval, oursign);
+}
+IRFormExprloc::IRFormExprloc(IRFormInterface * interface)
+{
+ Dwarf_Unsigned len = 0;
+ Dwarf_Ptr data = 0;
+ Dwarf_Error error = 0;
+ int res = dwarf_formexprloc(interface->attr_,&len, &data, &error);
+ if(res != DW_DLV_OK) {
+ cerr << "Unable to read flag value. Impossible error.\n" << endl;
+ exit(1);
+ }
+ insertBlock(len,data);
+}
+IRFormFlag::IRFormFlag(IRFormInterface * interface)
+{
+ Dwarf_Bool flagval = 0;
+ Dwarf_Error error = 0;
+ int res = dwarf_formflag(interface->attr_,&flagval, &error);
+ if(res != DW_DLV_OK) {
+ cerr << "Unable to read flag value. Impossible error.\n" << endl;
+ exit(1);
+ }
+}
+
+// We are simply assuming (here) that the value is a global offset
+// to some section or other.
+// Calling code ensures that is true.
+//
+static Dwarf_Unsigned
+get_section_offset(IRFormInterface * interface)
+{
+ Dwarf_Unsigned uval = 0;
+ Dwarf_Signed sval = 0;
+ Dwarf_Error error = 0;
+ Dwarf_Off sectionoffset = 0;
+ int resu = 0;
+ // The following allows more sorts of value than
+ // we really want to allow here, but that is
+ // harmless, we believe.
+ int resgf = dwarf_global_formref(interface->attr_,
+ &sectionoffset, &error);
+ if(resgf == DW_DLV_OK ) {
+ return sectionoffset;
+ }
+ resu = dwarf_formudata(interface->attr_, &uval,&error);
+ if(resu != DW_DLV_OK ) {
+ int ress = dwarf_formsdata(interface->attr_, &sval,&error);
+ if(ress == DW_DLV_OK) {
+ uval = static_cast<Dwarf_Unsigned>(sval);
+ } else {
+ cerr << "Unable to read constant offset value. Impossible error.\n"
+ << endl;
+ exit(1);
+ }
+ }
+ return uval;
+}
+IRFormLoclistPtr::IRFormLoclistPtr(IRFormInterface * interface)
+{
+ Dwarf_Unsigned uval = get_section_offset(interface);
+ setOffset(uval);
+}
+IRFormLinePtr::IRFormLinePtr(IRFormInterface * interface)
+{
+ Dwarf_Unsigned uval = get_section_offset(interface);
+ setOffset(uval);
+}
+IRFormMacPtr::IRFormMacPtr(IRFormInterface * interface)
+{
+ Dwarf_Unsigned uval = get_section_offset(interface);
+ setOffset(uval);
+}
+IRFormRangelistPtr::IRFormRangelistPtr(IRFormInterface * interface)
+{
+ Dwarf_Unsigned uval = get_section_offset(interface);
+ setOffset(uval);
+}
+IRFormFramePtr::IRFormFramePtr(IRFormInterface * interface)
+{
+ Dwarf_Unsigned uval = get_section_offset(interface);
+ setOffset(uval);
+}
+
+// This is a .debug_info to .debug_info (or .debug_types to .debug_types)
+// reference.
+IRFormReference::IRFormReference(IRFormInterface * interface)
+{
+ Dwarf_Off val = 0;
+ Dwarf_Error error = 0;
+ Dwarf_Half form = interface->irattr_.getFinalForm();
+ if(form == DW_FORM_ref_sig8) {
+ Dwarf_Sig8 val8;
+ int res = dwarf_formsig8(interface->attr_,&val8, &error);
+ if(res != DW_DLV_OK) {
+ cerr << "Unable to read sig8 reference. Impossible error.\n" << endl;
+ exit(1);
+ }
+ setSignature(&val8);
+ return;
+ }
+ if(form == DW_FORM_ref_addr) {
+ int res = dwarf_global_formref(interface->attr_,&val, &error);
+ if(res != DW_DLV_OK) {
+ cerr << "Unable to read reference. Impossible error.\n" << endl;
+ exit(1);
+ }
+ setOffset(val);
+ return;
+ }
+ // Otherwise it is (if a correct FORM for a .debug_info reference)
+ // a local CU offset, and we record it as such..
+ int res = dwarf_formref(interface->attr_,&val, &error);
+ if(res != DW_DLV_OK) {
+ cerr << "Unable to read reference. Impossible error.\n" << endl;
+ exit(1);
+ }
+ setCUOffset(val);
+}
+
+// Global static data used to initialized a sig8 reliably.
+static Dwarf_Sig8 zero_sig8;
+// Initialization helper function.
+void
+IRFormReference::initSig8()
+{
+ typeSig8_ = zero_sig8;
+}
+
+IRFormString::IRFormString(IRFormInterface * interface)
+{
+ char *str = 0;
+ Dwarf_Error error = 0;
+ int res = dwarf_formstring(interface->attr_,&str, &error);
+ if(res != DW_DLV_OK) {
+ cerr << "Unable to read string. Impossible error.\n" << endl;
+ exit(1);
+ }
+ setString(str);
+}
+
+
+
diff --git a/dwarfgen/createirepfrombinary.cc b/dwarfgen/createirepfrombinary.cc
new file mode 100644
index 0000000..193e35d
--- /dev/null
+++ b/dwarfgen/createirepfrombinary.cc
@@ -0,0 +1,608 @@
+/*
+ Copyright (C) 2010-2011 David Anderson.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+*/
+
+// createirepfrombinary.cc
+
+// Reads an object and inserts its dwarf data into
+// an object intended to hold all the dwarf data.
+
+#include "config.h"
+#include <unistd.h>
+#include <stdlib.h> // for exit
+#include <iostream>
+#include <string>
+#include <list>
+#include <vector>
+#include <string.h> // For memset etc
+#include <sys/stat.h> //open
+#include <fcntl.h> //open
+#include "elf.h"
+#include "gelf.h"
+#include "strtabdata.h"
+#include "dwarf.h"
+#include "libdwarf.h"
+#include "irepresentation.h"
+#include "createirepfrombinary.h"
+#include "general.h" // For IToHex()
+
+using std::string;
+using std::cout;
+using std::cerr;
+using std::endl;
+using std::vector;
+using std::list;
+
+static void readFrameDataFromBinary(Dwarf_Debug dbg, IRepresentation & irep);
+static void readMacroDataFromBinary(Dwarf_Debug dbg, IRepresentation & irep);
+static void readCUDataFromBinary(Dwarf_Debug dbg, IRepresentation & irep);
+
+class DbgInAutoCloser {
+public:
+ DbgInAutoCloser(Dwarf_Debug dbg,int fd): dbg_(dbg),fd_(fd) {};
+ ~DbgInAutoCloser() {
+ Dwarf_Error err = 0;
+ dwarf_finish(dbg_,&err);
+ close(fd_);
+ };
+private:
+ Dwarf_Debug dbg_;
+ int fd_;
+};
+
+
+void
+createIrepFromBinary(const std::string &infile,
+ IRepresentation & irep)
+{
+ Dwarf_Debug dbg = 0;
+ Dwarf_Error err;
+ int fd = open(infile.c_str(),O_RDONLY, 0);
+ if(fd < 0 ) {
+ cerr << "Unable to open " << infile <<
+ " for reading." << endl;
+ exit(1);
+ }
+ // All reader error handling is via the err argument.
+ int res = dwarf_init(fd,DW_DLC_READ,
+ 0,
+ 0,
+ &dbg,
+ &err);
+ if(res != DW_DLV_OK) {
+ close(fd);
+ cerr << "Error init-ing " << infile <<
+ " for reading." << endl;
+ exit(1);
+ }
+
+ DbgInAutoCloser closer(dbg,fd);
+
+ readFrameDataFromBinary(dbg,irep);
+ readCUDataFromBinary(dbg,irep);
+ readMacroDataFromBinary(dbg,irep);
+
+ return;
+}
+
+static void
+readFrameDataFromBinary(Dwarf_Debug dbg, IRepresentation & irep)
+{
+ Dwarf_Error err = 0;
+ Dwarf_Cie * cie_data = 0;
+ Dwarf_Signed cie_count = 0;
+ Dwarf_Fde * fde_data = 0;
+ Dwarf_Signed fde_count = 0;
+ int res = dwarf_get_fde_list(dbg,
+ &cie_data,
+ &cie_count,
+ &fde_data,
+ &fde_count,
+ &err);
+ if(res == DW_DLV_NO_ENTRY) {
+ // No frame data.
+ return;
+ }
+ if(res == DW_DLV_ERROR) {
+ cerr << "Error reading frame data " << endl;
+ exit(1);
+ }
+
+ for(Dwarf_Signed i =0; i < cie_count; ++i) {
+ Dwarf_Unsigned bytes_in_cie = 0;
+ Dwarf_Small version = 0;
+ char * augmentation = 0;
+ Dwarf_Unsigned code_alignment_factor = 0;
+ Dwarf_Signed data_alignment_factor = 0;
+ Dwarf_Half return_address_register_rule = 0;
+ Dwarf_Ptr initial_instructions = 0;
+ Dwarf_Unsigned initial_instructions_length = 0;
+ res = dwarf_get_cie_info(cie_data[i], &bytes_in_cie,
+ &version,&augmentation, &code_alignment_factor,
+ &data_alignment_factor,&return_address_register_rule,
+ &initial_instructions,&initial_instructions_length,
+ &err);
+ if(res != DW_DLV_OK) {
+ cerr << "Error reading frame data cie index " << i << endl;
+ exit(1);
+ }
+ // Index in cie_data must match index in ciedata_, here
+ // correct by construction.
+ IRCie cie(bytes_in_cie,version,augmentation,code_alignment_factor,
+ data_alignment_factor,return_address_register_rule,
+ initial_instructions,initial_instructions_length);
+ irep.framedata().insert_cie(cie);
+ }
+ for(Dwarf_Signed i =0; i < fde_count; ++i) {
+ Dwarf_Addr low_pc = 0;
+ Dwarf_Unsigned func_length = 0;
+ Dwarf_Ptr fde_bytes = 0;
+ Dwarf_Unsigned fde_byte_length = 0;
+ Dwarf_Off cie_offset = 0;
+ Dwarf_Signed cie_index = 0;
+ Dwarf_Off fde_offset = 0;
+ res = dwarf_get_fde_range(fde_data[i], &low_pc,
+ &func_length,&fde_bytes, &fde_byte_length,
+ &cie_offset,&cie_index,
+ &fde_offset,
+ &err);
+ if(res != DW_DLV_OK) {
+ cerr << "Error reading frame data fde index " << i << endl;
+ exit(1);
+ }
+ IRFde fde(low_pc,func_length,fde_bytes,fde_byte_length,
+ cie_offset, cie_index,fde_offset);
+ Dwarf_Ptr instr_in = 0;
+ Dwarf_Unsigned instr_len = 0;
+ res = dwarf_get_fde_instr_bytes(fde_data[i],
+ &instr_in, &instr_len, &err);
+ if(res != DW_DLV_OK) {
+ cerr << "Error reading frame data fde instructions " << i << endl;
+ exit(1);
+ }
+ fde.get_fde_instrs_into_ir(instr_in,instr_len);
+ irep.framedata().insert_fde(fde);
+ }
+ dwarf_fde_cie_list_dealloc(dbg,cie_data,cie_count,
+ fde_data,fde_count);
+}
+
+
+static void
+readCUMacroDataFromBinary(Dwarf_Debug dbg, IRepresentation & irep,
+ Dwarf_Unsigned macrodataoffset,IRCUdata &cu)
+{
+ // Arbitrary, but way too high to be real!
+ // Probably should be lower.
+ Dwarf_Unsigned maxcount = 1000000000;
+ Dwarf_Error error;
+ Dwarf_Signed mcount=0;
+ Dwarf_Macro_Details *md = 0;
+ int res = dwarf_get_macro_details(dbg,macrodataoffset,
+ maxcount, &mcount, &md, &error);
+ if(res == DW_DLV_OK) {
+ IRMacro &macrodata = irep.macrodata();
+ vector<IRMacroRecord> mvec = macrodata.getMacroVec();
+ mvec.reserve(mcount);
+ Dwarf_Unsigned dieoffset = cu.baseDie().getGlobalOffset();
+ Dwarf_Macro_Details *mdp = md;
+ for(int i = 0; i < mcount; ++i, mdp++ ) {
+ IRMacroRecord i(dieoffset,mdp->dmd_offset,
+ mdp->dmd_type, mdp->dmd_lineno,
+ mdp->dmd_fileindex, mdp->dmd_macro?mdp->dmd_macro:"");
+ mvec.push_back(i);
+ }
+ }
+ dwarf_dealloc(dbg, md, DW_DLA_STRING);
+}
+
+void
+get_basic_attr_data_one_attr(Dwarf_Debug dbg,
+ Dwarf_Attribute attr,IRCUdata &cudata,IRAttr & irattr)
+{
+ Dwarf_Error error;
+ Dwarf_Half attrnum = 0;
+ Dwarf_Half dirform = 0;
+ Dwarf_Half indirform = 0;
+ int res = dwarf_whatattr(attr,&attrnum,&error);
+ if(res != DW_DLV_OK) {
+ cerr << "Unable to get attr number " << endl;
+ exit(1);
+ }
+ res = dwarf_whatform(attr,&dirform,&error);
+ if(res != DW_DLV_OK) {
+ cerr << "Unable to get attr form " << endl;
+ exit(1);
+ }
+
+ res = dwarf_whatform_direct(attr,&indirform,&error);
+ if(res != DW_DLV_OK) {
+ cerr << "Unable to get attr direct form " << endl;
+ exit(1);
+ }
+ irattr.setBaseData(attrnum,dirform,indirform);
+ enum Dwarf_Form_Class cl = dwarf_get_form_class(
+ cudata.getVersionStamp(), attrnum,
+ cudata.getOffsetSize(), dirform);
+ irattr.setFormClass(cl);
+ if (cl == DW_FORM_CLASS_UNKNOWN) {
+ cerr << "Unable to figure out form class. ver " <<
+ cudata.getVersionStamp() <<
+ " attrnum " << attrnum <<
+ " offsetsize " << cudata.getOffsetSize() <<
+ " formnum " << dirform << endl;
+ return;
+ }
+ irattr.setFormData(formFactory(dbg,attr,cudata,irattr));
+}
+void
+get_basic_die_data(Dwarf_Debug dbg,Dwarf_Die indie,IRDie &irdie)
+{
+ Dwarf_Half tagval = 0;
+ Dwarf_Error error = 0;
+ int res = dwarf_tag(indie,&tagval,&error);
+ if(res != DW_DLV_OK) {
+ cerr << "Unable to get die tag "<< endl;
+ exit(1);
+ }
+ Dwarf_Off goff = 0;
+ res = dwarf_dieoffset(indie,&goff,&error);
+ if(res != DW_DLV_OK) {
+ cerr << "Unable to get die offset "<< endl;
+ exit(1);
+ }
+ Dwarf_Off localoff = 0;
+ res = dwarf_die_CU_offset(indie,&localoff,&error);
+ if(res != DW_DLV_OK) {
+ cerr << "Unable to get cu die offset "<< endl;
+ exit(1);
+ }
+ irdie.setBaseData(tagval,goff,localoff);
+}
+
+
+static void
+get_attrs_of_die(Dwarf_Die in_die,IRDie &irdie,
+ IRCUdata &data, IRepresentation &irep,
+ Dwarf_Debug dbg)
+{
+ Dwarf_Error error = 0;
+ Dwarf_Attribute *atlist = 0;
+ Dwarf_Signed atcnt = 0;
+ std::list<IRAttr> &attrlist = irdie.getAttributes();
+ int res = dwarf_attrlist(in_die, &atlist,&atcnt,&error);
+ if(res == DW_DLV_NO_ENTRY) {
+ return;
+ }
+ if(res == DW_DLV_ERROR) {
+ cerr << "dwarf_attrlist failed " << endl;
+ exit(1);
+ }
+ for (Dwarf_Signed i = 0; i < atcnt; ++i) {
+ Dwarf_Attribute attr = atlist[i];
+ IRAttr irattr;
+ get_basic_attr_data_one_attr(dbg,attr,data,irattr);
+ attrlist.push_back(irattr);
+
+ }
+ dwarf_dealloc(dbg,atlist, DW_DLA_LIST);
+}
+
+// Invariant: IRDie and IRCUdata is in the irep tree,
+// not local record references to local scopes.
+static void
+get_children_of_die(Dwarf_Die in_die,IRDie&irdie,
+ IRCUdata &ircudata,
+ IRepresentation &irep,
+ Dwarf_Debug dbg)
+{
+ Dwarf_Die curchilddie = 0;
+ Dwarf_Error error = 0;
+ int res = dwarf_child(in_die,&curchilddie,&error);
+ if(res == DW_DLV_NO_ENTRY) {
+ return;
+ }
+ if(res == DW_DLV_ERROR) {
+ cerr << "dwarf_child failed " << endl;
+ exit(1);
+ }
+ //std::list<IRDie> & childlist = irdie.getChildren();
+ int childcount = 0;
+ for(;;) {
+ IRDie child;
+ get_basic_die_data(dbg,curchilddie,child);
+ get_attrs_of_die(curchilddie,child,ircudata,irep,dbg);
+ irdie.addChild(child);
+ IRDie &lastchild = irdie.lastChild();
+
+ get_children_of_die(curchilddie,lastchild,ircudata,irep,dbg);
+ ++childcount;
+
+ Dwarf_Die tchild = 0;
+ res = dwarf_siblingof(dbg,curchilddie,&tchild,&error);
+ if(res == DW_DLV_NO_ENTRY) {
+ break;
+ }
+ if(res == DW_DLV_ERROR) {
+ cerr << "dwarf_siblingof failed " << endl;
+ exit(1);
+ }
+ dwarf_dealloc(dbg,curchilddie,DW_DLA_DIE);
+ curchilddie = tchild;
+ }
+ dwarf_dealloc(dbg,curchilddie,DW_DLA_DIE);
+}
+
+static void
+get_linedata_of_cu_die(Dwarf_Die in_die,IRDie&irdie,
+ IRCUdata &ircudata,
+ IRepresentation &irep,
+ Dwarf_Debug dbg)
+{
+ Dwarf_Error error = 0;
+ char **srcfiles = 0;
+ Dwarf_Signed srccount = 0;
+ IRCULineData&culinesdata = ircudata.getCULines();
+ int res = dwarf_srcfiles(in_die,&srcfiles, &srccount,&error);
+ if(res == DW_DLV_ERROR) {
+ cerr << "dwarf_srcfiles failed " << endl;
+ exit(1);
+ } else if (res == DW_DLV_NO_ENTRY) {
+ // No data.
+ return;
+ }
+
+ std::vector<IRCUSrcfile> &srcs = culinesdata.get_cu_srcfiles();
+ for (Dwarf_Signed i = 0; i < srccount; ++i) {
+ IRCUSrcfile S(srcfiles[i]);
+ srcs.push_back(S);
+ /* use srcfiles[i] */
+ dwarf_dealloc(dbg, srcfiles[i], DW_DLA_STRING);
+ }
+ dwarf_dealloc(dbg, srcfiles, DW_DLA_LIST);
+
+ Dwarf_Line * linebuf = 0;
+ Dwarf_Signed linecnt = 0;
+ int res2 = dwarf_srclines(in_die,&linebuf,&linecnt, &error);
+ if(res == DW_DLV_ERROR) {
+ cerr << "dwarf_srclines failed " << endl;
+ exit(1);
+ } else if (res == DW_DLV_NO_ENTRY) {
+ // No data.
+ cerr << "dwarf_srclines failed NO_ENTRY, crazy "
+ "since srcfiles worked" << endl;
+ exit(1);
+ }
+
+ std::vector<IRCULine> &lines = culinesdata.get_cu_lines();
+ for(Dwarf_Signed j = 0; j < linecnt ; ++j ) {
+ Dwarf_Line li = linebuf[j];
+ int lres;
+
+ Dwarf_Addr address = 0;
+ lres = dwarf_lineaddr(li,&address,&error);
+ if (lres != DW_DLV_OK) {
+ cerr << "dwarf_lineaddr failed. " << endl;
+ exit(1);
+ }
+ Dwarf_Bool is_addr_set = 0;
+ lres = dwarf_line_is_addr_set(li,&is_addr_set,&error);
+ if (lres != DW_DLV_OK) {
+ cerr << "dwarf_line_is_addr_set failed. " << endl;
+ exit(1);
+ }
+ Dwarf_Unsigned fileno = 0;
+ lres = dwarf_line_srcfileno(li,&fileno,&error);
+ if (lres != DW_DLV_OK) {
+ cerr << "dwarf_srcfileno failed. " << endl;
+ exit(1);
+ }
+ Dwarf_Unsigned lineno = 0;
+ lres = dwarf_lineno(li,&lineno,&error);
+ if (lres != DW_DLV_OK) {
+ cerr << "dwarf_lineno failed. " << endl;
+ exit(1);
+ }
+ Dwarf_Unsigned lineoff = 0;
+ lres = dwarf_lineoff_b(li,&lineoff,&error);
+ if (lres != DW_DLV_OK) {
+ cerr << "dwarf_lineoff failed. " << endl;
+ exit(1);
+ }
+ char *linesrctmp = 0;
+ lres = dwarf_linesrc(li,&linesrctmp,&error);
+ if (lres != DW_DLV_OK) {
+ cerr << "dwarf_linesrc failed. " << endl;
+ exit(1);
+ }
+ // libdwarf is trying to generate a full path,
+ // the string here is that generated data, not
+ // simply the 'file' path represented by the
+ // file number (fileno).
+ std::string linesrc(linesrctmp);
+
+
+ Dwarf_Bool is_stmt = 0;
+ lres = dwarf_linebeginstatement(li,&is_stmt,&error);
+ if (lres != DW_DLV_OK) {
+ cerr << "dwarf_linebeginstatement failed. " << endl;
+ exit(1);
+ }
+
+ Dwarf_Bool basic_block = 0;
+ lres = dwarf_lineblock(li,&basic_block,&error);
+ if (lres != DW_DLV_OK) {
+ cerr << "dwarf_lineblock failed. " << endl;
+ exit(1);
+ }
+
+ Dwarf_Bool end_sequence = 0;
+ lres = dwarf_lineendsequence(li,&end_sequence,&error);
+ if (lres != DW_DLV_OK) {
+ cerr << "dwarf_lineendsequence failed. " << endl;
+ exit(1);
+ }
+
+ Dwarf_Bool prologue_end = 0;
+ Dwarf_Bool epilogue_begin = 0;
+ Dwarf_Unsigned isa = 0;
+ Dwarf_Unsigned discriminator = 0;
+ lres = dwarf_prologue_end_etc(li,&prologue_end,
+ &epilogue_begin,&isa,&discriminator,&error);
+ if (lres != DW_DLV_OK) {
+ cerr << "dwarf_prologue_end_etc failed. " << endl;
+ exit(1);
+ }
+
+ IRCULine L(address,
+ is_addr_set,
+ fileno,
+ lineno,
+ lineoff,
+ linesrc,
+ is_stmt,
+ basic_block,
+ end_sequence,
+ prologue_end,epilogue_begin,
+ isa,discriminator);
+ lines.push_back(L);
+ }
+ dwarf_srclines_dealloc(dbg, linebuf, linecnt);
+}
+
+static bool
+getToplevelOffsetAttr(Dwarf_Die cu_die,Dwarf_Half attrnumber,
+ Dwarf_Unsigned &offset_out)
+{
+ Dwarf_Error error = 0;
+ Dwarf_Off offset = 0;
+ Dwarf_Attribute attr = 0;
+ int res = dwarf_attr(cu_die,attrnumber,&attr, &error);
+ bool foundit = false;
+ Dwarf_Off sectoff = 0;
+ if(res == DW_DLV_OK) {
+ Dwarf_Signed sval = 0;
+ Dwarf_Unsigned uval = 0;
+ res = dwarf_global_formref(attr,&offset,&error);
+ if(res == DW_DLV_OK) {
+ foundit = true;
+ offset_out = offset;
+ }
+ }
+ return foundit;
+}
+
+// We record the .debug_info info for each CU found
+// To start with we restrict attention to very few DIEs and
+// attributes, but intend to get all eventually.
+static void
+readCUDataFromBinary(Dwarf_Debug dbg, IRepresentation & irep)
+{
+ Dwarf_Error error;
+ int cu_number = 0;
+ std::list<IRCUdata> &culist = irep.infodata().getCUData();
+
+ for(;;++cu_number) {
+ Dwarf_Unsigned cu_header_length = 0;
+ Dwarf_Half version_stamp = 0;
+ Dwarf_Unsigned abbrev_offset = 0;
+ Dwarf_Half address_size = 0;
+ Dwarf_Unsigned next_cu_header = 0;
+ Dwarf_Half offset_size = 0;
+ Dwarf_Half extension_size = 0;
+ Dwarf_Die no_die = 0;
+ Dwarf_Die cu_die = 0;
+ int res = DW_DLV_ERROR;
+ res = dwarf_next_cu_header_b(dbg,&cu_header_length,
+ &version_stamp, &abbrev_offset, &address_size,
+ &offset_size, &extension_size,
+ &next_cu_header, &error);
+ if(res == DW_DLV_ERROR) {
+ cerr <<"Error in dwarf_next_cu_header"<< endl;
+ exit(1);
+ }
+ if(res == DW_DLV_NO_ENTRY) {
+ /* Done. */
+ return;
+ }
+ IRCUdata cudata(cu_header_length,version_stamp,
+ abbrev_offset,address_size, offset_size,
+ extension_size,next_cu_header);
+
+ // The CU will have a single sibling (well, it is
+ // not exactly a sibling, but close enough), a cu_die.
+ res = dwarf_siblingof(dbg,no_die,&cu_die,&error);
+ if(res == DW_DLV_ERROR) {
+ cerr <<"Error in dwarf_siblingof on CU die "<< endl;
+ exit(1);
+ }
+ if(res == DW_DLV_NO_ENTRY) {
+ /* Impossible case. */
+ cerr <<"no Entry! in dwarf_siblingof on CU die "<< endl;
+ exit(1);
+ }
+ Dwarf_Off macrooffset = 0;
+ bool foundmsect = getToplevelOffsetAttr(cu_die,DW_AT_macro_info,
+ macrooffset);
+ Dwarf_Off linesoffset = 0;
+ bool foundlines = getToplevelOffsetAttr(cu_die,DW_AT_stmt_list,
+ linesoffset);
+ Dwarf_Off dieoff = 0;
+ res = dwarf_dieoffset(cu_die,&dieoff,&error);
+ if(res != DW_DLV_OK) {
+ cerr << "Unable to get cu die offset for macro infomation "<< endl;
+ exit(1);
+ }
+ if(foundmsect) {
+ cudata.setMacroData(macrooffset,dieoff);
+ }
+ if(foundlines) {
+ cudata.setLineData(linesoffset,dieoff);
+ }
+ culist.push_back(cudata);
+ IRCUdata & treecu = irep.infodata().lastCU();
+ IRDie &cuirdie = treecu.baseDie();
+ get_basic_die_data(dbg,cu_die,cuirdie);
+ get_attrs_of_die(cu_die,cuirdie,treecu,irep,dbg);
+ get_children_of_die(cu_die,cuirdie,treecu,irep,dbg);
+ get_linedata_of_cu_die(cu_die,cuirdie,treecu,irep,dbg);
+ dwarf_dealloc(dbg,cu_die,DW_DLA_DIE);
+ }
+ // If we want pointers from child to parent now is the time
+ // we can construct them.
+}
+
+// We read thru the CU headers and the CU die to find
+// the macro info for each CU (if any).
+// We record the CU macro info for each CU found (using
+// the value of the DW_AT_macro_info attribute, if any).
+static void
+readMacroDataFromBinary(Dwarf_Debug dbg, IRepresentation & irep)
+{
+
+ list<IRCUdata> &cudata = irep.infodata().getCUData();
+ list<IRCUdata>::iterator it = cudata.begin();
+ int ct = 0;
+ for( ; it != cudata.end(); ++it,++ct) {
+ Dwarf_Unsigned macrooffset = 0;
+ Dwarf_Unsigned cudieoffset = 0;
+ bool foundmsect = it->hasMacroData(&macrooffset,&cudieoffset);
+ if(foundmsect) {
+ readCUMacroDataFromBinary(dbg, irep, macrooffset,*it);
+ }
+ }
+}
+
diff --git a/dwarfgen/createirepfrombinary.h b/dwarfgen/createirepfrombinary.h
new file mode 100644
index 0000000..32d7d04
--- /dev/null
+++ b/dwarfgen/createirepfrombinary.h
@@ -0,0 +1,22 @@
+/*
+ Copyright (C) 2010-2011 David Anderson.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+*/
+
+// createirepfrombinary.h
+
+
+void createIrepFromBinary(const std::string &infile,
+ IRepresentation & irep);
diff --git a/dwarfgen/dwarfgen.1 b/dwarfgen/dwarfgen.1
new file mode 100644
index 0000000..dd90cbb
--- /dev/null
+++ b/dwarfgen/dwarfgen.1
@@ -0,0 +1,10 @@
+.TH DWARFGEN
+.SH NAME
+dwarfgen \- Generate example DWARF data.
+.SH SYNOPSIS
+.B dwarfgen
+.SH DESCRIPTION
+The
+.B dwarfgen
+command creates DWARF sections as requested by specific options.
+The command is under development as of January 2010.
diff --git a/dwarfgen/dwarfgen.cc b/dwarfgen/dwarfgen.cc
new file mode 100755
index 0000000..1eae4a4
--- /dev/null
+++ b/dwarfgen/dwarfgen.cc
@@ -0,0 +1,666 @@
+/*
+ Copyright (C) 2010-2011 David Anderson.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+*/
+// dwarfgen.cc
+//
+// Using some information source, create a tree of dwarf
+// information (speaking of a DIE tree).
+// Turn the die tree into dwarfdata using libdwarf producer
+// and write the resulting data in an object file.
+// It is a bit inconsistent in error handling just to
+// demonstrate the various possibilities using the producer
+// library.
+//
+// dwarfgen [-t def|obj|txt] [-o outpath] [-c cunum] path
+
+// where -t means what sort of input to read
+// def means predefined (no input is read, the output
+// is based on some canned setups built into dwarfgen).
+// 'path' is ignored in this case. This is the default.
+//
+// obj means 'path' is required, it is the object file to
+// read (the dwarf sections are duplicated in the output file)
+//
+// txt means 'path' is required, path must contain plain text
+// (in a form rather like output by dwarfdump)
+// that defines the dwarf that is to be output.
+//
+// where -o means specify the pathname of the output object. If not
+// supplied testout.o is used as the default output path.
+// where -c supplies a CU number of the obj input to output
+// because the dwarf producer wants just one CU.
+// Default is -1 which won't match anything.
+
+#include "config.h"
+#include <unistd.h>
+#include <stdlib.h> // for exit
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+#include <string>
+#include <list>
+#include <vector>
+#include <string.h> // For memset etc
+#include <sys/stat.h> //open
+#include <fcntl.h> //open
+#include "general.h"
+#include "elf.h"
+#include "gelf.h"
+#include "strtabdata.h"
+#include "dwarf.h"
+#include "libdwarf.h"
+#include "irepresentation.h"
+#include "ireptodbg.h"
+#include "createirepfrombinary.h"
+
+using std::string;
+using std::cout;
+using std::cerr;
+using std::endl;
+using std::vector;
+
+static void write_object_file(Dwarf_P_Debug dbg, IRepresentation &irep);
+static void write_text_section(Elf * elf);
+static void write_generated_dbg(Dwarf_P_Debug dbg,Elf * elf,
+ IRepresentation &irep);
+
+static string outfile("testout.o");
+static string infile;
+static enum WhichInputSource { OptNone, OptReadText,OptReadBin,OptPredefined}
+ whichinput(OptPredefined);
+
+
+// This is a global so thet CallbackFunc can get to it
+// If we used the dwarf_producer_init_c() user_data pointer
+// creatively we would not need a global.
+static IRepresentation Irep;
+
+static Elf * elf = 0;
+static Elf32_Ehdr * ehp = 0;
+static strtabdata secstrtab;
+
+// loff_t is signed for some reason (strange) but we make offsets unsigned.
+#define LOFFTODWUNS(x) ( (Dwarf_Unsigned)(x))
+
+class SectionFromDwarf {
+public:
+ std::string name_;
+ Dwarf_Unsigned section_name_itself_;
+ ElfSymIndex section_name_symidx_;
+ int size_;
+ Dwarf_Unsigned type_;
+ Dwarf_Unsigned flags_;
+ Dwarf_Unsigned link_;
+ Dwarf_Unsigned info_;
+private:
+ ElfSectIndex elf_sect_index_;
+ Dwarf_Unsigned lengthWrittenToElf_;
+public:
+ Dwarf_Unsigned getNextOffset() { return lengthWrittenToElf_; }
+ void setNextOffset(Dwarf_Unsigned v) { lengthWrittenToElf_ = v; }
+
+ unsigned getSectionNameSymidx() {
+ return section_name_symidx_.getSymIndex(); };
+ SectionFromDwarf():section_name_itself_(0),
+ section_name_symidx_(0),
+ size_(0),type_(0),flags_(0),
+ link_(0), info_(0), elf_sect_index_(0),
+ lengthWrittenToElf_(0) {} ;
+ ~SectionFromDwarf() {};
+ void setSectIndex(ElfSectIndex v) { elf_sect_index_ = v;}
+ ElfSectIndex getSectIndex() const { return elf_sect_index_;}
+ SectionFromDwarf(const std::string&name,
+ int size,Dwarf_Unsigned type,Dwarf_Unsigned flags,
+ Dwarf_Unsigned link, Dwarf_Unsigned info):
+ name_(name),
+ size_(size),type_(type),flags_(flags),
+ link_(link), info_(info), elf_sect_index_(0),
+ lengthWrittenToElf_(0) {
+ // Now create section name string section.
+ section_name_itself_ = secstrtab.addString(name.c_str());
+ ElfSymbols& es = Irep.getElfSymbols();
+ // Now creat a symbol for the section name.
+ // (which has its own string table)
+ section_name_symidx_ = es.addElfSymbol(0,name);
+ } ;
+};
+
+vector<SectionFromDwarf> dwsectab;
+
+static ElfSectIndex create_dw_elf(SectionFromDwarf &ds);
+
+static SectionFromDwarf & FindMySection(const ElfSectIndex & elf_section_index)
+{
+ for(unsigned i =0; i < dwsectab.size(); ++i) {
+ if(elf_section_index.getSectIndex() !=
+ dwsectab[i].getSectIndex().getSectIndex()) {
+ continue;
+ }
+ return dwsectab[i];
+ }
+ cerr << "Unable to find my dw sec data for elf section " <<
+ elf_section_index.getSectIndex() << endl;
+ exit(1);
+}
+
+static unsigned
+createnamestr(unsigned strtabstroff)
+{
+ Elf_Scn * strscn =elf_newscn(elf);
+ if(!strscn) {
+ cerr << "Unable to elf_newscn() on " << outfile << endl;
+ exit(1);
+ }
+ Elf_Data* shstr =elf_newdata(strscn);
+ if(!shstr) {
+ cerr << "Unable to elf_newdata() on " << outfile << endl;
+ exit(1);
+ }
+ shstr->d_buf = secstrtab.exposedata();
+ shstr->d_type = ELF_T_BYTE;
+ shstr->d_size = secstrtab.exposelen();
+ shstr->d_off = 0;
+ shstr->d_align = 1;
+ shstr->d_version = EV_CURRENT;
+
+ Elf32_Shdr * strshdr = elf32_getshdr(strscn);
+ if(!strshdr) {
+ cerr << "Unable to elf_getshdr() on " << outfile << endl;
+ exit(1);
+ }
+ strshdr->sh_name = strtabstroff;
+ strshdr->sh_type= SHT_STRTAB;
+ strshdr->sh_flags = SHF_STRINGS;
+ strshdr->sh_addr = 0;
+ strshdr->sh_offset = 0;
+ strshdr->sh_size = 0;
+ strshdr->sh_link = 0;
+ strshdr->sh_info = 0;
+ strshdr->sh_addralign = 1;
+ strshdr->sh_entsize = 0;
+ return elf_ndxscn(strscn);
+}
+
+
+// This functional interface is defined by libdwarf.
+int CallbackFunc(
+ char* name,
+ int size,
+ Dwarf_Unsigned type,
+ Dwarf_Unsigned flags,
+ Dwarf_Unsigned link,
+ Dwarf_Unsigned info,
+ Dwarf_Unsigned* sect_name_symbol_index,
+ void * user_data,
+ int* error)
+{
+ // Create an elf section.
+ // If the data is relocations, we suppress the generation
+ // of a section when we intend to do the relocations
+ // ourself (quite normal for dwarfgen but would
+ // be really surprising for a normal compiler
+ // back end using the producer code).
+
+ // The section name appears both in the section strings .shstrtab and
+ // in the elf symtab .symtab and its strings .strtab.
+
+ if (0 == strncmp(name,".rel",4)) {
+ // It is relocation, create no section!
+ return 0;
+ }
+ SectionFromDwarf ds(name,size,type,flags,link,info) ;
+ *sect_name_symbol_index = ds.getSectionNameSymidx();
+ ElfSectIndex createdsec = create_dw_elf(ds);
+
+ // Do all the data creation before pushing (copying) ds onto dwsectab!
+ dwsectab.push_back(ds);
+ return createdsec.getSectIndex();
+}
+
+static ElfSectIndex
+create_dw_elf(SectionFromDwarf &ds)
+{
+ Elf_Scn * scn =elf_newscn(elf);
+ if(!scn) {
+ cerr << "Unable to elf_newscn() on " << ds.name_ << endl;
+ exit(1);
+ }
+ Elf32_Shdr * shdr = elf32_getshdr(scn);
+ if(!shdr) {
+ cerr << "Unable to elf_getshdr() on " << ds.name_ << endl;
+ exit(1);
+ }
+ shdr->sh_name = ds.section_name_itself_;
+ shdr->sh_type = ds.type_;
+ shdr->sh_flags = ds.flags_;
+ shdr->sh_addr = 0;
+ shdr->sh_offset = 0;
+ shdr->sh_size = ds.size_;
+ shdr->sh_link = ds.link_;
+ shdr->sh_info = ds.info_;
+ shdr->sh_addralign = 1;
+ shdr->sh_entsize = 0;
+ ElfSectIndex si(elf_ndxscn(scn));
+ ds.setSectIndex(si);
+ return si;
+}
+
+// Default error handler of libdwarf producer code.
+void ErrorHandler(Dwarf_Error err,Dwarf_Ptr errarg)
+{
+ // FIXME do better error handling
+ cerr <<"Giving up, encountered an error" << endl;
+ exit(1);
+}
+
+
+static void
+setinput(enum WhichInputSource *src,
+ const string &type,
+ bool *pathreq)
+{
+ if(type == "txt") {
+ *src = OptReadText;
+ *pathreq = true;
+ return;
+ } else if (type == "obj") {
+ *src = OptReadBin;
+ *pathreq = true;
+ return;
+ } else if (type == "def") {
+ *src = OptPredefined;
+ *pathreq = false;
+ return;
+ }
+ cout << "Giving up, only txt obj or def accepted after -t" << endl;
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+
+
+ int opt;
+ bool pathrequired(false);
+ long cu_of_input_we_output = -1;
+ while((opt=getopt(argc,argv,"o:t:c:")) != -1) {
+ switch(opt) {
+ case 'c':
+ // At present we can only create a single
+ // cu in the output of the libdwarf producer.
+ cu_of_input_we_output = atoi(optarg);
+ break;
+ case 't':
+ setinput(&whichinput,optarg,&pathrequired);
+ break;
+ case 'o':
+ outfile = optarg;
+ break;
+ case '?':
+ cerr << "Invalid quest? option input " << endl;
+ exit(1);
+
+ default:
+ cerr << "Invalid option input " << endl;
+ exit(1);
+ }
+ }
+ if ( (optind >= argc) && pathrequired) {
+ cerr << "Expected argument after options! Giving up." << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ if(pathrequired) {
+ infile = argv[optind];
+ }
+
+ if(whichinput == OptReadBin) {
+ createIrepFromBinary(infile,Irep);
+ } else if (whichinput == OptReadText) {
+ cerr << "text read not supported yet" << endl;
+ exit(EXIT_FAILURE);
+ } else if (whichinput == OptPredefined) {
+ cerr << "predefined not supported yet" << endl;
+ exit(EXIT_FAILURE);
+ } else {
+ cerr << "Impossible: unknown input style." << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ // Example will return error value thru 'err' pointer
+ // and return DW_DLV_BADADDR if there is an error.
+ int ptrsize = DW_DLC_SIZE_32;
+ Dwarf_Ptr errarg = 0;
+ Dwarf_Error err = 0;
+ // We use DW_DLC_SYMBOLIC_RELOCATIONS so we can
+ // read the relocations and do our own relocating.
+ // See calls of dwarf_get_relocation_info().
+ Dwarf_P_Debug dbg = dwarf_producer_init_c(
+ DW_DLC_WRITE|ptrsize|DW_DLC_SYMBOLIC_RELOCATIONS,
+ CallbackFunc,
+ 0,
+ errarg,
+ 0, /* we are not using user_data, so pass in 0 */
+ &err);
+ if(dbg == reinterpret_cast<Dwarf_P_Debug>(DW_DLV_BADADDR)) {
+ cerr << "Failed init_b" << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ transform_irep_to_dbg(dbg,Irep,cu_of_input_we_output);
+
+ write_object_file(dbg,Irep);
+ // Example calls ErrorHandler if there is an error
+ // (which does not return, see above)
+ // so no need to test for error.
+ dwarf_producer_finish( dbg, 0);
+
+ return 0;
+}
+
+static void
+write_object_file(Dwarf_P_Debug dbg, IRepresentation &irep)
+{
+ int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+ int fd = open(outfile.c_str(),O_WRONLY|O_CREAT|O_TRUNC, mode);
+ if(fd < 0 ) {
+ cerr << "Unable to open " << outfile <<
+ " for writing." << endl;
+ exit(1);
+ }
+
+ if(elf_version(EV_CURRENT) == EV_NONE) {
+ cerr << "Bad elf_version" << endl;
+ exit(1);
+ }
+
+ Elf_Cmd cmd = ELF_C_WRITE;
+ elf = elf_begin(fd,cmd,0);
+ if(!elf) {
+ cerr << "Unable to elf_begin() on " << outfile << endl;
+ exit(1);
+ }
+ ehp = elf32_newehdr(elf);
+ if(!ehp) {
+ cerr << "Unable to elf_newehdr() on " << outfile << endl;
+ exit(1);
+ }
+ ehp->e_ident[EI_MAG0] = ELFMAG0;
+ ehp->e_ident[EI_MAG1] = ELFMAG1;
+ ehp->e_ident[EI_MAG2] = ELFMAG2;
+ ehp->e_ident[EI_MAG3] = ELFMAG3;
+ ehp->e_ident[EI_CLASS] = ELFCLASS32;
+ ehp->e_ident[EI_DATA] = ELFDATA2LSB;
+ ehp->e_ident[EI_VERSION] = EV_CURRENT;
+ ehp->e_machine = EM_386;
+ ehp->e_type = ET_EXEC;
+ ehp->e_version = EV_CURRENT;
+
+ unsigned strtabstroff = secstrtab.addString(".shstrtab");
+
+ // an object section with fake .text data (just as an example).
+ write_text_section(elf);
+
+ write_generated_dbg(dbg,elf,Irep);
+
+ // Now create section name string section.
+ unsigned shstrindex = createnamestr(strtabstroff);
+ ehp->e_shstrndx = shstrindex;
+
+ off_t ures = elf_update(elf,cmd);
+ if(ures == (off_t)(-1LL)) {
+ cerr << "Unable to elf_update() on " << outfile << endl;
+ int eer = elf_errno();
+ cerr << "Error is " << eer << " " << elf_errmsg(eer) << endl;
+ exit(1);
+ }
+ cout << " output image size in bytes " << ures << endl;
+
+ elf_end(elf);
+ close(fd);
+}
+
+
+// an object section with fake .text data (just as an example).
+static void
+write_text_section(Elf * elf)
+{
+ unsigned osecnameoff = secstrtab.addString(".text");
+ Elf_Scn * scn1 =elf_newscn(elf);
+ if(!scn1) {
+ cerr << "Unable to elf_newscn() on " << outfile << endl;
+ exit(1);
+ }
+
+ Elf_Data* ed1 =elf_newdata(scn1);
+ if(!ed1) {
+ cerr << "Unable to elf_newdata() on " << outfile << endl;
+ exit(1);
+ }
+ const char *d = "data in section";
+ ed1->d_buf = (void *)d;
+ ed1->d_type = ELF_T_BYTE;
+ ed1->d_size = strlen(d) +1;
+ ed1->d_off = 0;
+ ed1->d_align = 4;
+ ed1->d_version = EV_CURRENT;
+ Elf32_Shdr * shdr1 = elf32_getshdr(scn1);
+ if(!shdr1) {
+ cerr << "Unable to elf_getshdr() on " << outfile << endl;
+ exit(1);
+ }
+ shdr1->sh_name = osecnameoff;
+ shdr1->sh_type= SHT_PROGBITS;
+ shdr1->sh_flags = 0;
+ shdr1->sh_addr = 0;
+ shdr1->sh_offset = 0;
+ shdr1->sh_size = 0;
+ shdr1->sh_link = 0;
+ shdr1->sh_info = 0;
+ shdr1->sh_addralign = 1;
+ shdr1->sh_entsize = 0;
+}
+static void
+InsertDataIntoElf(Dwarf_Signed d,Dwarf_P_Debug dbg,Elf *elf)
+{
+ Dwarf_Signed elf_section_index = 0;
+ Dwarf_Unsigned length = 0;
+ Dwarf_Ptr bytes = dwarf_get_section_bytes(dbg,d,
+ &elf_section_index,&length,0);
+
+ Elf_Scn *scn = elf_getscn(elf,elf_section_index);
+ if(!scn) {
+ cerr << "Unable to elf_getscn on disk transform # " << d << endl;
+ exit(1);
+ }
+
+ ElfSectIndex si(elf_section_index);
+ SectionFromDwarf & sfd = FindMySection(si);
+
+ Elf_Data* ed =elf_newdata(scn);
+ if(!ed) {
+ cerr << "elf_newdata died on transformed index " << d << endl;
+ exit(1);
+ }
+ ed->d_buf = bytes;
+ ed->d_type = ELF_T_BYTE;
+ ed->d_size = length;
+ ed->d_off = sfd.getNextOffset();
+ sfd.setNextOffset(ed->d_off + length);
+ ed->d_align = 1;
+ ed->d_version = EV_CURRENT;
+ cout << "Inserted " << length << " bytes into elf section index " <<
+ elf_section_index << endl;
+}
+
+#if 0
+static string
+printable_rel_type(unsigned char reltype)
+{
+ enum Dwarf_Rel_Type t = (enum Dwarf_Rel_Type)reltype;
+ switch(t) {
+ case dwarf_drt_none:
+ return "dwarf_drt_none";
+ case dwarf_drt_data_reloc:
+ return "dwarf_drt_data_reloc";
+ case dwarf_drt_segment_rel:
+ return "dwarf_drt_segment_rel";
+ case dwarf_drt_first_of_length_pair:
+ return "dwarf_drt_first_of_length_pair";
+ case dwarf_drt_second_of_length_pair:
+ return "dwarf_drt_second_of_length_pair";
+ default:
+ break;
+ }
+ return "drt-unknown (impossible case)";
+}
+#endif
+
+static Dwarf_Unsigned
+FindSymbolValue(ElfSymIndex symi,IRepresentation &irep)
+{
+ ElfSymbols & syms = irep.getElfSymbols();
+ ElfSymbol & es = syms.getElfSymbol(symi);
+ Dwarf_Unsigned symv = es.getSymbolValue();
+ return symv;
+}
+
+static void
+bitreplace(char *buf, Dwarf_Unsigned newval,
+ size_t newvalsize,int length)
+{
+ if(length == 4) {
+ uint32_t my4 = newval;
+ uint32_t * p = reinterpret_cast<uint32_t *>(buf );
+ uint32_t oldval = *p;
+ *p = oldval + my4;
+ } else if (length == 8) {
+ uint64_t my8 = newval;
+ uint64_t * p = reinterpret_cast<uint64_t *>(buf );
+ uint64_t oldval = *p;
+ *p = oldval + my8;
+ } else {
+ cerr << " Relocation is length " << length <<
+ " which we do not yet handle." << endl;
+ exit(1);
+ }
+}
+
+// This remembers nothing, so is dreadfully slow.
+static char *
+findelfbuf(Elf *elf,Elf_Scn *scn,Dwarf_Unsigned offset, unsigned length)
+{
+ Elf_Data * edbase = 0;
+ Elf_Data * ed = elf_getdata(scn,edbase);
+ unsigned bct = 0;
+ for (;ed; ed = elf_getdata(scn,ed)) {
+ bct++;
+ if(offset >= LOFFTODWUNS(ed->d_off + ed->d_size) ) {
+ continue;
+ }
+ if(offset < LOFFTODWUNS(ed->d_off)) {
+ cerr << " Relocation at offset " <<
+ offset << " cannot be accomplished, no buffer. "
+ << endl;
+ exit(1);
+ }
+ Dwarf_Unsigned localoff = offset - ed->d_off;
+ if((localoff + length) > ed->d_size) {
+ cerr << " Relocation at offset " <<
+ offset << " cannot be accomplished, size mismatch. "
+ << endl;
+ exit(1);
+ }
+ char *lclptr = reinterpret_cast<char *>(ed->d_buf) + localoff;
+ return lclptr;
+ }
+ cerr << " Relocation at offset " << offset <<
+ " cannot be accomplished, past end of buffers" << endl;
+ return 0;
+
+}
+
+static void
+write_generated_dbg(Dwarf_P_Debug dbg,Elf * elf,IRepresentation &irep)
+{
+ Dwarf_Error err = 0;
+ Dwarf_Signed sectioncount =
+ dwarf_transform_to_disk_form(dbg,0);
+
+ Dwarf_Signed d = 0;
+ for(d = 0; d < sectioncount ; ++d) {
+ InsertDataIntoElf(d,dbg,elf);
+ }
+
+ // Since we are emitting in final form sometimes, we may
+ // do relocation processing here or we may
+ // instead emit relocation records into the object file.
+ // The following is for DW_DLC_SYMBOLIC_RELOCATIONS.
+ Dwarf_Unsigned reloc_sections_count = 0;
+ int drd_version = 0;
+ int res = dwarf_get_relocation_info_count(dbg,&reloc_sections_count,
+ &drd_version,&err);
+ if( res != DW_DLV_OK) {
+ cerr << "Error getting relocation info count." << endl;
+ exit(1);
+
+ }
+ cout << "Relocations sections count= " << reloc_sections_count <<
+ " relversion=" << drd_version << endl;
+ for( Dwarf_Unsigned ct = 0; ct < reloc_sections_count ; ++ct) {
+ // elf_section_index is the elf index of the relocations
+ // themselves.
+ Dwarf_Signed elf_section_index = 0;
+ // elf_section_index_link is the elf index of the section
+ // the relocations apply to.
+ Dwarf_Signed elf_section_index_link = 0;
+ // relocation_buffer_count is the number of relocations
+ // of this section.
+ Dwarf_Unsigned relocation_buffer_count = 0;
+ Dwarf_Relocation_Data reld;
+ res = dwarf_get_relocation_info(dbg,&elf_section_index,
+ &elf_section_index_link,
+ &relocation_buffer_count,
+ &reld,&err);
+ if (res != DW_DLV_OK) {
+ cerr << "Error getting relocation record " <<
+ ct << "." << endl;
+ exit(1);
+ }
+ ElfSectIndex si(elf_section_index_link);
+ cout << "Relocs for sec " << ct << " elf-sec=" << elf_section_index <<
+ " link=" << elf_section_index_link <<
+ " bufct=" << relocation_buffer_count << endl;
+ Elf_Scn *scn = elf_getscn(elf,si.getSectIndex());
+ if(!scn) {
+ cerr << "Unable to elf_getscn # " << si.getSectIndex() << endl;
+ exit(1);
+ }
+
+ for (Dwarf_Unsigned r = 0; r < relocation_buffer_count; ++r) {
+ Dwarf_Relocation_Data rec = reld+r;
+ ElfSymIndex symi(rec->drd_symbol_index);
+ Dwarf_Unsigned newval = FindSymbolValue(symi,irep);
+ char *buf_to_update = findelfbuf(elf,scn,
+ rec->drd_offset,rec->drd_length);
+ if(buf_to_update) {
+ bitreplace(buf_to_update, newval,sizeof(newval),
+ rec->drd_length);
+ }
+ }
+ }
+}
diff --git a/dwarfgen/general.h b/dwarfgen/general.h
new file mode 100644
index 0000000..4212092
--- /dev/null
+++ b/dwarfgen/general.h
@@ -0,0 +1,55 @@
+/*
+ Copyright (C) 2010-2011 David Anderson.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+*/
+// general.h
+// The following needed in code using this.
+//#include <sstream>
+//#include <iomanip> // iomanip for setw etc
+
+#include <sstream>
+#include <iomanip>
+
+template <typename T >
+std::string IToHex(T v,unsigned l=0)
+{
+ if(v == 0) {
+ // For a zero value, ostringstream does not insert 0x.
+ // So we do zeroes here.
+ std::string out = "0x0";
+ if(l > 3) {
+ out.append(l-3,'0');
+ }
+ return out;
+ }
+ std::ostringstream s;
+ s.setf(std::ios::hex,std::ios::basefield);
+ s.setf(std::ios::showbase);
+ if (l > 0) {
+ s << std::setw(l);
+ }
+ s << v ;
+ return s.str();
+};
+
+template <typename T>
+std::string BldName(const std::string & prefix, T v)
+{
+ std::ostringstream s;
+ s << prefix;
+ s << v;
+ return s.str();
+}
+
diff --git a/dwarfgen/install.sh b/dwarfgen/install.sh
new file mode 100755
index 0000000..0ff4b6a
--- /dev/null
+++ b/dwarfgen/install.sh
@@ -0,0 +1,119 @@
+#!/bin/sh
+
+#
+# install - install a program, script, or datafile
+# This comes from X11R5; it is not part of GNU.
+#
+# $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+
+instcmd="$mvprog"
+chmodcmd=""
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+fi
+
+if [ x"$dst" = x ]
+then
+ echo "install: no destination specified"
+ exit 1
+fi
+
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+if [ -d $dst ]
+then
+ dst="$dst"/`basename $src`
+fi
+
+# Make a temp file name in the proper directory.
+
+dstdir=`dirname $dst`
+dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+$doit $instcmd $src $dsttmp
+
+# and set any options; do chmod last to preserve setuid bits
+
+if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi
+if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi
+if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi
+if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi
+
+# Now rename the file to the real destination.
+
+$doit $rmcmd $dst
+$doit $mvcmd $dsttmp $dst
+
+
+exit 0
diff --git a/dwarfgen/irepattrtodbg.cc b/dwarfgen/irepattrtodbg.cc
new file mode 100644
index 0000000..c2f41ed
--- /dev/null
+++ b/dwarfgen/irepattrtodbg.cc
@@ -0,0 +1,221 @@
+/*
+ Copyright (C) 2010-2011 David Anderson.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+*/
+
+// irepattrtodbg.cc
+
+#include "config.h"
+#include <unistd.h>
+#include <stdlib.h> // for exit
+#include <iostream>
+#include <sstream> // For BldName
+#include <iomanip> // iomanp for setw etc
+#include <string>
+#include <list>
+#include <vector>
+#include <string.h> // For memset etc
+#include <sys/stat.h> //open
+#include <fcntl.h> //open
+#include "general.h"
+#include "elf.h"
+#include "gelf.h"
+#include "strtabdata.h"
+#include "dwarf.h"
+#include "libdwarf.h"
+#include "irepresentation.h"
+#include "ireptodbg.h"
+#include "irepattrtodbg.h"
+
+#ifdef HAVE_INTPTR_T
+#include <stdint.h>
+typedef intptr_t myintfromp; // intptr_t is from C99.
+#else
+// We want an integer that is big enough for a pointer so the
+// pointer return value from the libdwarf producer can be
+// tested for -1. Ugly overloading of integer and pointer in libdwarf.
+// We just hope it will compile for you.
+typedef long myintfromp;
+#endif
+
+using std::string;
+using std::cout;
+using std::cerr;
+using std::endl;
+using std::vector;
+using std::list;
+
+static Dwarf_Error error;
+static unsigned fakeaddrnum;
+
+// We are not going to 'validate' the FORM for this Attribute.
+// or this Die. We just assume that what we are handed is
+// what we are to produce. We do test the attribute
+// at times, partly to ensure we use as many of the dwarf_add_AT*
+// functions as possible.
+
+// Correctness/appropriateness must be evaluated elsewhere.
+
+void
+AddAttrToDie(Dwarf_P_Debug dbg,
+ IRepresentation & Irep,
+ Dwarf_P_Die outdie,IRDie & irdie,IRAttr &irattr)
+{
+ int attrnum = irattr.getAttrNum();
+ enum Dwarf_Form_Class formclass = irattr.getFormClass();
+ // IRForm is an abstract base class.
+ IRForm *form = irattr.getFormData();
+
+ switch(formclass) {
+ case DW_FORM_CLASS_UNKNOWN:
+ cerr << "ERROR Impossible DW_FORM_CLASS_UNKNOWN, attrnum "
+ <<attrnum << cerr;
+ break;
+ case DW_FORM_CLASS_ADDRESS:
+ {
+ IRFormAddress *f = dynamic_cast<IRFormAddress *>(form);
+ if (!f) {
+ cerr << "ERROR Impossible DW_FORM_CLASS_ADDRESS cast fails, attrnum "
+ <<attrnum << cerr;
+ break;
+ }
+ // FIXME: do better creating a symbol: try to match original
+ // or specified input.
+ Dwarf_Addr addr = f->getAddress();
+
+ string symname = BldName("addrsym",fakeaddrnum++);
+ Dwarf_Addr pcval = addr;
+
+ ElfSymbols& es = Irep.getElfSymbols();
+ ElfSymIndex esi = es.addElfSymbol(pcval,symname);
+ Dwarf_Unsigned sym_index = esi.getSymIndex();
+
+ // FIXME: we should allow for DW_FORM_indirect here.
+ // Relocation later will fix value.
+ Dwarf_P_Attribute a = dwarf_add_AT_targ_address(dbg,
+ outdie,attrnum,0,sym_index,&error);
+ if( reinterpret_cast<myintfromp>(a) == DW_DLV_BADADDR) {
+ cerr << "ERROR dwarf_add_AT_targ_address fails, attrnum "
+ <<attrnum << cerr;
+
+ }
+ }
+ break;
+ case DW_FORM_CLASS_BLOCK:
+ {
+ //FIXME
+ }
+ break;
+ case DW_FORM_CLASS_CONSTANT:
+ {
+ //FIXME
+ }
+ break;
+ case DW_FORM_CLASS_EXPRLOC:
+ {
+ //FIXME
+ }
+ break;
+ case DW_FORM_CLASS_FLAG:
+ {
+ IRFormFlag *f = dynamic_cast<IRFormFlag *>(form);
+ if (!f) {
+ cerr << "ERROR Impossible DW_FORM_CLASS_FLAG cast fails, attrnum "
+ <<attrnum << cerr;
+ break;
+ }
+ // FIXME: handle indirect form (libdwarf needs feature).
+ // FIXME: handle implicit flag (libdwarf needs feature).
+ // FIXME: rel type ok?
+ Dwarf_P_Attribute a =
+ dwarf_add_AT_flag(dbg,outdie,attrnum,f->getFlagVal(),&error);
+ if( reinterpret_cast<myintfromp>(a) == DW_DLV_BADADDR) {
+ cerr << "ERROR dwarf_add_AT_flag fails, attrnum "
+ <<attrnum << cerr;
+ }
+ }
+ break;
+ case DW_FORM_CLASS_LINEPTR:
+ {
+ //FIXME
+ }
+ break;
+ case DW_FORM_CLASS_LOCLISTPTR:
+ {
+ //FIXME
+ }
+ break;
+ case DW_FORM_CLASS_MACPTR:
+ {
+ //FIXME
+ }
+ break;
+ case DW_FORM_CLASS_RANGELISTPTR:
+ {
+ //FIXME
+ }
+ break;
+ case DW_FORM_CLASS_REFERENCE:
+ break;
+ case DW_FORM_CLASS_STRING:
+ {
+ IRFormString *f = dynamic_cast<IRFormString *>(form);
+ if (!f) {
+ cerr << "ERROR Impossible DW_FORM_CLASS_STRING cast fails, attrnum "
+ <<attrnum << cerr;
+ break;
+ }
+ Dwarf_P_Attribute a = 0;
+ // We know libdwarf does not change the string. Historical mistake
+ // not making it a const char * argument.
+ // Ugly cast.
+ // FIXME: handle indirect form (libdwarf needs feature).
+ // FIXME: rel type ok?
+ char *mystr = const_cast<char *>(f->getString().c_str());
+ switch(attrnum) {
+ case DW_AT_name:
+ a = dwarf_add_AT_name(outdie,mystr,&error);
+ break;
+ case DW_AT_producer:
+ a = dwarf_add_AT_producer(outdie,mystr,&error);
+ break;
+ case DW_AT_comp_dir:
+ a = dwarf_add_AT_comp_dir(outdie,mystr,&error);
+ break;
+ default:
+ a = dwarf_add_AT_string(dbg,outdie,attrnum,mystr,
+ &error);
+ break;
+ }
+ if( reinterpret_cast<myintfromp>(a) == DW_DLV_BADADDR) {
+ cerr << "ERROR dwarf_add_AT_string fails, attrnum "
+ <<attrnum << cerr;
+ }
+ }
+ break;
+ case DW_FORM_CLASS_FRAMEPTR: // SGI/MIPS/IRIX only.
+ {
+ //FIXME
+ }
+ break;
+ default:
+ cerr << "ERROR Impossible DW_FORM_CLASS "<<
+ static_cast<int>(formclass)
+ <<attrnum << cerr;
+ //FIXME
+ }
+ return;
+}
+
diff --git a/dwarfgen/irepattrtodbg.h b/dwarfgen/irepattrtodbg.h
new file mode 100644
index 0000000..963c123
--- /dev/null
+++ b/dwarfgen/irepattrtodbg.h
@@ -0,0 +1,26 @@
+#ifndef IREPATTRTODBG_H
+#define IREPATTRTODBG_H
+/*
+ Copyright (C) 2010-2011 David Anderson.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+*/
+
+// irepattrtodbg.h
+
+void AddAttrToDie(Dwarf_P_Debug dbg,
+ IRepresentation & Irep,
+ Dwarf_P_Die outdie,IRDie & irdie,IRAttr &irattr);
+
+#endif /* IREPATTRTODBG_H */
diff --git a/dwarfgen/irepdie.h b/dwarfgen/irepdie.h
new file mode 100644
index 0000000..2a0732a
--- /dev/null
+++ b/dwarfgen/irepdie.h
@@ -0,0 +1,228 @@
+/*
+ Copyright (C) 2010-2011 David Anderson.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+*/
+
+
+//
+// irepdie.h
+//
+//
+class IRCUdata;
+
+class IRAttr {
+public:
+ IRAttr():attr_(0),directform_(0),indirectform_(0),
+ formclass_(DW_FORM_CLASS_UNKNOWN),formdata_(0) {
+ };
+ IRAttr(Dwarf_Half attr,Dwarf_Half dirform, Dwarf_Half indirform):
+ attr_(attr),directform_(dirform),indirectform_(indirform),
+ formclass_(DW_FORM_CLASS_UNKNOWN),formdata_(0) {
+ };
+ IRAttr(const IRAttr &r) {
+ attr_ = r.attr_;
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ if(r.formdata_) {
+ formdata_ = r.formdata_->clone();
+ } else {
+ formdata_ = 0;
+ }
+ };
+ ~IRAttr() { delete formdata_; };
+ IRAttr & operator=( const IRAttr &r) {
+ if(this == &r) {
+ return *this;
+ }
+ attr_ = r.attr_;
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ if(r.formdata_) {
+ formdata_ = r.formdata_->clone();
+ } else {
+ formdata_ = 0;
+ }
+ return *this;
+ }
+ void setBaseData(Dwarf_Half attr, Dwarf_Half dirform,
+ Dwarf_Half indirform){
+ attr_ = attr;
+ directform_ = dirform;
+ indirectform_ = indirform;
+ };
+ void setFormClass(enum Dwarf_Form_Class cl) {
+ formclass_ = cl;
+ };
+ enum Dwarf_Form_Class getFormClass() const {return formclass_; };
+ void setFormData(IRForm *f) { formdata_ = f; };
+ Dwarf_Half getFinalForm() const { return indirectform_; };
+ Dwarf_Half getDirectForm() const { return directform_; };
+ Dwarf_Half getAttrNum() const { return attr_; };
+ IRForm * getFormData() { return formdata_;};
+private:
+ Dwarf_Half attr_;
+ Dwarf_Half directform_;
+ // In most cases directform == indirect form.
+ // Otherwise, directform == DW_FORM_indirect.
+ Dwarf_Half indirectform_;
+ enum Dwarf_Form_Class formclass_;
+ IRForm *formdata_;
+};
+
+class IRDie {
+public:
+ IRDie():tag_(0),globalOffset_(0), cuRelativeOffset_(0) {};
+ ~IRDie() {};
+ void addChild(const IRDie & newdie ) {
+ children_.push_back(newdie);
+ };
+ std::string getName() {
+ std::list<IRAttr>::iterator it = attrs_.begin();
+ for( ; it != attrs_.end() ; ++it) {
+ if (it->getAttrNum() == DW_AT_name) {
+ IRForm *f = it->getFormData();
+ const IRFormString * isv =
+ dynamic_cast<const IRFormString *>(f);
+ if(isv) {
+ return isv->getString();
+ }
+ }
+ }
+ return "";
+ };
+ std::list<IRAttr> & getAttributes() {return attrs_; };
+ std::list<IRDie> & getChildren() {return children_; };
+ bool hasNewestChild(IRDie **lastch) { size_t N = children_.size();
+ if(N < 1) {
+ return false;
+ }
+ *lastch = &children_.back();
+ return true;
+ };
+ // lastChild will throw if no child exists.
+ IRDie &lastChild() { return children_.back(); };
+ void setBaseData(Dwarf_Half tag,Dwarf_Unsigned goff,
+ Dwarf_Unsigned cuoff) {
+ tag_ = tag;
+ globalOffset_=goff;
+ cuRelativeOffset_ = cuoff;
+ };
+ Dwarf_Unsigned getGlobalOffset() const { return globalOffset_;};
+ unsigned getTag() {return tag_; }
+
+private:
+ std::list<IRDie> children_;
+ std::list<IRAttr> attrs_;
+ unsigned tag_;
+ Dwarf_Unsigned globalOffset_;
+ Dwarf_Unsigned cuRelativeOffset_;
+};
+
+class IRCUdata {
+public:
+ IRCUdata():
+ cu_header_length_(0),
+ abbrev_offset_(0),
+ next_cu_header_offset_(0),
+ version_stamp_(0),
+ address_size_(0),
+ length_size_(0),
+ extension_size_(0),
+ has_macrodata_(false),
+ macrodata_offset_(0),
+ has_linedata_(false),
+ linedata_offset_(0),
+ cudie_offset_(0)
+ {};
+ IRCUdata(Dwarf_Unsigned len,Dwarf_Half version,
+ Dwarf_Unsigned abbrev_offset,
+ Dwarf_Half addr_size,
+ Dwarf_Half length_size,
+ Dwarf_Half extension_size,
+ Dwarf_Unsigned next_cu_header):
+ cu_header_length_(len),
+ abbrev_offset_(abbrev_offset),
+ next_cu_header_offset_(addr_size),
+ version_stamp_(version),
+ address_size_(addr_size),
+ length_size_(length_size),
+ extension_size_(extension_size),
+ has_macrodata_(false),
+ macrodata_offset_(0),
+ has_linedata_(false),
+ linedata_offset_(0),
+ cudie_offset_(0) {};
+ ~IRCUdata() { };
+ bool hasMacroData(Dwarf_Unsigned *offset_out,Dwarf_Unsigned *cudie_off) {
+ *offset_out = macrodata_offset_;
+ *cudie_off = cudie_offset_;
+ return has_macrodata_;
+ }
+ bool hasLineData(Dwarf_Unsigned *offset_out,Dwarf_Unsigned *cudie_off) {
+ *offset_out = linedata_offset_;
+ *cudie_off = cudie_offset_;
+ return has_linedata_;
+ }
+ void setMacroData(Dwarf_Unsigned offset,Dwarf_Unsigned cudieoff) {
+ has_macrodata_ = true;
+ macrodata_offset_ = offset;
+ cudie_offset_ = cudieoff;
+ };
+ void setLineData(Dwarf_Unsigned offset,Dwarf_Unsigned cudieoff) {
+ has_linedata_ = true;
+ linedata_offset_ = offset;
+ cudie_offset_ = cudieoff;
+ };
+ IRDie & baseDie() { return cudie_; };
+ Dwarf_Half getVersionStamp() { return version_stamp_; };
+ Dwarf_Half getOffsetSize() { return length_size_; };
+ IRCULineData & getCULines() { return cu_lines_; };
+ std::string getCUName() {
+ return cudie_.getName();
+ }
+
+private:
+ Dwarf_Unsigned cu_header_length_;
+ Dwarf_Unsigned abbrev_offset_;
+ Dwarf_Unsigned next_cu_header_offset_;
+ Dwarf_Half version_stamp_;
+ Dwarf_Half address_size_;
+ Dwarf_Half length_size_;
+ Dwarf_Half extension_size_;
+ bool has_macrodata_;
+ Dwarf_Unsigned macrodata_offset_;
+ bool has_linedata_;
+ Dwarf_Unsigned linedata_offset_;
+ Dwarf_Unsigned cudie_offset_;
+ IRCULineData cu_lines_;
+
+ // If true, is 32bit dwarf,else 64bit. Gives the size of a reference.
+ bool dwarf32bit_;
+
+ IRDie cudie_;
+};
+
+class IRDInfo {
+public:
+ IRDInfo() {};
+ ~IRDInfo() {};
+ IRCUdata &lastCU() { return cudata_.back(); }
+ std::list<IRCUdata>& getCUData() {return cudata_; };
+private:
+ std::list<IRCUdata> cudata_;
+};
+
diff --git a/dwarfgen/irepform.h b/dwarfgen/irepform.h
new file mode 100644
index 0000000..2388ea6
--- /dev/null
+++ b/dwarfgen/irepform.h
@@ -0,0 +1,592 @@
+/*
+ Copyright (C) 2010-2011 David Anderson.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+*/
+
+
+//
+// irepform.h
+//
+//
+class IRCUdata;
+class IRAttr;
+class IRFormInterface;
+
+// An Abstract class.
+class IRForm {
+public:
+ //virtual void emitvalue() = 0;
+ //IRForm & operator=(const IRForm &r);
+ virtual IRForm * clone() const =0;
+ virtual ~IRForm() {};
+ IRForm() {};
+ virtual enum Dwarf_Form_Class getFormClass() const = 0;
+private:
+};
+
+class IRFormUnknown : public IRForm {
+public:
+ IRFormUnknown():
+ directform_(0), indirectform_(0),
+ formclass_(DW_FORM_CLASS_UNKNOWN)
+ {}
+ ~IRFormUnknown() {};
+ IRFormUnknown(IRFormInterface *);
+ IRFormUnknown(const IRFormUnknown &r) {
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ }
+ virtual IRFormUnknown * clone() const {
+ return new IRFormUnknown(*this);
+ }
+ IRFormUnknown & operator=(const IRFormUnknown &r) {
+ if(this == &r) return *this;
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ };
+ enum Dwarf_Form_Class getFormClass() const { return formclass_; };
+private:
+ Dwarf_Half directform_;
+ // In most cases directform == indirect form.
+ // Otherwise, directform == DW_FORM_indirect.
+ Dwarf_Half indirectform_;
+ enum Dwarf_Form_Class formclass_;
+};
+// An address class entry refers to some part
+// (normally a loadable) section of the object file.
+// Not to DWARF info. Typically into .text or .data for example.
+// We therefore want a section number and offset (generally useless for us)
+// or preferably an elf symbol as that has a value
+// and an elf section number.
+// We often/usually know neither here so we do not even try.
+// Later we will make one up if we have to.
+class IRFormAddress : public IRForm {
+public:
+ IRFormAddress():
+ directform_(0), indirectform_(0),
+ formclass_(DW_FORM_CLASS_ADDRESS),
+ address_(0)
+ {};
+ IRFormAddress(IRFormInterface *);
+ ~IRFormAddress() {};
+ IRFormAddress & operator=(const IRFormAddress &r) {
+ if(this == &r) return *this;
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ address_ = r.address_;
+ };
+ IRFormAddress(const IRFormAddress &r) {
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ address_ = r.address_;
+ }
+ virtual IRFormAddress * clone() const {
+ return new IRFormAddress(*this);
+ };
+ Dwarf_Addr getAddress() { return address_;};
+ enum Dwarf_Form_Class getFormClass() const { return formclass_; };
+private:
+ void setAddress(Dwarf_Addr addr) { address_ = addr; };
+ Dwarf_Half directform_;
+ // In most cases directform == indirect form.
+ // Otherwise, directform == DW_FORM_indirect.
+ Dwarf_Half indirectform_;
+ enum Dwarf_Form_Class formclass_;
+ Dwarf_Addr address_;
+};
+class IRFormBlock : public IRForm {
+public:
+ IRFormBlock():
+ directform_(0), indirectform_(0),
+ formclass_(DW_FORM_CLASS_BLOCK),
+ fromloclist_(0),sectionoffset_(0)
+ {}
+ IRFormBlock(IRFormInterface *);
+ ~IRFormBlock() {};
+ IRFormBlock & operator=(const IRFormBlock &r) {
+ if(this == &r) return *this;
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ blockdata_ = r.blockdata_;
+ fromloclist_ = r.fromloclist_;
+ sectionoffset_ = r.sectionoffset_;
+ };
+ IRFormBlock(const IRFormBlock &r) {
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ blockdata_ = r.blockdata_;
+ fromloclist_ = r.fromloclist_;
+ sectionoffset_ = r.sectionoffset_;
+ }
+ virtual IRFormBlock * clone() const {
+ return new IRFormBlock(*this);
+ }
+ enum Dwarf_Form_Class getFormClass() const { return formclass_; };
+private:
+ Dwarf_Half directform_;
+ // In most cases directform == indirect form.
+ // Otherwise, directform == DW_FORM_indirect.
+ Dwarf_Half indirectform_;
+ enum Dwarf_Form_Class formclass_;
+ std::vector<char> blockdata_;
+ Dwarf_Small fromloclist_;
+ Dwarf_Unsigned sectionoffset_;
+
+ void insertBlock(Dwarf_Block *bl) {
+ char *d = static_cast<char *>(bl->bl_data);
+ Dwarf_Unsigned len = bl->bl_len;
+ blockdata_.clear();
+ blockdata_.insert(blockdata_.end(),d+0,d+len);
+ fromloclist_ = bl->bl_from_loclist;
+ sectionoffset_ = bl->bl_section_offset;
+ };
+};
+class IRFormConstant : public IRForm {
+public:
+ IRFormConstant():
+ directform_(0), indirectform_(0),
+ formclass_(DW_FORM_CLASS_CONSTANT),
+ signedness_(SIGN_NOT_SET),
+ uval_(0), sval_(0)
+ {}
+ IRFormConstant(IRFormInterface *);
+ ~IRFormConstant() {};
+ IRFormConstant & operator=(const IRFormConstant &r) {
+ if(this == &r) return *this;
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ signedness_ = r.signedness_;
+ uval_ = r.uval_;
+ sval_ = r.sval_;
+ };
+ IRFormConstant(const IRFormConstant &r) {
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ signedness_ = r.signedness_;
+ uval_ = r.uval_;
+ sval_ = r.sval_;
+ }
+ virtual IRFormConstant * clone() const {
+ return new IRFormConstant(*this);
+ }
+ enum Dwarf_Form_Class getFormClass() const { return formclass_; };
+private:
+ Dwarf_Half directform_;
+ // In most cases directform == indirect form.
+ // Otherwise, directform == DW_FORM_indirect.
+ Dwarf_Half indirectform_;
+ enum Dwarf_Form_Class formclass_;
+ // Starts at SIGN_NOT_SET.
+ // SIGN_UNKNOWN means it was a DW_FORM_data* of some
+ // kind so we do not really know.
+ enum Signedness {SIGN_NOT_SET,SIGN_UNKNOWN,UNSIGNED, SIGNED };
+ enum Signedness signedness_;
+ // Both uval_ and sval_ are always set to the same bits.
+ Dwarf_Unsigned uval_;
+ Dwarf_Signed sval_;
+
+ void setValues(Dwarf_Signed sval, Dwarf_Unsigned uval,
+ enum Signedness s) {
+ signedness_ = s;
+ uval_ = uval;
+ sval_ = sval;
+ }
+};
+
+class IRFormExprloc : public IRForm {
+public:
+ IRFormExprloc():
+ directform_(0), indirectform_(0),
+ formclass_(DW_FORM_CLASS_EXPRLOC)
+ {};
+ IRFormExprloc(IRFormInterface *);
+ ~IRFormExprloc() {};
+ IRFormExprloc & operator=(const IRFormExprloc &r) {
+ if(this == &r) return *this;
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ exprlocdata_ = r.exprlocdata_;
+ };
+ IRFormExprloc(const IRFormExprloc &r) {
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ exprlocdata_ = r.exprlocdata_;
+
+ }
+ virtual IRFormExprloc * clone() const {
+ return new IRFormExprloc(*this);
+ }
+ enum Dwarf_Form_Class getFormClass() const { return formclass_; };
+private:
+ Dwarf_Half directform_;
+ // In most cases directform == indirect form.
+ // Otherwise, directform == DW_FORM_indirect.
+ Dwarf_Half indirectform_;
+ enum Dwarf_Form_Class formclass_;
+ std::vector<char> exprlocdata_;
+ void insertBlock(Dwarf_Unsigned len, Dwarf_Ptr data) {
+ char *d = static_cast<char *>(data);
+ exprlocdata_.clear();
+ exprlocdata_.insert(exprlocdata_.end(),d+0,d+len);
+ };
+};
+
+
+class IRFormFlag : public IRForm {
+public:
+ IRFormFlag():
+ directform_(0), indirectform_(0),
+ formclass_(DW_FORM_CLASS_FLAG),
+ flagval_(0)
+ {};
+ IRFormFlag(IRFormInterface*);
+ ~IRFormFlag() {};
+ IRFormFlag & operator=(const IRFormFlag &r) {
+ if(this == &r) return *this;
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ flagval_ = r.flagval_;
+ };
+ IRFormFlag(const IRFormFlag &r) {
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ flagval_ = r.flagval_;
+ }
+ virtual IRFormFlag * clone() const {
+ return new IRFormFlag(*this);
+ }
+ enum Dwarf_Form_Class getFormClass() const { return formclass_; };
+ Dwarf_Bool getFlagVal() { return flagval_; }
+private:
+ Dwarf_Half directform_;
+ // In most cases directform == indirect form.
+ // Otherwise, directform == DW_FORM_indirect.
+ Dwarf_Half indirectform_;
+ enum Dwarf_Form_Class formclass_;
+ Dwarf_Bool flagval_;
+};
+
+
+class IRFormLinePtr : public IRForm {
+public:
+ IRFormLinePtr():
+ directform_(0), indirectform_(0),
+ formclass_(DW_FORM_CLASS_LINEPTR),
+ debug_line_offset_(0)
+ {};
+ IRFormLinePtr(IRFormInterface *);
+ ~IRFormLinePtr() {};
+ IRFormLinePtr & operator=(const IRFormLinePtr &r) {
+ if(this == &r) return *this;
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ debug_line_offset_ = r.debug_line_offset_;
+ };
+ IRFormLinePtr(const IRFormLinePtr &r) {
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ debug_line_offset_ = r.debug_line_offset_;
+ }
+ virtual IRFormLinePtr * clone() const {
+ return new IRFormLinePtr(*this);
+ }
+ enum Dwarf_Form_Class getFormClass() const { return formclass_; };
+private:
+ Dwarf_Half directform_;
+ // In most cases directform == indirect form.
+ // Otherwise, directform == DW_FORM_indirect.
+ Dwarf_Half indirectform_;
+ enum Dwarf_Form_Class formclass_;
+ Dwarf_Off debug_line_offset_;
+
+ void setOffset(Dwarf_Unsigned uval) {
+ debug_line_offset_ = uval;
+ };
+};
+
+
+class IRFormLoclistPtr : public IRForm {
+public:
+ IRFormLoclistPtr():
+ directform_(0), indirectform_(0),
+ formclass_(DW_FORM_CLASS_LOCLISTPTR),
+ loclist_offset_(0)
+ {};
+ IRFormLoclistPtr(IRFormInterface *);
+ ~IRFormLoclistPtr() {};
+ IRFormLoclistPtr & operator=(const IRFormLoclistPtr &r) {
+ if(this == &r) return *this;
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ loclist_offset_ = r.loclist_offset_;
+ };
+ IRFormLoclistPtr(const IRFormLoclistPtr &r) {
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ loclist_offset_ = r.loclist_offset_;
+ }
+ virtual IRFormLoclistPtr * clone() const {
+ return new IRFormLoclistPtr(*this);
+ }
+ enum Dwarf_Form_Class getFormClass() const { return formclass_; };
+private:
+ Dwarf_Half directform_;
+ // In most cases directform == indirect form.
+ // Otherwise, directform == DW_FORM_indirect.
+ Dwarf_Half indirectform_;
+ enum Dwarf_Form_Class formclass_;
+ Dwarf_Off loclist_offset_;
+
+ void setOffset(Dwarf_Unsigned uval) {
+ loclist_offset_ = uval;
+ };
+};
+
+
+class IRFormMacPtr : public IRForm {
+public:
+ IRFormMacPtr():
+ directform_(0), indirectform_(0),
+ formclass_(DW_FORM_CLASS_MACPTR),
+ macro_offset_(0)
+ {};
+ IRFormMacPtr(IRFormInterface *);
+ ~IRFormMacPtr() {};
+ IRFormMacPtr & operator=(const IRFormMacPtr &r) {
+ if(this == &r) return *this;
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ macro_offset_ = r.macro_offset_;
+ };
+ IRFormMacPtr(const IRFormMacPtr &r) {
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ macro_offset_ = r.macro_offset_;
+ }
+ virtual IRFormMacPtr * clone() const {
+ return new IRFormMacPtr(*this);
+ }
+ enum Dwarf_Form_Class getFormClass() const { return formclass_; };
+private:
+ Dwarf_Half directform_;
+ // In most cases directform == indirect form.
+ // Otherwise, directform == DW_FORM_indirect.
+ Dwarf_Half indirectform_;
+ enum Dwarf_Form_Class formclass_;
+ Dwarf_Off macro_offset_;
+
+ void setOffset(Dwarf_Unsigned uval) {
+ macro_offset_ = uval;
+ };
+};
+
+
+class IRFormRangelistPtr : public IRForm {
+public:
+ IRFormRangelistPtr():
+ directform_(0), indirectform_(0),
+ formclass_(DW_FORM_CLASS_RANGELISTPTR),
+ rangelist_offset_(0)
+ {};
+ IRFormRangelistPtr(IRFormInterface *);
+ ~IRFormRangelistPtr() {};
+ IRFormRangelistPtr & operator=(const IRFormRangelistPtr &r) {
+ if(this == &r) return *this;
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ rangelist_offset_ = r.rangelist_offset_;
+ };
+ IRFormRangelistPtr(const IRFormRangelistPtr &r) {
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ rangelist_offset_ = r.rangelist_offset_;
+ }
+ virtual IRFormRangelistPtr * clone() const {
+ return new IRFormRangelistPtr(*this);
+ }
+ enum Dwarf_Form_Class getFormClass() const { return formclass_; };
+private:
+ Dwarf_Half directform_;
+ // In most cases directform == indirect form.
+ // Otherwise, directform == DW_FORM_indirect.
+ Dwarf_Half indirectform_;
+ enum Dwarf_Form_Class formclass_;
+ Dwarf_Off rangelist_offset_;
+
+ void setOffset(Dwarf_Unsigned uval) {
+ rangelist_offset_ = uval;
+ };
+};
+
+class IRFormFramePtr : public IRForm {
+public:
+ IRFormFramePtr():
+ directform_(0), indirectform_(0),
+ formclass_(DW_FORM_CLASS_FRAMEPTR),
+ frame_offset_(0)
+ {};
+ IRFormFramePtr(IRFormInterface *);
+ ~IRFormFramePtr() {};
+ IRFormFramePtr & operator=(const IRFormFramePtr &r) {
+ if(this == &r) return *this;
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ frame_offset_ = r.frame_offset_;
+ };
+ IRFormFramePtr(const IRFormFramePtr &r) {
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ frame_offset_ = r.frame_offset_;
+ }
+ virtual IRFormFramePtr * clone() const {
+ return new IRFormFramePtr(*this);
+ }
+ enum Dwarf_Form_Class getFormClass() const { return formclass_; };
+private:
+ Dwarf_Half directform_;
+ // In most cases directform == indirect form.
+ // Otherwise, directform == DW_FORM_indirect.
+ Dwarf_Half indirectform_;
+ enum Dwarf_Form_Class formclass_;
+ Dwarf_Off frame_offset_;
+
+ void setOffset(Dwarf_Unsigned uval) {
+ frame_offset_ = uval;
+ };
+};
+
+
+
+class IRFormReference : public IRForm {
+public:
+ IRFormReference():
+ directform_(0), indirectform_(0),
+ formclass_(DW_FORM_CLASS_REFERENCE),
+ reftype_(RT_NONE),
+ globalOffset_(0),cuRelativeOffset_(0)
+ {initSig8();};
+ IRFormReference(IRFormInterface *);
+ ~IRFormReference() {};
+ IRFormReference & operator=(const IRFormReference &r) {
+ if(this == &r) return *this;
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ reftype_ = r.reftype_;
+ globalOffset_ = r.globalOffset_;
+ cuRelativeOffset_ = r.cuRelativeOffset_;
+ typeSig8_ = r.typeSig8_;
+ };
+ IRFormReference(const IRFormReference &r) {
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ reftype_ = r.reftype_;
+ globalOffset_ = r.globalOffset_;
+ cuRelativeOffset_ = r.cuRelativeOffset_;
+ typeSig8_ = r.typeSig8_;
+ }
+ virtual IRFormReference * clone() const {
+ return new IRFormReference(*this);
+ }
+ void setOffset(Dwarf_Off off) { globalOffset_ = off;
+ reftype_ = RT_GLOBAL;};
+ void setCUOffset(Dwarf_Off off) { cuRelativeOffset_= off;
+ reftype_ = RT_CUREL;};
+ void setSignature(Dwarf_Sig8 * sig) { typeSig8_ = *sig;
+ reftype_ = RT_SIG;};
+ enum Dwarf_Form_Class getFormClass() const { return formclass_; };
+private:
+ void initSig8();
+
+ Dwarf_Half directform_;
+ // In most cases directform == indirect form.
+ // Otherwise, directform == DW_FORM_indirect.
+ Dwarf_Half indirectform_;
+ enum Dwarf_Form_Class formclass_;
+ enum RefType { RT_NONE,RT_GLOBAL, RT_CUREL,RT_SIG };
+ enum RefType reftype_;
+ Dwarf_Off globalOffset_;
+ Dwarf_Off cuRelativeOffset_;
+ Dwarf_Sig8 typeSig8_;
+};
+
+
+class IRFormString: public IRForm {
+public:
+ IRFormString():
+ directform_(0), indirectform_(0),
+ formclass_(DW_FORM_CLASS_STRING),
+ strpoffset_(0) {};
+ ~IRFormString() {};
+ IRFormString(IRFormInterface *);
+ IRFormString(const IRFormString &r) {
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ formdata_= r.formdata_;
+ strpoffset_= r.strpoffset_;
+ }
+ virtual IRFormString * clone() const {
+ return new IRFormString(*this);
+ }
+ IRFormString & operator=(const IRFormString &r) {
+ if(this == &r) return *this;
+ directform_ = r.directform_;
+ indirectform_ = r.indirectform_;
+ formclass_ = r.formclass_;
+ formdata_ = r.formdata_;
+ strpoffset_ = r.strpoffset_;
+ };
+ void setString(const char *s) {formdata_ = s; };
+ const std::string & getString() const {return formdata_; };
+ enum Dwarf_Form_Class getFormClass() const { return formclass_; };
+private:
+ Dwarf_Half directform_;
+ // In most cases directform == indirect form.
+ // Otherwise, directform == DW_FORM_indirect.
+ Dwarf_Half indirectform_;
+ enum Dwarf_Form_Class formclass_;
+ std::string formdata_;
+ Dwarf_Unsigned strpoffset_;
+};
+
+
+// Factory Method.
+IRForm *formFactory(Dwarf_Debug dbg, Dwarf_Attribute attr,
+ IRCUdata &cudata,IRAttr & irattr);
+
diff --git a/dwarfgen/irepframe.h b/dwarfgen/irepframe.h
new file mode 100644
index 0000000..3f598f8
--- /dev/null
+++ b/dwarfgen/irepframe.h
@@ -0,0 +1,154 @@
+/*
+ Copyright (C) 2010-2011 David Anderson.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+*/
+
+//
+// irepframe.h
+//
+
+class IRCie {
+public:
+ IRCie(): cie_byte_length_(0), version_(0),
+ code_alignment_factor_(1),
+ data_alignment_factor_(1),
+ return_address_register_rule_(0)
+ {};
+ IRCie(Dwarf_Unsigned length, Dwarf_Unsigned version,
+ const std::string &augmentation, Dwarf_Unsigned code_align,
+ Dwarf_Signed data_align, Dwarf_Half return_reg_rule,
+ const void * init_instrs, Dwarf_Unsigned instrs_len):
+ cie_byte_length_(length), version_(version),
+ augmentation_(augmentation), code_alignment_factor_(code_align),
+ data_alignment_factor_(data_align),
+ return_address_register_rule_(return_reg_rule)
+ {
+ const Dwarf_Small *x =
+ reinterpret_cast<const Dwarf_Small *>(init_instrs);
+ for(Dwarf_Unsigned i = 0; i < instrs_len; ++i) {
+ initial_instructions_.push_back(x[i]);
+ }
+ }
+ void insert_fde_index(unsigned i) { fde_index_.push_back(i); };
+ ~IRCie() {};
+ void get_basic_cie_data(Dwarf_Unsigned * version,
+ std::string * aug,
+ Dwarf_Unsigned * code_align,
+ Dwarf_Signed * data_align,
+ Dwarf_Half * ret_addr_reg) {
+ *version = version_;
+ *aug = augmentation_;
+ *code_align = code_alignment_factor_;
+ *data_align = data_alignment_factor_;
+ *ret_addr_reg = return_address_register_rule_;
+ }
+ void get_init_instructions(Dwarf_Unsigned *len,
+ void **bytes) {
+ *len = initial_instructions_.size();
+ *bytes = reinterpret_cast<void *>(&initial_instructions_[0]);
+ };
+
+private:
+ // Byte length 0 if not known yet.
+ Dwarf_Unsigned cie_byte_length_;
+ Dwarf_Unsigned version_;
+ std::string augmentation_;
+ Dwarf_Unsigned code_alignment_factor_;
+ Dwarf_Signed data_alignment_factor_;
+ Dwarf_Half return_address_register_rule_;
+ std::vector<Dwarf_Small> initial_instructions_;
+ // fde_index is the array of indexes into fdedata_
+ // that are fdes used by this cie.
+ std::vector<unsigned> fde_index_;
+};
+class IRFde {
+public:
+ IRFde(): low_pc_(0), func_length_(0),
+ cie_offset_(0), cie_index_(-1),
+ fde_offset_(0) {};
+ IRFde(Dwarf_Addr low_pc,Dwarf_Unsigned func_length,
+ Dwarf_Ptr fde_bytes, Dwarf_Unsigned fde_length,
+ Dwarf_Off cie_offset,Dwarf_Signed cie_index,
+ Dwarf_Off fde_offset): low_pc_(low_pc), func_length_(func_length),
+ cie_offset_(cie_offset), cie_index_(cie_index),
+ fde_offset_(fde_offset) {
+ const Dwarf_Small *x =
+ reinterpret_cast<const Dwarf_Small *>(fde_bytes);
+ for(Dwarf_Unsigned i = 0; i < fde_length; ++i) {
+ fde_bytes_.push_back(x[i]);
+ }
+ };
+ ~IRFde() {};
+ Dwarf_Signed cie_index() { return cie_index_; };
+ void get_fde_base_data(Dwarf_Addr *lowpc, Dwarf_Unsigned * funclen,
+ Dwarf_Signed *cie_index_input) {
+ *lowpc = low_pc_;
+ *funclen = func_length_;
+ *cie_index_input = cie_index_;
+ };
+ void get_fde_instrs_into_ir(Dwarf_Ptr ip,Dwarf_Unsigned len ) {
+ const Dwarf_Small *x =
+ reinterpret_cast<const Dwarf_Small *>(ip);
+ for(Dwarf_Unsigned i = 0; i < len; ++i) {
+ fde_instrs_.push_back(x[i]);
+ }
+ };
+
+ void get_fde_instructions(Dwarf_Unsigned *len,
+ void **bytes) {
+ *len = fde_instrs_.size();
+ *bytes = reinterpret_cast<void *>(&fde_instrs_[0]);
+ };
+ void fde_instrs () {
+ };
+
+private:
+ Dwarf_Addr low_pc_;
+ Dwarf_Unsigned func_length_;
+ // fde_bytes_ may be empty if content bytes not yet created.
+ std::vector<Dwarf_Small> fde_bytes_;
+
+ std::vector<Dwarf_Small> fde_instrs_;
+ // cie_offset may be 0 if not known yet.
+ Dwarf_Off cie_offset_;
+ // cie_index is the index in ciedata_ of
+ // the applicable CIE. Begins with index 0.
+ Dwarf_Signed cie_index_;
+ // fde_offset may be 0 if not yet known.
+ Dwarf_Off fde_offset_;
+};
+
+class IRFrame {
+public:
+ IRFrame() {};
+ ~IRFrame() {};
+ void insert_cie(IRCie &cie) {
+ ciedata_.push_back(cie);
+ }
+ void insert_fde(IRFde &fdedata) {
+ fdedata_.push_back(fdedata);
+ unsigned findex = fdedata_.size() -1;
+ Dwarf_Signed cindex = fdedata.cie_index();
+ if( cindex != -1) {
+ IRCie & mycie = ciedata_[cindex];
+ mycie.insert_fde_index(findex);
+ }
+ }
+ std::vector<IRCie> &get_cie_vec() { return ciedata_; };
+ std::vector<IRFde> &get_fde_vec() { return fdedata_; };
+private:
+ std::vector<IRCie> ciedata_;
+ std::vector<IRFde> fdedata_;
+};
diff --git a/dwarfgen/irepline.h b/dwarfgen/irepline.h
new file mode 100644
index 0000000..88c3e07
--- /dev/null
+++ b/dwarfgen/irepline.h
@@ -0,0 +1,101 @@
+#ifndef IREPLINE_H
+#define IREPLINE_H
+/*
+ Copyright (C) 2011 David Anderson.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+*/
+
+//
+// irepline.h
+//
+
+class IRCULine {
+public:
+ IRCULine(Dwarf_Addr addr,Dwarf_Bool isset,
+ Dwarf_Unsigned fileno,
+ Dwarf_Unsigned lineno,
+ Dwarf_Unsigned linecol,
+ const std::string & linename,
+ Dwarf_Bool is_stmt,
+ Dwarf_Bool bb,
+ Dwarf_Bool endseq,
+ Dwarf_Bool prol_end,
+ Dwarf_Bool epil_beg,
+ Dwarf_Unsigned isa,
+ Dwarf_Unsigned discrim):
+ address_(addr),
+ isaddrset_(isset),
+ srcfileno_(fileno),
+ lineno_(lineno),
+ linecol_(linecol),
+ linesrc_(linename),
+ is_stmt_(is_stmt),
+ basic_block_(bb),
+ end_sequence_(endseq),
+ prologue_end_(prol_end),
+ epilogue_begin_(epil_beg),
+ isa_(isa),
+ discriminator_(discrim)
+ {};
+ const std::string &getpath() { return linesrc_; };
+ Dwarf_Addr getaddr() { return address_;};
+ bool getaddrset() { return isaddrset_;};
+ bool getendsequence() { return end_sequence_; };
+ Dwarf_Unsigned getlineno() { return lineno_; };
+ Dwarf_Unsigned getlinecol() { return linecol_; };
+ bool getisstmt() { return is_stmt_; };
+ bool getisblock() { return basic_block_; };
+ bool getepiloguebegin() { return epilogue_begin_; };
+ bool getprologueend() { return prologue_end_; };
+ Dwarf_Unsigned getisa() { return isa_; };
+ Dwarf_Unsigned getdiscriminator() { return discriminator_; };
+ ~IRCULine() {};
+private:
+
+ // Names taken from the DWARF4 std. document, sec 6.2.2.
+ Dwarf_Addr address_;
+ bool isaddrset_;
+ Dwarf_Unsigned srcfileno_;
+ Dwarf_Unsigned lineno_;
+ Dwarf_Signed linecol_; // aka lineoff
+ std::string linesrc_; // Name for the file, constructed by libdwarf.
+ bool is_stmt_;
+ bool basic_block_;
+ bool end_sequence_;
+ bool prologue_end_;
+ bool epilogue_begin_;
+ int isa_;
+ int discriminator_;
+};
+class IRCUSrcfile {
+public:
+ IRCUSrcfile(std::string file): cusrcfile_(file) {};
+ ~IRCUSrcfile() {};
+ std::string &getfilepath() {return cusrcfile_;};
+private:
+ std::string cusrcfile_;
+};
+
+class IRCULineData {
+public:
+ IRCULineData() {};
+ ~IRCULineData() {};
+ std::vector<IRCULine> &get_cu_lines() { return culinedata_; };
+ std::vector<IRCUSrcfile> &get_cu_srcfiles() { return cusrcfiledata_; };
+private:
+ std::vector<IRCUSrcfile> cusrcfiledata_;
+ std::vector<IRCULine> culinedata_;
+};
+#endif // IREPLINE_H
diff --git a/dwarfgen/irepmacro.h b/dwarfgen/irepmacro.h
new file mode 100644
index 0000000..103772e
--- /dev/null
+++ b/dwarfgen/irepmacro.h
@@ -0,0 +1,47 @@
+/*
+ Copyright (C) 2010-2011 David Anderson.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+*/
+
+//
+// irepmacro.h
+//
+
+class IRMacroRecord {
+public:
+ IRMacroRecord() {};
+ ~IRMacroRecord() {};
+ IRMacroRecord(Dwarf_Off cuDieOffset,Dwarf_Off offset,Dwarf_Small type,
+ Dwarf_Signed lineno, Dwarf_Signed lineindex,
+ const std::string &macro):cuDieOffset_(cuDieOffset),
+ offset_(offset),
+ type_(type),lineno_(lineno),lineindex_(lineindex),
+ macro_(macro) {};
+private:
+ Dwarf_Off cuDieOffset_;
+ Dwarf_Off offset_;
+ Dwarf_Small type_;
+ Dwarf_Signed lineno_;
+ Dwarf_Signed lineindex_;
+ std::string macro_;
+};
+class IRMacro {
+public:
+ IRMacro() {};
+ ~IRMacro() {};
+ std::vector<IRMacroRecord> &getMacroVec() { return macrorec_; };
+private:
+ std::vector<IRMacroRecord> macrorec_;
+};
diff --git a/dwarfgen/irepresentation.h b/dwarfgen/irepresentation.h
new file mode 100644
index 0000000..3718c71
--- /dev/null
+++ b/dwarfgen/irepresentation.h
@@ -0,0 +1,135 @@
+/*
+ Copyright (C) 2010-2011 David Anderson.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+*/
+
+//
+// irepresentation.h
+// The internal (to dwarfgen) representation of debug information.
+// All the various components (info, frame, etc)
+// will be stored here in an internal-to-dwarfgen form.
+//
+//
+#include "irepform.h"
+#include "irepline.h"
+#include "irepdie.h"
+#include "irepmacro.h"
+#include "irepframe.h"
+#include "strtabdata.h"
+
+// The elf symbols are used to tie relocations to values.
+// We do relocations ourselves in dwarfgen so the data is not needed
+// once the dwarf .debug_* sections created in elf.
+// We don't write the symbols out as an elf section.
+// The position in the vector of symbols is the 'elf symbol index'
+// we create.
+// Symbol 0 is 'no symbol'.
+// Symbol 1 is .text
+class ElfSymbol {
+public:
+ ElfSymbol():symbolValue_(0),
+ nameIndex_(0) {};
+ ElfSymbol(Dwarf_Unsigned val, const std::string&name, strtabdata&stab):
+ symbolValue_(val),name_(name) {
+ nameIndex_ = stab.addString(name);
+ };
+ ~ElfSymbol() {};
+ Dwarf_Unsigned getSymbolValue() const { return symbolValue_;}
+private:
+ Dwarf_Unsigned symbolValue_;
+ std::string name_;
+ // The offset in the string table.
+ unsigned nameIndex_;
+};
+
+class ElfSectIndex {
+public:
+ ElfSectIndex():elfsect_(0) {};
+ ~ElfSectIndex() {};
+ ElfSectIndex(unsigned v):elfsect_(v) {};
+ unsigned getSectIndex() const { return elfsect_; }
+ void setSectIndex(unsigned v) { elfsect_ = v; }
+private:
+ unsigned elfsect_;
+};
+
+
+class ElfSymIndex {
+public:
+ ElfSymIndex():elfsym_(0) {};
+ ~ElfSymIndex() {};
+ ElfSymIndex(unsigned v):elfsym_(v) {};
+ unsigned getSymIndex() const { return elfsym_; }
+ void setSymIndex(unsigned v) { elfsym_ = v; }
+private:
+ unsigned elfsym_;
+};
+
+class ElfSymbols {
+public:
+ ElfSymbols() {
+ // The initial symbol is 'no symbol'.
+ std::string emptyname("");
+ elfSymbols_.push_back(ElfSymbol(0,emptyname,symstrtab_));
+
+ // We arbitrarily make this symbol .text now, though
+ // not needed yet.
+ std::string textname(".text");
+ elfSymbols_.push_back(ElfSymbol(0,textname,symstrtab_));
+ baseTextAddressSymbol_.setSymIndex(elfSymbols_.size()-1);
+ }
+ ~ElfSymbols() {};
+ ElfSymIndex getBaseTextSymbol() const {return baseTextAddressSymbol_;};
+ ElfSymIndex addElfSymbol(Dwarf_Unsigned val, const std::string&name) {
+ elfSymbols_.push_back(ElfSymbol(val,name,symstrtab_));
+ ElfSymIndex indx(elfSymbols_.size()-1);
+ return indx;
+
+ };
+ ElfSymbol & getElfSymbol(ElfSymIndex symi) {
+ size_t i = symi.getSymIndex();
+ if (i >= elfSymbols_.size()) {
+ std::cerr << "Error, sym index " << i << " to big for symtab size " << elfSymbols_.size() << std::endl;
+ exit(1);
+ }
+ return elfSymbols_[i];
+ }
+private:
+ std::vector<ElfSymbol> elfSymbols_;
+ strtabdata symstrtab_;
+ ElfSymIndex baseTextAddressSymbol_;
+};
+
+
+class IRepresentation {
+public:
+ IRepresentation() {};
+ ~IRepresentation(){};
+ IRFrame &framedata() { return framedata_; };
+ IRMacro &macrodata() { return macrodata_; };
+ IRDInfo &infodata() { return debuginfodata_; };
+ ElfSymbols &getElfSymbols() { return elfSymbols_;};
+ unsigned getBaseTextSymbol() {
+ return elfSymbols_.getBaseTextSymbol().getSymIndex();};
+private:
+ // The Elf symbols data to use for relocations
+ ElfSymbols elfSymbols_;
+
+ IRFrame framedata_;
+ IRMacro macrodata_;
+
+ // Line data is inside IRDInfo.
+ IRDInfo debuginfodata_;
+};
diff --git a/dwarfgen/ireptodbg.cc b/dwarfgen/ireptodbg.cc
new file mode 100644
index 0000000..bc56e36
--- /dev/null
+++ b/dwarfgen/ireptodbg.cc
@@ -0,0 +1,371 @@
+/*
+ Copyright (C) 2010-2011 David Anderson.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+*/
+
+// ireptodbg.cc
+
+#include "config.h"
+#include <unistd.h>
+#include <stdlib.h> // for exit
+#include <iostream>
+#include <string>
+#include <list>
+#include <map>
+#include <vector>
+#include <string.h> // For memset etc
+#include <sys/stat.h> //open
+#include <fcntl.h> //open
+#include "elf.h"
+#include "gelf.h"
+#include "strtabdata.h"
+#include "dwarf.h"
+#include "libdwarf.h"
+#include "irepresentation.h"
+#include "ireptodbg.h"
+#include "irepattrtodbg.h"
+#include "general.h"
+
+using std::string;
+using std::cout;
+using std::cerr;
+using std::endl;
+using std::vector;
+using std::map;
+using std::list;
+
+static Dwarf_Error error;
+
+typedef std::map<std::string,unsigned> pathToUnsignedType;
+
+static Dwarf_P_Die
+HandleOneDieAndChildren(Dwarf_P_Debug dbg,
+ IRepresentation & Irep,
+ IRDie &inDie, unsigned level)
+{
+ list<IRDie>& children = inDie.getChildren();
+ // We create our target DIE first so we can link
+ // children to it, but add no content yet.
+ Dwarf_P_Die ourdie = dwarf_new_die(dbg,inDie.getTag(),NULL,NULL,
+ NULL,NULL,&error);
+ if (reinterpret_cast<int>(ourdie) == DW_DLV_BADADDR) {
+ cerr << "Die creation failure. "<< endl;
+ exit(1);
+ }
+
+ Dwarf_P_Die lastch = 0;
+ for ( list<IRDie>::iterator it = children.begin();
+ it != children.end();
+ it++) {
+ IRDie & ch = *it;
+ Dwarf_P_Die chp = HandleOneDieAndChildren(dbg,Irep,ch,level+1);
+ Dwarf_P_Die res = 0;
+ if(lastch) {
+ // Link to right of earlier sibling.
+ res = dwarf_die_link(chp,NULL,NULL,lastch,NULL,&error);
+ } else {
+ // Link as first child.
+ res = dwarf_die_link(chp,ourdie,NULL,NULL, NULL,&error);
+ }
+ // Bad cast here, FIXME
+ if (reinterpret_cast<int>(res) == DW_DLV_BADADDR) {
+ cerr << "Die link failure. "<< endl;
+ exit(1);
+ }
+ lastch = chp;
+ }
+ list<IRAttr>& attrs = inDie.getAttributes();
+ // Now we add attributes (content), if any, to the 'ourdie'.
+ for (list<IRAttr>::iterator it = attrs.begin();
+ it != attrs.end();
+ it++) {
+ IRAttr & attr = *it;
+ AddAttrToDie(dbg,Irep,ourdie,inDie,attr);
+ }
+ return ourdie;
+}
+
+static void
+HandleLineData(Dwarf_P_Debug dbg,IRepresentation & Irep, IRCUdata&cu)
+{
+ Dwarf_Error error = 0;
+ // We refer to files by fileno, this builds an index.
+ pathToUnsignedType pathmap;
+
+ IRCULineData& ld = cu.getCULines();
+ std::vector<IRCULine> & cu_lines = ld.get_cu_lines();
+ //std::vector<IRCUSrcfile> &cu_srcfiles = ld.get_cu_srcfiles();
+ if(cu_lines.empty()) {
+ // No lines data to emit, do nothing.
+ return;
+ }
+ // To start with, we are doing a trivial generation here.
+ // To be refined 'soon'. FIXME
+ // Initially we don't worry about dwarf_add_directory_decl().
+
+ bool firstline = true;
+ bool addrsetincu = false;
+ for(unsigned k = 0; k < cu_lines.size(); ++k) {
+ IRCULine &li = cu_lines[k];
+ const std::string&path = li.getpath();
+ unsigned pathindex = 0;
+ pathToUnsignedType::const_iterator it = pathmap.find(path);
+ if(it == pathmap.end()) {
+ Dwarf_Error error = 0;
+ Dwarf_Unsigned idx = dwarf_add_file_decl(
+ dbg,const_cast<char *>(path.c_str()),
+ 0,0,0,&error);
+ if(idx == DW_DLV_NOCOUNT) {
+ cerr << "Error from dwarf_add_file_decl() on " <<
+ path << endl;
+ exit(1);
+ }
+ pathindex = idx;
+ pathmap[path] = pathindex;
+ } else {
+ pathindex = it->second;
+ }
+ Dwarf_Addr a = li.getaddr();
+ bool addrsetinline = li.getaddrset();
+ bool endsequence = li.getendsequence();
+ if(firstline || !addrsetincu) {
+ // We fake an elf sym index here.
+ Dwarf_Unsigned elfsymidx = 0;
+ if(firstline && !addrsetinline) {
+ cerr << "Error building line, first entry not addr set" <<
+ endl;
+ exit(1);
+ }
+ Dwarf_Unsigned res = dwarf_lne_set_address(dbg,
+ a,elfsymidx,&error);
+ if(res == DW_DLV_NOCOUNT) {
+ cerr << "Error building line, dwarf_lne_set_address" <<
+ endl;
+ exit(1);
+ }
+ addrsetincu = true;
+ firstline = false;
+ } else if( endsequence) {
+ Dwarf_Unsigned esres = dwarf_lne_end_sequence(dbg,
+ a,&error);
+ if(esres == DW_DLV_NOCOUNT) {
+ cerr << "Error building line, dwarf_lne_end_sequence" <<
+ endl;
+ exit(1);
+ }
+ addrsetincu = false;
+ continue;
+ }
+ Dwarf_Signed linecol = li.getlinecol();
+ // It's really the code address or (when in a proper compiler)
+ // a section or function offset.
+ // libdwarf subtracts the code_offset from the address passed
+ // this way or from dwarf_lne_set_address() and writes a small
+ // offset in a DW_LNS_advance_pc instruction.
+ Dwarf_Addr code_offset = a;
+ Dwarf_Unsigned lineno = li.getlineno();
+ Dwarf_Bool isstmt = li.getisstmt()?1:0;
+ Dwarf_Bool isblock = li.getisblock()?1:0;
+ Dwarf_Bool isepiloguebegin = li.getepiloguebegin()?1:0;
+ Dwarf_Bool isprologueend = li.getprologueend()?1:0;
+ Dwarf_Unsigned isa = li.getisa();
+ Dwarf_Unsigned discriminator = li.getdiscriminator();
+ Dwarf_Unsigned lires = dwarf_add_line_entry_b(dbg,
+ pathindex,
+ code_offset,
+ lineno,
+ linecol,
+ isstmt,
+ isblock,
+ isepiloguebegin,
+ isprologueend,
+ isa,
+ discriminator,
+ &error);
+ if(lires == DW_DLV_NOCOUNT) {
+ cerr << "Error building line, dwarf_add_line_entry" <<
+ endl;
+ exit(1);
+ }
+ }
+ if(addrsetincu) {
+ cerr << "CU Lines did not end in an end_sequence!" << endl;
+ }
+}
+// This emits the DIEs for a single CU and possibly line data
+// associated with the CU.
+// The DIEs form a graph (which can be created and linked together
+// in any order) and which is emitted in tree preorder as
+// defined by the DWARF spec.
+//
+static void
+emitOneCU( Dwarf_P_Debug dbg,IRepresentation & Irep, IRCUdata&cu,
+ int cu_of_input_we_output)
+{
+ // We descend the the tree, creating DIEs and linking
+ // them in as we return back up the tree of recursing
+ // on IRDie children.
+ Dwarf_Error error;
+
+ IRDie & basedie = cu.baseDie();
+ Dwarf_P_Die cudie = HandleOneDieAndChildren(dbg,Irep,basedie,0);
+
+ // Add base die to debug, this is the CU die.
+ // This is not a good design as DWARF3/4 have
+ // requirements of multiple CUs in a single creation,
+ // which cannot be handled yet.
+ Dwarf_Unsigned res = dwarf_add_die_to_debug(dbg,cudie,&error);
+ if(res != DW_DLV_OK) {
+ cerr << "Unable to add_die_to_debug " << endl;
+ exit(1);
+ }
+
+ HandleLineData(dbg,Irep,cu);
+}
+// .debug_info creation.
+// Also creates .debug_line
+static void
+transform_debug_info(Dwarf_P_Debug dbg,
+ IRepresentation & irep,int cu_of_input_we_output)
+{
+ int cu_number = 0;
+ std::list<IRCUdata> &culist = irep.infodata().getCUData();
+ // For now, just one CU we write (as spoken by Yoda).
+
+ for ( list<IRCUdata>::iterator it = culist.begin();
+ it != culist.end();
+ it++,cu_number++) {
+ if(cu_number == cu_of_input_we_output) {
+ IRCUdata & primecu = *it;
+ emitOneCU(dbg,irep,primecu,cu_of_input_we_output);
+ break;
+ }
+ }
+}
+static void
+transform_cie_fde(Dwarf_P_Debug dbg,
+ IRepresentation & Irep,int cu_of_input_we_output)
+{
+ Dwarf_Error err = 0;
+ std::vector<IRCie> &cie_vec = Irep.framedata().get_cie_vec();
+ std::vector<IRFde> &fde_vec = Irep.framedata().get_fde_vec();
+
+ for(size_t i = 0; i < cie_vec.size(); ++i) {
+ IRCie &ciein = cie_vec[i];
+ Dwarf_Unsigned version = 0;
+ string aug;
+ Dwarf_Unsigned code_align = 0;
+ Dwarf_Signed data_align = 0;
+ Dwarf_Half ret_addr_reg = -1;
+ void * bytes = 0;
+ Dwarf_Unsigned bytes_len;
+ ciein.get_basic_cie_data(&version, &aug,
+ &code_align, &data_align, &ret_addr_reg);
+ ciein.get_init_instructions(&bytes_len,&bytes);
+ // version implied: FIXME, need to let user code set output
+ // frame version.
+ char *str = const_cast<char *>(aug.c_str());
+ Dwarf_Signed out_cie_index =
+ dwarf_add_frame_cie(dbg, str,
+ code_align, data_align, ret_addr_reg,
+ bytes,bytes_len,
+ &err);
+ if(out_cie_index == DW_DLV_NOCOUNT) {
+ cerr << "Error creating cie from input cie " << i << endl;
+ exit(1);
+ }
+ vector<int> fdeindex;
+ // This inner loop is C*F so a bit slow.
+ for(size_t j = 0; j < fde_vec.size(); ++j) {
+ IRFde &fdein = fde_vec[j];
+ Dwarf_Unsigned code_len = 0;
+ Dwarf_Addr code_virt_addr = 0;
+ Dwarf_Signed cie_input_index = 0;
+ fdein.get_fde_base_data(&code_virt_addr,
+ &code_len, &cie_input_index);
+ if(cie_input_index != i) {
+ // Wrong cie, ignore this fde right now.
+ continue;
+ }
+
+
+ Dwarf_P_Fde fdeout = dwarf_new_fde(dbg,&err);
+ if(reinterpret_cast<Dwarf_Addr>(fdeout) == DW_DLV_BADADDR) {
+ cerr << "Error creating new fde " << j << endl;
+ exit(1);
+ }
+ Dwarf_Unsigned ilen = 0;
+ void *instrs = 0;
+ fdein.get_fde_instructions(&ilen, &instrs);
+
+ int res = dwarf_insert_fde_inst_bytes(dbg,
+ fdeout, ilen, instrs,&err);
+ if(res != DW_DLV_OK) {
+ cerr << "Error inserting frame instr block " << j << endl;
+ exit(1);
+ }
+
+ Dwarf_P_Die irix_die = 0;
+ Dwarf_Signed irix_table_offset = 0;
+ Dwarf_Unsigned irix_excep_sym = 0;
+ Dwarf_Unsigned code_virt_addr_symidx =
+ Irep.getBaseTextSymbol();
+ Dwarf_Unsigned fde_index = dwarf_add_frame_info(
+ dbg, fdeout,irix_die,
+ out_cie_index, code_virt_addr,
+ code_len,code_virt_addr_symidx,
+ irix_table_offset,irix_excep_sym,
+ &err);
+ if(fde_index == DW_DLV_BADADDR) {
+ cerr << "Error creating new fde " << j << endl;
+ exit(1);
+ }
+ }
+ }
+}
+
+static void
+transform_macro_info(Dwarf_P_Debug dbg,
+ IRepresentation & Irep,int cu_of_input_we_output)
+{
+ IRMacro &macrodata = Irep.macrodata();
+ std::vector<IRMacroRecord> &macrov = macrodata.getMacroVec();
+ for(size_t m = 0; m < macrov.size() ; m++ ) {
+ // FIXME: we need to coordinate with generated
+ // CUs .
+ cout << "FIXME: macros not really output yet " <<
+ m << " " <<
+ macrov.size() << endl;
+ }
+ Dwarf_Unsigned reloc_count = 0;
+ int drd_version = 0;
+ int res = dwarf_get_relocation_info_count(dbg,&reloc_count,
+ &drd_version,&error);
+ if( res != DW_DLV_OK) {
+ cerr << "Error getting relocation info count." << endl;
+ exit(1);
+
+ }
+ for( Dwarf_Unsigned ct = 0; ct < reloc_count ; ++ct) {
+ }
+}
+void
+transform_irep_to_dbg(Dwarf_P_Debug dbg,
+ IRepresentation & Irep,int cu_of_input_we_output)
+{
+ transform_debug_info(dbg,Irep,cu_of_input_we_output);
+ transform_cie_fde(dbg,Irep,cu_of_input_we_output);
+ transform_macro_info(dbg,Irep,cu_of_input_we_output);
+}
diff --git a/dwarfgen/ireptodbg.h b/dwarfgen/ireptodbg.h
new file mode 100644
index 0000000..ae1088c
--- /dev/null
+++ b/dwarfgen/ireptodbg.h
@@ -0,0 +1,24 @@
+/*
+ Copyright (C) 2010-2011 David Anderson.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+*/
+
+
+
+// ireptodbg.h
+
+
+void transform_irep_to_dbg(Dwarf_P_Debug dbg, IRepresentation & Irep,
+ int cu_of_input_we_output);
diff --git a/dwarfgen/strtabdata.h b/dwarfgen/strtabdata.h
new file mode 100755
index 0000000..d005055
--- /dev/null
+++ b/dwarfgen/strtabdata.h
@@ -0,0 +1,65 @@
+#ifndef STRTABDATA_H
+#define STRTABDATA_H
+/*
+ Copyright (C) 2010-2011 David Anderson.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+*/
+
+
+// strtabdata.h
+// Creates a string table in a way consistent with
+// elf string tables. The zero index is a null byte always.
+
+class strtabdata {
+public:
+ strtabdata(): data_(new char[1000]),
+ datalen_(1000), nexttouse_(0) { data_[0] = 0; nexttouse_ = 1;};
+ ~strtabdata() { delete[]data_; };
+ unsigned addString(const std::string & newstr) {
+ // The 1 is for the terminating null byte.
+ unsigned nsz = newstr.size() +1;
+ unsigned needed = nexttouse_ + nsz;
+ if (needed >= datalen_) {
+ unsigned baseincr = nsz;
+ unsigned altincr = datalen_*2;
+ if(altincr> baseincr) {
+ baseincr = altincr;
+ }
+ unsigned newsize = datalen_ + baseincr;
+ char *newdata = new char [newsize];
+ memcpy(newdata, data_, nexttouse_);
+ delete [] data_;
+ data_ = newdata;
+ datalen_ = newsize;
+ }
+ memcpy(data_ + nexttouse_, newstr.c_str(),nsz);
+ unsigned newstrindex = nexttouse_;
+ nexttouse_ += nsz;
+ return newstrindex;
+ };
+ void *exposedata() {return (void *)data_;};
+ unsigned exposelen() const {return nexttouse_;};
+private:
+ char * data_;
+
+ // datalen_ is the size in bytes pointed to by data_ .
+ unsigned datalen_;
+
+ // nexttouse_ is the index of the next (unused) byte in
+ // data_ , so it is also the amount of space in data_ that
+ // is in use.
+ unsigned nexttouse_;
+};
+#endif /* STRTABDATA_H */
diff --git a/libdwarf/CHANGES b/libdwarf/CHANGES
new file mode 100644
index 0000000..88fbcd8
--- /dev/null
+++ b/libdwarf/CHANGES
@@ -0,0 +1,102 @@
+
+
+-------------------------------------------------------------
+April 14, 2000 davea@sgi.com
+Corrected minor bugs in production of 32bit dwarf with
+64 bit pointers. Fixed omissions in legal
+DIE children of a DIE. Make small changes in
+description of regster output in frame information
+access.
+
+-------------------------------------------------------------
+Mar 7, 2000 davea@sgi.com
+Corrected line table reading so it will handle
+reading an object with a diffent number of standard
+op codes than at libdwarf compile time.
+This was possible all along, but libdwarf did
+not do it right.
+
+-------------------------------------------------------------
+Dec 8, 1999 davea@sgi.com
+Changed nearly all files.
+Adding the capability to read and produce
+the new, accepted by committee, but not
+released-publically 64bit extension proposal
+dwarf data.
+This allows dwarf compilation units
+with 64bit section offsets and 32bit
+sections offsets to be mixed.
+So that offsets can grow very large with
+64-bit pointer applications (though 64bit pointers
+and 64bit offsets are not the same notion).
+
+In addition, removed all the contents (or nearly all)
+of the dwarf_funcs.c dwarf_weaks.c dwarf_vars.c,
+and dwarf_types.c, as the data format is identical
+to dwarf globals (pubnames) and there is no need
+to duplicate all that code.
+
+All these sections whose contents were gutted are things that
+are formatted exactly like pubnames, and all are sgi
+extensions. Now the implementation uses pubnames code
+(dwarf_global.c) to do the work for all the pubnames-like
+sections.
+
+The (minor, IMO) difference is that in case of an incorrect
+dwarf file (leading to libdwarf being unable to process
+something in one of the sgi-specific pubnames-like sections)
+the dwarf error string may reference pubnames when weaks,
+static functions, static variables, or global typenames are
+actually the problem. This is fixable, however the price would
+appear to be that even globals would need to call a helper
+function (to pass in the correct error return). Right now the
+dwarf_weaks.c calls the dwarf_global.c function, for example,
+with no extra arguments indicating the true section involved.
+(Other approaches keeping the original error codes exist.
+Producing the code uniquely via macros seems unappealing.
+Inline functions would be ok though. This version does not
+inline the functions we are talking about, such as
+dwarf_global_name_offsets() when called from
+dwarf_type_name_offsets().)
+
+Since these extra sections are SGI only and only really used by
+SGI's workshop product, and the performance hit is small, the
+extra function calls in reading each seem acceptable.
+
+
+-------------------------------------------------------------
+Sep 29,1999 davea@sgi.com
+Changed many files, so that it is easy to switch
+from 32bit-offset-only (like cygnus
+and dwarf2 v 2.0.0) to sgi/mips 64 bit dwarf.
+See NEWS for more info on 32bit-offset.
+
+
+-------------------------------------------------------------
+Since Oct 95 and before May, 1996
+
+Added the function dwarf_get_cie_of_fde() which makes it possible
+to remember a single fde/cie set out of a block usefully.
+
+Enhanced doc of dwarf_bitoffset()
+
+Added new function dwarf_global_formref() so all reference
+forms can be retrieved.
+
+Fixed bug in retrieving array bounds: was failing to sign extend
+formsdata.
+
+Added function dwarf_get_fde_info_for_all_regs(), which makes
+retrieval of the complete set of registers (as needed by
+debuggers and exception handlers) effectively N times faster
+than getting them one a time where N is the number of registers.
+
+Added support for exception table handling (really just support
+for a reference to an exception table for c++ exceptions).
+
+Fixed a bug where useless extra space (several megabytes)
+were malloc'ed for the abbreviations table by the libdwarf
+consumer code.
+
+davea@sgi.com
+-------------------------------------------------------------
diff --git a/libdwarf/CODINGSTYLE b/libdwarf/CODINGSTYLE
new file mode 100644
index 0000000..3dd7601
--- /dev/null
+++ b/libdwarf/CODINGSTYLE
@@ -0,0 +1,61 @@
+This document is a brief description of the main
+coding style conventions in libdwarf. Many of them
+will be obvious from the code, but over time some
+accidental diffences crept in.
+
+
+Code should be indented in multiples of 4 spaces, and
+tabs should not be used to indent the source code.
+Use the dicheck program to check indenting.
+
+
+dwarf.h and libdwarf.h must have all arguments commented
+out as these are public headers. Because a prototype like
+int dwarf_example_prototype(Dwarf_Debug foo);
+would be made unusable by a legitimate
+preprocessor definition
+such as #define foo +
+
+The struct naming convention is 'struct Camel_Caps_s' for the
+struct and 'Camel_Caps' for any typedef for the struct.
+Admittedly having both camel caps
+and an underbar is an unusual convention, but it is
+the way the coding was begun in the early 1990's and
+we should remain consistent now.
+
+All user-referenceable data and functions
+and user_visible types should begin with DW_ or
+dwarf_. Non-static libdwarf global data and functions
+should begin with _dwarf (a somewhat questionable
+approach, but workable).
+
+Function names should be all lower case with underbars
+for readability.
+
+There should never be static data in any function.
+Nor should there ever be static data outside of libdwarf
+functions. libdwarf can be called from multiple threads
+(but only from one thread per Dwarf_Debug) and multiple
+Dwarf_Debug objects can be open at one time.
+Instead place such data per-dbg into the Dwarf_Debug structure
+in dwarf_opaque.h. Similarly for the producer code.
+
+Function-local variables should be lower-case with
+underbars for readability. It's ok for a small loop
+with counters to use single letter names like i or k or m.
+
+structure members should have a struct-specific
+2-character prefix to the name (followed by
+an underbar). That makes it much
+easier to grep for uses of members.
+
+Try to keep lines under 80 characters in length.
+
+Ensure every if() has {} to enclose the actions.
+
+Use libdwarf.h types for all the data objects you define,
+though sometimes an 'unsigned' or 'int' or 'size_t' is
+ok in restricted circumstances. Dwarf_Unsigned Dwarf_Signed
+are the preferred integer types for general use.
+
+------------
diff --git a/libdwarf/COPYING b/libdwarf/COPYING
new file mode 100644
index 0000000..eb621ce
--- /dev/null
+++ b/libdwarf/COPYING
@@ -0,0 +1,37 @@
+
+
+The files:
+ libdwarf.h
+ dwarf.h
+ and all the .h and .c files in this implementation of
+ libdwarf are copyrighted according to the file
+ LIBDWARFCOPYRIGHT (which mentions the LGPL version 2.1).
+ The full text of the LGPL 2.1 is provided in LGPL.txt
+
+
+The dwarf documentation:
+ dwarf.v2.mm and its postscript form and its
+ indexes are copyright Unix International (UI is now defunct).
+ One presumes XOPEN owns the copyright now. In any case copying
+ and revision without fee is permitted (see the
+ copyright in the document).
+
+The libdwarf documentation:
+ libdwarf2.1.mm
+ is based on material submitted to the UI PLSIG as proposed
+ interfaces for dwarf, but completely rewritten.
+ Copyright ownership is therefore SGI (but see the document for details)
+ and it seems clear that the intent was there was to be free
+ copying with no fees.
+
+ libdwarf2p.1.mm
+ is documentation of a set of interfaces
+ (not part of the UI PLSIG proposals)
+ and the document was written from scratch at SGI.
+ Copyright ownership is therefore SGI (but see the document for details)
+ and it seems clear that the intent was there was to be free
+ copying with no fees.
+
+$Source: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/libdwarf/RCS/COPYING,v $
+$Revision: 1.2 $
+$Date: 2001/01/16 17:08:36 $
diff --git a/libdwarf/ChangeLog b/libdwarf/ChangeLog
new file mode 100644
index 0000000..247cf9f
--- /dev/null
+++ b/libdwarf/ChangeLog
@@ -0,0 +1,9 @@
+2012-04-04 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h: A pointer "*" was right next to
+ a "/*" so a space introduced between them for clarity.
+ Fixed comments on DW_DLC_SIZE_64 and DW_DLC_SIZE_32.
+ * dwarf_die_deliv.c: Two local variables were declared in the
+ middle of code, accidentally creating C99 dependencies.
+ Both trivially fixed with no change in logic.
+2012-01-01 DavidAnderson <davea42@earthlink.net>
+ * A new year starts.
diff --git a/libdwarf/ChangeLog2006 b/libdwarf/ChangeLog2006
new file mode 100644
index 0000000..02009d6
--- /dev/null
+++ b/libdwarf/ChangeLog2006
@@ -0,0 +1,835 @@
+2006-12-05 David Anderson <davea@sgi.com>
+ * dwarf_error.c, libdwarf.h: added
+ DW_DLE_FRAME_REGISTER_COUNT_MISMATCH.
+ * dwarf_frame.c (_dwarf_exec_frame_instr): removed references
+ to compile-time constants for register table size. Now uses
+ run-time-chosen sizes. Now uses heap for reg table instead
+ of stack. Now uses SIMPLE_ERROR_RETURN macro to simplify
+ the code.
+2006-11-08 David Anderson <davea@sgi.com>
+ * pro_expr.c (dwarf_add_expr_gen): DW_OP_deref_size,
+ DW_OP_xderef_size, and DW_OP_pick were incorrect, missing
+ & operator. Would coredump. Thanks to Alan Chambers for mentioning
+ the coredump.
+2006-09-26 David Anderson <davea@sgi.com>
+ * dwarf_die_deliv.c (dwarf_offdie): Now returns the
+ correct die (worked before, almost always, but worked by accident).
+ Thanks to Mattias Lindblad for supplying a test case.
+2006-09-01 David Anderson <davea@sgi.com>
+ * libdwarf2.1.mm (dwarf_loclist_n): Minor refinement
+ of the description.
+ * libdwarf2.1.ps: regenerated
+2006-08-31 David Anderson <davea@sgi.com>
+ * libdwarf2.1.mm (dwarf_loclist_n): A location expression
+ sets ld_lopc to 0, ld_hipc to all-bits-on, and this
+ is now documented.
+ * libdwarf2.1.ps: regenerated
+2006-06-14 David Anderson <davea@sgi.com>
+ * dwarf_opaque.h dwarf_frame.h dwarf_frame.c
+ dwarf_init_finish.c dwarf_frame2.c: Corrected handling
+ of eh_frame zP encoding.
+ Thanks to Cristi Vlasceanu for noticing it was broken.
+ * Makefile.in: remove libdwarf.so in 'clean' rule.
+ Thanks to Cristi Vlasceanu for noticing it was missing.
+2006-04-28 David Anderson <davea@sgi.com>
+ * dwarf_frame.c: Changed local variable type to
+ avoid compiler warning.
+2006-04-21 David Anderson <davea@sgi.com>
+ * dwarf_frame.c: Initialized local to 0, wrong value.
+ Thanks to Cristi Vlasceanu for noticing.
+2006-04-18 David Anderson <davea@sgi.com>
+ * All *.c: Ran indent so all c files follow a standard look.
+2006-04-16 David Anderson <davea@sgi.com>
+ * dwarf.h: Remove #if 0 around some #defines, it is ok to
+ leave the defines visible (the defines are HP extensions).
+ * libdwarf.h: Add new dwarf3 interface to frames.
+ (which actually is also a better interface to dwarf2 info,
+ not strictly for dwarf3).
+ * dwarf_alloc.c: Add 'constructor/destructor' pointers
+ to the initialization table so we can handle a more
+ flexible (dwarf3) frame interface.Call the functions
+ at the appropriate times.
+ * dwarf_frame.c: Using macro FDE_NULL_CHECKS_AND_SET_DBG
+ reduce duplicate coding.Internal code now handles dwarf2
+ and dwarf3 and interfaces to exported interfaces appropriately.
+ * dwarf_frame.h: Alter internal struct to handle frames more flexibly.
+ * dwarf_frame2.c: Remove unused local variable.
+ * dwarf_init_finish.c: Add initialization of new Dwarf_Debug
+ struct entries allowing handling
+ of run-time-config of frame info.
+ * dwarf_loc.c: Add DWARF3 operators, such as DW_OP_call4.
+ * dwarf_opaque.h: Declaration of new Dwarf_Debug struct
+ entries allowing handling of run-time-config of frame info.
+ * pro_expr.c: Add entries allowing creation of DWARF3 DW_OP
+ such as call2.
+ * pro_section.c: Change crucial code handling section lengths,
+ using a macro BEGIN_LEN_SIZE to clarify and correct a few places.
+2006-03-31 David Anderson <davea@sgi.com>
+ * libdwarf.h: Added dwarf_get_fde_info_for_cfa_reg3() prototype
+ preparing for dwarf3 frame interface.
+ * dwarf_frame.c: Now uses separate rule, not DW_FRAME_CFA_COL,
+ to record CFA.
+ * dwarf_frame.h: Add commentary on frame access.
+2006-03-30 David Anderson <davea@sgi.com>
+ * Makefile.in configure.in: Adding --enable-shared --enable-nonshared
+ --disable-shared and --disable-nonshared.
+ * configure: regenerated with 2.59 autoconf.
+ * README: Added explanation on changing dwarf.h libdwarf.h.
+2006-03-29 David Anderson <davea@sgi.com>
+ * dwarf_print_lines.c dwarf_sort_line.c: Clean up initialization
+ code for line table reading. When returning rules table
+ data to caller ensure fully filled out yet no overrun
+ (handling case where rules table sizes not defined identically
+ by caller and library).
+ * dwarf.h: New commentary on ABI/register-number issues.
+ * libdwarf.h: New commentary on ABI/register-number issues.
+2006-03-26 David Anderson <davea@sgi.com>
+ * dwarf_line.c: file_entry_count local was not initialized.
+ Initialized some locals at declaration.
+ Thanks to Mikael Vidstedt for noticing.
+2006-03-23 David Anderson <davea@sgi.com>
+ * dwarf_error.c: added error strings for codes 200,201
+ * dwarf_line.c dwarf_line.h dwarf_print_lines.c dwarf_sort_line.c: Moved
+ line prefix reading to a common routine, filling in a new internal
+ struct to make it simple. Removed much duplicate code.
+ Added more support for dwarf3 line table standard opcodes.
+ Now prints details (with -v -v) of standard opcodes it
+ does not understand (if any present).
+2006-03-13 David Anderson <davea@sgi.com>
+ * dwarf.h: add ALTIUM #defines (extensions to dwarf)
+ * libdwarf.h: Alter arguments to new
+ functions dwarf_get_fde_augmentation_data() and
+ dwarf_get_cie_augmentation_data() used by GNU eh_frame.
+ * dwarf_frame.h: Add new fields so we can handle GNU eh_frame.
+ * dwarf_frame.c: Remove erroneous load_sections calls (wrong for eh_frame
+ data) and correct the new dwarf_get_fde_augmentation_data() and
+ dwarf_get_cie_augmentation_data() implementation.
+ * dwarf_frame2.c: Implement support for GNU eh_frame.
+ * dwarf_line.h: Correct handling of DWARF3 opcode base check.
+ * dwarf_line.c: Add new macro use to get DWARF3 opcode base handling correct.
+ * dwarf_print_lines.c: Add new macro use to get DWARF3 opcode base handling correct.
+ * dwarf_sort_lines.c: Add new macro use to get DWARF3 opcode base handling correct.
+2006-03-08 David Anderson <davea@sgi.com>
+ * dwarf_frame2.c: ensure local variables initialized
+ to avoid coredump.
+2006-03-08 David Anderson <davea@sgi.com>
+ * dwarf_die_deliv.c: Remove Richard Stukey's -1 and
+ replace with a simpler more complete fix.
+2006-03-07 David Anderson <davea@sgi.com>
+ * Makefile.in: Add dwarf_line2.c dwarf_frame3.c to files to build.
+ * dwarf_addr_finder.c: Add comments about file purpose.
+ * dwarf_frame.c: Move IRIX specific function out of this file.
+ * dwarf_frame3.c: Move IRIX specific function to this new file.
+ * dwarf_frame.h: Add interface declaration.
+ * dwarf_line.c: Move IRIX specific function out of this file.
+ * dwarf_line2.c: Move IRIX specific function to this new file.
+ * dwarf_line.h: Add interface declaration.
+ * dwarf_frame2.c: Altered comments so indent handles them better,
+ ran indent.
+
+2006-03-07 David Anderson <davea@sgi.com>
+ * dwarf_die_deliv.c (dwarf_siblingof): -1 to point to end of cu,
+ not one-past-end. With thanks to Richard Stuckey.
+ * libdwarf2.1.mm: document existing function dwarf_get_fde_exception_info()
+ * dwarf_frame.h: Add new internal interfaces.
+ * dwarf_frame.c: Remove cie/fde reader to dwarf_frame2.c.
+ * dwarf_frame2.c: Contains heavily refactored cie/fde reader,
+ preparing for eh_frame support and avoids some searching
+ in fde creation. Removes duplicated code into new
+ internal functions.
+ * Makefile.in: Adding comment about flag for malloc_checking
+ code. Add dwarf_frame2.c to source list.
+ * libdwarf.h: added declarations for eh_frame information, though
+ these are not yet supported.
+ * dwarf.h: Added defines for eh_frame information, though these
+ are not yet used.
+2006-02-23 David Anderson <davea@sgi.com>
+ * dwarf_line.h dwarf_line.c: added dwarf_line_srcfileno()
+ to complement dwarf_lineno.
+ * libdwarf2.1.mm: document dwarf_line_srcfileno().
+
+2005-11-25 David Anderson <davea@sgi.com>
+ * dwarf.h: Now matches 2005 DWARF3 public review document.
+
+2005-11-08 David Anderson <davea@sgi.com>
+ * dwarf_alloc.c, dwarf_init_finish.c, dwarf_sort_line.c, malloc_check.c:
+ remove malloc.h include, it is not needed, stdlib.h suffices.
+
+2005-10-24 David Anderson <davea@sgi.com>
+ * dwarf.h: Updated to match DWARF3 public review document.
+
+2005-10-03 David Anderson <davea@sgi.com>
+ * dwarf_alloc.c: Change some entries to BASE_ALLOC.
+ * dwarf_global.h: Add argument to interface so we do not
+ universally use DW_DLA_GLOBAL, but cater to compatibility.
+ * dwarf_funcs.c, dwarf_global.c, dwarf_weaks.c,
+ dwarf_funcs.c, dwarf_types.c: Restored use of DW_DLA_*
+ instead of universally using DW_DLA_GLOBAL.
+ * dwarf_pubtypes.c: added comments about DW_DLA_GLOBAL use.
+2005-08-01 David Anderson <davea@sgi.com>
+ * malloc_check.c: Moved the #ifdef WANT_LIBBDWARF_MALLOC_CHECK
+ down after #includes so the test is meaningful.
+2005-07-15 David Anderson <davea@sgi.com>
+ * libdwarf.h: New DW_DLA codes and full .debug_types support added.
+ new dealloc functions declared.
+ * Makefile.in: Add dwarf_pubtypes.o (.debug_pubtypes support).
+ * dwarf_abbrev.c: Add dealloc() calls where needed.
+ * dwarf_alloc.c: Add dwarf_malloc_check calls, rename and
+ update _DW_RESERVE to DW_RESERVE, make hash table declaration
+ in array more readable. Add optional final dealloc loop.
+ * dwarf_alloc.h: Increase the index array to add .debug_pubtypes
+ support.
+ * dwarf_base_types.h: Increase the index array to add .debug_pubtypes
+ support.
+ * dwarf_die_deliv.c: Add dealloc calls to get full dealloc.
+ * dwarf_error.c: Document new error codes for .debug_pubtypes.
+ * dwarf_init_finish.c: Add .debug_pubtypes support, add
+ dwarf_malloc_check_complete() call for alloc checking.
+ * dwarf_form.c: Document dwarf_formstring() use.
+ * dwarf_frame.c: Add dwarf_fde_cie_list_dealloc() for
+ complete dealloc.
+ * dwarf_global.h: Add _dwarf_internal_globals_dealloc
+ declaration for libdwarf-internal use.
+ * dwarf_global.c dwarf_funcs.c dwarf_types.c dwarf_vars.c
+ dwarf_weaks.c: Add new dealloc public routines for
+ complete dealloc and add .debug_pubtypes support.
+ * dwarf_pubtypes.c: Support for .debug_pubtypes.
+ * dwarf_malloc_check.h dwarf_malloc_check.c : New checking
+ for complete accurate dealloc (off by default).
+ * dwarf_opaque.h: Add internal .debug_pubtypes support.
+ * libdwarf2.1.mm: Document new dealloc code, correct
+ dwarf_formstring documentation.
+
+2005-07-14 David Anderson <davea@sgi.com>
+ * dwarf_line.c: Added dwarf_srclines_dealloc and call it
+ for dwarf_srclines output. Does complete deallocation,
+ unlike previous method, which was incomplete deallocation.
+ Thanks to Alan Alexander for pointing out there was
+ incomplete deallocation.
+ * dwarf_print_lines.c: remove references and allocation
+ of line_context. Memory was leaking due to unreferenced
+ variable.
+ * libdwarf2.1.mm: Document new dwarf_srclines_dealloc()
+ deallocation routine for dwarf_srclines().
+
+2005-07-13 David Anderson <davea@sgi.com>
+ * dwarf_init_finish.c (dwarf_init): if _dwarf_setup() fails,
+ free elf resources with elf_end() call.
+ Thanks to Cristi Vlasceanu for pointing out that a memory
+ leak existed here.
+
+2005-06-13 David Anderson <davea@sgi.com>
+ * dwarf_frame.c (_dwarf_exec_frame_instr): Corrected test
+ so that .o files (pre-relocation) are less likely to generate
+ DW_DLE_DF_NEW_LOC_LESS_OLD_LOC error. Renamed local variable
+ for better readability.
+2005-04-13 David Anderson <davea@sgi.com>
+ * dwarf_error.c: Error codes 194 and 195 were missing
+ strings, added them to table.
+ * dwarf_frame.c: Check for newer gcc .eh_frame
+ augmentation strings and avoid trying to handle these
+ for now.
+ * dwarf_global.c: Add an error check for
+ pubnames-style sections for bad offset.
+ * dwarf_init_finish.c: Add dwarf_get_section_max_offsets()
+ to allow clients to do additional error checking.
+ This code will have to change again, so leaving it
+ undocumented. As written it's not useful for COMDAT
+ style DWARF sections.
+ * libdwarf.h: Added prototype for dwarf_get_section_max_offsets().
+
+2005-03-31 David Anderson <davea@sgi.com>
+ * mips_extensions.mm: Documented the libexc/.debug_funcnames
+ dependency and the 64bit-offset DWARF extension.
+ * mips_extensions.ps: Regenerated.
+
+2005-03-21 David Anderson <davea@sgi.com>
+ * dwarf_line.c: Added commentary.
+ * libdwarf2.1.mm: Documented dwarf_lineendsequence() better.
+ * libdwarf2.1.ps: Regenerated.
+ * libdwarf.h: Added DW_DLE_FRAME_AUGMENTATION_UNKNOWN as
+ error code 195.
+ * dwarf_init_finish.c: Corrected comment spelling.
+ * dwarf_frame.h dwarf_frame.c: Added handling for
+ much (but not all) of gcc 3.3 gcc 3.4 .eh_frame
+ 'z' augmentation. Gives error on attempting
+ to get z augmentation data since such is not
+ completely handled.
+
+2005-03-18 David Anderson <davea@sgi.com>
+ * dwarf_frame.h dwarf_frame.c: The gcc .eh_frame
+ info did not print correctly so we now access the
+ correct section data so it prints. Still no support
+ for dwarf3 frame operators.
+ * dwarf_macro.c: Detect end-of-macros properly
+ (stopped too soon before).
+
+2005-02-14 David Anderson <davea@sgi.com>
+ * pro_incl.h: Added #elif defined(HAVE_LIBELF_H)
+ enabling build on a platform missing normal elf.h.
+
+2005-02-11 David Anderson <davea@sgi.com>
+ * dwarf_base_types.h: Added DW_CIE_VERSION3 define.
+ * dwarf_die_deliv.c: Allowed CURRENT_VERSION_STAMP3.
+ * dwarf_frame.c: Allowed DW_CIE_VERSION3.
+ * dwarf_frame.h: Define DW_DEBUG_FRAME_VERSION3.
+ * dwarf_line.c: Allow CURRENT_VERSION_STAMP3.
+ * dwarf_line.h: Add lc_version_number to line structure.
+ * dwarf_opaque.h: Add CURRENT_VERSION_STAMP3 and comment showing
+ version numbers (DWARF3 vs DWARF2) by DWARF section.
+
+2004-11-21 David Anderson <davea@sgi.com>
+ * configure.in libdwarfdefs.h: Now tests more precisely for __uint32_t
+ and __uint64_t (previous test was not sufficient for debian/mips).
+ Regenerated configure config.h.in.
+
+2004-10-28 David Anderson <davea@sgi.com>
+ * LIBDWARFCOPYRIGHT Makefile.in NEWS config.h dwarf_abbrev.c
+ dwarf_abbrev.h dwarf_addr_finder.c dwarf_alloc.c dwarf_alloc.h
+ dwarf_arange.c dwarf_arange.h dwarf_base_types.h dwarf_die_deliv.c
+ dwarf_die_deliv.h dwarf_error.c dwarf_error.h dwarf_form.c
+ dwarf_frame.c dwarf_frame.h dwarf_funcs.c dwarf_funcs.h
+ dwarf_global.c dwarf_global.h dwarf_incl.h dwarf_init_finish.c
+ dwarf_leb.c dwarf_line.c dwarf_line.h dwarf_loc.c dwarf_loc.h
+ dwarf_macro.c dwarf_macro.h dwarf_opaque.h dwarf_print_lines.c
+ dwarf_query.c dwarf_sort_line.c dwarf_string.c dwarf_stubs.c
+ dwarf_types.c dwarf_types.h dwarf_util.c dwarf_util.h
+ dwarf_vars.c dwarf_vars.h dwarf_weaks.c dwarf_weaks.h
+ libdwarfdefs.h pro_alloc.c pro_alloc.h pro_arange.c pro_arange.h
+ pro_die.c pro_die.h pro_encode_nm.c pro_encode_nm.h pro_error.c
+ pro_error.h pro_expr.c pro_expr.h pro_finish.c pro_forms.c
+ pro_frame.c pro_frame.h pro_funcs.c pro_funcs.h pro_incl.h
+ pro_init.c pro_line.c pro_line.h pro_macinfo.c pro_macinfo.h
+ pro_opaque.h pro_pubnames.c pro_pubnames.h pro_reloc.c
+ pro_reloc.h pro_reloc_stream.c pro_reloc_stream.h pro_reloc_symbolic.c
+ pro_reloc_symbolic.h pro_section.c pro_section.h pro_types.c
+ pro_types.h pro_util.c pro_util.h pro_vars.c pro_vars.h
+ pro_weaks.c pro_weaks.h: Copyright update with
+ 2004 and new SGI official address.
+
+2004-10-26 David Anderson <davea@sgi.com>
+ * acconfig.h: removed. Was old style autoconf usage.
+ * configure.in: Updated AC_DEFINE usage, adding args 2 & 3.
+ * config.guess: Updated. timestamp='2004-06-11'.
+ * config.sub: Updated. timestamp='2004-03-12'.
+ * configure config.h.in: regenerated with autoconf 2.58.
+
+2004-06-09 David Anderson <davea@sgi.com>
+ * dwarf_frame.c (_dwarf_exec_frame_instr):
+ Was not setting ru_offset to 1 in DW_CFA_def_cfa_offset
+ case, now it does.
+
+2004-02-24 David Anderson <davea@sgi.com>
+ * dwarf_frame.c (_dwarf_exec_frame_instr):
+ DW_CFA_def_cfa_register case, was setting offset, which
+ is incorrect. Thanks to Tom Hughes <thh@cyberscience.com>
+ for pointing this out.
+
+2004-02-03 David Anderson <davea@sgi.com>
+ * dwarf_util.h: DECODE_LEB128_UWORD DECODE_LEB128_SWORD
+ were simply wrong if Dwarf_Word or
+ Dwarf_Sword longer than 4 bytes. Upper bits left random.
+ Large values not extracted correctly.
+
+2004-01-15 David Anderson <davea@sgi.com>
+ * dwarf_alloc.c pro_alloc.c pro_init.c: changing BSD-ish bzero()
+ to posix-standard memset() calls.
+ * configure.in: remove bstring.h test, add alloca.h test.
+ No longer useing bzero, some environments have alloca
+ in malloc.h, no alloca.h. If neither exist
+ it's up to you to deal with it.
+ * dwarf_line.c dwarf_print_lines.c dwarf_sort_line.c: Test
+ HAVE_ALLOCA_H
+ * configure config.h.in: regenerated
+
+2003-12-31 David Anderson <davea@sgi.com>
+ * dwarf_init_finish.c: added #error to detect and describe
+ absence of libelf.h.
+ * README: Added mention of libelf.h requirement, minor
+ cleanout of obsolete comments, added configure example.
+ * Makefile.in: Removed bogus LIBS line, updated copyright date.
+ * acconfig.h: Updated copyright date.
+ * config.guess config.sub: new versions from automake-1.6.
+ * config.h.in configure: Regenerated.
+
+2003-12-15 David Anderson <davea@sgi.com>
+ * dwarf_init_finish.c (_dwarf_setup): test for (section_size)
+ was wrong for eh_frame section. Changed this one to
+ (section_size == 0) so it is like all the others testing
+ section_size. Thanks to David Mosberger
+ for pointing out this inconsistency.
+
+2003-12-08 David Anderson <davea@sgi.com>
+ * dwarf_line.h: reference in comment to li_dbg meant to
+ refer to li_offset. Corrected and amplified comment.
+
+2003-10-06 David Anderson <davea@sgi.com>
+ * dwarf_abbrev.c dwarf_die_deliv.c dwarf_form.c dwarf_loc.c
+ dwarf_util.c: applied indent(1).
+
+2003-10-02 David Anderson <davea@sgi.com>
+ * dwarf_loc.c: Implemented dwarf_get_loclist_entry(),
+ implemented new dwarf_loclist_n() fully implementing
+ loclist support.
+ * dwarf_stubs.c: removed dwarf_get_loclist_entry stub.
+ * libdwarf2.1.mm: Documented dwarf_loclist_n() and
+ updated documentation on dwarf_loclist().
+
+2003-09-29 David Anderson <davea@sgi.com>
+ * dwarf_abbrev.c: Ensure the .debug_abbrev section is loaded.
+ * dwarf_arange.c dwarf_global.c: Recent dwarf committee
+ discussions have revealed we were wrong in not allowing
+ padding in aranges.
+ * dwarf_die_deliv.c dwarf_query.c: handle DW_FORM_indirect.
+ * dwarf_form.c: Add dwarf_whatform_direct() so folks
+ can report on DW_FORM_indirect use.
+ Fill in new Dwarf_Locdesc fields.
+ * dwarf_loc.c: Handle .debug_loc partially.
+ Fill in new Dwarf_Locdesc fields.
+ Load .debug_loc if not present and if it's needed.
+ * dwarf_opaque.h: Added ar_attribute_form_direct field
+ so we can report DW_FORM_indirect
+ in libdwarf-using code (where such wants to).
+ * dwarf_util.c: Don't confuse DW_FORM_indirect uleb length
+ with other lengths.
+ * libdwarf2.1.mm: Document new function dwarf_whatform_direct()
+ Not needed by ordinary clients, just for clients
+ wanting to print certain debug info.
+
+2003-04-15 Brian Ford <ford@vss.fsi.com>
+ * configure.in (AC_C_BIGENDIAN): Move after AC_PROG_CC so a proper
+ working compiler is used for the test.
+
+2003-01-21 David Anderson <davea@sgi.com>
+ * dwarf_die_deliv.c (dwarf_next_cu_header, dwarf_offdie):
+ Add calls to dwarf_load_object() to load .debug_info,
+ .debug_abbrev
+ * dwarf_init_finish.c (_dwarf_setup): Remove calls to
+ dwarf_load_object for .debug_info, .debug_abbrev sections.
+ * dwarf_opaque.h: Add new fields to Dwarf_Debug so
+ we don't need to pre-load .debug_info, .debug_abbrev
+ * dwarf_util.h: Fix READ_AREA_LENGTH macro so it uses
+ only length itself to determine which format the
+ length is.
+
+2003-01-14 David Anderson <davea@sgi.com>
+ * dwarf_loc.c: Made comment at head of dwarf_loclist()
+ a bit clearer.
+
+2002-11-22 Tom Hughes <thh@cyberscience.com>
+ * dwarf_macro.c: Corrected bugs in macro-info functions.
+
+2002-10-29 David Anderson <davea@sgi.com>
+ * dwarf_init_finish.c: The libelf_sgi mods
+ left a HAVE_ELF64_GETSHDR ifdef in the wrong place
+ so folks without Elf64 could not build. Fixed.
+
+2002-10-21 David Anderson <davea@sgi.com>
+ * dwarf_form.c: the form_ref functions were failing to
+ add in cc_extension_size when checking for offset
+ legality. Thanks to Kelly O'Hair <kelly.ohair@sun.com>
+ for pointing out the 4 places this was wrong.
+ Used cu_context local pointer to avoid numerous
+ double indirections.
+
+2002-08-14 David Anderson <davea@sgi.com>
+ * dwarf_string.c (dwarf_get_str): Return
+ DW_DLV_NO_ENTRY when offset is just at the end of the
+ sections, making it possible to use dwarf_get_str
+ to print the section independently.
+ * libdwarf2.1.mm, libdwarf2.1.ps: Document the
+ revised dwarf_get_str interface (which was not
+ fully thought thru before).
+ * dwarf_line.c (dwarf_srcfiles): Avoid core dump
+ when DW_AT_comp_dir absent (it's not required).
+
+
+2002-07-31 David Anderson <davea@sgi.com>
+ * pro_types.c (_dwarf_transform_simplename_to_disk): correct
+ generation of .debug_info size field.
+ Thanks to Kelly O'Hair <kelly.ohair@sun.com> for pointing out
+ the bug.
+
+2002-05-23 Daniel Gohman <gohmandj@sgi.com>
+ * dwarf_init_finish.c: Add support for using SGI's
+ ELF library as an alternative to using AT&T-style
+ libelf.
+ Add a new function _dwarf_load_section to handle
+ loading of sections.
+ * dwarf_opaque.h: Add entries to Dwarf_Debug_s to
+ store section indicies.
+ * most consumer files: Load sections on demand so
+ that unneeded sections don't get loaded.
+ * dwarf_init_finish.c: Fixed an incorrect check for
+ duplicate .eh_frame sections.
+
+2002-04-25 Kelly O'Hair <kelly.ohair@sun.com>
+ * pro_section.c (_dwarf_pro_generate_debuginfo): add
+ required dwarf2 sec 7.5.3 trailing null byte
+ to .debug_abbrev per compilation-unit.
+
+2002-03-31 David Anderson <davea@sgi.com>
+ * dwarf_abbref.c (dwarf_get_abbrev): change
+ DW_DLE_DEBUG_ABBREV_NULL to DW_DLE_DWARF_ABBREV_NULL.
+ Former was wrong code.
+ * libdwarf2.1.mm: correct argument reference, returned_abbrev
+ not returned_fde in dwarf_get_abbrev discussion.
+
+2002-03-07 David Anderson <davea@sgi.com>
+ * libdwarf.h: added struct Elf declaration
+ to reduce dependency on header include ordering.
+
+2002-02-11 David Anderson <davea@sgi.com>
+ * libdwarf2.1.mm libdwarf2.1.ps:
+ dwarf_offdie can return DW_DLV_NO_ENTRY and that
+ is now documented.
+ * dwarf_loc.c: if the length of a location description
+ is zero that is ok, not an error. dwarf2 sec 2.4.1.
+
+2002-01-10 David Anderson <davea@sgi.com>
+ * dwarf_opaque.h, dwarf_init_finish.c: if libdwarf does
+ the elf_begin() it must also do the elf_end() to
+ avoid a memory leak, and now does this correctly.
+
+2002-01-10 David Anderson <davea@sgi.com>
+ * dwarf_init_finish.c: Using a variable to
+ hold ELF_C_READ_MMAP. Really motivated by
+ code not added to this source.
+ * dwarf_die_deliv.c: Added comments, moved
+ a couple variables to local scope from function scope.
+
+ * dwarf.h: Added some #defines which were specified in the Dwarf
+ 2.1 Dwarf draft 5 (now called dwarf 3 draft 5).
+
+2001-09-18 David Anderson davea@sgi.com
+ * all files: applied gnu indent with
+ -bad -bap -nbbo -br -ce -brs
+ -l72 -lc72 -hnl -nprs
+ -fca -i4 -lp -psl -npcs
+ Code should use this set in libdwarf.
+
+
+2001-08-21 "kelly o'hair" <kelly.ohair@eng.sun.com>
+ * pro_section.c: If one called dwarf_add_file_decl()
+ or dwarf_add_directory_decl() but never added a line,
+ .debug_line was not produced. This was a mistake,
+ as if any file or directory was provided .debug_line
+ should be produced.
+
+2001-08-06 davea@sgi.com
+ * libdwarf2.1.mm: documented dwarf_dealloc rules
+ more clearly. (.ps updated too)
+ * mips_extensions.mm: documented the way SGI
+ gets frame stack pointer out of debug_frame.
+ (.ps updated too)
+
+2001-06-14 davea@sgi.com
+ * dwarf_leb.c: changed around where bytes counted in
+ _dwarf_decode_s_leb128 so it's easier to tell it is correct.
+ And removed one loop completely: it was
+ an early attempt at performance improvement and
+ is no longer relevant.
+
+ * dwarf_global.c: added new
+ dwarf_get_cu_die_offset_given_cu_header_offset function
+ to get CU die offset (as the long name says).
+ A variety of functions return cu-header-offsets, so
+ this is useful at times.
+ Used locals to reduce the number of indirections
+ and make things easier to follow.
+
+ * dwarf_arange.c: added new dwarf_get_arange_cu_header_offset
+ function so dwarfdump could print the cu header offset
+ (which appears in the arange headers).
+
+ * libdwarf2.1.mm: documented the above new functions.
+
+2001-06-07 davea@sgi.com
+ * dwarf_leb.c: shift operator was not being applied
+ to full size of Dwarf_Signed/Unsigned for 64bit
+ Dwarf_Signed/Unsigned (ILP32 compile) so
+ large numbers not decoded if signed.
+ * pro_encode_nm.c: added {} in a couple if/else
+ for 'clarity' and to make inserting debug printf easier.
+ * pro_expr.c: Added comments explaining why possible
+ compiler (gcc) warnings are ok, the result is safe.
+
+2001-05-30 davea@sgi.com
+ * pro_reloc_stream.c: Wrote Set_REL32_info and
+ Set_REL64_info macros
+ from generic ELF abi documents to make use acceptable
+ when IRIX elfaccess.h is not available.
+
+2001-05-30 "kelly o'hair" <kelly.ohair@eng.sun.com>
+ * Makefile.in: was missing pro_macinfo.o
+ pro_encode_nm.o dwarf_macro.o from the OBJS list.
+
+2001-05-22 davea@sgi.com
+ * dwarf_frame.c, pro_expr.c: Added comments on why
+ casts are safe in spite of gcc warnings (4 places total).
+
+2001-05-18 Dan Gritter <dgritter@us.ibm.com>
+ * dwarf_loc.c DW_OP_bregx operands are unsigned
+ reg num followed by signed offset.
+
+2001-04-11 David Anderson <davea@sgi.com>
+ * dwarf_die_deliv.c: check for 0 abbreviation code
+ and return a 'no entry' return value when found.
+ (normal dwarf2, 0 means no DIE, the end of some set of DIEs.)
+
+2001-01-16 David Anderson <davea@sgi.com>
+
+ * pro_die.c: set ar_reloc_len field
+ in all cases.
+
+2000-12-14 David Anderson <davea@sgi.com>
+
+ * dwarf_frame.h: clarified some comments.
+
+2000-12-14 Ulrich Drepper <drepper@cygnus.com>
+
+ * dwarf_line.c: Now sets DW_LNE_end_sequence to
+ default_is_stmt, the correct value, not is_stmt.
+
+
+2000 Aug 24 davea@sgi.com
+ dwarf_error.c: a dwarf_init() failure resulted in this
+ using a static Dwarf_Error struct. And dwarf_dealloc
+ did not deal properly with that.
+ dwarf_alloc.c dwarf_alloc.h: these had DYNAMIC_CHUNK protected code
+ which was never used. Deleted the unused code. Added a small
+ comment (hopefully useful) to dwarf_alloc.h.
+
+ And now deals correctly with a null dbg on
+ DW_DLA_ERROR due to failed
+ dwarf_init() call (or due to other error in calling
+ libdwarf that results in libdwarf not knowing the dbg,
+ a likely far more common case) and frees the memory.
+ This used to result in chaos (depending on your
+ luck...).
+
+2000 Aug 23 davea@sgi.com
+ libdwarf2.1.mm, ps. Failed to mention that dwarf_finish()
+ has to be accompanied by elf_end() if dwarf_init() was used
+ to initialize libdwarf to truly release all stuff.
+ Added text to dwarf_finish() describing how to do that.
+2000 April 14 davea@sgi.com
+
+ dwarf_abbrev.c - 1.22
+ - When it is a null abbrev entry, return it correctly so it can be
+ printed (meaning fill out all the return-parameters so the caller can
+ do the right thing).
+
+ dwarf_init_finish.c - 1.48
+ - For most sections, simply having an empty section (present but empty)
+ is just fine. There is no reason to register an error in such a case.
+
+ Copyright has changed. See LIBDWARFCOPYRIGHT and NEWS
+
+ dwarfdump/print_die.c - 1.42
+ - Explain what combo checker is doing and make it more maintainable (and fix bug which would not be hit, but was real enough).
+
+ dwarfdump/tag_tree.list - 1.2
+ - Add valid parent/child relationships so checker does not report valid
+ entries as bogus.
+
+ dwarf_form.c - 1.26
+ - Correct dwarf reader to use appropriate size, not de_length_size. This is part of the handling of the new dwarf2 64bit facilities. I
+ overlooked this small aspect before in one place
+ dwarf_query.c - 1.48
+ - Use correct size, not de_length_size. For offset size.
+ libdwarf2.1.mm - 1.41
+ - Tried to make frame register output args meaning clearer
+ libdwarf2.1.ps - 1.19
+ - Tried to make frame register output args meaning clearer
+ pro_forms.c - 1.33
+ - Get ref4, not ref8 when generating 32bit dwarf per original dwarf2
+ spec. even if pointer size is 64 bits.
+ pro_init.c - 1.18
+ - Get ref4, not ref8 when generating 32bit dwarf per original dwarf2
+ spec. even if pointer size is 64 bits.
+
+
+davea@sgi.com
+
+
+2000 March 7
+dwarf_line.c - 1.48
+dwarf_line.h - 1.16
+dwarf_print_lines.c - 1.10
+dwarf_sort_line.c - 1.8
+ - Now handles opcode_base of line section to be other than that at
+ compile time of libdwarf.
+Important as the dwarf2 committee is adding a new standard opcode
+davea@sgi.com
+
+2000 Feb 24
+pro_forms.c 1.31 ar_next field not always zeroed before.
+Could lead to infinite loop in the producer code.
+Now the field is always zeroed.
+
+Makefile.in - 1.3 Jason Merrill <jason@cygnus.com>
+ provided fix so gcc will work on libdwarf
+print_sections.c - 1.54 - casts to avoid warnings
+
+davea@sgi.com
+
+
+1999 Dec 14
+acconfig.h - 1.3
+config.h.in - 1.5
+configure - 1.4
+configure.in - 1.5
+ - HAVE_DWARF2_99_EXTENSION HAVE_OLD_DWARF2_32BIT_OFFSET
+ refinements added.
+CHANGES - 1.3
+Makefile.base - 1.98
+NEWS - 1.5
+config.h - 1.4
+config.h.in - 1.4
+configure.in - 1.4
+dwarf_alloc.c - 1.36
+dwarf_arange.c - 1.19
+dwarf_arange.h - 1.6
+dwarf_die_deliv.c - 1.51
+dwarf_frame.c - 1.62
+dwarf_frame.h - 1.23
+dwarf_funcs.c - 1.10
+dwarf_funcs.h - 1.3
+dwarf_global.c - 1.21
+dwarf_global.h - 1.7
+dwarf_init_finish.c - 1.45
+dwarf_line.c - 1.44
+dwarf_opaque.h - 1.52
+dwarf_print_lines.c - 1.8
+dwarf_query.c - 1.45
+dwarf_types.c - 1.10
+dwarf_types.h - 1.3
+dwarf_util.c - 1.40
+dwarf_util.h - 1.22
+dwarf_vars.c - 1.11
+dwarf_vars.h - 1.3
+dwarf_weaks.c - 1.10
+dwarf_weaks.h - 1.3
+libdwarf2.1.mm - 1.40
+libdwarf2.1.ps - 1.18
+pro_arange.c - 1.15
+pro_die.c - 1.23
+pro_frame.c - 1.29
+pro_init.c - 1.15
+pro_macinfo.c - 1.7
+pro_opaque.h - 1.14
+pro_pubnames.c - 1.18
+pro_reloc_stream.c - 1.5
+pro_section.c - 1.70
+pro_section.h - 1.16
+pro_types.c - 1.12
+ - Allowing generation of correct dwarf2 with the 1999 64bit dwarf
+ extension, and reading all forms of dwarf2 compatibly (all 32/64bit
+ dwarf2 section forms).
+
+This adds the ability to consume and produce both sgi 64bit
+and the new dwarf2 committee-approved 64bit dwarf extension.
+As a result of the new dwarf2 stuff , a producer (compiler)
+can mix 32 and 64bit dwarf (for a 64bit object) and the
+linker will work seamlessly. (as long as section sizes don't
+get over 2GBytes).
+
+And the producer is easily configured to produce mips/sgi style
+64bit dwarf or the new form of 64bit dwarf.
+
+This also eliminates a fair amount of rather silly duplicated code.
+davea@sgi.com
+
+
+1999 Nov 4
+
+pro_section.c - 1.69
+ - A pointer size entity had an offset-size value used at one place.
+davea@sgi.com
+
+1999 Sep 30
+dwarf_arange.c - 1.18
+ - Changed // comment to /* */. // failed to compile
+ with C89 compiler...
+davea@sgi.com
+
+
+1999 Sep 29
+Changed all the producer code
+substantially to allow generating assembler code
+for the dwarf2 (rather similar to what gcc does)
+allowing symbolic relocations.
+MIPS output still generates the binary form.
+davea@sgi.com
+
+
+
+1999 Aug 20
+Stan Shebs (shebs@cygnus.com) pointed out that the pro_util.h
+use of R_MIPS* was a problem compiling on Sun.
+Since the producer code is not really used at present except for
+MIPS/sgi, I've added #ifndefs to pro_util.h which provide zero values
+when <elf.h> does not provide the macros.
+When anyone needs the producer code to actually *work* for non-MIPS
+something better will have to be done.
+
+This has no effect on those simply compiling libdwarf for
+use by dwarfdump.
+davea@sgi.com
+
+1999 July 21
+Changed the READ_UNALAGNED macro to call a function
+depending on endianness of the host and the object being read.
+So all the dwarf_* source changed in a trivial way.
+Added support for printing egcs eh_frame section.
+Added a local memcpy-like function to do the cross-endian
+thing where applicable (called by READ_UNALIGNED macro).
+Because the .eh_frame section
+after linking can have some zeroed out bytes at the
+end of the CIE/FDE data the code looking for CIEs and FDEs
+now assumes a zero CIE/FDE length means it has reached
+the end of the CIE/FDE data.
+davea@sgi.com
+
+
+1999 June 14
+ Fred Fish fnf@ninemoons.com contributed
+ autoconf'ing of the libdwarf and dwarfdump source.
+
+
+ mips_extensions.* Documented additional old errors
+ in the Dwarf Version 2 spec.
+
+ The ChangeLog before this is incomplete.
+
+-------------------------------------------------------------
+Since Oct 95 and before May, 1996 davea@sgi.com David Anderson
+
+Added the function dwarf_get_cie_of_fde() which makes it possible
+to remember a single fde/cie set out of a block usefully.
+
+Enhanced doc of dwarf_bitoffset()
+
+Added new function dwarf_global_formref() so all reference
+forms can be retrieved.
+
+Fixed bug in retrieving array bounds: was failing to sign extend
+formsdata.
+
+Added function dwarf_get_fde_info_for_all_regs(), which makes
+retrieval of the complete set of registers (as needed by
+debuggers and exception handlers) effectively N times faster
+than getting them one a time where N is the number of registers.
+
+Added support for exception table handling (really just support
+for a reference to an exception table for c++ exceptions).
+
+Fixed a bug where useless extra space (several megabytes)
+were malloc'ed for the abbreviations table by the libdwarf
+consumer code.
+
+-------------------------------------------------------------
+June 10, 1999
+ Changelog started.
+-------------------------------------------------------------
diff --git a/libdwarf/ChangeLog2007 b/libdwarf/ChangeLog2007
new file mode 100644
index 0000000..6de48a5
--- /dev/null
+++ b/libdwarf/ChangeLog2007
@@ -0,0 +1,217 @@
+2007-12-09 DavidAnderson <davea42@earthlink.net>
+ * dwarf_sort_line.c dwarf_print_lines.c darf_frame.c: Forgot
+ to commit yesterday.
+ Today's commit includes renaming _dwarf_fde_section_offset
+ _dwarf_cie_section_offset, _dwarf_print_lines, _dwarf_ld_sort_lines
+ to dwarf_* name while retaining support for the now obsolete
+ _dwarf_* form.
+2007-12-08 DavidAnderson <davea42@earthlink.net>
+ * config.h.in, configure.in: Latest linux libelf.h requires
+ _GNU_SOURCE to get off64_t defined so dwarfdump compiles.
+ Only define _GNU_SOURCE if libelf.h defines off64_t.
+ Regenerated configure.
+ * config.guess, config.sub: Updated to 2.61
+ * acconfig.h: Deleted, removing autoconf complaint.
+2007-11-14 David Anderson <davea42@earthlink.net>
+ * dwarf_frame2.c (gnu_aug_encodings): Now allows 'S' augmentation
+ character in eh_frame.
+2007-10-16 David Anderson <davea42@earthlink.net>
+ * dwarf_alloc.c: Reformat a comment.
+ * dwarf_die_deliv.c (dwarf_siblingof): When there is no trailing
+ null-DIE in the section, ensure we don't test the contents
+ of a byte past section end.
+ * dwarf_frame.c: Changed spelling of a local variable
+ so it is easier to grep for and to read.
+ * dwarf_macro.c (free_macro_stack): Was free()ing memory that
+ _dwarf_get_alloc() had supplied, which could lead to core dump.
+ Fixed potential memory leaks (said leaks only possible with an
+ error in the macro data, not with valid macro section
+ data).
+2007-10-15 David Anderson <davea42@earthlink.net>
+ * dwarf_alloc.c: The code supporting the special build
+ flag DWARF_SIMPLE_MALLOC
+ was broken and could coredump libdwarf
+ (which did not affect normal use of libdwarf).
+ * dwarf_opaque.h: Remove the field de_simple_malloc_current
+ as it is no longer used.
+
+2007-09-04 David Anderson <davea42@earthlink.net>
+ * pro_forms.c: Add commentary relating to the
+ recent DWARF4 DW_AT_high_pc change.
+ Correct FSF address.
+ * libdwarf2p.1.mm: Document dwarf_add_AT_dataref()
+ and dwarf_add_AT_ref_address().
+ * libdwarf2p.1.pdf: Regenerate.
+ * dwarf.h: Update FSF address.
+ * dwarf_opaque.h: Add DWARF4 entry (version stamp).
+ Update FSF address.
+ * dwarf_die_deliv.c: Add check for .debug_info version 4
+ (version stamp). Update FSF address.
+ * libdwarf.h pro_macinfo.h pro_line.h dwarf_incl.h
+ pro_alloc.h pro_section.h libdwarfdefs.h pro_util.h
+ dwarf_vars.h dwarf_funcs.h pro_error.h dwarf_alloc.h pro_arange.h
+ dwarf_arange.h pro_die.h dwarf_global.h pro_expr.h
+ pro_reloc_stream.h pro_incl.h pro_encode_nm.h
+ dwarf_line.h pro_frame.h pro_opaque.h dwarf_error.h
+ dwarf_base_types.h dwarf_abbrev.h pro_types.h pro_reloc_symbolic.h
+ dwarf_weaks.h dwarf_util.h dwarf_loc.h malloc_check.h
+ dwarf_die_deliv.h acconfig.h dwarf_frame.h dwarf_macro.h
+ pro_reloc.h dwarf_types.h
+ pro_funcs.c Makefile.in pro_forms.c pro_line.c
+ dwarf_print_lines.c pro_alloc.c pro_init.c dwarf_addr_finder.c
+ pro_section.c dwarf_form.c dwarf_query.c dwarf_vars.c
+ dwarf_pubtypes.c dwarf_frame3.c dwarf_funcs.c pro_error.c
+ pro_arange.c dwarf_alloc.c dwarf_arange.c pro_die.c
+ dwarf_sort_line.c dwarf_global.c dwarf_init_finish.c pro_weaks.c
+ pro_pubnames.c pro_expr.c pro_reloc_stream.c pro_finish.c
+ pro_encode_nm.c dwarf_line.c pro_frame.c dwarf_error.c
+ dwarf_abbrev.c pro_types.c dwarf_leb.c pro_reloc_symbolic.c
+ dwarf_string.c pro_vars.c dwarf_line2.c dwarf_weaks.c
+ dwarf_frame2.c dwarf_util.c dwarf_loc.c LIBDWARFCOPYRIGHT
+ malloc_check.c dwarf_die_deliv.c dwarf_frame.c dwarf_stubs.c
+ dwarf_macro.c pro_reloc.c dwarf_types.c pro_macinfo.c:
+ Update FSF address.
+2007-07-26 David Anderson <davea42@earthlink.net>
+ * pro_frame.c: Added commentary about some missing DWARF3 support.
+ * dwarf_srclines_dealloc.c: File unused, now deleted.
+2007-07-04 David Anderson <davea42@earthlink.net>
+ * libdwarf.h: dwarf_get_loclist_entry() is implemented,
+ removed the erroneous 'unimplemented' comment.
+ * libdwarf2.1.mm: Improved the dwarf_get_loclist_entry()
+ documentation.
+ * libdwarf2.1.pdf: regenerated
+ * dwarf_loclist_entry.c: Removed from distribution, the
+ source has nothing of interest.
+
+2007-07-03 David Anderson <davea42@earthlink.net>
+ * libdwarf.h: Add declaration of dwarf_loclist_from_expr();
+ * dwarf_loc.c: Implement dwarf_loclist_from_expr() and add
+ sign-extension macro calls to case DW_OP_const4s numbers.
+ Removed unused local variables.
+ * dwarf_form.c: Removed unused local variables.
+ * libdwarf2.1.mm: Document dwarf_loclist_from_expr().
+ * libdwarf2.1.pdf: Regenerated.
+2007-07-01 David Anderson <davea42@earthlink.net>
+ * dwarf_frame2.c: Add commentary.
+ * dwarf_frame.c: Add in block_len for DW_CFA_val_expression
+ so libdwarf does not get confused by this frame expression
+ operator. Thanks to Cristian Vlasceanu for providing
+ a test case.
+2007-06-29 David Anderson <davea42@earthlink.net>
+ * README: added a note that a few warnings about conversions
+ from pointer to integer are normal at libdwarf compile time.
+2007-05-25 David Anderson <davea42@earthlink.net>
+ * dwarf_frame2.c (_dwarf_get_fde_list_internal):
+ Correct cie-list-creation so it adds to the tail of the list.
+ gcc 4.1.2 generates cie-use in an order the code did
+ not properly handle.
+2007-05-08 David Anderson <davea42@earthlink.net>
+ * Makefile.in: Now generates pdf files.
+ * mips_extensions.mm: The only changes were to eliminate
+ unsupported macro (.PM) and to try to get correct output
+ from groff. No technical content change intended.
+ The pdf/postscript output remains a little odd though.
+ * libdwarf2.1.mm: Remove troff comment line.
+2007-04-18 Chris Quenelle <chris.quenelle@sun.com>
+ * dwarf_addr_finder.c: repaired comment
+ * dwarf_form.c: add support for DW_AT_SUN_func_offsets
+ * pro_alloc.c: add memory block tracking to find and fix
+ lingering allocations. This is more important for very large
+ and intensive compiles.
+ * pro_die.c: Implement "markers" which are a generic way to
+ do things like relocations. You can set a marker on any
+ die, and when dwarf is produced in binary form, you get back
+ a list of your markers with the offset of each one in the binary
+ output. This is used by the Sun compilers to implement die
+ references that span compile unit blocks. (I may remove this,
+ it might be unused code related to partial_units and comdat
+ support)
+ * pro_die.c: Also check for loops in the die relationships so
+ that if you add a child twice, or other errors, you won't get
+ an infinite loop or a crash. Also start passing a DBG structure
+ to all allocation calls to help with memory block tracking.
+ * pro_expr.c: Add a public function to "reset" an expr. This
+ allows the same expr object to be reused over and over to save
+ memory if you're creating many many expressions for a location list.
+ * pro_finish.c: Free any left over blocks when the user calls
+ dwarf_producer_finish.
+ * pro_forms.c: More support for compressed integer blocks. Modify
+ error diagnostics so that user-defined attributes can be any type.
+ Add support for dwarf_add_AT_ref_address which is just like
+ dwarf_add_AT_address, only it produces a DW_FORM_ref_addr instead
+ of DW_FORM_addr. This is needed for cross-CU die pointers.
+ * pro_incl.h: add macros to control the spelling of relocation types.
+ * pro_init.c: use new macros to control reloc types
+ * pro_line.h: correct minimum instruction length on x86
+ * pro_opaque.h: add support for markers (see above) and also ability
+ have libdwarf tell the caller where the string constants are so
+ that they can be recorded as strings in case the binary output of libdwarf
+ needs to be converted back into assembly. That's what
+ Dwarf_P_Per_Sect_String_Attrs is about.
+ Remove de_mem_list as it is never used.
+ * pro_reloc_stream.c: repair prototype and comment for
+ _dwarf_pro_reloc_name_stream64, and use relocation type macros.
+ * pro_section.c: support for markers (see above) and for tracking
+ inline string attributes. Add code to sort the attributes so that
+ abbreviation table entries will be reduced. Change treatment of
+ DW_FORM_ref_addr to be more correct. Some support for packing
+ in the middle of sections, this will probably be removed.
+ Also pass DBg structure to more allocations.
+ * pro_util.h: relocation type values can't be zero.
+2007-04-10 David Anderson <davea42@earthlink.net
+ * dwarf_print_lines.c pro_section.c dwarf_query.c
+ dwarf_alloc.c dwarf_arange.c dwarf_sort_line.c
+ dwarf_global.c dwarf_line.c dwarf_abbrev.c
+ dwarf_frame2.c dwarf_util.c dwarf_loc.c dwarf_util.h
+ dwarf_die_deliv.c dwarf_frame.c dwarf_macro.c: Additions
+ to source for year 2007 now fit in with pre-existing
+ copyright wording. Effectively no change.
+ * dwarf_srclines_dealloc.c: Now has the (always-intended) SGI
+ LGPL copyright wording.
+2007-04-09 David Anderson <davea42@earthlink.net
+ * dwarf_error.h: Add DW_DLE_LINK_LOOP error code (Sun).
+ * libdwarf.h: Add DW_DLE_LINK_LOOP error code (Sun).
+ * dwarf.h: Incorporate Sun extensions. Thanks to
+ Chris Quenelle at Sun Microsystems.
+2007-04-06 David Anderson <davea42@earthlink.net
+ * dwarf_sort_line.c (_dwarf_update_line_sec): initialize
+ Dwarf_Debug_s struct. Thanks to Chris Quenelle of Sun Microsystems.
+ Also initialize other local variables.
+2007-04-02 David Anderson <davea42@earthlink.net
+ * dwarf_form.c (dwarf_formsdata, dwarf_formudata): Use
+ Dwarf_sfixed in dwarf_formsdata, document need for casts,
+ Use Dwarf_Signed as type for READ_UNALIGNED macro use.
+ The only real correction here is for a 64bit long compiled
+ libdwarf reading 32bit dwarf_formsdata FORM_data4.
+ * dwarf_base_types.h: Now Dwarf_sfixed64 and Dwarf_ufixed64
+ are properly declared (so they are usable).
+2007-03-11 David Anderson <davea42@earthlink.net
+ * Makefile.in: use groff to produce postscript.
+ * libdwarf2.1.mm libdwarf2.1.ps libdwarf2p.1.mm
+ libdwarf2p.1.ps: Clean up the introduction and history.
+ Add a non-restrictive copyright notice.
+2007-02-23 David Anderson <davea42@earthlink.net
+ * dwarf_util.h: now the macros use do{} while(0)
+ * pro_forms.c dwarf_print_lines.c pro_section.c dwarf_query.c
+ dwarf_arange.c dwarf_sort_line.c dwarf_global.c dwarf_line.c
+ dwarf_abbrev.c dwarf_frame2.c dwarf_util.c dwarf_loc.c
+ dwarf_die_deliv.c dwarf_frame.c: Now have ;
+ after all dwarf_util.h macros. Also added local variable
+ initializations (compiler noticed).
+ * dwarf_macro.c: was missing include of <stdlib.h> for free()
+ declaration.
+ * dwarf_print_lines.c pro_section.c dwarf_query.c dwarf_alloc.c
+ dwarf_arange.c dwarf_sort_line.c dwarf_global.c dwarf_line.c
+ dwarf_abbrev.c dwarf_srclines_dealloc.c dwarf_frame2.c
+ dwarf_util.c dwarf_loc.c dwarf_die_deliv.c dwarf_frame.c
+ dwarf_macro.c: indent run with standard libdwarf options.
+
+2007-02-20 David Anderson <davea42@earthlink.net
+ * dwarf_macro.c (dwarf_get_macro_details): Now call
+ dwarf_free_macro_stack() at every return so no data
+ is leaked and there is no longer any global data
+ (restoring thread safety).
+2007-02-09 David Anderson <davea42@earthlink.net
+ * dwarf_line.c (dwarf_srclines): Added in calls
+ to dwarf_free_line_table_prefix() which were omitted
+ by accident. Thanks to Cristian Vlasceanu for noticing.
diff --git a/libdwarf/ChangeLog2008 b/libdwarf/ChangeLog2008
new file mode 100644
index 0000000..1867b40
--- /dev/null
+++ b/libdwarf/ChangeLog2008
@@ -0,0 +1,263 @@
+2008-12-29 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h: Add support for .debug_ranges with
+ dwarf_get_ranges() and dwarf_ranges_dealloc().
+ * dwarf_init_finish.c: Add support for .debug_ranges.
+ * dwarf_base_types.h: Add support for .debug_ranges functions.
+ * dwarf_alloc.c, dwarf_alloc.h: Add support for .debug_ranges
+ alloc/dealloc.
+ * dwarf_opaque.h: Add support for .debug_ranges.
+ * libdwarf2.1.mm: Documented dwarf_get_ranges() and
+ dwarf_ranges_dealloc() (rev 1.72).
+ * libdwarf2.1.pdf: Regenerated.
+2008-12-09 DavidAnderson <davea42@earthlink.net>
+ * dwarf_alloc.c: Remove useless comments and
+ tweak a few comments.
+2008-12-08 DavidAnderson <davea42@earthlink.net>
+ * dwarf_opaque.h: Add di_abbrev_code field to record
+ a DIE abbreviation value so consumers can report it.
+ * libdwarf.h: Add dwarf_die_abbrev_code() interface.
+ * dwarf_query.c: Add dwarf_die_abbrev_code() interface.
+ * dwarf_die_deliv.c: Set di_abbrev_code for consumers.
+ * libdwarf2.1.mm: Documented dwarf_die_abbrev_code().
+ * libdwarf2.1.pdf: Regenerated.
+ * pro_util.h: Removed gratuitous tabs. Used a space instead.
+2008-12-07 DavidAnderson <davea42@earthlink.net>
+ * dwarf.h: Entered DWARF4 defines known so far.
+ * dwarf_opaque.h: Updated dwarf 4 section-version comment
+ with the latest info.
+2008-12-07 DavidAnderson <davea42@earthlink.net>
+ * dwarf_original_elf_init.c: Delete unused local variables.
+ * pro_forms.c: Delete unused local variables and initialize
+ local variables at definition.
+ * dwarf_pubtypes.c, dwarf_line.c: Delete accidental
+ duplicated /* comment-start.
+ * malloc_check.c: In the 'do nothing' case, create
+ an extern declaration to eliminate a compiler warning.
+2008-11-19 DavidAnderson <davea42@earthlink.net>
+ * dwarf_die_deliv.c: Handle the case where DW_AT_sibling
+ uses DW_FORM_ref_addr.
+ * dwarf_util.c: Add a comment about DW_FORM_ref_addr.
+ * dwarf_opaque.h: Add a comment about CU fields,
+ comment out an unused CU header field.
+ * dwarf_query.c: Added dwarf_die_CU_offset_range()
+ so dwarfdump can check for additional errors.
+ * dwarf_form.c: Clarifying a comment.
+ * dwarf_print_lines.c: Add additional print detail on
+ line table headers (used by dwarfdump).
+ * libdwarf2.1.mm: Documenting the new function
+ dwarf_die_CU_offset_range().
+ * libdwarf2.1.pdf: Regenerated.
+ * libdwarf.h: Added dwarf_die_CU_offset_range() interface
+ declaration.
+2008-10-13 DavidAnderson <davea42@earthlink.net>
+ * dwarf_frame2.c: Removed last use of DW_FRAME_LAST_REG_NUM:
+ use dbg->de_frame_reg_rules_entry_count instead.
+2008-09-30 DavidAnderson <davea42@earthlink.net>
+ * dwarf_print_lines.c: Print corrected warning
+ about bogus prologue length.
+ * dwarf_line.c: Work around bogus prologue length
+ compiler bug.
+ * dwarf_line.h: Rename arguments.
+2008-09-29 DavidAnderson <davea42@earthlink.net>
+ * libdwarf2.1.mm: Documented requirement that
+ dwarf_get_fde_n() dwarf_get_fde_at_pc() pass a
+ pointer to an fde table that contains at least 1 entry.
+ * libdwarf2.1.pdf: regenerated.
+ * dwarf_opaque.h: Add new fields for cie/fde specific
+ fields for eh.
+ * dwarf_frame2.c: Initialize the new Dwarf_debug and
+ Dwarf_Fde fields.
+ * dwarf_frame.c: Access the new Dwarf_Fde fields.
+ * dwarf_frame.h: Define a new Dwarf_Fde field so we
+ keep eh and non-eh distinct.
+
+2008-09-29 DavidAnderson <davea42@earthlink.net>
+ * All .c files: Mechanically removed tab characters with
+ the expand tool.
+2008-09-29 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h: DW_DLE_LINE_SET_ADDR_ERROR no longer used.
+ The tests which generated it were bogus.
+ * dwarf_print_lines.c: Print a warning if there are any
+ apparently wasted bytes after the line prologue and before
+ the line table instructions. Match the new prologue reading
+ function prototype.
+ * dwarf_sort_line.c: Match the new prologue reading function
+ prototype.
+ * dwarf_line.c: Modify the prologue reading function so
+ it correctly finds the beginning of instructions even
+ when there are 'wasted' bytes after the prologue.
+ Drop bogus tests for minimum-instruction-size
+ matching the ABI pointer size. Removing the tests removed
+ all uses of DW_DLE_LINE_SET_ADDR_ERROR.
+ * dwarf_line.h: Modify the prototype for the prologue reading
+ function so it is possible for a caller to know about the
+ possibly wasted bytes after a prologue.
+2008-09-02 DavidAnderson <davea42@earthlink.net>
+ * dwarf_init_finish.c (_dwarf_setup): Delete unused local
+ variable 'section_error'.
+2008-08-14 DavidAnderson <davea42@earthlink.net>
+ * libdwarf2p.1.mm: Make it clearer that dwarf_get_pubnames, dwarf_get_varnames,
+ etc return a result across all compilation units (an entire section),
+ not just for a single compilation unit. Document version 1.68.
+ * libdwarf2p.1.pdf: Regenerated.
+2008-08-08 DavidAnderson <davea42@earthlink.net>
+ * libdwarf2p.1.mm: Removed some long time
+ spelling mistakes: no technical change in content.
+ Document version 1.67.
+ * libdwarf2p.1.pdf: Regenerated.
+2008-08-05 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h, dwarf_error.c: DW_DLA_PUBTYPE_CONTEXT was a mistake,
+ DW_DLE_PUBTYPE_CONTEXT was intended and is now the spelling (neither
+ is used).
+ * dwarf_pubtypes.c dwarf_vars.c dwarf_funcs.c dwarf_global.c dwarf_weaks.c:
+ tabs removed and previous strange formatting generated by a tool
+ removed (4 space indent per level now present).
+
+2008-08-05 DavidAnderson <davea42@earthlink.net>
+ * libdwarf2.1.mm: There were numerous places the apostrophe
+ was used incorrectly, thru is now spelled through,
+ and a few other small typographical errors were corrected.
+ The document revision id printed is now 1.67.
+ There is no technical change in content.
+ * libdwarf2.1.pdf: Regenerated.
+2008-06-17 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h: Add DW_DLE_STRP_OFFSET_BAD error code.
+ * dwarf_form.c: Add runtime check for strp offset.
+ * dwarf_error.c: Add DW_DLE_STRP_OFFSET_BAD error code string.
+ * dwarf_init_finish.c, dwarf_opaque.h, dwarf_elf_access.h: Remove
+ CR characters that crept in.
+2008-06-13 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h: Remove __SGI_FAST_LIBELF
+ dwarf_original_elf_init.c: Remove __SGI_FAST_LIBELF
+ and fix some indentation botches.
+ * dwarf_init_finish.c: Fix typo in variable name introduced
+ a few days ago.
+ * dwarf_elf_access.c: Remove __SGI_FAST_LIBELF
+ and fix some indentation botches.
+
+2008-05-20 DavidAnderson <davea42@earthlink.net>
+ * dwarf_init_finish.c: Expand tabs to spaces.
+2008-05-20 DavidAnderson <davea42@earthlink.net>
+ * dwarf_init_finish.c(dwarf_object_init): When there is no
+ DWARF information return DW_DLV_NO_ENTRY gracefully.
+ Thanks to Carlos Alberto Enciso for pointing out
+ the bug.
+2008-04-12 DavidAnderson <davea42@earthlink.net>
+ * pro_section.c: Initialize local variables to zero.
+ Change leading tabs to spaces.
+ * pro_reloc_stream.c: Initialize local variables to zero.
+ Change leading tabs to spaces.
+ * pro_reloc.c: Initialize local variables to zero.
+ Change leading tabs to spaces.
+2008-04-04 DavidAnderson <davea42@earthlink.net>
+ * dwarf_base_types.h: Removed unused macro definition.
+ * dwarf_util.c: Altered abbreviations hash table for a small
+ performance improvement and space saving.
+ * dwarf_util.h: Changed declaration for space saving in dwarf
+ abbreviations table.
+2008-04-04 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h: A trivial change to make a declaration look better.
+ * dwarf_abbrev.h: We record tags in more than 16 bits now just in case
+ we encounter such a thing (increased ab_tag field size), though
+ we should not find such.
+ * dwarf_abbrev.c: Adding a comment about the dwarf TAG value.
+ * dwarf_util.c: Initialize local variables at declaration for safety.
+ Removed truncation of some values: internally record more bits.
+ Rewrote handling of the abbrev table as the old one did not scale
+ to large numbers of abbreviations (things got very slow).
+ * dwarf_util.h: Now has a larger field size in the argument to
+ _dwarf_get_abbrev_for_code (not quite necessary but not harmful).
+ * dwarf_die_deliv.c: Initializing local variables at declaration and
+ removing truncation of bits from some uleb values.
+ * dwarf_die_deliv.h: Increased size of ab_code field.
+ * dwarf_opaque.h: Added a comment about abbreviations.
+ * dwarf_base_types.h: Revised to match addition of new
+ allocation table entry.
+ * dwarf_alloc.h: Document macro definitions and increase one to
+ match new table size.
+ * dwarf_alloc.c: Arrange handling of new DW_DLA_HASH_TABLE_ENTRY
+ (most of the work done in dwarf_util.c).
+2008-02-27 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h: Fixed minor typo in latest libdwarf.h that gcc did not
+ complain about. Noted by Josh Fuhs.
+2008-02-26 DavidAnderson <davea42@earthlink.net>
+ * dwarf_alloc.h: Add comment giving placement of DWARF_SIMPLE_MALLOC.
+ * pro_opaque.h: Remove de_access field, it is never used.
+ * libdwarf.h: Add new data structures to allow reading of
+ non-Elf object files.
+ * dwarf_original_elf_init.c: dwarf_init(), dwarf_elf_init()
+ moved here from dwarf_init_finish.c.
+ * Makefile.in: Build new source files dwarf_original_elf_init.c
+ and dwarf_elf_access.c.
+ * dwarf_init_finish.c: All dependencies on libelf and elf
+ have been removed.
+ * dwarf_opaque.h: The elf related info is removed and Dwarf_Debug_s
+ now contains a new structure (from libdwarf.h) to hide object
+ information.
+ * dwarf_elf_access.c: All the Elf-using code is now in this
+ source file and elf details are kept in a struct defined and
+ used here. Non-libelf and non-elf object access code would
+ write a new source file with their own details using this
+ as an example.
+ * dwarf_elf_access.h: Prototypes for calling between
+ dwarf_original_elf_init.c and dwarf_elf_access.c.
+2008-02-18 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h: Declare new object-access functions and structures.
+ * dwarf_original_elf_init.c: Traditional dwarf_init() and dwarf_elf_init()
+ are moved to this new source file.
+ * Makefile.in: Add new source files.
+ * dwarf_init_finish.c: Now uses the function pointers, not
+ libelf specific fields or ifdefs.
+ * pro_opaque.h: Remove de_access field, it is unused.
+ * dwarf_opaque.h: New fields for new object-access functions.
+ * dwarf_elf_access.c: New implementation details for elf access functions
+ moved here from dwarf_init_finish.c.
+ * dwarf_elf_access.h: New function interface so dwarf_elf_access.c
+ and dwarf_original_elf_init.c can communicate.
+2008-02-08 DavidAnderson <davea42@earthlink.net>
+ * dwarf_print_lines.c: Added commentary to clarify that
+ dwarf_print_lines() and _dwarf_print_lines are intentionally
+ identical. Initialized local variables so they are alll
+ visibly set to some sensible value.
+2008-02-07 DavidAnderson <davea42@earthlink.net>
+ * dwarf_frame.c (_dwarf_fde_section_offset): A typo
+ in the last release made this an infinite loop.
+ A one character change fixed it. Thanks to Carlos Alberto
+ Enciso for noticing the bug.
+2008-02-04 DavidAnderson <davea42@earthlink.net>
+ * dwarf_incl.h, pro_incl.h: Moved #include of dwarf.h before libdwarf.h
+ * pro_forms.c: Some newer attributes are now handled.
+ * dwarf_print_lines.c: Removed unused #include.
+ * dwarf_sort_line.c: Removed alloca use in favor of
+ malloc and removed the alloca #include.
+ * dwarf_line.c: Removed unused #include.
+ * dwarf_line2.c: Removed unused #include.
+
+2008-02-04 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h: Fix commentary mistakes.
+2008-02-02 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h: Add DW_DLC_OFFSET_SIZE_64 for run-time
+ selection of DWARF3 64bit extension producer offset generation.
+ * libdwarf2p.1.mm: Document DW_DLC_OFFSET_SIZE_64.
+ * pro_init.c (dwarf_producer_init): Now standard DWARF3 is the default.
+ * configure.in: Add --enable-dwarf-format-sgi-irix for those
+ wanting IRIX offset-style DWARF2. Add --enable-dwarf-format-strict-32bit
+ for those wanting strictly 32bit offsets.
+ Otherwise default to generating 64bit offsets from the producer code,
+ but allow the DWARF3 extended 64bit offsets if the flag
+ DW_DLC_OFFSET_SIZE_64 is turned on in the call to dwarf_producer_init().
+ * config.h.in: Provide undefs for the offset macros.
+
+2008-01-25 DavidAnderson <davea42@earthlink.net>
+ * pro_die.c: Changed leading tabs to spaces.
+2008-01-23 DavidAnderson <davea42@earthlink.net>
+ * pro_die.c: Using di_last_child field dwarf_die_link
+ goes from O(N) to O(1) in adding a child.
+ Thanks to Daniel Gollub for the suggestion.
+ An omission in linking left/right children is fixed.
+ Changed some leading TABs to spaces.
+ * pro_opaque.h: Add di_last_child field.
+2008-01-14 DavidAnderson <davea42@earthlink.net>
+ * libdwarf2p.1.mm: Added missing backslash to correct formatting
+ error. Thanks to Daniel Golub for pointing out the ommission.
+ * libdwarf2.p1.pdf: Regenerated.
diff --git a/libdwarf/ChangeLog2009 b/libdwarf/ChangeLog2009
new file mode 100644
index 0000000..a62bc0f
--- /dev/null
+++ b/libdwarf/ChangeLog2009
@@ -0,0 +1,348 @@
+2009-12-30 DavidAnderson <davea42@earthlink.net>
+ * configure: Regenerated with autoconf 2.64.
+ * config.guess, config.sub: Delete these.
+ * configure.in, README: The --enable-nonshared
+ option was coded incorrectly. The configure
+ options are --enable-shared and --disable-nonshared
+ work correctly. Options --disable-shared and --enable-nonshared work
+ correctly as well (these are the default values).
+2009-12-29 DavidAnderson <davea42@earthlink.net>
+ * gennames.c: Add cast to int in printf so that the printf with *
+ as the field width sees an int, not size_t.
+ * Makefile.in: Add depenencies for libdwarf.so to match
+ libdwarf.a
+2009-12-26 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h, pro_section.c, pro_reloc_symbolic.c: Reformatted
+ a few lines that were badly formatted.
+ Initialized local variables where a few were not initialized
+ (this did not affect correctness, just readability).
+2009-11-27 DavidAnderson <davea42@earthlink.net>
+ * dwarf_form.c: Was an incorrect implemenation of
+ the reading of DW_FORM_sec_offset.
+ * libdwarf2.1.mm: Improved the documentation on reading DW_FORM_sec_offset.
+ See dwarf_global_formref() documentation.
+ * libdwarf2.1.pdf: Regenerate.
+2009-11-27 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h, dwarf_form.c, dwarf_query.c: Adding
+ new form-class for the old DW_AT_MIPS_fde
+ SGI/IRIX extension (offset into .debug_frame).
+2009-11-27 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h: Added dwarf_formexprloc() and a new
+ error code for it.
+ * dwarf_query.c: The new dwarf_get_form_class()
+ function had a typo for the address class.
+ * dwarf_form.c: dwarf_formexprloc() added so one can read
+ DW_FORM_exprloc location expressions.
+ * dwarf_error.c: New error added for dwarf_formexprloc().
+ * libdwarf2.1.mm: Document dwarf_formexprloc().
+ * libdwarf2.1.pdf: Regenerate.
+2009-11-27 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h: Defines typedef Dwarf_Sig8 and
+ the new function dwarf_formsig8().
+ * dwarf_error.c: Now deals with the latest
+ error codes, including a new one for dwarf_formsig8().
+ * libdwarf2.1.mm: Document dwarf_formsig8().
+ * libdwarf2.1.pdf: Regenerate.
+2009-11-24 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h: Added enum dwarf_form_class_e and
+ dwarf_get_form_class() so clients have a simple
+ way to get the form-class mentioned in the DWARF
+ specification.
+ * dwarf_query.c: Implemented dwarf_get_form_class().
+ * dwarf_die_deliv.c: Added dwarf_next_cu_header_b()
+ function as more useful than dwarf_next_cu_header().
+ * dwarf_opaque.h: Added commentary about CU record.
+ * dwarf_elf_access.c: Added commentary about the CU header
+ data.
+ * libdwarf2.1.mm: Document dwarf_next_cu_header_b()
+ and suggest users convert to it.
+ Document dwarf_get_form_class(). Rev 1.84
+ * libdwarf2.1.pdf: Regenerate.
+2009-11-23 DavidAnderson <davea42@earthlink.net>
+ * dwarf_line.c: file_name_is_full_path() did not
+ allow for lower case in Windows root path
+ detection (with --enable-windowspath at configure
+ time). Now it does.
+2009-11-17 DavidAnderson <davea42@earthlink.net>
+ * gennames.c: Check the return value from fgets().
+ * dwarf_form.c, dwarf_util.c: Handle DW_FORM_sec_offset, new in DWARF4.
+ * libdwarf2.1.mm: Add comment to macro example to clarify its
+ limitation (it cannot always work).
+ * libdwarf2.1.pdf: Regenerate.
+2009-09-30 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h: Added dwarf_insert_fde_inst_bytes()
+ to simplify copying an fde. Added dwarf_get_cie_index()
+ to provide a direct specific way to get a cie index for an fde.
+ * libdwarf2.1.mm: Minor reformatting to make things easier to read.
+ This is revision 1.82. Documented the new function
+ dwarf_get_cie_index().
+ * libdwarf2.1.pdf: Regenerated.
+ * dwarf.h: Corrected typo, DW_CFA_cfa_offset_extended_sf is
+ really spelled DW_CFA_offset_extended_sf.
+ Added final new attributes, tag, language.
+ * pro_alloc.c: Reformatting a comment so the line is not so long.
+ * libdwarf2p.1.mm: Clarified that some arguments in fde
+ creation are MIPS/IRIX only (other targets should just pass 0).
+ This is revision 1.27. Document the new function
+ dwarf_insert_fde_inst_bytes().
+ * libdwarf2p.1.pdf: Regenerated.
+ * config.h.in: Added HAVE_WINDOWS_PATH.
+ * configure.in: Added --enable-windowspath to set
+ HAVE_WINDOWS_PATH.
+ * configure: Regenerated.
+ * pro_section.c: Now allows use of a block of fde instructions
+ from dwarf_insert_fde_inst_bytes(). Some indentation fixed too.
+ * dwarf_line.c: Added detection of Windows full path if
+ HAVE_WINDOWS_PATH defined at library build time.
+ * pro_frame.c: Now handles dwarf3 CFA operations (but not the
+ expression operands yet). Removed some duplicated code in
+ a switch statement. Fixed commentary typos.
+ Created new function dwarf_insert_fde_inst_bytes().
+ * pro_frame.h: Added fields to support dwarf_insert_fde_inst_bytes().
+ * dwarf_arange.c: dwarf_get_arange_cu_header_offset() was
+ failing to load .debug_info, so a legitimate use of the function
+ might crash a client.
+ * dwarf_frame2.c: If there are CIE records but no FDEs this
+ is not considered a 'NO ENTRY' case. It is strange
+ but not a formal error and we might want to access the orphan
+ CIE records (to print them when debugging a compiler, for example).
+ * README: Documented --enable-windowspath.
+ * dwarf_frame.c: Adding dwarf_get_cie_index() convenience function.
+2009-09-09 DavidAnderson <davea42@earthlink.net>
+ * libdwarf2p.1.mm: Improved the discussion of
+ dwarf_transform_to_disk_form.
+ * libdwarf2p.1.pdf: Regenerated.
+2009-08-12 DavidAnderson <davea42@earthlink.net>
+ * pro_section.c: The Dwarf_Die argument to fde creation
+ functions is really optional (NULL is ok) and only used
+ for an IRIX/MIPS extension. So the code now allows
+ a NULL Dwarf_Die argument for these functions.
+ * libdwarf2p.1.mm: Rev 1.24, 11 Aug 2009 now documents
+ the argument as NULL for most users.
+ * libdwarf2p.1.pdf: Regenerated Rev 1.24, 11 Aug 2009.
+2009-08-07 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h: Added to Dwarf_Regtable_Entry_s
+ and Dwarf_Regtable_Entry_s comments.
+ * libdwarf2.1.mm: Revised dwarf_set_frame_rule_table_size()
+ description, making it a bit more complete.
+ * libdwarf2.1.pdf: Regenerated, rev 1.81, 07 August 2009.
+2009-08-05 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h: Interface to dwarf_expand_frame_instructions()
+ changed, the original could not really work right.
+ * libdwarf2.1.mm: Documented revised dwarf_expand_frame_instructions().
+ * libdwarf2.1.pdf: Regenerated, rev 1.80, 05 August 2009.
+ * dwarf_frame.c: Fixed dwarf_expand_frame_instructions();
+2009-08-05 DavidAnderson <davea42@earthlink.net>
+ * gennames.c: Change include from getopt.h to unistd.h
+ so the code is more universally compilable.
+2009-07-24 DavidAnderson <davea42@earthlink.net>
+ * dwarf_frame.c: Change debug printf to use libdwarf.h DW_PR macros
+ instead of %d.
+2009-07-20 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h: Added DW_DLE_NO_ELF64_SUPPORT.
+ * dwarf_elf_access.c: If one has no Elf64 libelf support at build time
+ and runtime one finds an Elf64 object then we return
+ an error (DW_DLE_NO_ELF64_SUPPORT). Pretending we could handle
+ the elf64 was a bug.
+ * dwarf_error.c: Adding strings for new error codes.
+ * dwarf_elf_access.c: Add error code argument.
+ * dwarf_elf_access.h: Add error code argument.
+ * dwarf_original_elf_init.c: Report the correct error code instead
+ of a generic code.
+
+2009-07-16 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h: Add an error message define relating to rela relocations.
+ * dwarf_alloc.c: Add code to free malloc space (related
+ to rela relocations).
+ * config.h.in: Add ifdef for Sun host machines so rela processing
+ does not segv.
+ * dwarf_opaque.h: Add a flag to the section data to note that we malloced
+ space when rela relocations are involved.
+ * dwarf_elf_access.c: Refine is_32bit_abs_reloc() and
+ is_64bit_abs_reloc() for easier debugging.
+ Add malloc call when doing rela processing
+ as some host libelf libraries make some libelf data areas read-only
+ (Solaris and Irix for example). The malloc space avoids getting
+ a segv.
+2009-07-13 DavidAnderson <davea42@earthlink.net>
+ * dwarf_elf_access.c: some cases had = where == was
+ needed in the reloc switch code.
+2009-07-05 DavidAnderson <davea42@earthlink.net>
+ * dwarf_opaque.h: New data for .rela and unify section data
+ information. The changes will require consumers supporting
+ non-elf-objects to make small (hopefully simple) changes.
+ * dwarf_init_finish.c: Note existence of .rela sections.
+ * pro_forms.c: Explicitly allow DW_AT_const_value,
+ DW_AT_entry_pc, DW_AT_call_file, DW_AT_call_line.
+ * dwarf_ranges.c: Use simplified _dwarf_load_section() interface.
+ Change an accidental C++ style // comment to oldstyle C comment.
+ * dwarf_print_lines.c, dwarf_form.c, dwarf_query.c,
+ dwarf_vars.c, dwarf_pubtypes.c, dwarf_frame3.c, dwarf_funcs.c,
+ dwarf_arange.c, dwarf_global.c, dwarf_init_finish.c,
+ dwarf_line.c, dwarf_opaque.h, dwarf_string.c, dwarf_weaks.c
+ dwarf_util.c, dwarf_loc.c, dwarf_frame.c, dwarf_macro.c,
+ dwarf_types.c: Use simplified _dwarf_load_section() interface.
+
+2009-07-05 DavidAnderson <davea42@earthlink.net>
+ * dwarf_init_finish.c: Unified some common code into
+ a new local function , reducing file by 60 lines.
+ * dwarf_init_finish.c: Has long checked the wrong field
+ for duplicate debug_info and debug_abbrev. Fixed.
+ Also noted SGI IRIX only sections by adding comments.
+2009-07-04 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h: Adding new function dwarf_CU_dieoffset_given_die(),
+ and comments on dwarf_get_cu_die_offset_given_cu_header_offset();
+ * libdwarf2.1.mm: documenting dwarf_CU_dieoffset_given_die().
+ * libdwarf2.1.pdf: Regenerated.
+ * dwarf_opaque.h: New structure Dwarf_Section_s consolidates
+ section information into one struct per section with
+ index and size so we remove many Dwarf_Debug_s fields.
+ * dwarf_print_lines.c, dwarf_form.c, dwarf_query.c, dwarf_vars.c,
+ dwarf_pubtypes.c, dwarf_frame3.c, dwarf_funcs.c,
+ dwarf_alloc.c, dwarf_arange.c, dwarf_init_finish.c ,
+ dwarf_ranges.c, dwarf_line.c, dwarf_abbrev.c, dwarf_string.c,
+ dwarf_weaks.c, dwarf_frame2.c, dwarf_util.c, dwarf_loc.c,
+ dwarf_die_deliv.c, dwarf_frame.c, dwarf_macro.c, dwarf_types.c,
+ Reflect Dwarf_Section_s addition using its fields.
+ Simplify years list of SGI copyright using y-y replacing comma list.
+ Minor reformatting for consistency with 4-space indentation.
+ Initialize uninitialized local variables at declaration.
+ * dwarf_addr_finder.c, dwarf_print_lines.c: Initialize 'res'
+ local variables at declaration to DW_DLV_ERROR.
+ * dwarf_global.c: Add dwarf_CU_dieoffset_given_die().
+ Reflect Dwarf_Section_s addition using its fields.
+ Simplify years list of SGI copyright using y-y replacing comma list.
+ Minor reformatting for consistency with 4-space indentation.
+ Initialize uninitialized local variables at declaration.
+2009-06-06 DavidAnderson <davea42@earthlink.net>
+ * configure.in: The new option --enable_namestable
+ switches build time to generate a runtime binary search
+ in the dwarf_get_TAG_name() etc functions instead of the
+ default switch statement (for the rare case one knows a
+ compiler generates poor switch code).
+ * configure: regenerated.
+ * libdwarf.h: Correct format mistakes and omissions in
+ the Dwarf_Regtable_Entry3_s comments.
+ Add prototypes for dwarf_get_TAG_name() and the related
+ new functions.
+ * dwarf_frame.c: Add {} to clarify some 'if' ranges.
+ Remove code updating the DW_FRAME_CFA_COL row when finishing
+ up establishing the current frame table. The code should never
+ have been there. Fixed some indentation of function
+ formal parameters. Removed use of DW_FRAME_CFA_COL
+ and use de_frame_cfa_col_number instead.
+ In dwarf_get_fde_info_for_reg (the older interface)
+ correctly return the cfa table column in the 'old style'.
+ * gennames.c: Copied from dwarfdump.c (with changes).
+ This generates dwarf_names.c so that libdwarf has
+ functions like dwarf_get_TAG_name() which returns
+ functions like dwarf_get_TAG_name() which returns
+ the tag as a string (through a pointer argument).
+ * dwarf.h: The first word of a comment is now capitalized (1 place).
+ * common.c: New, used by gennames.c.
+ * common.h: New, used by gennames.c
+ * Makefile.in: Now contains changes which build and run
+ gennames and create dwarf_names.o (which is part
+ of libdwarf).
+ * libdwarf2.1.mm: Document the new libdwarf functions.
+ * libdwarf2.1.pdf: Regenerated as rev 1.76, 6 June 2009.
+2009-06-05 DavidAnderson <davea42@earthlink.net>
+ * dwarf.h: added new DWARF4 attribute (etc) defines.
+2009-05-10 DavidAnderson <davea42@earthlink.net>
+ * dwarf_frame.c: Remove use of DW_FRAME_UNDEFINED_VAL in
+ favor of the value in the dbg structure.
+ Adding comments about the meaning of an error case.
+2009-05-07 DavidAnderson <davea42@earthlink.net>
+ * Makefile.in: Ensure temp files all get deleted.
+2009-05-04 DavidAnderson <davea42@earthlink.net>
+ * dwarf_die_deliv.c: Update _dwarf_get_size_of_val()
+ call (with its new address_size argument).
+ * dwarf_frame.c: Use the new ci_address_size instead
+ of de_pointer_size.
+ * dwarf_frame.h: Added ci_address_size to cie
+ in preparation for this value in DWARF4.
+ * dwarf_util.h: Adding address_size functions
+ and arguments declarations so address_size can vary by CU.
+ * dwarf_util.c: Adding address_size functions
+ and arguments so address_size can vary by CU.
+ * dwarf_loc.c: Adding function dwarf_loclist_from_expr_a()
+ as a version with an address size argument.
+ * dwarf_frame2.c: Now initializes new ci_address_size field.
+ * dwarf_line.c: Now uses address size for CU instead of
+ default de_pointer_size.
+ * dwarf_ranges.c: File left out of svn before.
+ Implements dwarf_get_ranges() and dwarf_get_ranges_a(),
+ the latter is new with address size passed in via a DIE pointer.
+ * dwarf_arange.c: Added commentary. Removed erroneous
+ insistence that every aranges group have the same
+ address_size as the main elf object.
+ * dwarf_query.c: Adding address size to internal calls.
+ * dwarf_print_lines.c: Added '(file number is %d)'
+ to -l -v -v -v output as the
+ file number and traditional C zero-origin index index of a
+ line table header are not the same value
+ (see DWARF3 documentation, the end of section 6.2.5.3).
+ * libdwarf2.1.mm: Documented dwarf_loclist_from_expr_a()
+ and dwarf_get_ranges_a().
+ * libdwarf2.1.pdf: Regenerated.
+ * libdwarf.h: Add commentary.
+ Add dwarf_loclist_from_expr_a() and
+ dwarf_get_ranges_a() interfaces so address_size passed in.
+2009-04-04 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h, dwarf_frame.c: Added dwarf_set_frame_cfa_value().
+ Added dwarf_set_frame_rule_initial_value() as proper
+ spelling of dwarf_set_frame_rule_inital_value(), keeping
+ the old spelling for compatibility.
+ * libdwarf2.1.mm: Documented Added dwarf_set_frame_cfa_value(),
+ corrected spelling to dwarf_set_frame_rule_initial_value().
+ * libdwarf2.1.pdf: Regenerated.
+ * dwarf_opaque.h: Added field de_frame_cfa_col_number so that
+ we do not need to use magic macros at execution time.
+ * dwarf_init_finish.c: Now sets de_frame_cfa_col_number,
+ de_frame_same_value_number, and de_frame_undefined_value_number.
+2009-02-02 DavidAnderson <davea42@earthlink.net>
+ * dwarf.h: Added dwarf extensions reported by
+ John Bishop.
+2009-03-30 DavidAnderson <davea42@earthlink.net>
+ * dwarf.h: Added dwarf extensions reported
+ on the dwarf-workgroup mailing list by John DelSignore.
+2009-03-19 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h: Expanded comments.
+ * dwarf_die_deliv.c: Expanded comments.
+2009-03-16 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h: Fixed several instances of
+ inconsistent indentation. Documented arguments
+ to dwarf_uncompress_integer_block().
+2009-02-17 DavidAnderson <davea42@earthlink.net>
+ * dwarf_print_lines.c,dwarf_line.c,dwarf_frame.c: C99-isms
+ of // comments and declarations-in-code do not belong in
+ libdwarf.
+2009-02-14 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h: Add support for compile-time definition
+ of the format for Dwarf_Unsigned types.
+ Using macros for DW_PR_DUx etc.
+ * dwarf_print_lines.c: Use the DW_PR_DUx macros.
+ * configure.in: Define --enable-nonstandardprintf
+ * config.h.in: new #undef HAVE_NONSTANDARD_PRINTF_64_FORMAT
+ * configure: Regenerated.
+ * config.guess, config.sub: Latest version from GNU.
+ * dwarf_line.c: Use the DW_PR_DUx macros.
+ * dwarf_frame2.c: Use the DW_PR_DUx macros.
+ * README: document --enable-nonstandardprintf
+
+2009-02-13 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h: Added argument to dwarf_print_lines()
+ for better error reporting. Added dwarf_check_lineheader()
+ which allows some error reporting when not calling dwarf_print_lines().
+ * dwarf_print_lines.c: Implements dwarf_check_lineheader() now.
+ * dwarf_sort_line.c: Match up with new arguments to
+ dwarf_read_line_table_prefix().
+ * dwarf_line.c: Implement new arguments to
+ dwarf_read_line_table_prefix() for better error reporting.
+ Allow erroneous ARM-compiler line table header to be used.
+ * dwarf_line.h: Adding new argument to dwarf_read_line_table_prefix
+ so we can report back on minor errors in the line table prefix.
+2009-01-31 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h: Corrected DW_DLE_LAST.
+ * dwarf_frame.c: Remove accidental use of C99 mid-block
+ variable definition.
diff --git a/libdwarf/ChangeLog2010 b/libdwarf/ChangeLog2010
new file mode 100644
index 0000000..844254b
--- /dev/null
+++ b/libdwarf/ChangeLog2010
@@ -0,0 +1,175 @@
+2010-10-13 DavidAnderson <davea42@earthlink.net>
+ * dwarf.h: Added DW_LANG_Go as 0x0015 per discussion on
+ mailing list.
+2010-09-29 DavidAnderson <davea42@earthlink.net>
+ * README: Document that there is no install target and
+ update some of the old references to postscript to refer
+ to pdf.
+ * Makefile.in: A dummy install target provided though it
+ gets ignored by make.
+2010-09-20 DavidAnderson <davea42@earthlink.net>
+ * libdwarf/libdwarf.h: Added commentary about markers.
+ * libdwarf/libdwarf2p.1.mm: Documented the marker calls.
+ * libdwarf/libdwarf2p.1.pdf: Regeenerated, ver 1.29.
+2010-06-30 DavidAnderson <davea42@earthlink.net>
+ * dwarf.h: Add DW_ISA_ARM values for DW_LNS_set_isa.
+2010-06-01 DavidAnderson <davea42@earthlink.net>
+ * README: Document issues with building on MacOSX and
+ how to deal with them.
+ * Makefile.in: Added comment about ar -s for MacOSX users.
+ * dwarf.h: Added comment about the gap in FORM number use
+ just before 0x20.
+2010-03-30 DavidAnderson <davea42@earthlink.net>
+ * dwarf_frame2.c: Tightned up a harmless error
+ message string and deleted an unused local variable.
+ * dwarf_harmless.c: Detected more errors in the implementation
+ and fixed them.
+ * dwarf_elf_access.c: If EM_MIPS not defined, define it to 8,
+ the standard value for EM_MIPS.
+ Refine the rela relocations code for MIPS 64 BE vs LE.
+ * dwarf_arange.h: Added new fields to properly represent
+ segments in aranges as documented in DWARF4.
+ * dwarf_arange.c: dwarf_get_aranges was thinking
+ an entry with 0,0 (end of a set) was the end of the aranges
+ for a CU. But that is not guaranteed by the DWARF standards,
+ there can be multiple sets in one CU, see the standard,
+ section 7.20 (DWARF2,3,4).
+ Created local function, removing lots of duplicated code.
+ Added some support for DWARF4 segment value in tuples.
+ Added dwarf_get_arange_info_b() so all DWARF4 information
+ can be retrieved by client code.
+ * libdwarf.h: Aded new interface dwarf_get_arange_info_b(),
+2010-03-28 DavidAnderson <davea42@earthlink.net>
+ * libdwarf.h: Adding dwarf_get_harmless_error_list(),
+ dwarf_insert_harmless_error(), and
+ dwarf_set_harmless_error_list_size() functions.
+ Some errors that are detectable are not sufficient
+ to warrant rejecting an object or refusing to process it.
+ * dwarf_harmless.c: Implementing
+ the harmless error functions.
+ * dwarf_harmless.h: Declaration of the libdwarf_internal
+ dwarf_harmless_init and dwarf_harmless_cleanout functions.
+ * dwarf_error.c: Added DW_DLE_DEBUG_FRAME_LENGTH_NOT_MULTIPLE
+ error string.
+ * dwarf_util.h: Clarify some comments on READ_AREA_LENGTH
+ macro.
+ * dwarf_opaque.h: Add structure and field to record
+ harmless errors for a dbg.
+ * dwarf_frame.h: Add commentary. Change ci_length from
+ Dwarf_Word to Dwarf_Unsigned for consistency with other such
+ length fields.
+ * Makefile.in: Add dwarf_harmless.o to the list of objects.
+ * dwarf_alloc.c: Add call to dwarf_harmless_cleanout() on
+ close of a dbg.
+ * dwarf_init_finish.c: Add call to dwarf_harmless_init
+ to initialize the fields for recording harmless errors.
+ * dwarf_frame2.c: Add handling of Arm "armcc+" augmentation
+ string. Create validate_length() local function to check
+ that the fde/cie length matches the requirements of the
+ specification, implementing the
+ DW_DLE_DEBUG_FRAME_LENGTH_NOT_MULTIPLE test (a harmless error).
+ Removed an earlier formally incorrect test.
+ * libdwarf2.1.mm: Documented the harmless error calls.
+ The version is now 1.90.
+ * libdwarf2.1.pdf: Regenerated as 1.90.
+2010-02-14 DavidAnderson <davea42@earthlink.net>
+ * dwarf.h: Add GNU template defines.
+ * libdwarf.h: Add new error code DW_DLE_NOT_REF_FORM for
+ the DWARF 4 case where DW_FORM_data4/8 no longer
+ valid global reference forms.
+ * libdwarf2.1.mm: Document the manner that DW_OP_implicit_value
+ is returned as a location description set.
+ * libdwarf2.1.pdf: Regenerate. Rev 1.89.
+ * dwarf_error.c: Add two new DW_DLE error strings.
+ * dwarf_frame.h: define DW_DEBUG_FRAME_VERSION4 for
+ DWARF4 support. Add address size and segment size fields
+ to the internal CIE structure.
+ * dwarf_query.c: The form-class code was not correct,
+ DWARF4 has DW_FORM_sec_offset, not DWARF3.
+ Some places did not use the CU context address size
+ when reading an address.
+ * dwarf_form.c: Use the CU-context address size
+ instead of the overall object address/offset size.
+ Initialize all local variables at the point of declaration.
+ Refine some commentary.
+ Use the CU version number to guide processing of some FORMs.
+ * dwarf_print_lines.c, dwarf_query.c: Use the CU-context
+ address size instead of the overall object address/offset size.
+ Handle DW_LNE user extensions as well as possible.
+ * dwarf_arange.c: Delete some erroneous code (already ifdefd out)
+ as the address size need not match the de_pointer_size.
+ If segment-selector non-zero, read it properly.
+ DWARF2 and DWARF3 left this documented in an incorrect
+ and unusable fashion (DWARF4 documents it properly).
+ * dwarf_die_deliv.c: Delete erroneous code (previously ifdefd out)
+ as the address size need not match the de_pointer_size.
+ * dwarf_sort_line.c, dwarf_line.c: Deal with DW_DLE extended
+ line operations past those defined by the standard
+ (such as user-defined operations).
+ * dwarf_line.h: For user-defined line extended operations, provide
+ a sanity check of DW_LNE_LEN_MAX.
+ * dwarf_base_types.h: Add DW_CIE_VERSION4 for DWARF4.
+ Add other defines so each defined version number (sections
+ differ) has a name for the relevant section.
+ * dwarf_frame2.c: Add address size to argument lists so the proper
+ CIE address size (a new field in DWARF4 CIEs) are honored.
+ Also read the new DWARF4 segment_size field.
+ Use the address size instead of the object-derived de_pointer_size.
+ * dwarf_util.c: Return address_size instead of de_pointer_size.
+ * dwarf_loc.c: DWARF4 uses DW_FORM_sec_offset, not
+ DW_FORM_data4 or DW_FORM_data8 when specifying offsets to
+ other sections. Add DWARF4 DW_OP_implicit_value and
+ DW_OP_stack_value.
+ * dwarf_frame.c: Initialize a local variable at the point
+ of declaration.
+2010-02-04 DavidAnderson <davea42@earthlink.net>
+ * libdwarf2.1.mm: Fix a spelling error.
+ * libdwarf2.1.mm: Regenerate. Rev 1.88.
+2010-02-01 DavidAnderson <davea42@earthlink.net>
+ * dwarf_frame.c: The DW_CFA_remember_state and DW_CFA_restore_state
+ operations were not recording/restoring the cfa_rule, now they do.
+2010-01-27 DavidAnderson <davea42@earthlink.net>
+ * dwarf_form.c: form_refsig8() had an uninitialized
+ local variable.
+2010-01-25 DavidAnderson <davea42@earthlink.net>
+ * libdwarf2.1.mm: Rev 1.87. Improved the discussion
+ of frame information.
+ * libdwarf2.1.pdf: regenerated.
+2010-01-25 DavidAnderson <davea42@earthlink.net>
+ * pro_opaque.h, pro_init.c, pro_section.c,
+ pro_reloc_stream.c, pro_reloc_symbolic.c: Rename the function
+ pointer members de_func and de_func_b to
+ de_callback_func and de_callback_func_b respectively.
+2010-01-17 DavidAnderson <davea42@earthlink.net>
+ * dwarf.h, libdwarf.h: Updated commentary about frame interfaces.
+ * libdwarf2.1.mm: New descriptions of DW_FRAME_CFA_COL
+ and DW_FRAME_CFA_COL3. Document rev 1.86 .
+ * libdwarf2.1.pdf: Regenerated.
+ * libdwarf2p.1.mm: Fixed a couple of typos. Rev 1.28.
+ * libdwarf2p.1.pdf: Regenerated.
+ * configure.in: Added support for configure
+ --enable-oldframcol.
+ * config.h.in: Added support for configure
+ --enable-oldframcol.
+ * dwarf_init_finish.c: Added support for configure
+ --enable-oldframecol (see DW_FRAME_CFA_COL and
+ DW_FRAME_CFA_COL3). By default the frame column
+ is now DW_FRAME_CFA_COL3. --enable-oldframecol
+ changes the default to DW_FRAME_CFA_COL.
+ * configure: Regenerated.
+ * dwarf_opaque.h: Added one blank line and deleted
+ one, hopefully aiding clarity.
+ * dwarf_frame.c: Added commentary about the frame
+ interfaces to emphasize the newer ones.
+2010-01-13 DavidAnderson <davea42@earthlink.net>
+ * dwarf_print_lines.c: Changed 'include files count'
+ to 'files count'.
+2010-01-04 DavidAnderson <davea42@earthlink.net>
+ * pro_section.c, pro_opaque.h: A pretty-print tool
+ generated some odd formatting (long ago) and there
+ were silly blank lines present as well. This makes things more
+ readable.
+2010-01-03 DavidAnderson <davea42@earthlink.net>
+ * common.h, common.c: Remove <cr> line end characters.
+ Update copyright for 2010.
+ * All other files: Update copyright year.
diff --git a/libdwarf/LGPL.txt b/libdwarf/LGPL.txt
new file mode 100644
index 0000000..5ab7695
--- /dev/null
+++ b/libdwarf/LGPL.txt
@@ -0,0 +1,504 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/libdwarf/LIBDWARFCOPYRIGHT b/libdwarf/LIBDWARFCOPYRIGHT
new file mode 100644
index 0000000..a6d75ec
--- /dev/null
+++ b/libdwarf/LIBDWARFCOPYRIGHT
@@ -0,0 +1,30 @@
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
diff --git a/libdwarf/Makefile.in b/libdwarf/Makefile.in
new file mode 100644
index 0000000..a2f3f0c
--- /dev/null
+++ b/libdwarf/Makefile.in
@@ -0,0 +1,227 @@
+#
+#
+# Copyright (C) 2000,2003,2004,2006 Silicon Graphics, Inc. All Rights Reserved.
+# Portions Copyright (C) 2010 David B Anderson. All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2.1 of the GNU Lesser General Public License
+# as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like. Any license provided herein, whether implied or
+# otherwise, applies only to this software file. Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, write the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+# USA.
+
+#
+# Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+# Mountain View, CA 94043, or:
+#
+# http://www.sgi.com
+#
+# For further information regarding this notice, see:
+#
+# http://oss.sgi.com/projects/GenInfo/NoticeExplan
+#
+#
+
+#
+# Makefile for libdwarf
+# This is made very simple so it should work with
+# any 'make'.
+#
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = $(exec_prefix)/bin
+libdir = $(exec_prefix)/lib
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+SHELL = /bin/sh
+CC = @CC@
+AR = @AR@
+# For use with BSD ar (MacOSX ar) edit the ARFLAGS to be -s
+#ARFLAGS = @ARFLAGS@
+RM = rm
+RANLIB = @RANLIB@
+DEFS = @DEFS@
+LIBS = @LIBS@
+INCLUDES = -I. -I$(srcdir)
+dwfpic = @dwfpic@
+CFLAGS = $(PREINCS) @CFLAGS@ $(INCLUDES) $(dwfpic) $(POSTINCS)
+# For more checking add -DWANT_LIBBDWARF_MALLOC_CHECK=1 to CFLAGS
+LDFLAGS = $(PRELIBS) @LDFLAGS@ $(POSTLIBS)
+
+
+BUILD_BASE = .
+
+OBJS= dwarf_abbrev.o \
+ dwarf_alloc.o \
+ dwarf_arange.o \
+ dwarf_die_deliv.o \
+ dwarf_elf_access.o \
+ dwarf_error.o \
+ dwarf_form.o \
+ dwarf_frame.o \
+ dwarf_frame2.o \
+ dwarf_frame3.o \
+ dwarf_funcs.o \
+ dwarf_global.o \
+ dwarf_harmless.o \
+ dwarf_init_finish.o \
+ dwarf_line.o \
+ dwarf_line2.o \
+ dwarf_loc.o \
+ dwarf_original_elf_init.o \
+ dwarf_query.o \
+ dwarf_string.o \
+ dwarf_stubs.o \
+ dwarf_pubtypes.o \
+ dwarf_types.o \
+ dwarf_util.o \
+ dwarf_leb.o \
+ dwarf_ranges.o \
+ dwarf_vars.o \
+ dwarf_weaks.o \
+ dwarf_addr_finder.o \
+ dwarf_sort_line.o \
+ dwarf_print_lines.o \
+ dwarf_macro.o \
+ malloc_check.o \
+ pro_alloc.o \
+ pro_arange.o \
+ pro_die.o \
+ pro_encode_nm.o \
+ pro_error.o \
+ pro_expr.o \
+ pro_finish.o \
+ pro_forms.o \
+ pro_funcs.o \
+ pro_frame.o \
+ pro_init.o \
+ pro_line.o \
+ pro_reloc.o \
+ pro_reloc_stream.o \
+ pro_reloc_symbolic.o \
+ pro_pubnames.o \
+ pro_section.o \
+ pro_types.o \
+ pro_vars.o \
+ pro_macinfo.o \
+ pro_weaks.o
+
+
+all: @build_shared@ @build_nonshared@
+
+libdwarf.a: dwarf_names.h dwarf_names.c $(OBJS) dwarf_names.o
+ $(AR) $(ARFLAGS) $@ $(OBJS) dwarf_names.o
+
+libdwarf.so: dwarf_names.h dwarf_names.c $(OBJS) dwarf_names.o
+ $(CC) $(CFLAGS) -shared $(OBJS) dwarf_names.o -o $@
+
+none:
+ echo "do nothing"
+common.o: $(srcdir)/common.c $(srcdir)/common.h
+ $(CC) $(CFLAGS) -c $(srcdir)/common.c
+gennames: $(srcdir)/gennames.c $(srcdir)/dwarf.h common.o
+ $(CC) $(CFLAGS) $(srcdir)/gennames.c common.o $(LDFLAGS) -o gennames
+dwarf_names.c dwarf_names.h: gennames $(srcdir)/dwarf.h
+ rm -f dwarf_names.h dwarf_names.c
+ ./gennames @dwarf_namestable@ -i $(srcdir) -o .
+
+
+#
+# The following are very SGI-centric
+# psroff is just a troff formatter.
+# the .mm files are in ATT/USL/USG mm form.
+# Calling it pdfbld or bldpdf is arbitrary, so allow both.
+
+docbld:pdfbld
+bldpdf: pdfbld
+pdfbld: libdwarf2.1.pdf libdwarf2p.1.pdf dwarf.v2.pdf index.v2.pdf mips_extensions.pdf
+#Oriented to using gsroff now.
+TROFF=/usr/bin/groff
+TROFFDEV="-T ps"
+TROFFDEV=
+PSTOPDF=/usr/bin/ps2pdf
+# pr expands tabs to spaces: this avoids problems with tab
+# interpretation
+
+# The warning about 'cant break line' is a too-long line used
+# in the table of contents.
+# Ignore the warning (and those like it).
+libdwarf2.1.pdf: $(BUILD_BASE)/libdwarf2.1.mm
+ -pr -t -e $(BUILD_BASE)/libdwarf2.1.mm \
+ | tbl | $(TROFF) $(TROFFDEV) -mm >libdwarf2.1.ps
+ $(PSTOPDF) libdwarf2.1.ps libdwarf2.1.pdf
+
+libdwarf2p.1.pdf: $(BUILD_BASE)/libdwarf2p.1.mm
+ -pr -t -e $(BUILD_BASE)/libdwarf2p.1.mm \
+ | tbl | $(TROFF) $(TROFFDEV) -mm >libdwarf2p.1.ps
+ $(PSTOPDF) libdwarf2p.1.ps libdwarf2p.1.pdf
+
+# At present, the newIndex is not usable: we have no tools
+# to build a new index page at the moment.
+
+dwarf.v2.pdf: $(BUILD_BASE)/dwarf.v2.mm
+ -pic $(BUILD_BASE)/dwarf.v2.mm \
+ | tbl | $(TROFF) $(TROFFDEV) -mm >dwarf.v2.ps 2> newIndex
+ $(PSTOPDF) dwarf.v2.ps dwarf.v2.pdf
+
+# the index is only useful till the document changes: it is
+# not autmatically correct. It was prepared by tools internal
+# to USL/Novell
+
+index.v2.pdf: index.v2.mm
+ -pic index.v2.mm | tbl | $(TROFF) $(TROFFDEV) -mm >index.v2.ps
+ $(PSTOPDF) index.v2.ps index.v2.pdf
+
+
+mips_extensions.pdf: mips_extensions.mm
+ -pr $(TROFFDEV) -e mips_extensions.mm | tbl | \
+ $(TROFF) $(TROFFDEV) -mm >mips_extensions.ps
+ $(PSTOPDF) mips_extensions.ps mips_extensions.pdf
+
+clean:
+ rm -f *.o libdwarf.a
+ rm -f libdwarf.so
+ rm -f libdwarf2.1.ps
+ rm -f newIndex
+ rm -f dwarf.v2.ps
+ rm -f index.v2.ps
+ rm -f mips_extensions.ps
+ rm -f libdwarf2p.1.ps
+ rm -f gennames
+ rm -f junk
+ rm -f ALL
+ rm -f gennames
+ rm -f dwarf_names_enum.h dwarf_names_new.h dwarf_names.c dwarf_names.h
+
+install: all
+ echo "No install provided, see comments in the README"
+
+distclean: clean
+ rm -f config.status config.log config.cache config.h
+ rm -rf autom4te.cache
+ rm -f Makefile
+
+
+shar:
+ @echo "shar not set up yet"
+dist:
+ @echo "dist not set up yet"
diff --git a/libdwarf/NEWS b/libdwarf/NEWS
new file mode 100644
index 0000000..4aa6176
--- /dev/null
+++ b/libdwarf/NEWS
@@ -0,0 +1,406 @@
+December 13, 2011
+ dwarf_lineoff() is now deprecated, dwarf_lineoff_b() is
+ strongly recommended instead.
+ dwarf_add_line_entry() does not have all the line fields
+ needed for generating DWARF3/4, use dwarf_add_line_entry_b() instead.
+ Generation of DWARF3/4 is not yet functional, this new function
+ is a first step.
+October 29, 2011
+ Added support for reading .debug_types (type unit) data.
+October 26,2011
+ Revised the Makefile.in and README to make building libdwarf
+ easier to accomplish with unusual locations of libelf headers
+ or other headers or libraries.
+June 04,2011
+ Non-Elf objects could be used with libdwarf, but
+ no one has contributed non-elf-reading code for libdwarf
+ and a crucial detail was not documented so those writing
+ such object-reading code have not done it entirely correctly.
+ Fundamentally such code must treat a section index of 0 as
+ a real but empty section with no name (an empty name).
+ dwarf_elf_access.c and dwarf_elf_init_finish.c have some comments
+ on this point now.
+March 29,2011
+ All the code changed a lot because indentations were all over
+ the map, now they are consistent.
+ Additions were made to DWARF4 support.
+ Now we use dicheck (a new open source application) to check indentation.
+ Library users will not see any change, all interfaces remain
+ as before.
+January 12,2010
+ A libdwarf user has noticed that the April 4, 2009
+ consumer function changes introduced
+ a problem: the default CFA column was DW_FRAME_CFA_COL
+ even when a newer DWARF3 consumer frame interface like
+ dwarf_get_fde_info_for_all_regs3() is used. The
+ libdwarf2.1.pdf documentation
+ stated the default should be DW_FRAME_CFA_COL3 in that case.
+
+ The introduction of a caller-specified frame-column
+ function (dwarf_set_frame_cfa_value())
+ in that April 4, 2009 release was flawed in that it failed
+ to match the documentation.
+
+ Now the default frame column is DW_FRAME_CFA_COL3 unless
+ the configure option --enable-oldframecol
+ is used at libdwarf build time.
+ If you are using libdwarf old frame consumer interfaces
+ dwarf_get_fde_info_for_reg(), dwarf_get_fde_info_for_cfa_reg(),
+ and dwarf_get_fde_info_for_all_regs() and want unchanged operation
+ then please configure libdwarf with --enable-oldframecol .
+ or add the call dwarf_set_frame_cfa_value(dbg,DW_FRAME_CFA_COL)
+ after calling a libdwarf initialization function.
+ It is impossible to configure a single libdwarf.a so that
+ it transparently defaults to both DW_FRAME_CFA_COL
+ and DW_FRAME_CFA_COL3.
+
+ A call such as dwarf_set_frame_cfa_value(dbg,DW_FRAME_CFA_COL3)
+ or dwarf_set_frame_cfa_value(dbg,DW_FRAME_CFA_COL)
+ (or some other name/value of your choosing)
+ following the dwarf_init() call gives your application
+ full control of the frame cfa column independent of the libdwarf
+ configure option. See the libdwarf2.1.pdf documentation for details.
+ We strongly recommend that you use dwarf_set_frame_cfa_value()
+ to avoid a configure-time dependency.
+
+July 7, 2009
+ Implemented support for elf 'rela' relocations so libdwarf and dwarfdump
+ can read *nix .o files with such relocations reasonably,
+ at least for some machines
+ (see dwarf_elf_access.c for EM_ in 'case' statements.)
+ This changes the binary access for non-Elf object users (folks
+ who have coded there own non-Elf access routines do reference
+ internals of dwarf_opaque.h), but the new data can be left zero
+ and the rest of the code should work fine.
+ dwarf_opaque.h gathers section data in Dwarf_Section_s structs
+ which simplifies the code in dwarf_init_finish.c and clarifies
+ what fields are section related.
+July 4, 2009
+ When something erroneous is detected in a die
+ information about the CU context may be of interest.
+ So we added dwarf_CU_dieoffset_given_die(), a function which allows
+ clients to find the relevant CU die for any die.
+ The consumer can use normal attribute access functions to
+ print information about that CU die (and the erroneous die,
+ of course). See the libdwarf consumer document for more
+ information.
+April 27, 2009
+ Interface additions: dwarf_loclist_from_expr_a() and
+ dwarf_get_ranges_a() are new interfaces like
+ dwarf_loclist_from_expr() and dwarf_get_ranges() respectively,
+ but with arguments allowing
+ full support for different CIEs
+ in an executable having different address-sizes
+ (and their compilation unit DIEs if .debug_info is present).
+ dwarf_get_loclist_entry() does not support
+ differing address sizes per CIE/CU.
+April 4, 2009
+ Added new functions dwarf_set_frame_cfa_value()
+ dwarf_set_frame_same_value(), and
+ dwarf_set_frame_undefined_value(). These are essential
+ for ABIs where the real register numbers exceed 1033
+ (such as ppc). Failing to use these leads to
+ frame instructions DW_CFA_undefined and
+ DW_CFA_same_value emitting values that cannot be
+ interpreted correctly by a libdwarf consumer.
+ See dwarfdump for examples of use.
+Feb 14, 2009
+ Added configure option --enable-nonstandardprintf
+ which makes it easy to get printf of Dwarf_Unsigned (etc)
+ types correct even for non-standard compilers.
+Dec 30, 2008
+ Added interfaces for getting and printing the .debug_ranges
+ data.
+Dec 8, 2008
+ Record the abbreviation 'code' (index) in each DIE.
+ Making it possible for a pretty-printer to print the
+ abbreviation code.
+Sep 30, 2008
+ Phil Mucci provided an a.out test chase which demonstrates a bug
+ in 64bit DWARF2 output by gcc. Now libdwarf works around this
+ and with -v -v -v -v prints a warning.
+Sep 29, 2008
+ Thanks to Phil Mucci for providing a little-endian 64bit
+ test object file that exposed a problem when there are 'extra' bytes
+ (possibly unused) after a line table prologue header and before the
+ line table itself. This releases fixes the bug.
+
+ Thanks to Matthew Legendre for pointing out that we were sharing
+ de_fde_count for eh and non-eh and that could cause erroneous
+ error returns in a couple of functions.
+ These counts are now separate.
+April 9, 2008
+ libdwarf would behave badly if one compilation unit had more than 64K
+ abbreviations: It was both very slow dealing with abbreviations and would
+ get mixed up and error-off. Increased the size of some internal variables
+ and rewrote abbreviation lookup.
+February 18, 2008
+ It is now possible to write one's own access to objects, making it possible
+ to use a different library than libelf or even read a completely
+ different object format than ELF.
+ See dwarf_object_init() and see the new source files
+ dwarf_original_elf_init.c and dwarf_elf_access.c for example
+ code using the new function-pointer approach as it's implementation.
+ Thanks to Josh Fuhs for doing the design and 99% of the work to make
+ this happen.
+February 2, 2008
+ Now pro_init() defaults to standard DWARF3 generated offset sizes.
+ But if a new flag DW_DLC_OFFSET_SIZE_64 or'd into flags passed to
+ dwarf_produser_init() or dwarf_producer_init_b,
+ the DWARF3 extended offset size is generated (if the address size
+ is 64 bit).
+ The new configure option --enable-dwarf-format-strict-32bit
+ forces pro_init() to always cause 32bit offset dwarf generation.
+ The new configure option --enable-dwarf-format-sgi-irix forces
+ the old SGI IRIX 64bit offset generation for 64bit pointer size objects.
+
+ This is intended to simplify standard DWARF3 generation with
+ the now-normal use of 32bit DWARF offsets for both 32 and 64
+ bit pointer objects.
+
+ It does require that anyone wanting SGI IRIX dwarf generation
+ with its non-standard offsets for 64bit objects use the new
+ --enable-dwarf-format-sgi-irix configure time option.
+
+ This has no effect on dwarf reader code. It affects code calling
+ the libdwarf producer interfaces.
+
+December 8, 2007
+ Had to add an ugly configure conditional as libelf has
+ unconditional use of off64_t in recent libelf.h
+July 3, 2007
+ A new interface function, dwarf_loclist_from_expr(),
+ allows easy extraction of dwarf expression bytes from
+ expressions in frame data.
+May 8, 2007
+ Now documents released as .mm and .pdf (no longer as .ps).
+May 7, 2007
+ Incorporates Sun Microsystems extensions to dwarf.h and
+ to the consumer and producer libraries. The changes
+ include corrections so the producer library cleans up it's memory
+ use on a call to dwarf_producer_finish(dbg).
+ Thanks to Chris Quenelle of Sun for these contributions.
+
+March 20, 2007
+ nroff/troff and the AT&T -mm package are not widely available,
+ so now the Makefile refers to groff, which works quite nicely.
+
+February 20, 2007
+ Documented libdwarf thread safety in README.
+ Fixed memory leak in dwarf macro reading code.
+ Removed use of static data in dwarf macro
+ reading code: now uses stack/heap (for
+ thread safety).
+
+February 9, 2007
+ Maintenance of libdwarf is now outside SGI
+ as David Anderson has left SGI.
+
+March 29, 2006
+ The March 27, 2006 version accomodates DWARF3.
+ Some people have been using the library without
+ altering dwarf.h, libdwarf.h to accomodate
+ large numbers of registers. This exposed a bug
+ (an off-by-one error) but also makes it clear
+ additional documentation is needed. So
+ in libdwarf large new comments near 'TARGET DEPENDENCY'
+ attempt to explain better.
+Oct 03, 2005
+ The July version had an incompatible interface: old
+ dealloc code did not always work right. The incompatibility
+ is now fixed and the new features remain.
+
+July 15, 2005
+ New optional alloc-check code optionally checks all
+ allocated memory is freed (malloc_check.h malloc_check.c)
+ Various new dealloc routines written as the previous approach
+ of letting client code do detailed dealloc turned out not
+ to dealloc all memory.
+ To get the new checking you must manually change a line
+ in malloc_check.h and rebuild libdwarf.
+
+
+Mar 31, 2005
+ Documented the libexc.so/.debug_funcnames
+ dependency and the 64bit-offset DWARF extension in
+ mips_extentions.{mm,ps}.
+
+Mar 21, 2005
+ gcc 3.3 and 3.4 .eh_frame 'z' augmentations are not handled
+ correctly, so libdwarf gives an error when attempting to
+ print such. gcc 2 'eh' augmentation is simpler and
+ prints correctly. (.eh_frame is a GNU section,
+ not DWARF2/3, and what is recorded in .eh_frame is not
+ specified by DWARF2/3, though .eh_frame does resemble
+ DWARF2/3 .debug_frame).
+
+
+Oct 28, 2004
+ Updated contact address in copyright: SGI moved 1/4 mile
+ in 2003 to a new address: 1500 Crittenden Lane.
+
+ Documented additional vendor extensions.
+
+Oct 27, 2004
+ Added known vendor extensions to dwarf2/3 to dwarf.h
+ HP, GNU, PGI and UPC extensions are now recorded.
+ Recorded vendor extensions from Concurrent.
+
+Feb 3, 2004
+ If 'Dwarf_Word' is 64 bits, two macros reading leb numbers
+ fail to initialize upper bits of the values read.
+ First noticed with bogus line numbers printing from dwarfdump.
+ Now we use already-existing functions, avoiding the problem.
+
+Oct 02, 2003
+ Support .debug_loc section fully.
+
+Sept 29, 2003
+ Support DW_FORM_indirect properly.
+ Supports loclists in part (but not multiple loclist entries yet).
+ Support 'padding bytes' at end of .debug_arange and
+ .debug_pubnames and .debug_pubtypes per CU
+ (recent dwarf committee email made it clear this is appropriate).
+
+May 23, 2002
+ Libdwarf now asks for sections only when they are
+ used, so that unneeded sections aren't loaded.
+ Support for using SGI's ELF library as an alternative to
+ using AT&T libelf-style has been added (the SGI ELF
+ library is presently only available internally to SGI).
+
+Jan 10, 2002
+ Fixed memory leak in dwarf_finish().
+
+Aug 21, 2001
+ If one called dwarf_add_file_decl()
+ or dwarf_add_directory_decl() but never added a line,
+ .debug_line was not produced. This was a mistake,
+ as if any file or directory was provided .debug_line
+ should be produced. Now it is produced.
+
+June 14, 2001
+ Given a cu header offset, it was not easy to derive the
+ CU header DIE offset. Created the new
+ function dwarf_get_cu_die_offset_given_cu_header_offset()
+ do get the CU header DIE offset.
+ Added the function dwarf_get_arange_cu_header_offset()
+ so the cu header offset could be retrieved from .debug_aranges
+ information.
+
+June 07, 2001
+ Major bug in dwarf_leb.c decoding large integers
+ (Dwarf_Signed 64 bit where library is compiled in ILP32)
+ found and fixed.
+
+May 21, 2001
+ Some small fixes have been found by various folks,
+ so it seems time to prepare a new source release.
+ See ChangeLog for details.
+
+April 15, 2000
+ The libdwarf copyright has changed to
+ version 2.1 of the GNU Lesser General Public License.
+ Anyone holding a version of libdwarf that was published
+ before this new copyright is allowed to use
+ the copyright published in that earlier libdwarf source
+ on the earlier source
+ or to use
+ this new copyright on the earlier source,
+ at their option.
+
+
+December 08, 1999
+ The dwarf committee has adopted the offset-extension
+ proposal. This allows compatibly emitting
+ dwarf with 64bit offsets.
+
+ The dwarf reader now automatically figures out which is in use.
+ The dwarf writer configures itself at the time the
+ writer initialization routine is called, though
+ the writer is restricted, at libdwarf
+ compile time, to one of
+ mips/sgi pure 32/pure 64 offsets/pointers.
+
+ 32bit offsets only (per dwarf 2.0.0 and cygnus)
+
+ 32bit offsets with extension to 64bit offsets
+ allowed (the offset-extension newly passed).
+
+ In addition, a great deal of duplicate code
+ for the sgi .debug_weaknames, .debug_funcnames,
+ .debug_varnames and .debug_typenames sections has
+ been removed: a single set of functions does the real work now.
+
+Sept 29, 1999
+ Just found out that cygnus is, on 64bit targets, generating
+ 32bit offsets (as elf32 has, for example) with 64 bit
+ pointers (in references to text and data).
+ Whereas sgi has always generated 64bit dwarf with
+ 64 bit offsets (as in elf64) and 64bit pointers for
+ 64bit pointer objects.
+ I'll call the sgi approach 64-bit and the cygnus approach
+ 32bit-offsets.
+
+ Cygnus is following the DWARF2 spec as written, so they are
+ right in doing only 32bit-offsets.
+
+ Folks at sgi (including me) think that, as for elf64,
+ the offsets in dwarf for 64bit pointer-apps should be
+ 64 bits. We think it is only a matter of time
+ before we really *need* 64bit offsets and when that happens
+ it will be on an important app. Disk space is cheap,
+ so lets just go 64 bit on 64bit apps (such as ia64 apps)
+ to avoid a future problem.
+ I(davea@sgi.com) think the 'pointer-size' references in the dwarf
+ spec were really written for 64-bit pointer apps.
+ I don't recall serious consideration of 64bit pointer
+ apps in the committee deliberations (I did miss
+ a couple of meetings) and think 64bit offsets
+ are consistent with dwarf2, even though the speci
+ was not written for such. We think true full 64 bit
+ dwarf2 is the right way to go (the spec changes
+ are obvious: file and section offsets become 64bit
+ with 64bit pointer objects.
+
+ MIPS/SGI is definitely 64-bit offsets for 64 bit objects,
+ cygnus is definitely 32bit-offsets for earlier 64bit pointer
+ environments.
+
+ At any rate, now the dwarf reader allows and accomodates
+ both and the dwarf producer also accomodates both.
+ Some tweaking of the pro_init.c or dwarf_init_finish.c
+ files may be necessary in future: no other changes should
+ be needed to accomodate the two 64bit approaches, as
+ the library (and dwarfdump) now deal with both forms.
+
+
+August 20, 1999
+ Added some #ifndef/#define to pro_util.h to let libdwarf build
+ on more hosts. (since those hosts don't need the producer
+ code, AFAIK, zero values suffice for missing #defines.)
+
+July 21, 1999
+ Now reader transparently reads either-endianness data
+ from an either-endianness object.
+ Updated dwarf.h and libdwarf.h to recognize
+ GNU egcs dwarf extensions and to print the egcs eh_frame
+ section.
+
+June 10, 1999
+ gnu configure version of libdwarf made available for the
+ first time.
+ Still allows only same-endian-as-host in objects.
+
+August, 1994
+ libdwarf source made available for ftp on sgigate.sgi.com
+ /ftp/pub
+
+June, 1994
+ Consumer interface changed completely, following
+ "Candy Machine Interfaces" chapter from
+ "Writing Solid Code" by Steve Maguire (Microsoft Press).
+
+April, 1993
+ Initial version of libdwarf for dwarf version 2
+ written at sgi.
diff --git a/libdwarf/README b/libdwarf/README
new file mode 100644
index 0000000..bf96a58
--- /dev/null
+++ b/libdwarf/README
@@ -0,0 +1,199 @@
+To build libdwarf.a, type
+ ./configure
+ make
+To build libdwarf.so, type
+ ./configure --enable-shared --disable-nonshared
+ make
+To build both, type
+ ./configure --enable-shared
+ make
+
+No real install target is provided here, so 'make install' does
+not do much. One can copy either or both of libdwarf.a libdwarf.so
+to somewhere fairly standard (but intended for software you build)
+like '/usr/local/lib'. Or anywhere else you want to copy it.
+
+To use dwarf or libdwarf, you may want to copy dwarf.h and
+libdwarf.h somewhere convenient (possibly /usr/local/include),
+and you may need to copy the libdwarf to a convenient spot
+(/usr/local/lib is a traditional place for libraries one builds
+oneself on Unix and Linux).
+This copying is not needed to build dwarfdump.
+
+
+Multi Threading, or using threads with libdwarf (Thread Safety):
+ Nothing in libdwarf does any locking. Every Dwarf_Debug
+ (such as returned by dwarf_init()) is fully independent
+ of all other Dwarf_Debug-s. However, calls to libdwarf can
+ change a Dwarf_Debug. So it is unsafe to have two different
+ threads accessing a single Dwarf_Debug simultaneously.
+ It is therefore sufficient to ensure than any one Dwarf_Debug
+ is only accessed from a single thread.
+
+Warnings like
+ "warning: cast from pointer to integer of different size"
+at compile time are to be expected in dwarf_frame.c and
+dwarf_frame2.c. Do not be alarmed.
+
+If your headers are not in the expected places,
+use the make command line to add flags and include directories.
+For example
+ ./configure
+ PREINCS="-I /usr/local/share/include" POSTINCS="-I /home/x/include" make
+PREINCS content is inserted before CFLAGS as make(1) is running.
+POSTINCS content is added after the CFLAGS value.
+
+To set LDFLAGS (which is used when building a .so and
+in building gennames to create some source here),
+do so at configure time, for example:
+ ./configure LDFLAGS="-L /var/tmp"
+Or use PRELIBS and/or POSTLIBS at 'make' time similar to the use
+of PREINCS and POSTINCS.
+
+If you are using the old frame interfaces and depend on
+the use of DW_FRAME_CFA_COL you must add --enable-oldframecol
+to the ./configure options to configure libdwarf.
+See NEWS and libdwarf2.1.mm/pdf .
+
+To generate SGI IRIX 64 bit offsets (in the producer code)
+configure with --enable-dwarf-format-sgi-irix.
+To configure with only 32bit offsets (aka DWARF2) configure
+with --enable-dwarf-format-strict-32bit.
+By default the producer now generates 32bit offsets by default
+but one can turn on DWARF3 64bit offset generation at runtime by ORing
+DW_DLC_OFFSET_SIZE_64 onto the flags in the call to
+dwarf_producer_init() (or dwarf_producer_init_b) [when the
+address size is specified as 64 bit].
+
+Mac OSX (June 2010): Since MacOSX does not use elf, there is no elf.h
+header in the headers provided on MacOSX.
+Use a search engine (like google) to find an elf.h you can use.
+http://www.rockbox.org/tracker/9006?getfile=16683
+might be useful.
+In addition, the archive (ar) program on MacOSX does not
+automatically generate some data so modify the generated
+Makefile to add -s to the options to ar.
+
+To enable dection of Windows pathnames as full paths
+add --enable-windowspath. Doing this does mean things like
+A:foo and \anything are treated as full paths (these are
+unlikely path names on a POSIX system but are legal
+POSIX partial paths).
+
+It is possible to request a shared library (libdwarf.so) build with
+ --enable-shared
+To turn off the build of the archive library (libdwarf.a) specify
+ --disable-nonshared
+but in this case you must specify --enable-shared or nothing will
+build!
+
+TARGET DEPENDENCIES of .debug_frame:
+dwarf.h
+ These should be revised if you have more than the defined
+ 63 'normal' registers. It's not harmful to have these too large!
+ Too small will lead to errors reading .debug_frame and .eh_frame.
+ DW_FRAME_HIGHEST_NORMAL_REGISTER
+ DW_FRAME_LAST_REG_NUM
+
+ These you might revise, but can safely ignore if simply
+ using dwarfdump. If using the producer code you will want
+ to get these exactly right for your architecture.
+ DW_FRAME_RA_COL
+ DW_FRAME_STATIC_LINK
+ DW_FRAME_CFA_COL
+
+libdwarf.h
+ The DW_FRAME_REG_INITIAL_VALUE #define should be set to
+ the value appropriate to your architecture. See libdwarf.h
+ for details.
+
+ If DW_REG_TABLE_SIZE is not set large enough attempts to
+ fill in the .debug_frame tables will get an error.
+ Should be at least as large as DW_FRAME_LAST_REG_NUM.
+ If it's too large nothing is harmed (but some extra space taken
+ at run time).
+
+If your printf does not support C standard %llx etc,
+(such as MSWindows with long long), configure
+option --enable-nonstandardprintf
+and defines like DW_PR_DUx etc in libdwarf.h
+provide a way to configure for that relatively easily.
+
+
+The .debug_frame is so very architecture dependent
+and because the host (where libdwarf/dwarfdump are executed)
+and target (the objects read) could be different.
+It's currently not supported to have dwarfdump/libdwarf determine
+the architecture on-the-fly and do-the-right-thing.
+Just setting DW_FRAME_LAST_REG_NUM and DW_FRAME_HIGHEST_NORMAL_REGISTER
+and DW_REG_TABLE_SIZE high enough will likely suffice for most
+purposes and most compilers/architectures..
+See comments in dwarf.h/libdwarf.h.
+
+It's perfectly safe to ignore the above suggestions as long
+as libdwarf does not get a DW_DLE_DF_REG_NUM_TOO_HIGH error.
+(which would only happen on reading .debug_frame or .eh_frame data).
+
+If you intend to use the libdwarf dwarf-producer code
+for .debug_frame information
+you must do a thorough analysys and revise dwarf.h
+substantially to match the output target architecture.
+
+In general, in the producer code, numbers are copied from and
+to integers with memcpy(). In case of endianness problems,
+constants set in dwarf_producer_init() can fix the problems.
+If one wants to produce a *different-endian* output the best
+solution is to change the integer memcpy calls to call thru a
+new dbg-based function pointer and have it 'do the right thing'
+to adjust endianness. Set the function pointer correctly in
+dwarf_producer_init() and the rest of the code will just call
+thru the function pointer. Tedious work to find and change the
+memcpy calls to be dbg->de_memcpy(), but once done the code is
+no longer endian dependent (right now there is no way to ask
+for cross-endian: a new flag needed or ?).
+
+leb128 numbers are endian-independent, so nothing need be
+done with those for cross-endian support (the storage
+of leb128 on disk is always little-endian).
+
+The .ps files are postscript. So those who cannot deal with mm
+format files but do have a postscript printer (or have
+ghostscript) can print the documents.
+This form was chosen before pdf format existed...
+
+libdwarf2.1.pdf documents a way for a debugger to read dwarf information.
+libdwarf2p.1.pdf documents a way for a compiler to generate dwarf information.
+dwarf.v2.pdf documents Dwarf Version 2.
+index.v2.pdf is an index to dwarf.v2.ps.
+indexDW.v2 is a plain text index of dwarf #defines to dwarf.v2.ps
+mips_extensions.ps documents the mips/sgi extensions to dwarf.
+
+See the Makefile for the commands used to build pdf files
+libdwarf.2.1.pdf and libdwarf1p.1.pdf.
+
+pic is a picture processing tool (ATT command).
+tbl is a table-processing tool.
+(part of Documentor's Work Bench on ATT-like systems).
+tbl and pic are available on linux.
+
+psroff is a name for a troff-like processor, part of
+Documentor's Work Bench on IRIX. Substitute a
+troff-like or nroff-like processor (GNU groff works fine).
+
+The index.v2.mm was generated by the dwarf-document writer
+using some local ATT/USL tools (which neither SGI
+nor the open-source community generally has, so
+there is no way I know of to regenerate this).
+
+To use dwarf or libdwarf, you may want to install dwarf.h and
+libdwarf.h somewhere convenient.
+
+You will also need libelf (libelf.a and/or libelf.so) and
+libelf.h installed. These are available from GNU repositories
+and from the normal Linux repositories for Linux releases.
+On Ubuntu 20/04 for example:
+ sudo apt-get install libelf-dev libelf1
+
+$Source: /home/davea/dwarf/dwarf-working/trunk/libdwarf/README,v $
+$Revision: 1.1 $
+$Date: 2009/11/23 17:15:37 $
diff --git a/libdwarf/bldDWindex.sh b/libdwarf/bldDWindex.sh
new file mode 100644
index 0000000..537d44d
--- /dev/null
+++ b/libdwarf/bldDWindex.sh
@@ -0,0 +1,24 @@
+sed -n -e '/^%%Page.*/p' -e '/.*DW_.*/p' <dwarf.v2.ps |
+sed -n -e '/^%%Page.*/p' -e 's/.*\(DW_[a-z_A-Z]*\).*/\1/p' |
+nawk ' /^%%Page/{ p = $2 } \
+ /DW_/ { printf "%-30s %04d \n",$1,p \
+ }' | sort -u |
+nawk ' BEGIN {h = "xx"} \
+ { \
+ done = 0 ; \
+ if ( $1 != h ) { \
+ if(h != "xx") { \
+ printf "%-30s %s\n",h, pgs ; \
+ h = $1 ; \
+ tv = $2 + 0 ; \
+ done = 1 ; \
+ pgs = "" tv \
+ } \
+ } \
+ h = $1 ; \
+ if(done == 0 ) { \
+ tv = $2 + 0 ; \
+ pgs = pgs ", " tv \
+ } \
+ } \
+ END { printf "%-30s %s\n",h,pgs } '
diff --git a/libdwarf/cmplrs/dwarf_addr_finder.h b/libdwarf/cmplrs/dwarf_addr_finder.h
new file mode 100644
index 0000000..0eda6d1
--- /dev/null
+++ b/libdwarf/cmplrs/dwarf_addr_finder.h
@@ -0,0 +1,55 @@
+/*
+ dwarf_addr_finder.h
+ $Source: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/include/cmplrs/RCS/dwarf_addr_finder.h,v $
+ $Date: 2002/06/11 17:49:06 $
+
+ Defines user interface.
+
+*/
+
+/* return codes for functions
+*/
+#define DW_DLV_NO_ENTRY -1
+#define DW_DLV_OK 0
+#define DW_DLV_ERROR 1
+
+
+/* the following are the 'section' number passed to the called-back
+ function.
+ The called-back application must translate this to the
+ appropriate elf section number/pointer.
+
+ Putting this burden on the application avoids having to store
+ the numbers in the Dwarf_Debug structure (thereby saving space
+ for most consumers).
+*/
+#define DW_SECTION_INFO 0
+#define DW_SECTION_FRAME 1
+#define DW_SECTION_ARANGES 2
+#define DW_SECTION_LINE 3
+#define DW_SECTION_LOC 4 /* .debug_loc */
+
+/* section is one of the above codes: it specifies a section.
+ secoff is the offset in the dwarf section.
+ existingAddr is the value at the specified offset (so the
+ called back routine can sanity check the proceedings).
+ It's up to the caller to know the size of an address (4 or 8)
+ and update the right number of bytes.
+*/
+typedef int (*Dwarf_addr_callback_func) (int /*section*/,
+ Dwarf_Off /*secoff*/, Dwarf_Addr /*existingAddr*/);
+
+/* call this to do the work: it calls back thru cb_func
+ once per each address to be modified.
+ Once this returns you are done.
+ Returns DW_DLV_OK if finished ok.
+ Returns DW_DLV_ERROR if there was some kind of error, in which
+ the dwarf error number was passed back thu the dwerr ptr.
+ Returns DW_DLV_NO_ENTRY if there are no relevant dwarf sections,
+ so there were no addresses to be modified (and none
+ called back).
+*/
+int _dwarf_addr_finder(dwarf_elf_handle elf_file_ptr,
+ Dwarf_addr_callback_func cb_func,
+ int *dwerr);
+
diff --git a/libdwarf/common.c b/libdwarf/common.c
new file mode 100644
index 0000000..8e93197
--- /dev/null
+++ b/libdwarf/common.c
@@ -0,0 +1,71 @@
+/*
+ Copyright (C) 2008-2010 SN Systems. All Rights Reserved.
+ Portions Copyright (C) 2008-2010 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+#include "common.h"
+
+void
+print_version(const char * name)
+{
+#ifdef _DEBUG
+ char *acType = "Debug";
+#else
+ char *acType = "Release";
+#endif /* _DEBUG */
+
+ char acVersion[60];
+ snprintf(acVersion,sizeof(acVersion),"[%s %s %s]",
+ __DATE__,__TIME__,acType);
+ printf("%s %s\n",name,acVersion);
+}
+
+void
+print_args(int argc, char *argv[])
+{
+ int index;
+ printf("Arguments: ");
+ for (index = 1; index < argc; ++index) {
+ printf("%s ",argv[index]);
+ }
+ printf("\n");
+}
+
+void
+print_usage_message(const char *options[])
+{
+ int index;
+ for (index = 0; *options[index]; ++index) {
+ printf("%s\n",options[index]);
+ }
+}
diff --git a/libdwarf/common.h b/libdwarf/common.h
new file mode 100644
index 0000000..ab26b20
--- /dev/null
+++ b/libdwarf/common.h
@@ -0,0 +1,47 @@
+/*
+ Copyright (C) 2009-2010 SN Systems. All Rights Reserved.
+ Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+#ifndef common_INCLUDED
+#define common_INCLUDED
+
+#include <stdio.h>
+
+
+void print_args(int argc, char *argv[]);
+void print_usage_message(const char *options[]);
+void print_version(const char * name);
+
+#endif /* common_INCLUDED */
diff --git a/libdwarf/config.h.in b/libdwarf/config.h.in
new file mode 100644
index 0000000..895c15e
--- /dev/null
+++ b/libdwarf/config.h.in
@@ -0,0 +1,143 @@
+/* config.h.in. Generated from configure.in by autoheader. */
+
+/* Define if building universal (internal helper macro) */
+#undef AC_APPLE_UNIVERSAL_BUILD
+
+/* Define to 1 if you have the <alloca.h> header file. */
+#undef HAVE_ALLOCA_H
+
+/* Define 1 if want to allow producer to build with 32/64bit section offsets
+ per dwarf3 */
+#undef HAVE_DWARF2_99_EXTENSION
+
+/* Define to 1 if the elf64_getehdr function is in libelf.a. */
+#undef HAVE_ELF64_GETEHDR
+
+/* Define to 1 if the elf64_getshdr function is in libelf.a. */
+#undef HAVE_ELF64_GETSHDR
+
+/* Define 1 if Elf64_Rela defined. */
+#undef HAVE_ELF64_RELA
+
+/* Define 1 if Elf64_Sym defined. */
+#undef HAVE_ELF64_SYM
+
+/* Define to 1 if you have the <elfaccess.h> header file. */
+#undef HAVE_ELFACCESS_H
+
+/* Define to 1 if you have the <elf.h> header file. */
+#undef HAVE_ELF_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <libelf.h> header file. */
+#undef HAVE_LIBELF_H
+
+/* Define to 1 if you have the <libelf/libelf.h> header file. */
+#undef HAVE_LIBELF_LIBELF_H
+
+/* Define 1 if off64 is defined via libelf with GNU_SOURCE. */
+#undef HAVE_LIBELF_OFF64_OK
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define 1 if need nonstandard printf format for 64bit */
+#undef HAVE_NONSTANDARD_PRINTF_64_FORMAT
+
+/* Define 1 to default to old DW_FRAME_CFA_COL */
+#undef HAVE_OLD_FRAME_CFA_COL
+
+/* Define 1 if plain libelf builds. */
+#undef HAVE_RAW_LIBELF_OK
+
+/* Define 1 if R_IA_64_DIR32LSB is defined (might be enum value). */
+#undef HAVE_R_IA_64_DIR32LSB
+
+/* Define 1 if want producer to build with IRIX offset sizes */
+#undef HAVE_SGI_IRIX_OFFSETS
+
+/* Define 1 if we have the Windows specific header stdafx.h */
+#undef HAVE_STDAFX_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define 1 if want producer to build with only 32bit section offsets */
+#undef HAVE_STRICT_DWARF2_32BIT_OFFSET
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/ia64/elf.h> header file. */
+#undef HAVE_SYS_IA64_ELF_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define 1 if want to allow Windows full path detection */
+#undef HAVE_WINDOWS_PATH
+
+/* See if __uint32_t is predefined in the compiler. */
+#undef HAVE___UINT32_T
+
+/* Define 1 if __uint32_t is in sgidefs.h. */
+#undef HAVE___UINT32_T_IN_SGIDEFS_H
+
+/* Define 1 if sys/types.h defines __uint32_t. */
+#undef HAVE___UINT32_T_IN_SYS_TYPES_H
+
+/* See if __uint64_t is predefined in the compiler. */
+#undef HAVE___UINT64_T
+
+/* Define 1 if is in sgidefs.h. */
+#undef HAVE___UINT64_T_IN_SGIDEFS_H
+
+/* Define 1 if sys/types.h defines __uint64_t. */
+#undef HAVE___UINT64_T_IN_SYS_TYPES_H
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+ significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+# define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+# undef WORDS_BIGENDIAN
+# endif
+#endif
diff --git a/libdwarf/configure b/libdwarf/configure
new file mode 100755
index 0000000..900b80a
--- /dev/null
+++ b/libdwarf/configure
@@ -0,0 +1,5480 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.67.
+#
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+# Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ # We cannot yet assume a decent shell, so we have to provide a
+ # neutralization value for shells without unset; and this also
+ # works around shells that cannot unset nonexistent variables.
+ BASH_ENV=/dev/null
+ ENV=/dev/null
+ (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -p'
+ fi
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+PACKAGE_URL=
+
+ac_unique_file="libdwarf.h"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+dwarf_namestable
+build_nonshared
+dwfpic
+build_shared
+AR
+RANLIB
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+EGREP
+GREP
+CPP
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_shared
+enable_nonshared
+enable_namestable
+enable_nonstandardprintf
+enable_windowspath
+enable_oldframecol
+enable_dwarf_format_sgi_irix
+enable_dwarf_format_strict_32bit
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used" >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-option-checking ignore unrecognized --enable/--with options
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --enable-shared build shared library libdwarf.so
+ --disable-nonshared do not build archive library libdwarf.a
+ --enable-namestable Name string functions implemented as binary search
+ (default is with C switch)
+ --enable-nonstandardprintf
+ Use a special printf format for 64bit (default is
+ NO)
+ --enable-windowspath Detect certain Windows paths as full paths (default
+ is NO)
+ --enable-oldframecol Use HAVE_OLD_FRAME_CFA_COL (default is to use new
+ DW_FRAME_CFA_COL3)
+ --enable-dwarf-format-sgi-irix
+ Force producer to SGI IRIX offset dwarf.
+ --enable-dwarf-format-strict-32bit
+ Force producer to generate only DWARF format 32bit.
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.67
+
+Copyright (C) 2010 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: program exited with status $ac_status" >&5
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=$ac_status
+fi
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval "test \"\${$3+set}\"" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if eval "test \"\${$3+set}\"" = set; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval "test \"\${$3+set}\"" = set; then :
+ $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_header_compiler=yes
+else
+ ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ ac_header_preproc=yes
+else
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+ yes:no: )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+ no:yes:* )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval "test \"\${$3+set}\"" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ $as_test_x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.67. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5 ; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5 ; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+if test -z "$ac_file"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5 ; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5 ; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5 ; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if test "${ac_cv_objext+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5 ; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if test "${ac_cv_prog_CPP+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5 ; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_stdc=yes
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then :
+ :
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
+$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
+if test "${ac_cv_c_bigendian+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_c_bigendian=unknown
+ # See if we're dealing with a universal compiler.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifndef __APPLE_CC__
+ not a universal capable compiler
+ #endif
+ typedef int dummy;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ # Check for potential -arch flags. It is not universal unless
+ # there are at least two -arch flags with different values.
+ ac_arch=
+ ac_prev=
+ for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
+ if test -n "$ac_prev"; then
+ case $ac_word in
+ i?86 | x86_64 | ppc | ppc64)
+ if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then
+ ac_arch=$ac_word
+ else
+ ac_cv_c_bigendian=universal
+ break
+ fi
+ ;;
+ esac
+ ac_prev=
+ elif test "x$ac_word" = "x-arch"; then
+ ac_prev=arch
+ fi
+ done
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ if test $ac_cv_c_bigendian = unknown; then
+ # See if sys/param.h defines the BYTE_ORDER macro.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/param.h>
+
+int
+main ()
+{
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
+ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
+ && LITTLE_ENDIAN)
+ bogus endian macros
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ # It does; now see whether it defined to BIG_ENDIAN or not.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_bigendian=yes
+else
+ ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ if test $ac_cv_c_bigendian = unknown; then
+ # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+
+int
+main ()
+{
+#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
+ bogus endian macros
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ # It does; now see whether it defined to _BIG_ENDIAN or not.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+
+int
+main ()
+{
+#ifndef _BIG_ENDIAN
+ not big endian
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_bigendian=yes
+else
+ ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ if test $ac_cv_c_bigendian = unknown; then
+ # Compile a test program.
+ if test "$cross_compiling" = yes; then :
+ # Try to guess by grepping values from an object file.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+short int ascii_mm[] =
+ { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+ short int ascii_ii[] =
+ { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+ int use_ascii (int i) {
+ return ascii_mm[i] + ascii_ii[i];
+ }
+ short int ebcdic_ii[] =
+ { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+ short int ebcdic_mm[] =
+ { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+ int use_ebcdic (int i) {
+ return ebcdic_mm[i] + ebcdic_ii[i];
+ }
+ extern int foo;
+
+int
+main ()
+{
+return use_ascii (foo) == use_ebcdic (foo);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
+ ac_cv_c_bigendian=yes
+ fi
+ if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+ if test "$ac_cv_c_bigendian" = unknown; then
+ ac_cv_c_bigendian=no
+ else
+ # finding both strings is unlikely to happen, but who knows?
+ ac_cv_c_bigendian=unknown
+ fi
+ fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+
+ /* Are we little or big endian? From Harbison&Steele. */
+ union
+ {
+ long int l;
+ char c[sizeof (long int)];
+ } u;
+ u.l = 1;
+ return u.c[sizeof (long int) - 1] == 1;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_c_bigendian=no
+else
+ ac_cv_c_bigendian=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
+$as_echo "$ac_cv_c_bigendian" >&6; }
+ case $ac_cv_c_bigendian in #(
+ yes)
+ $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h
+;; #(
+ no)
+ ;; #(
+ universal)
+
+$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
+
+ ;; #(
+ *)
+ as_fn_error $? "unknown endianness
+ presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
+ esac
+
+if test $ac_cv_c_compiler_gnu = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC needs -traditional" >&5
+$as_echo_n "checking whether $CC needs -traditional... " >&6; }
+if test "${ac_cv_prog_gcc_traditional+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_pattern="Autoconf.*'x'"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sgtty.h>
+Autoconf TIOCGETP
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "$ac_pattern" >/dev/null 2>&1; then :
+ ac_cv_prog_gcc_traditional=yes
+else
+ ac_cv_prog_gcc_traditional=no
+fi
+rm -f conftest*
+
+
+ if test $ac_cv_prog_gcc_traditional = no; then
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <termio.h>
+Autoconf TCGETA
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "$ac_pattern" >/dev/null 2>&1; then :
+ ac_cv_prog_gcc_traditional=yes
+fi
+rm -f conftest*
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_gcc_traditional" >&5
+$as_echo "$ac_cv_prog_gcc_traditional" >&6; }
+ if test $ac_cv_prog_gcc_traditional = yes; then
+ CC="$CC -traditional"
+ fi
+fi
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+ ./ | .// | /[cC]/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ rm -rf conftest.one conftest.two conftest.dir
+ echo one > conftest.one
+ echo two > conftest.two
+ mkdir conftest.dir
+ if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+ test -s conftest.one && test -s conftest.two &&
+ test -s conftest.dir/conftest.one &&
+ test -s conftest.dir/conftest.two
+ then
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+
+ done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_RANLIB+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_AR+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+ ac_ct_AR=$AR
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_AR+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_AR="ar"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_AR" = x; then
+ AR=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ AR=$ac_ct_AR
+ fi
+else
+ AR="$ac_cv_prog_AR"
+fi
+
+
+
+for ac_header in alloca.h elf.h elfaccess.h libelf.h libelf/libelf.h sys/types.h sys/ia64/elf.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for elf64_getehdr in -lelf" >&5
+$as_echo_n "checking for elf64_getehdr in -lelf... " >&6; }
+if test "${ac_cv_lib_elf_elf64_getehdr+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lelf $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char elf64_getehdr ();
+int
+main ()
+{
+return elf64_getehdr ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_elf_elf64_getehdr=yes
+else
+ ac_cv_lib_elf_elf64_getehdr=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_elf_elf64_getehdr" >&5
+$as_echo "$ac_cv_lib_elf_elf64_getehdr" >&6; }
+if test "x$ac_cv_lib_elf_elf64_getehdr" = x""yes; then :
+
+$as_echo "#define HAVE_ELF64_GETEHDR 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for elf64_getshdr in -lelf" >&5
+$as_echo_n "checking for elf64_getshdr in -lelf... " >&6; }
+if test "${ac_cv_lib_elf_elf64_getshdr+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lelf $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char elf64_getshdr ();
+int
+main ()
+{
+return elf64_getshdr ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_elf_elf64_getshdr=yes
+else
+ ac_cv_lib_elf_elf64_getshdr=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_elf_elf64_getshdr" >&5
+$as_echo "$ac_cv_lib_elf_elf64_getshdr" >&6; }
+if test "x$ac_cv_lib_elf_elf64_getshdr" = x""yes; then :
+
+$as_echo "#define HAVE_ELF64_GETSHDR 1" >>confdefs.h
+
+fi
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+__uint32_t p; p = 3;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE___UINT32_T 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+__uint64_t p; p = 3;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE___UINT64_T 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+int
+main ()
+{
+ __uint32_t p; p = 3;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE___UINT32_T_IN_SYS_TYPES_H 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+int
+main ()
+{
+ __uint64_t p; p = 3;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE___UINT64_T_IN_SYS_TYPES_H 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <elf.h>
+int
+main ()
+{
+ int p; p = R_IA_64_DIR32LSB;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE_R_IA_64_DIR32LSB 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <libelf.h>
+
+int
+main ()
+{
+ int p; p = 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE_RAW_LIBELF_OK 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#define _GNU_SOURCE
+#include <libelf.h>
+
+int
+main ()
+{
+ off64_t p; p = 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE_LIBELF_OFF64_OK 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sgidefs.h>
+int
+main ()
+{
+ __uint32_t p; p = 27;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE___UINT32_T_IN_SGIDEFS_H 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sgidefs.h>
+int
+main ()
+{
+ __uint64_t p; p = 27;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE___UINT64_T_IN_SGIDEFS_H 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sgidefs.h>
+int
+main ()
+{
+ __uint64_t p; p = 27;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE___UINT64_T_IN_SGIDEFS_H 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <elf.h>
+int
+main ()
+{
+ Elf64_Rela p; p.r_offset = 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE_ELF64_RELA 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <elf.h>
+int
+main ()
+{
+ Elf64_Sym p; p.st_info = 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE_ELF64_SYM 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+
+build_shared=none
+
+
+# Check whether --enable-shared was given.
+if test "${enable_shared+set}" = set; then :
+ enableval=$enable_shared;
+fi
+
+if test "x$enable_shared" = "xyes"; then :
+
+ build_shared=libdwarf.so
+
+ dwfpic=-fPIC
+
+
+fi
+
+build_nonshared=libdwarf.a
+
+# Check whether --enable-nonshared was given.
+if test "${enable_nonshared+set}" = set; then :
+ enableval=$enable_nonshared;
+fi
+
+if test "x$enable_nonshared" = "xno"; then :
+
+ build_nonshared=none
+
+
+fi
+
+
+dwarf_namestable=-s
+
+# Check whether --enable-namestable was given.
+if test "${enable_namestable+set}" = set; then :
+ enableval=$enable_namestable; dwarf_namestable=-s
+
+ dwarf_namestable=-t
+
+fi
+
+
+# Check whether --enable-nonstandardprintf was given.
+if test "${enable_nonstandardprintf+set}" = set; then :
+ enableval=$enable_nonstandardprintf;
+$as_echo "#define HAVE_NONSTANDARD_PRINTF_64_FORMAT 1" >>confdefs.h
+
+fi
+
+
+# Check whether --enable-windowspath was given.
+if test "${enable_windowspath+set}" = set; then :
+ enableval=$enable_windowspath;
+$as_echo "#define HAVE_WINDOWS_PATH 1" >>confdefs.h
+
+fi
+
+
+# Check whether --enable-oldframecol was given.
+if test "${enable_oldframecol+set}" = set; then :
+ enableval=$enable_oldframecol;
+$as_echo "#define HAVE_OLD_FRAME_CFA_COL 1" >>confdefs.h
+
+fi
+
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include "stdafx.h"
+int
+main ()
+{
+ int p; p = 27;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE_STDAFX_H 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+# Check whether --enable-dwarf_format_sgi_irix was given.
+if test "${enable_dwarf_format_sgi_irix+set}" = set; then :
+ enableval=$enable_dwarf_format_sgi_irix;
+$as_echo "#define HAVE_SGI_IRIX_OFFSETS 1" >>confdefs.h
+
+else
+ # Check whether --enable-dwarf_format_strict_32bit was given.
+if test "${enable_dwarf_format_strict_32bit+set}" = set; then :
+ enableval=$enable_dwarf_format_strict_32bit;
+$as_echo "#define HAVE_STRICT_DWARF2_32BIT_OFFSET 1" >>confdefs.h
+
+else
+
+$as_echo "#define HAVE_DWARF2_99_EXTENSION 1" >>confdefs.h
+
+fi
+
+fi
+
+
+ac_config_files="$ac_config_files Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ test "x$cache_file" != "x/dev/null" &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ cat confcache >$cache_file
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -p'
+ fi
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.67. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.67,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2010 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+ --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp=
+ trap 'exit_status=$?
+ { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+ ac_t=`sed -n "/$ac_delim/p" confdefs.h`
+ if test -z "$ac_t"; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any. Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[ ]*#[ ]*define[ ][ ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ for (key in D) D_is_set[key] = 1
+ FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+ line = \$ 0
+ split(line, arg, " ")
+ if (arg[1] == "#") {
+ defundef = arg[2]
+ mac1 = arg[3]
+ } else {
+ defundef = substr(arg[1], 2)
+ mac1 = arg[2]
+ }
+ split(mac1, mac2, "(") #)
+ macro = mac2[1]
+ prefix = substr(line, 1, index(line, defundef) - 1)
+ if (D_is_set[macro]) {
+ # Preserve the white space surrounding the "#".
+ print prefix "define", macro P[macro] D[macro]
+ next
+ } else {
+ # Replace #undef with comments. This is necessary, for example,
+ # in the case of _POSIX_SOURCE, which is predefined and required
+ # on some systems where configure will not decide to define it.
+ if (defundef == "undef") {
+ print "/*", prefix defundef, macro, "*/"
+ next
+ }
+ }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS "
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5 ;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5 ;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$tmp/stdin"
+ case $ac_file in
+ -) cat "$tmp/out" && rm -f "$tmp/out";;
+ *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+ if test x"$ac_file" != x-; then
+ {
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs"
+ } >"$tmp/config.h" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f "$ac_file"
+ mv "$tmp/config.h" "$ac_file" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ fi
+ else
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \
+ || as_fn_error $? "could not create -" "$LINENO" 5
+ fi
+ ;;
+
+
+ esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/libdwarf/configure.in b/libdwarf/configure.in
new file mode 100644
index 0000000..c8770f3
--- /dev/null
+++ b/libdwarf/configure.in
@@ -0,0 +1,134 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(libdwarf.h)
+AC_CONFIG_HEADER(config.h)
+
+AC_PROG_CC
+AC_C_BIGENDIAN
+AC_GCC_TRADITIONAL
+AC_PROG_INSTALL
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+AC_CHECK_TOOL(AR, ar)
+
+dnl AC_ARFLAGS
+
+AC_CHECK_HEADERS(alloca.h elf.h elfaccess.h libelf.h libelf/libelf.h sys/types.h sys/ia64/elf.h)
+
+AC_CHECK_LIB(elf,elf64_getehdr,
+ AC_DEFINE(HAVE_ELF64_GETEHDR,1,
+ [Define to 1 if the elf64_getehdr function is in libelf.a.]))
+AC_CHECK_LIB(elf,elf64_getshdr,
+ AC_DEFINE(HAVE_ELF64_GETSHDR,1,
+ [Define to 1 if the elf64_getshdr function is in libelf.a.]))
+AC_TRY_COMPILE( , __uint32_t p; p = 3; ,AC_DEFINE(HAVE___UINT32_T,1,
+ [See if __uint32_t is predefined in the compiler.]))
+AC_TRY_COMPILE( , __uint64_t p; p = 3; ,AC_DEFINE(HAVE___UINT64_T,1,
+ [See if __uint64_t is predefined in the compiler.]))
+AC_TRY_COMPILE([#include <sys/types.h>],[ __uint32_t p; p = 3;] ,
+ AC_DEFINE(HAVE___UINT32_T_IN_SYS_TYPES_H,1,
+ [Define 1 if sys/types.h defines __uint32_t.]))
+AC_TRY_COMPILE([#include <sys/types.h>],[ __uint64_t p; p = 3;] ,
+ AC_DEFINE(HAVE___UINT64_T_IN_SYS_TYPES_H,1,
+ [Define 1 if sys/types.h defines __uint64_t.]))
+dnl checking for ia 64 types, which might be enums, using HAVE_R_IA_64_DIR32LSB
+dnl to stand in for a small set.
+AC_TRY_COMPILE([#include <elf.h>],[ int p; p = R_IA_64_DIR32LSB;] ,
+ AC_DEFINE(HAVE_R_IA_64_DIR32LSB,1,
+ [Define 1 if R_IA_64_DIR32LSB is defined (might be enum value).]))
+
+AC_TRY_COMPILE([
+#include <libelf.h>
+],[ int p; p = 0; ] ,
+ AC_DEFINE(HAVE_RAW_LIBELF_OK,1,
+ [Define 1 if plain libelf builds.]))
+AC_TRY_COMPILE([
+#define _GNU_SOURCE
+#include <libelf.h>
+],[ off64_t p; p = 0;] ,
+ AC_DEFINE(HAVE_LIBELF_OFF64_OK,1,
+ [Define 1 if off64 is defined via libelf with GNU_SOURCE.]))
+
+dnl the existence of sgidefs.h does not prove it's truly SGI, nor
+dnl prove that __uint32_t or __uint64_t is defined therein.
+AC_TRY_COMPILE([#include <sgidefs.h>],[ __uint32_t p; p = 27;] ,
+ AC_DEFINE(HAVE___UINT32_T_IN_SGIDEFS_H,1,
+ [Define 1 if __uint32_t is in sgidefs.h.]))
+AC_TRY_COMPILE([#include <sgidefs.h>],[ __uint64_t p; p = 27;] ,
+ AC_DEFINE(HAVE___UINT64_T_IN_SGIDEFS_H,1,
+ [Define 1 if __uint64_t is in sgidefs.h.]))
+AC_TRY_COMPILE([#include <sgidefs.h>],[ __uint64_t p; p = 27;] ,
+ AC_DEFINE(HAVE___UINT64_T_IN_SGIDEFS_H,1,
+ [Define 1 if is in sgidefs.h.]))
+AC_TRY_COMPILE([#include <elf.h>],[ Elf64_Rela p; p.r_offset = 1; ],
+ AC_DEFINE(HAVE_ELF64_RELA,1,
+ [Define 1 if Elf64_Rela defined.]))
+AC_TRY_COMPILE([#include <elf.h>],[ Elf64_Sym p; p.st_info = 1; ],
+ AC_DEFINE(HAVE_ELF64_SYM,1,
+ [Define 1 if Elf64_Sym defined.]))
+
+
+
+dnl default-disabled shared
+AC_SUBST(build_shared,[none])
+AC_SUBST(dwfpic,[])
+AC_ARG_ENABLE(shared,AC_HELP_STRING([--enable-shared],
+ [build shared library libdwarf.so]))
+AS_IF([ test "x$enable_shared" = "xyes"], [
+ AC_SUBST(build_shared,[libdwarf.so])
+ AC_SUBST(dwfpic,[-fPIC])
+])
+
+dnl default-enabled nonshared
+AC_SUBST(build_nonshared,[libdwarf.a])
+AC_ARG_ENABLE(nonshared,AC_HELP_STRING([--disable-nonshared],
+ [do not build archive library libdwarf.a]))
+AS_IF([ test "x$enable_nonshared" = "xno"], [
+ dnl We could turn on shared here if not already on.
+ AC_SUBST(build_nonshared,[none])
+])
+
+
+dnl This changes the gennames option from -s to -t
+AC_SUBST(dwarf_namestable,[-s])
+AC_ARG_ENABLE(namestable,AC_HELP_STRING([--enable-namestable],
+ [Name string functions implemented as binary search (default is with C switch)]),
+ [ AC_SUBST(dwarf_namestable,[-s]) ]
+ [ AC_SUBST(dwarf_namestable,[-t]) ])
+
+AC_ARG_ENABLE(nonstandardprintf,AS_HELP_STRING([--enable-nonstandardprintf],
+ [Use a special printf format for 64bit (default is NO)]),
+ [ AC_DEFINE([HAVE_NONSTANDARD_PRINTF_64_FORMAT],[1],
+ [Define 1 if need nonstandard printf format for 64bit] )],
+ [])
+
+AC_ARG_ENABLE(windowspath,AC_HELP_STRING([--enable-windowspath],
+ [Detect certain Windows paths as full paths (default is NO)]),
+ [ AC_DEFINE([HAVE_WINDOWS_PATH],[1],
+ [Define 1 if want to allow Windows full path detection] )],
+ [])
+
+AC_ARG_ENABLE(oldframecol,AC_HELP_STRING([--enable-oldframecol],
+ [Use HAVE_OLD_FRAME_CFA_COL (default is to use new DW_FRAME_CFA_COL3)]),
+ [ AC_DEFINE([HAVE_OLD_FRAME_CFA_COL],[1],
+ [Define 1 to default to old DW_FRAME_CFA_COL] )],
+ [])
+
+AC_TRY_COMPILE([#include "stdafx.h"],[ int p; p = 27;] ,
+ AC_DEFINE(HAVE_STDAFX_H,1,
+ [Define 1 if we have the Windows specific header stdafx.h]))
+
+dnl See pro_init(), HAVE_DWARF2_99_EXTENSION also generates
+dnl 32bit offset dwarf unless DW_DLC_OFFSET_SIZE_64 flag passed to
+dnl pro_init.
+AC_ARG_ENABLE(dwarf_format_sgi_irix, AC_HELP_STRING([--enable-dwarf-format-sgi-irix],
+ [Force producer to SGI IRIX offset dwarf.]),
+ [AC_DEFINE(HAVE_SGI_IRIX_OFFSETS,1,
+ [Define 1 if want producer to build with IRIX offset sizes] )],
+
+ [AC_ARG_ENABLE(dwarf_format_strict_32bit, AC_HELP_STRING([--enable-dwarf-format-strict-32bit],
+ [Force producer to generate only DWARF format 32bit.]),
+ [AC_DEFINE(HAVE_STRICT_DWARF2_32BIT_OFFSET,1,
+ [Define 1 if want producer to build with only 32bit section offsets] )],
+ [AC_DEFINE(HAVE_DWARF2_99_EXTENSION,1,
+ [Define 1 if want to allow producer to build with 32/64bit section offsets per dwarf3] )])])
+
+AC_OUTPUT(Makefile)
diff --git a/libdwarf/dwarf.h b/libdwarf/dwarf.h
new file mode 100644
index 0000000..92c36e9
--- /dev/null
+++ b/libdwarf/dwarf.h
@@ -0,0 +1,1182 @@
+/*
+ Copyright (C) 2000,2001,2003,2004,2005,2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2007-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+#ifndef __DWARF_H
+#define __DWARF_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ dwarf.h DWARF debugging information values
+ $Revision: 1.41 $ $Date: 2006/04/17 00:09:56 $
+
+ The comment "DWARF3" appears where there are
+ new entries from DWARF3 as of 2004, "DWARF3f"
+ where there are new entries as of the November 2005
+ public review document and other comments apply
+ where extension entries appear.
+
+ Extensions part of DWARF4 are marked DWARF4.
+
+ A few extension names have omitted the 'vendor id'
+ (See chapter 7, "Vendor Extensibility"). Please
+ always use a 'vendor id' string in extension names.
+
+ Vendors should use a vendor string in names and
+ whereever possible avoid duplicating values used by
+ other vendor extensions
+*/
+
+
+#define DW_TAG_array_type 0x01
+#define DW_TAG_class_type 0x02
+#define DW_TAG_entry_point 0x03
+#define DW_TAG_enumeration_type 0x04
+#define DW_TAG_formal_parameter 0x05
+#define DW_TAG_imported_declaration 0x08
+#define DW_TAG_label 0x0a
+#define DW_TAG_lexical_block 0x0b
+#define DW_TAG_member 0x0d
+#define DW_TAG_pointer_type 0x0f
+#define DW_TAG_reference_type 0x10
+#define DW_TAG_compile_unit 0x11
+#define DW_TAG_string_type 0x12
+#define DW_TAG_structure_type 0x13
+#define DW_TAG_subroutine_type 0x15
+#define DW_TAG_typedef 0x16
+#define DW_TAG_union_type 0x17
+#define DW_TAG_unspecified_parameters 0x18
+#define DW_TAG_variant 0x19
+#define DW_TAG_common_block 0x1a
+#define DW_TAG_common_inclusion 0x1b
+#define DW_TAG_inheritance 0x1c
+#define DW_TAG_inlined_subroutine 0x1d
+#define DW_TAG_module 0x1e
+#define DW_TAG_ptr_to_member_type 0x1f
+#define DW_TAG_set_type 0x20
+#define DW_TAG_subrange_type 0x21
+#define DW_TAG_with_stmt 0x22
+#define DW_TAG_access_declaration 0x23
+#define DW_TAG_base_type 0x24
+#define DW_TAG_catch_block 0x25
+#define DW_TAG_const_type 0x26
+#define DW_TAG_constant 0x27
+#define DW_TAG_enumerator 0x28
+#define DW_TAG_file_type 0x29
+#define DW_TAG_friend 0x2a
+#define DW_TAG_namelist 0x2b
+ /* Early releases of this header had the following
+ misspelled with a trailing 's' */
+#define DW_TAG_namelist_item 0x2c /* DWARF3/2 spelling */
+#define DW_TAG_namelist_items 0x2c /* SGI misspelling/typo */
+#define DW_TAG_packed_type 0x2d
+#define DW_TAG_subprogram 0x2e
+ /* The DWARF2 document had two spellings of the following
+ two TAGs, DWARF3 specifies the longer spelling. */
+#define DW_TAG_template_type_parameter 0x2f /* DWARF3/2 spelling*/
+#define DW_TAG_template_type_param 0x2f /* DWARF2 spelling*/
+#define DW_TAG_template_value_parameter 0x30 /* DWARF3/2 spelling*/
+#define DW_TAG_template_value_param 0x30 /* DWARF2 spelling*/
+#define DW_TAG_thrown_type 0x31
+#define DW_TAG_try_block 0x32
+#define DW_TAG_variant_part 0x33
+#define DW_TAG_variable 0x34
+#define DW_TAG_volatile_type 0x35
+#define DW_TAG_dwarf_procedure 0x36 /* DWARF3 */
+#define DW_TAG_restrict_type 0x37 /* DWARF3 */
+#define DW_TAG_interface_type 0x38 /* DWARF3 */
+#define DW_TAG_namespace 0x39 /* DWARF3 */
+#define DW_TAG_imported_module 0x3a /* DWARF3 */
+#define DW_TAG_unspecified_type 0x3b /* DWARF3 */
+#define DW_TAG_partial_unit 0x3c /* DWARF3 */
+#define DW_TAG_imported_unit 0x3d /* DWARF3 */
+ /* Do not use DW_TAG_mutable_type */
+#define DW_TAG_mutable_type 0x3e /* Withdrawn from DWARF3 by DWARF3f. */
+#define DW_TAG_condition 0x3f /* DWARF3f */
+#define DW_TAG_shared_type 0x40 /* DWARF3f */
+#define DW_TAG_type_unit 0x41 /* DWARF4 */
+#define DW_TAG_rvalue_reference_type 0x42 /* DWARF4 */
+#define DW_TAG_template_alias 0x43 /* DWARF4 */
+#define DW_TAG_lo_user 0x4080
+
+#define DW_TAG_MIPS_loop 0x4081
+
+/* HP extensions: ftp://ftp.hp.com/pub/lang/tools/WDB/wdb-4.0.tar.gz */
+#define DW_TAG_HP_array_descriptor 0x4090 /* HP */
+
+/* GNU extensions. The first 3 missing the GNU_. */
+#define DW_TAG_format_label 0x4101 /* GNU. Fortran. */
+#define DW_TAG_function_template 0x4102 /* GNU. For C++ */
+#define DW_TAG_class_template 0x4103 /* GNU. For C++ */
+#define DW_TAG_GNU_BINCL 0x4104 /* GNU */
+#define DW_TAG_GNU_EINCL 0x4105 /* GNU */
+
+/* GNU extension. http://gcc.gnu.org/wiki/TemplateParmsDwarf */
+#define DW_TAG_GNU_template_template_parameter 0x4106 /* GNU */
+#define DW_TAG_GNU_template_template_param 0x4106 /* GNU */
+#define DW_TAG_GNU_template_parameter_pack 0x4107 /* GNU */
+#define DW_TAG_GNU_formal_parameter_pack 0x4108 /* GNU */
+
+#define DW_TAG_GNU_call_site 0x4109 /* GNU */
+#define DW_TAG_GNU_call_site_parameter 0x410a /* GNU */
+
+/* ALTIUM extensions */
+ /* DSP-C/Starcore __circ qualifier */
+#define DW_TAG_ALTIUM_circ_type 0x5101 /* ALTIUM */
+ /* Starcore __mwa_circ qualifier */
+#define DW_TAG_ALTIUM_mwa_circ_type 0x5102 /* ALTIUM */
+ /* Starcore __rev_carry qualifier */
+#define DW_TAG_ALTIUM_rev_carry_type 0x5103 /* ALTIUM */
+ /* M16 __rom qualifier */
+#define DW_TAG_ALTIUM_rom 0x5111 /* ALTIUM */
+
+/* The following 3 are extensions to support UPC */
+#define DW_TAG_upc_shared_type 0x8765 /* UPC */
+#define DW_TAG_upc_strict_type 0x8766 /* UPC */
+#define DW_TAG_upc_relaxed_type 0x8767 /* UPC */
+
+/* PGI (STMicroelectronics) extensions. */
+#define DW_TAG_PGI_kanji_type 0xa000 /* PGI */
+#define DW_TAG_PGI_interface_block 0xa020 /* PGI */
+/* The following are SUN extensions */
+#define DW_TAG_SUN_function_template 0x4201 /* SUN */
+#define DW_TAG_SUN_class_template 0x4202 /* SUN */
+#define DW_TAG_SUN_struct_template 0x4203 /* SUN */
+#define DW_TAG_SUN_union_template 0x4204 /* SUN */
+#define DW_TAG_SUN_indirect_inheritance 0x4205 /* SUN */
+#define DW_TAG_SUN_codeflags 0x4206 /* SUN */
+#define DW_TAG_SUN_memop_info 0x4207 /* SUN */
+#define DW_TAG_SUN_omp_child_func 0x4208 /* SUN */
+#define DW_TAG_SUN_rtti_descriptor 0x4209 /* SUN */
+#define DW_TAG_SUN_dtor_info 0x420a /* SUN */
+#define DW_TAG_SUN_dtor 0x420b /* SUN */
+#define DW_TAG_SUN_f90_interface 0x420c /* SUN */
+#define DW_TAG_SUN_fortran_vax_structure 0x420d /* SUN */
+#define DW_TAG_SUN_hi 0x42ff /* SUN */
+
+
+#define DW_TAG_hi_user 0xffff
+
+#define DW_children_no 0
+#define DW_children_yes 1
+
+
+
+#define DW_FORM_addr 0x01
+#define DW_FORM_block2 0x03
+#define DW_FORM_block4 0x04
+#define DW_FORM_data2 0x05
+#define DW_FORM_data4 0x06
+#define DW_FORM_data8 0x07
+#define DW_FORM_string 0x08
+#define DW_FORM_block 0x09
+#define DW_FORM_block1 0x0a
+#define DW_FORM_data1 0x0b
+#define DW_FORM_flag 0x0c
+#define DW_FORM_sdata 0x0d
+#define DW_FORM_strp 0x0e
+#define DW_FORM_udata 0x0f
+#define DW_FORM_ref_addr 0x10
+#define DW_FORM_ref1 0x11
+#define DW_FORM_ref2 0x12
+#define DW_FORM_ref4 0x13
+#define DW_FORM_ref8 0x14
+#define DW_FORM_ref_udata 0x15
+#define DW_FORM_indirect 0x16
+#define DW_FORM_sec_offset 0x17 /* DWARF4 */
+#define DW_FORM_exprloc 0x18 /* DWARF4 */
+#define DW_FORM_flag_present 0x19 /* DWARF4 */
+/* 0x1a thru 0x1f were left unused accidentally. Reserved for future use. */
+#define DW_FORM_ref_sig8 0x20 /* DWARF4 */
+
+#define DW_AT_sibling 0x01
+#define DW_AT_location 0x02
+#define DW_AT_name 0x03
+#define DW_AT_ordering 0x09
+#define DW_AT_subscr_data 0x0a
+#define DW_AT_byte_size 0x0b
+#define DW_AT_bit_offset 0x0c
+#define DW_AT_bit_size 0x0d
+#define DW_AT_element_list 0x0f
+#define DW_AT_stmt_list 0x10
+#define DW_AT_low_pc 0x11
+#define DW_AT_high_pc 0x12
+#define DW_AT_language 0x13
+#define DW_AT_member 0x14
+#define DW_AT_discr 0x15
+#define DW_AT_discr_value 0x16
+#define DW_AT_visibility 0x17
+#define DW_AT_import 0x18
+#define DW_AT_string_length 0x19
+#define DW_AT_common_reference 0x1a
+#define DW_AT_comp_dir 0x1b
+#define DW_AT_const_value 0x1c
+#define DW_AT_containing_type 0x1d
+#define DW_AT_default_value 0x1e
+#define DW_AT_inline 0x20
+#define DW_AT_is_optional 0x21
+#define DW_AT_lower_bound 0x22
+#define DW_AT_producer 0x25
+#define DW_AT_prototyped 0x27
+#define DW_AT_return_addr 0x2a
+#define DW_AT_start_scope 0x2c
+#define DW_AT_bit_stride 0x2e /* DWARF3 name */
+#define DW_AT_stride_size 0x2e /* DWARF2 name */
+#define DW_AT_upper_bound 0x2f
+#define DW_AT_abstract_origin 0x31
+#define DW_AT_accessibility 0x32
+#define DW_AT_address_class 0x33
+#define DW_AT_artificial 0x34
+#define DW_AT_base_types 0x35
+#define DW_AT_calling_convention 0x36
+#define DW_AT_count 0x37
+#define DW_AT_data_member_location 0x38
+#define DW_AT_decl_column 0x39
+#define DW_AT_decl_file 0x3a
+#define DW_AT_decl_line 0x3b
+#define DW_AT_declaration 0x3c
+#define DW_AT_discr_list 0x3d
+#define DW_AT_encoding 0x3e
+#define DW_AT_external 0x3f
+#define DW_AT_frame_base 0x40
+#define DW_AT_friend 0x41
+#define DW_AT_identifier_case 0x42
+#define DW_AT_macro_info 0x43
+#define DW_AT_namelist_item 0x44
+#define DW_AT_priority 0x45
+#define DW_AT_segment 0x46
+#define DW_AT_specification 0x47
+#define DW_AT_static_link 0x48
+#define DW_AT_type 0x49
+#define DW_AT_use_location 0x4a
+#define DW_AT_variable_parameter 0x4b
+#define DW_AT_virtuality 0x4c
+#define DW_AT_vtable_elem_location 0x4d
+#define DW_AT_allocated 0x4e /* DWARF3 */
+#define DW_AT_associated 0x4f /* DWARF3 */
+#define DW_AT_data_location 0x50 /* DWARF3 */
+#define DW_AT_byte_stride 0x51 /* DWARF3f */
+#define DW_AT_stride 0x51 /* DWARF3 (do not use) */
+#define DW_AT_entry_pc 0x52 /* DWARF3 */
+#define DW_AT_use_UTF8 0x53 /* DWARF3 */
+#define DW_AT_extension 0x54 /* DWARF3 */
+#define DW_AT_ranges 0x55 /* DWARF3 */
+#define DW_AT_trampoline 0x56 /* DWARF3 */
+#define DW_AT_call_column 0x57 /* DWARF3 */
+#define DW_AT_call_file 0x58 /* DWARF3 */
+#define DW_AT_call_line 0x59 /* DWARF3 */
+#define DW_AT_description 0x5a /* DWARF3 */
+#define DW_AT_binary_scale 0x5b /* DWARF3f */
+#define DW_AT_decimal_scale 0x5c /* DWARF3f */
+#define DW_AT_small 0x5d /* DWARF3f */
+#define DW_AT_decimal_sign 0x5e /* DWARF3f */
+#define DW_AT_digit_count 0x5f /* DWARF3f */
+#define DW_AT_picture_string 0x60 /* DWARF3f */
+#define DW_AT_mutable 0x61 /* DWARF3f */
+#define DW_AT_threads_scaled 0x62 /* DWARF3f */
+#define DW_AT_explicit 0x63 /* DWARF3f */
+#define DW_AT_object_pointer 0x64 /* DWARF3f */
+#define DW_AT_endianity 0x65 /* DWARF3f */
+#define DW_AT_elemental 0x66 /* DWARF3f */
+#define DW_AT_pure 0x67 /* DWARF3f */
+#define DW_AT_recursive 0x68 /* DWARF3f */
+#define DW_AT_signature 0x69 /* DWARF4 */
+#define DW_AT_main_subprogram 0x6a /* DWARF4 */
+#define DW_AT_data_bit_offset 0x6b /* DWARF4 */
+#define DW_AT_const_expr 0x6c /* DWARF4 */
+#define DW_AT_enum_class 0x6d /* DWARF4 */
+#define DW_AT_linkage_name 0x6e /* DWARF4 */
+
+/* In extensions, we attempt to include the vendor extension
+ in the name even when the vendor leaves it out. */
+
+/* HP extensions. */
+#define DW_AT_HP_block_index 0x2000 /* HP */
+
+/* Follows extension so dwarfdump prints the most-likely-useful name. */
+#define DW_AT_lo_user 0x2000
+
+#define DW_AT_MIPS_fde 0x2001 /* MIPS/SGI */
+#define DW_AT_MIPS_loop_begin 0x2002 /* MIPS/SGI */
+#define DW_AT_MIPS_tail_loop_begin 0x2003 /* MIPS/SGI */
+#define DW_AT_MIPS_epilog_begin 0x2004 /* MIPS/SGI */
+#define DW_AT_MIPS_loop_unroll_factor 0x2005 /* MIPS/SGI */
+#define DW_AT_MIPS_software_pipeline_depth 0x2006 /* MIPS/SGI */
+#define DW_AT_MIPS_linkage_name 0x2007 /* MIPS/SGI, GNU, and others.*/
+#define DW_AT_MIPS_stride 0x2008 /* MIPS/SGI */
+#define DW_AT_MIPS_abstract_name 0x2009 /* MIPS/SGI */
+#define DW_AT_MIPS_clone_origin 0x200a /* MIPS/SGI */
+#define DW_AT_MIPS_has_inlines 0x200b /* MIPS/SGI */
+#define DW_AT_MIPS_stride_byte 0x200c /* MIPS/SGI */
+#define DW_AT_MIPS_stride_elem 0x200d /* MIPS/SGI */
+#define DW_AT_MIPS_ptr_dopetype 0x200e /* MIPS/SGI */
+#define DW_AT_MIPS_allocatable_dopetype 0x200f /* MIPS/SGI */
+#define DW_AT_MIPS_assumed_shape_dopetype 0x2010 /* MIPS/SGI */
+#define DW_AT_MIPS_assumed_size 0x2011 /* MIPS/SGI */
+
+/* HP extensions. */
+#define DW_AT_HP_unmodifiable 0x2001 /* conflict: MIPS */
+#define DW_AT_HP_actuals_stmt_list 0x2010 /* conflict: MIPS */
+#define DW_AT_HP_proc_per_section 0x2011 /* conflict: MIPS */
+#define DW_AT_HP_raw_data_ptr 0x2012 /* HP */
+#define DW_AT_HP_pass_by_reference 0x2013 /* HP */
+#define DW_AT_HP_opt_level 0x2014 /* HP */
+#define DW_AT_HP_prof_version_id 0x2015 /* HP */
+#define DW_AT_HP_opt_flags 0x2016 /* HP */
+#define DW_AT_HP_cold_region_low_pc 0x2017 /* HP */
+#define DW_AT_HP_cold_region_high_pc 0x2018 /* HP */
+#define DW_AT_HP_all_variables_modifiable 0x2019 /* HP */
+#define DW_AT_HP_linkage_name 0x201a /* HP */
+#define DW_AT_HP_prof_flags 0x201b /* HP */
+
+#define DW_AT_CPQ_discontig_ranges 0x2001 /* COMPAQ/HP */
+#define DW_AT_CPQ_semantic_events 0x2002 /* COMPAQ/HP */
+#define DW_AT_CPQ_split_lifetimes_var 0x2003 /* COMPAQ/HP */
+#define DW_AT_CPQ_split_lifetimes_rtn 0x2004 /* COMPAQ/HP */
+#define DW_AT_CPQ_prologue_length 0x2005 /* COMPAQ/HP */
+
+#define DW_AT_INTEL_other_endian 0x2026 /* Intel, 1 if byte swapped. */
+
+/* GNU extensions. */
+#define DW_AT_sf_names 0x2101 /* GNU */
+#define DW_AT_src_info 0x2102 /* GNU */
+#define DW_AT_mac_info 0x2103 /* GNU */
+#define DW_AT_src_coords 0x2104 /* GNU */
+#define DW_AT_body_begin 0x2105 /* GNU */
+#define DW_AT_body_end 0x2106 /* GNU */
+#define DW_AT_GNU_vector 0x2107 /* GNU */
+
+/* Thread safety, see http://gcc.gnu.org/wiki/ThreadSafetyAnnotation . */
+/* The values here are from gcc-4.6.2 include/dwarf2.h. The
+ values are not given on the web page at all, nor on web pages
+ it refers to. */
+#define DW_AT_GNU_guarded_by 0x2108 /* GNU */
+#define DW_AT_GNU_pt_guarded_by 0x2109 /* GNU */
+#define DW_AT_GNU_guarded 0x210a /* GNU */
+#define DW_AT_GNU_pt_guarded 0x210b /* GNU */
+#define DW_AT_GNU_locks_excluded 0x210c /* GNU */
+#define DW_AT_GNU_exclusive_locks_required 0x210d /* GNU */
+#define DW_AT_GNU_shared_locks_required 0x210e /* GNU */
+
+/* See http://gcc.gnu.org/wiki/DwarfSeparateTypeInfo */
+#define DW_AT_GNU_odr_signature 0x210f /* GNU */
+
+/* See See http://gcc.gnu.org/wiki/TemplateParmsDwarf */
+/* The value here is from gcc-4.6.2 include/dwarf2.h. The value is
+ not consistent with the web page as of December 2011. */
+#define DW_AT_GNU_template_name 0x2110 /* GNU */
+/* The GNU call site extension.
+ See http://www.dwarfstd.org/ShowIssue.php?issue=100909.2&type=open . */
+#define DW_AT_GNU_call_site_value 0x2111 /* GNU */
+#define DW_AT_GNU_call_site_data_value 0x2112 /* GNU */
+#define DW_AT_GNU_call_site_target 0x2113 /* GNU */
+#define DW_AT_GNU_call_site_target_clobbered 0x2114 /* GNU */
+#define DW_AT_GNU_tail_call 0x2115 /* GNU */
+#define DW_AT_GNU_all_tail_call_sites 0x2116 /* GNU */
+#define DW_AT_GNU_all_call_sites 0x2117 /* GNU */
+#define DW_AT_GNU_all_source_call_sites 0x2118 /* GNU */
+
+
+
+/* ALTIUM extension: ALTIUM Compliant location lists (flag) */
+#define DW_AT_ALTIUM_loclist 0x2300 /* ALTIUM */
+
+/* Sun extensions */
+#define DW_AT_SUN_template 0x2201 /* SUN */
+#define DW_AT_VMS_rtnbeg_pd_address 0x2201 /* VMS */
+#define DW_AT_SUN_alignment 0x2202 /* SUN */
+#define DW_AT_SUN_vtable 0x2203 /* SUN */
+#define DW_AT_SUN_count_guarantee 0x2204 /* SUN */
+#define DW_AT_SUN_command_line 0x2205 /* SUN */
+#define DW_AT_SUN_vbase 0x2206 /* SUN */
+#define DW_AT_SUN_compile_options 0x2207 /* SUN */
+#define DW_AT_SUN_language 0x2208 /* SUN */
+#define DW_AT_SUN_browser_file 0x2209 /* SUN */
+#define DW_AT_SUN_vtable_abi 0x2210 /* SUN */
+#define DW_AT_SUN_func_offsets 0x2211 /* SUN */
+#define DW_AT_SUN_cf_kind 0x2212 /* SUN */
+#define DW_AT_SUN_vtable_index 0x2213 /* SUN */
+#define DW_AT_SUN_omp_tpriv_addr 0x2214 /* SUN */
+#define DW_AT_SUN_omp_child_func 0x2215 /* SUN */
+#define DW_AT_SUN_func_offset 0x2216 /* SUN */
+#define DW_AT_SUN_memop_type_ref 0x2217 /* SUN */
+#define DW_AT_SUN_profile_id 0x2218 /* SUN */
+#define DW_AT_SUN_memop_signature 0x2219 /* SUN */
+#define DW_AT_SUN_obj_dir 0x2220 /* SUN */
+#define DW_AT_SUN_obj_file 0x2221 /* SUN */
+#define DW_AT_SUN_original_name 0x2222 /* SUN */
+#define DW_AT_SUN_hwcprof_signature 0x2223 /* SUN */
+#define DW_AT_SUN_amd64_parmdump 0x2224 /* SUN */
+#define DW_AT_SUN_part_link_name 0x2225 /* SUN */
+#define DW_AT_SUN_link_name 0x2226 /* SUN */
+#define DW_AT_SUN_pass_with_const 0x2227 /* SUN */
+#define DW_AT_SUN_return_with_const 0x2228 /* SUN */
+#define DW_AT_SUN_import_by_name 0x2229 /* SUN */
+#define DW_AT_SUN_f90_pointer 0x222a /* SUN */
+#define DW_AT_SUN_pass_by_ref 0x222b /* SUN */
+#define DW_AT_SUN_f90_allocatable 0x222c /* SUN */
+#define DW_AT_SUN_f90_assumed_shape_array 0x222d /* SUN */
+#define DW_AT_SUN_c_vla 0x222e /* SUN */
+#define DW_AT_SUN_return_value_ptr 0x2230 /* SUN */
+#define DW_AT_SUN_dtor_start 0x2231 /* SUN */
+#define DW_AT_SUN_dtor_length 0x2232 /* SUN */
+#define DW_AT_SUN_dtor_state_initial 0x2233 /* SUN */
+#define DW_AT_SUN_dtor_state_final 0x2234 /* SUN */
+#define DW_AT_SUN_dtor_state_deltas 0x2235 /* SUN */
+#define DW_AT_SUN_import_by_lname 0x2236 /* SUN */
+#define DW_AT_SUN_f90_use_only 0x2237 /* SUN */
+#define DW_AT_SUN_namelist_spec 0x2238 /* SUN */
+#define DW_AT_SUN_is_omp_child_func 0x2239 /* SUN */
+#define DW_AT_SUN_fortran_main_alias 0x223a /* SUN */
+#define DW_AT_SUN_fortran_based 0x223b /* SUN */
+
+/* See http://gcc.gnu.org/wiki/DW_AT_GNAT_descriptive_type . */
+#define DW_AT_use_GNAT_descriptive_type 0x2301 /* GNAT */
+#define DW_AT_GNAT_descriptive_type 0x2302 /* GNAT */
+
+/* UPC extension */
+#define DW_AT_upc_threads_scaled 0x3210 /* UPC */
+
+/* PGI (STMicroelectronics) extensions. */
+#define DW_AT_PGI_lbase 0x3a00 /* PGI. Block, constant, reference. This attribute is an ASTPLAB extension used to describe the array local base. */
+#define DW_AT_PGI_soffset 0x3a01 /* PGI. Block, constant, reference. ASTPLAB adds this attribute to describe the section offset, or the offset to the first element in the dimension. */
+#define DW_AT_PGI_lstride 0x3a02 /* PGI. Block, constant, reference. ASTPLAB adds this attribute to describe the linear stride or the distance between elements in the dimension. */
+
+/* There are two groups of Apple extensions here, it is
+ unclear what exactly is correct. */
+#define DW_AT_APPLE_optimized 0x3fe1 /* Apple */
+#define DW_AT_APPLE_flags 0x3fe2 /* Apple */
+#define DW_AT_APPLE_isa 0x3fe3 /* Apple */
+#define DW_AT_APPLE_block 0x3fe4 /* Apple */
+#define DW_AT_APPLE_major_runtime_vers 0x3fe5 /* Apple */
+#define DW_AT_APPLE_runtime_class 0x3fe6 /* Apple */
+#define DW_AT_APPLE_omit_frame_ptr 0x3fe7 /* Apple */
+
+/* Apple Extensions for closures */
+#define DW_AT_APPLE_closure 0x3fe4 /* Apple */
+/* Apple Extensions for Objective-C runtime info */
+#define DW_AT_APPLE_major_runtime_vers 0x3fe5 /* Apple */
+#define DW_AT_APPLE_runtime_class 0x3fe6 /* Apple */
+
+
+#define DW_AT_hi_user 0x3fff
+
+#define DW_OP_addr 0x03
+#define DW_OP_deref 0x06
+#define DW_OP_const1u 0x08
+#define DW_OP_const1s 0x09
+#define DW_OP_const2u 0x0a
+#define DW_OP_const2s 0x0b
+#define DW_OP_const4u 0x0c
+#define DW_OP_const4s 0x0d
+#define DW_OP_const8u 0x0e
+#define DW_OP_const8s 0x0f
+#define DW_OP_constu 0x10
+#define DW_OP_consts 0x11
+#define DW_OP_dup 0x12
+#define DW_OP_drop 0x13
+#define DW_OP_over 0x14
+#define DW_OP_pick 0x15
+#define DW_OP_swap 0x16
+#define DW_OP_rot 0x17
+#define DW_OP_xderef 0x18
+#define DW_OP_abs 0x19
+#define DW_OP_and 0x1a
+#define DW_OP_div 0x1b
+#define DW_OP_minus 0x1c
+#define DW_OP_mod 0x1d
+#define DW_OP_mul 0x1e
+#define DW_OP_neg 0x1f
+#define DW_OP_not 0x20
+#define DW_OP_or 0x21
+#define DW_OP_plus 0x22
+#define DW_OP_plus_uconst 0x23
+#define DW_OP_shl 0x24
+#define DW_OP_shr 0x25
+#define DW_OP_shra 0x26
+#define DW_OP_xor 0x27
+#define DW_OP_bra 0x28
+#define DW_OP_eq 0x29
+#define DW_OP_ge 0x2a
+#define DW_OP_gt 0x2b
+#define DW_OP_le 0x2c
+#define DW_OP_lt 0x2d
+#define DW_OP_ne 0x2e
+#define DW_OP_skip 0x2f
+#define DW_OP_lit0 0x30
+#define DW_OP_lit1 0x31
+#define DW_OP_lit2 0x32
+#define DW_OP_lit3 0x33
+#define DW_OP_lit4 0x34
+#define DW_OP_lit5 0x35
+#define DW_OP_lit6 0x36
+#define DW_OP_lit7 0x37
+#define DW_OP_lit8 0x38
+#define DW_OP_lit9 0x39
+#define DW_OP_lit10 0x3a
+#define DW_OP_lit11 0x3b
+#define DW_OP_lit12 0x3c
+#define DW_OP_lit13 0x3d
+#define DW_OP_lit14 0x3e
+#define DW_OP_lit15 0x3f
+#define DW_OP_lit16 0x40
+#define DW_OP_lit17 0x41
+#define DW_OP_lit18 0x42
+#define DW_OP_lit19 0x43
+#define DW_OP_lit20 0x44
+#define DW_OP_lit21 0x45
+#define DW_OP_lit22 0x46
+#define DW_OP_lit23 0x47
+#define DW_OP_lit24 0x48
+#define DW_OP_lit25 0x49
+#define DW_OP_lit26 0x4a
+#define DW_OP_lit27 0x4b
+#define DW_OP_lit28 0x4c
+#define DW_OP_lit29 0x4d
+#define DW_OP_lit30 0x4e
+#define DW_OP_lit31 0x4f
+#define DW_OP_reg0 0x50
+#define DW_OP_reg1 0x51
+#define DW_OP_reg2 0x52
+#define DW_OP_reg3 0x53
+#define DW_OP_reg4 0x54
+#define DW_OP_reg5 0x55
+#define DW_OP_reg6 0x56
+#define DW_OP_reg7 0x57
+#define DW_OP_reg8 0x58
+#define DW_OP_reg9 0x59
+#define DW_OP_reg10 0x5a
+#define DW_OP_reg11 0x5b
+#define DW_OP_reg12 0x5c
+#define DW_OP_reg13 0x5d
+#define DW_OP_reg14 0x5e
+#define DW_OP_reg15 0x5f
+#define DW_OP_reg16 0x60
+#define DW_OP_reg17 0x61
+#define DW_OP_reg18 0x62
+#define DW_OP_reg19 0x63
+#define DW_OP_reg20 0x64
+#define DW_OP_reg21 0x65
+#define DW_OP_reg22 0x66
+#define DW_OP_reg23 0x67
+#define DW_OP_reg24 0x68
+#define DW_OP_reg25 0x69
+#define DW_OP_reg26 0x6a
+#define DW_OP_reg27 0x6b
+#define DW_OP_reg28 0x6c
+#define DW_OP_reg29 0x6d
+#define DW_OP_reg30 0x6e
+#define DW_OP_reg31 0x6f
+#define DW_OP_breg0 0x70
+#define DW_OP_breg1 0x71
+#define DW_OP_breg2 0x72
+#define DW_OP_breg3 0x73
+#define DW_OP_breg4 0x74
+#define DW_OP_breg5 0x75
+#define DW_OP_breg6 0x76
+#define DW_OP_breg7 0x77
+#define DW_OP_breg8 0x78
+#define DW_OP_breg9 0x79
+#define DW_OP_breg10 0x7a
+#define DW_OP_breg11 0x7b
+#define DW_OP_breg12 0x7c
+#define DW_OP_breg13 0x7d
+#define DW_OP_breg14 0x7e
+#define DW_OP_breg15 0x7f
+#define DW_OP_breg16 0x80
+#define DW_OP_breg17 0x81
+#define DW_OP_breg18 0x82
+#define DW_OP_breg19 0x83
+#define DW_OP_breg20 0x84
+#define DW_OP_breg21 0x85
+#define DW_OP_breg22 0x86
+#define DW_OP_breg23 0x87
+#define DW_OP_breg24 0x88
+#define DW_OP_breg25 0x89
+#define DW_OP_breg26 0x8a
+#define DW_OP_breg27 0x8b
+#define DW_OP_breg28 0x8c
+#define DW_OP_breg29 0x8d
+#define DW_OP_breg30 0x8e
+#define DW_OP_breg31 0x8f
+#define DW_OP_regx 0x90
+#define DW_OP_fbreg 0x91
+#define DW_OP_bregx 0x92
+#define DW_OP_piece 0x93
+#define DW_OP_deref_size 0x94
+#define DW_OP_xderef_size 0x95
+#define DW_OP_nop 0x96
+#define DW_OP_push_object_address 0x97 /* DWARF3 */
+#define DW_OP_call2 0x98 /* DWARF3 */
+#define DW_OP_call4 0x99 /* DWARF3 */
+#define DW_OP_call_ref 0x9a /* DWARF3 */
+#define DW_OP_form_tls_address 0x9b /* DWARF3f */
+#define DW_OP_call_frame_cfa 0x9c /* DWARF3f */
+#define DW_OP_bit_piece 0x9d /* DWARF3f */
+#define DW_OP_implicit_value 0x9e /* DWARF4 */
+#define DW_OP_stack_value 0x9f /* DWARF4 */
+
+
+ /* GNU extensions. */
+#define DW_OP_GNU_push_tls_address 0xe0 /* GNU */
+
+/* Follows extension so dwarfdump prints the most-likely-useful name. */
+#define DW_OP_lo_user 0xe0
+
+
+#define DW_OP_GNU_uninit 0xf0 /* GNU */
+#define DW_OP_GNU_encoded_addr 0xf1 /* GNU */
+#define DW_OP_GNU_implicit_pointer 0xf2 /* GNU */
+#define DW_OP_GNU_entry_value 0xf3 /* GNU */
+
+ /* HP extensions. */
+#define DW_OP_HP_unknown 0xe0 /* HP conflict: GNU */
+#define DW_OP_HP_is_value 0xe1 /* HP */
+#define DW_OP_HP_fltconst4 0xe2 /* HP */
+#define DW_OP_HP_fltconst8 0xe3 /* HP */
+#define DW_OP_HP_mod_range 0xe4 /* HP */
+#define DW_OP_HP_unmod_range 0xe5 /* HP */
+#define DW_OP_HP_tls 0xe6 /* HP */
+
+#define DW_OP_INTEL_bit_piece 0xe8 /* Intel: made obsolete by DW_OP_bit_piece above. */
+
+ /* Apple extension. */
+#define DW_OP_APPLE_uninit 0xf0 /* Apple */
+#define DW_OP_PGI_omp_thread_num 0xf8 /* PGI (STMicroelectronics) */
+
+#define DW_OP_hi_user 0xff
+
+#define DW_ATE_address 0x1
+#define DW_ATE_boolean 0x2
+#define DW_ATE_complex_float 0x3
+#define DW_ATE_float 0x4
+#define DW_ATE_signed 0x5
+#define DW_ATE_signed_char 0x6
+#define DW_ATE_unsigned 0x7
+#define DW_ATE_unsigned_char 0x8
+#define DW_ATE_imaginary_float 0x9 /* DWARF3 */
+#define DW_ATE_packed_decimal 0xa /* DWARF3f */
+#define DW_ATE_numeric_string 0xb /* DWARF3f */
+#define DW_ATE_edited 0xc /* DWARF3f */
+#define DW_ATE_signed_fixed 0xd /* DWARF3f */
+#define DW_ATE_unsigned_fixed 0xe /* DWARF3f */
+#define DW_ATE_decimal_float 0xf /* DWARF3f */
+
+
+/* ALTIUM extensions. x80, x81 */
+#define DW_ATE_ALTIUM_fract 0x80 /* ALTIUM __fract type */
+
+/* Follows extension so dwarfdump prints the most-likely-useful name. */
+#define DW_ATE_lo_user 0x80
+
+/* Shown here to help dwarfdump build script. */
+#define DW_ATE_ALTIUM_accum 0x81 /* ALTIUM __accum type */
+
+/* HP Floating point extensions. */
+#define DW_ATE_HP_float80 0x80 /* (80 bit). HP */
+
+
+#define DW_ATE_HP_complex_float80 0x81 /* Complex (80 bit). HP */
+#define DW_ATE_HP_float128 0x82 /* (128 bit). HP */
+#define DW_ATE_HP_complex_float128 0x83 /* Complex (128 bit). HP */
+#define DW_ATE_HP_floathpintel 0x84 /* (82 bit IA64). HP */
+#define DW_ATE_HP_imaginary_float80 0x85 /* HP */
+#define DW_ATE_HP_imaginary_float128 0x86 /* HP */
+
+/* Sun extensions */
+#define DW_ATE_SUN_interval_float 0x91
+#define DW_ATE_SUN_imaginary_float 0x92 /* Obsolete: See DW_ATE_imaginary_float */
+
+#define DW_ATE_hi_user 0xff
+
+
+/* Decimal Sign codes. */
+#define DW_DS_unsigned 0x01 /* DWARF3f */
+#define DW_DS_leading_overpunch 0x02 /* DWARF3f */
+#define DW_DS_trailing_overpunch 0x03 /* DWARF3f */
+#define DW_DS_leading_separate 0x04 /* DWARF3f */
+
+#define DW_DS_trailing_separate 0x05 /* DWARF3f */
+
+/* Endian code name. */
+#define DW_END_default 0x00 /* DWARF3f */
+#define DW_END_big 0x01 /* DWARF3f */
+#define DW_END_little 0x02 /* DWARF3f */
+
+#define DW_END_lo_user 0x40 /* DWARF3f */
+#define DW_END_hi_user 0xff /* DWARF3f */
+
+/* For use with DW_TAG_SUN_codeflags
+ If DW_TAG_SUN_codeflags is accepted as a dwarf standard, then
+ standard dwarf ATCF entries start at 0x01 */
+#define DW_ATCF_lo_user 0x40 /* SUN */
+#define DW_ATCF_SUN_mop_bitfield 0x41 /* SUN */
+#define DW_ATCF_SUN_mop_spill 0x42 /* SUN */
+#define DW_ATCF_SUN_mop_scopy 0x43 /* SUN */
+#define DW_ATCF_SUN_func_start 0x44 /* SUN */
+#define DW_ATCF_SUN_end_ctors 0x45 /* SUN */
+#define DW_ATCF_SUN_branch_target 0x46 /* SUN */
+#define DW_ATCF_SUN_mop_stack_probe 0x47 /* SUN */
+#define DW_ATCF_SUN_func_epilog 0x48 /* SUN */
+#define DW_ATCF_hi_user 0xff /* SUN */
+
+/* Accessibility code name. */
+#define DW_ACCESS_public 0x01
+#define DW_ACCESS_protected 0x02
+#define DW_ACCESS_private 0x03
+
+/* Visibility code name. */
+#define DW_VIS_local 0x01
+#define DW_VIS_exported 0x02
+#define DW_VIS_qualified 0x03
+
+/* Virtuality code name. */
+#define DW_VIRTUALITY_none 0x00
+#define DW_VIRTUALITY_virtual 0x01
+#define DW_VIRTUALITY_pure_virtual 0x02
+
+#define DW_LANG_C89 0x0001
+#define DW_LANG_C 0x0002
+#define DW_LANG_Ada83 0x0003
+#define DW_LANG_C_plus_plus 0x0004
+#define DW_LANG_Cobol74 0x0005
+#define DW_LANG_Cobol85 0x0006
+#define DW_LANG_Fortran77 0x0007
+#define DW_LANG_Fortran90 0x0008
+#define DW_LANG_Pascal83 0x0009
+#define DW_LANG_Modula2 0x000a
+#define DW_LANG_Java 0x000b /* DWARF3 */
+#define DW_LANG_C99 0x000c /* DWARF3 */
+#define DW_LANG_Ada95 0x000d /* DWARF3 */
+#define DW_LANG_Fortran95 0x000e /* DWARF3 */
+#define DW_LANG_PLI 0x000f /* DWARF3 */
+#define DW_LANG_ObjC 0x0010 /* DWARF3f */
+#define DW_LANG_ObjC_plus_plus 0x0011 /* DWARF3f */
+#define DW_LANG_UPC 0x0012 /* DWARF3f */
+#define DW_LANG_D 0x0013 /* DWARF3f */
+#define DW_LANG_Python 0x0014 /* DWARF4 */
+/* The following 2 are not yet formally approved October 2010, but
+ it seems extremely likely they will be approved as the committee
+ chair agrees these should be ok and no one on the committee
+ has objected. */
+#define DW_LANG_OpenCL 0x0015 /* Provisionally DWARF5 */
+#define DW_LANG_Go 0x0016 /* Provisionally DWARF5 */
+#define DW_LANG_lo_user 0x8000
+#define DW_LANG_Mips_Assembler 0x8001 /* MIPS */
+#define DW_LANG_Upc 0x8765 /* UPC, use
+ DW_LANG_UPC instead. */
+/* ALTIUM extension */
+#define DW_LANG_ALTIUM_Assembler 0x9101 /* ALTIUM */
+
+/* Sun extensions */
+#define DW_LANG_SUN_Assembler 0x9001 /* SUN */
+
+#define DW_LANG_hi_user 0xffff
+
+/* Identifier case name. */
+#define DW_ID_case_sensitive 0x00
+#define DW_ID_up_case 0x01
+#define DW_ID_down_case 0x02
+#define DW_ID_case_insensitive 0x03
+
+/* Calling Convention Name. */
+#define DW_CC_normal 0x01
+#define DW_CC_program 0x02
+#define DW_CC_nocall 0x03
+#define DW_CC_lo_user 0x40
+
+#define DW_CC_GNU_renesas_sh 0x40 /* GNU */
+#define DW_CC_GNU_borland_fastcall_i386 0x41 /* GNU */
+
+
+
+/* ALTIUM extensions. */
+/* Function is an interrupt handler, return address on system stack. */
+#define DW_CC_ALTIUM_interrupt 0x65 /* ALTIUM*/
+
+/* Near function model, return address on system stack. */
+#define DW_CC_ALTIUM_near_system_stack 0x66 /*ALTIUM */
+
+/* Near function model, return address on user stack. */
+#define DW_CC_ALTIUM_near_user_stack 0x67 /* ALTIUM */
+
+/* Huge function model, return address on user stack. */
+#define DW_CC_ALTIUM_huge_user_stack 0x68 /* ALTIUM */
+
+
+#define DW_CC_hi_user 0xff
+
+/* Inline Code Name. */
+#define DW_INL_not_inlined 0x00
+#define DW_INL_inlined 0x01
+#define DW_INL_declared_not_inlined 0x02
+#define DW_INL_declared_inlined 0x03
+
+/* Ordering Name. */
+#define DW_ORD_row_major 0x00
+#define DW_ORD_col_major 0x01
+
+/* Discriminant Descriptor Name. */
+#define DW_DSC_label 0x00
+#define DW_DSC_range 0x01
+
+/* Line number standard opcode name. */
+#define DW_LNS_copy 0x01
+#define DW_LNS_advance_pc 0x02
+#define DW_LNS_advance_line 0x03
+#define DW_LNS_set_file 0x04
+#define DW_LNS_set_column 0x05
+#define DW_LNS_negate_stmt 0x06
+#define DW_LNS_set_basic_block 0x07
+#define DW_LNS_const_add_pc 0x08
+#define DW_LNS_fixed_advance_pc 0x09
+#define DW_LNS_set_prologue_end 0x0a /* DWARF3 */
+#define DW_LNS_set_epilogue_begin 0x0b /* DWARF3 */
+#define DW_LNS_set_isa 0x0c /* DWARF3 */
+
+/* Line number extended opcode name. */
+#define DW_LNE_end_sequence 0x01
+#define DW_LNE_set_address 0x02
+#define DW_LNE_define_file 0x03
+#define DW_LNE_set_discriminator 0x04 /* DWARF4 */
+
+/* HP extensions. */
+#define DW_LNE_HP_negate_is_UV_update 0x11 /* 17 HP */
+#define DW_LNE_HP_push_context 0x12 /* 18 HP */
+#define DW_LNE_HP_pop_context 0x13 /* 19 HP */
+#define DW_LNE_HP_set_file_line_column 0x14 /* 20 HP */
+#define DW_LNE_HP_set_routine_name 0x15 /* 21 HP */
+#define DW_LNE_HP_set_sequence 0x16 /* 22 HP */
+#define DW_LNE_HP_negate_post_semantics 0x17 /* 23 HP */
+#define DW_LNE_HP_negate_function_exit 0x18 /* 24 HP */
+#define DW_LNE_HP_negate_front_end_logical 0x19 /* 25 HP */
+#define DW_LNE_HP_define_proc 0x20 /* 32 HP */
+
+#define DW_LNE_HP_source_file_correlation 0x80 /* HP */
+#define DW_LNE_lo_user 0x80 /* DWARF3 */
+#define DW_LNE_hi_user 0xff /* DWARF3 */
+
+/* These are known values for DW_LNS_set_isa. */
+#define DW_ISA_UNKNOWN 0
+/* The following two are ARM specific. */
+#define DW_ISA_ARM_thumb 1 /* ARM ISA */
+#define DW_ISA_ARM_arm 2 /* ARM ISA */
+
+/* Macro information. */
+#define DW_MACINFO_define 0x01
+#define DW_MACINFO_undef 0x02
+#define DW_MACINFO_start_file 0x03
+#define DW_MACINFO_end_file 0x04
+#define DW_MACINFO_vendor_ext 0xff
+
+/* CFA operator compaction (a space saving measure, see
+ the DWARF standard) means DW_CFA_extended and DW_CFA_nop
+ have the same value here. */
+#define DW_CFA_advance_loc 0x40
+#define DW_CFA_offset 0x80
+#define DW_CFA_restore 0xc0
+#define DW_CFA_extended 0
+
+#define DW_CFA_nop 0x00
+#define DW_CFA_set_loc 0x01
+#define DW_CFA_advance_loc1 0x02
+#define DW_CFA_advance_loc2 0x03
+#define DW_CFA_advance_loc4 0x04
+#define DW_CFA_offset_extended 0x05
+#define DW_CFA_restore_extended 0x06
+#define DW_CFA_undefined 0x07
+#define DW_CFA_same_value 0x08
+#define DW_CFA_register 0x09
+#define DW_CFA_remember_state 0x0a
+#define DW_CFA_restore_state 0x0b
+#define DW_CFA_def_cfa 0x0c
+#define DW_CFA_def_cfa_register 0x0d
+#define DW_CFA_def_cfa_offset 0x0e
+#define DW_CFA_def_cfa_expression 0x0f /* DWARF3 */
+#define DW_CFA_expression 0x10 /* DWARF3 */
+#define DW_CFA_offset_extended_sf 0x11 /* DWARF3 */
+#define DW_CFA_def_cfa_sf 0x12 /* DWARF3 */
+#define DW_CFA_def_cfa_offset_sf 0x13 /* DWARF3 */
+#define DW_CFA_val_offset 0x14 /* DWARF3f */
+#define DW_CFA_val_offset_sf 0x15 /* DWARF3f */
+#define DW_CFA_val_expression 0x16 /* DWARF3f */
+
+#define DW_CFA_lo_user 0x1c
+#define DW_CFA_low_user 0x1c /* Incorrect spelling, do not use. */
+
+/* SGI/MIPS extension. */
+#define DW_CFA_MIPS_advance_loc8 0x1d /* MIPS */
+
+/* GNU extensions. */
+#define DW_CFA_GNU_window_save 0x2d /* GNU */
+#define DW_CFA_GNU_args_size 0x2e /* GNU */
+#define DW_CFA_GNU_negative_offset_extended 0x2f /* GNU */
+
+#define DW_CFA_high_user 0x3f
+
+/* GNU exception header encoding. See the Generic
+ Elf Specification of the Linux Standard Base (LSB).
+ http://refspecs.freestandards.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html
+ The upper 4 bits indicate how the value is to be applied.
+ The lower 4 bits indicate the format of the data.
+*/
+#define DW_EH_PE_absptr 0x00 /* GNU */
+#define DW_EH_PE_uleb128 0x01 /* GNU */
+#define DW_EH_PE_udata2 0x02 /* GNU */
+#define DW_EH_PE_udata4 0x03 /* GNU */
+#define DW_EH_PE_udata8 0x04 /* GNU */
+#define DW_EH_PE_sleb128 0x09 /* GNU */
+#define DW_EH_PE_sdata2 0x0A /* GNU */
+#define DW_EH_PE_sdata4 0x0B /* GNU */
+#define DW_EH_PE_sdata8 0x0C /* GNU */
+
+#define DW_EH_PE_pcrel 0x10 /* GNU */
+#define DW_EH_PE_textrel 0x20 /* GNU */
+#define DW_EH_PE_datarel 0x30 /* GNU */
+#define DW_EH_PE_funcrel 0x40 /* GNU */
+#define DW_EH_PE_aligned 0x50 /* GNU */
+
+#define DW_EH_PE_omit 0xff /* GNU. Means no value present. */
+
+
+/* Mapping from machine registers and pseudo-regs into the
+ .debug_frame table. DW_FRAME entries are machine specific.
+ These describe MIPS/SGI R3000, R4K, R4400 and all later
+ MIPS/SGI IRIX machines. They describe a mapping from
+ hardware register number to the number used in the table
+ to identify that register.
+
+ The CFA (Canonical Frame Address) described in DWARF is
+ called the Virtual Frame Pointer on MIPS/SGI machines.
+
+ The DW_FRAME* names here are MIPS/SGI specific.
+ Libdwarf interfaces defined in 2008 make the
+ frame definitions here (and the fixed table sizes
+ they imply) obsolete. They are left here for compatibility.
+*/
+/* Default column used for CFA in the libdwarf reader client.
+ Assumes reg 0 never appears as
+ a register in DWARF information. Usable for MIPS,
+ but never a good idea, really. */
+#define DW_FRAME_CFA_COL 0
+
+#define DW_FRAME_REG1 1 /* integer reg 1 */
+#define DW_FRAME_REG2 2 /* integer reg 2 */
+#define DW_FRAME_REG3 3 /* integer reg 3 */
+#define DW_FRAME_REG4 4 /* integer reg 4 */
+#define DW_FRAME_REG5 5 /* integer reg 5 */
+#define DW_FRAME_REG6 6 /* integer reg 6 */
+#define DW_FRAME_REG7 7 /* integer reg 7 */
+#define DW_FRAME_REG8 8 /* integer reg 8 */
+#define DW_FRAME_REG9 9 /* integer reg 9 */
+#define DW_FRAME_REG10 10 /* integer reg 10 */
+#define DW_FRAME_REG11 11 /* integer reg 11 */
+#define DW_FRAME_REG12 12 /* integer reg 12 */
+#define DW_FRAME_REG13 13 /* integer reg 13 */
+#define DW_FRAME_REG14 14 /* integer reg 14 */
+#define DW_FRAME_REG15 15 /* integer reg 15 */
+#define DW_FRAME_REG16 16 /* integer reg 16 */
+#define DW_FRAME_REG17 17 /* integer reg 17 */
+#define DW_FRAME_REG18 18 /* integer reg 18 */
+#define DW_FRAME_REG19 19 /* integer reg 19 */
+#define DW_FRAME_REG20 20 /* integer reg 20 */
+#define DW_FRAME_REG21 21 /* integer reg 21 */
+#define DW_FRAME_REG22 22 /* integer reg 22 */
+#define DW_FRAME_REG23 23 /* integer reg 23 */
+#define DW_FRAME_REG24 24 /* integer reg 24 */
+#define DW_FRAME_REG25 25 /* integer reg 25 */
+#define DW_FRAME_REG26 26 /* integer reg 26 */
+#define DW_FRAME_REG27 27 /* integer reg 27 */
+#define DW_FRAME_REG28 28 /* integer reg 28 */
+#define DW_FRAME_REG29 29 /* integer reg 29 */
+#define DW_FRAME_REG30 30 /* integer reg 30 */
+#define DW_FRAME_REG31 31 /* integer reg 31, aka ra */
+
+ /* MIPS1, 2 have only some of these 64-bit registers.
+ ** MIPS1 save/restore takes 2 instructions per 64-bit reg, and
+ ** in that case, the register is considered stored after the second
+ ** swc1.
+ */
+#define DW_FRAME_FREG0 32 /* 64-bit floating point reg 0 */
+#define DW_FRAME_FREG1 33 /* 64-bit floating point reg 1 */
+#define DW_FRAME_FREG2 34 /* 64-bit floating point reg 2 */
+#define DW_FRAME_FREG3 35 /* 64-bit floating point reg 3 */
+#define DW_FRAME_FREG4 36 /* 64-bit floating point reg 4 */
+#define DW_FRAME_FREG5 37 /* 64-bit floating point reg 5 */
+#define DW_FRAME_FREG6 38 /* 64-bit floating point reg 6 */
+#define DW_FRAME_FREG7 39 /* 64-bit floating point reg 7 */
+#define DW_FRAME_FREG8 40 /* 64-bit floating point reg 8 */
+#define DW_FRAME_FREG9 41 /* 64-bit floating point reg 9 */
+#define DW_FRAME_FREG10 42 /* 64-bit floating point reg 10 */
+#define DW_FRAME_FREG11 43 /* 64-bit floating point reg 11 */
+#define DW_FRAME_FREG12 44 /* 64-bit floating point reg 12 */
+#define DW_FRAME_FREG13 45 /* 64-bit floating point reg 13 */
+#define DW_FRAME_FREG14 46 /* 64-bit floating point reg 14 */
+#define DW_FRAME_FREG15 47 /* 64-bit floating point reg 15 */
+#define DW_FRAME_FREG16 48 /* 64-bit floating point reg 16 */
+#define DW_FRAME_FREG17 49 /* 64-bit floating point reg 17 */
+#define DW_FRAME_FREG18 50 /* 64-bit floating point reg 18 */
+#define DW_FRAME_FREG19 51 /* 64-bit floating point reg 19 */
+#define DW_FRAME_FREG20 52 /* 64-bit floating point reg 20 */
+#define DW_FRAME_FREG21 53 /* 64-bit floating point reg 21 */
+#define DW_FRAME_FREG22 54 /* 64-bit floating point reg 22 */
+#define DW_FRAME_FREG23 55 /* 64-bit floating point reg 23 */
+#define DW_FRAME_FREG24 56 /* 64-bit floating point reg 24 */
+#define DW_FRAME_FREG25 57 /* 64-bit floating point reg 25 */
+#define DW_FRAME_FREG26 58 /* 64-bit floating point reg 26 */
+#define DW_FRAME_FREG27 59 /* 64-bit floating point reg 27 */
+#define DW_FRAME_FREG28 60 /* 64-bit floating point reg 28 */
+#define DW_FRAME_FREG29 61 /* 64-bit floating point reg 29 */
+#define DW_FRAME_FREG30 62 /* 64-bit floating point reg 30 */
+#define DW_FRAME_FREG31 63 /* 64-bit floating point reg 31 */
+
+#define DW_FRAME_FREG32 64 /* 64-bit floating point reg 18 */
+#define DW_FRAME_FREG33 65 /* 64-bit floating point reg 19 */
+#define DW_FRAME_FREG34 66 /* 64-bit floating point reg 20 */
+#define DW_FRAME_FREG35 67 /* 64-bit floating point reg 21 */
+#define DW_FRAME_FREG36 68 /* 64-bit floating point reg 22 */
+#define DW_FRAME_FREG37 69 /* 64-bit floating point reg 23 */
+#define DW_FRAME_FREG38 70 /* 64-bit floating point reg 24 */
+#define DW_FRAME_FREG39 71 /* 64-bit floating point reg 25 */
+#define DW_FRAME_FREG40 72 /* 64-bit floating point reg 26 */
+#define DW_FRAME_FREG41 73 /* 64-bit floating point reg 27 */
+#define DW_FRAME_FREG42 74 /* 64-bit floating point reg 28 */
+#define DW_FRAME_FREG43 75 /* 64-bit floating point reg 29 */
+#define DW_FRAME_FREG44 76 /* 64-bit floating point reg 30 */
+#define DW_FRAME_FREG45 77 /* 64-bit floating point reg 31 */
+#define DW_FRAME_FREG46 78 /* 64-bit floating point reg 18 */
+#define DW_FRAME_FREG47 79 /* 64-bit floating point reg 19 */
+#define DW_FRAME_FREG48 80 /* 64-bit floating point reg 20 */
+#define DW_FRAME_FREG49 81 /* 64-bit floating point reg 21 */
+#define DW_FRAME_FREG50 82 /* 64-bit floating point reg 22 */
+#define DW_FRAME_FREG51 83 /* 64-bit floating point reg 23 */
+#define DW_FRAME_FREG52 84 /* 64-bit floating point reg 24 */
+#define DW_FRAME_FREG53 85 /* 64-bit floating point reg 25 */
+#define DW_FRAME_FREG54 86 /* 64-bit floating point reg 26 */
+#define DW_FRAME_FREG55 87 /* 64-bit floating point reg 27 */
+#define DW_FRAME_FREG56 88 /* 64-bit floating point reg 28 */
+#define DW_FRAME_FREG57 89 /* 64-bit floating point reg 29 */
+#define DW_FRAME_FREG58 90 /* 64-bit floating point reg 30 */
+#define DW_FRAME_FREG59 91 /* 64-bit floating point reg 31 */
+#define DW_FRAME_FREG60 92 /* 64-bit floating point reg 22 */
+#define DW_FRAME_FREG61 93 /* 64-bit floating point reg 23 */
+#define DW_FRAME_FREG62 94 /* 64-bit floating point reg 24 */
+#define DW_FRAME_FREG63 95 /* 64-bit floating point reg 25 */
+#define DW_FRAME_FREG64 96 /* 64-bit floating point reg 26 */
+#define DW_FRAME_FREG65 97 /* 64-bit floating point reg 27 */
+#define DW_FRAME_FREG66 98 /* 64-bit floating point reg 28 */
+#define DW_FRAME_FREG67 99 /* 64-bit floating point reg 29 */
+#define DW_FRAME_FREG68 100 /* 64-bit floating point reg 30 */
+#define DW_FRAME_FREG69 101 /* 64-bit floating point reg 31 */
+#define DW_FRAME_FREG70 102 /* 64-bit floating point reg 22 */
+#define DW_FRAME_FREG71 103 /* 64-bit floating point reg 23 */
+#define DW_FRAME_FREG72 104 /* 64-bit floating point reg 24 */
+#define DW_FRAME_FREG73 105 /* 64-bit floating point reg 25 */
+#define DW_FRAME_FREG74 106 /* 64-bit floating point reg 26 */
+#define DW_FRAME_FREG75 107 /* 64-bit floating point reg 27 */
+#define DW_FRAME_FREG76 108 /* 64-bit floating point reg 28 */
+
+
+/* ***IMPORTANT NOTE, TARGET DEPENDENCY ****
+ The following 4 #defines are dependent on
+ the target cpu(s) that you apply libdwarf to.
+ Ensure that DW_FRAME_UNDEFINED_VAL and DW_FRAME_SAME_VAL
+ do not conflict with the range [0-DW_FRAME_STATIC_LINK].
+ The value 63 works for MIPS cpus at least up to the R16000.
+
+ For a cpu with more than 63 real registers
+ DW_FRAME_HIGHEST_NORMAL_REGISTER
+ must be increased for things to work properly!
+ Also ensure that DW_FRAME_UNDEFINED_VAL DW_FRAME_SAME_VAL
+ are not in the range [0-DW_FRAME_STATIC_LINK]
+
+ Having DW_FRAME_HIGHEST_NORMAL_REGISTER be higher than
+ is strictly needed is safe.
+
+*/
+
+#ifndef DW_FRAME_HIGHEST_NORMAL_REGISTER
+#define DW_FRAME_HIGHEST_NORMAL_REGISTER 188
+#endif
+/* This is the number of columns in the Frame Table.
+ This constant should
+ be kept in sync with DW_REG_TABLE_SIZE defined in libdwarf.h
+ It must also be large enough to be beyond the highest
+ compiler-defined-register (meaning DW_FRAME_RA_COL DW_FRAME_STATIC_LINK
+ in the MIPS/IRIX case */
+#ifndef DW_FRAME_LAST_REG_NUM
+#define DW_FRAME_LAST_REG_NUM (DW_FRAME_HIGHEST_NORMAL_REGISTER + 3)
+#endif
+
+
+/* Column recording ra (return address from a function call).
+ This is common to many architectures, but as a 'simple register'
+ is not necessarily adequate for all architectures.
+ For MIPS/IRIX this register number is actually recorded on disk
+ in the .debug_frame section.
+ */
+#define DW_FRAME_RA_COL (DW_FRAME_HIGHEST_NORMAL_REGISTER + 1)
+
+/* Column recording static link applicable to up-level
+ addressing, as in IRIX mp code, pascal, etc.
+ This is common to many architectures but
+ is not necessarily adequate for all architectures.
+ For MIPS/IRIX this register number is actually recorded on disk
+ in the .debug_frame section.
+*/
+#define DW_FRAME_STATIC_LINK (DW_FRAME_HIGHEST_NORMAL_REGISTER + 2)
+
+
+
+/*
+ DW_FRAME_UNDEFINED_VAL and DW_FRAME_SAME_VAL are
+ never on disk, just generated by libdwarf. See libdwarf.h
+ for their values.
+*/
+
+
+
+#define DW_CHILDREN_no 0x00
+#define DW_CHILDREN_yes 0x01
+
+#define DW_ADDR_none 0
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __DWARF_H */
diff --git a/libdwarf/dwarf.v2.mm b/libdwarf/dwarf.v2.mm
new file mode 100644
index 0000000..5b12dac
--- /dev/null
+++ b/libdwarf/dwarf.v2.mm
@@ -0,0 +1,7699 @@
+'\"#ident "%W%"
+'\" $Source: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/libdwarf/RCS/dwarf.v2.mm,v $
+'\"
+'\" $Revision: 1.2 $
+'\"
+'\" DESCRIPTION
+'\"
+'\" Requirements for
+'\"
+'\" COMPILATION
+'\"
+'\" pic file.mm | tbl | troff -mm
+'\"
+'\" local mileage may vary
+'\"
+'\" AUTHOR
+'\"
+'\" UNIX International Programming Languages SIG
+'\"
+'\" COPYRIGHT
+'\"
+'\" Copyright (c) 1992,1993, UNIX International
+'\"
+'\" Permission to use, copy, modify, and distribute this documentation for
+'\" any purpose and without fee is hereby granted, provided that the above
+'\" copyright notice appears in all copies and that both that copyright
+'\" notice and this permission notice appear in supporting documentation,
+'\" and that the name UNIX International not be used in advertising or
+'\" publicity pertaining to distribution of the software without specific,
+'\" written prior permission. UNIX International makes no representations
+'\" about the suitability of this documentation for any purpose. It is
+'\" provided "as is" without express or implied warranty.
+'\"
+'\" UNIX INTERNATIONAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+'\" DOCUMENTATION, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+'\" FITNESS. IN NO EVENT SHALL UNIX INTERNATIONAL BE LIABLE FOR ANY
+'\" SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+'\" RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+'\" CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+'\" CONNECTION WITH THE USE OR PERFORMANCE OF THIS DOCUMENTATION.
+'\"
+'\" NOTICE:
+'\"
+'\" UNIX International is making this documentation available as a
+'\" reference point for the industry. While UNIX International believes
+'\" that this specification is well defined in this first release of the
+'\" document, minor changes may be made prior to products meeting this
+'\" specification being made available from UNIX System Laboratories or
+'\" UNIX International members.
+'\"
+'\" $Log$
+'\" Revision 1.1 1994/05/18 18:50:42 davea
+'\" Initial revision
+'\"
+'\"
+'\" Abbrevs for funny typeset words
+.pl-0.25i
+.ds aX U\s-2NIX\s+2
+.ds iX \*(aX International
+.ds uL \s-2AT&T\ USL\s+2
+'\"
+'\" uI should be set to 1 if the publication and copyright page is needed.
+.nr uI 1
+'\"
+'\" Make the appropriate replacements in this section!
+'\"
+'\" Set the ND date to the current date.
+'\" tT is the formal document title
+'\" tP is the name of the Project (if appropriate)
+'\" tD is the short document title
+'\" tE is the work group name (may be the same as the project name)
+.ds tT DWARF Debugging Information Format
+.ds tP
+'\" Document name (i.e., without project name)
+.ds tD DWARF Debugging Information Format
+.ds tE Programming Languages SIG
+'\"
+'\" Define headers and footers macro
+'\"
+.ds fA Revision: 2.0.0
+'\"
+'\" fB null to remove page numbers on cover page
+.ds fB
+.ds fC July 27, 1993
+.ds fE Industry Review Draft
+.ds fF \*(tD
+.PH "''''"
+.PF "''\*(fE''"
+.tr ~
+.SA 1
+.S 10
+.nr Ej 1
+.nr Hs 5
+.nr Hu 1
+.nr Hb 5
+.ds HP +2 +2 +1 +0 +0 +0 +0
+.ds HF 3 3 3 3 3 1 1
+.if n .ds HF 1 1 1 1 1 1 1 1
+'\"
+'\" First page, print title and authors
+'\"
+.S +4
+.DS C
+
+
+
+
+
+
+\fB\*(tT
+
+\s-2\*(tP\s+2\fP
+
+.DE
+.S
+.sp 3i
+\*(iX
+.br
+\*(tE
+.br
+\*(fA (\*(fC)
+.SK
+.if \n(uI\{
+.DS C
+.in -.25i
+.B "Published by:"
+.R
+
+\*(iX
+Waterview Corporate Center
+20 Waterview Boulevard
+Parsippany, NJ 07054
+
+for further information, contact:
+Vice President of Marketing
+
+Phone: +1 201-263-8400
+Fax: +1 201-263-8401
+.DE
+.P
+Copyright \(co 1992, 1993 \*(iX, Inc.
+.P
+Permission to use, copy, modify, and distribute this
+documentation for any purpose and without fee is hereby granted, provided
+that the above copyright notice appears in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name \*(iX not be used in
+advertising or publicity pertaining to distribution of the software
+without specific, written prior permission. \*(iX makes
+no representations about the suitability of this documentation for any
+purpose. It is provided "as is" without express or implied warranty.
+.P
+UNIX INTERNATIONAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS DOCUMENTATION,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+EVENT SHALL UNIX INTERNATIONAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS DOCUMENTATION.
+.sp 2l
+.if \n(uI\{
+NOTICE:
+.P
+\*(iX is making this documentation available as a
+reference point for the industry.
+While \*(iX believes that this specification is well
+defined in this first release of the document,
+minor changes may be made prior to products meeting this specification
+being made available from \*(aX System Laboratories or \*(iX members.
+.sp 1l \}
+Trademarks:
+.P
+Intel386 is a trademark of Intel Corporation.
+.br
+\*(aX\(rg is a registered trademark of \*(aX System Laboratories
+in the United States and other countries.
+.br
+.OH "'''\s10\\\\*(tE\s0'"
+.EH "'\s10\\\\*(tD\s0'''"
+.SK
+'\".VM 0 2
+.PF "''\s10\\\\*(fE\s0''"
+.OF "'\s10\\\\*(fA'\\\\*(fB'\\\\*(fC\s0'"
+.EF "'\s10\\\\*(fA'\\\\*(fB'\\\\*(fC\s0'"
+'\" -----------------------------------------------------------------------
+'\".
+'\" Reset page numbers
+'\"
+.nr P 1
+.nr % 1
+'\"
+'\" Define headers and footers
+'\"
+.FH
+'\" Turn on the page numbering in the footers
+.ds fB Page %
+'\"
+'\" MACROEND
+'\"
+.if n .fp 2 R
+.if n .fp 3 R
+.tr ~
+\fR
+.S 11
+.SA 1
+.tr ~
+.OP
+.ds | |
+.ds ~ ~
+.ds ' '
+.if t .ds Cw \&\f(CW
+.if n .ds Cw \fB
+.de Cf \" Place every other arg in Cw font, beginning with first
+.if \\n(.$=1 \&\*(Cw\\$1\fP
+.if \\n(.$=2 \&\*(Cw\\$1\fP\\$2
+.if \\n(.$=3 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP
+.if \\n(.$=4 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP\\$4
+.if \\n(.$=5 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP\\$4\*(Cw\\$5\fP
+.if \\n(.$=6 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP\\$4\*(Cw\\$5\fP\\$6
+.if \\n(.$=7 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP\\$4\*(Cw\\$5\fP\\$6\*(Cw\\$7\fP
+.if \\n(.$=8 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP\\$4\*(Cw\\$5\fP\\$6\*(Cw\\$7\fP\\$8
+.if \\n(.$=9 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP\\$4\*(Cw\\$5\fP\\$6\*(Cw\\$7\fP\\$8\*(Cw
+..
+'\" macros used by index generating tool
+.deIX
+.ie '\\n(.z'' .tm .Index: \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9 \\n%
+.el \\!.ix \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.deix
+.ie '\\n(.z'' .tm .Index: \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9 \\n%
+.el \\!.ix \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.ta .5i +.5i +.5i +.5i +.5i +.5i +.5i +.5i
+.HU "FOREWORD"
+This document specifies the second generation of symbolic debugging
+information based on the DWARF format that
+has been developed by the \*(iX
+Programming Languages Special Interest Group (SIG).
+It is being circulated for industry review.
+The first version of the DWARF specification was published
+by \*(iX in January, 1992. The current version adds significant
+new functionality, but its main thrust is to achieve a much
+denser encoding of the DWARF information. Because of the new
+encoding, DWARF Version 2 is not binary compatible with
+DWARF Version 1.
+.P
+At this point, the SIG believes that this document sufficiently
+supports the debugging needs of C, C++, FORTRAN 77,
+Fortran90, Modula2 and Pascal, and we have
+released it for public comment. We will accept comments on this
+document until September 30, 1994. Comments may be directed via email
+to the SIG mailing list (plsig@ui.org). If you are unable
+to send email, paper mail, FAX, or machine readable copy
+on \*(aX, MS-DOS, or Macintosh compatible media can be
+sent to \*(iX at the address listed below,
+and will be forwarded to the SIG.
+.SP
+.SP
+.SP
+.in +20
+UNIX International
+.br
+Waterview Corporate Center
+.br
+20 Waterview Boulevard
+.br
+Parsippany, NJ 07054
+.br
+Phone: +1 201-263-8400
+.br
+Fax: +1 201-263-8401
+.br
+.in -20
+.nr H1 0
+.OP
+.H 1 "INTRODUCTION"
+\fR
+This document defines the format for the information generated by
+compilers, assemblers and linkage editors that is necessary for symbolic,
+source-level debugging. The debugging information format does not favor the
+design of any compiler or debugger. Instead, the goal is to create a method of
+communicating an accurate picture of the source program to any debugger in a
+form that is economically extensible to different languages while retaining
+backward compatibility.
+.P
+The design of the debugging information format is open-ended, allowing for the
+addition of new debugging information to accommodate new languages or
+debugger capabilities while remaining compatible with other languages or
+different debuggers.
+.H 2 "Purpose and Scope"
+The debugging information format described in this document is designed to
+meet the symbolic, source-level debugging needs of
+different languages in a unified fashion by
+requiring language independent debugging information whenever possible.
+.IX C++ %caa
+.IX virtual functions
+.IX Fortran
+Individual needs, such as C++ virtual functions or Fortran common blocks are
+accommodated by creating attributes that are used only for those
+languages. The \*(iX \*(tE believes
+that this document sufficiently covers the
+.IX languages
+debugging information needs of C, C++, FORTRAN77, Fortran90,
+Modula2 and Pascal.
+.IX C %c
+.IX Modula2
+.IX Pascal
+.IX FORTRAN77
+.IX Fortran90
+.P
+This document describes DWARF Version 2, the second generation of debugging
+.IX Version 2
+information based on the DWARF format. While DWARF Version 2 provides
+new debugging information not available in Version 1, the primary focus
+of the changes for Version 2 is the representation of the information,
+rather than the information content itself. The basic structure of
+the Version 2 format remains as in Version 1: the debugging information
+is represented as a series of debugging information entries, each containing
+one or more attributes (name/value pairs).
+.IX debugging information entries
+.IX attributes
+The Version 2 representation, however,
+is much more compact than the Version 1 representation.
+.IX Version 1
+In some cases, this greater density has been achieved at the expense
+of additional complexity or greater difficulty in producing and processing
+the DWARF information. We believe that the reduction in I/O and in
+memory paging should more than make up for any increase in processing time.
+.P
+Because the representation of information has changed from Version 1 to
+Version 2, Version 2 DWARF information is not binary compatible
+.IX compatibility
+with Version 1 information. To make it easier for consumers to
+support both Version 1 and Version 2 DWARF information, the Version
+2 information has been moved to a different object file section,
+.Cf .debug_info .
+.IX \f(CW.debug_info\fP %debugai
+.P
+The intended audience for this document are the developers of
+both producers and consumers of debugging information, typically
+language compilers, debuggers and other tools that need to interpret
+a binary program in terms of its original source.
+.H 2 "Overview"
+There are two major pieces to the description of the DWARF format in
+this document. The first piece is the informational content
+of the debugging entries. The second piece
+is the way the debugging information is encoded and
+represented in an object file.
+.P
+The informational content is described in sections two
+through six.
+Section two describes the overall structure of
+the information and attributes that are common to many or all of
+the different debugging information entries.
+Sections three, four and five describe the specific debugging
+information entries and how they communicate the
+necessary information about the source program to a debugger.
+Section six describes debugging information contained
+outside of the debugging information entries, themselves.
+The encoding of the DWARF information is
+presented in section seven.
+.P
+Section eight describes some future directions for the DWARF
+specification.
+.P
+In the following sections, text in normal font describes required aspects
+of the DWARF format. Text in \fIitalics\fP is explanatory or supplementary
+material, and not part of the format definition itself.
+.H 2 "Vendor Extensibility"
+.IX vendor extensions
+This document does not attempt to cover all interesting languages or even
+to cover all of the interesting debugging information needs for its primary
+target languages (C, C++, FORTRAN77, Fortran90, Modula2, Pascal).
+Therefore the document provides
+vendors a way to define their own debugging information tags, attributes,
+base type encodings, location operations, language names,
+calling conventions and call frame instructions
+by reserving a portion of the name space and valid values
+for these constructs for vendor specific additions. Future versions
+of this document will not use names or values reserved for vendor specific
+additions. All names and values not reserved for vendor additions, however,
+are reserved for future versions of this document. See section 7 for
+details.
+.H 2 "Changes from Version 1"
+The following is a list of the major changes made to the DWARF Debugging
+Information Format since Version 1 of the format was published (January
+.IX Version 1
+20, 1992). The list is not meant to be exhaustive.
+.BL
+.LI
+Debugging information entries have been moved from the
+.Cf .debug
+.IX \f(CW.debug\fP %debugaaa
+to the
+.Cf .debug_info
+.IX \f(CW.debug_info\fP %debugai
+section of an object file.
+.LI
+.IX tags
+.IX attributes, names
+.IX attributes, forms
+The tag, attribute names and attribute forms encodings have been moved
+out of the debugging information itself to a separate abbreviations table.
+.IX abbreviations table
+.LI
+Explicit sibling pointers have been made optional. Each
+.IX debugging information entries, siblings
+entry now specifies (through the abbreviations table) whether
+or not it has children.
+.IX debugging information entries, child entries
+.LI
+New more compact attribute forms have been added, including a variable
+length constant data form. Attribute values may now have any
+.IX variable length data
+.IX attributes, forms
+.IX attributes, values
+form within a given class of forms.
+.LI
+Location descriptions have been replaced by a new, more compact
+and more expressive format.
+.IX locations, descriptions
+There is now a way of expressing multiple locations for an object
+whose location changes during its lifetime.
+.IX locations, lists
+.LI
+There is a new format for line number information
+that provides information
+for code contributed to a compilation unit from an included file.
+Line number information is now in the
+.IX line number information
+.Cf .debug_line
+.IX \f(CW.debug_line\fP %debugali
+section of an object file.
+.LI
+The representation of the type of a declaration has been
+reworked.
+.IX declarations, types of
+.LI
+A new section provides an encoding for pre-processor macro information.
+.IX macro information
+.IX pre-processor
+.LI
+Debugging information entries now provide for the representation
+of non-defining declarations of objects, functions or types.
+.IX declarations, non-defining
+.LI
+More complete support for Modula2 and Pascal has been added.
+.LI
+There is now a way of describing locations for segmented address spaces.
+.IX segmented address space
+.IX address space, segmented
+.LI
+A new section provides an encoding for information about call
+frame activations.
+.IX call frame information
+.IX activations
+.LI
+The representation of enumeration and array types has been
+.IX enumerations
+.IX arrays
+reworked so that DWARF presents only a single way of
+representing lists of items.
+.LI
+Support has been added for C++ templates and exceptions.
+.IX C++ %caa
+.IX templates
+.IX exceptions
+.LE
+.OP
+.H 1 "GENERAL DESCRIPTION"
+.H 2 "The Debugging Information Entry"
+DWARF uses a series of debugging information entries to define a
+.IX debugging information entries
+low-level representation of a source program. Each debugging
+information entry is described by an identifying tag and
+contains a series of attributes.
+The tag specifies the class to which an entry
+belongs, and the attributes define the specific characteristics
+of the entry.
+.P
+.nr aX \n(Fg+1
+The set of required tag names is listed in Figure \n(aX.
+.IX tags
+The debugging information entries they identify are described in sections three, four and five.
+.P
+The debugging information entries in DWARF Version 2 are intended
+to exist in the
+.Cf .debug_info
+section of an object file.
+.IX \f(CW.debug_info\fP %debugai
+.DF
+.TS
+center box;
+lf(CW) lf(CW)
+.
+DW_TAG_access_declaration DW_TAG_array_type
+DW_TAG_base_type DW_TAG_catch_block
+DW_TAG_class_type DW_TAG_common_block
+DW_TAG_common_inclusion DW_TAG_compile_unit
+DW_TAG_const_type DW_TAG_constant
+DW_TAG_entry_point DW_TAG_enumeration_type
+DW_TAG_enumerator DW_TAG_file_type
+DW_TAG_formal_parameter DW_TAG_friend
+DW_TAG_imported_declaration DW_TAG_inheritance
+DW_TAG_inlined_subroutine DW_TAG_label
+DW_TAG_lexical_block DW_TAG_member
+DW_TAG_module DW_TAG_namelist
+DW_TAG_namelist_item DW_TAG_packed_type
+DW_TAG_pointer_type DW_TAG_ptr_to_member_type
+DW_TAG_reference_type DW_TAG_set_type
+DW_TAG_string_type DW_TAG_structure_type
+DW_TAG_subprogram DW_TAG_subrange_type
+DW_TAG_subroutine_type DW_TAG_template_type_param
+DW_TAG_template_value_param DW_TAG_thrown_type
+DW_TAG_try_block DW_TAG_typedef
+DW_TAG_union_type DW_TAG_unspecified_parameters
+DW_TAG_variable DW_TAG_variant
+DW_TAG_variant_part DW_TAG_volatile_type
+DW_TAG_with_stmt
+.TE
+.FG "Tag names"
+.DE
+.H 2 "Attribute Types"
+Each attribute value is characterized by an attribute name.
+.IX attributes
+.IX attributes, names
+The set of attribute names is
+.nr aX \n(Fg+1
+listed in Figure \n(aX.
+.DF
+.TS
+center box;
+lf(CW) lf(CW)
+.
+DW_AT_abstract_origin DW_AT_accessibility
+DW_AT_address_class DW_AT_artificial
+DW_AT_base_types DW_AT_bit_offset
+DW_AT_bit_size DW_AT_byte_size
+DW_AT_calling_convention DW_AT_common_reference
+DW_AT_comp_dir DW_AT_const_value
+DW_AT_containing_type DW_AT_count
+DW_AT_data_member_location DW_AT_decl_column
+DW_AT_decl_file DW_AT_decl_line
+DW_AT_declaration DW_AT_default_value
+DW_AT_discr DW_AT_discr_list
+DW_AT_discr_value DW_AT_encoding
+DW_AT_external DW_AT_frame_base
+DW_AT_friend DW_AT_high_pc
+DW_AT_identifier_case DW_AT_import
+DW_AT_inline DW_AT_is_optional
+DW_AT_language DW_AT_location
+DW_AT_low_pc DW_AT_lower_bound
+DW_AT_macro_info DW_AT_name
+DW_AT_namelist_item DW_AT_ordering
+DW_AT_priority DW_AT_producer
+DW_AT_prototyped DW_AT_return_addr
+DW_AT_segment DW_AT_sibling
+DW_AT_specification DW_AT_start_scope
+DW_AT_static_link DW_AT_stmt_list
+DW_AT_stride_size DW_AT_string_length
+DW_AT_type DW_AT_upper_bound
+DW_AT_use_location DW_AT_variable_parameter
+DW_AT_virtuality DW_AT_visibility
+DW_AT_vtable_elem_location
+.TE
+.FG "Attribute names"
+.DE
+.P
+The permissible values for an attribute belong to one or more classes
+.IX attributes, values
+.IX attributes, forms
+of attribute value forms. Each form class may be represented in one or more
+ways. For instance, some attribute values consist of a single piece
+of constant data. ``Constant data'' is the class of attribute value
+that those attributes may have. There are several representations
+of constant data, however (one, two, four, eight bytes and variable
+length data). The particular representation for any given instance
+of an attribute is encoded along with the attribute name as part
+of the information that guides the interpretation of a debugging
+information entry. Attribute value forms may belong
+to one of the following classes.
+.VL 18
+.LI address
+.IX attributes, addresses
+Refers to some location in the address space of the described program.
+.LI block
+.IX attributes, blocks
+An arbitrary number of uninterpreted bytes of data.
+.LI constant
+.IX attributes, constants
+One, two, four or eight bytes of uninterpreted data, or data encoded
+in the variable length format known as LEB128 (see section 7.6).
+.IX variable length data
+.IX LEB128
+.LI flag
+.IX attributes, flags
+A small constant that indicates the presence or absence of an attribute.
+.LI reference
+.IX attributes, references
+Refers to some member of the set of debugging information entries that describe
+the program. There are two types of reference. The first is an
+offset relative to the beginning of the compilation unit in
+which the reference occurs and must refer to an entry within
+that same compilation unit. The second type of reference
+is the address of any debugging information entry within
+the same executable or shared object; it may refer to an entry
+in a different compilation unit from the unit containing the
+reference.
+.LI string
+.IX attributes, strings
+A null-terminated sequence of zero or more (non-null) bytes.
+Data in this form are generally printable strings. Strings
+may be represented directly in the debugging information entry
+or as an offset in a separate string table.
+.LE
+.P
+There are no limitations on the ordering of attributes within a debugging
+.IX attributes, ordering
+information entry, but to prevent ambiguity,
+no more than one attribute with a given name may appear in any debugging
+information entry.
+.H 2 "Relationship of Debugging Information Entries"
+.I
+A variety of needs can be met by permitting a single debugging
+information entry to ``own'' an arbitrary number of other debugging
+entries and by permitting the same debugging information entry to be
+one of many owned by another debugging information entry.
+This makes it possible to describe, for example,
+the static block structure within
+a source file, show the members of a structure, union, or class, and associate
+declarations with source files or source files with shared objects.
+.P
+.R
+The ownership relation
+of debugging information entries is achieved naturally
+.IX debugging information entries
+because the debugging information is represented as a tree.
+The nodes of the tree are the debugging information entries
+themselves. The child entries of any node are exactly those
+.IX debugging information entries, child entries
+debugging information entries owned by that node.\*F
+.FS
+While the ownership relation of the debugging information
+entries is represented as a tree, other relations among
+the entries exist, for example, a pointer from an entry
+representing a variable to another entry representing
+the type of that variable. If all such relations are
+taken into account, the debugging entries form a graph,
+not a tree.
+.FE
+.P
+The tree itself is represented by flattening it in prefix
+order. Each debugging information entry
+is defined either to have child entries or not to have child entries
+(see section 7.5.3).
+If an entry is defined not to have children, the next physically
+succeeding entry is the sibling of the prior entry. If an entry
+.IX debugging information entries, siblings
+is defined to have children, the next physically succeeding entry
+is the first child of the prior entry. Additional children of the parent
+entry are represented as siblings of the first child. A chain
+of sibling entries is terminated by a null entry.
+.IX debugging information entries, null entries
+.P
+In cases where a producer of debugging information
+feels that it will be important for consumers of that information
+to quickly scan chains of sibling entries, ignoring the children
+of individual siblings, that producer may attach an
+.Cf AT_sibling
+attribute to any debugging information entry. The value of
+this attribute is a reference to the sibling entry of the
+entry to which the attribute is attached.
+.H 2 "Location Descriptions"
+.I
+The debugging information must provide consumers a way to find the location
+of program variables, determine the bounds of dynamic arrays and strings
+and possibly to find the base address of a subroutine's stack frame or
+the return address of a subroutine. Furthermore, to meet the needs
+of recent computer architectures and optimization techniques, the debugging
+information must be able to describe the location of an object
+whose location changes over the object's lifetime.
+.P
+.R
+Information about the location of program objects is provided by
+location descriptions. Location
+.IX locations, descriptions
+descriptions can be either of two forms:
+.AL
+.LI
+\fILocation expressions\fP which are a language independent representation of
+addressing rules
+.IX locations, expressions
+of arbitrary complexity built from a few basic
+building blocks, or \fIoperations\fP. They are sufficient for describing
+the location of any object as long as its lifetime is either static
+or the same as the lexical block that owns it, and it does not move throughout
+its lifetime.
+.LI
+\fILocation lists\fP which are used to describe objects that
+.IX locations, lists
+have a limited lifetime or change their location throughout their
+lifetime. Location lists are more completely described below.
+.LE
+.P
+The two forms are distinguished in a context sensitive manner. As the value
+of an attribute, a location expression is
+encoded as a block and a location list is encoded as a constant offset into
+a location list table.
+.P
+.I
+Note: The Version 1 concept of "location descriptions" was replaced in Version 2
+with this new abstraction because it is denser and more descriptive.
+.IX Version 1
+.IX Version 2
+.R
+.H 3 "Location Expressions"
+A location expression consists of zero or more location operations.
+.IX locations, expressions
+An expression with zero operations
+is used to denote an object that is
+present in the source code but not present in the object code
+(perhaps because of optimization).
+.IX optimized code
+The location operations fall into two categories, register names and
+addressing operations. Register names always appear alone and indicate
+that the referred object is contained inside a particular
+register. Addressing operations are memory address computation
+rules. All location operations are encoded as a stream of opcodes that
+are each followed by zero or more literal operands. The number of operands
+is determined by the opcode.
+.H 3 "Register Name Operators"
+.IX locations, register name operators
+The following operations can be used to name a register.
+.P
+.I
+Note that the
+register number represents a DWARF specific mapping of numbers onto
+the actual registers of a given architecture.
+The mapping should be chosen to gain optimal density and
+should be shared by all users of a given architecture.
+The \*(tE recommends
+that this mapping be defined by the ABI\*F
+.IX ABI
+.FS
+\fISystem V Application Binary Interface\fP, consisting of the generic
+interface and processor supplements for each target architecture.
+.FE
+authoring committee for each
+architecture.
+.R
+.AL
+.LI
+.Cf DW_OP_reg0 , " DW_OP_reg1" ", ..., " DW_OP_reg31
+.br
+The
+\f(CWDW_OP_reg\fP\fIn\fP
+operations encode the names of up to 32 registers, numbered from
+0 through 31, inclusive. The object addressed is in register \fIn\fP.
+.LI
+.Cf DW_OP_regx
+.br
+The
+.Cf DW_OP_regx
+operation has a single unsigned LEB128 literal operand that encodes the
+name of a register.
+.LE
+.H 3 "Addressing Operations"
+.IX locations, stack
+Each addressing operation represents a postfix operation on a simple stack
+machine. Each element of the stack is the size of an
+address on the target machine.
+The value on the top of the stack after
+``executing'' the location expression is taken to be the result (the address
+of the object, or the value of the array bound, or the length of a
+dynamic string). In the case of locations used for structure members,
+.IX members, locations
+the computation assumes that the base address of the containing structure
+has been pushed on the stack before evaluation of the addressing operation.
+.R
+.H 4 "Literal Encodings"
+.IX locations, literal encodings
+The following operations all push a value onto the addressing stack.
+.AL
+.LI
+.Cf DW_OP_lit0 , " DW_OP_lit1" ", ..., " DW_OP_lit31
+.br
+The
+\f(CWDW_OP_lit\fP\fIn\fP operations encode the unsigned
+literal values from 0 through 31, inclusive.
+.LI
+.Cf DW_OP_addr
+.br
+The
+.Cf DW_OP_addr
+operation has a single operand that encodes a
+machine address and whose size is the size of an address on the
+target machine.
+.LI
+.Cf DW_OP_const1u
+.br
+The single operand of the
+.Cf DW_OP_const1u
+operation provides a 1-byte unsigned integer constant.
+.LI
+.Cf DW_OP_const1s
+.br
+The single operand of the
+.Cf DW_OP_const1s
+operation provides a
+1-byte signed integer constant.
+.LI
+.Cf DW_OP_const2u
+.br
+The single operand of the
+.Cf DW_OP_const2u
+operation provides a
+2-byte unsigned integer constant.
+.LI
+.Cf DW_OP_const2s
+.br
+The single operand of the
+.Cf DW_OP_const2s
+operation provides a
+2-byte signed integer constant.
+.LI
+.Cf DW_OP_const4u
+.br
+The single operand of the
+.Cf DW_OP_const4u
+operation provides a
+4-byte unsigned integer constant.
+.LI
+.Cf DW_OP_const4s
+.br
+The single operand of the
+.Cf DW_OP_const4s
+operation provides a
+4-byte signed integer constant.
+.LI
+.Cf DW_OP_const8u
+.br
+The single operand of the
+.Cf DW_OP_const8u
+operation provides an
+8-byte unsigned integer constant.
+.LI
+.Cf DW_OP_const8s
+.br
+The single operand of the
+.Cf DW_OP_const8s
+operation provides an
+8-byte signed integer constant.
+.LI
+.Cf DW_OP_constu
+.br
+The single operand of the
+.Cf DW_OP_constu
+operation provides an
+unsigned LEB128 integer constant.
+.LI
+.Cf DW_OP_consts
+.br
+The single operand of the
+.Cf DW_OP_consts
+operation provides a
+signed LEB128 integer constant.
+.LE
+.H 4 "Register Based Addressing"
+.IX locations, register based addressing
+The following operations push a value onto the stack that
+is the result of adding the contents of a register with
+a given signed offset.
+.AL
+.LI
+.Cf DW_OP_fbreg
+.br
+The
+\f(CWDW_OP_fbreg\fP
+operation provides a signed LEB128 offset from the address specified
+by the location descriptor in the
+.Cf DW_AT_frame_base
+attribute of the current
+.IX subroutines, frame base
+function. \fI(This is typically a "stack pointer" register
+plus or minus some
+offset. On more sophisticated systems it might be a location list that
+adjusts the offset according to changes in the stack pointer as
+the PC changes.)\fP
+.LI
+.Cf DW_OP_breg0 , " DW_OP_breg1" ", ..., " DW_OP_breg31
+.br
+The single operand of the
+\f(CWDW_OP_breg\fP\fIn\fP
+operations provides a signed LEB128 offset from the specified register.
+.LI
+.Cf DW_OP_bregx
+.br
+The
+.Cf DW_OP_bregx
+operation has two operands: a signed LEB128 offset from the specified register
+which is defined with an unsigned LEB128 number.
+.LE
+.H 4 "Stack Operations"
+.IX locations, stack
+The following operations
+manipulate the ``location stack.''
+Location operations that index the location stack assume that
+the top of the stack (most recently added entry) has index 0.
+.AL
+.LI
+.Cf DW_OP_dup
+.br
+The
+.Cf DW_OP_dup
+operation duplicates the value at the top of the location stack.
+.LI
+.Cf DW_OP_drop
+.br
+The
+.Cf DW_OP_drop
+operation pops the value at the top of the stack.
+.LI
+.Cf DW_OP_pick
+.br
+The single operand of the
+.Cf DW_OP_pick
+operation provides a 1-byte index. The stack entry with the specified index
+(0 through 255, inclusive) is pushed on the stack.
+.LI
+.Cf DW_OP_over
+.br
+The
+.Cf DW_OP_over
+operation duplicates the entry currently second in the stack
+at the top of the stack. This is equivalent to an
+.Cf DW_OP_pick
+operation, with index 1.
+.LI
+.Cf DW_OP_swap
+.br
+The
+.Cf DW_OP_swap
+operation swaps the top two stack entries. The entry at
+the top of the stack becomes the second stack entry, and
+the second entry becomes the top of the stack.
+.LI
+.Cf DW_OP_rot
+.br
+The
+.Cf DW_OP_rot
+operation rotates the first three stack entries. The entry at
+the top of the stack becomes the third stack entry, the second entry
+becomes the top of the stack, and the third entry becomes the second
+entry.
+.LI
+.Cf DW_OP_deref
+.br
+The
+.Cf DW_OP_deref
+operation pops the top stack entry and treats it as an address.
+The value retrieved from that address is pushed. The size of the
+data retrieved from the dereferenced address is the size of an address
+on the target machine.
+.LI
+.Cf DW_OP_deref_size
+.br
+The
+.Cf DW_OP_deref_size
+operation behaves like the
+.Cf DW_OP_deref
+operation: it
+pops the top stack entry and treats it as an address.
+The value retrieved from that address is pushed.
+In the
+.Cf DW_OP_deref_size
+operation, however,
+the size in bytes of the
+data retrieved from the dereferenced address is specified by the
+single operand. This operand is a 1-byte unsigned integral constant
+whose value may not be larger than the size of an address on
+the target machine. The data retrieved is zero extended to the size
+of an address on the target machine before being pushed on
+the expression stack.
+.LI
+.Cf DW_OP_xderef
+.br
+The
+.Cf DW_OP_xderef
+.IX address space, multiple
+operation provides an extended dereference mechanism. The entry at the
+top of the stack is treated as an address. The second stack entry
+is treated as an ``address space identifier'' for those architectures
+that support multiple address spaces. The top two stack elements
+are popped, a data item is retrieved through an implementation-defined
+address calculation and pushed as the new stack top. The size of the
+data retrieved from the dereferenced address is the size of an address
+on the target machine.
+.LI
+.Cf DW_OP_xderef_size
+.br
+The
+.Cf DW_OP_xderef_size
+operation behaves like the
+.Cf DW_OP_xderef
+operation: the entry at the
+top of the stack is treated as an address. The second stack entry
+is treated as an ``address space identifier'' for those architectures
+that support multiple address spaces. The top two stack elements
+are popped, a data item is retrieved through an implementation-defined
+address calculation and pushed as the new stack top.
+In the
+.Cf DW_OP_xderef_size
+operation, however,
+the size in bytes of the
+data retrieved from the dereferenced address is specified by the
+single operand. This operand is a 1-byte unsigned integral constant
+whose value may not be larger than the size of an address on
+the target machine. The data retrieved is zero extended to the size
+of an address on the target machine before being pushed on
+the expression stack.
+.LE
+.H 4 "Arithmetic and Logical Operations"
+.IX locations, arithmetic operations
+.IX locations, logical operations
+The following provide arithmetic and logical operations.
+The arithmetic operations perform ``addressing arithmetic,''
+that is, unsigned arithmetic that wraps on an address-sized
+boundary. The operations do not cause an exception on overflow.
+.AL
+.LI
+.Cf DW_OP_abs
+.br
+The
+.Cf DW_OP_abs
+operation pops the top stack entry and pushes its absolute value.
+.LI
+.Cf DW_OP_and
+.br
+The
+.Cf DW_OP_and
+operation pops the top two stack values, performs a bitwise \fIand\fP
+operation on the two, and pushes the result.
+.LI
+.Cf DW_OP_div
+.br
+The
+.Cf DW_OP_div
+operation pops the top two stack values, divides the former second entry
+by the former top of the stack
+using signed division,
+and pushes the result.
+.LI
+.Cf DW_OP_minus
+.br
+The
+.Cf DW_OP_minus
+operation pops the top two stack values, subtracts the former top of the stack
+from the former second entry, and pushes the result.
+.LI
+.Cf DW_OP_mod
+.br
+The
+.Cf DW_OP_mod
+operation pops the top two stack values and pushes the result of the
+calculation: former second stack entry modulo the former top of the
+stack.
+.LI
+.Cf DW_OP_mul
+.br
+The
+.Cf DW_OP_mul
+operation pops the top two stack entries, multiplies them together,
+and pushes the result.
+.LI
+.Cf DW_OP_neg
+.br
+The
+.Cf DW_OP_neg
+operation pops the top stack entry, and pushes its negation.
+.LI
+.Cf DW_OP_not
+.br
+The
+.Cf DW_OP_not
+operation pops the top stack entry, and pushes its bitwise complement.
+.LI
+.Cf DW_OP_or
+.br
+The
+.Cf DW_OP_or
+operation pops the top two stack entries, performs a bitwise \fIor\fP
+operation on the two, and pushes the result.
+.LI
+.Cf DW_OP_plus
+.br
+The
+.Cf DW_OP_plus
+operation pops the top two stack entries, adds them together,
+and pushes the result.
+.LI
+.Cf DW_OP_plus_uconst
+.br
+The
+.Cf DW_OP_plus_uconst
+operation pops the top stack entry, adds it to the unsigned LEB128
+constant operand and pushes the result.
+.I
+This operation is supplied specifically to be able to encode more field
+offsets in two bytes than can be done with "\f(CWDW_OP_lit\fP\fIn\fP\f(CW DW_OP_add\fP".
+.R
+.LI
+.Cf DW_OP_shl
+.br
+The
+.Cf DW_OP_shl
+operation pops the top two stack entries, shifts the former second
+entry left by the number of bits specified by the former top of
+the stack, and pushes the result.
+.LI
+.Cf DW_OP_shr
+.br
+The
+.Cf DW_OP_shr
+operation pops the top two stack entries, shifts the former second
+entry right (logically) by the number of bits specified by the former top of
+the stack, and pushes the result.
+.LI
+.Cf DW_OP_shra
+.br
+The
+.Cf DW_OP_shra
+operation pops the top two stack entries, shifts the former second
+entry right (arithmetically) by the number of bits specified by the former top of
+the stack, and pushes the result.
+.LI
+.Cf DW_OP_xor
+.br
+The
+.Cf DW_OP_xor
+operation pops the top two stack entries, performs the logical
+\fIexclusive-or\fP operation on the two, and pushes the result.
+.LE
+.H 4 "Control Flow Operations"
+.IX locations, control flow operations
+The following operations provide simple control of the flow of a location
+expression.
+.AL
+.LI
+Relational operators
+.br
+The six relational operators each pops the top two stack values,
+compares the former top of the stack with the former second entry,
+and pushes the constant value 1 onto the stack if the result of the
+operation is true or the constant value 0 if the result of the operation
+is false. The comparisons are done as signed operations. The six
+operators are
+.Cf DW_OP_le
+(less than or equal to),
+.Cf DW_OP_ge
+(greater than or equal to),
+.Cf DW_OP_eq
+(equal to),
+.Cf DW_OP_lt
+(less than),
+.Cf DW_OP_gt
+(greater than) and
+.Cf DW_OP_ne
+(not equal to).
+.LI
+.Cf DW_OP_skip
+.br
+.Cf DW_OP_skip
+is an unconditional branch. Its
+single operand is a 2-byte signed integer constant.
+The 2-byte constant is the number of bytes of the location
+expression to skip from the current operation, beginning after the
+2-byte constant.
+.LI
+.Cf DW_OP_bra
+.br
+.Cf DW_OP_bra
+is a conditional branch. Its
+single operand is a 2-byte signed integer constant.
+This operation pops the top of stack. If the value
+popped is not the constant 0, the 2-byte constant operand is the number
+of bytes of the location
+expression to skip from the current operation, beginning after the
+2-byte constant.
+.LE
+.H 4 "Special Operations"
+.IX locations, special operations
+There are two special operations currently defined:
+.AL
+.LI
+.Cf DW_OP_piece
+.br
+.I
+Many compilers store a single variable in sets of registers, or store
+a variable partially in memory and partially in registers.
+.Cf DW_OP_piece
+provides a way of describing how large a part of a variable
+a particular addressing expression refers to.
+.R
+.P
+.Cf DW_OP_piece
+takes a single argument which is an unsigned LEB128 number. The number
+describes the size in bytes of the piece of the object referenced
+by the addressing expression whose result is at the top of
+the stack.
+.LI
+.Cf DW_OP_nop
+.br
+The
+.Cf DW_OP_nop
+operation is a place holder. It has no effect on the location stack or
+any of its values.
+.LE
+.H 3 "Sample Stack Operations"
+.IX locations, examples
+.I
+The stack operations defined in section 2.4.3.3 are fairly
+.IX locations, stack
+conventional, but the following examples illustrate their behavior
+graphically.
+.R
+.DS
+.TS
+box expand center tab(;);
+l s l l s
+lf(CW) lf(CW) lf(CW) lf(CW) lf(CW)
+.
+Before;Operation;After;
+_
+0;17;DW_OP_dup;0;17
+1;29;;1;17
+2;1000;;2;29
+;;;3;1000
+_
+0;17;DW_OP_drop;0;29
+1;29;;1;1000
+2;1000;;;;
+_
+0;17;DW_OP_pick 2;0;1000
+1;29;;1;17
+2;1000;;2;29
+;;;3;1000
+_
+0;17;DW_OP_over;0;29
+1;29;;1;17
+2;1000;;2;29
+;;;3;1000
+_
+0;17;DW_OP_swap;0;29
+1;29;;1;17
+2;1000;;2;1000
+_
+0;17;DW_OP_rot;0;29
+1;29;;1;1000
+2;1000;;2;17
+.TE
+.DE
+.H 3 "Example Location Expressions"
+.I
+.IX locations, examples
+The addressing expression represented by a location expression,
+if evaluated, generates the
+runtime address of the value of a symbol except where the
+.Cf DW_OP_reg n,
+or
+.Cf DW_OP_regx
+operations are used.
+.P
+Here are some examples of how location operations are used to form location
+expressions:
+.R
+.DS
+\f(CWDW_OP_reg3\fI
+ The value is in register 3.
+
+\f(CWDW_OP_regx 54\fI
+ The value is in register 54.
+
+\f(CWDW_OP_addr 0x80d0045c\fI
+ The value of a static variable is
+ at machine address 0x80d0045c.
+
+\f(CWDW_OP_breg11 44\fI
+ Add 44 to the value in
+ register 11 to get the address of an
+ automatic variable instance.
+
+\f(CWDW_OP_fbreg -50\fI
+ Given an \f(CWDW_AT_frame_base\fI value of
+ "\f(CWOPBREG31 64\fI," this example
+ computes the address of a local variable
+ that is -50 bytes from a logical frame
+ pointer that is computed by adding
+ 64 to the current stack pointer (register 31).
+
+\f(CWDW_OP_bregx 54 32 DW_OP_deref\fI
+ A call-by-reference parameter
+ whose address is in the
+ word 32 bytes from where register
+ 54 points.
+
+\f(CWDW_OP_plus_uconst 4\fI
+ A structure member is four bytes
+ from the start of the structure
+ instance. The base address is
+ assumed to be already on the stack.
+
+\f(CWDW_OP_reg3 DW_OP_piece 4 DW_OP_reg10 DW_OP_piece 2\fI
+ A variable whose first four bytes reside
+ in register 3 and whose next two bytes
+ reside in register 10.\fR
+.DE
+.H 3 "Location Lists"
+.IX locations, lists
+Location lists are used in place of location expressions whenever
+the object whose location is being described can change location
+during its lifetime. Location lists are contained in a separate
+object file section called
+.Cf .debug_loc.
+.IX \f(CW.debug_loc\fP %debugalo
+A location list is indicated by a location
+attribute whose value is represented as a
+constant offset from the beginning of the
+.Cf .debug_loc
+section to the first byte of the list for the object in question.
+.P
+Each entry in a location list consists of:
+.AL
+.LI
+A beginning address. This address is relative to the base address
+of the compilation unit referencing this location list. It marks
+the beginning of the address range over which the location is valid.
+.LI
+An ending address, again relative to the base address
+of the compilation unit referencing this location list. It marks
+the first address past the end of the address range over
+which the location is valid.
+.LI
+A location expression describing the location of the object over the
+range specified by the beginning and end addresses.
+.LE
+.P
+Address ranges may overlap. When they do, they describe a situation
+in which an object exists simultaneously in more than one place.
+If all of the address ranges
+in a given location list do not collectively cover the entire
+range over which the object in question is defined, it is assumed
+that the object is not available for the portion of the range that is not
+covered.
+.IX optimized code
+.P
+The end of any given location list is marked by a 0 for the beginning
+address and a 0 for the end address; no location description is present.
+A location list containing
+only such a 0 entry describes an object that exists in the source
+code but not in the executable program.
+.H 2 "Types of Declarations"
+.IX declarations, types of
+Any debugging information entry describing a declaration that
+has a type has a
+.Cf DW_AT_type
+attribute, whose value is a reference to another debugging
+information entry. The entry referenced may describe
+.IX base types
+.IX types, base
+a base type, that is, a type that is not defined in terms
+.IX user-defined types
+.IX types, user-defined
+of other data types, or it may describe a user-defined type,
+such as an array, structure or enumeration. Alternatively,
+the entry referenced may describe a type modifier: constant,
+packed, pointer, reference or volatile, which in turn will reference
+another entry describing a type or type modifier (using a
+.IX type modifiers
+.IX types, modifiers
+.IX types, packed
+.IX types, constant
+.IX types, pointer
+.IX types, reference
+.IX types, volatile
+.Cf DW_AT_type
+attribute of its own). See section 5 for descriptions of
+the entries describing base types, user-defined types and
+type modifiers.
+.H 2 "Accessibility of Declarations"
+.I
+.IX accessibility
+.IX declarations, accessibility
+Some languages, notably C++ and Ada, have the concept of
+.IX C++ %caa
+the accessibility of an object or of some other program entity.
+The accessibility specifies which classes of other program objects
+are permitted access to the object in question.
+.R
+.P
+The accessibility of a declaration is represented by a
+.Cf DW_AT_accessibility
+attribute, whose value is a constant drawn from the set of codes
+.nr aX \n(Fg+1
+listed in Figure \n(aX.
+.DF
+.TS
+box center;
+lf(CW)
+.
+DW_ACCESS_public
+DW_ACCESS_private
+DW_ACCESS_protected
+.TE
+.FG "Accessibility codes"
+.DE
+.H 2 "Visibility of Declarations"
+.I
+.IX Modula2
+.IX visibility
+.IX declarations, visibility
+Modula2 has the concept of the visibility of a declaration.
+The visibility specifies which declarations are to be visible outside
+of the module in which they are declared.
+.R
+.P
+The visibility of a declaration is represented by a
+.Cf DW_AT_visibility
+attribute, whose value is a constant drawn from the set of codes
+.nr aX \n(Fg+1
+listed in Figure \n(aX.
+.DF
+.TS
+box center;
+lf(CW)
+.
+DW_VIS_local
+DW_VIS_exported
+DW_VIS_qualified
+.TE
+.FG "Visibility codes"
+.DE
+.H 2 "Virtuality of Declarations"
+.I
+.IX C++ %caa
+.IX virtuality
+.IX virtual functions
+C++ provides for virtual and pure virtual structure or class
+member functions and for virtual base classes.
+.P
+.R
+The virtuality of a declaration is represented by a
+.Cf DW_AT_virtuality
+attribute, whose value is a constant drawn from the set of codes
+.nr aX \n(Fg+1
+listed in Figure \n(aX.
+.DF
+.TS
+box center;
+lf(CW)
+.
+DW_VIRTUALITY_none
+DW_VIRTUALITY_virtual
+DW_VIRTUALITY_pure_virtual
+.TE
+.FG "Virtuality codes"
+.DE
+.H 2 "Artificial Entries"
+.I
+.IX artificial entries
+A compiler may wish to generate debugging information entries
+for objects or types that were not actually declared
+in the source of the application. An example is a formal parameter
+entry to represent the hidden
+.Cf this
+parameter that most C++ implementations pass as the first argument
+to non-static member functions.
+.R
+.P
+Any debugging information entry representing the declaration of an
+object or type artificially generated by a compiler and
+not explicitly declared by the source program may have a
+.Cf DW_AT_artificial
+attribute. The value of this attribute is a flag.
+.H 2 "Target-Specific Addressing Information"
+.I
+.IX segmented address space
+.IX address space, segmented
+In some systems, addresses are specified as offsets within a given
+segment rather than as locations within a single flat address space.
+.R
+.P
+Any debugging information entry that contains a description of the
+location of an object or subroutine may have a
+.Cf DW_AT_segment
+attribute, whose value is a location description. The description
+evaluates to the segment value of the item being described. If
+the entry containing the
+.Cf DW_AT_segment
+attribute has a
+.Cf DW_AT_low_pc
+or
+.Cf DW_AT_high_pc
+attribute, or a location description that evaluates to an address,
+.IX locations, descriptions
+.IX addresses, offset portion
+then those values represent the offset portion of the address
+within the segment specified by
+.Cf DW_AT_segment .
+.P
+If an entry has no
+.Cf DW_AT_segment
+attribute, it inherits the segment value from its parent entry.
+If none of the entries in the chain of parents for this entry
+back to its containing compilation unit entry have
+.Cf DW_AT_segment
+attributes, then the entry is assumed to exist within a flat
+address space. Similarly, if the entry has a
+.IX flat address space
+.IX address space, flat
+.Cf DW_AT_segment
+attribute containing an empty location description, that entry
+is assumed to exist within a flat address space.
+.P
+.I
+Some systems support different classes of addresses. The address
+class may affect the way a pointer is dereferenced or the way
+a subroutine is called.
+.P
+.R
+Any debugging information entry representing a pointer or reference
+type or a subroutine or subroutine type may have a
+.IX types, pointer
+.IX types, reference
+.IX subroutines
+.IX subroutines, types
+.Cf DW_AT_address_class
+.IX addresses, class
+attribute, whose value is a constant. The set of permissible
+values is specific to each target architecture. The value
+.Cf DW_ADDR_none ,
+however, is common to all encodings, and means that no address class
+has been specified.
+.P
+.I
+For example, the Intel386\(tm processor might use the following
+values:
+.R
+.DF
+.TS
+box center;
+l l l
+lf(CW) lf(CW) l
+.
+Name Value Meaning
+_
+DW_ADDR_none 0 no class specified
+DW_ADDR_near16 1 16-bit offset, no segment
+DW_ADDR_far16 2 16-bit offset, 16-bit segment
+DW_ADDR_huge16 3 16-bit offset, 16-bit segment
+DW_ADDR_near32 4 32-bit offset, no segment
+DW_ADDR_far32 5 32-bit offset, 16-bit segment
+.TE
+.FG "Example address class codes"
+.DE
+.H 2 "Non-Defining Declarations"
+.IX declarations, non-defining
+.IX declarations, defining
+A debugging information entry representing a program object or type
+typically represents the defining declaration of that object or type. In
+certain contexts, however, a debugger might need information about a
+declaration of a subroutine, object or type that is not also a
+definition to evaluate an expression correctly.
+.P
+.I
+As an example, consider the following fragment of C code:
+.DS
+\f(CWvoid myfunc()
+{
+ int x;
+ {
+ extern float x;
+ g(x);
+ }
+}\fP
+.DE
+.P
+ANSI-C scoping rules require that the value of the variable \f(CWx\fP
+passed to the function \f(CWg\fP is the value of the global variable
+\f(CWx\fP rather than of the local version.
+.R
+.P
+Debugging information entries that represent non-defining declarations
+of a program object or type have a
+.Cf DW_AT_declaration
+attribute, whose value is a flag.
+.H 2 "Declaration Coordinates"
+.I
+It is sometimes useful in a debugger to be able to associate a declaration
+with its occurrence in the program source.
+.P
+.R
+.IX declarations, coordinates
+Any debugging information entry representing the declaration of
+an object, module, subprogram or type may have
+.Cf DW_AT_decl_file ,
+.Cf DW_AT_decl_line
+and
+.Cf DW_AT_decl_column
+attributes, each of whose value is a constant.
+.P
+The value of the
+.Cf DW_AT_decl_file
+attribute corresponds
+to a file number from the statement information table for the compilation
+.IX line number information
+unit containing this debugging information entry and represents the
+source file in which the declaration appeared (see section 6.2).
+.IX source, files
+The value 0 indicates that no source file has been specified.
+.P
+The value of the
+.Cf DW_AT_decl_line
+attribute represents the source line number at which the first
+.IX source, lines
+character of the identifier of the declared object appears.
+The value 0 indicates that no source line has been specified.
+.P
+The value of the
+.Cf DW_AT_decl_column
+attribute represents the source column number at which the first
+.IX source, columns
+character of the identifier of the declared object appears.
+The value 0 indicates that no column has been specified.
+.H 2 "Identifier Names"
+.IX identifiers, names
+Any debugging information entry representing a program entity that
+has been given a name may have a
+.Cf DW_AT_name
+attribute, whose value is a string representing the name as it appears
+in the source program. A debugging information entry containing
+no name attribute, or containing a name attribute whose value consists
+of a name containing a single null byte,
+represents a program entity for which no name was given in the source.
+.I
+.P
+Note that since the names of program objects
+described by DWARF are the names as they appear in the source program,
+implementations of language translators that use some form of mangled
+name (as do many implementations of C++) should use the unmangled
+.IX C++ %caa
+form of the name in the DWARF
+.Cf DW_AT_name
+attribute, including the keyword
+.Cf operator ,
+if present. Sequences of multiple whitespace characters may be compressed.
+.R
+.OP
+.H 1 "PROGRAM SCOPE ENTRIES"
+This section describes debugging information entries that relate
+to different levels of program scope: compilation unit, module,
+subprogram, and so on. These entries may be thought of as
+bounded by ranges of text addresses within the program.
+.H 2 "Compilation Unit Entries"
+An object file may be derived from one or more compilation units. Each
+such compilation unit will be described by a debugging information
+entry with the tag \f(CWDW_TAG_compile_unit\fP.
+.I
+.P
+A compilation unit typically represents the text and data contributed
+.IX compilation units
+to an executable by a single relocatable object file. It may
+be derived from several source files, including pre-processed ``include
+files.''
+.R
+.P
+The compilation unit entry may have the following attributes:
+.AL
+.LI
+A
+.Cf DW_AT_low_pc
+attribute whose value is the
+relocated address of the first machine instruction generated for that
+compilation unit.
+.LI
+A
+.Cf DW_AT_high_pc
+attribute whose value is the
+relocated address of the first location
+past the last machine instruction generated for that compilation unit.
+.P
+.I
+The address may be beyond the last valid instruction in the executable,
+of course, for this and other similar attributes.
+.R
+.P
+The presence of low and high pc attributes in a compilation unit entry
+imply that the code generated for that compilation unit is
+contiguous and exists totally within the boundaries specified
+by those two attributes. If that is not the case, no low
+and high pc attributes should be produced.
+.IX address space, contiguous
+.LI
+A
+.Cf DW_AT_name
+attribute whose value is a
+null-terminated string containing the full or relative path name of
+the primary source file from which the compilation unit was derived.
+.IX source, files
+.LI
+A
+.Cf DW_AT_language
+attribute whose constant value is
+.IX languages
+a code indicating the source language of the compilation unit.
+.nr aX \n(Fg+1
+The set of language names and their meanings are
+given in Figure \n(aX.
+.DF
+.TS
+box center;
+lf(CW) lf(R)
+.
+DW_LANG_C Non-ANSI C, such as K&R
+DW_LANG_C89 ISO/ANSI C
+DW_LANG_C_plus_plus C++
+DW_LANG_Fortran77 FORTRAN77
+DW_LANG_Fortran90 Fortran90
+DW_LANG_Modula2 Modula2
+DW_LANG_Pascal83 ISO/ANSI Pascal
+.TE
+.FG "Language names"
+.DE
+.LI
+A
+.Cf DW_AT_stmt_list
+attribute whose value is a reference to
+line number information for this compilation unit.
+.IX line number information
+.P
+This information is placed in a separate object file section from the debugging
+information entries themselves. The value of the statement list attribute
+is the offset in the \f(CW.debug_line\fP section of the first byte of the
+line number information for this compilation unit. See section 6.2.
+.LI
+A
+.Cf DW_AT_macro_info
+attribute whose value is a reference to the macro information for this
+compilation unit.
+.IX macro information
+.P
+This information is placed in a separate object file section from the debugging
+information entries themselves. The value of the macro information attribute
+is the offset in the \f(CW.debug_macinfo\fP section of the first byte of the
+macro information for this compilation unit. See section 6.3.
+.LI
+A
+.Cf DW_AT_comp_dir
+attribute whose value is a null-terminated string containing
+the current working directory of the compilation command that
+produced this compilation unit in whatever form makes sense
+for the host system.
+.P
+.I
+The suggested form for the value of the \f(CWDW_AT_comp_dir\fP
+attribute on \*(aX systems is ``hostname\f(CW:\fPpathname''. If no
+hostname is available, the suggested form is ``\f(CW:\fPpathname''.
+.R
+.LI
+A
+.Cf DW_AT_producer
+attribute whose value is a null-terminated string containing information
+about the compiler that produced the compilation unit. The
+actual contents of the string will be specific to each producer,
+but should begin with the name of the compiler vendor or some
+other identifying character sequence that should avoid
+confusion with other producer values.
+.LI
+A
+.Cf DW_AT_identifier_case
+.IX identifiers, case
+attribute whose constant value is a code describing the treatment of
+identifiers within this compilation unit. The set of identifier case
+.nr aX \n(Fg+1
+codes is given in Figure \n(aX.
+.DF
+.TS
+box center;
+lf(CW)
+.
+DW_ID_case_sensitive
+DW_ID_up_case
+DW_ID_down_case
+DW_ID_case_insensitive
+.TE
+.FG "Identifier case codes"
+.DE
+.P
+.Cf DW_ID_case_sensitive
+is the default for all compilation units that do not have this attribute.
+It indicates that names given as the values of
+.Cf DW_AT_name
+attributes in debugging information entries for the compilation unit
+reflect the names as they appear in the source program.
+The debugger should be sensitive to the case of identifier names
+when doing identifier lookups.
+.P
+.Cf DW_ID_up_case
+means that the producer of the debugging information for this compilation
+unit converted all source names to upper case. The values of the
+name attributes may not reflect the names as they appear in the source
+program. The debugger should convert all names to upper case
+when doing lookups.
+.P
+.Cf DW_ID_down_case
+means that the producer of the debugging information for this compilation
+unit converted all source names to lower case. The values of the
+name attributes may not reflect the names as they appear in the source
+program. The debugger should convert all names to lower case when
+doing lookups.
+.P
+.Cf DW_ID_case_insensitive
+means that the values of the name attributes reflect the names
+as they appear in the source program but that a case insensitive
+lookup should be used to access those names.
+.LI
+A
+.Cf DW_AT_base_types
+.IX base types
+.IX types, base
+attribute whose value is a reference. This attribute points to
+a debugging information entry representing another compilation
+unit. It may be used to specify the compilation unit containing
+the base type entries used by entries in the current compilation
+unit (see section 5.1).
+.P
+.I
+This attribute provides a consumer a way to find the definition
+of base types for a compilation unit that does not itself
+contain such definitions. This allows a consumer, for example,
+to interpret a type conversion to a base type correctly.
+.R
+.LE
+.R
+.P
+A compilation unit entry
+owns debugging information entries that represent the declarations made in
+the corresponding compilation unit.
+.H 2 "Module Entries"
+.I
+Several languages have the concept of a ``module.''
+.IX modules
+.P
+.R
+A module is
+represented by a debugging information entry with the tag
+.Cf DW_TAG_module .
+Module entries may own other debugging information entries describing
+program entities whose declaration scopes end at the end of the module
+itself.
+.P
+If the module has a name, the module entry has a
+.Cf DW_AT_name
+attribute whose
+value is a null-terminated string containing the module name as it appears
+in the source program.
+.P
+If the module contains initialization code, the module entry
+has a
+.Cf DW_AT_low_pc
+attribute whose value is the
+relocated address of the first machine instruction generated for that
+initialization code. It also has a
+.Cf DW_AT_high_pc
+attribute whose value is
+the relocated address of the first location past the last machine
+instruction generated for the initialization code.
+.P
+If the module has been assigned a priority, it may have a
+.Cf DW_AT_priority
+attribute. The value of this attribute is a reference to another
+.IX modules, priority
+debugging information entry describing a variable with a constant
+value. The value of this variable is the actual constant
+value of the module's priority, represented as it would be on the
+target architecture.
+.P
+.I
+.IX Modula2
+.IX modules, definition
+A Modula2 definition module may be represented by a module entry
+containing a
+.Cf DW_AT_declaration
+attribute.
+.R
+.H 2 "Subroutine and Entry Point Entries"
+.IX subroutines
+.IX entry points
+The following tags exist to describe debugging information
+entries for subroutines and entry points:
+.VL 30
+.LI \f(CWDW_TAG_subprogram\fP
+A global or file static subroutine or function.
+.LI \f(CWDW_TAG_inlined_subroutine\fP
+A particular inlined instance of a subroutine or function.
+.LI \f(CWDW_TAG_entry_point\fP
+A Fortran entry point.
+.LE
+.H 3 "General Subroutine and Entry Point Information"
+The subroutine or entry point entry has a
+.Cf DW_AT_name
+attribute
+whose value is a null-terminated string containing the subroutine or entry
+point name as it appears in the source program.
+.P
+If the name of the subroutine described by an entry with the tag
+.Cf DW_TAG_subprogram
+is visible outside of its containing compilation unit, that
+entry has a
+.Cf DW_AT_external
+attribute, whose value is a flag.
+.IX declarations, external
+.I
+.P
+.IX members, functions
+.IX subroutines, members
+Additional attributes for functions that are members of a class or
+structure are described in section 5.5.5.
+.P
+A common debugger feature is to allow the debugger user to call a
+subroutine within the subject program. In certain cases, however,
+the generated code for a subroutine will not obey the standard calling
+conventions for the target architecture and will therefore not
+.IX calling conventions
+be safe to call from within a debugger.
+.R
+.P
+A subroutine entry may contain a
+.Cf DW_AT_calling_convention
+attribute, whose value is a constant. If this attribute is not
+present, or its value is the constant
+.Cf DW_CC_normal ,
+then the subroutine may be safely called by obeying the ``standard''
+calling conventions of the target architecture. If the value of
+the calling convention attribute is the constant
+.Cf DW_CC_nocall ,
+the subroutine does not obey standard calling conventions, and it
+may not be safe for the debugger to call this subroutine.
+.P
+If the semantics of the language of the compilation unit
+containing the subroutine entry distinguishes between ordinary subroutines
+.IX main programs
+and subroutines that can serve as the ``main program,'' that is, subroutines
+that cannot be called directly following the ordinary calling conventions,
+then the debugging information entry for such a subroutine may have a
+calling convention attribute whose value is the constant
+.Cf DW_CC_program .
+.P
+.I
+The
+.Cf DW_CC_program
+value is intended to support Fortran main programs.
+It is not intended as a way of finding the entry address for the program.
+.R
+.H 3 "Subroutine and Entry Point Return Types"
+.IX subroutines, return types
+.IX entry points, return types
+If the subroutine or entry point is a function that returns a value, then
+its debugging information entry has a
+.Cf DW_AT_type
+attribute to denote the type returned by that function.
+.P
+.I
+Debugging information entries for C
+.Cf void
+.IX C %c
+functions should not have an attribute for the return type.
+.P
+In ANSI-C there is a difference between the types of functions
+declared using function prototype style declarations and those
+declared using non-prototype declarations.
+.IX subroutines, prototypes
+.P
+.R
+A subroutine entry
+declared with a function prototype style declaration may have a
+.Cf DW_AT_prototyped
+attribute, whose value is a flag.
+.H 3 "Subroutine and Entry Point Locations"
+.IX subroutines, locations
+.IX entry points, locations
+A subroutine entry has a
+.Cf DW_AT_low_pc
+attribute whose value is the relocated address of the first machine instruction
+generated for the subroutine.
+It also has a
+.Cf DW_AT_high_pc
+attribute whose value is the relocated address of the
+first location past the last machine instruction generated
+for the subroutine.
+.P
+.I
+Note that for the low and high pc attributes to have meaning, DWARF
+makes the assumption that the code for a single subroutine is allocated
+in a single contiguous block of memory.
+.IX address space, contiguous
+.R
+.P
+An entry point has a
+.Cf DW_AT_low_pc
+attribute whose value is the relocated address of the first machine instruction
+generated for the entry point.
+.P
+Subroutines and entry points may also have
+.Cf DW_AT_segment
+and
+.Cf DW_AT_address_class
+.IX segmented address space
+.IX address space, segmented
+.IX addresses, class
+attributes, as appropriate, to specify which segments the code
+for the subroutine resides in and the addressing mode to be used
+in calling that subroutine.
+.P
+A subroutine entry representing a subroutine declaration
+that is not also a definition does not have low and high pc attributes.
+.IX declarations, non-defining
+.H 3 "Declarations Owned by Subroutines and Entry Points"
+.IX subroutines, declarations owned by
+.IX entry points, declarations owned by
+The declarations enclosed by a subroutine or entry point
+are represented by debugging information entries that are
+owned by the subroutine or entry point entry.
+Entries representing the formal parameters of the subroutine or
+entry point appear in
+the same order as the corresponding declarations in the source program.
+.IX attributes, ordering
+.IX parameters, formal
+.P
+.I
+There is no ordering requirement on entries for declarations that are
+children of subroutine or entry point entries but that do not represent
+formal parameters. The formal parameter entries may be interspersed
+with other entries used by formal parameter entries, such as type entries.
+.R
+.P
+The unspecified parameters of a variable parameter list
+.IX parameters, unspecified
+are represented by a debugging information entry with the tag
+.Cf DW_TAG_unspecified_parameters .
+.P
+The entry for a subroutine or entry point that includes a Fortran
+.IX Fortran
+.IX common blocks
+common block has a child entry with the tag
+.Cf DW_TAG_common_inclusion .
+The common inclusion entry has a
+.Cf DW_AT_common_reference
+attribute whose value is a reference to the debugging entry for
+the common block being included (see section 4.2).
+.H 3 "Low-Level Information"
+A subroutine or entry point entry may have a
+.Cf DW_AT_return_addr
+.IX subroutines, return addresses
+attribute, whose value is a location description.
+The location calculated is the place where the return address for
+the subroutine or entry point is stored.
+.P
+A subroutine or entry point entry may also have a
+.Cf DW_AT_frame_base
+.IX subroutines, frame base
+attribute, whose value is a location description that
+computes the ``frame base'' for the subroutine or entry point.
+.P
+.I
+The frame base for a procedure is typically an address fixed
+relative to the first unit of storage allocated for the procedure's
+stack frame. The
+.Cf DW_AT_frame_base
+attribute can be used in several ways:
+.AL
+.LI
+In procedures that need location lists to locate local variables, the
+.Cf DW_AT_frame_base
+can hold the needed location list, while all variables'
+location descriptions can be simpler location expressions involving the frame
+base.
+.LI
+It can be used as a key in resolving "up-level" addressing with nested
+routines. (See
+.Cf DW_AT_static_link ,
+below)
+.LE
+.P
+Some languages support nested subroutines. In such languages, it is possible
+.IX subroutines, nested
+to reference the local variables of an outer subroutine from within
+an inner subroutine. The
+.Cf DW_AT_static_link
+and
+.Cf DW_AT_frame_base
+attributes allow debuggers to support this same kind of referencing.
+.R
+.P
+If a subroutine or entry point is nested, it may have a
+.Cf DW_AT_static_link
+attribute, whose value is a location description that
+computes the frame base of the relevant instance of the subroutine
+that immediately encloses the subroutine or entry point.
+.P
+In the context of supporting nested subroutines, the
+.Cf DW_AT_frame_base
+attribute value should obey the following constraints:
+.AL
+.LI
+It should compute a value that does not change during the life of the procedure,
+and
+.LI
+The computed value should be unique among instances of the same subroutine.
+(For typical
+.Cf DW_AT_frame_base
+use, this means that a recursive
+subroutine's stack frame must have non-zero size.)
+.LE
+.P
+.I
+If a debugger is attempting to resolve an up-level reference to a variable, it
+uses the nesting structure of DWARF to determine which subroutine is the lexical
+parent and the
+.Cf DW_AT_static_link
+value to identify the appropriate active frame
+of the parent. It can then attempt to find the reference within the context
+of the parent.
+.R
+.H 3 "Types Thrown by Exceptions"
+.I
+In C++ a subroutine may declare a set of types for which
+.IX C++ %caa
+.IX exceptions
+that subroutine may generate or ``throw'' an exception.
+.P
+.R
+If a subroutine explicitly declares that it may throw an
+exception for one or more types, each such type is
+represented by a debugging information entry with the tag
+.Cf DW_TAG_thrown_type .
+Each such entry is a child of the entry representing the
+subroutine that may throw this type. All thrown type entries
+should follow all entries representing the formal parameters
+of the subroutine and precede all entries representing the
+local variables or lexical blocks contained in the subroutine.
+Each thrown type entry contains a
+.Cf DW_AT_type
+attribute, whose value is a reference to an entry describing
+the type of the exception that may be thrown.
+.H 3 "Function Template Instantiations"
+.I
+.IX C++ %caa
+.IX templates
+In C++ a function template is a generic
+definition of a function that
+is instantiated differently when called with values
+of different types. DWARF does not represent the generic
+template definition, but does represent each instantiation.
+.R
+.P
+A template instantiation is represented by a debugging information
+entry with the tag
+.Cf DW_TAG_subprogram .
+With three exceptions,
+such an entry will contain the same attributes and have the same
+types of child entries as would an entry for a subroutine
+defined explicitly
+using the instantiation types. The exceptions are:
+.AL
+.LI
+Each formal parameterized type declaration appearing in the
+template definition is represented by a debugging information entry
+with the tag
+.Cf DW_TAG_template_type_parameter .
+Each such entry has a
+.Cf DW_AT_name
+attribute, whose value is a null-terminated
+string containing the name of the formal type parameter as it
+appears in the source program. The template type parameter
+entry also has a
+.Cf DW_AT_type
+attribute describing the actual type by
+which the formal is replaced for this instantiation.
+All template type parameter entries should appear before
+the entries describing the instantiated formal parameters
+to the function.
+.LI
+.IX compilation units
+If the compiler has generated a special compilation unit
+to hold the template instantiation and that compilation unit
+has a different name
+from the compilation unit containing the template definition,
+the name attribute for the debugging entry representing
+that compilation unit should be empty or omitted.
+.LI
+.IX declarations, coordinates
+If the subprogram entry representing the template instantiation
+or any of its child entries
+contain declaration coordinate attributes, those attributes
+should refer to the source for the template definition, not
+to any source generated artificially by the compiler for this
+instantiation.
+.LE
+.H 3 "Inline Subroutines"
+.IX subroutines, inline
+A declaration or a definition of an inlinable subroutine
+is represented by a debugging information entry with the tag
+.Cf DW_TAG_subprogram .
+The entry for a subroutine that is explicitly declared
+to be available for inline expansion or that was expanded inline
+implicitly by the compiler has a
+.Cf DW_AT_inline
+attribute whose value is a constant. The set of values
+for the
+.Cf DW_AT_inline
+.nr aX \n(Fg+1
+attribute is given in Figure \n(aX.
+.DF
+.TS
+box center;
+l l
+lf(CW) l
+.
+Name Meaning
+_
+DW_INL_not_inlined Not declared inline nor inlined by the compiler
+DW_INL_inlined Not declared inline but inlined by the compiler
+DW_INL_declared_not_inlined Declared inline but not inlined by the compiler
+DW_INL_declared_inlined Declared inline and inlined by the compiler
+.TE
+.FG "Inline codes"
+.DE
+.H 4 "Abstract Instances"
+For the remainder of this discussion,
+any debugging information entry that is owned (either directly or
+indirectly) by a debugging information entry that contains the
+.Cf DW_AT_inline
+attribute will be referred to as an ``abstract instance entry.''
+Any subroutine entry that contains a
+.Cf DW_AT_inline
+attribute will be known as an ``abstract instance root.''
+Any set of abstract instance entries that are all children (either directly
+or indirectly) of some abstract instance root, together with the root itself,
+will be known as an ``abstract instance tree.''
+.P
+A debugging information entry that is a member of an abstract instance
+tree should not contain a
+.Cf DW_AT_high_pc ,
+.Cf DW_AT_low_pc ,
+.Cf DW_AT_location ,
+.Cf DW_AT_return_addr ,
+.Cf DW_AT_start_scope ,
+or
+.Cf DW_AT_segment
+attribute.
+.P
+.I
+It would not make sense to put these attributes
+into abstract instance entries since
+such entries do not represent actual (concrete) instances and thus
+do not actually exist at run-time.
+.P
+.R
+The rules for the relative location of entries belonging to abstract instance
+trees are exactly
+the same as for other similar types of entries that are not abstract.
+Specifically, the rule that requires that an entry representing a
+declaration be a direct child of the entry representing the scope of
+the declaration applies equally to both abstract and
+non-abstract entries. Also, the ordering rules for formal parameter entries,
+member entries, and so on, all apply regardless of whether or not a given entry
+is abstract.
+.H 4 "Concrete Inlined Instances"
+.IX subroutines, inlined
+Each inline expansion of an inlinable subroutine is represented
+by a debugging information entry with the tag
+.Cf DW_TAG_inlined_subroutine .
+Each such entry should be a direct child of the entry that represents the
+scope within which the inlining occurs.
+.P
+Each inlined subroutine entry contains a
+.Cf DW_AT_low_pc
+attribute, representing the address of the first
+instruction associated with the given inline
+expansion. Each inlined subroutine entry also contains a
+.Cf DW_AT_high_pc
+attribute, representing the
+address of the first location past the last instruction associated with
+the inline expansion.
+.P
+For the remainder of this discussion,
+any debugging information entry that is owned (either directly or indirectly)
+by a debugging information entry with the tag
+.Cf DW_TAG_inlined_subroutine
+will be referred to as a ``concrete inlined instance entry.''
+Any entry that has the tag
+.Cf DW_TAG_inlined_subroutine
+will be known as
+a ``concrete inlined instance root.''
+Any set of concrete inlined instance entries that are all children (either
+directly or indirectly) of some concrete inlined instance root, together
+with the root itself, will be known as a ``concrete inlined instance
+tree.''
+.P
+Each concrete inlined instance tree is uniquely associated with one (and
+only one) abstract instance tree.
+.P
+.I
+Note, however, that the reverse is not true. Any given abstract instance
+tree may be associated with several different concrete inlined instance
+trees, or may even be associated with zero concrete inlined instance
+trees.
+.P
+.R
+Also, each separate entry within a given concrete inlined instance tree is
+uniquely associated with one particular entry in the associated abstract
+instance tree. In other words, there is a one-to-one mapping from entries
+in a given concrete inlined instance tree to the entries in the associated
+abstract instance tree.
+.P
+.I
+Note, however, that the reverse is not true. A given abstract instance
+tree that is associated with a given concrete inlined instance tree
+may (and quite probably will) contain more entries than the associated
+concrete inlined instance tree (see below).
+.R
+.P
+Concrete inlined instance entries do not have most of the attributes (except
+for
+.Cf DW_AT_low_pc ,
+.Cf DW_AT_high_pc ,
+.Cf DW_AT_location ,
+.Cf DW_AT_return_addr ,
+.Cf DW_AT_start_scope
+and
+.Cf DW_AT_segment )
+that such entries
+would otherwise normally have. In place of these omitted attributes,
+each concrete inlined instance entry has a
+.Cf DW_AT_abstract_origin
+attribute that
+may be used to obtain the missing information (indirectly) from
+the associated abstract instance entry. The value of the abstract
+origin attribute is a reference to the associated abstract instance entry.
+.P
+For each pair of entries that are associated via a
+.Cf DW_AT_abstract_origin
+attribute, both members of the pair will have the same tag. So, for
+example, an entry with the tag
+.Cf DW_TAG_local_variable
+can only be associated
+with another entry that also has the tag
+.Cf DW_TAG_local_variable.
+The only exception to this rule is that the root of a concrete
+instance tree (which must always have the tag
+.Cf DW_TAG_inlined_subroutine )
+can only be associated with the root of its associated abstract
+instance tree (which must have the tag
+.Cf DW_TAG_subprogram ).
+.P
+In general, the structure and content of any given concrete
+instance tree will be directly analogous to the structure and content
+of its associated abstract instance tree.
+There are two exceptions to this general rule however.
+.AL
+.LI
+.IX anonymous types
+No entries representing anonymous types are ever made a part
+of any concrete instance inlined tree.
+.LI
+.IX members
+No entries representing members of structure, union or class
+types are ever made a part of any concrete inlined instance tree.
+.LE
+.P
+.I
+Entries that represent members and anonymous types are omitted from concrete
+inlined instance trees because they would simply be redundant duplicates of
+the corresponding entries in the associated abstract instance trees. If
+any entry within a concrete inlined instance tree needs to refer to an
+anonymous type that was declared within the scope of the
+relevant inline function, the reference should simply refer to the abstract
+instance entry for the given anonymous type.
+.R
+.P
+.IX declarations, coordinates
+If an entry within a concrete inlined instance tree contains
+attributes describing the declaration coordinates of
+that entry,
+then those attributes should refer to the file, line and column
+of the original declaration of the subroutine, not to the
+point at which it was inlined.
+.H 4 "Out-of-Line Instances of Inline Subroutines"
+.IX subroutines, out-of-line
+Under some conditions, compilers may need to generate concrete executable
+instances of inline subroutines other than at points where those subroutines
+are actually called. For the remainder of this discussion,
+such concrete instances of inline subroutines will
+be referred to as ``concrete out-of-line instances.''
+.P
+.I
+In C++, for example, taking the address of a function declared to be inline
+can necessitate the generation of a concrete out-of-line
+instance of the given function.
+.P
+.R
+The DWARF representation of a concrete out-of-line instance of an inline
+subroutine is essentially the same as for a concrete inlined instance of
+that subroutine (as described in the preceding section). The representation
+of such a concrete out-of-line instance makes use of
+.Cf DW_AT_abstract_origin
+attributes in exactly the same way as they are used for a concrete inlined
+instance (that is, as references to corresponding entries
+within the associated
+abstract instance tree) and, as for concrete instance trees, the
+entries for anonymous types and for all members are omitted.
+.P
+The differences between the DWARF representation of a concrete out-of-line
+instance of a given subroutine and the representation of a concrete inlined
+instance of that same subroutine are as follows:
+.AL
+.LI
+The root entry for a concrete out-of-line instance of a given
+inline subroutine has the same tag as does its associated
+(abstract) inline subroutine entry (that is, it does not have the
+tag
+.Cf DW_TAG_inlined_subroutine ).
+.LI
+The root entry for a concrete out-of-line instance tree is
+always directly owned by the same parent entry that
+also owns the root entry of the associated abstract instance.
+.LE
+.H 2 "Lexical Block Entries"
+.I
+.IX lexical blocks
+A lexical block is a bracketed sequence of source statements that may
+contain any number of declarations. In some languages (C and C++)
+blocks can be nested within other blocks to any depth.
+.P
+.R
+A lexical block is represented by a debugging information entry
+with the tag
+.Cf DW_TAG_lexical_block .
+.P
+The lexical block entry has a
+.Cf DW_AT_low_pc
+attribute whose value is the
+relocated address of the first machine instruction generated for the lexical
+block.
+The lexical block entry also has a
+.Cf DW_AT_high_pc
+attribute whose value is the
+relocated address of the first location
+past the last machine instruction generated for the lexical block.
+.P
+If a name has been given to the lexical block in the source program,
+then the corresponding lexical block entry has a
+.Cf DW_AT_name
+attribute
+whose value is a null-terminated string containing the name of the
+lexical block as it appears in the source program.
+.P
+.I
+This is not the
+same as a C or C++ label (see below).
+.R
+.P
+The lexical block entry owns debugging information entries that
+describe the declarations within that lexical block.
+There is one such debugging information entry for each local declaration
+of an identifier or inner lexical block.
+.H 2 "Label Entries"
+.I
+.IX labels
+A label is a way of identifying a source statement. A labeled statement
+is usually the target of one or more ``go to'' statements.
+.P
+.R
+A label is represented by a debugging information entry
+with the tag
+.Cf DW_TAG_label .
+The entry for a label should be owned by
+the debugging information entry representing the scope within which the name
+of the label could be legally referenced within the source program.
+.P
+The label entry has a
+.Cf DW_AT_low_pc
+attribute whose value is the
+relocated address of the first machine instruction generated for the
+statement identified by the label in the source program.
+The label entry also has a
+.Cf DW_AT_name
+attribute
+whose value is a null-terminated string containing the name of the
+label as it appears in the source program.
+.H 2 "With Statement Entries"
+.I
+.IX with statements
+.IX Pascal
+.IX Modula2
+Both Pascal and Modula support the concept of a ``with'' statement.
+The with statement specifies a sequence of executable statements
+within which the fields of a record variable may be referenced, unqualified
+by the name of the record variable.
+.P
+.R
+A with statement is represented by a debugging information entry with
+the tag
+.Cf DW_TAG_with_stmt .
+A with statement entry has a
+.Cf DW_AT_low_pc
+attribute whose value is the relocated
+address of the first machine instruction generated for the body of
+the with statement. A with statement entry also has a
+.Cf DW_AT_high_pc
+attribute whose value is the relocated
+address of the first location after the last machine instruction generated for the body of
+the statement.
+.P
+The with statement entry has a
+.Cf DW_AT_type
+attribute, denoting
+the type of record whose fields may be referenced without full qualification
+within the body of the statement. It also has a
+.Cf DW_AT_location
+attribute, describing how to find the base address
+of the record object referenced within the body of the with statement.
+.H 2 "Try and Catch Block Entries"
+.I
+.IX C++ %caa
+.IX exceptions
+.IX try blocks
+.IX catch blocks
+In C++ a lexical block may be designated as a ``catch block.''
+A catch block is an exception handler that handles exceptions
+thrown by an immediately preceding ``try block.'' A catch block
+designates the type of the exception that it can handle.
+.R
+.P
+A try block is represented by a debugging information entry
+with the tag
+.Cf DW_TAG_try_block .
+A catch block is represented by a debugging information entry
+with the tag
+.Cf DW_TAG_catch_block .
+Both try and catch block entries contain a
+.Cf DW_AT_low_pc
+attribute whose value is the
+relocated address of the first machine instruction generated for that
+block. These entries also contain a
+.Cf DW_AT_high_pc
+attribute whose value is the
+relocated address of the first location
+past the last machine instruction generated for that block.
+.P
+Catch block entries have at least one child entry,
+an entry representing the type of exception accepted
+by that catch block. This child entry will have one of the tags
+.Cf DW_TAG_formal_parameter
+or
+.Cf DW_TAG_unspecified_parameters ,
+.IX parameters, formal
+.IX parameters, unspecified
+and will have the same form as other parameter entries.
+.P
+The first sibling of each try block entry will be a catch block
+entry.
+.OP
+.H 1 "DATA OBJECT AND OBJECT LIST ENTRIES"
+This section presents the debugging information entries that
+describe individual data objects: variables, parameters and
+constants, and lists of those objects that may be grouped
+in a single declaration, such as a common block.
+.H 2 "Data Object Entries"
+.IX variables
+.IX parameters, formal
+.IX constants
+Program variables, formal parameters and constants are represented
+by debugging information entries with the tags
+.Cf DW_TAG_variable ,
+.Cf DW_TAG_formal_parameter
+and
+.Cf DW_TAG_constant ,
+respectively.
+.P
+.I
+The tag
+.Cf DW_TAG_constant
+is used for languages that distinguish between variables
+that may have constant value and true named constants.
+.R
+.P
+The debugging information entry for a program variable, formal
+parameter or constant may have the following attributes:
+.AL
+.LI
+A
+.Cf DW_AT_name
+attribute whose value is a null-terminated
+string containing the data object name as it appears in the source program.
+.P
+.IX anonymous unions
+.IX unions, anonymous
+.IX C++ %caa
+If a variable entry describes a C++ anonymous union, the name
+attribute is omitted or consists of a single zero byte.
+.LI
+If the name of a variable is visible outside of its enclosing
+compilation unit, the variable entry has a
+.Cf DW_AT_external
+.IX declarations, external
+attribute, whose value is a flag.
+.I
+.P
+.IX members, static data
+The definitions of C++ static data members
+of structures or classes are represented by variable entries flagged
+as external.
+.IX C %c
+.IX C++ %caa
+Both file static and local variables in C and C++ are represented
+by non-external variable entries.
+.R
+.LI
+A
+.Cf DW_AT_location
+attribute, whose value describes the location of a variable or parameter
+at run-time.
+.P
+.IX declarations, non-defining
+A data object entry representing a non-defining declaration of the object
+will not have a location attribute, and will have the
+.Cf DW_AT_declaration
+attribute.
+.P
+In a variable entry representing the definition of the variable
+(that is, with no
+.Cf DW_AT_declaration
+attribute)
+if no location attribute is present, or if
+the location attribute is present but describes
+a null entry (as described in section 2.4), the variable
+is assumed to exist in the source code but not in the executable
+program (but see number 9, below).
+.IX optimized code
+.P
+The location of a variable may be further specified with a
+.Cf DW_AT_segment
+attribute, if appropriate.
+.IX segmented address space
+.IX address space, segmented
+.LI
+A
+.Cf DW_AT_type
+attribute describing the type of the variable, constant or formal
+parameter.
+.LI
+.IX members, static data
+.IX declarations, defining
+If the variable entry represents the defining declaration for a C++ static
+data member of a structure, class or union, the entry has a
+.Cf DW_AT_specification
+attribute, whose value is a reference to the debugging information
+entry representing the declaration of this data member. The
+referenced entry will be a child of some class, structure or
+union type entry.
+.IX classes
+.IX structures
+.IX unions
+.P
+Variable entries containing the
+.Cf DW_AT_specification
+attribute do not need to duplicate information provided by the
+declaration entry referenced by the specification attribute.
+In particular, such variable entries do not need to contain
+attributes for the name or type of the data member whose
+definition they represent.
+.LI
+.I
+Some languages distinguish between parameters whose value in the
+calling function can be modified by the callee (variable parameters),
+and parameters whose value in the calling function cannot be modified
+by the callee (constant parameters).
+.P
+.R
+If a formal parameter entry represents a parameter whose value
+in the calling function may be modified by the callee, that entry
+may have a
+.Cf DW_AT_variable_parameter
+attribute, whose value is a flag. The absence of this attribute
+implies that the parameter's value in the calling function cannot
+be modified by the callee.
+.IX parameters, variable
+.LI
+.I
+Fortran90 has the concept of an optional parameter.
+.IX Fortran90
+.P
+.R
+.IX parameters, optional
+If a parameter entry represents an optional parameter, it has a
+.Cf DW_AT_is_optional
+attribute, whose value is a flag.
+.LI
+.IX parameters, default value
+A formal parameter entry describing a formal parameter that has a default
+value may have a
+.Cf DW_AT_default_value
+attribute. The value of this attribute is a reference to the
+debugging information entry for a variable or subroutine. The
+default value of the parameter is the value of the variable (which
+may be constant) or the value returned by the subroutine. If the
+value of the
+.Cf DW_AT_default_value
+attribute is 0, it means that no default value has been specified.
+.LI
+.IX constants
+An entry describing a variable whose value is constant
+and not represented by an object in the address space of the program,
+or an entry describing a named constant,
+does not have a location attribute. Such entries have a
+.Cf DW_AT_const_value
+attribute, whose value may be a string or any of the constant
+data or data block forms, as appropriate for the representation
+of the variable's value. The value of this attribute is the actual
+constant value of the variable, represented as it would be
+on the target architecture.
+.LI
+.IX scope
+.IX declarations, scope
+If the scope of an object begins sometime after the low pc value
+for the scope most closely enclosing the object, the
+object entry may have a
+.Cf DW_AT_start_scope
+attribute. The value of this attribute is the offset in bytes of the beginning
+of the scope for the object from the low pc value of the debugging
+information entry that defines its scope.
+.P
+.I
+The scope of a variable may begin somewhere in the middle of a lexical
+block in a language that allows executable code in a
+block before a variable declaration, or where one declaration
+containing initialization code may change the scope of a subsequent
+declaration. For example, in the following C code:
+.DS
+\f(CWfloat x = 99.99;
+
+int myfunc()
+{
+ float f = x;
+ float x = 88.99;
+
+ return 0;
+}\fP
+.DE
+.P
+ANSI-C scoping rules require that the value of the variable \f(CWx\fP
+assigned to the variable \f(CWf\fP in the initialization sequence
+is the value of the global variable \f(CWx\fP, rather than the local \f(CWx\fP,
+because the scope of the local variable \f(CWx\fP only starts after the full
+declarator for the local \f(CWx\fP.
+.R
+.LE
+.P
+.H 2 "Common Block Entries"
+.IX common blocks
+.IX Fortran
+A Fortran common block may be described by a debugging information
+entry with the tag
+.Cf DW_TAG_common_block .
+The common block entry has a
+.Cf DW_AT_name
+attribute whose value is a null-terminated
+string containing the common block name as it appears in the source program.
+It also has a
+.Cf DW_AT_location
+attribute whose value describes the location of the beginning of the
+common block. The common block entry owns debugging information
+entries describing the variables contained within the common block.
+.H 2 "Imported Declaration Entries"
+.I
+.IX declarations, imported
+.IX imports
+Some languages support the concept of importing into a given
+module declarations made in a different module.
+.R
+.P
+An imported declaration is represented by a debugging information
+entry with the tag
+.Cf DW_TAG_imported_declaration .
+The entry for the imported declaration has a
+.Cf DW_AT_name
+attribute whose value
+is a null-terminated string containing the name of the entity
+whose declaration is being imported as it appears in the source
+program. The imported declaration entry also has a
+.Cf DW_AT_import
+attribute, whose value is a reference to the debugging information
+entry representing the declaration that is being imported.
+.H 2 "Namelist Entries"
+.I
+.IX namelists
+.IX Fortran90
+At least one language, Fortran90, has the concept of a namelist.
+A namelist is an ordered list of the names of some set of declared objects.
+The namelist object itself may be used as a replacement for the
+list of names in various contexts.
+.R
+.P
+A namelist is represented by a debugging information entry with
+the tag
+.Cf DW_TAG_namelist .
+If the namelist itself has a name, the namelist entry has a
+.Cf DW_AT_name
+attribute, whose value is a null-terminated string containing the namelist's
+name as it appears in the source program.
+.P
+Each name that is part of the namelist is represented by a debugging
+information entry with the tag
+.Cf DW_TAG_namelist_item .
+Each such entry is a child of the namelist entry, and all of
+the namelist item entries for a given namelist are ordered as were
+the list of names they correspond to in the source program.
+.P
+Each namelist item entry contains a
+.Cf DW_AT_namelist_item
+attribute whose value is a reference to the debugging information
+entry representing the declaration of the item whose name
+appears in the namelist.
+.OP
+.H 1 "TYPE ENTRIES"
+This section presents the debugging information entries
+that describe program types: base types, modified types
+and user-defined types.
+.P
+If the scope of the declaration of a named type begins sometime after
+.IX scope
+.IX declarations, scope
+the low pc value
+for the scope most closely enclosing the declaration, the
+declaration may have a
+.Cf DW_AT_start_scope
+attribute. The value of this attribute is the offset in bytes of the beginning
+of the scope for the declaration from the low pc value of the debugging
+information entry that defines its scope.
+.H 2 "Base Type Entries"
+.I
+.IX base types
+.IX types, base
+A base type is a data type that is not defined in terms of
+other data types. Each programming language has a set of
+base types that are considered to be built into that language.
+.R
+.P
+A base type is represented by a debugging information entry
+with the tag
+.Cf DW_TAG_base_type .
+A base type entry has a
+.Cf DW_AT_name
+attribute whose value is a null-terminated
+string describing the name of the base type as recognized by
+the programming language of the compilation unit containing
+the base type entry.
+.P
+A base type entry also has a
+.Cf DW_AT_encoding
+attribute describing how the base type is encoded and is
+to be interpreted. The value of this attribute is a constant.
+The set of values and their meanings for the
+.Cf DW_AT_encoding
+.nr aX \n(Fg+1
+attribute is given in Figure \n(aX.
+.DF
+.TS
+box center;
+l l
+lf(CW) l
+.
+Name Meaning
+_
+DW_ATE_address linear machine address
+DW_ATE_boolean true or false
+DW_ATE_complex_float complex floating-point number
+DW_ATE_float floating-point number
+DW_ATE_signed signed binary integer
+DW_ATE_signed_char signed character
+DW_ATE_unsigned unsigned binary integer
+DW_ATE_unsigned_char unsigned character
+.TE
+.FG "Encoding attribute values"
+.DE
+.P
+All encodings assume the representation that is ``normal'' for
+the target architecture.
+.P
+A base type entry has a
+.Cf DW_AT_byte_size
+attribute, whose value is a constant,
+describing the size in bytes of the storage
+unit used to represent an object of the given type.
+.P
+If the value of an object of the given type does not
+fully occupy the storage unit described by the byte size attribute,
+the base type entry may have a
+.Cf DW_AT_bit_size
+attribute and a
+.Cf DW_AT_bit_offset
+attribute, both of whose values are constants.
+The bit size attribute describes the actual size in bits used
+to represent a value of the given type. The bit offset
+attribute describes the offset in bits of the high order
+bit of a value of the given type from the high order bit
+of the storage unit used to contain that value.
+.I
+.P
+For example, the C type
+.Cf int
+on a machine that uses 32-bit integers would be
+represented by a base type entry with a name
+attribute whose value was ``\f(CWint\fP,'' an
+encoding attribute whose value was
+.Cf DW_ATE_signed
+and a byte size attribute whose value was
+.Cf 4 .
+.R
+.H 2 "Type Modifier Entries"
+.IX type modifiers
+.IX types, modifiers
+A base or user-defined type may be modified in different
+ways in different languages. A type modifier is represented
+in DWARF by a debugging information entry with one of the
+.nr aX \n(Fg+1
+tags given in Figure \n(aX.
+.DF
+.TS
+box center;
+l l
+lf(CW) l
+.
+Tag Meaning
+_
+DW_TAG_const_type C or C++ const qualified type
+DW_TAG_packed_type Pascal packed type
+DW_TAG_pointer_type The address of the object whose type is being modified
+DW_TAG_reference_type A C++ reference to the object whose type is being modified
+DW_TAG_volatile_type C or C++ volatile qualified type
+.TE
+.FG "Type modifier tags"
+.DE
+.P
+.IX types, constant
+.IX types, packed
+.IX types, volatile
+.IX types, pointer
+.IX types, reference
+Each of the type modifier entries has a
+.Cf DW_AT_type
+attribute, whose value is a reference to a debugging information
+entry describing a base type, a user-defined type or another type
+modifier.
+.P
+A modified type entry describing a pointer or reference type
+may have a
+.IX addresses, class
+.Cf DW_AT_address_class
+attribute
+to describe how objects having the given pointer or reference type
+ought to be dereferenced.
+.P
+When multiple type modifiers are chained together to modify
+a base or user-defined type, they are ordered as if part of
+a right-associative expression involving the base or user-defined
+type.
+.I
+.P
+As examples of how type modifiers are ordered, take the following
+C declarations:
+.R
+.DS
+.ta .5i +.5i +.5i +.5i +.5i +.5i +.5i +.5i
+\f(CWconst char * volatile p;\fP
+ \fIwhich represents a volatile pointer to a constant character.\fP
+ \fIThis is encoded in DWARF as:\fP
+ \f(CWDW_TAG_volatile_type \(->
+ DW_TAG_pointer_type \(->
+ DW_TAG_const_type \(->
+ DW_TAG_base_type\fP
+
+\f(CWvolatile char * const p;\fP
+ \fIon the other hand, represents a constant pointer
+ to a volatile character.\fP
+ \fIThis is encoded as:\fP
+ \f(CWDW_TAG_const_type \(->
+ DW_TAG_pointer_type \(->
+ DW_TAG_volatile_type \(->
+ DW_TAG_base_type\fP
+
+.DE
+.R
+.H 2 "Typedef Entries"
+.IX typedefs
+Any arbitrary type named via a typedef is represented
+by a debugging information entry with the tag
+.Cf DW_TAG_typedef .
+The typedef entry has a
+.Cf DW_AT_name
+attribute whose value is a null-terminated
+string containing the name of the typedef as it appears in the
+source program.
+The typedef entry also contains a
+.Cf DW_AT_type
+attribute.
+.P
+If the debugging information entry for a typedef represents a
+declaration of the type that is not also a definition,
+it does not contain a type attribute.
+.IX declarations, non-defining
+.H 2 "Array Type Entries"
+.I
+.IX arrays
+Many languages share the concept of an ``array,'' which is a
+table of components of identical type.
+.P
+.R
+An array type is represented by a debugging information entry with
+the tag
+.Cf DW_TAG_array_type .
+.P
+If a name has been given to the array type in the source program, then the
+corresponding array type entry has a
+.Cf DW_AT_name
+attribute whose value is a
+null-terminated string containing the array type name as it appears in the
+source program.
+.P
+.IX arrays, ordering
+The array type entry describing a multidimensional array may have a
+.Cf DW_AT_ordering
+attribute whose constant value is interpreted to mean either
+row-major or column-major ordering of array elements.
+The set of values and their meanings for the ordering attribute
+.nr aX \n(Fg+1
+are listed in Figure \n(aX.
+If no ordering attribute is present, the default ordering for
+the source language (which is indicated by the
+.Cf DW_AT_language
+attribute of the enclosing compilation unit entry)
+is assumed.
+.DF
+.TS
+box center;
+lf(CW)
+.
+DW_ORD_col_major
+DW_ORD_row_major
+.TE
+.FG "Array ordering"
+.DE
+.P
+The ordering attribute may optionally appear on one-dimensional arrays; it
+will be ignored.
+.P
+An array type entry has a
+.Cf DW_AT_type
+attribute describing the type
+of each element of the array.
+.P
+.IX arrays, stride
+If the amount of storage allocated to hold each element of an object of
+the given array type is different from the amount of storage that is normally
+allocated to hold an individual object of the indicated element type, then
+the array type entry has a
+.Cf DW_AT_stride_size
+attribute, whose constant value
+represents the size in bits of each element of the array.
+.P
+If the size of the entire array can be determined statically at compile
+time, the array type entry may have a
+.Cf DW_AT_byte_size
+attribute, whose constant value represents the total size in bytes of an
+instance of the array type.
+.P
+.I
+Note that if the size of the array can be determined statically at
+compile time, this value can usually be computed by multiplying
+the number of array elements by the size of each element.
+.P
+.R
+Each array dimension is described by a debugging information
+entry with either the tag
+.IX subranges
+.IX enumerations
+.IX arrays, dimensions
+.Cf DW_TAG_subrange_type
+or the tag
+.Cf DW_TAG_enumeration_type .
+These entries are children of the array type entry and are
+ordered to reflect the appearance of the dimensions in the source
+program (i.e. leftmost dimension first, next to leftmost second,
+and so on).
+.P
+.I
+.IX C %c
+In languages, such as ANSI-C, in which there is no concept of a
+``multidimensional array,''
+an array of arrays may be represented by a debugging information entry
+for a multidimensional array.
+.R
+.H 2 "Structure, Union, and Class Type Entries"
+.I
+The languages C, C++, and Pascal, among others,
+allow the programmer to define types that
+are collections of related components. In C and C++, these collections are
+called ``structures.'' In Pascal, they are called ``records.'' The components
+may be of different types. The components are called ``members'' in C and
+C++, and ``fields'' in Pascal.
+.P
+.IX structures
+.IX classes
+.IX unions
+.IX records
+.IX C %c
+.IX C++ %caa
+.IX Pascal
+The components of these collections each exist in their own space in
+computer memory. The components of a C or C++ ``union'' all coexist in
+the same memory.
+.P
+Pascal and other languages have a ``discriminated union,'' also called a
+.IX variants
+.IX discriminated unions
+``variant record.'' Here, selection of a number of alternative substructures
+(``variants'') is based on the value of a component that is not part of any of
+those substructures (the ``discriminant'').
+.P
+Among the languages discussed in this document,
+the ``class'' concept is unique to C++. A class is similar to a structure.
+A C++ class or structure may have ``member functions'' which are subroutines
+that are within the scope of a class or structure.
+.R
+.H 3 "General Structure Description"
+Structure, union, and class types are represented by
+debugging information entries with the tags
+.Cf DW_TAG_structure_type ,
+.Cf DW_TAG_union_type
+and
+.Cf DW_TAG_class_type ,
+respectively.
+If a name has been given to the structure, union, or class in the source
+program, then the corresponding structure type, union type, or class type
+entry has a
+.Cf DW_AT_name
+attribute whose value is a null-terminated string
+containing the type name as it appears in the source program.
+.P
+If the size of an instance of the
+structure type, union type, or class type entry can be determined
+statically at compile time, the entry has a
+.Cf DW_AT_byte_size
+attribute whose constant value is the number of bytes required to
+hold an instance of the structure, union, or class, and any padding bytes.
+.I
+.P
+.IX structures, incomplete
+.IX classes, incomplete
+.IX unions, incomplete
+For C and C++, an incomplete structure, union or class type is represented
+by a structure, union or class entry that does not have
+a byte size attribute and that has a
+.Cf DW_AT_declaration
+attribute.
+.R
+.P
+The members of a structure, union, or class are represented by
+debugging information entries that are owned by the corresponding
+structure type, union type, or class type entry and appear in the same
+order as the corresponding declarations in the source program.
+.P
+.I
+.IX declarations, defining
+.IX members, static data
+.IX members, data
+.IX members, functions
+Data member declarations occurring within the declaration of a structure,
+union or class type are considered to be ``definitions'' of those members,
+with the exception of C++ ``static'' data members, whose definitions
+appear outside of the declaration of the enclosing structure, union
+or class type. Function member declarations appearing within a structure,
+union or class type declaration are definitions only if the body
+of the function also appears within the type declaration.
+.R
+.P
+.IX declarations, non-defining
+If the definition for a given member of the structure, union or class
+does not appear within the body of the declaration, that member
+also has a debugging information entry describing its definition.
+That entry will have a
+.Cf DW_AT_specification
+attribute referencing
+the debugging entry owned by the
+body of the structure, union or class debugging entry and representing
+a non-defining declaration of the data or function member. The
+referenced entry will
+not have information about the location of that member (low and high
+pc attributes for function members, location descriptions for data
+members) and will have a
+.Cf DW_AT_declaration
+attribute.
+.H 3 "Derived Classes and Structures"
+.IX classes, derived
+.IX structures, derived
+.IX inheritance
+The class type or structure type entry that describes a derived class
+or structure owns debugging information entries describing each of
+the classes or structures it is derived from, ordered as they were
+in the source program. Each such entry has the tag
+.Cf DW_TAG_inheritance .
+.P
+An inheritance entry has a
+.Cf DW_AT_type
+attribute whose
+value is a reference to the debugging information entry describing
+the structure or class from which the parent structure or class
+of the inheritance entry is derived. It also has a
+.Cf DW_AT_data_member_location
+attribute, whose value is a location description describing
+the location of the beginning of
+the data members contributed to the entire class by this
+subobject relative to the beginning address of the data members of the
+entire class.
+.P
+.IX accessibility
+.IX virtuality
+.IX classes, virtual base
+An inheritance entry may have a
+.Cf DW_AT_accessibility
+attribute.
+If no accessibility attribute is present,
+private access is assumed.
+If the structure or class referenced by the inheritance entry serves
+as a virtual base class, the inheritance entry has a
+.Cf DW_AT_virtuality
+attribute.
+.P
+.I
+In C++, a derived class may contain access declarations that
+change the accessibility of individual class members from
+the overall accessibility specified by the inheritance declaration.
+A single access declaration may refer to a set of overloaded
+names.
+.R
+.P
+If a derived class or structure contains access declarations,
+.IX access declarations
+.IX C++ %caa
+each such declaration may be represented by a debugging information
+entry with the tag
+.Cf DW_TAG_access_declaration .
+Each such entry is a child of the structure or class type entry.
+.P
+An access declaration entry has a
+.Cf DW_AT_name
+attribute, whose value
+is a null-terminated string representing the name used in the
+declaration in the source program, including any class or structure
+qualifiers.
+.P
+An access declaration entry also has a
+.Cf DW_AT_accessibility
+attribute
+describing the declared accessibility of the named entities.
+.H 3 "Friends"
+.IX friends
+.IX classes, friends
+Each ``friend'' declared by
+a structure, union or class type may be represented by
+a debugging information entry that is a child of the structure,
+union or class type entry; the friend entry has the tag
+.Cf DW_TAG_friend.
+.P
+A friend entry has a
+.Cf DW_AT_friend
+attribute, whose value is a reference to the debugging information
+entry describing the declaration of the friend.
+.H 3 "Structure Data Member Entries"
+.IX members, data
+A data member (as opposed to a member function) is represented by
+a debugging information entry with the tag
+.Cf DW_TAG_member .
+The member entry for a named member has a
+.Cf DW_AT_name
+attribute
+whose value is a null-terminated string containing the member name
+as it appears in the source program. If the member entry describes
+a C++ anonymous union, the name attribute is omitted or consists
+of a single zero byte.
+.IX unions, anonymous
+.IX anonymous unions
+.P
+The structure data member entry has a
+.Cf DW_AT_type
+attribute
+to denote the type of that member.
+.P
+If the member entry is defined in the structure or class body, it has a
+.Cf DW_AT_data_member_location
+attribute whose value is a location
+description that describes the location of that
+member relative to the base address of the structure, union, or class that
+most closely encloses the corresponding member declaration.
+.I
+.P
+.IX locations, expressions
+.IX locations, descriptions
+The addressing expression represented by the location
+description for a structure data member expects the base address
+of the structure data member to be on the expression stack
+before being evaluated.
+.P
+.IX unions
+The location description for a data member of a union may be omitted,
+since all data members of a union begin at the same address.
+.R
+.P
+.IX bit fields
+.IX members, bit fields
+If the member entry describes a bit field, then that entry has the following
+attributes:
+.AL
+.LI
+A
+.Cf DW_AT_byte_size
+attribute whose constant value is the number of bytes that
+contain an instance of the bit field and any padding bits.
+.P
+.I
+The byte size attribute may be omitted if the size of the object containing
+the bit field can be inferred from the type attribute of the data
+member containing the bit field.
+.R
+.LI
+A
+.Cf DW_AT_bit_offset
+attribute whose constant value is the number of bits
+to the left of the leftmost (most significant) bit of the bit field value.
+.LI
+A
+.Cf DW_AT_bit_size
+attribute whose constant value is the number of bits occupied
+by the bit field value.
+.LE
+.P
+The location description for a bit field calculates the address of
+an anonymous object containing the bit field. The address is
+relative to the structure, union, or class that
+most closely encloses the bit field declaration. The number
+of bytes in this anonymous object is the value of the byte
+size attribute of the bit field. The offset (in bits)
+from the most significant bit of the
+anonymous object to the most significant bit of the bit field is the
+value of the bit offset attribute.
+.I
+.P
+For example, take one possible representation of the following
+structure definition in both big and little endian byte orders:
+.DS
+\f(CW
+struct S {
+ int j:5;
+ int k:6;
+ int m:5;
+ int n:8;
+};\fP
+.DE
+.P
+In both cases, the location descriptions for the debugging information
+entries for \f(CWj\fP, \f(CWk\fP, \f(CWm\fP and \f(CWn\fP
+describe the address of
+the same 32-bit word that contains all three members.
+(In the big-endian case,
+the location description addresses the most significant byte, in
+the little-endian case, the least significant).
+The following diagram shows the structure layout and lists the bit
+offsets for each case. The offsets
+are from the most significant bit of the object addressed by the location
+description.
+.PS
+bitht = .3
+boxht = bitht
+bitwid = .11
+nibwid = .75 * bitwid
+bytewid = 8 * bitwid
+boxwid = bytewid
+define nibble X # nibble(len, "label", hi-left, hi-right, lo-left, lo-right, any)
+N: box width $1*nibwid $2 $7
+ { if $3 >= 0 then % "\s-4\|$3\s0" at N.w + (0,bitht/3) ljust %
+ } # curly on separate line for pic bug
+ { if $4 >= 0 then % "\s-4\|$4\s0" at N.e + (0,bitht/3) rjust %
+ }
+ { if $5 >= 0 then % "\s-4\|$5\s0" at N.w - (0,bitht/3) ljust %
+ }
+ { if $6 >= 0 then % "\s-4$6\|\s0" at N.e - (0,bitht/3) rjust %
+ }
+X
+define tbox X # tbox(width,"label", any)
+T: box width $1*nibwid ht 1/6 $3 invis
+ { $2 at T.w ljust
+ }
+X
+.PE
+.DS
+.PS
+ down
+H: tbox(20,"Bit Offsets:")
+ tbox(20,"\f(CW j:0\fP")
+ tbox(20,"\f(CW k:5\fP")
+ tbox(20,"\f(CW m:11\fP")
+ tbox(20,"\f(CW n:16\fP")
+ right
+H: tbox(32, "Big-Endian", with .w at H.e)
+H: nibble(5,"\f(CWj\fP",0,-1,31,-1,with .nw at H.sw)
+H: nibble(6,"\f(CWk\fP",-1,-1,26,-1)
+H: nibble(5,"\f(CWm\fP",-1,-1,20,-1)
+H: nibble(8,"\f(CWn\fP",-1,-1,15,-1)
+H: nibble(8,"\fIpad\fP",-1,-1,7,0)
+.PE
+.DE
+.DS
+.PS
+ down
+H: tbox(20,"Bit Offsets:")
+ tbox(20,"\f(CW j:27\fP")
+ tbox(20,"\f(CW k:21\fP")
+ tbox(20,"\f(CW m:16\fP")
+ tbox(20,"\f(CW n:8\fP")
+ right
+H: tbox(32, "Little-Endian", with .w at H.e)
+H: nibble(8,"\f2pad\fP",-1,-1,31,-1, with .nw at H.sw)
+H: nibble(8,"\f(CWn\fP",-1,-1,23,-1)
+H: nibble(5,"\f(CWm\fP",-1,-1,15,-1)
+H: nibble(6,"\f(CWk\fP",-1,-1,10,-1)
+H: nibble(5,"\f(CWj\fP",-1,0,4,0)
+.PE
+.DE
+.R
+.H 3 "Structure Member Function Entries"
+.IX subroutines, members
+.IX members, functions
+.IX members, locations
+A member function is represented in the debugging information by a
+debugging information entry with the tag
+.Cf DW_TAG_subprogram .
+The member function entry may contain the same attributes and follows
+the same rules as non-member global subroutine entries (see section 3.3).
+.P
+.IX virtuality
+.IX virtual functions
+If the member function entry describes a virtual function, then that entry
+has a
+.Cf DW_AT_virtuality
+attribute.
+.P
+An entry for a virtual function also has a
+.Cf DW_AT_vtable_elem_location
+attribute whose value contains a location
+description yielding the address of the slot for the function
+within the virtual function table for the enclosing class or structure.
+.P
+.IX declarations, defining
+If a subroutine entry represents the defining declaration
+of a member function and that definition appears outside
+of the body of the enclosing class or structure declaration,
+the subroutine entry has a
+.Cf DW_AT_specification
+attribute, whose value is a reference to the debugging information
+entry representing the declaration of this function member. The
+referenced entry will be a child of some class or structure
+type entry.
+.P
+Subroutine entries containing the
+.Cf DW_AT_specification
+attribute do not need to duplicate information provided by the
+declaration entry referenced by the specification attribute.
+In particular, such entries do not need to contain
+attributes for the name or return type of the function member whose
+definition they represent.
+.H 3 "Class Template Instantiations"
+.I
+.IX C++ %caa
+.IX templates
+In C++ a class template is a generic
+definition of a class type that
+is instantiated differently when an instance of the class
+is declared or defined. The generic description of the class
+may include both parameterized types and parameterized constant
+values. DWARF does not represent the generic
+template definition, but does represent each instantiation.
+.R
+.P
+A class template instantiation is represented by a debugging information
+with the tag
+.Cf DW_TAG_class_type .
+With four exceptions,
+such an entry will contain the same attributes and have the same
+types of child entries as would an entry for a class type defined
+explicitly using the instantiation types and values.
+The exceptions are:
+.AL
+.LI
+Each formal parameterized type declaration appearing in the
+template definition is represented by a debugging information entry
+with the tag
+.Cf DW_TAG_template_type_parameter .
+Each such entry has a
+.Cf DW_AT_name
+attribute, whose value is a null-terminated
+string containing the name of the formal type parameter as it
+appears in the source program. The template type parameter
+entry also has a
+.Cf DW_AT_type
+attribute describing the actual type by
+which the formal is replaced for this instantiation.
+.LI
+Each formal parameterized value declaration appearing
+in the templated definition is represented by a debugging information
+entry with the tag
+.Cf DW_TAG_template_value_parameter .
+Each such entry has a
+.Cf DW_AT_name
+attribute, whose value is a null-terminated
+string containing the name of the formal value parameter as it
+appears in the source program. The template value parameter
+entry also has a
+.Cf DW_AT_type
+attribute describing the type of the parameterized
+value. Finally, the template value parameter entry has a
+.Cf DW_AT_const_value
+attribute, whose value is the actual constant value of the value
+parameter for this instantiation as represented on the target
+architecture.
+.LI
+.IX compilation units
+If the compiler has generated a special compilation unit
+to hold the template instantiation and that compilation unit
+has a different name
+from the compilation unit containing the template definition,
+the name attribute for the debugging entry representing
+that compilation unit should be empty or omitted.
+.LI
+.IX declarations, coordinates
+If the class type entry representing the template instantiation
+or any of its child entries
+contain declaration coordinate attributes, those attributes
+should refer to the source for the template definition, not
+to any source generated artificially by the compiler.
+.LE
+.H 3 "Variant Entries"
+.IX variants
+.IX discriminated unions
+A variant part of a structure is represented by a debugging
+information entry with the tag
+.Cf DW_TAG_variant_part
+and is owned by the corresponding structure type
+entry.
+.P
+.IX discriminants
+If the variant part has a discriminant, the discriminant is represented
+by a separate debugging information entry which is a child of
+the variant part entry. This entry has the form of a structure data member
+entry.
+The variant part entry will have a
+.Cf DW_AT_discr
+attribute whose value is a
+reference to the member entry for the discriminant.
+.P
+If the variant part
+does not have a discriminant (tag field), the variant part entry has a
+.Cf DW_AT_type
+attribute to represent the tag type.
+.P
+Each variant of a particular variant part is represented by a debugging
+information entry with the tag
+.Cf DW_TAG_variant
+and is a child of the variant part entry. The value that selects a
+given variant may be represented in one of three ways. The
+variant entry may have a
+.Cf DW_AT_discr_value
+attribute whose value represents a single case label.
+The value of this attribute
+is encoded as an LEB128 number. The number is signed if the tag
+type for the variant part containing this variant is
+a signed type. The number is unsigned if the tag type is an unsigned type.
+.P
+Alternatively, the variant entry may contain a
+.Cf DW_AT_discr_list
+attribute, whose value represents a list of discriminant values.
+This list is represented by any of the block forms and may contain
+a mixture of case labels and label ranges. Each item on the list
+is prefixed with a discriminant value descriptor that determines whether
+the list item represents a single label or a label range.
+A single case label is represented as an LEB128
+number as defined above
+for the
+.Cf DW_AT_discr_value
+attribute. A label range is represented by two LEB128 numbers,
+the low value of the range followed by the high value. Both values
+follow the rules for signedness just described.
+The discriminant value descriptor is a constant that may have
+.nr aX \n(Fg+1
+one of the values given in Figure \n(aX.
+.DF
+.TS
+center box;
+lf(CW)
+.
+DW_DSC_label
+DW_DSC_range
+.TE
+.FG "Discriminant descriptor values"
+.DE
+.P
+If a variant entry has neither a
+.Cf DW_AT_discr_value
+attribute nor a
+.Cf DW_AT_discr_list
+attribute, or if it has a
+.Cf DW_AT_discr_list
+attribute with 0 size, the variant is a default variant.
+.P
+The components selected by a particular variant are represented
+by debugging information entries owned by the corresponding variant
+entry and appear in the same order as the corresponding declarations in
+the source program.
+.H 2 "Enumeration Type Entries"
+.I
+.IX enumerations
+An ``enumeration type'' is a scalar that can assume one of a fixed number of
+symbolic values.
+.P
+.R
+An enumeration type is represented by a debugging information entry
+with the tag
+.Cf DW_TAG_enumeration_type .
+.P
+If a name has been given to the enumeration type in the source program,
+then the corresponding enumeration type entry has a
+.Cf DW_AT_name
+attribute
+whose value is a null-terminated string containing the enumeration type
+name as it appears in the source program.
+These entries also have a
+.Cf DW_AT_byte_size
+attribute whose
+constant value is the number of bytes required to hold an
+instance of the enumeration.
+.P
+Each enumeration literal is represented by a debugging information
+entry with the tag
+.Cf DW_TAG_enumerator .
+Each such entry is a child of the enumeration type entry, and
+the enumerator entries appear in the same order as the declarations of
+the enumeration literals in the source program.
+.P
+Each enumerator entry has a
+.Cf DW_AT_name
+attribute, whose value is
+a null-terminated string containing the name of the enumeration
+literal as it appears in the source program. Each enumerator
+entry also has a
+.Cf DW_AT_const_value
+attribute, whose value is the actual numeric value of the enumerator
+as represented on the target system.
+.H 2 "Subroutine Type Entries"
+.I
+.IX subroutines, types
+It is possible in C to declare pointers to subroutines that return a value
+of a specific type. In both ANSI C and C++, it is possible to declare
+pointers to subroutines that not only return a value of a specific type,
+but accept only arguments of specific types. The type of such pointers
+would be described with a ``pointer to'' modifier applied to a user-defined
+type.
+.R
+.P
+A subroutine type is represented by a debugging information entry
+with the tag
+.Cf DW_TAG_subroutine_type .
+If a name has been given to the subroutine type in the source program,
+then the corresponding subroutine type entry has a
+.Cf DW_AT_name
+attribute
+whose value is a null-terminated string containing the subroutine type
+name as it appears in the source program.
+.P
+.IX subroutines, return types
+If the subroutine type describes a function that returns a value, then
+the subroutine type entry has a
+.Cf DW_AT_type
+attribute
+to denote the type returned by the subroutine.
+If the types of the arguments are necessary to describe the subroutine type,
+then the corresponding subroutine type entry owns debugging
+information entries that describe the arguments.
+These debugging information entries appear in the order
+that the corresponding argument types appear in the source program.
+.P
+.I
+.IX C %c
+.IX subroutines, prototypes
+In ANSI-C there is a difference between the types of functions
+declared using function prototype style declarations and those
+declared using non-prototype declarations.
+.P
+.R
+A subroutine entry
+declared with a function prototype style declaration may have a
+.Cf DW_AT_prototyped
+attribute, whose value is a flag.
+.P
+Each debugging information entry
+owned by a subroutine type entry has a tag whose value has one of
+two possible interpretations.
+.AL
+.LI
+.IX parameters, formal
+Each debugging information entry that is owned by a subroutine type entry and
+that defines a single argument of a specific type has the tag
+.Cf DW_TAG_formal_parameter .
+.P
+The formal parameter entry has a type attribute
+to denote the type of the corresponding formal parameter.
+.LI
+The unspecified parameters of a variable parameter list are represented by a
+debugging information entry owned by the subroutine type entry with the tag
+.Cf DW_TAG_unspecified_parameters .
+.IX parameters, unspecified
+.LE
+.H 2 "String Type Entries"
+.I
+.IX string types
+.IX Fortran
+A ``string'' is a sequence of characters that have specific semantics and
+operations that separate them from arrays of characters.
+Fortran is one of
+the languages that has a string type.
+.R
+.P
+A string type is represented by a debugging information entry
+with the tag
+.Cf DW_TAG_string_type .
+If a name has been given to the string type in the source program,
+then the corresponding string type entry has a
+.Cf DW_AT_name
+attribute
+whose value is a null-terminated string containing the string type
+name as it appears in the source program.
+.P
+The string type entry may have a
+.Cf DW_AT_string_length
+attribute whose value is a location description
+yielding the location where the length of the string
+is stored in the program. The string type entry may also have a
+.Cf DW_AT_byte_size
+attribute, whose constant value is the size in bytes of the data
+to be retrieved from the location referenced by the string length
+attribute. If no byte size attribute is present, the size of the
+data to be retrieved is the same as the size of an address on
+the target machine.
+.P
+If no string length attribute is present, the string type entry may have
+a
+.Cf DW_AT_byte_size
+attribute, whose constant value is the length in bytes of
+the string.
+.H 2 "Set Entries"
+.I
+Pascal provides the concept of a ``set,'' which represents a group of
+values of ordinal type.
+.P
+.R
+.IX Pascal
+.IX set types
+A set is represented by a debugging information entry
+with the tag
+.Cf DW_TAG_set_type .
+If a name has been given to the set type,
+then the set type entry has a
+.Cf DW_AT_name
+attribute
+whose value is a null-terminated string containing the set type name
+as it appears in the source program.
+.P
+The set type entry has a
+.Cf DW_AT_type
+attribute to denote the type
+of an element of the set.
+.P
+If the amount of storage allocated to hold each element of an object of
+the given set type is different from the amount of storage that is normally
+allocated to hold an individual object of the indicated element type, then
+the set type entry has a
+.Cf DW_AT_byte_size
+attribute, whose constant value
+represents the size in bytes of an instance of the set type.
+.H 2 "Subrange Type Entries"
+.I
+Several languages support the concept of a ``subrange'' type object.
+These objects can represent a subset of the values that an
+object of the basis type for the subrange can represent.
+Subrange type entries may also be used to represent the bounds
+of array dimensions.
+.R
+.P
+.IX subranges
+A subrange type is represented by a debugging information entry
+with the tag
+.Cf DW_TAG_subrange_type .
+If a name has been given to the subrange type,
+then the subrange type entry has a
+.Cf DW_AT_name
+attribute
+whose value is a null-terminated string containing the subrange type name
+as it appears in the source program.
+.P
+The subrange entry may have a
+.Cf DW_AT_type
+attribute to describe
+the type of object of whose values this subrange is a subset.
+.P
+If the amount of storage allocated to hold each element of an object of
+the given subrange type is different from the amount of storage that is normally
+allocated to hold an individual object of the indicated element type, then
+the subrange type entry has a
+.Cf DW_AT_byte_size
+attribute, whose constant value
+represents the size in bytes of each element of the subrange type.
+.P
+The subrange entry may have the attributes
+.Cf DW_AT_lower_bound
+and
+.Cf DW_AT_upper_bound
+to describe, respectively, the lower and upper bound values
+of the subrange.
+The
+.Cf DW_AT_upper_bound
+attribute may be replaced by a
+.Cf DW_AT_count
+attribute, whose value describes the number of elements in
+the subrange rather than the value of the last element.
+If a bound or count value is described by a constant
+not represented in the program's address space and can
+be represented by one of the constant attribute forms, then the value
+of the lower or upper bound or count attribute may be one of the constant
+types. Otherwise, the value of the lower or upper bound or count
+attribute is a reference to a debugging information entry describing
+an object containing the bound value or itself describing a constant
+value.
+.P
+If either the lower or upper bound or count values are missing, the
+bound value is assumed to be a language-dependent default
+constant.
+.P
+.I
+.IX C %c
+.IX C++ %caa
+.IX Fortran
+The default lower bound value for C or C++ is 0. For Fortran,
+it is 1. No other default values are currently defined by DWARF.
+.R
+.P
+If the subrange entry has no type attribute describing the basis
+type, the basis type is assumed to be the same as the object
+described by the lower bound attribute (if it references an object).
+If there is no lower bound attribute, or it does not reference
+an object, the basis type is the type of the upper bound or count
+attribute
+(if it references an object). If there is no upper bound or count attribute
+or it does not reference an object, the type is assumed to be
+the same type, in the source language
+of the compilation unit containing the subrange entry,
+as a signed integer with the same size
+as an address on the target machine.
+.H 2 "Pointer to Member Type Entries"
+.I
+In C++, a pointer to a data or function member of a class or
+structure is a unique type.
+.P
+.R
+.IX C++ %caa
+.IX members, pointers to
+.IX pointers to members
+A debugging information entry
+representing the type of an object that is a pointer to a structure
+or class member has the tag
+.Cf DW_TAG_ptr_to_member_type .
+.P
+If the pointer to member type has a name, the pointer to member entry
+has a
+.Cf DW_AT_name
+attribute, whose value is a null-terminated string
+containing the type name as it appears in the source program.
+.P
+The pointer to member entry has a
+.Cf DW_AT_type
+attribute to describe
+the type of the class or structure member to which objects
+of this type may point.
+.P
+The pointer to member entry also has a
+.Cf DW_AT_containing_type
+attribute, whose value is a reference to a debugging information
+entry for the class or structure to whose members objects of
+this type may point.
+.P
+Finally, the pointer to member entry has a
+.Cf DW_AT_use_location
+attribute whose value is a location description that computes
+the address of the member of the class or structure to which the
+pointer to member type entry can point.
+.P
+.I
+The method used to find the address of a given member
+of a class or structure is common to any instance of that
+class or structure and to any instance of the pointer or
+member type. The method is thus associated
+with the type entry, rather than with each instance of the type.
+.P
+The
+.Cf DW_AT_use_location
+expression, however, cannot be used on its own, but must
+be used in conjunction with the location expressions for
+a particular object of the given pointer to member type
+and for a particular structure or class instance. The
+.Cf DW_AT_use_location
+attribute expects two values to be pushed onto the location expression
+stack before the
+.Cf DW_AT_use_location
+expression is evaluated. The first value pushed should be
+the value of the pointer to member object itself.
+The second value pushed should be the base address of the entire
+structure or union instance containing the member whose
+address is being calculated.
+.P
+So, for an expression like
+.DS
+ \f(CWobject.*mbr_ptr\fP
+.DE
+where \f(CWmbr_ptr\fP has some pointer to member type,
+a debugger should:
+.AL
+.LI
+Push the value of
+.Cf mbr_ptr
+onto the location expression stack.
+.LI
+Push the base address of
+.Cf object
+onto the location expression stack.
+.LI
+Evaluate the
+.Cf DW_AT_use_location
+expression for the type of
+.Cf mbr_ptr .
+.LE
+.R
+.H 2 "File Type Entries"
+.I
+Some languages, such as Pascal, provide a first class data type
+to represent files.
+.R
+.P
+.IX Pascal
+.IX file types
+A file type is represented by a debugging information entry
+with the tag
+.Cf DW_TAG_file_type.
+If the file type has a name, the file type entry
+has a
+.Cf DW_AT_name
+attribute, whose value is a null-terminated string
+containing the type name as it appears in the source program.
+.P
+The file type entry has a
+.Cf DW_AT_type
+attribute describing the type
+of the objects contained in the file.
+.P
+The file type entry also has a
+.Cf DW_AT_byte_size
+attribute, whose value
+is a constant representing the size in bytes of an instance
+of this file type.
+.OP
+.H 1 "OTHER DEBUGGING INFORMATION"
+This section describes debugging information that
+is not represented in the form of debugging information
+entries and is not contained within the
+.Cf .debug_info
+section.
+.H 2 "Accelerated Access"
+.I
+.IX accelerated access
+A debugger frequently needs to find the debugging information for
+a program object defined outside of the compilation unit
+where the debugged program is currently stopped. Sometimes
+it will know only the name of the object; sometimes only the address.
+To find the debugging information
+associated with a global object by name, using the DWARF debugging information
+entries alone, a debugger would need
+to run through all entries at the highest scope within each
+compilation unit. For lookup by address, for a subroutine,
+a debugger can use the low and high pc attributes
+of the compilation unit entries to quickly narrow down the search,
+but these attributes only cover
+the range of addresses for the text associated with a compilation
+unit entry. To find the debugging information associated with a
+data object, an exhaustive search would be needed.
+Furthermore, any search through debugging information entries for
+different compilation units within a large program
+would potentially require the access of many memory pages,
+probably hurting debugger performance.
+.R
+.P
+To make lookups of program objects by name or by address faster,
+a producer of DWARF information may provide two different types
+of tables containing information about the debugging information
+entries owned by a particular compilation unit entry in a more condensed
+format.
+.H 3 "Lookup by Name"
+.IX lookup, by name
+For lookup by name, a table is maintained in a separate
+object file section called
+.Cf .debug_pubnames .
+.IX \f(CW.debug_pubnames\fP %debugap
+The table consists of sets of variable length entries, each
+set describing the names of global objects whose definitions
+or declarations are represented by debugging information entries
+owned by a single compilation unit. Each set begins
+with a header containing four values: the total length of the entries
+for that set, not including the length field itself, a version number,
+the offset from the beginning of the
+.Cf .debug_info
+.IX \f(CW.debug_info\fP %debugai
+section of the compilation unit entry referenced by the set and
+the size in bytes of the contents of the
+.Cf .debug_info
+section generated to represent that compilation unit. This
+header is followed by a variable number of offset/name pairs.
+Each pair consists of the offset from the beginning of the compilation
+unit entry corresponding to the current set to the
+debugging information entry for
+the given object, followed by a null-terminated character
+string representing the name of the object as given by
+the
+.Cf DW_AT_name
+attribute of the referenced debugging entry.
+Each set of names is terminated by zero.
+.P
+.IX C++ %caa
+.IX members, static data
+In the case of the name of a static data member or function member
+of a C++ structure, class or union, the name presented
+in the
+.Cf .debug_pubnames
+section is not the simple name given by the
+.Cf DW_AT_name
+attribute of the referenced debugging entry, but rather
+the fully class qualified name of the data or function member.
+.IX identifiers, names
+.H 3 "Lookup by Address"
+.IX lookup, by address
+For lookup by address, a table is maintained in a separate
+object file section called
+.Cf .debug_aranges .
+.IX \f(CW.debug_aranges\fP %debugaar
+The table consists of sets of variable length entries, each
+set describing the portion of the program's address space that
+is covered by a single compilation unit. Each set begins
+with a header containing five values:
+.AL
+.LI
+The total length of the entries
+for that set, not including the length field itself.
+.LI
+A version number.
+.LI
+The offset from the beginning of the
+.Cf .debug_info
+.IX \f(CW.debug_info\fP %debugai
+section of the compilation unit entry referenced by the set.
+.LI
+The size in bytes of an address on the target architecture. For
+segmented addressing, this is the size of the offset portion of the
+.IX addresses, offset portion
+.IX addresses, size of
+address.
+.LI
+.IX address space, segmented
+.IX segmented address space
+The size in bytes of a segment descriptor on the target architecture.
+If the target system uses a flat address space, this value is 0.
+.LE
+.P
+This
+header is followed by a variable number of address
+range descriptors. Each descriptor is a pair consisting of
+the beginning address
+of a range of text or data covered by some entry owned
+by the corresponding compilation unit entry, followed by the length
+of that range. A particular set is terminated by an entry consisting
+of two zeroes. By scanning the table, a debugger can quickly
+decide which compilation unit to look in to find the debugging information
+for an object that has a given address.
+.H 2 "Line Number Information"
+.I
+.IX line number information
+A source-level debugger will need to know how to associate statements in
+the source files with the corresponding machine instruction addresses in
+the executable object or the shared objects used by that executable
+object. Such an association would make it possible for the debugger user
+to specify machine instruction addresses in terms of source statements.
+This would be done by specifying the line number and the source file
+containing the statement. The debugger can also use this information to
+display locations in terms of the source files and to single step from
+statement to statement.
+.R
+.P
+As mentioned in section 3.1, above,
+the line number information generated for a compilation unit
+is represented in the \f(CW.debug_line\fP section of an object file and is
+referenced by a corresponding compilation unit debugging information entry
+in the \f(CW.debug_info\fP section.
+.IX \f(CW.debug_info\fP %debugai
+.IX \f(CW.debug_line\fP %debugali
+.I
+.P
+If space were not a consideration, the information
+provided in the
+.Cf .debug_line
+section could be represented as a large matrix,
+with one row for each instruction in the emitted
+object code. The matrix would have columns for:
+.DL
+.LI
+the source file name
+.LI
+the source line number
+.LI
+the source column number
+.LI
+whether this instruction is the beginning of a source statement
+.LI
+whether this instruction is the beginning of a basic block.
+.LE
+.P
+Such a matrix, however, would be impractically large. We shrink it with
+two techniques. First, we delete from the matrix each row whose file,
+line and source column information is identical with that of its predecessors.
+Second, we design a byte-coded language for a state machine and store a stream
+of bytes in the object file instead of the matrix. This language can be
+much more compact than the matrix. When a consumer of the statement
+information executes, it must ``run'' the state machine to generate
+the matrix for each compilation unit it is interested in. The concept
+of an encoded matrix also leaves room for expansion. In the future,
+columns can be added to the matrix to encode other things that are
+related to individual instruction addresses.
+.R
+.H 3 "Definitions"
+.IX line number information, definitions
+The following terms are used in the description of the line number information
+format:
+.VL 20
+.LI "state machine"
+The hypothetical machine used by a consumer of the line number information
+to expand the byte-coded instruction stream into a
+matrix of line number information.
+.LI "statement program"
+A series of byte-coded line number information instructions representing one
+compilation unit.
+.LI "basic block"
+A sequence of instructions that is entered only at the first instruction
+and exited only at the last instruction. We define a procedure invocation
+to be an exit from a basic block.
+.LI "sequence"
+A series of contiguous target machine instructions. One compilation
+unit may emit multiple sequences (that is, not all instructions within
+a compilation unit are assumed to be contiguous).
+.LI "sbyte"
+Small signed integer.
+.LI "ubyte"
+Small unsigned integer.
+.LI "uhalf"
+Medium unsigned integer.
+.LI "sword"
+Large signed integer.
+.LI "uword"
+Large unsigned integer.
+.LI "LEB128"
+.IX LEB128
+Variable length signed and unsigned data. See section 7.6.
+.LE
+.H 3 "State Machine Registers"
+.IX line number information, state machine registers
+The statement information state machine has the following registers:
+.VL 20
+.LI "\f(CWaddress\fP"
+The program-counter value corresponding to a machine instruction generated
+by the compiler.
+.LI "\f(CWfile\fP"
+An unsigned integer indicating the identity of the source file corresponding
+to a machine instruction.
+.IX source, files
+.LI "\f(CWline\fP"
+.IX source, lines
+An unsigned integer indicating a source line number. Lines are numbered
+beginning at 1. The compiler may emit the value 0 in cases where an
+instruction cannot be attributed to any source line.
+.LI "\f(CWcolumn\fP"
+.IX source, columns
+An unsigned integer indicating a column number within a source line.
+Columns are numbered beginning at 1. The value 0 is reserved to indicate
+that a statement begins at the ``left edge'' of the line.
+.LI "\f(CWis_stmt\fP"
+A boolean indicating that the current instruction is the beginning of a
+statement.
+.LI "\f(CWbasic_block\fP"
+A boolean indicating that the current instruction is the beginning of
+a basic block.
+.LI "\f(CWend_sequence\fP"
+A boolean indicating that the current address is that of the first
+byte after the end of a sequence of target machine instructions.
+.LE
+.P
+At the beginning of each sequence within a statement program, the
+state of the registers is:
+.DS
+.TS
+;
+lf(CW) l.
+address 0
+file 1
+line 1
+column 0
+is_stmt determined by \f(CWdefault_is_stmt\fP in the statement program prologue
+basic_block ``false''
+end_sequence ``false''
+.TE
+.DE
+.H 3 "Statement Program Instructions"
+The state machine instructions in a statement program belong to one
+of three categories:
+.VL 20
+.LI "special opcodes"
+.IX line number information, special opcodes
+These have a ubyte opcode field and no arguments.
+Most of the instructions in a statement program are special opcodes.
+.LI "standard opcodes"
+.IX line number information, standard opcodes
+These have a ubyte opcode field which may be followed by zero or more
+LEB128 arguments (except for
+.Cf DW_LNS_fixed_advance_pc ,
+see below).
+The opcode implies the number of arguments and their
+meanings, but the statement program prologue also specifies the number
+of arguments for each standard opcode.
+.LI "extended opcodes"
+.IX line number information, extended opcodes
+These have a multiple byte format. The first byte is zero;
+the next bytes are an unsigned LEB128 integer giving the number of bytes
+in the instruction itself (does not include the first zero byte or the size).
+The remaining bytes are the instruction itself.
+.LE
+.H 3 "The Statement Program Prologue"
+.IX line number information, prologue
+The optimal encoding of line number information depends to a certain
+degree upon the architecture of the target machine. The statement program
+prologue provides information used by consumers in decoding the statement
+program instructions for a particular compilation unit and also provides
+information used throughout the rest of the statement program. The statement
+program for each compilation unit begins with a prologue containing the
+following fields in order:
+.AL
+.LI
+.Cf total_length
+(uword)
+.br
+The size in bytes of the statement information for this compilation unit
+(not including the
+.Cf total_length
+field itself).
+.LI
+.Cf version
+(uhalf)
+.br
+Version identifier for the statement information format.
+.LI
+.Cf prologue_length
+(uword)
+.br
+The number of bytes following the
+.Cf prologue_length
+field to the beginning of the first byte of the statement program itself.
+.LI
+.Cf minimum_instruction_length
+(ubyte)
+.br
+The size in bytes of the smallest target machine instruction. Statement
+program opcodes that alter the
+.Cf address
+register first multiply their operands by this value.
+.LI
+.Cf default_is_stmt
+(ubyte)
+.br
+The initial value of the
+.Cf is_stmt
+register.
+.P
+.I
+A simple code generator
+that emits machine instructions in the order implied by the source program
+would set this to ``true,'' and every entry in the matrix would represent
+a statement boundary. A pipeline scheduling code generator would set
+this to ``false'' and emit a specific statement program opcode for each
+instruction that represented a statement boundary.
+.R
+.LI
+.Cf line_base
+(sbyte)
+.br
+This parameter affects the meaning of the special opcodes. See below.
+.LI
+.Cf line_range
+(ubyte)
+.br
+This parameter affects the meaning of the special opcodes. See below.
+.LI
+.Cf opcode_base
+(ubyte)
+.br
+The number assigned to the first special opcode.
+.LI
+.Cf standard_opcode_lengths
+(array of ubyte)
+.br
+This array specifies the number of LEB128 operands for each of
+the standard opcodes. The first element of the array corresponds
+to the opcode whose value is 1, and the last element corresponds
+to the opcode whose value is
+.Cf "opcode_base - 1" .
+By increasing
+.Cf opcode_base ,
+and adding elements to this array, new standard opcodes
+can be added, while allowing consumers who do not know about these
+new opcodes to be able to skip them.
+.LI
+.Cf include_directories
+(sequence of path names)
+.br
+The sequence contains an entry for each path that was searched
+for included source files in this compilation. (The paths include
+those directories specified explicitly by the user for the compiler
+to search and those the compiler searches without explicit direction).
+Each path entry is either a full
+path name or is relative to the current directory of the compilation.
+The current directory of the compilation is understood to be the first entry
+and is not explicitly represented.
+Each entry is a null-terminated
+string containing a full path name. The last entry is followed by
+a single null byte.
+.LI
+.Cf file_names
+(sequence of file entries)
+.br
+.IX source, files
+The sequence contains an entry for each source file that contributed
+to the statement information for this compilation unit or is
+used in other contexts, such as in a declaration coordinate
+or a macro file inclusion. Each entry
+has a null-terminated string containing the file name,
+an unsigned LEB128 number representing the directory index of the
+directory in which the file was found,
+an unsigned LEB128 number representing the time of last modification for
+the file and an unsigned LEB128 number representing the length in
+bytes of the file. A compiler may choose to emit LEB128(0) for the
+time and length fields to indicate that this information is not
+available. The last entry is followed by a single null byte.
+.P
+The directory index represents an entry in the
+.Cf include_directories
+section. The index is LEB128(0) if the file was found in
+the current directory of the compilation, LEB128(1) if it was
+found in the first directory in the
+.Cf include_directories
+section, and so on. The directory index is ignored for file names
+that represent full path names.
+.P
+The statement program assigns numbers to each of the file entries
+in order, beginning with 1, and uses those numbers instead of file
+names in the
+.Cf file
+register.
+.P
+A compiler may generate a single null byte for the file names field
+and define file names using the extended opcode
+.Cf DEFINE_FILE .
+.LE
+.H 3 "The Statement Program"
+As stated before, the goal of a statement program is to build a
+matrix representing
+one compilation unit, which may have produced multiple sequences of
+target-machine instructions. Within a sequence, addresses may only increase.
+(Line numbers may decrease in cases of pipeline scheduling.)
+.H 4 "Special Opcodes"
+.IX line number information, special opcodes
+Each 1-byte special opcode has the following effect on the state machine:
+.AL
+.LI
+Add a signed integer to the
+.Cf line
+register.
+.LI
+Multiply an unsigned integer by the
+.Cf minimum_instruction_length
+field of the statement program prologue and
+add the result to the
+.Cf address
+register.
+.LI
+Append a row to the matrix using the current values of the state machine
+registers.
+.LI
+Set the
+.Cf basic_block
+register to ``false.''
+.LE
+.P
+All of the special opcodes do those same four things;
+they differ from one another
+only in what values they add to the
+.Cf line
+and
+.Cf address
+registers.
+.P
+.I
+Instead of assigning a fixed meaning to each special opcode, the statement
+program uses several
+parameters in the prologue to configure the instruction set. There are two
+reasons for this.
+First, although the opcode space available for special opcodes now
+ranges from 10 through 255, the lower bound may increase if one adds new
+standard opcodes. Thus, the
+.Cf opcode_base
+field of the statement program
+prologue gives the value of the first special opcode.
+Second, the best choice of special-opcode meanings depends on the target
+architecture. For example, for a RISC machine where the compiler-generated code
+interleaves instructions from different lines to schedule the pipeline,
+it is important to be able to add a negative value to the
+.Cf line
+register
+to express the fact that a later instruction may have been emitted for an
+earlier source line. For a machine where pipeline scheduling never occurs,
+it is advantageous to trade away the ability to decrease the
+.Cf line
+register
+(a standard opcode provides an alternate way to decrease the line number) in
+return for the ability to add larger positive values to the
+.Cf address
+register. To permit this variety of strategies, the statement program prologue
+defines a
+.Cf line_base
+field that specifies the minimum value which a special opcode can add
+to the
+.Cf line
+register and a
+.Cf line_range
+field that defines the range of
+values it can add to the
+.Cf line
+register.
+.R
+.P
+A special opcode value is chosen based on the amount that needs to
+be added to the
+.Cf line
+and
+.Cf address
+registers. The maximum line increment
+for a special opcode is the value of the
+.Cf line_base
+field in the
+prologue, plus the value of the
+.Cf line_range
+field, minus 1
+(\f(CWline base + line range - 1\fP). If the desired line increment
+is greater than the maximum line increment, a standard opcode
+must be used instead of a special opcode.
+The ``address advance'' is calculated by dividing the desired address
+increment by the
+.Cf minimum_instruction_length
+field from the
+prologue. The special opcode is then calculated using the following
+formula:
+.br
+ \f(CWopcode = (desired line increment - line_base) +
+.br
+ (line_range * address advance) + opcode_base\fP
+.br
+If the resulting opcode is greater than 255, a standard opcode
+must be used instead.
+.P
+To decode a special opcode, subtract the
+.Cf opcode_base
+from
+the opcode itself. The amount to increment the
+.Cf address
+register is
+the adjusted opcode divided by the
+.Cf line_range .
+The amount to
+increment the
+.Cf line
+register is the
+.Cf line_base
+plus the result
+of the adjusted opcode modulo the
+.Cf line_range .
+That is,
+.br
+ \f(CWline increment = line_base + (adjusted opcode % line_range)\fP
+.br
+.P
+.I
+As an example, suppose that the
+.Cf opcode_base
+is 16,
+.Cf line_base
+is -1 and
+.Cf line_range
+is 4.
+This means that we can use a special opcode whenever two successive
+rows in the matrix have source line numbers differing by any value within
+the range [-1, 2] (and, because of the limited number of opcodes available,
+when the difference between addresses is within the range [0, 59]).
+.P
+The opcode mapping would be:
+.R
+.DS
+.TS
+box center;
+l l l
+nf(CW) nf(CW) nf(CW)
+.
+Opcode Line advance Address advance
+_
+16 -1 0
+17 0 0
+18 1 0
+19 2 0
+20 -1 1
+21 0 1
+22 1 1
+23 2 1
+... ... ...
+253 0 59
+254 1 59
+255 2 59
+.TE
+.DE
+.P
+There is no requirement that the expression \f(CW255 - line_base + 1\fP be an
+integral multiple of
+.Cf line_range .
+.H 4 "Standard Opcodes"
+.IX line number information, standard opcodes
+There are currently 9 standard ubyte opcodes. In the future
+additional ubyte opcodes may be defined by setting the
+.Cf opcode_base
+field in the statement program
+prologue to a value greater than 10.
+.AL
+.LI
+.Cf DW_LNS_copy
+.br
+Takes no arguments. Append a row to the matrix using the current values of
+the state-machine registers. Then set the
+.Cf basic_block
+register to ``false.''
+.LI
+.Cf DW_LNS_advance_pc
+.br
+Takes a single unsigned LEB128 operand,
+multiplies it by the
+.Cf minimum_instruction_length
+field of the prologue, and adds the result to the
+.Cf address
+register of the state machine.
+.LI
+.Cf DW_LNS_advance_line
+.br
+Takes a single signed LEB128 operand and adds
+that value to the
+.Cf line
+register of the state machine.
+.LI
+.Cf DW_LNS_set_file
+.br
+Takes a single unsigned LEB128 operand and stores
+it in the
+.Cf file
+register of the state machine.
+.LI
+.Cf DW_LNS_set_column
+.br
+Takes a single unsigned LEB128 operand and stores
+it in the
+.Cf column
+register of the state machine.
+.LI
+.Cf DW_LNS_negate_stmt
+.br
+Takes no arguments.
+Set the
+.Cf is_stmt
+register of the state machine to the
+logical negation of its current value.
+.LI
+.Cf DW_LNS_set_basic_block
+.br
+Takes no arguments. Set the
+.Cf basic_block
+register of the state machine to ``true.''
+.LI
+.Cf DW_LNS_const_add_pc
+.br
+Takes no arguments.
+Add to the
+.Cf address
+register of the state machine the
+address increment value corresponding to special
+opcode 255.
+.P
+.I
+The motivation for
+.Cf DW_LNS_const_add_pc
+is this: when the statement program needs
+to advance the address by a small amount, it can use a single special
+opcode, which occupies a single byte. When it needs to advance the
+address by up to twice the range of the last special opcode, it can use
+.Cf DW_LNS_const_add_pc
+followed by a special opcode, for a total of two bytes.
+Only if it needs to advance the address by more than twice that range
+will it need to use both
+.Cf DW_LNS_advance_pc
+and a special opcode, requiring three or more bytes.
+.R
+.LI
+.Cf DW_LNS_fixed_advance_pc
+.br
+Takes a single uhalf operand. Add to the
+.Cf address
+register of the state machine the value of the (unencoded) operand.
+This is the only extended opcode that takes an argument that is not
+a variable length number.
+.P
+.I
+The motivation for
+.Cf DW_LNS_fixed_advance_pc
+is this: existing assemblers cannot emit
+.Cf DW_LNS_advance_pc
+or special opcodes because they cannot encode LEB128 numbers
+or judge when the computation of a special opcode overflows and requires
+the use of
+.Cf DW_LNS_advance_pc .
+Such assemblers, however, can use
+.Cf DW_LNS_fixed_advance_pc
+instead, sacrificing compression.
+.R
+.LE
+.H 4 "Extended Opcodes"
+.IX line number information, extended opcodes
+There are three extended opcodes currently defined. The first byte
+following the length field of the encoding for each contains a sub-opcode.
+.AL
+.LI
+\f(CWDW_LNE_end_sequence\fP
+.br
+Set the
+.Cf end_sequence
+register of the state machine
+to ``true'' and append a row to the matrix using the
+current values of the state-machine registers. Then
+reset the registers to the initial values specified
+above.
+.P
+Every statement program sequence must end with a
+.Cf DW_LNE_end_sequence
+instruction which creates a
+row whose address is that of the byte after the last target machine instruction
+of the sequence.
+.LI
+\f(CWDW_LNE_set_address\fP
+.br
+Takes a single relocatable address as an operand. The size of the
+operand is the size appropriate to hold an address on the target machine.
+Set the
+.Cf address
+register to the value given by the
+relocatable address.
+.P
+.I
+All of the other statement program opcodes that affect the
+.Cf address
+register add a delta to it.
+This instruction stores a relocatable value into it instead.
+.R
+.LI
+\f(CWDW_LNE_define_file\fP
+.br
+.IX source, files
+Takes 4 arguments. The first is a null terminated string containing a
+source file name. The second is an
+unsigned LEB128 number representing the directory index of the
+directory in which the file was found.
+The third is an unsigned LEB128 number representing
+the time of last modification of the file. The fourth is an unsigned
+LEB128 number representing the length in bytes of the file.
+The time and length fields may contain LEB128(0) if the information is
+not available.
+.P
+The directory index represents an entry in the
+.Cf include_directories
+section of the statement program prologue.
+The index is LEB128(0) if the file was found in
+the current directory of the compilation, LEB128(1) if it was
+found in the first directory in the
+.Cf include_directories
+section, and so on. The directory index is ignored for file names
+that represent full path names.
+.P
+The files are numbered, starting at 1,
+in the order in which they appear; the names in the prologue
+come before names defined by the
+.Cf DW_LNE_define_file
+instruction.
+These numbers are used in the the
+.Cf file
+register of the state machine.
+.LE
+.P
+.I
+Appendix 3 gives some sample statement programs.
+.R
+.H 2 "Macro Information"
+.I
+.IX macro information
+.IX pre-processor
+.IX C %c
+.IX C++ %caa
+Some languages, such as C and C++, provide a way to replace text
+in the source program with macros defined either in the source
+file itself, or in another file included by the source file.
+Because these macros are not themselves defined in the target
+language, it is difficult to represent their definitions
+using the standard language constructs of DWARF. The debugging
+information therefore reflects the state of the source after
+the macro definition has been expanded, rather than as the
+programmer wrote it.
+The macro information table provides a way of preserving the original
+source in the debugging information.
+.R
+.P
+As described in section 3.1, the macro information for a given
+compilation unit is represented in the
+.Cf .debug_macinfo
+.IX \f(CW.debug_macinfo\fP %debugam
+section of an object file. The macro information for each compilation
+unit is represented as a series of ``macinfo'' entries. Each
+macinfo entry consists of a ``type code'' and up to two additional
+operands. The series of entries for a given compilation unit
+ends with an entry containing a type code of 0.
+.H 3 "Macinfo Types"
+The valid macinfo types are as follows:
+.VL 30
+.LI \f(CWDW_MACINFO_define\fP
+A macro definition.
+.LI \f(CWDW_MACINFO_undef\fP
+A macro un-definition.
+.LI \f(CWDW_MACINFO_start_file\fP
+The start of a new source file inclusion.
+.LI \f(CWDW_MACINFO_end_file\fP
+The end of the current source file inclusion.
+.LI \f(CWDW_MACINFO_vendor_ext\fP
+Vendor specific macro information directives that do not fit
+into one of the standard categories.
+.LE
+.H 4 "Define and Undefine Entries"
+.IX macro information, define and undefine entries
+All
+.Cf DW_MACINFO_define
+and
+.Cf DW_MACINFO_undef
+entries have two operands.
+The first operand encodes the line number of the source line
+.IX source, lines
+on which the relevant defining or undefining
+pre-processor directives appeared.
+.P
+The second operand consists of a null-terminated character string.
+In the case of a
+.Cf DW_MACINFO_undef
+entry, the value of this
+string will be simply the name of the pre-processor
+symbol which was undefined at the indicated source line.
+.P
+In the case of a
+.Cf DW_MACINFO_define
+entry, the value of this
+string will be the name of the pre-processor symbol
+that was defined at the indicated source line,
+followed immediately by the macro formal parameter
+list including the surrounding parentheses (in the
+case of a function-like macro) followed by the
+definition string for the macro. If there is no
+formal parameter list, then the name of the defined
+macro is followed directly by its definition string.
+.P
+In the case of a function-like macro definition, no
+whitespace characters should appear between the
+name of the defined macro and the following left
+parenthesis. Also, no whitespace characters should
+appear between successive formal parameters in the
+formal parameter list. (Successive formal parameters
+should, however, be separated by commas.) Also, exactly
+one space character
+should separate the right parenthesis which terminates
+the formal parameter list and the following definition
+string.
+.P
+In the case of a ``normal'' (i.e. non-function-like)
+macro definition, exactly one space character
+should separate the name of the defined macro from the following definition
+text.
+.H 4 "Start File Entries"
+.IX macro information, start file entries
+Each
+.Cf DW_MACINFO_start_file
+entry also has two operands. The first operand
+encodes the line number of the
+source line on which the inclusion pre-processor
+directive occurred.
+.P
+.IX source, files
+The second operand encodes a
+source file name index. This index corresponds to a file
+number in the statement information table for the relevant
+compilation unit. This index
+indicates (indirectly) the name of the file
+which is being included by the inclusion directive on
+the indicated source line.
+.H 4 "End File Entries"
+.IX macro information, end file entries
+A
+.Cf DW_MACINFO_end_file
+entry has no operands. The presence of the entry marks the end of
+the current source file inclusion.
+.H 4 "Vendor Extension Entries"
+.IX macro information, vendor extensions
+.IX vendor extensions
+A
+.Cf DW_MACINFO_vendor_ext
+entry has two operands.
+The first is a constant. The second is a null-terminated
+character string.
+The meaning and/or significance of these operands is
+intentionally left undefined by this specification.
+.P
+A consumer must be able to totally ignore all
+.Cf DW_MACINFO_vendor_ext
+entries that it does not understand.
+.H 3 "Base Source Entries"
+.IX macro information, base source entries
+In addition to producing a matched pair of
+.Cf DW_MACINFO_start_file
+and
+.Cf DW_MACINFO_end_file
+entries for
+each inclusion directive actually processed during
+compilation, a producer should generate such a matched
+pair also for the ``base'' source file submitted to the
+compiler for compilation. If the base source file
+.IX source, files
+for a compilation is submitted to the compiler via
+some means other than via a named disk file (e.g. via
+the standard input \fIstream\fP on a UNIX system) then the
+compiler should still produce this matched pair of
+.Cf DW_MACINFO_start_file
+and
+.Cf DW_MACINFO_end_file
+entries for
+the base source file, however, the file name indicated
+(indirectly) by the
+.Cf DW_MACINFO_start_file
+entry of the
+pair should reference a statement information file name entry consisting
+of a null string.
+.H 3 "Macinfo Entries for Command Line Options"
+.IX macro information, command line options
+In addition to producing
+.Cf DW_MACINFO_define
+and
+.Cf DW_MACINFO_undef
+entries for each of the define and
+undefine directives processed during compilation, the
+DWARF producer should generate a
+.Cf DW_MACINFO_define
+or
+.Cf DW_MACINFO_undef
+entry for each pre-processor symbol
+which is defined or undefined by some
+means other than via a define or undefine directive
+within the compiled source text. In particular,
+pre-processor symbol definitions and un-definitions
+which occur as a result of command line options
+(when invoking the compiler) should be represented by
+their own
+.Cf DW_MACINFO_define
+and
+.Cf DW_MACINFO_undef
+entries.
+.P
+All such
+.Cf DW_MACINFO_define
+and
+.Cf DW_MACINFO_undef
+entries representing compilation options should appear
+before the first
+.Cf DW_MACINFO_start_file
+entry for that compilation unit and should encode the value
+0 in their line number operands.
+.H 3 " General Rules and Restrictions"
+.IX line number information, general rules
+All macinfo entries within a
+.Cf .debug_macinfo
+section for a given compilation unit should appear in the same order
+in which the directives were processed by the compiler.
+.P
+All macinfo entries representing command line options
+should appear in the same order as the relevant command
+line options were given to the compiler. In the case
+where the compiler itself implicitly supplies one or
+more macro definitions or un-definitions in addition
+to those which may be specified on the command line,
+macinfo entries should also be produced for these
+implicit definitions and un-definitions, and
+these entries should also appear in the proper order
+relative to each other and to any definitions or
+undefinitions given explicitly by the user on the
+command line.
+.H 2 "Call Frame Information"
+.IX call frame information
+.IX activations
+.I
+Debuggers often need to be able to view and modify the state of any
+subroutine activation that is on the call stack. An activation
+consists of:
+.BL
+.LI
+A code location that is within the subroutine. This location is
+either the place where the program stopped when the debugger got
+control (e.g. a breakpoint), or is a place where a subroutine
+made a call or was interrupted by an asynchronous event (e.g. a
+signal).
+.LI
+An area of memory that is allocated on a stack called a ``call
+frame.'' The call frame is identified by an address on the
+stack. We refer to this address as the Canonical Frame Address or CFA.
+.LI
+A set of registers that are in use by the subroutine at the code
+location.
+.LE
+.P
+Typically, a set of registers are designated to be preserved across a
+call. If a callee wishes to use such a register, it saves the value
+that the register had at entry time in its call frame and restores it
+on exit. The code that allocates space on the call frame stack and
+performs the save operation is called the subroutine's prologue, and the
+code that performs the restore operation and deallocates the frame is
+called its epilogue. Typically, the prologue code is physically at the
+beginning of a subroutine and the epilogue code is at the end.
+.P
+To be able to view or modify an activation that is not on the top of
+the call frame stack, the debugger must ``virtually unwind'' the stack of
+activations until it finds the activation of interest.
+A debugger unwinds a
+stack in steps. Starting with the current activation it restores any
+registers that were preserved by the current activation and computes the
+predecessor's CFA and code location. This has the logical effect of
+returning from the current subroutine to its predecessor. We say that
+the debugger virtually unwinds the stack because it preserves enough
+information to be able to ``rewind'' the stack back to the state it was
+in before it attempted to unwind it.
+.P
+The unwinding operation needs to know where registers are saved and how
+to compute the predecessor's CFA and code location. When considering
+an architecture-independent way of encoding this information one has to
+consider a number of special things.
+.BL
+.LI
+Prologue and epilogue code is not always in distinct blocks at the
+beginning and end of a subroutine. It is common to duplicate the
+epilogue code at the site of each return from the code. Sometimes
+a compiler breaks up the register save/unsave operations and moves
+them into the body of the subroutine to just where they are needed.
+.LI
+Compilers use different ways to manage the call frame. Sometimes
+they use a frame pointer register, sometimes not.
+.LI
+The algorithm to compute the CFA changes as you progress through
+the prologue and epilogue code. (By definition, the CFA value
+does not change.)
+.LI
+Some subroutines have no call frame.
+.LI
+Sometimes a register is saved in another register that by
+convention does not need to be saved.
+.LI
+Some architectures have special instructions that
+perform some or all of the register management in one instruction,
+leaving special information on the stack that indicates how
+registers are saved.
+.LI
+Some architectures treat return address values
+specially. For example, in one architecture,
+the call instruction guarantees that the low order two
+bits will be zero and the return instruction ignores those bits.
+This leaves two bits of storage that are available to other uses
+that must be treated specially.
+.LE
+.R
+.H 3 "Structure of Call Frame Information"
+.IX call frame information, structure
+DWARF supports virtual unwinding by defining an architecture independent
+basis for recording how procedures save and restore registers throughout
+their lifetimes. This basis must be augmented on some machines with
+specific information that is defined by either an architecture specific
+ABI authoring committee, a hardware vendor, or a compiler producer.
+.IX ABI
+.IX vendor extensions
+The body defining a specific augmentation is referred to
+below as the ``augmenter.''
+.P
+Abstractly, this mechanism describes a very large table that has the
+following structure:
+.TS
+center;
+l l l l l l
+l s s s s s.
+LOC CFA R0 R1 ... RN
+L0
+L1
+\...
+LN
+.TE
+.P
+The first column indicates an address for every location that contains
+code in a program. (In shared objects, this is an object-relative
+offset.) The remaining columns contain virtual unwinding rules that are
+associated with the indicated location. The first column of the rules
+defines the CFA rule which is a register and a signed offset that are
+added together to compute the CFA value.
+.P
+The remaining columns are labeled by register number. This includes
+some registers that have special designation on some architectures such
+as the PC and the stack pointer register. (The actual mapping of
+registers for a particular architecture is performed by the augmenter.)
+The register columns contain rules that describe
+whether a given register has been saved and the rule to find
+the value for the register in the previous frame.
+.P
+The register rules are:
+.IX call frame information, register rules
+.VL 20
+.LI "undefined"
+A register that has this rule has no value in the
+previous frame. (By convention, it is not preserved by a callee.)
+.LI "same value"
+This register has not been modified from the
+previous frame. (By convention, it is preserved by the callee,
+but the callee has not modified it.)
+.LI "offset(N)"
+The previous value of this register is saved at the address CFA+N where
+CFA is the current CFA value and N is a signed offset.
+.LI "register(R)"
+The previous value of this register is stored in
+another register numbered R.
+.LI "architectural"
+The rule is defined externally to this specification by the augmenter.
+.LE
+.P
+.I
+This table would be extremely large if actually constructed as
+described. Most of the entries at any point in the table are identical
+to the ones above them. The whole table can be represented quite
+compactly by recording just the differences starting at the beginning
+address of each subroutine in the program.
+.R
+.P
+The virtual unwind information is encoded in a self-contained section
+called
+.Cf .debug_frame .
+.IX \f(CW.debug_frame\fP %debugaf
+Entries in a
+.Cf .debug_frame
+section are aligned on
+.IX call frame information, Common Information Entry
+an addressing unit boundary and come in two forms: A Common Information
+Entry (CIE) and a Frame Description Entry (FDE).
+Sizes of data objects used in the encoding of the
+.Cf .debug_frame
+section are described in terms of the same data definitions
+used for the line number information (see section 6.2.1).
+.P
+A Common Information Entry holds information that is shared among many
+Frame Descriptors. There is at least one CIE in every non-empty
+.Cf .debug_frame
+section. A CIE contains the following fields, in order:
+.AL
+.LI
+\f(CWlength\fP
+.br
+A uword constant that gives the number of bytes of the CIE
+structure, not including the length field, itself
+(length mod <addressing unit size> == 0).
+.LI
+\f(CWCIE_id\fP
+.br
+A uword constant that is used to distinguish CIEs
+from FDEs.
+.LI
+\f(CWversion\fP
+.br
+A ubyte version number. This number is specific to the call frame
+information and is independent of the DWARF version number.
+.LI
+\f(CWaugmentation\fP
+.br
+A null terminated string that identifies the
+augmentation to this CIE or to the FDEs that use
+it. If a reader encounters an augmentation string that is
+unexpected, then only the following fields can be read:
+CIE:
+.Cf length ,
+.Cf CIE_id ,
+.Cf version ,
+.Cf augmentation ;
+FDE:
+.Cf length ,
+.Cf CIE_pointer ,
+.Cf initial_location ,
+.Cf address_range .
+If there is no augmentation, this value is a zero byte.
+.LI
+\f(CWcode_alignment_factor\fP
+.br
+An unsigned LEB128 constant that is factored out
+of all advance location instructions (see below).
+.LI
+\f(CWdata_alignment_factor\fP
+.br
+A signed LEB128 constant that is factored out
+of all offset instructions (see below.)
+.LI
+\f(CWreturn_address_register\fP
+.br
+A ubyte constant that indicates
+which column in the rule table represents the return address
+of the function. Note that this column might not correspond
+to an actual machine register.
+.LI
+\f(CWinitial_instructions\fP
+.br
+A sequence of rules that are interpreted to
+create the initial setting of each column in the table.
+.LI
+\f(CWpadding\fP
+.br
+Enough
+.Cf DW_CFA_nop
+instructions to make the size of this entry
+match the
+.Cf length
+value above.
+.LE
+.P
+An FDE contains the following fields, in order:
+.IX call frame information, Frame Description Entry
+.AL
+.LI
+\f(CWlength\fP
+.br
+A uword constant that gives the number of bytes of the header
+and instruction stream for this function (not including the length
+field itself) (length mod <addressing unit size> == 0).
+.LI
+\f(CWCIE_pointer\fP
+.br
+A uword constant offset into the
+.Cf .debug_frame
+section that denotes the CIE that is associated with this FDE.
+.LI
+\f(CWinitial_location\fP
+An addressing-unit sized constant indicating
+the address of the first location associated with this table entry.
+.LI
+\f(CWaddress_range\fP
+.br
+An addressing unit sized constant indicating the
+number of bytes of program instructions described by this entry.
+.LI
+\f(CWinstructions\fP
+.br
+A sequence of table defining instructions that are
+described below.
+.LE
+.H 3 "Call Frame Instructions"
+.IX call frame information, instructions
+Each call frame instruction is defined to
+take 0 or more operands. Some of the operands may be
+encoded as part of the opcode (see section 7.23).
+The instructions are as follows:
+.AL
+.LI
+.Cf DW_CFA_advance_loc
+takes a single argument that represents a constant delta.
+The required action is to
+create a new table row with a location value that
+is computed by taking the current entry's location value and
+adding (delta * \f(CWcode_alignment_factor\fP). All other values in the
+new row are initially identical to the current row.
+.LI
+.Cf DW_CFA_offset
+takes two arguments:
+an unsigned LEB128 constant representing a factored offset
+and a register number. The required action is
+to change the rule for the register indicated by the register
+number to be an offset(N) rule with a value of
+(N = factored offset * \f(CWdata_alignment_factor\fP).
+.LI
+.Cf DW_CFA_restore
+takes a single argument that represents a register number.
+The required action is
+to change the rule for the indicated register
+to the rule assigned it by the \f(CWinitial_instructions\fP in the CIE.
+.LI
+.Cf DW_CFA_set_loc
+takes a single argument that represents an address.
+The required action is to create a new table row
+using the specified address as the location.
+All other values in the
+new row are initially identical to the current row.
+The new location value should always be greater than the current
+one.
+.LI
+.Cf DW_CFA_advance_loc1
+takes a single ubyte argument that represents a constant delta.
+This instruction is identical to
+.Cf DW_CFA_advance_loc
+except for the encoding and size of the delta argument.
+.LI
+.Cf DW_CFA_advance_loc2
+takes a single uhalf argument that represents a constant delta.
+This instruction is identical to
+.Cf DW_CFA_advance_loc
+except for the encoding and size of the delta argument.
+.LI
+.Cf DW_CFA_advance_loc4
+takes a single uword argument that represents a constant delta.
+This instruction is identical to
+.Cf DW_CFA_advance_loc
+except for the encoding and size of the delta argument.
+.LI
+.Cf DW_CFA_offset_extended
+takes two unsigned LEB128 arguments representing a register number
+and a factored offset.
+This instruction is identical to
+.Cf DW_CFA_offset
+except for the encoding and size of the register argument.
+.LI
+.Cf DW_CFA_restore_extended
+takes a single unsigned LEB128 argument that represents a register number.
+This instruction is identical to
+.Cf DW_CFA_restore
+except for the encoding and size of the register argument.
+.LI
+.Cf DW_CFA_undefined
+takes a single unsigned LEB128 argument that represents a register number.
+The required action is to set the rule for the specified register
+to ``undefined.''
+.LI
+.Cf DW_CFA_same_value
+takes a single unsigned LEB128 argument that represents a register number.
+The required action is to set the rule for the specified register
+to ``same value.''
+.LI
+.Cf DW_CFA_register
+takes two unsigned LEB128 arguments representing register numbers.
+The required action is to set the rule for the first register
+to be the second register.
+.LI
+\f(CWDW_CFA_remember_state\fP
+.LI
+\f(CWDW_CFA_restore_state\fP
+.br
+These instructions define a stack of information. Encountering the
+.Cf DW_CFA_remember_state
+instruction means to save the rules for every register
+on the current row on the stack. Encountering the
+.Cf DW_CFA_restore_state
+instruction means to pop the set of rules
+off the stack and place them in the current row.
+.I
+(This
+operation is useful for compilers that move epilogue
+code into the body of a function.)
+.R
+.LI
+.Cf DW_CFA_def_cfa
+takes two unsigned LEB128 arguments representing a
+register number and an offset.
+The required action is to define the current CFA rule
+to use the provided register and offset.
+.LI
+.Cf DW_CFA_def_cfa_register
+takes a single unsigned LEB128 argument representing a register
+number. The required action is to define the current CFA
+rule to use the provided register (but to keep the old offset).
+.LI
+.Cf DW_CFA_def_cfa_offset
+takes a single unsigned LEB128 argument representing an offset.
+The required action is to define the current CFA
+rule to use the provided offset (but to keep the old register).
+.LI
+.Cf DW_CFA_nop
+has no arguments and no required actions. It is used as padding
+to make the FDE an appropriate size.
+.LE
+.H 3 "Call Frame Instruction Usage"
+.IX call frame information, usage
+.I
+To determine the virtual unwind rule set for a given location (L1), one
+searches through the FDE headers looking at the
+.Cf initial_location
+and
+.Cf address_range
+values to see if L1 is contained in the FDE. If so, then:
+.AL
+.LI
+Initialize a register set by reading the
+.Cf initial_instructions
+field of the associated CIE.
+.LI
+Read and process the FDE's instruction sequence until a
+.Cf DW_CFA_advance_loc ,
+.Cf DW_CFA_set_loc ,
+or the end of the instruction stream is
+encountered.
+.LI
+If a
+.Cf DW_CFA_advance_loc
+or
+.Cf DW_CFA_set_loc
+instruction was encountered, then
+compute a new location value (L2). If L1 >= L2 then process the
+instruction and go back to step 2.
+.LI
+The end of the instruction stream can be thought of as a
+.br
+\f(CWDW_CFA_set_loc( initial_location + address_range )\fP
+.br
+instruction.
+Unless the FDE is ill-formed, L1 should be less than L2 at this point.
+.LE
+.P
+The rules in the register set now apply to location L1.
+.P
+For an example, see Appendix 5.
+.R
+.OP
+.H 1 "DATA REPRESENTATION"
+This section describes the binary representation of the debugging
+information entry itself, of the
+attribute types and of other fundamental elements described above.
+.H 2 "Vendor Extensibility"
+.IX vendor extensions
+To reserve a portion of the DWARF name space and ranges of
+enumeration values for use for vendor specific extensions,
+.IX tags
+.IX types, base
+.IX base types
+.IX locations, expressions
+.IX calling conventions
+.IX call frame information
+special labels are reserved for tag names, attribute names,
+base type encodings, location operations, language names,
+calling conventions and call frame instructions.
+The labels denoting the beginning and end of the reserved value
+range for vendor specific extensions consist of the appropriate prefix (
+.Cf DW_TAG ,
+.Cf DW_AT ,
+.Cf DW_ATE ,
+.Cf DW_OP ,
+.Cf DW_LANG ,
+.CF DW_CC
+or
+.Cf DW_CFA
+respectively) followed by
+.Cf _lo_user
+or
+.Cf _hi_user .
+For example, for entry tags, the special labels are
+.Cf DW_TAG_lo_user
+and
+.Cf DW_TAG_hi_user .
+Values in the range between \fIprefix\fP\f(CW_lo_user\fP and
+\fIprefix\fP\f(CW_hi_user\fP
+inclusive, are reserved for vendor specific extensions.
+Vendors may use values in this range without
+conflicting with current or future system-defined values.
+All other values are reserved for use by the system.
+.P
+Vendor defined tags, attributes, base type encodings, location atoms,
+language names, calling conventions and call frame instructions,
+conventionally use the form
+\fIprefix\f(CW_\fIvendor_id\f(CW_\fIname\fR, where \fIvendor_id\fP is some
+identifying character sequence chosen so as to avoid conflicts with other
+vendors.
+.P
+.IX compatibility
+To ensure that extensions added by one vendor may be safely ignored
+by consumers that do not understand those extensions,
+the following rules should be followed:
+.AL
+.LI
+New attributes should be added in such a way that a debugger may recognize
+the format of a new attribute value without knowing the content of that
+attribute value.
+.LI
+The semantics of any new attributes should not alter the semantics of
+previously existing attributes.
+.LI
+The semantics of any new tags
+should not conflict with the semantics of previously existing tags.
+.LE
+.H 2 "Reserved Error Values"
+.IX error values
+As a convenience for consumers of DWARF information,
+the value 0 is reserved in the encodings for attribute names, attribute
+forms, base type encodings, location operations, languages,
+statement program opcodes, macro information entries and tag names
+to represent an error condition or unknown value. DWARF does
+not specify names for these reserved values, since they do not
+represent valid encodings for the given type and should not appear
+in DWARF debugging information.
+.H 2 "Executable Objects and Shared Objects"
+The relocated addresses in the debugging information for an executable
+object are virtual addresses and the relocated addresses in the
+debugging information for a shared object are offsets relative to
+the start of the lowest segment used by that shared object.
+.P
+.I
+This requirement makes the debugging information for shared objects
+position independent.
+Virtual addresses in a shared object may be calculated by adding the
+offset to the base address at which the object was attached.
+This offset is available in the run-time linker's data structures.
+.H 2 "File Constraints"
+All debugging information entries in a relocatable object file,
+executable object or shared
+object are required to be physically contiguous.
+.H 2 "Format of Debugging Information"
+.IX Version 2
+For each compilation unit compiled with a DWARF Version 2 producer,
+.IX compilation units
+.IX compilation units, header
+a contribution is made to the
+.Cf .debug_info
+.IX \f(CW.debug_info\fP %debugai
+section of the object file. Each such contribution consists of
+a compilation unit header followed by a series of debugging information
+entries. Unlike the information encoding for DWARF Version 1, Version 2
+.IX Version 1
+debugging information entries do not themselves contain the debugging
+information entry tag or the attribute name and form encodings for
+each attribute. Instead, each debugging information entry begins with
+a code that represents an entry in a separate abbreviations table.
+This code is followed directly by a series of attribute values.
+The appropriate entry in the abbreviations table guides the interpretation
+of the information contained directly in the
+.Cf .debug_info
+section. Each compilation unit is associated with a particular
+abbreviation table, but multiple compilation units may share
+the same table.
+.IX abbreviations table
+.I
+.P
+This encoding was based on the observation that typical DWARF producers
+produce a very limited number of different types of debugging information
+entries. By extracting the common information from those entries
+into a separate table, we are able to compress the generated information.
+.R
+.H 3 "Compilation Unit Header"
+.IX compilation units, header
+The header for the series of debugging information entries contributed
+by a single compilation unit consists of the following information:
+.AL
+.LI
+A 4-byte unsigned integer representing the length of the
+.Cf .debug_info
+contribution for that compilation unit, not including the length field itself.
+.LI
+A 2-byte unsigned integer representing the version of the DWARF information
+for that compilation unit. For DWARF Version 2, the value in this field is 2.
+.IX Version 2
+.LI
+A 4-byte unsigned offset into the
+.Cf .debug_abbrev
+.IX \f(CW.debug_abbrev\fP %debugaab
+section. This offset associates the compilation unit with a particular
+set of debugging information entry abbreviations.
+.LI
+.IX segmented address space
+.IX address space, segmented
+.IX addresses, size of
+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.
+.IX addresses, offset portion
+.LE
+.P
+.I
+The compilation unit header does not replace the
+.Cf DW_TAG_compile_unit
+debugging information entry. It is additional information that
+is represented outside the standard DWARF tag/attributes format.
+.R
+.H 3 "Debugging Information Entry"
+Each debugging information entry begins with an unsigned LEB128
+.IX debugging information entries
+number containing the abbreviation code for the entry.
+This code represents an entry within the abbreviation table associated
+with the compilation unit containing this entry. The abbreviation
+.IX abbreviations table
+code is followed by a series of attribute values.
+.IX attributes, values
+.P
+On some architectures, there are alignment constraints on section boundaries.
+To make it easier to pad debugging information sections to satisfy
+such constraints, the abbreviation code 0 is reserved. Debugging
+information entries consisting of only the 0 abbreviation code are considered
+null entries.
+.IX debugging information entries, null entries
+.H 3 "Abbreviation Tables"
+.IX abbreviations table
+The abbreviation tables for all compilation units are contained in
+a separate object file section called
+.Cf .debug_abbrev .
+.IX \f(CW.debug_abbrev\fP %debugaab
+As mentioned before, multiple compilation units may share the same
+abbreviation table.
+.P
+The abbreviation table for a single compilation
+unit consists of a series of abbreviation declarations.
+Each declaration specifies the tag and attributes for a particular
+.IX tags
+.IX attributes
+form of debugging information entry. Each declaration begins with
+an unsigned LEB128 number representing the abbreviation code itself.
+It is this code that appears at the beginning of a debugging information
+entry in the
+.Cf .debug_info
+section. As described above, the abbreviation code 0 is reserved for null
+debugging information entries.
+The abbreviation code is followed by another unsigned LEB128
+number that encodes the entry's tag.
+.IX tags
+.nr aX \n(Fg+1
+.nr bX \n(Fg+2
+The encodings for the tag names are given in Figures \n(aX
+and \n(bX.
+.DF
+.TS
+box center;
+l l
+lf(CW) lf(CW)
+.
+Tag name Value
+_
+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
+.TE
+.FG "Tag encodings (part 1)"
+.DE
+.DF
+.TS
+box center;
+l l
+lf(CW) lf(CW)
+.
+Tag name Value
+_
+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_lo_user 0x4080
+DW_TAG_hi_user 0xffff
+.TE
+.FG "Tag encodings (part 2)"
+.DE
+.P
+Following the tag encoding is a 1-byte value that determines
+whether a debugging information entry using this abbreviation
+has child entries or not. If the value is
+.Cf DW_CHILDREN_yes ,
+the next physically succeeding entry of any debugging information
+entry using this abbreviation is the first child of the prior entry.
+If the 1-byte value following the abbreviation's tag encoding
+is
+.Cf DW_CHILDREN_no ,
+the next physically succeeding entry of any debugging information entry
+using this abbreviation is a sibling of the prior entry. (Either
+the first child or sibling entries may be null entries).
+.IX debugging information entries, siblings
+.IX debugging information entries, child entries
+.IX debugging information entries, null entries
+.nr aX \n(Fg+1
+The encodings for the child determination byte are given in Figure \n(aX.
+(As mentioned in section 2.3, each chain of sibling entries is
+terminated by a null entry).
+.IX debugging information entries, null entries
+.DF
+.TS
+box center;
+l l
+lf(CW) lf(CW)
+.
+Child determination name Value
+_
+DW_CHILDREN_no 0
+DW_CHILDREN_yes 1
+.TE
+.FG "Child determination encodings"
+.DE
+.P
+Finally, the child encoding is followed by a series of attribute specifications.
+.IX attributes
+Each attribute specification consists of two parts. The first part
+is an unsigned LEB128 number representing the attribute's name.
+.IX attributes, names
+The second part is an unsigned LEB128 number representing the
+attribute's form. The series of attribute specifications ends
+.IX attributes, forms
+with an entry containing 0 for the name and 0 for the form.
+.P
+The attribute form
+.Cf DW_FORM_indirect
+is a special case. For attributes with this form, the attribute value
+itself in the
+.Cf .debug_info
+section begins with an unsigned LEB128 number that represents its form.
+This allows producers to choose forms for particular attributes dynamically,
+without having to add a new entry to the abbreviation table.
+.P
+The abbreviations for a given compilation unit end with an entry
+consisting of a 0 byte for the abbreviation code.
+.I
+.P
+See Appendix 2 for a depiction of the organization
+of the debugging information.
+.R
+.H 3 "Attribute Encodings"
+.nr aX \n(Fg+1
+.nr bX \n(Fg+2
+The encodings for the attribute names are given in Figures \n(aX
+and \n(bX.
+.DF
+.TS
+box center;
+l l l
+lf(CW) lf(CW) l
+.
+Attribute name Value Classes
+_
+DW_AT_sibling 0x01 reference
+DW_AT_location 0x02 block, constant
+DW_AT_name 0x03 string
+DW_AT_ordering 0x09 constant
+DW_AT_byte_size 0x0b constant
+DW_AT_bit_offset 0x0c constant
+DW_AT_bit_size 0x0d constant
+DW_AT_stmt_list 0x10 constant
+DW_AT_low_pc 0x11 address
+DW_AT_high_pc 0x12 address
+DW_AT_language 0x13 constant
+DW_AT_discr 0x15 reference
+DW_AT_discr_value 0x16 constant
+DW_AT_visibility 0x17 constant
+DW_AT_import 0x18 reference
+DW_AT_string_length 0x19 block, constant
+DW_AT_common_reference 0x1a reference
+DW_AT_comp_dir 0x1b string
+DW_AT_const_value 0x1c string, constant, block
+DW_AT_containing_type 0x1d reference
+DW_AT_default_value 0x1e reference
+DW_AT_inline 0x20 constant
+DW_AT_is_optional 0x21 flag
+DW_AT_lower_bound 0x22 constant, reference
+DW_AT_producer 0x25 string
+DW_AT_prototyped 0x27 flag
+DW_AT_return_addr 0x2a block, constant
+DW_AT_start_scope 0x2c constant
+DW_AT_stride_size 0x2e constant
+DW_AT_upper_bound 0x2f constant, reference
+.TE
+.FG "Attribute encodings, part 1"
+.DE
+.DF
+.TS
+box center;
+l l l
+lf(CW) lf(CW) l
+.
+Attribute name Value Classes
+_
+DW_AT_abstract_origin 0x31 reference
+DW_AT_accessibility 0x32 constant
+DW_AT_address_class 0x33 constant
+DW_AT_artificial 0x34 flag
+DW_AT_base_types 0x35 reference
+DW_AT_calling_convention 0x36 constant
+DW_AT_count 0x37 constant, reference
+DW_AT_data_member_location 0x38 block, reference
+DW_AT_decl_column 0x39 constant
+DW_AT_decl_file 0x3a constant
+DW_AT_decl_line 0x3b constant
+DW_AT_declaration 0x3c flag
+DW_AT_discr_list 0x3d block
+DW_AT_encoding 0x3e constant
+DW_AT_external 0x3f flag
+DW_AT_frame_base 0x40 block, constant
+DW_AT_friend 0x41 reference
+DW_AT_identifier_case 0x42 constant
+DW_AT_macro_info 0x43 constant
+DW_AT_namelist_item 0x44 block
+DW_AT_priority 0x45 reference
+DW_AT_segment 0x46 block, constant
+DW_AT_specification 0x47 reference
+DW_AT_static_link 0x48 block, constant
+DW_AT_type 0x49 reference
+DW_AT_use_location 0x4a block, constant
+DW_AT_variable_parameter 0x4b flag
+DW_AT_virtuality 0x4c constant
+DW_AT_vtable_elem_location 0x4d block, reference
+DW_AT_lo_user 0x2000 \(em
+DW_AT_hi_user 0x3fff \(em
+.TE
+.FG "Attribute encodings, part 2"
+.DE
+.P
+.IX attributes, forms
+The attribute form governs how the value of the attribute is encoded.
+The possible forms may belong to one of the following
+form classes:
+.VL 18
+.LI address
+.IX attributes, addresses
+Represented as an object of appropriate size to hold an
+address on the target machine (\f(CWDW_FORM_addr\fP).
+This address is relocatable in
+a relocatable object file and is relocated in an
+executable file or shared object.
+.LI "block"
+.IX attributes, blocks
+Blocks come in four forms. The first consists of a 1-byte length
+followed by 0 to 255 contiguous information bytes (\f(CWDW_FORM_block1\fP).
+The second consists of a 2-byte length
+followed by 0 to 65,535 contiguous information bytes (\f(CWDW_FORM_block2\fP).
+The third consists of a 4-byte length
+followed by 0 to 4,294,967,295 contiguous information bytes (\f(CWDW_FORM_block4\fP).
+The fourth consists of an unsigned LEB128 length followed by the number
+of bytes specified by the length (\f(CWDW_FORM_block\fP).
+In all forms, the length is the number of information bytes that follow.
+The information bytes may contain any mixture of relocated (or
+relocatable) addresses, references to other debugging information entries or
+data bytes.
+.LI "constant"
+.IX attributes, constants
+There are six forms of constants:
+one, two, four and eight byte values (respectively,
+.Cf DW_FORM_data1 ,
+.Cf DW_FORM_data2 ,
+.Cf DW_FORM_data4 ,
+and
+.Cf DW_FORM_data8 ).
+.IX variable length data
+.IX LEB128
+There are also variable length constant data forms encoded
+using LEB128 numbers (see below). Both signed (\f(CWDW_FORM_sdata\fP)
+and unsigned (\f(CWDW_FORM_udata\fP) variable length constants are available.
+.LI flag
+.IX attributes, flags
+A flag is represented as a single byte of data (\f(CWDW_FORM_flag\fP).
+If the flag has value zero, it indicates the absence of the attribute.
+If the flag has a non-zero value, it indicates the presence of
+the attribute.
+.LI reference
+.IX attributes, references
+There are two types of reference. The first is an
+offset relative to the first byte of the compilation unit header
+for the compilation unit containing the reference.
+The offset must refer to an entry within
+that same compilation unit. There are five forms for this
+type of reference:
+one, two, four and eight byte offsets (respectively,
+.Cf DW_FORM_ref1 ,
+.Cf DW_FORM_ref2 ,
+.Cf DW_FORM_ref4 ,
+and
+.Cf DW_FORM_ref8 ).
+There are is also an unsigned variable length offset encoded
+using LEB128 numbers (\f(CWDW_FORM_ref_udata\fP).
+.P
+The second type of reference
+is the address of any debugging information entry within
+the same executable or shared object; it may refer to an entry
+in a different compilation unit from the unit containing the
+reference. This type of reference (\f(CWDW_FORM_ref_addr\fP) is the
+size of an address on the target architecture; it is relocatable
+in a relocatable object file and relocated in an executable file
+or shared object.
+.P
+.I
+The use of compilation unit relative references will reduce
+the number of link-time relocations and so speed up linking.
+.P
+The use of address-type references allows for the commonization
+of information, such as types, across compilation units.
+.R
+.LI string
+.IX attributes, strings
+A string is a sequence of contiguous non-null bytes followed by one null
+byte. A string may be represented immediately in the debugging information
+entry itself (\f(CWDW_FORM_string\fP), or may be represented as a 4-byte offset
+into a string table contained in the
+.Cf .debug_str
+.IX \f(CW.debug_str\fP %debugas
+.IX string table
+section of the object file (\f(CWDW_FORM_strp\fP).
+.LE
+.P
+.nr aX \n(Fg+1
+The form encodings are listed in Figure \n(aX.
+.DF
+.TS
+box center;
+l l l
+lf(CW) lf(CW) l
+.
+Form name Value Class
+_
+DW_FORM_addr 0x01 address
+DW_FORM_block2 0x03 block
+DW_FORM_block4 0x04 block
+DW_FORM_data2 0x05 constant
+DW_FORM_data4 0x06 constant
+DW_FORM_data8 0x07 constant
+DW_FORM_string 0x08 string
+DW_FORM_block 0x09 block
+DW_FORM_block1 0x0a block
+DW_FORM_data1 0x0b constant
+DW_FORM_flag 0x0c flag
+DW_FORM_sdata 0x0d constant
+DW_FORM_strp 0x0e string
+DW_FORM_udata 0x0f constant
+DW_FORM_ref_addr 0x10 reference
+DW_FORM_ref1 0x11 reference
+DW_FORM_ref2 0x12 reference
+DW_FORM_ref4 0x13 reference
+DW_FORM_ref8 0x14 reference
+DW_FORM_ref_udata 0x15 reference
+DW_FORM_indirect 0x16 (see section 7.5.3)
+.TE
+.FG "Attribute form encodings"
+.DE
+.H 2 "Variable Length Data"
+.IX variable length data
+.IX LEB128
+The special constant data forms
+.Cf DW_FORM_sdata
+and
+.Cf DW_FORM_udata
+are encoded using ``Little Endian Base 128'' (LEB128)
+numbers. LEB128 is a scheme for encoding integers densely that
+exploits the assumption that most integers are small in magnitude.
+(This encoding is equally suitable whether the target machine
+architecture represents data in big-endian or little-endian order.
+It is ``little endian'' only in the sense that it avoids using space
+to represent the ``big'' end of an unsigned integer, when the big
+end is all zeroes or sign extension bits).
+.P
+.Cf DW_FORM_udata
+(unsigned LEB128) numbers are encoded as follows:
+start at the
+low order end of an unsigned integer and chop it into 7-bit chunks.
+Place each chunk into the low order 7 bits of a byte. Typically,
+several of the high order bytes will be zero; discard them. Emit the
+remaining bytes in a stream, starting with the low order byte;
+set the high order bit on each byte except the last emitted byte.
+The high bit of zero on the last byte indicates to the decoder
+that it has encountered the last byte.
+.P
+The integer zero is a special case, consisting of a single zero byte.
+.P
+.I
+.nr aX \n(Fg+1
+Figure \n(aX gives some examples of
+.Cf DW_FORM_udata
+numbers. The
+.Cf 0x80
+in each case is the high order bit of the byte, indicating that
+an additional byte follows:
+.R
+.DF
+.TS
+box center;
+l l l
+nf(CW) lf(CW) lf(CW)
+.
+Number First byte Second byte
+_
+2 2 \(em
+127 127 \(em
+128 0+0x80 1
+129 1+0x80 1
+130 2+0x80 1
+12857 57+0x80 100
+.TE
+.FG "Examples of unsigned LEB128 encodings"
+.DE
+.P
+The encoding for
+.Cf DW_FORM_sdata
+(signed, 2s complement LEB128) numbers is similar, except that the
+criterion for discarding high order bytes is not whether they are
+zero, but whether they consist entirely of sign extension bits.
+Consider the 32-bit integer
+.Cf -2 .
+The three high level bytes of the number are sign extension, thus LEB128
+would represent it as a single byte containing the low order 7 bits,
+with the high order bit cleared to indicate the end of the byte
+stream. Note that there is nothing within the LEB128 representation
+that indicates whether an encoded number is signed or unsigned.
+The decoder must know what type of number to expect.
+.P
+.I
+.nr aX \n(Fg+1
+Figure \n(aX gives some examples of
+.Cf DW_FORM_sdata
+numbers.
+.R
+.P
+.I
+Appendix 4 gives algorithms for encoding and decoding these forms.
+.R
+.DF
+.TS
+box center;
+l l l
+nf(CW) lf(CW) lf(CW)
+.
+Number First byte Second byte
+_
+2 2 \(em
+-2 0x7e \(em
+127 127+0x80 0
+-127 1+0x80 0x7f
+128 0+0x80 1
+-128 0+0x80 0x7f
+129 1+0x80 1
+-129 0x7f+0x80 0x7e
+.TE
+.FG "Examples of signed LEB128 encodings"
+.DE
+.H 2 "Location Descriptions"
+.H 3 "Location Expressions"
+.IX locations, descriptions
+.IX locations, expressions
+A location expression is stored in a block of contiguous bytes.
+The bytes form a set of operations.
+Each location operation has a 1-byte code
+that identifies that operation. Operations can be followed
+by one or more bytes of additional data. All operations in a
+location expression are concatenated from left to right.
+The encodings for the operations in a location expression
+.IX locations, expressions
+.nr aX \n(Fg+1
+.nr bX \n(Fg+2
+are described in Figures \n(aX and \n(bX.
+.DS
+.TS
+center box;
+l l l l
+lf(CW) lf(CW) l l
+.
+Operation Code No. of Operands Notes
+_
+DW_OP_addr 0x03 1 constant address (size target specific)
+DW_OP_deref 0x06 0
+DW_OP_const1u 0x08 1 1-byte constant
+DW_OP_const1s 0x09 1 1-byte constant
+DW_OP_const2u 0x0a 1 2-byte constant
+DW_OP_const2s 0x0b 1 2-byte constant
+DW_OP_const4u 0x0c 1 4-byte constant
+DW_OP_const4s 0x0d 1 4-byte constant
+DW_OP_const8u 0x0e 1 8-byte constant
+DW_OP_const8s 0x0f 1 8-byte constant
+DW_OP_constu 0x10 1 ULEB128 constant
+DW_OP_consts 0x11 1 SLEB128 constant
+DW_OP_dup 0x12 0
+DW_OP_drop 0x13 0
+DW_OP_over 0x14 0
+DW_OP_pick 0x15 1 1-byte stack index
+DW_OP_swap 0x16 0
+DW_OP_rot 0x17 0
+DW_OP_xderef 0x18 0
+DW_OP_abs 0x19 0
+DW_OP_and 0x1a 0
+DW_OP_div 0x1b 0
+DW_OP_minus 0x1c 0
+DW_OP_mod 0x1d 0
+DW_OP_mul 0x1e 0
+DW_OP_neg 0x1f 0
+DW_OP_not 0x20 0
+DW_OP_or 0x21 0
+DW_OP_plus 0x22 0
+DW_OP_plus_uconst 0x23 1 ULEB128 addend
+DW_OP_shl 0x24 0
+DW_OP_shr 0x25 0
+DW_OP_shra 0x26 0
+.TE
+.FG "Location operation encodings, part 1"
+.DE
+.DS
+.TS
+center box;
+l l l l
+lf(CW) lf(CW) l l
+.
+Operation Code No. of Operands Notes
+_
+DW_OP_xor 0x27 0
+DW_OP_skip 0x2f 1 signed 2-byte constant
+DW_OP_bra 0x28 1 signed 2-byte constant
+DW_OP_eq 0x29 0
+DW_OP_ge 0x2a 0
+DW_OP_gt 0x2b 0
+DW_OP_le 0x2c 0
+DW_OP_lt 0x2d 0
+DW_OP_ne 0x2e 0
+DW_OP_lit0 0x30 0 literals 0..31 = (DW_OP_LIT0|literal)
+DW_OP_lit1 0x31 0
+\.\.\.
+DW_OP_lit31 0x4f 0
+DW_OP_reg0 0x50 0 reg 0..31 = (DW_OP_REG0|regnum)
+DW_OP_reg1 0x51 0
+\.\.\.
+DW_OP_reg31 0x6f 0
+DW_OP_breg0 0x70 1 SLEB128 offset
+DW_OP_breg1 0x71 1 base reg 0..31 = (DW_OP_BREG0|regnum)
+\.\.\.
+DW_OP_breg31 0x8f 1
+DW_OP_regx 0x90 1 ULEB128 register
+DW_OP_fbreg 0x91 1 SLEB128 offset
+DW_OP_bregx 0x92 2 ULEB128 register followed by SLEB128 offset
+DW_OP_piece 0x93 1 ULEB128 size of piece addressed
+DW_OP_deref_size 0x94 1 1-byte size of data retrieved
+DW_OP_xderef_size 0x95 1 1-byte size of data retrieved
+DW_OP_nop 0x96 0
+DW_OP_lo_user 0xe0
+DW_OP_hi_user 0xff
+.TE
+.FG "Location operation encodings, part 2"
+.DE
+.H 3 "Location Lists"
+.IX locations, lists
+Each entry in a location list consists of two relative addresses
+followed by a 2-byte length, followed by a block of contiguous
+bytes. The length specifies the number of bytes in the block
+that follows. The two addresses are the same size as used by
+.Cf DW_FORM_addr
+on the target machine.
+.H 2 "Base Type Encodings"
+.nr aX \n(Fg+1
+.IX base types
+.IX types, base
+The values of the constants used in the
+.Cf DW_AT_encoding
+attribute are given in Figure \n(aX.
+.DF
+.TS
+box center;
+l l
+lf(CW) lf(CW)
+.
+Base type encoding name Value
+_
+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_lo_user 0x80
+DW_ATE_hi_user 0xff
+.TE
+.FG "Base type encoding values"
+.DE
+.H 2 "Accessibility Codes"
+.nr aX \n(Fg+1
+.IX accessibility
+.IX declarations, accessibility
+The encodings of the constants used in the
+.Cf DW_AT_accessibility
+attribute are given in Figure \n(aX.
+.DF
+.TS
+box center;
+l l
+lf(CW) lf(CW)
+.
+Accessibility code name Value
+_
+DW_ACCESS_public 1
+DW_ACCESS_protected 2
+DW_ACCESS_private 3
+.TE
+.FG "Accessibility encodings"
+.DE
+.H 2 "Visibility Codes"
+.nr aX \n(Fg+1
+The encodings of the constants used in the
+.Cf DW_AT_visibility
+.IX visibility
+.IX declarations, visibility
+attribute are given in Figure \n(aX.
+.DF
+.TS
+box center;
+l l
+lf(CW) lf(CW)
+.
+Visibility code name Value
+_
+DW_VIS_local 1
+DW_VIS_exported 2
+DW_VIS_qualified 3
+.TE
+.FG "Visibility encodings"
+.DE
+.H 2 "Virtuality Codes"
+.nr aX \n(Fg+1
+.IX virtuality
+The encodings of the constants used in the
+.Cf DW_AT_virtuality
+attribute are given in Figure \n(aX.
+.DF
+.TS
+box center;
+l l
+lf(CW) lf(CW)
+.
+Virtuality code name Value
+_
+DW_VIRTUALITY_none 0
+DW_VIRTUALITY_virtual 1
+DW_VIRTUALITY_pure_virtual 2
+.TE
+.FG "Virtuality encodings"
+.DE
+.H 2 "Source Languages"
+.nr aX \n(Fg+1
+.IX languages
+The encodings for source languages are given in Figure \n(aX.
+Names marked with \(dg and their associated
+values are reserved, but the languages
+they represent are not supported in DWARF Version 2.
+.DF
+.TS
+box center;
+l l
+lf(CW) lf(CW)
+.
+Language name Value
+_
+DW_LANG_C89 0x0001
+DW_LANG_C 0x0002
+DW_LANG_Ada83\(dg 0x0003
+DW_LANG_C_plus_plus 0x0004
+DW_LANG_Cobol74\(dg 0x0005
+DW_LANG_Cobol85\(dg 0x0006
+DW_LANG_Fortran77 0x0007
+DW_LANG_Fortran90 0x0008
+DW_LANG_Pascal83 0x0009
+DW_LANG_Modula2 0x000a
+DW_LANG_lo_user 0x8000
+DW_LANG_hi_user 0xffff
+.TE
+.FG "Language encodings"
+.DE
+.H 2 "Address Class Encodings"
+.IX addresses, class
+The value of the common address class encoding
+.Cf DW_ADDR_none
+is 0.
+.H 2 "Identifier Case"
+.IX identifiers, case
+The encodings of the constants used in the
+.Cf DW_AT_identifier_case
+.nr aX \n(Fg+1
+attribute are given in Figure \n(aX.
+.DF
+.TS
+box center;
+l l
+lf(CW) lf(CW)
+.
+Identifier Case Name Value
+_
+DW_ID_case_sensitive 0
+DW_ID_up_case 1
+DW_ID_down_case 2
+DW_ID_case_insensitive 3
+.TE
+.FG "Identifier case encodings"
+.DE
+.H 2 "Calling Convention Encodings"
+.IX calling conventions
+The encodings for the values of the
+.Cf DW_AT_calling_convention
+.nr aX \n(Fg+1
+attribute are given in Figure \n(aX.
+.DF
+.TS
+box center;
+l l
+lf(CW) lf(CW)
+.
+Calling Convention Name Value
+_
+DW_CC_normal 0x1
+DW_CC_program 0x2
+DW_CC_nocall 0x3
+DW_CC_lo_user 0x40
+DW_CC_hi_user 0xff
+.TE
+.FG "Calling convention encodings"
+.DE
+.H 2 "Inline Codes"
+.IX subroutines, inline
+The encodings of the constants used in the
+.Cf DW_AT_inline
+.nr aX \n(Fg+1
+attribute are given in Figure \n(aX.
+.DF
+.TS
+box center;
+l l
+lf(CW) lf(CW)
+.
+Inline Code Name Value
+_
+DW_INL_not_inlined 0
+DW_INL_inlined 1
+DW_INL_declared_not_inlined 2
+DW_INL_declared_inlined 3
+.TE
+.FG "Inline encodings"
+.DE
+.H 2 "Array Ordering"
+.IX arrays, ordering
+The encodings for the values of the order attributes of arrays
+.nr aX \n(Fg+1
+is given in Figure \n(aX.
+.DF
+.TS
+box center;
+l l
+lf(CW) lf(CW)
+.
+Ordering name Value
+_
+DW_ORD_row_major 0
+DW_ORD_col_major 1
+.TE
+.FG "Ordering encodings"
+.DE
+.H 2 "Discriminant Lists"
+.IX variants
+.IX discriminated unions
+.IX discriminants
+The descriptors used in the
+.Cf DW_AT_dicsr_list
+attribute are encoded as 1-byte constants.
+.nr aX \n(Fg+1
+The defined values are presented in Figure \n(aX.
+.DF
+.TS
+box center;
+l l
+lf(CW) lf(CW)
+.
+Descriptor Name Value
+_
+DW_DSC_label 0
+DW_DSC_range 1
+.TE
+.FG "Discriminant descriptor encodings"
+.DE
+.H 2 "Name Lookup Table"
+.IX lookup, by name
+Each set of entries in the table of global names contained in the
+.Cf .debug_pubnames
+.IX \f(CW.debug_pubnames\fP %debugap
+section begins with a header consisting of: a 4-byte length containing
+the length of the set of entries for this compilation unit, not including
+the length field itself; a 2-byte version identifier containing
+the value 2 for DWARF Version 2; a 4-byte offset into the
+.Cf .debug_info
+section; and a 4-byte length containing the size in bytes
+of the contents of the
+.Cf .debug_info
+section generated to represent this compilation unit.
+This header is followed by a series of tuples.
+Each tuple consists of a 4-byte offset
+followed by a string of non-null bytes terminated by one null byte.
+Each set is terminated by a 4-byte word containing the value 0.
+.H 2 "Address Range Table"
+.IX lookup, by address
+Each set of entries in the table of address ranges contained in the
+.Cf .debug_aranges
+.IX \f(CW.debug_aranges\fP %debugaar
+section begins with a header consisting of: a 4-byte length containing
+the length of the set of entries for this compilation unit, not including
+the length field itself; a 2-byte version identifier containing
+the value 2 for DWARF Version 2; a 4-byte offset into the
+.Cf .debug_info
+section; a 1-byte unsigned integer containing the size in bytes of an
+address (or the offset portion of an address for segmented addressing)
+.IX addresses, offset portion
+.IX addresses, size of
+on the target system; and a 1-byte unsigned integer containing the
+size in bytes of a segment descriptor on the target system.
+This header is followed by a series of tuples.
+Each tuple consists of an address and a length, each
+in the size appropriate for an address on the target architecture.
+The first tuple following the header in each set begins at
+an offset that is a multiple of the size of a single tuple
+(that is, twice the size of an address). The header is
+padded, if necessary, to the appropriate boundary.
+Each set of tuples is terminated by a 0 for the address and 0 for the length.
+.H 2 "Line Number Information"
+.IX line number information
+.IX line number information, definitions
+The sizes of the integers used in the line number and
+call frame information sections are as follows:
+.VL 15
+.LI "sbyte"
+Signed 1-byte value.
+.LI "ubyte"
+Unsigned 1-byte value.
+.LI "uhalf"
+Unsigned 2-byte value.
+.LI "sword"
+Signed 4-byte value.
+.LI "uword"
+Unsigned 4-byte value.
+.LI
+.LE
+.P
+.IX Version 2
+The version number in the statement program prologue is 2 for
+DWARF Version 2.
+The boolean values ``true'' and ``false'' used by the statement
+information program are encoded as a single byte containing the
+value 0 for ``false,'' and a non-zero value for ``true.''
+The encodings for the pre-defined standard opcodes are given
+.IX line number information, standard opcodes
+.nr aX \n(Fg+1
+in Figure \n(aX.
+.DF
+.TS
+box center;
+l l
+lf(CW) lf(CW)
+.
+Opcode Name Value
+_
+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
+.TE
+.FG "Standard Opcode Encodings"
+.DE
+The encodings for the pre-defined extended opcodes are given
+.IX line number information, extended opcodes
+.nr aX \n(Fg+1
+in Figure \n(aX.
+.DF
+.TS
+box center;
+l l
+lf(CW) lf(CW)
+.
+Opcode Name Value
+_
+DW_LNE_end_sequence 1
+DW_LNE_set_address 2
+DW_LNE_define_file 3
+.TE
+.FG "Extended Opcode Encodings"
+.DE
+.H 2 "Macro Information"
+.IX macro information
+.IX source, files
+The source line numbers and source file indices encoded in the
+macro information section are represented as unsigned LEB128 numbers
+as are the constants in an
+.Cf DW_MACINFO_vendor_ext
+entry.
+The macinfo type is encoded as a single byte. The encodings are given
+.nr aX \n(Fg+1
+in Figure \n(aX.
+.DF
+.TS
+box center;
+l l
+lf(CW) lf(CW)
+.
+Macinfo Type Name Value
+_
+DW_MACINFO_define 1
+DW_MACINFO_undef 2
+DW_MACINFO_start_file 3
+DW_MACINFO_end_file 4
+DW_MACINFO_vendor_ext 255
+.TE
+.FG "Macinfo Type Encodings"
+.DE
+.H 2 "Call Frame Information"
+.IX call frame information
+The value of the CIE id in the CIE header is
+.Cf 0xffffffff .
+The initial value of the CIE version number is 1.
+.P
+Call frame instructions are encoded in one or more bytes.
+.IX call frame information, instructions
+The primary opcode is encoded in the high order two bits of
+the first byte (that is, opcode = byte >> 6).
+An operand or extended opcode may be encoded in the low order
+6 bits. Additional operands are encoded in subsequent bytes.
+The instructions and their encodings are presented
+.nr aX \n(Fg+1
+in Figure \n(aX.
+.DS
+.TS
+center box;
+l l l l l
+lf(CW) lf(CW) l l
+lf(CW) lf(CW) l l
+lf(CW) lf(CW) l l
+lf(CW) lf(CW) lf(CW) l.
+Instruction High 2 Bits Low 6 Bits Operand 1 Operand 2
+_
+DW_CFA_advance_loc 0x1 delta
+DW_CFA_offset 0x2 register ULEB128 offset
+DW_CFA_restore 0x3 register
+DW_CFA_set_loc 0 0x01 address
+DW_CFA_advance_loc1 0 0x02 1-byte delta
+DW_CFA_advance_loc2 0 0x03 2-byte delta
+DW_CFA_advance_loc4 0 0x04 4-byte delta
+DW_CFA_offset_extended 0 0x05 ULEB128 register ULEB128 offset
+DW_CFA_restore_extended 0 0x06 ULEB128 register
+DW_CFA_undefined 0 0x07 ULEB128 register
+DW_CFA_same_value 0 0x08 ULEB128 register
+DW_CFA_register 0 0x09 ULEB128 register ULEB128 register
+DW_CFA_remember_state 0 0x0a
+DW_CFA_restore_state 0 0x0b
+DW_CFA_def_cfa 0 0x0c ULEB128 register ULEB128 offset
+DW_CFA_def_cfa_register 0 0x0d ULEB128 register
+DW_CFA_def_cfa_offset 0 0x0e ULEB128 offset
+DW_CFA_nop 0 0
+DW_CFA_lo_user 0 0x1c
+DW_CFA_hi_user 0 0x3f
+.TE
+.FG "Call frame instruction encodings"
+.DE
+.H 2 "Dependencies"
+The debugging information in this format is intended to exist in the
+.Cf .debug_abbrev ,
+.Cf .debug_aranges ,
+.Cf .debug_frame ,
+.Cf .debug_info ,
+.Cf .debug_line ,
+.Cf .debug_loc ,
+.Cf .debug_macinfo ,
+.Cf .debug_pubnames
+and
+.Cf .debug_str
+.IX \f(CW.debug_abbrev\fP %debugaab
+.IX \f(CW.debug_aranges\fP %debugaar
+.IX \f(CW.debug_frame\fP %debugaf
+.IX \f(CW.debug_info\fP %debugai
+.IX \f(CW.debug_line\fP %debugali
+.IX \f(CW.debug_loc\fP %debugalo
+.IX \f(CW.debug_macinfo\fP %debugam
+.IX \f(CW.debug_pubnames\fP %debugap
+.IX \f(CW.debug_str\fP %debugas
+sections of an object file.
+The information is not word-aligned, so the assembler must provide a
+way for the compiler to produce 2-byte and 4-byte quantities without
+alignment restrictions, and the linker must be able to
+relocate a 4-byte reference at an arbitrary alignment.
+In target architectures with 64-bit addresses, the assembler and linker
+must similarly handle 8-byte references at arbitrary alignments.
+.OP
+.H 1 "FUTURE DIRECTIONS"
+The \*(iX \*(tE is working on a specification for a set of interfaces
+for reading DWARF information, that will hide changes in the
+representation of that information from its consumers. It is
+hoped that using these interfaces will make the transition from
+DWARF Version 1 to Version 2 much simpler and will make it
+easier for a single consumer to support objects using either
+Version 1 or Version 2 DWARF.
+.P
+A draft of this specification is available for review from
+\*(iX. The \*(tE wishes to stress, however, that the specification
+is still in flux.
+.OP
+.HU "Appendix 1 -- Current Attributes by Tag Value"
+.P
+The list below enumerates the attributes that are most applicable to each type
+of debugging information entry.
+DWARF does not in general require that a given debugging information
+entry contain a particular attribute or set of attributes. Instead, a
+DWARF producer is free to generate any, all, or none of the attributes
+described in the text as being applicable to a given entry. Other
+attributes (both those defined within this document but not explicitly
+associated with the entry in question, and new, vendor-defined ones)
+may also appear in a given debugging entry.
+Therefore, the list may be
+taken as instructive, but cannot be considered definitive.
+.sp
+.sp
+.DS
+.TS
+box, tab(:) ;
+lfB lfB
+lf(CW) lf(CW) .
+TAG NAME:APPLICABLE ATTRIBUTES
+_
+DW_TAG_access_declaration:DECL\(dg
+:DW_AT_accessibility
+:DW_AT_name
+:DW_AT_sibling
+_
+DW_TAG_array_type:DECL
+:DW_AT_abstract_origin
+:DW_AT_accessibility
+:DW_AT_byte_size
+:DW_AT_declaration
+:DW_AT_name
+:DW_AT_ordering
+:DW_AT_sibling
+:DW_AT_start_scope
+:DW_AT_stride_size
+:DW_AT_type
+:DW_AT_visibility
+_
+DW_TAG_base_type:DW_AT_bit_offset
+:DW_AT_bit_size
+:DW_AT_byte_size
+:DW_AT_encoding
+:DW_AT_name
+:DW_AT_sibling
+_
+DW_TAG_catch_block:DW_AT_abstract_origin
+:DW_AT_high_pc
+:DW_AT_low_pc
+:DW_AT_segment
+:DW_AT_sibling
+.TE
+.DE
+.br
+\(dg
+.Cf DW_AT_decl_column ,
+.Cf DW_AT_decl_file ,
+.Cf DW_AT_decl_line .
+.SK
+.DS
+.B "Appendix 1 (cont'd) -- Current Attributes by Tag Value"
+
+
+
+.TS
+box, tab(:) ;
+lfB lfB
+lf(CW) lf(CW) .
+TAG NAME:APPLICABLE ATTRIBUTES
+_
+DW_TAG_class_type:DECL
+:DW_AT_abstract_origin
+:DW_AT_accessibility
+:DW_AT_byte_size
+:DW_AT_declaration
+:DW_AT_name
+:DW_AT_sibling
+:DW_AT_start_scope
+:DW_AT_visibility
+_
+DW_TAG_common_block:DECL
+:DW_AT_declaration
+:DW_AT_location
+:DW_AT_name
+:DW_AT_sibling
+:DW_AT_visibility
+_
+DW_TAG_common_inclusion:DECL
+:DW_AT_common_reference
+:DW_AT_declaration
+:DW_AT_sibling
+:DW_AT_visibility
+_
+DW_TAG_compile_unit:DW_AT_base_types
+:DW_AT_comp_dir
+:DW_AT_identifier_case
+:DW_AT_high_pc
+:DW_AT_language
+:DW_AT_low_pc
+:DW_AT_macro_info
+:DW_AT_name
+:DW_AT_producer
+:DW_AT_sibling
+:DW_AT_stmt_list
+_
+DW_TAG_const_type:DW_AT_sibling
+:DW_AT_type
+.TE
+.DE
+.br
+.SK
+.DS
+.B "Appendix 1 (cont'd) -- Current Attributes by Tag Value"
+
+
+
+.TS
+box, tab(:) ;
+lfB lfB
+lf(CW) lf(CW) .
+TAG NAME:APPLICABLE ATTRIBUTES
+_
+DW_TAG_constant:DECL
+:DW_AT_accessibility
+:DW_AT_constant_value
+:DW_AT_declaration
+:DW_AT_external
+:DW_AT_name
+:DW_AT_sibling
+:DW_AT_start_scope
+:DW_AT_type
+:DW_AT_visibility
+_
+DW_TAG_entry_point:DW_AT_address_class
+:DW_AT_low_pc
+:DW_AT_name
+:DW_AT_return_addr
+:DW_AT_segment
+:DW_AT_sibling
+:DW_AT_static_link
+:DW_AT_type
+_
+DW_TAG_enumeration_type:DECL
+:DW_AT_abstract_origin
+:DW_AT_accessibility
+:DW_AT_byte_size
+:DW_AT_declaration
+:DW_AT_name
+:DW_AT_sibling
+:DW_AT_start_scope
+:DW_AT_visibility
+_
+DW_TAG_enumerator:DECL
+:DW_AT_const_value
+:DW_AT_name
+:DW_AT_sibling
+_
+DW_TAG_file_type:DECL
+:DW_AT_abstract_origin
+:DW_AT_byte_size
+:DW_AT_name
+:DW_AT_sibling
+:DW_AT_start_scope
+:DW_AT_type
+:DW_AT_visibility
+.TE
+.DE
+.br
+.SK
+.DS
+.B "Appendix 1 (cont'd) -- Current Attributes by Tag Value"
+
+
+
+.TS
+box, tab(:) ;
+lfB lfB
+lf(CW) lf(CW) .
+TAG NAME:APPLICABLE ATTRIBUTES
+_
+DW_TAG_formal_parameter:DECL
+:DW_AT_abstract_origin
+:DW_AT_artificial
+:DW_AT_default_value
+:DW_AT_is_optional
+:DW_AT_location
+:DW_AT_name
+:DW_AT_segment
+:DW_AT_sibling
+:DW_AT_type
+:DW_AT_variable_parameter
+_
+DW_TAG_friend:DECL
+:DW_AT_abstract_origin
+:DW_AT_friend
+:DW_AT_sibling
+_
+DW_TAG_imported_declaration:DECL
+:DW_AT_accessibility
+:DW_AT_import
+:DW_AT_name
+:DW_AT_sibling
+:DW_AT_start_scope
+_
+DW_TAG_inheritance:DECL
+:DW_AT_accessibility
+:DW_AT_data_member_location
+:DW_AT_sibling
+:DW_AT_type
+:DW_AT_virtuality
+_
+DW_TAG_inlined_subroutine:DECL
+:DW_AT_abstract_origin
+:DW_AT_high_pc
+:DW_AT_low_pc
+:DW_AT_segment
+:DW_AT_sibling
+:DW_AT_return_addr
+:DW_AT_start_scope
+_
+DW_TAG_label:DW_AT_abstract_origin
+:DW_AT_low_pc
+:DW_AT_name
+:DW_AT_segment
+:DW_AT_start_scope
+:DW_AT_sibling
+.TE
+.DE
+.br
+.SK
+.DS
+.B "Appendix 1 (cont'd) -- Current Attributes by Tag Value"
+
+
+
+.TS
+box, tab(:) ;
+lfB lfB
+lf(CW) lf(CW) .
+TAG NAME:APPLICABLE ATTRIBUTES
+_
+DW_TAG_lexical_block:DW_AT_abstract_origin
+:DW_AT_high_pc
+:DW_AT_low_pc
+:DW_AT_name
+:DW_AT_segment
+:DW_AT_sibling
+_
+DW_TAG_member:DECL
+:DW_AT_accessibility
+:DW_AT_byte_size
+:DW_AT_bit_offset
+:DW_AT_bit_size
+:DW_AT_data_member_location
+:DW_AT_declaration
+:DW_AT_name
+:DW_AT_sibling
+:DW_AT_type
+:DW_AT_visibility
+_
+DW_TAG_module:DECL
+:DW_AT_accessibility
+:DW_AT_declaration
+:DW_AT_high_pc
+:DW_AT_low_pc
+:DW_AT_name
+:DW_AT_priority
+:DW_AT_segment
+:DW_AT_sibling
+:DW_AT_visibility
+_
+DW_TAG_namelist:DECL
+:DW_AT_accessibility
+:DW_AT_abstract_origin
+:DW_AT_declaration
+:DW_AT_sibling
+:DW_AT_visibility
+_
+DW_TAG_namelist_item:DECL
+:DW_AT_namelist_item
+:DW_AT_sibling
+_
+DW_TAG_packed_type:DW_AT_sibling
+:DW_AT_type
+.TE
+.DE
+.br
+.SK
+.DS
+.B "Appendix 1 (cont'd) -- Current Attributes by Tag Value"
+
+
+
+.TS
+box, tab(:) ;
+lfB lfB
+lf(CW) lf(CW) .
+TAG NAME:APPLICABLE ATTRIBUTES
+_
+DW_TAG_pointer_type:DW_AT_address_class
+:DW_AT_sibling
+:DW_AT_type
+_
+DW_TAG_ptr_to_member_type:DECL
+:DW_AT_abstract_origin
+:DW_AT_address_class
+:DW_AT_containing_type
+:DW_AT_declaration
+:DW_AT_name
+:DW_AT_sibling
+:DW_AT_type
+:DW_AT_use_location
+:DW_AT_visibility
+_
+DW_TAG_reference_type:DW_AT_address_class
+:DW_AT_sibling
+:DW_AT_type
+_
+DW_TAG_set_type:DECL
+:DW_AT_abstract_origin
+:DW_AT_accessibility
+:DW_AT_byte_size
+:DW_AT_declaration
+:DW_AT_name
+:DW_AT_start_scope
+:DW_AT_sibling
+:DW_AT_type
+:DW_AT_visibility
+_
+DW_TAG_string_type:DECL
+:DW_AT_accessibility
+:DW_AT_abstract_origin
+:DW_AT_byte_size
+:DW_AT_declaration
+:DW_AT_name
+:DW_AT_segment
+:DW_AT_sibling
+:DW_AT_start_scope
+:DW_AT_string_length
+:DW_AT_visibility
+.TE
+.DE
+.SK
+.DS
+.B "Appendix 1 (cont'd) -- Current Attributes by Tag Value"
+
+
+
+.TS
+box, tab(:) ;
+lfB lfB
+lf(CW) lf(CW) .
+TAG NAME:APPLICABLE ATTRIBUTES
+_
+DW_TAG_structure_type:DECL
+:DW_AT_abstract_origin
+:DW_AT_accessibility
+:DW_AT_byte_size
+:DW_AT_declaration
+:DW_AT_name
+:DW_AT_sibling
+:DW_AT_start_scope
+:DW_AT_visibility
+_
+DW_TAG_subprogram:DECL
+:DW_AT_abstract_origin
+:DW_AT_accessibility
+:DW_AT_address_class
+:DW_AT_artificial
+:DW_AT_calling_convention
+:DW_AT_declaration
+:DW_AT_external
+:DW_AT_frame_base
+:DW_AT_high_pc
+:DW_AT_inline
+:DW_AT_low_pc
+:DW_AT_name
+:DW_AT_prototyped
+:DW_AT_return_addr
+:DW_AT_segment
+:DW_AT_sibling
+:DW_AT_specification
+:DW_AT_start_scope
+:DW_AT_static_link
+:DW_AT_type
+:DW_AT_visibility
+:DW_AT_virtuality
+:DW_AT_vtable_elem_location
+.TE
+.DE
+.SK
+.DS
+.B "Appendix 1 (cont'd) -- Current Attributes by Tag Value"
+
+
+
+.TS
+box, tab(:) ;
+lfB lfB
+lf(CW) lf(CW) .
+TAG NAME:APPLICABLE ATTRIBUTES
+_
+DW_TAG_subrange_type:DECL
+:DW_AT_abstract_origin
+:DW_AT_accessibility
+:DW_AT_byte_size
+:DW_AT_count
+:DW_AT_declaration
+:DW_AT_lower_bound
+:DW_AT_name
+:DW_AT_sibling
+:DW_AT_type
+:DW_AT_upper_bound
+:DW_AT_visibility
+_
+DW_TAG_subroutine_type:DECL
+:DW_AT_abstract_origin
+:DW_AT_accessibility
+:DW_AT_address_class
+:DW_AT_declaration
+:DW_AT_name
+:DW_AT_prototyped
+:DW_AT_sibling
+:DW_AT_start_scope
+:DW_AT_type
+:DW_AT_visibility
+_
+DW_TAG_template_type_param:DECL
+:DW_AT_name
+:DW_AT_sibling
+:DW_AT_type
+_
+DW_TAG_template_value_param:DECL
+:DW_AT_name
+:DW_AT_const_value
+:DW_AT_sibling
+:DW_AT_type
+_
+DW_TAG_thrown_type:DECL
+:DW_AT_sibling
+:DW_AT_type
+_
+DW_TAG_try_block:DW_AT_abstract_origin
+:DW_AT_high_pc
+:DW_AT_low_pc
+:DW_AT_segment
+:DW_AT_sibling
+.TE
+.DE
+.br
+.SK
+.DS
+.B "Appendix 1 (cont'd) -- Current Attributes by Tag Value"
+
+
+
+.TS
+box, tab(:) ;
+lfB lfB
+lf(CW) lf(CW) .
+TAG NAME:APPLICABLE ATTRIBUTES
+_
+DW_TAG_typedef:DECL
+:DW_AT_abstract_origin
+:DW_AT_accessibility
+:DW_AT_declaration
+:DW_AT_name
+:DW_AT_sibling
+:DW_AT_start_scope
+:DW_AT_type
+:DW_AT_visibility
+_
+DW_TAG_union_type:DECL
+:DW_AT_abstract_origin
+:DW_AT_accessibility
+:DW_AT_byte_size
+:DW_AT_declaration
+:DW_AT_friends
+:DW_AT_name
+:DW_AT_sibling
+:DW_AT_start_scope
+:DW_AT_visibility
+_
+DW_TAG_unspecified_parameters:DECL
+:DW_AT_abstract_origin
+:DW_AT_artificial
+:DW_AT_sibling
+_
+DW_TAG_variable:DECL
+:DW_AT_accessibility
+:DW_AT_constant_value
+:DW_AT_declaration
+:DW_AT_external
+:DW_AT_location
+:DW_AT_name
+:DW_AT_segment
+:DW_AT_sibling
+:DW_AT_specification
+:DW_AT_start_scope
+:DW_AT_type
+:DW_AT_visibility
+.TE
+.DE
+.br
+.SK
+.DS
+.B "Appendix 1 (cont'd) -- Current Attributes by Tag Value"
+
+
+
+.TS
+box, tab(:) ;
+lfB lfB
+lf(CW) lf(CW) .
+TAG NAME:APPLICABLE ATTRIBUTES
+_
+DW_TAG_variant:DECL
+:DW_AT_accessibility
+:DW_AT_abstract_origin
+:DW_AT_declaration
+:DW_AT_discr_list
+:DW_AT_discr_value
+:DW_AT_sibling
+_
+DW_TAG_variant_part:DECL
+:DW_AT_accessibility
+:DW_AT_abstract_origin
+:DW_AT_declaration
+:DW_AT_discr
+:DW_AT_sibling
+:DW_AT_type
+_
+DW_TAG_volatile_type:DW_AT_sibling
+:DW_AT_type
+_
+DW_TAG_with_statement:DW_AT_accessibility
+:DW_AT_address_class
+:DW_AT_declaration
+:DW_AT_high_pc
+:DW_AT_location
+:DW_AT_low_pc
+:DW_AT_segment
+:DW_AT_sibling
+:DW_AT_type
+:DW_AT_visibility
+.TE
+.DE
+.SK
+.OP
+.HU "Appendix 2 -- Organization of Debugging Information"
+The following diagram depicts the relationship of the abbreviation
+tables contained in the
+.Cf .debug_abbrev
+section to the information contained in the
+.Cf .debug_info
+section. Values are given in symbolic form, where possible.
+.DF
+.nf
+.PS
+scale=100
+define t201 |
+[ box invis ht 154 wid 295 with .sw at 0,0
+"\f(CW\s9\&1\f1\s0" at 0,147 ljust
+"\f(CW\s9\&DW_TAG_compile_unit\f1\s0" at 0,133 ljust
+"\f(CW\s9\&DW_CHILDREN_yes\f1\s0" at 0,119 ljust
+"\f(CW\s9\&DW_AT_name DW_FORM_string\f1\s0" at 0,105 ljust
+"\f(CW\s9\&DW_AT_producer DW_FORM_string\f1\s0" at 0,91 ljust
+"\f(CW\s9\&DW_AT_compdir DW_FORM_string\f1\s0" at 0,77 ljust
+"\f(CW\s9\&DW_AT_language DW_FORM_data1\f1\s0" at 0,63 ljust
+"\f(CW\s9\&DW_AT_low_poc DW_FORM_addr\f1\s0" at 0,49 ljust
+"\f(CW\s9\&DW_AT_high_pc DW_FORM_addr\f1\s0" at 0,35 ljust
+"\f(CW\s9\&DW_AT_stmt_list DW_FORM_indirect\f1\s0" at 0,21 ljust
+"\f(CW\s9\&0 0\f1\s0" at 0,7 ljust
+] |
+
+define t103 |
+[ box invis ht 42 wid 74 with .sw at 0,0
+"\f(CW\s9\&4\f1\s0" at 0,35 ljust
+"\f(CW\s9\&\"POINTER\"\f1\s0" at 0,21 ljust
+"\f(CW\s9\&\f1\s0" at 0,7 ljust
+] |
+
+define t177 |
+[ box invis ht 28 wid 13 with .sw at 0,0
+"\f(CW\s9\&3\f1\s0" at 0,21 ljust
+"\f(CW\s9\&\f1\s0" at 0,7 ljust
+] |
+
+define t224 |
+[ box invis ht 84 wid 280 with .sw at 0,0
+"\f(CW\s9\&4\f1\s0" at 0,77 ljust
+"\f(CW\s9\&DW_TAG_typedef\f1\s0" at 0,63 ljust
+"\f(CW\s9\&DW_CHILDREN_no\f1\s0" at 0,49 ljust
+"\f(CW\s9\&DW_AT_name DW_FORM_string\f1\s0" at 0,35 ljust
+"\f(CW\s9\&DW_AT_type DW_FORM_ref4 \f1\s0" at 0,21 ljust
+"\f(CW\s9\&0 0 \f1\s0" at 0,7 ljust
+] |
+
+define t149 |
+[ box invis ht 28 wid 51 with .sw at 0,0
+"\f(CW\s9\&4\f1\s0" at 0,21 ljust
+"\f(CW\s9\&\"strp\"\f1\s0" at 0,7 ljust
+] |
+
+define t205 |
+[ box invis ht 98 wid 280 with .sw at 0,0
+"\f(CW\s9\&2\f1\s0" at 0,91 ljust
+"\f(CW\s9\&DW_TAG_base_type\f1\s0" at 0,77 ljust
+"\f(CW\s9\&DW_CHILDREN_no\f1\s0" at 0,63 ljust
+"\f(CW\s9\&DW_AT_name DW_FORM_string\f1\s0" at 0,49 ljust
+"\f(CW\s9\&DW_AT_encoding DW_FORM_data1\f1\s0" at 0,35 ljust
+"\f(CW\s9\&DW_AT_byte_size DW_FORM_data1\f1\s0" at 0,21 ljust
+"\f(CW\s9\&0 0\f1\s0" at 0,7 ljust
+] |
+
+define t126 |
+[ box invis ht 126 wid 257 with .sw at 0,0
+"\f(CW\s9\&\"myfile.c\"\f1\s0" at 0,119 ljust
+"\f(CW\s9\&\"Best Compiler Corp: Version 1.3\"\f1\s0" at 0,105 ljust
+"\f(CW\s9\&\"mymachine:/home/mydir/src:\"\f1\s0" at 0,91 ljust
+"\f(CW\s9\&DW_LANG_C89\f1\s0" at 0,77 ljust
+"\f(CW\s9\&0x0\f1\s0" at 0,63 ljust
+"\f(CW\s9\&0x55\f1\s0" at 0,49 ljust
+"\f(CW\s9\&DW_FORM_data4\f1\s0" at 0,35 ljust
+"\f(CW\s9\&0x0\f1\s0" at 0,21 ljust
+"\f(CW\s9\&\f1\s0" at 0,7 ljust
+] |
+
+define t219 |
+[ box invis ht 70 wid 260 with .sw at 0,0
+"\f(CW\s9\&3\f1\s0" at 0,63 ljust
+"\f(CW\s9\&DW_TAG_pointer_type\f1\s0" at 0,49 ljust
+"\f(CW\s9\&DW_CHILDREN_no\f1\s0" at 0,35 ljust
+"\f(CW\s9\&DW_AT_type DW_FORM_ref4\f1\s0" at 0,21 ljust
+"\f(CW\s9\&0 0\f1\s0" at 0,7 ljust
+] |
+
+define t109 |
+[ box invis ht 42 wid 165 with .sw at 0,0
+"\f(CW\s9\&\"char\"\f1\s0" at 0,35 ljust
+"\f(CW\s9\&DW_ATE_unsigned_char\f1\s0" at 0,21 ljust
+"\f(CW\s9\&1\f1\s0" at 0,7 ljust
+] |
+
+box invis ht 704 wid 680 with .sw at 0,0
+t201 with .nw at 376,657
+box ht 520 wid 320 with .nw at 360,672
+box ht 208 wid 280 with .nw at 24,208
+t103 with .nw at 40,353
+t177 with .nw at 40,398
+line from 360,176 to 680,176
+line from 360,280 to 680,280
+line from 360,368 to 680,368
+line from 360,488 to 680,488
+t224 with .nw at 376,270
+"\f(CW\s9\&0\f1\s0" at 376,164 ljust
+"\f(CW\s9\&0\f1\s0" at 40,289 ljust
+"\fI\s9\&e2\f1\s0" at 40,317 ljust
+"\fI\s9\&e2:\f1\s0" at 0,389 ljust
+"\f(CW\s9\&2\f1\s0" at 44,176 ljust
+line from 24,128 to 304,128
+"\f(CW\s9\&...\f1\s0" at 44,113 ljust
+t149 with .nw at 44,88
+"\fI\s9\&e2\f1\s0" at 44,49 ljust
+"\f(CW\s9\&...\f1\s0" at 44,17 ljust
+box ht 416 wid 280 with .nw at 24,688
+"\fI\s9\&length\f1\s0" at 44,192 ljust
+"\f(CW\s9\&4\f1\s0" at 48,140
+"\fI\s9\&a1 (abbreviation table offset)\f1\s0" at 44,160 ljust
+"\f(CW\s9\&4\f1\s0" at 44,624
+"\fI\s9\&a1 (abbreviation table offset)\f1\s0" at 40,640 ljust
+t205 with .nw at 376,477
+"\fI\s9\&a1:\f1\s0" at 348,657 rjust
+"\fI\s9\&length\f1\s0" at 40,672 ljust
+"\fR\s10\&Abbreviation Table - .debug_abbrev\f1\s0" at 384,678 ljust
+"\fR\s10\&Compilation Unit 1 - .debug_info\f1\s0" at 68,694 ljust
+"\fR\s10\&Compilation Unit 2 - .debug_info\f1\s0" at 64,218 ljust
+"\f(CW\s9\&2\f1\s0" at 44,656
+"\f(CW\s9\&1\f1\s0" at 44,605
+t126 with .nw at 36,599
+line from 24,616 to 304,616
+"\f(CW\s9\&2\f1\s0" at 40,461 ljust
+t219 with .nw at 376,359
+line from 24,96 to 304,96
+line from 24,32 to 304,32
+t109 with .nw at 40,449
+"\fI\s9\&e1\f1\s0" at 40,373 ljust
+"\fI\s9\&e1:\f1\s0" at 0,461 ljust
+line from 24,480 to 304,480
+line from 24,400 to 304,400
+line from 24,360 to 304,360
+line from 24,304 to 304,304
+.PE
+.fi
+.DE
+.SK
+.OP
+.HU "Appendix 3 -- Statement Program Examples"
+.P
+Consider this simple source file and the resulting machine code for
+the Intel 8086 processor:
+.DS
+.S -2
+.TS
+;
+lf(CW) lf(CW) s
+lf(CW) lf(CW) s
+lf(CW) lf(CW) lf(CW)
+lf(CW) lf(CW) lf(CW)
+lf(CW) lf(CW) s
+lf(CW) lf(CW) s
+lf(CW) lf(CW) lf(CW)
+lf(CW) lf(CW) lf(CW)
+lf(CW) lf(CW) lf(CW)
+lf(CW) lf(CW) lf(CW)
+lf(CW) lf(CW) s
+lf(CW) lf(CW) lf(CW)
+lf(CW) lf(CW) lf(CW)
+lf(CW) lf(CW) lf(CW)
+lf(CW) lf(CW) lf(CW)
+lf(CW) lf(CW) s
+lf(CW) lf(CW) lf(CW)
+lf(CW) lf(CW) lf(CW)
+lf(CW) lf(CW) s
+lf(CW) lf(CW) lf(CW).
+1: int
+2: main()
+ 0x239: push pb
+ 0x23a: mov bp,sp
+3: {
+4: printf("Omit needless words\en");
+ 0x23c: mov ax,0xaa
+ 0x23f: push ax
+ 0x240: call _printf
+ 0x243: pop cx
+5: exit(0);
+ 0x244: xor ax,ax
+ 0x246: push ax
+ 0x247: call _exit
+ 0x24a: pop cx
+6: }
+ 0x24b: pop bp
+ 0x24c: ret
+7:
+ 0x24d:
+.TE
+.S +2
+.DE
+.P
+If the statement program prologue specifies the following:
+.DS
+.S -2
+.TS
+;
+lf(CW) lf(CW).
+minimum_instruction_length 1
+opcode_base 10
+line_base 1
+line_range 15
+.TE
+.S +2
+.DE
+.P
+Then one encoding of the statement program would occupy 12 bytes
+(the opcode \f(CWSPECIAL(\fIm\fP, \fIn\fP)\fR indicates the special
+opcode generated for a line increment of \fIm\fP and an address increment
+of \fIn\fP):
+.DS
+.S -2
+.TS
+;
+l l l
+lf(CW) lf(CW) lf(CW).
+Opcode Operand Byte Stream
+_
+DW_LNS_advance_pc LEB128(0x239) 0x2, 0xb9, 0x04
+SPECIAL(2, 0) 0xb
+SPECIAL(2, 3) 0x38
+SPECIAL(1, 8) 0x82
+SPECIAL(1, 7) 0x73
+DW_LNS_advance_pc LEB128(2) 0x2, 0x2
+DW_LNE_end_sequence 0x0, 0x1, 0x1
+.TE
+.S +2
+.DE
+.P
+An alternate encoding of the same program using standard opcodes to
+advance the program counter would occupy 22 bytes:
+.DS
+.S -2
+.TS
+;
+l l l
+lf(CW) lf(CW) lf(CW).
+Opcode Operand Byte Stream
+_
+DW_LNS_fixed_advance_pc 0x239 0x9, 0x39, 0x2
+SPECIAL(2, 0) 0xb
+DW_LNS_fixed_advance_pc 0x3 0x9, 0x3, 0x0
+SPECIAL(2, 0) 0xb
+DW_LNS_fixed_advance_pc 0x8 0x9, 0x8, 0x0
+SPECIAL(1, 0) 0xa
+DW_LNS_fixed_advance_pc 0x7 0x9, 0x7, 0x0
+SPECIAL(1, 0) 0xa
+DW_LNS_fixed_advance_pc 0x2 0x9, 0x2, 0x0
+DW_LNE_end_sequence 0x0, 0x1, 0x1
+.TE
+.S +2
+.DE
+.SK
+.OP
+.HU "Appendix 4 -- Encoding and decoding variable length data"
+.ta .5i +.5i +.5i +.5i +.5i +.5i +.5i +.5i
+.P
+Here are algorithms expressed in a C-like pseudo-code to encode and decode
+signed and unsigned numbers in LEB128:
+.P
+\fBEncode an unsigned integer:\fP
+.br
+.DS
+.S -2
+\f(CWdo
+{
+ byte = low order 7 bits of value;
+ value >>= 7;
+ if (value != 0) /* more bytes to come */
+ set high order bit of byte;
+ emit byte;
+} while (value != 0);\fP
+.S +2
+.DE
+.P
+\fBEncode a signed integer:\fP
+.br
+.DS
+.S -2
+\f(CWmore = 1;
+negative = (value < 0);
+size = no. of bits in signed integer;
+while(more)
+{
+ byte = low order 7 bits of value;
+ value >>= 7;
+ /* the following is unnecessary if the implementation of >>=
+ * uses an arithmetic rather than logical shift for a signed
+ * left operand
+ */
+ if (negative)
+ /* sign extend */
+ value |= - (1 << (size - 7));
+ /* sign bit of byte is 2nd high order bit (0x40) */
+ if ((value == 0 && sign bit of byte is clear) ||
+ (value == -1 && sign bit of byte is set))
+ more = 0;
+ else
+ set high order bit of byte;
+ emit byte;
+}\fP
+.S +2
+.DE
+.SK
+.ta .5i +.5i +.5i +.5i +.5i +.5i +.5i +.5i
+.P
+\fBDecode unsigned LEB128 number:\fP
+.br
+.DS
+.S -2
+\f(CWresult = 0;
+shift = 0;
+while(true)
+{
+ byte = next byte in input;
+ result |= (low order 7 bits of byte << shift);
+ if (high order bit of byte == 0)
+ break;
+ shift += 7;
+}\fP
+.S +2
+.DE
+.P
+\fBDecode signed LEB128 number:\fP
+.br
+.DS
+.S -2
+\f(CWresult = 0;
+shift = 0;
+size = no. of bits in signed integer;
+while(true)
+{
+ byte = next byte in input;
+ result |= (low order 7 bits of byte << shift);
+ shift += 7;
+ /* sign bit of byte is 2nd high order bit (0x40) */
+ if (high order bit of byte == 0)
+ break;
+}
+if ((shift < size) && (sign bit of byte is set))
+ /* sign extend */
+ result |= - (1 << shift);\fP
+.S +2
+.DE
+.SK
+.OP
+.HU "Appendix 5 -- Call Frame Information Examples"
+The following example uses a hypothetical RISC machine in the style of
+the Motorola 88000.
+.BL
+.LI
+Memory is byte addressed.
+.LI
+Instructions are all 4-bytes each and word aligned.
+.LI
+Instruction operands are typically of the form:
+.br
+.DS
+ <destination reg> <source reg> <constant>
+.DE
+.LI
+The address for the load and store instructions is computed by
+adding the contents of the source register with the constant.
+.LI
+There are 8 4-byte registers:
+.br
+.DS
+ R0 always 0
+ R1 holds return address on call
+ R2-R3 temp registers (not preserved on call)
+ R4-R6 preserved on call
+ R7 stack pointer.
+.DE
+.LI
+The stack grows in the negative direction.
+.LE
+.P
+The following are two code fragments from a subroutine
+called \f(CWfoo\fP that
+uses a frame pointer (in addition to the stack pointer.) The first
+column values are byte addresses.
+.DS
+.S -2
+.TS
+;
+lf(CW) lf(CW) s s
+lf(CW) lf(CW) lf(CW) lf(CW)
+lf(CW) lf(CW) lf(CW) lf(CW)
+lf(CW) lf(CW) lf(CW) lf(CW)
+lf(CW) lf(CW) lf(CW) lf(CW)
+lf(CW) lf(CW) lf(CW) lf(CW)
+lf(CW) lf(CW) s s
+lf(CW) lf(CW) s s
+lf(CW) lf(CW) s s
+lf(CW) lf(CW) lf(CW) lf(CW).
+ ;; start prologue
+foo sub R7, R7, <fsize> ; Allocate frame
+foo+4 store R1, R7, (<fsize>-4) ; Save the return address
+foo+8 store R6, R7, (<fsize>-8) ; Save R6
+foo+12 add R6, R7, 0 ; R6 is now the Frame ptr
+foo+16 store R4, R6, (<fsize>-12) ; Save a preserve reg.
+ ;; This subroutine does not change R5
+ ...
+ ;; Start epilogue (R7 has been returned to entry value)
+foo+64 load R4, R6, (<fsize>-12) ; Restore R4
+foo+68 load R6, R7, (<fsize>-8) ; Restore R6
+foo+72 load R1, R7, (<fsize>-4) ; Restore return address
+foo+76 add R7, R7, <fsize> ; Deallocate frame
+foo+80 jump R ; Return
+foo+84
+.TE
+.S +2
+.DE
+.SK
+The table for the \f(CWfoo\fP subroutine is as follows.
+It is followed by the
+corresponding fragments from the
+.Cf .debug_frame
+section.
+.DS
+.S -2
+.TS
+tab(|);
+lf(CW) lf(CW) lf(CW) lf(CW) lf(CW) lf(CW) lf(CW) lf(CW) lf(CW) lf(CW) lf(CW).
+Loc|CFA|R0|R1|R2|R3|R4|R5|R6|R7|R8
+foo|[R7]+0|s|u|u|u|s|s|s|s|r1
+foo+4|[R7]+fsize|s|u|u|u|s|s|s|s|r1
+foo+8|[R7]+fsize|s|u|u|u|s|s|s|s|c4
+foo+12|[R7]+fsize|s|u|u|u|s|s|c8|s|c4
+foo+16|[R6]+fsize|s|u|u|u|s|s|c8|s|c4
+foo+20|[R6]+fsize|s|u|u|u|c12|s|c8|s|c4
+...
+foo+64|[R6]+fsize|s|u|u|u|c12|s|c8|s|c4
+foo+68|[R6]+fsize|s|u|u|u|s|s|c8|s|c4
+foo+72|[R7]+fsize|s|u|u|u|s|s|s|s|c4
+foo+76|[R7]+fsize|s|u|u|u|s|s|s|s|r1
+foo+80|[R7]+0|s|u|u|u|s|s|s|s|r1
+.TE
+.TS
+;
+l s
+l l.
+notes:
+1. R8 is the return address
+2. s = same_value rule
+3. u = undefined rule
+4. rN = register(N) rule
+5. cN = offset(N) rule
+.sp
+.sp
+.TE
+.S +2
+.DE
+.P
+Common Information Entry (CIE):
+.DS
+.S -2
+.TS
+;
+lf(CW) lf(CW) lf(CW).
+cie 32 ; length
+cie+4 0xffffffff ; CIE_id
+cie+8 1 ; version
+cie+9 0 ; augmentation
+cie+10 4 ; code_alignment_factor
+cie+11 4 ; data_alignment_factor
+cie+12 8 ; R8 is the return addr.
+cie+13 DW_CFA_def_cfa (7, 0) ; CFA = [R7]+0
+cie+16 DW_CFA_same_value (0) ; R0 not modified (=0)
+cie+18 DW_CFA_undefined (1) ; R1 scratch
+cie+20 DW_CFA_undefined (2) ; R2 scratch
+cie+22 DW_CFA_undefined (3) ; R3 scratch
+cie+24 DW_CFA_same_value (4) ; R4 preserve
+cie+26 DW_CFA_same_value (5) ; R5 preserve
+cie+28 DW_CFA_same_value (6) ; R6 preserve
+cie+30 DW_CFA_same_value (7) ; R7 preserve
+cie+32 DW_CFA_register (8, 1) ; R8 is in R1
+cie+35 DW_CFA_nop ; padding
+cie+36
+.TE
+.S +2
+.DE
+.SK
+.P
+Frame Description Entry (FDE):
+.DS
+.S -2
+.TS
+;
+lf(CW) lf(CW) lf(CW).
+fde 40 ; length
+fde+4 cie ; CIE_ptr
+fde+8 foo ; initial_location
+fde+12 84 ; address_range
+fde+16 DW_CFA_advance_loc(1) ; instructions
+fde+17 DW_CFA_def_cfa_offset(<fsize>/4) ; assuming <fsize> < 512
+fde+19 DW_CFA_advance_loc(1)
+fde+20 DW_CFA_offset(8,1)
+fde+22 DW_CFA_advance_loc(1)
+fde+23 DW_CFA_offset(6,2)
+fde+25 DW_CFA_advance_loc(1)
+fde+26 DW_CFA_def_cfa_register(6)
+fde+28 DW_CFA_advance_loc(1)
+fde+29 DW_CFA_offset(4,3)
+fde+31 DW_CFA_advance_loc(11)
+fde+32 DW_CFA_restore(4)
+fde+33 DW_CFA_advance_loc(1)
+fde+34 DW_CFA_restore(6)
+fde+35 DW_CFA_def_cfa_register(7)
+fde+37 DW_CFA_advance_loc(1)
+fde+38 DW_CFA_restore(8)
+fde+39 DW_CFA_advance_loc(1)
+fde+40 DW_CFA_def_cfa_offset(0)
+fde+42 DW_CFA_nop ; padding
+fde+43 DW_CFA_nop ; padding
+fde+44
+.TE
+.S +2
+.DE
+.S +1
+
+'\"
+'\" Table of Contents stuff
+'\"
+.de TP
+.sp 4
+..
+.VM
+.de TY
+.ce 1
+Table of Contents
+.sp
+..
+.nr Lf 1
+.ds Lf List of Figures
+.SK
+.TC 1 1 7 0
diff --git a/libdwarf/dwarf.v2.pdf b/libdwarf/dwarf.v2.pdf
new file mode 100644
index 0000000..58358bc
--- /dev/null
+++ b/libdwarf/dwarf.v2.pdf
Binary files differ
diff --git a/libdwarf/dwarf_abbrev.c b/libdwarf/dwarf_abbrev.c
new file mode 100644
index 0000000..a15bb80
--- /dev/null
+++ b/libdwarf/dwarf_abbrev.c
@@ -0,0 +1,289 @@
+/*
+
+ Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the above address.
+*/
+
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include "dwarf_abbrev.h"
+
+int
+dwarf_get_abbrev(Dwarf_Debug dbg,
+ Dwarf_Unsigned offset,
+ Dwarf_Abbrev * returned_abbrev,
+ Dwarf_Unsigned * length,
+ Dwarf_Unsigned * abbr_count, Dwarf_Error * error)
+{
+ Dwarf_Small *abbrev_ptr = 0;
+ Dwarf_Small *abbrev_section_end = 0;
+ Dwarf_Half attr = 0;
+ Dwarf_Half attr_form = 0;
+ Dwarf_Abbrev ret_abbrev = 0;
+ Dwarf_Unsigned labbr_count = 0;
+ Dwarf_Unsigned utmp = 0;
+
+
+ if (dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+ if (dbg->de_debug_abbrev.dss_data == 0) {
+ /* Loads abbrev section (and .debug_info as we do those
+ together). */
+ int res = _dwarf_load_debug_info(dbg, error);
+
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ }
+
+ if (offset >= dbg->de_debug_abbrev.dss_size) {
+ return (DW_DLV_NO_ENTRY);
+ }
+
+
+ ret_abbrev = (Dwarf_Abbrev) _dwarf_get_alloc(dbg, DW_DLA_ABBREV, 1);
+ if (ret_abbrev == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ ret_abbrev->ab_dbg = dbg;
+ if (returned_abbrev == 0 || abbr_count == 0) {
+ dwarf_dealloc(dbg, ret_abbrev, DW_DLA_ABBREV);
+ _dwarf_error(dbg, error, DW_DLE_DWARF_ABBREV_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+
+ *abbr_count = 0;
+ if (length != NULL)
+ *length = 1;
+
+ abbrev_ptr = dbg->de_debug_abbrev.dss_data + offset;
+ abbrev_section_end =
+ dbg->de_debug_abbrev.dss_data + dbg->de_debug_abbrev.dss_size;
+
+ DECODE_LEB128_UWORD(abbrev_ptr, utmp);
+ ret_abbrev->ab_code = (Dwarf_Word) utmp;
+ if (ret_abbrev->ab_code == 0) {
+ *returned_abbrev = ret_abbrev;
+ *abbr_count = 0;
+ if (length) {
+ *length = 1;
+ }
+ return (DW_DLV_OK);
+ }
+
+ DECODE_LEB128_UWORD(abbrev_ptr, utmp);
+ ret_abbrev->ab_tag = utmp;
+ ret_abbrev->ab_has_child = *(abbrev_ptr++);
+ ret_abbrev->ab_abbrev_ptr = abbrev_ptr;
+
+ do {
+ Dwarf_Unsigned utmp2;
+
+ DECODE_LEB128_UWORD(abbrev_ptr, utmp2);
+ attr = (Dwarf_Half) utmp2;
+ DECODE_LEB128_UWORD(abbrev_ptr, utmp2);
+ attr_form = (Dwarf_Half) utmp2;
+
+ if (attr != 0)
+ (labbr_count)++;
+
+ } while (abbrev_ptr < abbrev_section_end &&
+ (attr != 0 || attr_form != 0));
+
+ if (abbrev_ptr > abbrev_section_end) {
+ dwarf_dealloc(dbg, ret_abbrev, DW_DLA_ABBREV);
+ _dwarf_error(dbg, error, DW_DLE_ABBREV_DECODE_ERROR);
+ return (DW_DLV_ERROR);
+ }
+
+ if (length != NULL)
+ *length = abbrev_ptr - dbg->de_debug_abbrev.dss_data - offset;
+
+ *returned_abbrev = ret_abbrev;
+ *abbr_count = labbr_count;
+ return (DW_DLV_OK);
+}
+
+int
+dwarf_get_abbrev_code(Dwarf_Abbrev abbrev,
+ Dwarf_Unsigned * returned_code,
+ Dwarf_Error * error)
+{
+ if (abbrev == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DWARF_ABBREV_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ *returned_code = abbrev->ab_code;
+ return (DW_DLV_OK);
+}
+
+/* DWARF defines DW_TAG_hi_user as 0xffff so no tag should be
+ over 16 bits. */
+int
+dwarf_get_abbrev_tag(Dwarf_Abbrev abbrev,
+ Dwarf_Half * returned_tag, Dwarf_Error * error)
+{
+ if (abbrev == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DWARF_ABBREV_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ *returned_tag = abbrev->ab_tag;
+ return (DW_DLV_OK);
+}
+
+
+int
+dwarf_get_abbrev_children_flag(Dwarf_Abbrev abbrev,
+ Dwarf_Signed * returned_flag,
+ Dwarf_Error * error)
+{
+ if (abbrev == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DWARF_ABBREV_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ *returned_flag = abbrev->ab_has_child;
+ return (DW_DLV_OK);
+}
+
+
+int
+dwarf_get_abbrev_entry(Dwarf_Abbrev abbrev,
+ Dwarf_Signed index,
+ Dwarf_Half * returned_attr_num,
+ Dwarf_Signed * form,
+ Dwarf_Off * offset, Dwarf_Error * error)
+{
+ Dwarf_Byte_Ptr abbrev_ptr = 0;
+ Dwarf_Byte_Ptr abbrev_end = 0;
+ Dwarf_Byte_Ptr mark_abbrev_ptr = 0;
+ Dwarf_Half attr = 0;
+ Dwarf_Half attr_form = 0;
+
+ if (index < 0)
+ return (DW_DLV_NO_ENTRY);
+
+ if (abbrev == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DWARF_ABBREV_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ if (abbrev->ab_code == 0) {
+ return (DW_DLV_NO_ENTRY);
+ }
+
+ if (abbrev->ab_dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ abbrev_ptr = abbrev->ab_abbrev_ptr;
+ abbrev_end =
+ abbrev->ab_dbg->de_debug_abbrev.dss_data +
+ abbrev->ab_dbg->de_debug_abbrev.dss_size;
+
+ for (attr = 1, attr_form = 1;
+ index >= 0 && abbrev_ptr < abbrev_end && (attr != 0 ||
+ attr_form != 0);
+ index--) {
+ Dwarf_Unsigned utmp4;
+
+ mark_abbrev_ptr = abbrev_ptr;
+ DECODE_LEB128_UWORD(abbrev_ptr, utmp4);
+ attr = (Dwarf_Half) utmp4;
+ DECODE_LEB128_UWORD(abbrev_ptr, utmp4);
+ attr_form = (Dwarf_Half) utmp4;
+ }
+
+ if (abbrev_ptr >= abbrev_end) {
+ _dwarf_error(abbrev->ab_dbg, error, DW_DLE_ABBREV_DECODE_ERROR);
+ return (DW_DLV_ERROR);
+ }
+
+ if (index >= 0) {
+ return (DW_DLV_NO_ENTRY);
+ }
+
+ if (form != NULL)
+ *form = attr_form;
+ if (offset != NULL)
+ *offset = mark_abbrev_ptr - abbrev->ab_dbg->de_debug_abbrev.dss_data;
+
+ *returned_attr_num = (attr);
+ return DW_DLV_OK;
+}
+
+/* This function is not entirely safe to call.
+ The problem is that the DWARF[234] specification does not insist
+ that bytes in .debug_abbrev that are not referenced by .debug_info
+ or .debug_types need to be initialized to anything specific.
+ Any garbage bytes may cause trouble. Not all compilers/linkers
+ leave unreferenced garbage bytes in .debug_abbrev, so this may
+ work for most objects. */
+int
+dwarf_get_abbrev_count(Dwarf_Debug dbg)
+{
+ Dwarf_Abbrev ab;
+ Dwarf_Unsigned offset = 0;
+ Dwarf_Unsigned length = 0;
+ Dwarf_Unsigned attr_count = 0;
+ Dwarf_Unsigned abbrev_count = 0;
+ int abres = DW_DLV_OK;
+ Dwarf_Error err;
+
+ while ((abres = dwarf_get_abbrev(dbg, offset, &ab,
+ &length, &attr_count,
+ &err)) == DW_DLV_OK) {
+
+ ++abbrev_count;
+ offset += length;
+ dwarf_dealloc(dbg, ab, DW_DLA_ABBREV);
+ }
+ return abbrev_count;
+}
+
diff --git a/libdwarf/dwarf_abbrev.h b/libdwarf/dwarf_abbrev.h
new file mode 100644
index 0000000..80adf1c
--- /dev/null
+++ b/libdwarf/dwarf_abbrev.h
@@ -0,0 +1,54 @@
+/*
+ Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2008-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+
+/* In a given CU, one of these is (eventually) set up
+ for every abbreviation we need to find (and for all.
+ those ealier in the abbreviations for that CU).
+ So we don't want elements needlessly big.
+*/
+struct Dwarf_Abbrev_s {
+ /* No TAG should exceed DW_TAG_hi_user, 0xffff, but
+ we do allow a larger value here. */
+ Dwarf_Word ab_tag;
+ /* Abbreviations are numbered (normally sequentially from
+ 1 and so 16 bits is not enough! */
+ Dwarf_Word ab_code;
+ Dwarf_Small ab_has_child;
+ Dwarf_Byte_Ptr ab_abbrev_ptr;
+ Dwarf_Debug ab_dbg;
+};
diff --git a/libdwarf/dwarf_addr_finder.c b/libdwarf/dwarf_addr_finder.c
new file mode 100644
index 0000000..303ca45
--- /dev/null
+++ b/libdwarf/dwarf_addr_finder.c
@@ -0,0 +1,680 @@
+/*
+
+ Copyright (C) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+/* This code used by SGI-IRIX rqs processing, not needed by
+ any other system or application.
+ The 'We need' and 'FIX' here are left in for historical
+ interest, the code is not really used in the public libdwarf
+ or applications.
+*/
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#ifdef HAVE_ELF_H
+#include <elf.h>
+#endif
+#include <dwarf.h>
+#include <libdwarf.h>
+#include "dwarf_base_types.h"
+#include "dwarf_alloc.h"
+#include "dwarf_opaque.h"
+#include "dwarf_arange.h"
+#include "dwarf_line.h"
+#include "dwarf_frame.h"
+#include <cmplrs/dwarf_addr_finder.h>
+#include "dwarf_error.h"
+
+typedef unsigned long long ull;
+
+static int do_this_die_and_dealloc(Dwarf_Debug dbg, Dwarf_Die die,
+ int *errval);
+static int handle_debug_info(Dwarf_Debug dbg, int *errval);
+static int handle_debug_frame(Dwarf_Debug dbg,
+ Dwarf_addr_callback_func cb_func, int *errval);
+static int handle_debug_aranges(Dwarf_Debug dbg,
+ Dwarf_addr_callback_func cb_func, int *errval);
+static int handle_debug_line(Dwarf_Debug dbg,
+ Dwarf_Die cu_die, Dwarf_addr_callback_func cb_func, int *errval);
+static int handle_debug_loc(void);
+
+
+/* A static variable is not thread-safe, but this is only
+ used by SGI-internal software which is single-threaded
+ so the static variable is safe.
+*/
+static Dwarf_addr_callback_func send_addr_note;
+
+/* A function which should probably not be used outside
+ of SGI. Intended to be used by executable and
+ shared-library post-processor software.
+*/
+int
+_dwarf_addr_finder(dwarf_elf_handle elf_file_ptr,
+ Dwarf_addr_callback_func cb_func, int *dwerr)
+{
+
+ Dwarf_Error err = 0;
+ Dwarf_Debug dbg = 0;
+ int res = 0;
+ int errval = 0;
+ int sections_found = 0;
+
+ res = dwarf_elf_init(elf_file_ptr, DW_DLC_READ, /* errhand */ 0,
+ /* errarg */ 0, &dbg, &err);
+ if (res == DW_DLV_ERROR) {
+ int errv = (int) dwarf_errno(err);
+ return errv;
+ }
+ if (res == DW_DLV_NO_ENTRY) {
+ return res;
+ }
+ send_addr_note = cb_func;
+ res = handle_debug_info(dbg, &errval);
+ switch (res) {
+ case DW_DLV_OK:
+ ++sections_found;
+ break;
+ case DW_DLV_NO_ENTRY:
+
+ break;
+ default:
+ case DW_DLV_ERROR:
+ dwarf_finish(dbg, &err);
+ *dwerr = errval;
+ return res;
+ }
+
+ res = handle_debug_aranges(dbg, cb_func, &errval);
+ switch (res) {
+ case DW_DLV_OK:
+ ++sections_found;
+ break;
+ case DW_DLV_NO_ENTRY:
+ break;
+ default:
+ case DW_DLV_ERROR:
+ dwarf_finish(dbg, &err);
+ *dwerr = errval;
+ return res;
+ }
+ res = handle_debug_frame(dbg, cb_func, &errval);
+ switch (res) {
+ case DW_DLV_OK:
+ ++sections_found;
+ break;
+ case DW_DLV_NO_ENTRY:
+ break;
+ default:
+ case DW_DLV_ERROR:
+ dwarf_finish(dbg, &err);
+ *dwerr = errval;
+ return res;
+ }
+
+ res = handle_debug_loc(); /* does nothing */
+ switch (res) {
+ case DW_DLV_OK:
+ ++sections_found;
+ break;
+ case DW_DLV_NO_ENTRY:
+ break;
+ default:
+ case DW_DLV_ERROR:
+ /* IMPOSSIBLE : handle_debug_loc cannot return this */
+ dwarf_finish(dbg, &err);
+ *dwerr = errval;
+ return res;
+ }
+
+
+
+ *dwerr = 0;
+ res = dwarf_finish(dbg, &err);
+ if (res == DW_DLV_ERROR) {
+ *dwerr = (int) dwarf_errno(err);
+ return DW_DLV_ERROR;
+ }
+ if (sections_found == 0) {
+ return DW_DLV_NO_ENTRY;
+ }
+ return DW_DLV_OK;
+
+}
+
+/* Return DW_DLV_OK, ERROR, or NO_ENTRY. */
+static int
+handle_debug_info(Dwarf_Debug dbg, int *errval)
+{
+ Dwarf_Unsigned nxtoff = 1;
+ Dwarf_Unsigned hdr_length;
+ Dwarf_Half version_stamp;
+ Dwarf_Unsigned abbrev_offset;
+ Dwarf_Half addr_size;
+ Dwarf_Error err;
+ int terminate_now = 0;
+ int res = 0;
+ Dwarf_Die sibdie;
+ int sibres;
+ int nres = DW_DLV_OK;
+
+
+ for (nres = dwarf_next_cu_header(dbg, &hdr_length, &version_stamp,
+ &abbrev_offset,
+ &addr_size, &nxtoff, &err);
+ terminate_now == 0 && nres == DW_DLV_OK;
+ nres = dwarf_next_cu_header(dbg, &hdr_length, &version_stamp,
+ &abbrev_offset,
+ &addr_size, &nxtoff, &err)) {
+
+ Dwarf_Die curdie = 0;
+
+ /* Try to get the compilation unit die */
+ sibres = dwarf_siblingof(dbg, curdie, &sibdie, &err);
+ if (sibres == DW_DLV_OK) {
+ res = do_this_die_and_dealloc(dbg, sibdie, errval);
+ switch (res) {
+ case DW_DLV_OK:
+ break;
+ case DW_DLV_NO_ENTRY:
+ break;
+ default:
+ case DW_DLV_ERROR:
+ return DW_DLV_ERROR;
+ }
+ } else if (sibres == DW_DLV_ERROR) {
+ *errval = (int) dwarf_errno(err);
+ return DW_DLV_ERROR;
+ } else {
+ /* NO ENTRY! */
+ /* impossible? */
+ }
+
+ }
+ if (nres == DW_DLV_ERROR) {
+ int localerr = (int) dwarf_errno(err);
+
+ *errval = localerr;
+ return DW_DLV_ERROR;
+ }
+ return DW_DLV_OK;
+}
+
+static int
+ might_have_addr[] = {
+ DW_AT_high_pc,
+ DW_AT_low_pc,
+};
+static int might_have_locdesc[] = {
+ DW_AT_segment,
+ DW_AT_return_addr,
+ DW_AT_frame_base,
+ DW_AT_static_link,
+ DW_AT_data_member_location,
+ DW_AT_string_length,
+ DW_AT_location,
+ DW_AT_use_location,
+ DW_AT_vtable_elem_location,
+};
+
+/* Return DW_DLV_OK if handling this went ok. */
+static int
+handle_attr_addr(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Half attrnum,
+ Dwarf_Error * perr)
+{
+ int res = DW_DLV_OK;
+ Dwarf_Off offset;
+ Dwarf_Addr addr;
+ Dwarf_Half form;
+ int ares;
+
+ Dwarf_Attribute attr;
+
+ ares = dwarf_attr(die, attrnum, &attr, perr);
+ if (ares == DW_DLV_OK) {
+ int formres = dwarf_whatform(attr, &form, perr);
+
+ switch (formres) {
+ case DW_DLV_OK:
+ break;
+ case DW_DLV_ERROR:
+ case DW_DLV_NO_ENTRY: /* impossible. */
+ return formres;
+
+ }
+
+ switch (form) {
+ case DW_FORM_ref_addr:
+ case DW_FORM_addr:
+ res = dwarf_attr_offset(die, attr, &offset, perr);
+ if (res == DW_DLV_OK) {
+ ares = dwarf_formaddr(attr, &addr, perr);
+ if (ares == DW_DLV_OK) {
+ send_addr_note(DW_SECTION_INFO, offset, addr);
+ } else if (ares == DW_DLV_ERROR) {
+ return ares;
+ }
+ /* no entry: ok. */
+ } else {
+ /* NO_ENTRY is impossible. */
+ res = DW_DLV_ERROR;
+ }
+ break;
+
+ default:
+ /* surprising! An error? */
+ /* do nothing */
+ ;
+ }
+ dwarf_dealloc(dbg, attr, DW_DLA_ATTR);
+ } else {
+ res = ares;
+ }
+ return res;
+}
+
+/* Return DW_DLV_OK if handling this went ok. */
+static int
+handle_attr_locdesc(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Half attrnum,
+ Dwarf_Error * perr)
+{
+ int retval = DW_DLV_OK;
+ Dwarf_Attribute attr;
+ Dwarf_Locdesc *llbuf;
+ Dwarf_Signed i;
+ Dwarf_Off offset;
+ Dwarf_Loc *locp;
+ unsigned int entindx;
+ int res;
+ int ares;
+
+
+ ares = dwarf_attr(die, attrnum, &attr, perr);
+ if (ares == DW_DLV_OK) {
+ Dwarf_Half form;
+ int fres = dwarf_whatform(attr, &form, perr);
+
+ if (fres == DW_DLV_OK) {
+ switch (form) {
+ case DW_FORM_block1:
+ case DW_FORM_block2:
+ case DW_FORM_block4:
+ /* must be location description */
+ res = dwarf_attr_offset(die, attr, &offset, perr);
+ llbuf = 0;
+ if (res == DW_DLV_OK) {
+ Dwarf_Signed count;
+ int lres = dwarf_loclist(attr, &llbuf, &count, perr);
+ if (lres != DW_DLV_OK) {
+ return lres;
+ }
+ if (count != 1) {
+ /* this cannot happen! */
+ /* perr? */
+ _dwarf_error(dbg, perr,
+ DW_DLE_LOCDESC_COUNT_WRONG);
+ retval = DW_DLV_ERROR;
+ return retval;
+ }
+ for (i = 0; i < count; ++i) {
+ unsigned int ents = llbuf[i].ld_cents;
+
+ locp = llbuf[i].ld_s;
+ for (entindx = 0; entindx < ents; entindx++) {
+ Dwarf_Loc *llocp;
+
+ llocp = locp + entindx;
+ if (llocp->lr_atom == DW_OP_addr) {
+ send_addr_note(DW_SECTION_INFO, offset +
+ llocp->lr_offset + 1
+ /* The offset is the
+ offset of the atom,
+ ** and we know the
+ addr is 1 past it. */
+ , llocp->lr_number);
+ }
+ }
+ }
+
+
+ if (count > 0) {
+ for (i = 0; i < count; ++i) {
+ dwarf_dealloc(dbg, llbuf[i].ld_s,
+ DW_DLA_LOC_BLOCK);
+ }
+ dwarf_dealloc(dbg, llbuf, DW_DLA_LOCDESC);
+ }
+ } else {
+ retval = res;
+ }
+ break;
+
+ default:
+ /* must be a const offset in debug_loc */
+ ; /* do nothing */
+ }
+ dwarf_dealloc(dbg, attr, DW_DLA_ATTR);
+ } /* else error or no entry */
+ retval = fres;
+ } else {
+ retval = ares;
+ }
+ return retval;
+}
+
+/* Return DW_DLV_OK, or DW_DLV_ERROR
+
+ Handle the addrs in a single die. */
+static int
+process_this_die_attrs(Dwarf_Debug dbg, Dwarf_Die newdie, int *errval)
+{
+ Dwarf_Error err;
+ Dwarf_Half i;
+ Dwarf_Half newattrnum;
+ int res;
+ int tres;
+ Dwarf_Half ltag;
+
+ Dwarf_Off doff;
+ int doffres = dwarf_dieoffset(newdie, &doff, &err);
+
+ if (doffres != DW_DLV_OK) {
+ if (doffres == DW_DLV_ERROR) {
+ *errval = (int) dwarf_errno(err);
+ }
+ return doffres;
+ }
+ tres = dwarf_tag(newdie, &ltag, &err);
+ if (tres != DW_DLV_OK) {
+ return tres;
+ }
+ if (DW_TAG_compile_unit == ltag) {
+ /* Because of the way the dwarf_line code works, we do lines
+ only per compile unit. This may turn out to be wrong if
+ we have lines left unconnected to a CU. of course such
+ lines will not, at present, be used by gnome. This is
+ not ideal as coded due to the dwarf_line.c issue. */
+ int lres = handle_debug_line(dbg, newdie, send_addr_note, errval);
+ if (lres == DW_DLV_ERROR) {
+ return lres;
+ }
+ }
+
+ for (i = 0; i < sizeof(might_have_addr) / sizeof(int); i++) {
+ int resattr;
+ Dwarf_Bool hasattr;
+
+ newattrnum = might_have_addr[i];
+ err = 0;
+ resattr = dwarf_hasattr(newdie, newattrnum, &hasattr, &err);
+ if (DW_DLV_OK == resattr) {
+ if (hasattr) {
+ res = handle_attr_addr(dbg, newdie, newattrnum, &err);
+ if (res != DW_DLV_OK) {
+ *errval = (int) dwarf_errno(err);
+ return DW_DLV_ERROR;
+ }
+ }
+ } else {
+ if (resattr == DW_DLV_ERROR) {
+ *errval = (int) dwarf_errno(err);
+ return resattr;
+ }
+ }
+ }
+ for (i = 0; i < sizeof(might_have_locdesc) / sizeof(int); i++) {
+ int resattr;
+ Dwarf_Bool hasattr;
+
+ newattrnum = might_have_locdesc[i];
+ err = 0;
+ resattr = dwarf_hasattr(newdie, newattrnum, &hasattr, &err);
+ if (DW_DLV_OK == resattr) {
+ if (hasattr) {
+ res =
+ handle_attr_locdesc(dbg, newdie, newattrnum, &err);
+ if (res != DW_DLV_OK) {
+ *errval = (int) dwarf_errno(err);
+ return DW_DLV_ERROR;
+ }
+ }
+ } else {
+ if (resattr == DW_DLV_ERROR) {
+ *errval = (int) dwarf_errno(err);
+ return resattr;
+ }
+ }
+ }
+
+ return DW_DLV_OK;
+}
+
+/* Handle siblings as a list,
+ Do children by recursing.
+ Effectively this is walking the tree preorder.
+
+ This dealloc's any die passed to it, so the
+ caller should not do that dealloc.
+ It seems more logical to have the one causing
+ the alloc to do the dealloc, but that way this
+ routine became a mess.
+*/
+static int
+do_this_die_and_dealloc(Dwarf_Debug dbg, Dwarf_Die die, int *errval)
+{
+
+ Dwarf_Die prevdie = 0;
+ Dwarf_Die newdie = die;
+ Dwarf_Error err = 0;
+ int res = 0;
+ int sibres = DW_DLV_OK;
+ int tres = DW_DLV_OK;
+ Dwarf_Die sibdie;
+
+ while (sibres == DW_DLV_OK) {
+ Dwarf_Die ch_die;
+
+
+ res = process_this_die_attrs(dbg, newdie, errval);
+ switch (res) {
+ case DW_DLV_OK:
+ break;
+ case DW_DLV_NO_ENTRY:
+ break;
+ default:
+ case DW_DLV_ERROR:
+ if (prevdie) {
+ dwarf_dealloc(dbg, prevdie, DW_DLA_DIE);
+ prevdie = 0;
+ }
+ return DW_DLV_ERROR;
+ }
+
+ tres = dwarf_child(newdie, &ch_die, &err);
+
+ if (tres == DW_DLV_OK) {
+ res = do_this_die_and_dealloc(dbg, ch_die, errval);
+ switch (res) {
+ case DW_DLV_OK:
+ break;
+ case DW_DLV_NO_ENTRY:
+ break;
+ default:
+ case DW_DLV_ERROR:
+ if (prevdie) {
+ dwarf_dealloc(dbg, prevdie, DW_DLA_DIE);
+ prevdie = 0;
+ }
+ return DW_DLV_ERROR;
+ }
+ } else if (tres == DW_DLV_ERROR) {
+ /* An error! */
+ *errval = (int) dwarf_errno(err);
+ if (prevdie) {
+ dwarf_dealloc(dbg, prevdie, DW_DLA_DIE);
+ prevdie = 0;
+ }
+ dwarf_dealloc(dbg, err, DW_DLA_ERROR);
+ return DW_DLV_ERROR;
+ } /* else was NO ENTRY */
+ prevdie = newdie;
+ sibdie = 0;
+ sibres = dwarf_siblingof(dbg, newdie, &sibdie, &err);
+ if (prevdie) {
+ dwarf_dealloc(dbg, prevdie, DW_DLA_DIE);
+ prevdie = 0;
+ }
+ newdie = sibdie;
+
+ }
+ if (sibres == DW_DLV_NO_ENTRY) {
+ return DW_DLV_OK;
+ }
+ /* error. */
+ *errval = (int) dwarf_errno(err);
+ if (prevdie) {
+ dwarf_dealloc(dbg, prevdie, DW_DLA_DIE);
+ prevdie = 0;
+ }
+ dwarf_dealloc(dbg, err, DW_DLA_ERROR);
+ return DW_DLV_ERROR;
+
+}
+
+
+static int
+handle_debug_frame(Dwarf_Debug dbg, Dwarf_addr_callback_func cb_func,
+ int *errval)
+{
+ int retval = DW_DLV_OK;
+ int res;
+ Dwarf_Error err;
+ Dwarf_Addr *addrlist;
+ Dwarf_Off *offsetlist;
+ Dwarf_Signed count;
+ int i;
+
+ res =
+ _dwarf_frame_address_offsets(dbg, &addrlist, &offsetlist,
+ &count, &err);
+ if (res == DW_DLV_OK) {
+ for (i = 0; i < count; i++) {
+ cb_func(DW_SECTION_FRAME, offsetlist[i], addrlist[i]);
+ }
+ dwarf_dealloc(dbg, offsetlist, DW_DLA_ADDR);
+ dwarf_dealloc(dbg, addrlist, DW_DLA_ADDR);
+ } else if (res == DW_DLV_NO_ENTRY) {
+ retval = res;
+ } else {
+ *errval = (int) dwarf_errno(err);
+ retval = DW_DLV_ERROR;
+ }
+ return retval;
+
+}
+static int
+handle_debug_aranges(Dwarf_Debug dbg, Dwarf_addr_callback_func cb_func,
+ int *errval)
+{
+ int retval = DW_DLV_OK;
+ Dwarf_Error err;
+ Dwarf_Addr *aranges;
+ Dwarf_Signed count;
+ int indx;
+ Dwarf_Off *offsets;
+
+ retval =
+ _dwarf_get_aranges_addr_offsets(dbg, &aranges, &offsets, &count,
+ &err);
+ if (retval == DW_DLV_OK) {
+ if (count == 0) {
+ retval = DW_DLV_NO_ENTRY;
+ } else {
+ for (indx = 0; indx < count; indx++) {
+ cb_func(DW_SECTION_ARANGES, offsets[indx],
+ aranges[indx]);
+ }
+ }
+ dwarf_dealloc(dbg, aranges, DW_DLA_ADDR);
+ dwarf_dealloc(dbg, offsets, DW_DLA_ADDR);
+ } else if (retval == DW_DLV_NO_ENTRY) {
+ ; /* do nothing */
+ } else {
+ *errval = (int) dwarf_errno(err);
+ retval = DW_DLV_ERROR;
+ }
+ return retval;
+}
+static int
+handle_debug_line(Dwarf_Debug dbg, Dwarf_Die cu_die,
+ Dwarf_addr_callback_func cb_func, int *errval)
+{
+ int retval = DW_DLV_OK;
+ int res;
+ Dwarf_Error err;
+ Dwarf_Addr *addrlist;
+ Dwarf_Off *offsetlist;
+ Dwarf_Unsigned count;
+ Dwarf_Unsigned i;
+
+ res =
+ _dwarf_line_address_offsets(dbg, cu_die, &addrlist, &offsetlist,
+ &count, &err);
+ if (res == DW_DLV_OK) {
+ for (i = 0; i < count; i++) {
+ cb_func(DW_SECTION_LINE, offsetlist[i], addrlist[i]);
+
+ }
+ dwarf_dealloc(dbg, offsetlist, DW_DLA_ADDR);
+ dwarf_dealloc(dbg, addrlist, DW_DLA_ADDR);
+ } else if (res == DW_DLV_NO_ENTRY) {
+ retval = res;
+ } else {
+ *errval = (int) dwarf_errno(err);
+ retval = DW_DLV_ERROR;
+ }
+ return retval;
+}
+
+/* We need to add support for this. Currently we do not
+ generate this section.
+ FIX!
+*/
+static int
+handle_debug_loc(void)
+{
+ int retval = DW_DLV_NO_ENTRY;
+
+ return retval;
+}
diff --git a/libdwarf/dwarf_alloc.c b/libdwarf/dwarf_alloc.c
new file mode 100644
index 0000000..353fb6f
--- /dev/null
+++ b/libdwarf/dwarf_alloc.c
@@ -0,0 +1,1270 @@
+/*
+
+ Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+
+#undef DEBUG
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <sys/types.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "malloc_check.h"
+
+/* These files are included to get the sizes
+ of structs to set the ah_bytes_one_struct field
+ of the Dwarf_Alloc_Hdr_s structs for each
+ allocation type.
+*/
+#include "dwarf_line.h"
+#include "dwarf_global.h"
+#include "dwarf_arange.h"
+#include "dwarf_abbrev.h"
+#include "dwarf_die_deliv.h"
+#include "dwarf_frame.h"
+#include "dwarf_loc.h"
+#include "dwarf_funcs.h"
+#include "dwarf_types.h"
+#include "dwarf_vars.h"
+#include "dwarf_weaks.h"
+#include "dwarf_harmless.h"
+
+
+static void _dwarf_free_special_error(Dwarf_Ptr space);
+
+#ifdef DWARF_SIMPLE_MALLOC
+static void _dwarf_simple_malloc_add_to_list(Dwarf_Debug dbg,
+ Dwarf_Ptr addr,
+ unsigned long size,
+ short alloc_type);
+static void _dwarf_simple_malloc_delete_from_list(Dwarf_Debug dbg,
+ Dwarf_Ptr space,
+ short alloc_type);
+void _dwarf_simple_malloc_botch(int err);
+
+#endif /* DWARF_SIMPLE_MALLOC */
+
+
+
+
+/* This macro adds the size of a pointer to the size of a
+ struct that is given to it. It rounds up the size to
+ be a multiple of the size of a pointer. This is done
+ so that every struct returned by _dwarf_get_alloc()
+ can be preceded by a pointer to the chunk it came from.
+ Before allocating, it checks if the size of struct is less than
+ the size of a pointer. If yes, it returns the size
+ of 2 pointers. The returned size should be at least
+ the size of 2 pointers, since the first points to the
+ chunk the struct was allocated from, and the second
+ is used to link the free list.
+
+ We want DW_RESERVE to be at least the size of
+ a long long and at least the size of a pointer because
+ our struct has a long long and we want that aligned right.
+ Now Standard C defines long long as 8 bytes, so lets
+ make that standard. It will become unworkable when
+ long long or pointer grows beyound 8 bytes.
+ Unclear what to do with wierd requirements, like
+ 36 bit pointers.
+*/
+#define DW_RESERVE 8
+
+/* Round size up to the next multiple of DW_RESERVE bytes
+*/
+#define ROUND_SIZE(inputsize) \
+ (((inputsize) % (DW_RESERVE)) == 0 ? \
+ (inputsize): \
+ ((inputsize) + \
+ (DW_RESERVE) - ((inputsize) % (DW_RESERVE)) ))
+
+#define ROUND_SIZE_WITH_POINTER(i_size) (ROUND_SIZE(i_size) + DW_RESERVE)
+
+/* SMALL_ALLOC is for trivia where allocation is a waste.
+ Things that should be removed, really. */
+#define SMALL_ALLOC 2
+
+/* BASE_ALLOC is where a basic allocation makes sense,
+ but 'not too large'.
+ No thorough evaluation of this value has been done, though
+ it was found wasteful of memory to have BASE_ALLOC be as large as
+ BIG_ALLOC. */
+#define BASE_ALLOC 64
+
+/* BIG_ALLOC is where a larger-than-BASE_ALLOC
+ allocation makes sense, but still 'not too large'.
+ No thorough evaluation of this value has been done. */
+#define BIG_ALLOC 128
+
+/* This translates into de_alloc_hdr index
+ the 0,1,1 entries are special: they don't use the
+ table values at all.
+ Rearranging the DW_DLA values would break binary compatibility
+ so that is not an option.
+*/
+struct ial_s {
+ int ia_al_num; /* Index into de_alloc_hdr table. */
+
+ /* In bytes, one struct instance. This does not account for extra
+ space needed per block, but that (DW_RESERVE) will be added in
+ later where it is needed
+ (DW_RESERVE space never added in here). */
+ int ia_struct_size;
+
+
+ /* Number of instances per alloc block. MUST be > 0. */
+ int ia_base_count;
+
+ int (*specialconstructor) (Dwarf_Debug, void *);
+ void (*specialdestructor) (void *);
+};
+
+static const
+struct ial_s index_into_allocated[ALLOC_AREA_INDEX_TABLE_MAX] = {
+ {0, 1, 1, 0, 0}, /* 0 none */
+ {0, 1, 1, 0, 0}, /* 1 DW_DLA_STRING */
+ {1, sizeof(Dwarf_Loc), BASE_ALLOC, 0, 0} ,/* 2 DW_DLA_LOC */
+ {2, sizeof(Dwarf_Locdesc), BASE_ALLOC, 0, 0} , /* 3 DW_DLA_LOCDESC */
+ {0, 1, 1, 0, 0} , /* not used *//* 4 DW_DLA_ELLIST */
+ {0, 1, 1, 0, 0} , /* not used *//* 5 DW_DLA_BOUNDS */
+ {3, sizeof(Dwarf_Block), BASE_ALLOC, 0, 0} , /* 6 DW_DLA_BLOCK */
+
+ /* the actual dwarf_debug structure */ /* 7 DW_DLA_DEBUG */
+ {0, 1, 1, 0, 0} ,
+
+ {4, sizeof(struct Dwarf_Die_s), BIG_ALLOC, 0, 0},/* 8 DW_DLA_DIE */
+ {5, sizeof(struct Dwarf_Line_s), BIG_ALLOC, 0, 0},/* 9 DW_DLA_LINE */
+
+ /* 10 DW_DLA_ATTR */
+ {6, sizeof(struct Dwarf_Attribute_s), BIG_ALLOC * 2, 0, 0},
+
+ {0, 1, 1, 0, 0}, /* not used */ /* 11 DW_DLA_TYPE */
+ {0, 1, 1, 0, 0}, /* not used */ /* 12 DW_DLA_SUBSCR */
+
+ /* 13 DW_DLA_GLOBAL */
+ {7, sizeof(struct Dwarf_Global_s), BASE_ALLOC, 0, 0},
+
+ /* 14 DW_DLA_ERROR */
+ {8, sizeof(struct Dwarf_Error_s), BASE_ALLOC, 0, 0},
+
+ {0, 1, 1, 0, 0}, /* 15 DW_DLA_LIST */
+ {0, 1, 1, 0, 0}, /* not used *//* 16 DW_DLA_LINEBUF */
+
+ /* 17 DW_DLA_ARANGE */
+ {9, sizeof(struct Dwarf_Arange_s), BASE_ALLOC, 0, 0},
+
+ /* 18 DW_DLA_ABBREV */
+ {10, sizeof(struct Dwarf_Abbrev_s), BIG_ALLOC, 0, 0},
+
+ /* 19 DW_DLA_FRAME_OP */
+ {11, sizeof(Dwarf_Frame_Op), BIG_ALLOC, 0, 0} ,
+
+ /* 20 DW_DLA_CIE */
+ {12, sizeof(struct Dwarf_Cie_s), BASE_ALLOC, 0, 0},
+
+ {13, sizeof(struct Dwarf_Fde_s), BASE_ALLOC, 0, 0},/* 21 DW_DLA_FDE */
+ {0, 1, 1, 0, 0}, /* 22 DW_DLA_LOC_BLOCK */
+ {0, 1, 1, 0, 0}, /* 23 DW_DLA_FRAME_BLOCK */
+
+ /* 24 DW_DLA_FUNC UNUSED */
+ {14, sizeof(struct Dwarf_Global_s), BASE_ALLOC, 0, 0},
+
+ /* 25 DW_DLA_TYPENAME UNUSED */
+ {15, sizeof(struct Dwarf_Global_s), BASE_ALLOC, 0, 0},
+
+ /* 26 DW_DLA_VAR UNUSED */
+ {16, sizeof(struct Dwarf_Global_s), BASE_ALLOC, 0, 0},
+
+ /* 27 DW_DLA_WEAK UNUSED */
+ {17, sizeof(struct Dwarf_Global_s), BASE_ALLOC, 0, 0},
+
+ {0, 1, 1, 0, 0}, /* 28 DW_DLA_ADDR */
+ {0, 1,1,0,0 }, /* 29 DW_DLA_RANGES */
+
+ /* The following DW_DLA data types
+ are known only inside libdwarf. */
+
+ /* 30 DW_DLA_ABBREV_LIST */
+ {18, sizeof(struct Dwarf_Abbrev_List_s), BIG_ALLOC, 0, 0},
+
+ /* 31 DW_DLA_CHAIN */
+ {19, sizeof(struct Dwarf_Chain_s), BIG_ALLOC, 0, 0},
+
+ /* 32 DW_DLA_CU_CONTEXT */
+ {20, sizeof(struct Dwarf_CU_Context_s), BASE_ALLOC, 0, 0},
+
+ {21, sizeof(struct Dwarf_Frame_s), BASE_ALLOC,
+ _dwarf_frame_constructor,
+ _dwarf_frame_destructor}, /* 33 DW_DLA_FRAME */
+
+ /* 34 DW_DLA_GLOBAL_CONTEXT */
+ {22, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC, 0, 0},
+
+ /* 35 DW_DLA_FILE_ENTRY */
+ {23, sizeof(struct Dwarf_File_Entry_s), BASE_ALLOC, 0, 0},
+
+ /* 36 DW_DLA_LINE_CONTEXT */
+ {24, sizeof(struct Dwarf_Line_Context_s), BASE_ALLOC, 0, 0},
+
+ /* 37 DW_DLA_LOC_CHAIN */
+ {25, sizeof(struct Dwarf_Loc_Chain_s), BASE_ALLOC, 0, 0},
+
+ /* 38 DW_DLA_HASH_TABLE */
+ {26, sizeof(struct Dwarf_Hash_Table_s),BASE_ALLOC, 0, 0},
+
+ /* The following really use Global struct: used to be unique struct
+ per type, but now merged (11/99). The opaque types
+ are visible in the interface. The types for
+ DW_DLA_FUNC, DW_DLA_TYPENAME, DW_DLA_VAR, DW_DLA_WEAK also use
+ the global types. */
+
+ /* 39 DW_DLA_FUNC_CONTEXT */
+ {27, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC, 0, 0},
+
+ /* 40 DW_DLA_TYPENAME_CONTEXT */
+ {28, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC, 0, 0},
+
+ /* 41 DW_DLA_VAR_CONTEXT */
+ {29, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC, 0, 0},
+
+ /* 42 DW_DLA_WEAK_CONTEXT */
+ {30, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC, 0, 0},
+
+ /* 43 DW_DLA_PUBTYPES_CONTEXT DWARF3 */
+ {31, sizeof(struct Dwarf_Global_Context_s), BASE_ALLOC, 0, 0},
+
+ {0,1,1,0,0 }, /* 44 DW_DLA_HASH_TABLE_ENTRY */
+
+
+};
+
+#ifndef DWARF_SIMPLE_MALLOC
+
+/* This function is given a pointer to the header
+ structure that is used to allocate 1 struct of
+ the type given by alloc_type. It first checks
+ if a struct is available in its free list. If
+ not, it checks if 1 is available in its blob,
+ which is a chunk of memory that is reserved for
+ its use. If not, it malloc's a chunk. The
+ initial part of it is used to store the end
+ address of the chunk, and also to keep track
+ of the number of free structs in that chunk.
+ This information is used for freeing the chunk
+ when all the structs in it are free.
+
+ Assume all input arguments have been validated.
+
+ This function can be used only to allocate 1
+ struct of the given type.
+
+ It returns a pointer to the struct that the
+ user can use. It returns NULL only when it
+ is out of free structs, and cannot malloc
+ any more. The struct returned is zero-ed.
+
+ A pointer to the chunk that the struct belongs
+ to is stored in the bytes preceding the
+ returned address. Since this pointer it
+ never overwritten, when a struct is allocated
+ from the free_list this pointer does not
+ have to be written. In the 2 other cases,
+ where the struct is allocated from a new
+ chunk, or the blob, a pointer to the chunk
+ is written.
+*/
+static Dwarf_Ptr
+_dwarf_find_memory(Dwarf_Alloc_Hdr alloc_hdr)
+{
+ /* Pointer to the struct allocated. */
+ Dwarf_Small *ret_mem = 0;
+
+ /* Pointer to info about chunks allocated. */
+ Dwarf_Alloc_Area alloc_area;
+
+ /* Size of chunk malloc'ed when no free structs left. */
+ Dwarf_Signed mem_block_size;
+
+ /* Pointer to block malloc'ed. */
+ Dwarf_Small *mem_block;
+
+ /* Check the alloc_area from which the last allocation was made
+ (most recent new block). If that is not successful, then search
+ the list of alloc_area's from alloc_header. */
+ alloc_area = alloc_hdr->ah_last_alloc_area;
+ if (alloc_area == NULL || alloc_area->aa_free_structs_in_chunk == 0)
+ for (alloc_area = alloc_hdr->ah_alloc_area_head;
+ alloc_area != NULL; alloc_area = alloc_area->aa_next) {
+
+ if (alloc_area->aa_free_structs_in_chunk > 0) {
+ break; /* found a free entry! */
+ }
+
+ }
+
+ if (alloc_area != NULL) {
+ alloc_area->aa_free_structs_in_chunk--;
+
+ if (alloc_area->aa_free_list != NULL) {
+ ret_mem = alloc_area->aa_free_list;
+
+ /* Update the free list. The initial part of the struct is
+ used to hold a pointer to the next struct on the free
+ list. In this way, the free list chain is maintained at
+ 0 memory cost. */
+ alloc_area->aa_free_list =
+ ((Dwarf_Free_List) ret_mem)->fl_next;
+ } else if (alloc_area->aa_blob_start < alloc_area->aa_blob_end) {
+ ret_mem = alloc_area->aa_blob_start;
+
+ /* Store pointer to chunk this struct belongs to in the
+ first few bytes. Return pointer to bytes after this
+ pointer storage. */
+ *(Dwarf_Alloc_Area *) ret_mem = alloc_area;
+ ret_mem += DW_RESERVE;
+
+ alloc_area->aa_blob_start += alloc_hdr->ah_bytes_one_struct;
+ } else {
+ /* else fall thru , though it should be impossible to fall
+ thru. And represents a disastrous programming error if
+ we get here. */
+#ifdef DEBUG
+ fprintf(stderr, "libdwarf Internal error start %x end %x\n",
+ (int) alloc_area->aa_blob_start,
+ (int) alloc_area->aa_blob_end);
+#endif
+ }
+ }
+
+ /* New memory has to malloc'ed since there are no free structs. */
+ if (ret_mem == 0) {
+ Dwarf_Word rounded_area_hdr_size;
+
+ alloc_hdr->ah_chunks_allocated++;
+
+ { /* this nonsense avoids a warning */
+ /* CONSTCOND would be better */
+ unsigned long v = sizeof(struct Dwarf_Alloc_Area_s);
+
+ rounded_area_hdr_size = ROUND_SIZE(v);
+ }
+
+ /* Allocate memory to contain the required number of structs
+ and the Dwarf_Alloc_Area_s to control it. */
+ mem_block_size = alloc_hdr->ah_bytes_malloc_per_chunk +
+ rounded_area_hdr_size;
+
+ mem_block = malloc(mem_block_size);
+ if (mem_block == NULL) {
+ return (NULL);
+ }
+
+
+ /* Attach the Dwarf_Alloc_Area_s struct to the list of chunks
+ malloc'ed for this struct type. Also initialize the fields
+ of the Dwarf_Alloc_Area_s. */
+ alloc_area = (Dwarf_Alloc_Area) mem_block;
+ alloc_area->aa_prev = 0;
+ if (alloc_hdr->ah_alloc_area_head != NULL) {
+ alloc_hdr->ah_alloc_area_head->aa_prev = alloc_area;
+ }
+ alloc_area->aa_free_list = 0;
+ alloc_area->aa_next = alloc_hdr->ah_alloc_area_head;
+ alloc_hdr->ah_alloc_area_head = alloc_area;
+
+ alloc_area->aa_alloc_hdr = alloc_hdr;
+ alloc_area->aa_free_structs_in_chunk =
+ (Dwarf_Sword) alloc_hdr->ah_structs_per_chunk - 1;
+ if (alloc_area->aa_free_structs_in_chunk < 1) {
+ /* If we get here, there is a disastrous programming error
+ somewhere. */
+#ifdef DEBUG
+ fprintf(stderr,
+ "libdwarf Internal error: free structs in chunk %d\n",
+ (int) alloc_area->aa_free_structs_in_chunk);
+#endif
+ return NULL;
+ }
+
+ /* The struct returned begins immediately after the
+ Dwarf_Alloc_Area_s struct. */
+ ret_mem = mem_block + rounded_area_hdr_size;
+ alloc_area->aa_blob_start =
+ ret_mem + alloc_hdr->ah_bytes_one_struct;
+ alloc_area->aa_blob_end = mem_block + mem_block_size;
+
+ /* Store pointer to chunk this struct belongs to in the first
+ few bytes. Return pointer to bytes after this pointer
+ storage. */
+ *(Dwarf_Alloc_Area *) ret_mem = alloc_area;
+ ret_mem += DW_RESERVE;
+ }
+
+ alloc_hdr->ah_last_alloc_area = alloc_area;
+ alloc_hdr->ah_struct_user_holds++;
+ memset(ret_mem, 0, alloc_hdr->ah_bytes_one_struct - DW_RESERVE);
+ return (ret_mem);
+}
+
+#endif /* ndef DWARF_SIMPLE_MALLOC */
+
+/* This function returns a pointer to a region
+ of memory. For alloc_types that are not
+ strings or lists of pointers, only 1 struct
+ can be requested at a time. This is indicated
+ by an input count of 1. For strings, count
+ equals the length of the string it will
+ contain, i.e it the length of the string
+ plus 1 for the terminating null. For lists
+ of pointers, count is equal to the number of
+ pointers. For DW_DLA_FRAME_BLOCK, DW_DLA_RANGES, and
+ DW_DLA_LOC_BLOCK allocation types also, count
+ is the count of the number of structs needed.
+
+ This function cannot be used to allocate a
+ Dwarf_Debug_s struct. */
+Dwarf_Ptr
+_dwarf_get_alloc(Dwarf_Debug dbg,
+ Dwarf_Small alloc_type, Dwarf_Unsigned count)
+{
+ Dwarf_Alloc_Hdr alloc_hdr;
+
+ Dwarf_Ptr ret_mem;
+
+ Dwarf_Signed size = 0;
+ unsigned int index;
+ unsigned int type = alloc_type;
+
+ if (dbg == NULL) {
+ return (NULL);
+ }
+
+ if (type >= ALLOC_AREA_INDEX_TABLE_MAX) {
+ /* internal error */
+ return NULL;
+ }
+ index = index_into_allocated[type].ia_al_num;
+ /* Zero also illegal but not tested for */
+
+ /* If the Dwarf_Debug is not fully set up, we will get index 0 for
+ any type and must do something. 'Not fully set up' can only
+ happen for DW_DLA_ERROR, I (davea) believe, and for that we call
+ special code here.. */
+
+ if (index == 0) {
+ if (alloc_type == DW_DLA_STRING) {
+ size = count;
+ } else if (alloc_type == DW_DLA_LIST) {
+ size = count * sizeof(Dwarf_Ptr);
+ } else if (alloc_type == DW_DLA_FRAME_BLOCK) {
+ size = count * sizeof(Dwarf_Frame_Op);
+ } else if (alloc_type == DW_DLA_LOC_BLOCK) {
+ size = count * sizeof(Dwarf_Loc);
+ } else if (alloc_type == DW_DLA_HASH_TABLE_ENTRY) {
+ size = count * sizeof(struct Dwarf_Hash_Table_Entry_s);
+ } else if (alloc_type == DW_DLA_ADDR) {
+ size = count *
+ (sizeof(Dwarf_Addr) > sizeof(Dwarf_Off) ?
+ sizeof(Dwarf_Addr) : sizeof(Dwarf_Off));
+ } else if (alloc_type == DW_DLA_RANGES) {
+ size = count * sizeof(Dwarf_Ranges);
+ } else if (alloc_type == DW_DLA_ERROR) {
+ void *m = _dwarf_special_no_dbg_error_malloc();
+
+ dwarf_malloc_check_alloc_data(m, DW_DLA_ERROR);
+ return m;
+
+ } else {
+ /* If we get here, there is a disastrous programming error
+ somewhere. */
+#ifdef DEBUG
+ fprintf(stderr,
+ "libdwarf Internal error: type %d unexpected\n",
+ (int) type);
+#endif
+ }
+ } else {
+ alloc_hdr = &dbg->de_alloc_hdr[index];
+ if (alloc_hdr->ah_bytes_one_struct > 0) {
+#ifdef DWARF_SIMPLE_MALLOC
+ size = alloc_hdr->ah_bytes_one_struct;
+#else
+ {
+ void *m = _dwarf_find_memory(alloc_hdr);
+
+ dwarf_malloc_check_alloc_data(m, type);
+ if (index_into_allocated[type].specialconstructor) {
+ int res =
+ index_into_allocated[type].
+ specialconstructor(dbg, m);
+ if (res != DW_DLV_OK) {
+ /* We leak what we allocated in
+ _dwarf_find_memory when constructor fails. */
+ return NULL;
+ }
+ }
+ return m;
+ }
+#endif
+
+ } else {
+ /* Special case: should not really happen at all. */
+ if (type == DW_DLA_ERROR) {
+ /* dwarf_init failure. Because dbg is incomplete we
+ won't use it to record the malloc. */
+ void *m = _dwarf_special_no_dbg_error_malloc();
+
+ dwarf_malloc_check_alloc_data(m, DW_DLA_ERROR);
+ return m;
+ } else {
+ /* If we get here, there is a disastrous programming
+ error somewhere. */
+#ifdef DWARF_SIMPLE_MALLOC
+ _dwarf_simple_malloc_botch(3);
+#endif
+#ifdef DEBUG
+ fprintf(stderr,
+ "libdwarf Internal error: Type %d unexpected\n",
+ (int) type);
+#endif
+ }
+ }
+ }
+
+ ret_mem = malloc(size);
+#ifdef DWARF_SIMPLE_MALLOC
+ _dwarf_simple_malloc_add_to_list(dbg, ret_mem,
+ (unsigned long) size, type);
+#endif
+ if (ret_mem != NULL)
+ memset(ret_mem, 0, size);
+
+ dwarf_malloc_check_alloc_data(ret_mem, type);
+ if (index_into_allocated[type].specialconstructor) {
+ int res =
+ index_into_allocated[type].specialconstructor(dbg, ret_mem);
+ if (res != DW_DLV_OK) {
+ /* We leak what we allocated in _dwarf_find_memory when
+ constructor fails. */
+ return NULL;
+ }
+ }
+
+ return (ret_mem);
+}
+
+
+
+/*
+ This function is used to deallocate a region of memory
+ that was obtained by a call to _dwarf_get_alloc. Note
+ that though dwarf_dealloc() is a public function,
+ _dwarf_get_alloc() isn't.
+
+ For lists, typically arrays of pointers, it is assumed
+ that the space was allocated by a direct call to malloc,
+ and so a straight free() is done. This is also the case
+ for variable length blocks such as DW_DLA_FRAME_BLOCK
+ and DW_DLA_LOC_BLOCK and DW_DLA_RANGES.
+
+ For strings, the pointer might point to a string in
+ .debug_info or .debug_string. After this is checked,
+ and if found not to be the case, a free() is done,
+ again on the assumption that a malloc was used to
+ obtain the space.
+
+ For other types of structs, a pointer to the chunk that
+ the struct was allocated out of, is present in the bytes
+ preceding the pointer passed in. For this chunk it is
+ checked whether all the structs in that chunk are now free.
+ If so, the entire chunk is free_ed. Otherwise, the space
+ is added to the free list for that chunk, and the free count
+ incremented.
+
+ This function does not return anything.
+*/
+void
+dwarf_dealloc(Dwarf_Debug dbg,
+ Dwarf_Ptr space, Dwarf_Unsigned alloc_type)
+{
+ Dwarf_Alloc_Hdr alloc_hdr;
+ Dwarf_Alloc_Area alloc_area;
+ unsigned int type = alloc_type;
+ unsigned int index;
+
+ if (space == NULL) {
+ return;
+ }
+ if (type == DW_DLA_ERROR) {
+ /* Get pointer to Dwarf_Alloc_Area this struct came from. See
+ dwarf_alloc.h ROUND_SIZE_WITH_POINTER stuff */
+#ifdef DWARF_SIMPLE_MALLOC
+ _dwarf_simple_malloc_delete_from_list(dbg, space, type);
+ free(space);
+ return;
+#endif
+ alloc_area =
+ *(Dwarf_Alloc_Area *) ((char *) space - DW_RESERVE);
+ if (alloc_area == 0) {
+ /* This is the special case of a failed dwarf_init(). Also
+ (and more signficantly) there are a variety of other
+ situations where libdwarf does not *know* what dbg is
+ involved (because of a libdwarf-caller-error) so
+ libdwarf uses NULL as the dbg. Those too wind up here. */
+ _dwarf_free_special_error(space);
+ dwarf_malloc_check_dealloc_data(space, type);
+ return;
+ }
+
+ }
+ if (dbg == NULL) {
+ /* App error, or an app that failed to succeed in a
+ dwarf_init() call. */
+ return;
+ }
+ if (type >= ALLOC_AREA_INDEX_TABLE_MAX) {
+ /* internal or user app error */
+ return;
+ }
+
+ index = index_into_allocated[type].ia_al_num;
+ /* A string pointer may point into .debug_info or .debug_string.
+ Otherwise, they are directly malloc'ed. */
+ dwarf_malloc_check_dealloc_data(space, type);
+ if (index == 0) {
+ if (type == DW_DLA_STRING) {
+ if ((Dwarf_Small *) space >= dbg->de_debug_info.dss_data &&
+ (Dwarf_Small *) space <
+ dbg->de_debug_info.dss_data + dbg->de_debug_info.dss_size)
+ return;
+ if ((Dwarf_Small *) space >= dbg->de_debug_types.dss_data &&
+ (Dwarf_Small *) space <
+ dbg->de_debug_types.dss_data + dbg->de_debug_types.dss_size)
+ return;
+
+ if (dbg->de_debug_line.dss_data != NULL &&
+ (Dwarf_Small *) space >= dbg->de_debug_line.dss_data &&
+ (Dwarf_Small *) space <
+ dbg->de_debug_line.dss_data + dbg->de_debug_line.dss_size)
+ return;
+
+ if (dbg->de_debug_pubnames.dss_data != NULL &&
+ (Dwarf_Small *) space >= dbg->de_debug_pubnames.dss_data &&
+ (Dwarf_Small *) space <
+ dbg->de_debug_pubnames.dss_data +
+ dbg->de_debug_pubnames.dss_size)
+ return;
+
+ if (dbg->de_debug_frame.dss_data != NULL &&
+ (Dwarf_Small *) space >= dbg->de_debug_frame.dss_data &&
+ (Dwarf_Small *) space <
+ dbg->de_debug_frame.dss_data + dbg->de_debug_frame.dss_size)
+ return;
+
+ if (dbg->de_debug_str.dss_data != NULL &&
+ (Dwarf_Small *) space >= dbg->de_debug_str.dss_data &&
+ (Dwarf_Small *) space <
+ dbg->de_debug_str.dss_data + dbg->de_debug_str.dss_size)
+ return;
+
+ if (dbg->de_debug_funcnames.dss_data != NULL &&
+ (Dwarf_Small *) space >= dbg->de_debug_funcnames.dss_data &&
+ (Dwarf_Small *) space <
+ dbg->de_debug_funcnames.dss_data +
+ dbg->de_debug_funcnames.dss_size)
+ return;
+
+ if (dbg->de_debug_typenames.dss_data != NULL &&
+ (Dwarf_Small *) space >= dbg->de_debug_typenames.dss_data &&
+ (Dwarf_Small *) space <
+ dbg->de_debug_typenames.dss_data +
+ dbg->de_debug_typenames.dss_size)
+ return;
+ if (dbg->de_debug_pubtypes.dss_data != NULL &&
+ (Dwarf_Small *) space >= dbg->de_debug_pubtypes.dss_data &&
+ (Dwarf_Small *) space <
+ dbg->de_debug_pubtypes.dss_data +
+ dbg->de_debug_pubtypes.dss_size)
+ return;
+
+ if (dbg->de_debug_varnames.dss_data != NULL &&
+ (Dwarf_Small *) space >= dbg->de_debug_varnames.dss_data &&
+ (Dwarf_Small *) space <
+ dbg->de_debug_varnames.dss_data +
+ dbg->de_debug_varnames.dss_size)
+ return;
+
+ if (dbg->de_debug_weaknames.dss_data != NULL &&
+ (Dwarf_Small *) space >= dbg->de_debug_weaknames.dss_data &&
+ (Dwarf_Small *) space <
+ dbg->de_debug_weaknames.dss_data +
+ dbg->de_debug_weaknames.dss_size)
+ return;
+
+#ifdef DWARF_SIMPLE_MALLOC
+ _dwarf_simple_malloc_delete_from_list(dbg, space, type);
+#endif
+ free(space);
+ return;
+ }
+
+ if (type == DW_DLA_LIST ||
+ type == DW_DLA_FRAME_BLOCK ||
+ type == DW_DLA_LOC_BLOCK || type == DW_DLA_ADDR ||
+ type == DW_DLA_RANGES ||
+ type == DW_DLA_HASH_TABLE_ENTRY) {
+
+#ifdef DWARF_SIMPLE_MALLOC
+ _dwarf_simple_malloc_delete_from_list(dbg, space, type);
+#endif
+ free(space);
+ return;
+ }
+ /* else is an alloc type that is not used */
+ /* app or internal error */
+#ifdef DWARF_SIMPLE_MALLOC
+ _dwarf_simple_malloc_botch(4);
+#endif
+ return;
+
+ }
+ if (index_into_allocated[type].specialdestructor) {
+ index_into_allocated[type].specialdestructor(space);
+ }
+#ifdef DWARF_SIMPLE_MALLOC
+ _dwarf_simple_malloc_delete_from_list(dbg, space, type);
+ free(space);
+#else /* !DWARF_SIMPLE_MALLOC */
+ alloc_hdr = &dbg->de_alloc_hdr[index];
+
+ /* Get pointer to Dwarf_Alloc_Area this struct came from. See
+ dwarf_alloc.h ROUND_SIZE_WITH_POINTER stuff */
+ alloc_area = *(Dwarf_Alloc_Area *) ((char *) space - DW_RESERVE);
+
+ /* ASSERT: alloc_area != NULL If NULL we could abort, let it
+ coredump below, or return, pretending all is well. We go on,
+ letting program crash. Is caller error. */
+
+ /* Check that the alloc_hdr field of the alloc_area we have is
+ pointing to the right alloc_hdr. This is used to catch use of
+ incorrect deallocation code by the user. */
+ if (alloc_area->aa_alloc_hdr != alloc_hdr) {
+ /* If we get here, the user has called dwarf_dealloc wrongly or
+ there is some other disastrous error. By leaking mem here we
+ try to be safe... */
+#ifdef DEBUG
+ fprintf(stderr,
+ "libdwarf Internal error: type %d hdr mismatch %lx %lx "
+ "area ptr %lx\n",
+ (int) type,
+ (long) alloc_area->aa_alloc_hdr,
+ (long) alloc_hdr, (long) alloc_area);
+#endif
+ return;
+ }
+
+ alloc_hdr->ah_struct_user_holds--;
+ alloc_area->aa_free_structs_in_chunk++;
+
+ /* Give chunk back to malloc only when every struct is freed */
+ if (alloc_area->aa_free_structs_in_chunk ==
+ alloc_hdr->ah_structs_per_chunk) {
+ if (alloc_area->aa_prev != NULL) {
+ alloc_area->aa_prev->aa_next = alloc_area->aa_next;
+ } else {
+ alloc_hdr->ah_alloc_area_head = alloc_area->aa_next;
+ }
+
+ if (alloc_area->aa_next != NULL) {
+ alloc_area->aa_next->aa_prev = alloc_area->aa_prev;
+ }
+
+ alloc_hdr->ah_chunks_allocated--;
+
+ if (alloc_area == alloc_hdr->ah_last_alloc_area) {
+ alloc_hdr->ah_last_alloc_area = NULL;
+ }
+ memset(alloc_area, 0, sizeof(*alloc_area));
+ free(alloc_area);
+ }
+
+ else {
+ ((Dwarf_Free_List) space)->fl_next = alloc_area->aa_free_list;
+ alloc_area->aa_free_list = space;
+ }
+#endif /* !DWARF_SIMPLE_MALLOC */
+}
+
+
+/*
+ Allocates space for a Dwarf_Debug_s struct,
+ since one does not exist.
+*/
+Dwarf_Debug
+_dwarf_get_debug(void
+ )
+{
+ Dwarf_Debug dbg;
+
+ dbg = (Dwarf_Debug) malloc(sizeof(struct Dwarf_Debug_s));
+ if (dbg == NULL) {
+ return (NULL);
+ } else {
+ memset(dbg, 0, sizeof(struct Dwarf_Debug_s));
+ }
+ return (dbg);
+}
+
+
+/*
+ Sets up the Dwarf_Debug_s struct for all the
+ allocation types currently defined.
+ Allocation types DW_DLA_STRING, DW_DLA_LIST,
+ DW_DLA_FRAME_BLOCK, DW_DLA_LOC_BLOCK, DW_DLA_RANGES are
+ malloc'ed directly.
+
+ This routine should be called after _dwarf_setup(),
+ so that information about the sizes of the Dwarf
+ sections can be used to decide the number of
+ structs of each type malloc'ed.
+
+ Also DW_DLA_ELLIST, DW_DLA_BOUNDS, DW_DLA_TYPE,
+ DW_DLA_SUBSCR, DW_DLA_LINEBUF allocation types
+ are currently not used.
+ The ah_bytes_one_struct and ah_structs_per_chunk fields for
+ these types have been set to 1 for efficiency
+ in dwarf_get_alloc().
+
+ Ah_alloc_num should be greater than 1 for all
+ types that are currently being used.
+
+ Therefore, for these allocation types the
+ ah_bytes_one_struct, and ah_structs_per_chunk fields do not
+ need to be initialized.
+
+ Being an internal routine, assume proper dbg.
+*/
+
+Dwarf_Debug
+_dwarf_setup_debug(Dwarf_Debug dbg)
+{
+ int i;
+
+ for (i = 1; i <= MAX_DW_DLA; i++) {
+ const struct ial_s *ialp = &index_into_allocated[i];
+ unsigned int hdr_index = ialp->ia_al_num;
+ Dwarf_Word str_size = ialp->ia_struct_size;
+ Dwarf_Word str_count = ialp->ia_base_count;
+ Dwarf_Word rnded_size = ROUND_SIZE_WITH_POINTER(str_size);
+
+ Dwarf_Alloc_Hdr alloc_hdr = &dbg->de_alloc_hdr[hdr_index];
+
+ alloc_hdr->ah_bytes_one_struct = (Dwarf_Half) rnded_size;
+
+ /* ah_structs_per_chunk must be >0 else we are in trouble */
+ alloc_hdr->ah_structs_per_chunk = str_count;
+ alloc_hdr->ah_bytes_malloc_per_chunk = rnded_size * str_count;
+ }
+ return (dbg);
+}
+
+/*
+ This function prints out the statistics
+ collected on allocation of memory chunks.
+*/
+void
+dwarf_print_memory_stats(Dwarf_Debug dbg)
+{
+ Dwarf_Alloc_Hdr alloc_hdr;
+ Dwarf_Shalf i;
+
+ /* Alloc types start at 1, not 0. Hence, the first NULL string, and
+ also a size of MAX_DW_DLA + 1. */
+ char *alloc_type_name[MAX_DW_DLA + 1] = {
+ "",
+ "DW_DLA_STRING",
+ "DW_DLA_LOC",
+ "DW_DLA_LOCDESC",
+ "DW_DLA_ELLIST",
+ "DW_DLA_BOUNDS",
+ "DW_DLA_BLOCK",
+ "DW_DLA_DEBUG",
+ "DW_DLA_DIE",
+ "DW_DLA_LINE",
+ "DW_DLA_ATTR",
+ "DW_DLA_TYPE",
+ "DW_DLA_SUBSCR",
+ "DW_DLA_GLOBAL",
+ "DW_DLA_ERROR",
+ "DW_DLA_LIST",
+ "DW_DLA_LINEBUF",
+ "DW_DLA_ARANGE",
+ "DW_DLA_ABBREV",
+ "DW_DLA_FRAME_OP",
+ "DW_DLA_CIE",
+ "DW_DLA_FDE",
+ "DW_DLA_LOC_BLOCK",
+ "DW_DLA_FRAME_BLOCK",
+ "DW_DLA_FUNC",
+ "DW_DLA_TYPENAME",
+ "DW_DLA_VAR",
+ "DW_DLA_WEAK",
+ "DW_DLA_ADDR",
+ "DW_DLA_RANGES",
+ "DW_DLA_ABBREV_LIST",
+ "DW_DLA_CHAIN",
+ "DW_DLA_CU_CONTEXT",
+ "DW_DLA_FRAME",
+ "DW_DLA_GLOBAL_CONTEXT",
+ "DW_DLA_FILE_ENTRY",
+ "DW_DLA_LINE_CONTEXT",
+ "DW_DLA_LOC_CHAIN",
+ "DW_DLA_HASH_TABLE",
+ "DW_DLA_FUNC_CONTEXT",
+ "DW_DLA_TYPENAME_CONTEXT",
+ "DW_DLA_VAR_CONTEXT",
+ "DW_DLA_WEAK_CONTEXT",
+ "DW_DLA_PUBTYPES_CONTEXT",
+ "DW_DLA_HASH_TABLE_ENTRY",
+ };
+
+ if (dbg == NULL)
+ return;
+
+ printf("Size of Dwarf_Debug %4ld bytes\n",
+ (long) sizeof(*dbg));
+ printf("Size of Dwarf_Alloc_Hdr_s %4ld bytes\n",
+ (long) sizeof(struct Dwarf_Alloc_Hdr_s));
+ printf("size of Dwarf_Alloc_Area_s %4ld bytes\n",
+ (long) sizeof(struct Dwarf_Alloc_Area_s));
+
+ printf(" Alloc Type Curr Structs byt str\n");
+ printf(" ---------- ---- ------- per per\n");
+ for (i = 1; i <= MAX_DW_DLA; i++) {
+ int indx = index_into_allocated[i].ia_al_num;
+
+ alloc_hdr = &dbg->de_alloc_hdr[indx];
+ if (alloc_hdr->ah_bytes_one_struct != 1) {
+ printf("%2d %-25s %6d %8d %6d %6d\n",
+ (int) i,
+ alloc_type_name[i],
+ (int) alloc_hdr->ah_chunks_allocated,
+ (int) alloc_hdr->ah_struct_user_holds,
+ (int) alloc_hdr->ah_bytes_malloc_per_chunk,
+ (int) alloc_hdr->ah_structs_per_chunk);
+ }
+ }
+}
+
+
+#ifndef DWARF_SIMPLE_MALLOC
+/*
+ This recursively frees
+ the chunks still allocated, and
+ forward chained through the aa_next
+ pointer.
+*/
+static void
+_dwarf_recursive_free(Dwarf_Alloc_Area alloc_area)
+{
+ if (alloc_area->aa_next != NULL) {
+ _dwarf_recursive_free(alloc_area->aa_next);
+ }
+
+ alloc_area->aa_next = 0;
+ alloc_area->aa_prev = 0;
+ free(alloc_area);
+}
+#endif
+
+/* In the 'rela' relocation case we might have malloc'd
+ space to ensure it is read-write. In that case, free the space. */
+static void
+rela_free(struct Dwarf_Section_s * sec)
+{
+ if (sec->dss_data_was_malloc) {
+ free(sec->dss_data);
+ }
+ sec->dss_data = 0;
+ sec->dss_data_was_malloc = 0;
+}
+
+static void
+freecontextlist(Dwarf_Debug dbg, Dwarf_Debug_InfoTypes dis)
+{
+ Dwarf_CU_Context context = 0;
+ Dwarf_CU_Context nextcontext = 0;
+ for (context = dis->de_cu_context_list;
+ context; context = nextcontext) {
+ Dwarf_Hash_Table hash_table = context->cc_abbrev_hash_table;
+ _dwarf_free_abbrev_hash_table_contents(dbg,hash_table);
+ nextcontext = context->cc_next;
+ dwarf_dealloc(dbg, hash_table, DW_DLA_HASH_TABLE);
+ dwarf_dealloc(dbg, context, DW_DLA_CU_CONTEXT);
+ }
+}
+
+/*
+ Used to free all space allocated for this Dwarf_Debug.
+ The caller should assume that the Dwarf_Debug pointer
+ itself is no longer valid upon return from this function.
+
+ In case of difficulty, this function simply returns quietly.
+*/
+int
+_dwarf_free_all_of_one_debug(Dwarf_Debug dbg)
+{
+ Dwarf_Alloc_Hdr alloc_hdr = 0;
+ Dwarf_Shalf i = 0;
+
+ if (dbg == NULL) {
+ return (DW_DLV_ERROR);
+ }
+
+ /* To do complete validation that we have no surprising missing or
+ erroneous deallocs it is advisable to do the dwarf_deallocs here
+ that are not things the user can otherwise request.
+ Housecleaning. */
+ freecontextlist(dbg,&dbg->de_info_reading);
+ freecontextlist(dbg,&dbg->de_types_reading);
+
+ /* Housecleaning done. Now really free all the space. */
+#ifdef DWARF_SIMPLE_MALLOC
+ if (dbg->de_simple_malloc_base) {
+ struct simple_malloc_record_s *smp = dbg->de_simple_malloc_base;
+
+ while (smp) {
+ int i;
+ struct simple_malloc_record_s *prev_smp = 0;
+
+ for (i = 0; i < smp->sr_used; ++i) {
+ struct simple_malloc_entry_s *cur;
+
+ cur = &smp->sr_entry[i];
+ if (cur->se_addr != 0) {
+ free(cur->se_addr);
+ cur->se_addr = 0;
+ }
+ }
+ prev_smp = smp;
+ smp = smp->sr_next;
+ free(prev_smp);
+ }
+ dbg->de_simple_malloc_base = 0;
+ }
+#else
+ for (i = 1; i < ALLOC_AREA_REAL_TABLE_MAX; i++) {
+ int indx = i;
+
+ alloc_hdr = &dbg->de_alloc_hdr[indx];
+ if (alloc_hdr->ah_alloc_area_head != NULL) {
+ _dwarf_recursive_free(alloc_hdr->ah_alloc_area_head);
+ }
+ }
+
+#endif
+ rela_free(&dbg->de_debug_info);
+ rela_free(&dbg->de_debug_types);
+ rela_free(&dbg->de_debug_abbrev);
+ rela_free(&dbg->de_debug_line);
+ rela_free(&dbg->de_debug_loc);
+ rela_free(&dbg->de_debug_aranges);
+ rela_free(&dbg->de_debug_macinfo);
+ rela_free(&dbg->de_debug_pubnames);
+ rela_free(&dbg->de_debug_str);
+ rela_free(&dbg->de_debug_frame);
+ rela_free(&dbg->de_debug_frame_eh_gnu);
+ rela_free(&dbg->de_debug_pubtypes);
+ rela_free(&dbg->de_debug_funcnames);
+ rela_free(&dbg->de_debug_typenames);
+ rela_free(&dbg->de_debug_varnames);
+ rela_free(&dbg->de_debug_weaknames);
+ rela_free(&dbg->de_debug_ranges);
+ dwarf_harmless_cleanout(&dbg->de_harmless_errors);
+
+ memset(dbg, 0, sizeof(*dbg)); /* Prevent accidental use later. */
+ free(dbg);
+ return (DW_DLV_OK);
+}
+
+/* A special case: we have no dbg, no alloc header etc.
+ So create something out of thin air that we can recognize
+ in dwarf_dealloc.
+ Something with the prefix (prefix space hidden from caller).
+
+ Only applies to DW_DLA_ERROR, making up an error record. */
+struct Dwarf_Error_s *
+_dwarf_special_no_dbg_error_malloc(void)
+{
+ /* The union unused things are to guarantee proper alignment */
+ union u {
+ Dwarf_Alloc_Area ptr_not_used;
+ struct Dwarf_Error_s base_not_used;
+ char data_space[sizeof(struct Dwarf_Error_s) +
+ (DW_RESERVE * 2)];
+ };
+ char *mem;
+
+ mem = malloc(sizeof(union u));
+
+ if (mem == 0) {
+ return 0;
+
+ }
+ memset(mem, 0, sizeof(union u));
+ mem += DW_RESERVE;
+ return (struct Dwarf_Error_s *) mem;
+}
+
+/* The free side of _dwarf_special_no_dbg_error_malloc()
+*/
+static void
+_dwarf_free_special_error(Dwarf_Ptr space)
+{
+ char *mem = (char *) space;
+
+ mem -= DW_RESERVE;
+ free(mem);
+}
+
+
+#ifdef DWARF_SIMPLE_MALLOC
+/* here solely for planting a breakpoint. */
+/* ARGSUSED */
+void
+_dwarf_simple_malloc_botch(int err)
+{
+ fprintf(stderr,"simple malloc botch %d\n",err);
+}
+static void
+_dwarf_simple_malloc_add_to_list(Dwarf_Debug dbg,
+ Dwarf_Ptr addr,
+ unsigned long size, short alloc_type)
+{
+ struct simple_malloc_record_s *cur;
+ struct simple_malloc_entry_s *newentry;
+
+ if (!dbg->de_simple_malloc_base) {
+ /* First entry to this routine. */
+ dbg->de_simple_malloc_base =
+ malloc(sizeof(struct simple_malloc_record_s));
+ if (!dbg->de_simple_malloc_base) {
+ _dwarf_simple_malloc_botch(7);
+ return; /* no memory, give up */
+ }
+ memset(dbg->de_simple_malloc_base,
+ 0, sizeof(struct simple_malloc_record_s));
+ }
+ cur = dbg->de_simple_malloc_base;
+
+ if (cur->sr_used >= DSM_BLOCK_COUNT) {
+ /* Better not be > than as that means chaos */
+
+ /* Create a new block to link at the head. */
+
+ struct simple_malloc_record_s *newblock =
+ malloc(sizeof(struct simple_malloc_record_s));
+ if (!newblock) {
+ _dwarf_simple_malloc_botch(8);
+ return; /* Can do nothing, out of memory */
+ }
+ memset(newblock, 0, sizeof(struct simple_malloc_record_s));
+ /* Link the new block at the head of the chain, and make it
+ 'current' */
+ dbg->de_simple_malloc_base = newblock;
+ newblock->sr_next = cur;
+ cur = newblock;
+ }
+ newentry = &cur->sr_entry[cur->sr_used];
+ newentry->se_addr = addr;
+ newentry->se_size = size;
+ newentry->se_type = alloc_type;
+ ++cur->sr_used;
+}
+
+/*
+ DWARF_SIMPLE_MALLOC: testing the hypothesis that the existing
+ malloc scheme here (see _dwarf_get_alloc()) is pointless complexity.
+
+ DWARF_SIMPLE_MALLOC also makes it easy for a malloc-tracing
+ tool to verify libdwarf malloc has no botches (though of course
+ such does not test the complicated standard-libdwarf-alloc code).
+
+ To properly answer the question, the simple-malloc allocate
+ and delete should be something other than a simple list.
+ Perhaps a heap, or perhaps a red-black tree.
+
+*/
+static void
+_dwarf_simple_malloc_delete_from_list(Dwarf_Debug dbg,
+ Dwarf_Ptr space, short alloc_type)
+{
+ if (space == 0) {
+ _dwarf_simple_malloc_botch(6);
+ }
+ if (dbg->de_simple_malloc_base) {
+ struct simple_malloc_record_s *smp = dbg->de_simple_malloc_base;
+
+ while (smp) {
+ int i;
+
+ for (i = 0; i < smp->sr_used; ++i) {
+ struct simple_malloc_entry_s *cur;
+
+ cur = &smp->sr_entry[i];
+ if (cur->se_addr == space) {
+ if (cur->se_type != alloc_type) {
+ _dwarf_simple_malloc_botch(0);
+ }
+ cur->se_addr = 0;
+ return;
+ }
+ }
+ smp = smp->sr_next;
+ }
+ }
+ /* Never found the space. */
+ _dwarf_simple_malloc_botch(1);
+ return;
+
+}
+#endif
diff --git a/libdwarf/dwarf_alloc.h b/libdwarf/dwarf_alloc.h
new file mode 100644
index 0000000..c0eb2a7
--- /dev/null
+++ b/libdwarf/dwarf_alloc.h
@@ -0,0 +1,168 @@
+/*
+ Copyright (C) 2000,2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2008-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+/* #define DWARF_SIMPLE_MALLOC 1 */
+
+Dwarf_Ptr _dwarf_get_alloc(Dwarf_Debug, Dwarf_Small, Dwarf_Unsigned);
+Dwarf_Debug _dwarf_get_debug(void);
+Dwarf_Debug _dwarf_setup_debug(Dwarf_Debug);
+int _dwarf_free_all_of_one_debug(Dwarf_Debug);
+
+typedef struct Dwarf_Alloc_Area_s *Dwarf_Alloc_Area;
+typedef struct Dwarf_Free_List_s *Dwarf_Free_List;
+
+/* ALLOC_AREA_INDEX_TABLE_MAX is the size of the
+ struct ial_s index_into_allocated array in dwarf_alloc.c
+*/
+#define ALLOC_AREA_INDEX_TABLE_MAX 45
+/* ALLOC_AREA_REAL_TABLE_MAX is the size of the array needed
+ to hold pointers to dwarf alloc chunk areas.
+ It's smaller as some of the index_into_allocated
+ entries (they look like {0,1,1,0,0} )
+ are treated specially and don't use 'chunks'.
+*/
+#define ALLOC_AREA_REAL_TABLE_MAX 32
+
+/*
+ This struct is used to chain all the deallocated
+ structs on the free list of each chain. The structs
+ are chained internally, by using the memory they
+ contain.
+*/
+struct Dwarf_Free_List_s {
+ Dwarf_Free_List fl_next;
+};
+
+
+/*
+ This struct is used to manage all the chunks malloc'ed
+ for a particular alloc_type. Many of the fields are
+ initialized by dwarf_init().
+*/
+struct Dwarf_Alloc_Hdr_s {
+
+ /* Count of actual number of structs user app holds pointers to
+ currently. */
+ Dwarf_Sword ah_struct_user_holds;
+
+ /* Size of each struct that will be allocated for this alloc_type.
+ Initialized by dwarf_init(). */
+ Dwarf_Half ah_bytes_one_struct;
+
+ /* Number of structs of this alloc_type that will be contained in
+ each chunk that is malloc'ed. Initialized by dwarf_init(). */
+ Dwarf_Word ah_structs_per_chunk;
+
+ /* Number of bytes malloc'ed per chunk which is basically
+ (ah_bytes_one_struct+_DWARF_RESERVE) * ah_alloc_num. */
+ Dwarf_Word ah_bytes_malloc_per_chunk;
+
+ /* Count of chunks currently allocated for type. */
+ Dwarf_Sword ah_chunks_allocated;
+
+ /* Points to a chain of Dwarf_Alloc_Area_s structs that represent
+ all the chunks currently allocated for the alloc_type. */
+ Dwarf_Alloc_Area ah_alloc_area_head;
+
+ /* Last Alloc Area that was allocated by malloc. The
+ free-space-search area looks here first and only if it is full
+ goes thru the list pointed to by ah_alloc_area_head. */
+ Dwarf_Alloc_Area ah_last_alloc_area;
+};
+
+
+/*
+ This struct is used to manage each chunk that is
+ malloc'ed for a particular alloc_type. For each
+ allocation type, the allocation header points to
+ a list of all the chunks malloc'ed for that type.
+*/
+struct Dwarf_Alloc_Area_s {
+
+ /* Points to the free list of structs in the chunk. */
+ Dwarf_Ptr aa_free_list;
+
+ /* Count of the number of free structs in the chunk. This includes
+ both those on the free list, and in the blob. */
+ Dwarf_Sword aa_free_structs_in_chunk;
+
+ /* Points to the first byte of the blob from which struct will be
+ allocated. A struct is put on the free_list only when it
+ dwarf_deallocated. Initial allocations are from the blob. */
+ Dwarf_Small *aa_blob_start;
+
+ /* Points just past the last byte of the blob. */
+ Dwarf_Small *aa_blob_end;
+
+ /* Points to alloc_hdr this alloc_area is linked to: The owner, in
+ other words. */
+ Dwarf_Alloc_Hdr aa_alloc_hdr;
+
+ /* Used for chaining Dwarf_Alloc_Area_s atructs. Alloc areas are
+ doubly linked to enable deletion from the list in constant time. */
+ Dwarf_Alloc_Area aa_next;
+ Dwarf_Alloc_Area aa_prev;
+};
+
+struct Dwarf_Error_s *_dwarf_special_no_dbg_error_malloc(void);
+
+#ifdef DWARF_SIMPLE_MALLOC
+/*
+ DWARF_SIMPLE_MALLOC is for testing the hypothesis that the existing
+ complex malloc scheme in libdwarf is pointless complexity.
+
+ DWARF_SIMPLE_MALLOC also makes it easy for a malloc-tracing
+ tool to verify libdwarf malloc has no botches (though of course
+ such does not test the complicated standard-libdwarf-alloc code).
+*/
+
+struct simple_malloc_entry_s {
+ Dwarf_Small *se_addr;
+ unsigned long se_size;
+ short se_type;
+};
+#define DSM_BLOCK_COUNT (1000)
+#define DSM_BLOCK_SIZE (sizeof(struct simple_malloc_entry_s)*DSM_BLOCK_COUNT)
+
+/* We do this so dwarf_dealloc can really free everything */
+struct simple_malloc_record_s {
+ struct simple_malloc_record_s *sr_next;
+ int sr_used;
+ struct simple_malloc_entry_s sr_entry[DSM_BLOCK_COUNT];
+};
+
+
+
+#endif /* DWARF_SIMPLE_MALLOC */
diff --git a/libdwarf/dwarf_arange.c b/libdwarf/dwarf_arange.c
new file mode 100644
index 0000000..fe74385
--- /dev/null
+++ b/libdwarf/dwarf_arange.c
@@ -0,0 +1,616 @@
+/*
+
+ Copyright (C) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+
+
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include "dwarf_arange.h"
+#include "dwarf_global.h" /* for _dwarf_fixup_* */
+
+
+/* Common code for two user-visible routines to share.
+ Errors here result in memory leaks, but errors here
+ are serious (making aranges unusable) so we assume
+ callers will not repeat the error often or mind the leaks.
+*/
+static int
+dwarf_get_aranges_list(Dwarf_Debug dbg,
+ Dwarf_Chain * chain_out,
+ Dwarf_Signed * chain_count_out,
+ Dwarf_Error * error)
+{
+ /* Sweeps through the arange. */
+ Dwarf_Small *arange_ptr = 0;
+ Dwarf_Small *arange_ptr_start = 0;
+
+ /* Start of arange header. Used for rounding offset of arange_ptr
+ to twice the tuple size. Libdwarf requirement. */
+ Dwarf_Small *header_ptr = 0;
+
+ /* Version of .debug_aranges header. */
+ Dwarf_Half version = 0;
+
+ /* Offset of current set of aranges into .debug_info. */
+ Dwarf_Off info_offset = 0;
+
+ /* Size in bytes of addresses in target. */
+ Dwarf_Small address_size = 0;
+
+ /* Size in bytes of segment offsets in target. */
+ Dwarf_Small segment_size = 0;
+
+ /* Count of total number of aranges. */
+ Dwarf_Unsigned arange_count = 0;
+
+ Dwarf_Arange arange = 0;
+
+ /* Used to chain Dwarf_Aranges structs. */
+ Dwarf_Chain curr_chain = NULL;
+ Dwarf_Chain prev_chain = NULL;
+ Dwarf_Chain head_chain = NULL;
+ if (!dbg->de_debug_aranges.dss_size) {
+ return (DW_DLV_NO_ENTRY);
+ }
+
+
+ arange_ptr = dbg->de_debug_aranges.dss_data;
+ arange_ptr_start = arange_ptr;
+ do {
+ /* Length of current set of aranges. */
+ Dwarf_Unsigned length = 0;
+ Dwarf_Small remainder = 0;
+ Dwarf_Small *arange_ptr_past_end = 0;
+ Dwarf_Unsigned range_entry_size = 0;
+
+ int local_length_size;
+
+ /*REFERENCED*/ /* Not used in this instance of the macro */
+ int local_extension_size = 0;
+
+ header_ptr = arange_ptr;
+
+ /* READ_AREA_LENGTH updates arange_ptr for consumed bytes */
+ READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
+ arange_ptr, local_length_size,
+ local_extension_size);
+ arange_ptr_past_end = arange_ptr + length;
+
+
+ READ_UNALIGNED(dbg, version, Dwarf_Half,
+ arange_ptr, sizeof(Dwarf_Half));
+ arange_ptr += sizeof(Dwarf_Half);
+ length = length - sizeof(Dwarf_Half);
+ if (version != CURRENT_VERSION_STAMP) {
+ _dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR);
+ return (DW_DLV_ERROR);
+ }
+
+ READ_UNALIGNED(dbg, info_offset, Dwarf_Off,
+ arange_ptr, local_length_size);
+ arange_ptr += local_length_size;
+ length = length - local_length_size;
+ /* This applies to debug_info only, not to debug_types. */
+ if (info_offset >= dbg->de_debug_info.dss_size) {
+ FIX_UP_OFFSET_IRIX_BUG(dbg, info_offset,
+ "arange info offset.a");
+ if (info_offset >= dbg->de_debug_info.dss_size) {
+ _dwarf_error(dbg, error, DW_DLE_ARANGE_OFFSET_BAD);
+ return (DW_DLV_ERROR);
+ }
+ }
+
+ address_size = *(Dwarf_Small *) arange_ptr;
+ if(address_size > sizeof(Dwarf_Addr)) {
+ _dwarf_error(dbg, error, DW_DLE_ADDRESS_SIZE_ERROR);
+ return DW_DLV_ERROR;
+ }
+ if(address_size == 0) {
+ _dwarf_error(dbg, error, DW_DLE_ADDRESS_SIZE_ERROR);
+ return DW_DLV_ERROR;
+ }
+ /* It is not an error if the sizes differ.
+ Unusual, but not an error. */
+ arange_ptr = arange_ptr + sizeof(Dwarf_Small);
+ length = length - sizeof(Dwarf_Small);
+
+ /* Even DWARF2 had a segment_size field here, meaning
+ size in bytes of a segment descriptor on the target
+ system. */
+ segment_size = *(Dwarf_Small *) arange_ptr;
+ if(segment_size > sizeof(Dwarf_Addr)) {
+ _dwarf_error(dbg, error, DW_DLE_SEGMENT_SIZE_BAD);
+ return (DW_DLV_ERROR);
+ }
+ arange_ptr = arange_ptr + sizeof(Dwarf_Small);
+ length = length - sizeof(Dwarf_Small);
+
+ range_entry_size = 2*address_size + segment_size;
+ /* Round arange_ptr offset to next multiple of address_size. */
+ remainder = (Dwarf_Unsigned) (arange_ptr - header_ptr) %
+ (range_entry_size);
+ if (remainder != 0) {
+ arange_ptr = arange_ptr + (2 * address_size) - remainder;
+ length = length - ((2 * address_size) - remainder);
+ }
+ do {
+ Dwarf_Addr range_address = 0;
+ Dwarf_Unsigned segment_selector = 0;
+ Dwarf_Unsigned range_length = 0;
+ /* For segmented address spaces, the first field to
+ read is a segment selector (new in DWARF4).
+ Surprising since the segment_size was always there
+ in the table header! */
+ if(version == 4 && segment_size != 0) {
+ READ_UNALIGNED(dbg, segment_selector, Dwarf_Unsigned,
+ arange_ptr, segment_size);
+ arange_ptr += address_size;
+ length = length - address_size;
+ }
+
+ READ_UNALIGNED(dbg, range_address, Dwarf_Addr,
+ arange_ptr, address_size);
+ arange_ptr += address_size;
+ length = length - address_size;
+
+ READ_UNALIGNED(dbg, range_length, Dwarf_Unsigned,
+ arange_ptr, address_size);
+ arange_ptr += address_size;
+ length = length - address_size;
+
+ {
+ /* We used to suppress all-zero entries, but
+ now we return all aranges entries so we show
+ the entire content. March 31, 2010. */
+
+ arange = (Dwarf_Arange)
+ _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1);
+ if (arange == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ arange->ar_segment_selector = segment_selector;
+ arange->ar_segment_selector_size = segment_size;
+ arange->ar_address = range_address;
+ arange->ar_length = range_length;
+ arange->ar_info_offset = info_offset;
+ arange->ar_dbg = dbg;
+ arange_count++;
+
+ curr_chain = (Dwarf_Chain)
+ _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (curr_chain == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ curr_chain->ch_item = arange;
+ if (head_chain == NULL)
+ head_chain = prev_chain = curr_chain;
+ else {
+ prev_chain->ch_next = curr_chain;
+ prev_chain = curr_chain;
+ }
+ }
+ /* The current set of ranges is terminated by
+ range_address 0 and range_length 0, but that
+ does not necessarily terminate the ranges for this CU!
+ There can be multiple sets in that DWARF
+ does not explicitly forbid multiple sets.
+ DWARF2,3,4 section 7.20
+ We stop short to avoid overrun of the end of the CU. */
+
+ } while (arange_ptr_past_end >= (arange_ptr + range_entry_size));
+
+ /* A compiler could emit some padding bytes here. dwarf2/3
+ (dwarf4 sec 7.20) does not clearly make extra padding
+ bytes illegal. */
+ if (arange_ptr_past_end < arange_ptr) {
+ char buf[200];
+ Dwarf_Unsigned pad_count = arange_ptr - arange_ptr_past_end;
+ Dwarf_Unsigned offset = arange_ptr - arange_ptr_start;
+ snprintf(buf,sizeof(buf),"DW_DLE_ARANGE_LENGTH_BAD."
+ " 0x%" DW_PR_XZEROS DW_PR_DUx
+ " pad bytes at offset 0x%" DW_PR_XZEROS DW_PR_DUx
+ " in .debug_aranges",
+ pad_count, offset);
+ dwarf_insert_harmless_error(dbg,buf);
+ }
+ /* For most compilers, arange_ptr == arange_ptr_past_end at
+ this point. But not if there were padding bytes */
+ arange_ptr = arange_ptr_past_end;
+ } while (arange_ptr <
+ dbg->de_debug_aranges.dss_data + dbg->de_debug_aranges.dss_size);
+
+ if (arange_ptr !=
+ dbg->de_debug_aranges.dss_data + dbg->de_debug_aranges.dss_size) {
+ _dwarf_error(dbg, error, DW_DLE_ARANGE_DECODE_ERROR);
+ return (DW_DLV_ERROR);
+ }
+ *chain_out = head_chain;
+ *chain_count_out = arange_count;
+ return DW_DLV_OK;
+}
+
+/*
+ This function returns the count of the number of
+ aranges in the .debug_aranges section. It sets
+ aranges to point to a block of Dwarf_Arange's
+ describing the arange's. It returns DW_DLV_ERROR
+ on error.
+
+ Must be identical in most aspects to
+ dwarf_get_aranges_addr_offsets!
+
+*/
+int
+dwarf_get_aranges(Dwarf_Debug dbg,
+ Dwarf_Arange ** aranges,
+ Dwarf_Signed * returned_count, Dwarf_Error * error)
+{
+ /* Count of total number of aranges. */
+ Dwarf_Signed arange_count = 0;
+
+ Dwarf_Arange *arange_block = 0;
+
+ /* Used to chain Dwarf_Aranges structs. */
+ Dwarf_Chain curr_chain = NULL;
+ Dwarf_Chain prev_chain = NULL;
+ Dwarf_Chain head_chain = NULL;
+ Dwarf_Unsigned i = 0;
+ int res = DW_DLV_ERROR;
+
+ /* ***** BEGIN CODE ***** */
+
+ if (dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ res = _dwarf_load_section(dbg, &dbg->de_debug_aranges, error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ res = dwarf_get_aranges_list(dbg,&head_chain,&arange_count,error);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+
+ arange_block = (Dwarf_Arange *)
+ _dwarf_get_alloc(dbg, DW_DLA_LIST, arange_count);
+ if (arange_block == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ curr_chain = head_chain;
+ for (i = 0; i < arange_count; i++) {
+ *(arange_block + i) = curr_chain->ch_item;
+ prev_chain = curr_chain;
+ curr_chain = curr_chain->ch_next;
+ dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
+ }
+
+ *aranges = arange_block;
+ *returned_count = (arange_count);
+ return DW_DLV_OK;
+}
+
+/*
+ This function returns DW_DLV_OK if it succeeds
+ and DW_DLV_ERR or DW_DLV_OK otherwise.
+ count is set to the number of addresses in the
+ .debug_aranges section.
+ For each address, the corresponding element in
+ an array is set to the address itself(aranges) and
+ the section offset (offsets).
+ Must be identical in most aspects to
+ dwarf_get_aranges!
+*/
+int
+_dwarf_get_aranges_addr_offsets(Dwarf_Debug dbg,
+ Dwarf_Addr ** addrs,
+ Dwarf_Off ** offsets,
+ Dwarf_Signed * count,
+ Dwarf_Error * error)
+{
+ Dwarf_Unsigned i = 0;
+
+ /* Used to chain Dwarf_Aranges structs. */
+ Dwarf_Chain curr_chain = NULL;
+ Dwarf_Chain prev_chain = NULL;
+ Dwarf_Chain head_chain = NULL;
+
+ Dwarf_Signed arange_count = 0;
+ Dwarf_Addr *arange_addrs = 0;
+ Dwarf_Off *arange_offsets = 0;
+
+ int res = DW_DLV_ERROR;
+
+ /* ***** BEGIN CODE ***** */
+
+ if (error != NULL)
+ *error = NULL;
+
+ if (dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ res = _dwarf_load_section(dbg, &dbg->de_debug_aranges,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ res = dwarf_get_aranges_list(dbg,&head_chain,&arange_count,error);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+
+ arange_addrs = (Dwarf_Addr *)
+ _dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count);
+ if (arange_addrs == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ arange_offsets = (Dwarf_Off *)
+ _dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count);
+ if (arange_offsets == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ curr_chain = head_chain;
+ for (i = 0; i < arange_count; i++) {
+ Dwarf_Arange ar = curr_chain->ch_item;
+
+ arange_addrs[i] = ar->ar_address;
+ arange_offsets[i] = ar->ar_info_offset;
+ prev_chain = curr_chain;
+ curr_chain = curr_chain->ch_next;
+ dwarf_dealloc(dbg, ar, DW_DLA_ARANGE);
+ dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
+ }
+ *count = arange_count;
+ *offsets = arange_offsets;
+ *addrs = arange_addrs;
+ return (DW_DLV_OK);
+}
+
+
+/*
+ This function takes a pointer to a block
+ of Dwarf_Arange's, and a count of the
+ length of the block. It checks if the
+ given address is within the range of an
+ address range in the block. If yes, it
+ returns the appropriate Dwarf_Arange.
+ Otherwise, it returns DW_DLV_ERROR.
+*/
+int
+dwarf_get_arange(Dwarf_Arange * aranges,
+ Dwarf_Unsigned arange_count,
+ Dwarf_Addr address,
+ Dwarf_Arange * returned_arange, Dwarf_Error * error)
+{
+ Dwarf_Arange curr_arange = 0;
+ Dwarf_Unsigned i = 0;
+
+ if (aranges == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_ARANGES_NULL);
+ return (DW_DLV_ERROR);
+ }
+ for (i = 0; i < arange_count; i++) {
+ curr_arange = *(aranges + i);
+ if (address >= curr_arange->ar_address &&
+ address <
+ curr_arange->ar_address + curr_arange->ar_length) {
+ *returned_arange = curr_arange;
+ return (DW_DLV_OK);
+ }
+ }
+
+ return (DW_DLV_NO_ENTRY);
+}
+
+
+/*
+ This function takes an Dwarf_Arange,
+ and returns the offset of the first
+ die in the compilation-unit that the
+ arange belongs to. Returns DW_DLV_ERROR
+ on error.
+
+ For an arange, the cu_die can only be from debug_info,
+ not debug_types, it seems.
+*/
+int
+dwarf_get_cu_die_offset(Dwarf_Arange arange,
+ Dwarf_Off * returned_offset,
+ Dwarf_Error * error)
+{
+ Dwarf_Debug dbg = 0;
+ Dwarf_Off offset = 0;
+
+ if (arange == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_ARANGE_NULL);
+ return (DW_DLV_ERROR);
+ }
+ dbg = arange->ar_dbg;
+ offset = arange->ar_info_offset;
+ /* This applies to debug_info only, not to debug_types. */
+ if (!dbg->de_debug_info.dss_data) {
+ int res = _dwarf_load_debug_info(dbg, error);
+
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ }
+ *returned_offset = offset + _dwarf_length_of_cu_header(dbg, offset, true);
+ return DW_DLV_OK;
+}
+
+/* This function takes an Dwarf_Arange,
+ and returns the offset of the CU header
+ in the compilation-unit that the
+ arange belongs to. Returns DW_DLV_ERROR
+ on error.
+ Ensures .debug_info loaded so
+ the cu_offset is meaningful. */
+int
+dwarf_get_arange_cu_header_offset(Dwarf_Arange arange,
+ Dwarf_Off * cu_header_offset_returned,
+ Dwarf_Error * error)
+{
+ Dwarf_Debug dbg = 0;
+ if (arange == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_ARANGE_NULL);
+ return (DW_DLV_ERROR);
+ }
+ dbg = arange->ar_dbg;
+ /* This applies to debug_info only, not to debug_types. */
+ /* Like dwarf_get_arange_info this ensures debug_info loaded:
+ the cu_header is in debug_info and will be used else
+ we would not call dwarf_get_arange_cu_header_offset. */
+ if (!dbg->de_debug_info.dss_data) {
+ int res = _dwarf_load_debug_info(dbg, error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ }
+ *cu_header_offset_returned = arange->ar_info_offset;
+ return DW_DLV_OK;
+}
+
+
+
+
+/*
+ This function takes a Dwarf_Arange, and returns
+ true if it is not NULL. It also stores the start
+ address of the range in *start, the length of the
+ range in *length, and the offset of the first die
+ in the compilation-unit in *cu_die_offset. It
+ returns false on error.
+ If cu_die_offset returned ensures .debug_info loaded so
+ the cu_die_offset is meaningful.
+*/
+int
+dwarf_get_arange_info(Dwarf_Arange arange,
+ Dwarf_Addr * start,
+ Dwarf_Unsigned * length,
+ Dwarf_Off * cu_die_offset, Dwarf_Error * error)
+{
+ if (arange == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_ARANGE_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ if (start != NULL)
+ *start = arange->ar_address;
+ if (length != NULL)
+ *length = arange->ar_length;
+ if (cu_die_offset != NULL) {
+ Dwarf_Debug dbg = arange->ar_dbg;
+ Dwarf_Off offset = arange->ar_info_offset;
+
+ /* This applies to debug_info only, not to debug_types. */
+ if (!dbg->de_debug_info.dss_data) {
+ int res = _dwarf_load_debug_info(dbg, error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ }
+ *cu_die_offset =
+ offset + _dwarf_length_of_cu_header(dbg, offset,true);
+ }
+ return (DW_DLV_OK);
+}
+
+
+/* New for DWARF4, entries may have segment information.
+ *segment is only meaningful if *segment_entry_size is non-zero. */
+int
+dwarf_get_arange_info_b(Dwarf_Arange arange,
+ Dwarf_Unsigned* segment,
+ Dwarf_Unsigned* segment_entry_size,
+ Dwarf_Addr * start,
+ Dwarf_Unsigned* length,
+ Dwarf_Off * cu_die_offset,
+ Dwarf_Error * error)
+{
+ if (arange == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_ARANGE_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ if(segment != NULL) {
+ *segment = arange->ar_segment_selector;
+ }
+ if(segment_entry_size != NULL) {
+ *segment_entry_size = arange->ar_segment_selector_size;
+ }
+ if (start != NULL)
+ *start = arange->ar_address;
+ if (length != NULL)
+ *length = arange->ar_length;
+ if (cu_die_offset != NULL) {
+ Dwarf_Debug dbg = arange->ar_dbg;
+ Dwarf_Off offset = arange->ar_info_offset;
+
+ /* This applies to debug_info only, not to debug_types. */
+ if (!dbg->de_debug_info.dss_data) {
+ int res = _dwarf_load_debug_info(dbg, error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ }
+ *cu_die_offset =
+ offset + _dwarf_length_of_cu_header(dbg, offset,true);
+ }
+ return (DW_DLV_OK);
+}
diff --git a/libdwarf/dwarf_arange.h b/libdwarf/dwarf_arange.h
new file mode 100644
index 0000000..e5833b9
--- /dev/null
+++ b/libdwarf/dwarf_arange.h
@@ -0,0 +1,71 @@
+/*
+
+ Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+/* This structure is used to read an arange into. */
+struct Dwarf_Arange_s {
+
+ /* The segment selector. Only non-zero if Dwarf4, only
+ meaningful if ar_segment_selector_size non-zero */
+ Dwarf_Unsigned ar_segment_selector;
+
+ /* Starting address of the arange, ie low-pc. */
+ Dwarf_Addr ar_address;
+
+ /* Length of the arange. */
+ Dwarf_Unsigned ar_length;
+
+
+ /* Offset into .debug_info of the start of the compilation-unit
+ containing this set of aranges.
+ Applies only to .debug_info, not .debug_types. */
+ Dwarf_Off ar_info_offset;
+
+ /* Corresponding Dwarf_Debug. */
+ Dwarf_Debug ar_dbg;
+
+ Dwarf_Half ar_segment_selector_size;
+};
+
+
+
+int
+_dwarf_get_aranges_addr_offsets(Dwarf_Debug dbg,
+ Dwarf_Addr ** addrs,
+ Dwarf_Off ** offsets,
+ Dwarf_Signed * count,
+ Dwarf_Error * error);
diff --git a/libdwarf/dwarf_base_types.h b/libdwarf/dwarf_base_types.h
new file mode 100644
index 0000000..0258c76
--- /dev/null
+++ b/libdwarf/dwarf_base_types.h
@@ -0,0 +1,118 @@
+/*
+
+ Copyright (C) 2000,2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2008-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "libdwarfdefs.h"
+
+#define true 1
+#define false 0
+
+/* To identify a cie */
+#define DW_CIE_ID ~(0x0)
+#define DW_CIE_VERSION 1 /* DWARF2 */
+#define DW_CIE_VERSION3 3 /* DWARF3 */
+#define DW_CIE_VERSION4 4 /* DWARF4 */
+
+#define DW_CU_VERSION2 2
+#define DW_CU_VERSION3 3
+#define DW_CU_VERSION4 4
+
+/* DWARF2,3 and 4 */
+#define DW_ARANGES_VERSION2 2
+
+#define DW_LINE_VERSION2 2
+#define DW_LINE_VERSION3 3
+#define DW_LINE_VERSION4 4
+
+
+/* These are allocation type codes for structs that
+ are internal to the Libdwarf Consumer library. */
+#define DW_DLA_ABBREV_LIST DW_DLA_RANGES + 1
+#define DW_DLA_CHAIN DW_DLA_RANGES + 2
+#define DW_DLA_CU_CONTEXT DW_DLA_RANGES + 3
+#define DW_DLA_FRAME DW_DLA_RANGES + 4
+#define DW_DLA_GLOBAL_CONTEXT DW_DLA_RANGES + 5
+#define DW_DLA_FILE_ENTRY DW_DLA_RANGES + 6
+#define DW_DLA_LINE_CONTEXT DW_DLA_RANGES + 7
+#define DW_DLA_LOC_CHAIN DW_DLA_RANGES + 8
+#define DW_DLA_HASH_TABLE DW_DLA_RANGES + 9
+#define DW_DLA_FUNC_CONTEXT DW_DLA_RANGES + 10
+#define DW_DLA_TYPENAME_CONTEXT DW_DLA_RANGES + 11
+#define DW_DLA_VAR_CONTEXT DW_DLA_RANGES + 12
+#define DW_DLA_WEAK_CONTEXT DW_DLA_RANGES + 13
+#define DW_DLA_PUBTYPES_CONTEXT DW_DLA_RANGES + 14 /* DWARF3 */
+#define DW_DLA_HASH_TABLE_ENTRY DW_DLA_RANGES + 15
+
+/* Maximum number of allocation types for allocation routines. */
+#define MAX_DW_DLA DW_DLA_HASH_TABLE_ENTRY
+
+/*Dwarf_Word is unsigned word usable for index, count in memory */
+/*Dwarf_Sword is signed word usable for index, count in memory */
+/* The are 32 or 64 bits depending if 64 bit longs or not, which
+ fits the ILP32 and LP64 models
+ These work equally well with ILP64. */
+
+typedef unsigned long Dwarf_Word;
+typedef signed long Dwarf_Sword;
+
+typedef signed char Dwarf_Sbyte;
+typedef unsigned char Dwarf_Ubyte;
+typedef signed short Dwarf_Shalf;
+typedef Dwarf_Small *Dwarf_Byte_Ptr;
+
+/* These 2 are fixed sizes which must not vary with the
+ ILP32/LP64 model. Between these two, stay at 32 bit. */
+typedef __uint32_t Dwarf_ufixed;
+typedef __int32_t Dwarf_sfixed;
+
+/* In various places the code mistakenly associates
+ forms 8 bytes long with Dwarf_Signed or Dwarf_Unsigned
+ This is not a very portable assumption.
+ The following should be used instead for 64 bit integers.
+*/
+typedef __uint64_t Dwarf_ufixed64;
+typedef __int64_t Dwarf_sfixed64;
+
+
+typedef struct Dwarf_Abbrev_List_s *Dwarf_Abbrev_List;
+typedef struct Dwarf_File_Entry_s *Dwarf_File_Entry;
+typedef struct Dwarf_CU_Context_s *Dwarf_CU_Context;
+typedef struct Dwarf_Hash_Table_s *Dwarf_Hash_Table;
+typedef struct Dwarf_Hash_Table_Entry_s *Dwarf_Hash_Table_Entry;
+
+
+typedef struct Dwarf_Alloc_Hdr_s *Dwarf_Alloc_Hdr;
diff --git a/libdwarf/dwarf_die_deliv.c b/libdwarf/dwarf_die_deliv.c
new file mode 100644
index 0000000..9ef5c45
--- /dev/null
+++ b/libdwarf/dwarf_die_deliv.c
@@ -0,0 +1,1214 @@
+/*
+
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#ifdef HAVE_ELF_H
+#include <elf.h>
+#endif
+#include <stdio.h>
+#include "dwarf_die_deliv.h"
+
+
+static int
+dwarf_next_cu_header_internal(Dwarf_Debug dbg,
+ Dwarf_Bool is_info,
+ Dwarf_Unsigned * cu_header_length,
+ Dwarf_Half * version_stamp,
+ Dwarf_Unsigned * abbrev_offset,
+ Dwarf_Half * address_size,
+ Dwarf_Half * offset_size,
+ Dwarf_Half * extension_size,
+ Dwarf_Sig8 * signature,
+ Dwarf_Unsigned *typeoffset,
+ Dwarf_Unsigned * next_cu_offset,
+ Dwarf_Error * error);
+
+/* New October 2011. Enables client code to know if
+ it is a debug_info or debug_types context. */
+Dwarf_Bool
+dwarf_get_die_infotypes_flag(Dwarf_Die die)
+{
+ return die->di_is_info;
+}
+
+/*
+ For a given Dwarf_Debug dbg, this function checks
+ if a CU that includes the given offset has been read
+ or not. If yes, it returns the Dwarf_CU_Context
+ for the CU. Otherwise it returns NULL. Being an
+ internal routine, it is assumed that a valid dbg
+ is passed.
+
+ **This is a sequential search. May be too slow.
+
+ If debug_info and debug_abbrev not loaded, this will
+ wind up returning NULL. So no need to load before calling
+ this.
+*/
+static Dwarf_CU_Context
+_dwarf_find_CU_Context(Dwarf_Debug dbg, Dwarf_Off offset,Dwarf_Bool is_info)
+{
+ Dwarf_CU_Context cu_context = 0;
+ Dwarf_Debug_InfoTypes dis = is_info? &dbg->de_info_reading:
+ &dbg->de_types_reading;
+
+ if (offset >= dis->de_last_offset)
+ return (NULL);
+
+ if (dis->de_cu_context != NULL &&
+ dis->de_cu_context->cc_next != NULL &&
+ dis->de_cu_context->cc_next->cc_debug_offset == offset) {
+
+ return (dis->de_cu_context->cc_next);
+ }
+
+ if (dis->de_cu_context != NULL &&
+ dis->de_cu_context->cc_debug_offset <= offset) {
+
+ for (cu_context = dis->de_cu_context;
+ cu_context != NULL; cu_context = cu_context->cc_next) {
+
+ if (offset >= cu_context->cc_debug_offset &&
+ offset < cu_context->cc_debug_offset +
+ cu_context->cc_length + cu_context->cc_length_size
+ + cu_context->cc_extension_size) {
+
+ return (cu_context);
+ }
+ }
+ }
+
+ for (cu_context = dis->de_cu_context_list;
+ cu_context != NULL; cu_context = cu_context->cc_next) {
+
+ if (offset >= cu_context->cc_debug_offset &&
+ offset < cu_context->cc_debug_offset +
+ cu_context->cc_length + cu_context->cc_length_size
+ + cu_context->cc_extension_size) {
+
+ return (cu_context);
+ }
+ }
+
+ return (NULL);
+}
+
+
+/* This routine checks the dwarf_offdie() list of
+ CU contexts for the right CU context. */
+static Dwarf_CU_Context
+_dwarf_find_offdie_CU_Context(Dwarf_Debug dbg, Dwarf_Off offset,
+ Dwarf_Bool is_info)
+{
+ Dwarf_CU_Context cu_context = 0;
+ Dwarf_Debug_InfoTypes dis = is_info? &dbg->de_info_reading:
+ &dbg->de_types_reading;
+
+ for (cu_context = dis->de_offdie_cu_context;
+ cu_context != NULL; cu_context = cu_context->cc_next)
+
+ if (offset >= cu_context->cc_debug_offset &&
+ offset < cu_context->cc_debug_offset +
+ cu_context->cc_length + cu_context->cc_length_size
+ + cu_context->cc_extension_size)
+
+ return (cu_context);
+
+ return (NULL);
+}
+
+
+/* This function is used to create a CU Context for
+ a compilation-unit that begins at offset in
+ .debug_info. The CU Context is attached to the
+ list of CU Contexts for this dbg. It is assumed
+ that the CU at offset has not been read before,
+ and so do not call this routine before making
+ sure of this with _dwarf_find_CU_Context().
+ Returns NULL on error. As always, being an
+ internal routine, assumes a good dbg.
+
+ This function must always set a dwarf error code
+ before returning NULL. Always. */
+static Dwarf_CU_Context
+_dwarf_make_CU_Context(Dwarf_Debug dbg,
+ Dwarf_Off offset,Dwarf_Bool is_info,Dwarf_Error * error)
+{
+ Dwarf_CU_Context cu_context = 0;
+ Dwarf_Unsigned length = 0;
+ Dwarf_Signed abbrev_offset = 0;
+ Dwarf_Unsigned typeoffset = 0;
+ Dwarf_Sig8 signaturedata;
+ Dwarf_Unsigned types_extra_len = 0;
+ Dwarf_Byte_Ptr cu_ptr = 0;
+ int local_extension_size = 0;
+ int local_length_size = 0;
+ Dwarf_Debug_InfoTypes dis = is_info? &dbg->de_info_reading:
+ &dbg->de_types_reading;
+ Dwarf_Unsigned section_size = is_info? dbg->de_debug_info.dss_size:
+ dbg->de_debug_types.dss_size;
+
+ cu_context =
+ (Dwarf_CU_Context) _dwarf_get_alloc(dbg, DW_DLA_CU_CONTEXT, 1);
+ if (cu_context == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (NULL);
+ }
+ cu_context->cc_dbg = dbg;
+ cu_context->cc_is_info = is_info;
+
+ {
+ Dwarf_Small *dataptr = is_info? dbg->de_debug_info.dss_data:
+ dbg->de_debug_types.dss_data;
+ cu_ptr = (Dwarf_Byte_Ptr) (dataptr+offset);
+ }
+
+ /* READ_AREA_LENGTH updates cu_ptr for consumed bytes */
+ READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
+ cu_ptr, local_length_size, local_extension_size);
+ cu_context->cc_length_size = local_length_size;
+ cu_context->cc_extension_size = local_extension_size;
+
+
+ cu_context->cc_length = (Dwarf_Word) length;
+
+ READ_UNALIGNED(dbg, cu_context->cc_version_stamp, Dwarf_Half,
+ cu_ptr, sizeof(Dwarf_Half));
+ cu_ptr += sizeof(Dwarf_Half);
+
+ READ_UNALIGNED(dbg, abbrev_offset, Dwarf_Signed,
+ cu_ptr, local_length_size);
+ cu_ptr += local_length_size;
+ cu_context->cc_abbrev_offset = (Dwarf_Sword) abbrev_offset;
+
+ cu_context->cc_address_size = *(Dwarf_Small *) cu_ptr;
+ ++cu_ptr;
+
+
+
+ if(cu_context->cc_address_size > sizeof(Dwarf_Addr)) {
+ _dwarf_error(dbg, error, DW_DLE_CU_ADDRESS_SIZE_BAD);
+ return (NULL);
+ }
+ if(!is_info) {
+ /* debug_types CU headers have extra header bytes. */
+ types_extra_len = sizeof(signaturedata) + local_length_size;
+ }
+ if ((length < (CU_VERSION_STAMP_SIZE + local_length_size +
+ CU_ADDRESS_SIZE_SIZE + types_extra_len)) ||
+ ((offset + length + local_length_size + local_extension_size) >
+ section_size)) {
+
+ dwarf_dealloc(dbg, cu_context, DW_DLA_CU_CONTEXT);
+ _dwarf_error(dbg, error, DW_DLE_CU_LENGTH_ERROR);
+ return (NULL);
+ }
+
+ if (cu_context->cc_version_stamp != CURRENT_VERSION_STAMP
+ && cu_context->cc_version_stamp != CURRENT_VERSION_STAMP3
+ && cu_context->cc_version_stamp != CURRENT_VERSION_STAMP4) {
+ dwarf_dealloc(dbg, cu_context, DW_DLA_CU_CONTEXT);
+ _dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR);
+ return (NULL);
+ }
+ if (!is_info) {
+ if (cu_context->cc_version_stamp != CURRENT_VERSION_STAMP4) {
+ dwarf_dealloc(dbg, cu_context, DW_DLA_CU_CONTEXT);
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_TYPES_ONLY_DWARF4);
+ return (NULL);
+ }
+ /* Now read the debug_types extra header fields of
+ the signature (8 bytes) and the typeoffset. */
+ memcpy(&signaturedata,cu_ptr,sizeof(signaturedata));
+ cu_ptr += sizeof(signaturedata);
+ READ_UNALIGNED(dbg, typeoffset, Dwarf_Unsigned,
+ cu_ptr, local_length_size);
+ cu_context->cc_typeoffset = typeoffset;
+ cu_context->cc_signature = signaturedata;
+ {
+ Dwarf_Unsigned cu_len = length - (local_length_size +
+ local_extension_size);
+ if(typeoffset >= cu_len) {
+ dwarf_dealloc(dbg, cu_context, DW_DLA_CU_CONTEXT);
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_TYPEOFFSET_BAD);
+ return (NULL);
+ }
+ }
+ }
+
+ if (abbrev_offset >= dbg->de_debug_abbrev.dss_size) {
+ dwarf_dealloc(dbg, cu_context, DW_DLA_CU_CONTEXT);
+ _dwarf_error(dbg, error, DW_DLE_ABBREV_OFFSET_ERROR);
+ return (NULL);
+ }
+
+ cu_context->cc_abbrev_hash_table =
+ (Dwarf_Hash_Table) _dwarf_get_alloc(dbg, DW_DLA_HASH_TABLE, 1);
+ if (cu_context->cc_abbrev_hash_table == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (NULL);
+ }
+
+ cu_context->cc_debug_offset = (Dwarf_Word) offset;
+
+ dis->de_last_offset = (Dwarf_Word) (offset + length +
+ local_extension_size + local_length_size);
+
+ if (dis->de_cu_context_list == NULL) {
+ dis->de_cu_context_list = cu_context;
+ dis->de_cu_context_list_end = cu_context;
+ } else {
+ dis->de_cu_context_list_end->cc_next = cu_context;
+ dis->de_cu_context_list_end = cu_context;
+ }
+
+ return (cu_context);
+}
+
+static int
+reloc_incomplete(Dwarf_Error err)
+{
+ int e = dwarf_errno(err);
+ if( e == DW_DLE_RELOC_MISMATCH_INDEX ||
+ e == DW_DLE_RELOC_MISMATCH_RELOC_INDEX ||
+ e == DW_DLE_RELOC_MISMATCH_STRTAB_INDEX ||
+ e == DW_DLE_RELOC_SECTION_MISMATCH ||
+ e == DW_DLE_RELOC_SECTION_MISSING_INDEX ||
+ e == DW_DLE_RELOC_SECTION_LENGTH_ODD ||
+ e == DW_DLE_RELOC_SECTION_PTR_NULL ||
+ e == DW_DLE_RELOC_SECTION_MALLOC_FAIL ||
+ e == DW_DLE_RELOC_SECTION_SYMBOL_INDEX_BAD ) {
+ return 1;
+ }
+ return 0;
+}
+
+
+
+/* Returns offset of next compilation-unit thru next_cu_offset
+ pointer.
+ It sequentially moves from one
+ cu to the next. The current cu is recorded
+ internally by libdwarf.
+
+ The _b form is new for DWARF4 adding new returned fields. */
+int
+dwarf_next_cu_header(Dwarf_Debug dbg,
+ Dwarf_Unsigned * cu_header_length,
+ Dwarf_Half * version_stamp,
+ Dwarf_Unsigned * abbrev_offset,
+ Dwarf_Half * address_size,
+ Dwarf_Unsigned * next_cu_offset,
+ Dwarf_Error * error)
+{
+ Dwarf_Bool is_info = true;
+ return dwarf_next_cu_header_internal(dbg,
+ is_info,
+ cu_header_length,
+ version_stamp,
+ abbrev_offset,
+ address_size,
+ 0,0,0,0,
+ next_cu_offset,
+ error);
+}
+int
+dwarf_next_cu_header_b(Dwarf_Debug dbg,
+ Dwarf_Unsigned * cu_header_length,
+ Dwarf_Half * version_stamp,
+ Dwarf_Unsigned * abbrev_offset,
+ Dwarf_Half * address_size,
+ Dwarf_Half * offset_size,
+ Dwarf_Half * extension_size,
+ Dwarf_Unsigned * next_cu_offset,
+ Dwarf_Error * error)
+{
+ Dwarf_Bool is_info = true;
+ return dwarf_next_cu_header_internal(dbg,
+ is_info,
+ cu_header_length,
+ version_stamp,
+ abbrev_offset,
+ address_size,
+ offset_size,extension_size,
+ 0,0,
+ next_cu_offset,
+ error);
+}
+
+int
+dwarf_next_cu_header_c(Dwarf_Debug dbg,
+ Dwarf_Bool is_info,
+ Dwarf_Unsigned * cu_header_length,
+ Dwarf_Half * version_stamp,
+ Dwarf_Unsigned * abbrev_offset,
+ Dwarf_Half * address_size,
+ Dwarf_Half * offset_size,
+ Dwarf_Half * extension_size,
+ Dwarf_Sig8 * signature,
+ Dwarf_Unsigned * typeoffset,
+ Dwarf_Unsigned * next_cu_offset,
+ Dwarf_Error * error)
+{
+ return dwarf_next_cu_header_internal(dbg,
+ is_info,
+ cu_header_length,
+ version_stamp,
+ abbrev_offset,
+ address_size,
+ offset_size,
+ extension_size,
+ signature,
+ typeoffset,
+ next_cu_offset,
+ error);
+}
+static int
+dwarf_next_cu_header_internal(Dwarf_Debug dbg,
+ Dwarf_Bool is_info,
+ Dwarf_Unsigned * cu_header_length,
+ Dwarf_Half * version_stamp,
+ Dwarf_Unsigned * abbrev_offset,
+ Dwarf_Half * address_size,
+ Dwarf_Half * offset_size,
+ Dwarf_Half * extension_size,
+ Dwarf_Sig8 * signature,
+ Dwarf_Unsigned *typeoffset,
+ Dwarf_Unsigned * next_cu_offset,
+ Dwarf_Error * error)
+{
+ /* Offset for current and new CU. */
+ Dwarf_Unsigned new_offset = 0;
+
+ /* CU Context for current CU. */
+ Dwarf_CU_Context cu_context = 0;
+ Dwarf_Debug_InfoTypes dis = 0;
+ Dwarf_Unsigned section_size = 0;
+
+
+
+ /* ***** BEGIN CODE ***** */
+
+ if (dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+ dis = is_info? &dbg->de_info_reading: &dbg->de_types_reading;
+ /* Get offset into .debug_info of next CU. If dbg has no context,
+ this has to be the first one. */
+ if (dis->de_cu_context == NULL) {
+ Dwarf_Small *dataptr = is_info? dbg->de_debug_info.dss_data:
+ dbg->de_debug_types.dss_data;
+ new_offset = 0;
+ if (!dataptr) {
+ Dwarf_Error err2= 0;
+ int res = is_info?_dwarf_load_debug_info(dbg, &err2):
+ _dwarf_load_debug_types(dbg,&err2);
+
+ if (res != DW_DLV_OK) {
+ if(reloc_incomplete(err2)) {
+ /* We will assume all is ok, though it is not.
+ Relocation errors need not be fatal. */
+ char msg_buf[200];
+ snprintf(msg_buf,sizeof(msg_buf),
+ "Relocations did not complete successfully, but we are "
+ " ignoring error: %s",dwarf_errmsg(err2));
+ dwarf_insert_harmless_error(dbg,msg_buf);
+ res = DW_DLV_OK;
+ } else {
+ if( error) {
+ *error = err2;
+ }
+ return res;
+ }
+
+ }
+ }
+
+ } else {
+ new_offset = dis->de_cu_context->cc_debug_offset +
+ dis->de_cu_context->cc_length +
+ dis->de_cu_context->cc_length_size +
+ dis->de_cu_context->cc_extension_size;
+ }
+
+ /* Check that there is room in .debug_info beyond the new offset
+ for at least a new cu header. If not, return 0 to indicate end
+ of debug_info section, and reset de_cu_debug_info_offset to
+ enable looping back through the cu's. */
+ section_size = is_info? dbg->de_debug_info.dss_size:
+ dbg->de_debug_types.dss_size;
+ if ((new_offset + _dwarf_length_of_cu_header_simple(dbg,is_info)) >=
+ section_size) {
+ dis->de_cu_context = NULL;
+ return (DW_DLV_NO_ENTRY);
+ }
+
+ /* Check if this CU has been read before. */
+ cu_context = _dwarf_find_CU_Context(dbg, new_offset,is_info);
+
+ /* If not, make CU Context for it. */
+ if (cu_context == NULL) {
+ cu_context = _dwarf_make_CU_Context(dbg, new_offset,is_info, error);
+ if (cu_context == NULL) {
+ /* Error if CU Context could not be made. Since
+ _dwarf_make_CU_Context has already registered an error
+ we do not do that here: we let the lower error pass
+ thru. */
+ return (DW_DLV_ERROR);
+ }
+ }
+
+ dis->de_cu_context = cu_context;
+
+ if (cu_header_length != NULL) {
+ *cu_header_length = cu_context->cc_length;
+ }
+
+ if (version_stamp != NULL) {
+ *version_stamp = cu_context->cc_version_stamp;
+ }
+ if (abbrev_offset != NULL) {
+ *abbrev_offset = cu_context->cc_abbrev_offset;
+ }
+
+ if (address_size != NULL) {
+ *address_size = cu_context->cc_address_size;
+ }
+ if (offset_size != NULL) {
+ *offset_size = cu_context->cc_length_size;
+ }
+ if (extension_size != NULL) {
+ *extension_size = cu_context->cc_extension_size;
+ }
+ if(!is_info) {
+ if(signature) {
+ *signature = cu_context->cc_signature;
+ }
+ if(typeoffset) {
+ *typeoffset = cu_context->cc_typeoffset;
+ }
+ }
+
+ new_offset = new_offset + cu_context->cc_length +
+ cu_context->cc_length_size + cu_context->cc_extension_size;
+ *next_cu_offset = new_offset;
+ return (DW_DLV_OK);
+}
+
+static int
+dwarf_ptr_CU_offset(Dwarf_CU_Context cu_context,
+ Dwarf_Byte_Ptr di_ptr,
+ Dwarf_Bool is_info,
+ Dwarf_Off * cu_off)
+{
+ Dwarf_Debug dbg = cu_context->cc_dbg;
+ Dwarf_Small *dataptr = is_info? dbg->de_debug_info.dss_data:
+ dbg->de_debug_types.dss_data;
+ *cu_off = (di_ptr - dataptr);
+ return DW_DLV_OK;
+}
+#if 0
+/* Just for debug purposes */
+void print_sib_offset(Dwarf_Die sibling)
+{
+ Dwarf_Off sib_off;
+ Dwarf_Error error;
+ dwarf_dieoffset(sibling,&sib_off,&error);
+ fprintf(stderr," SIB OFF = 0x%" DW_PR_XZEROS DW_PR_DUx,sib_off);
+}
+void print_ptr_offset(Dwarf_CU_Context cu_context,Dwarf_Byte_Ptr di_ptr)
+{
+ Dwarf_Off ptr_off;
+ dwarf_ptr_CU_offset(cu_context,di_ptr,&ptr_off);
+ fprintf(stderr," PTR OFF = 0x%" DW_PR_XZEROS DW_PR_DUx,ptr_off);
+}
+#endif
+
+
+/* Validate the sibling DIE. This only makes sense to call
+ if the sibling's DIEs have been travsersed and
+ dwarf_child() called on each,
+ so that the last DIE dwarf_child saw was the last.
+ Essentially ensuring that (after such traversal) that we
+ are in the same place a sibling attribute would identify.
+ In case we return DW_DLV_ERROR, the global offset of the last
+ DIE traversed by dwarf_child is returned through *offset
+
+ It is essentially guaranteed that dbg->de_last_die
+ is a stale DIE pointer of a deallocated DIE when we get here.
+ It must not be used as a DIE pointer here,
+ just as a sort of anonymous pointer that we just check against
+ NULL.
+
+ There is a (subtle?) dependence on the fact that when we call this
+ the last dwarf_child() call would have been for this sibling.
+ Meaning that this works in a depth-first traversal even though there
+ is no stack of 'de_last_die' values.
+
+ The check for dbg->de_last_die just ensures sanity.
+
+ If one is switching between normal debug_frame and eh_frame
+ (traversing them in tandem, let us say) in a single
+ Dwarf_Debug this validator makes no sense.
+ It works if one processes a .debug_frame (entirely) and
+ then an eh_frame (or vice versa) though.
+ Use caution.
+*/
+int
+dwarf_validate_die_sibling(Dwarf_Die sibling,Dwarf_Off *offset)
+{
+ Dwarf_Debug dbg = 0;
+ Dwarf_Error *error = 0;
+ Dwarf_Debug_InfoTypes dis = 0;
+ CHECK_DIE(sibling, DW_DLV_ERROR);
+ dbg = sibling->di_cu_context->cc_dbg;
+
+ dis = sibling->di_is_info? &dbg->de_info_reading: &dbg->de_types_reading;
+
+ *offset = 0;
+ if (dis->de_last_die && dis->de_last_di_ptr) {
+ if (sibling->di_debug_ptr == dis->de_last_di_ptr) {
+ return (DW_DLV_OK);
+ }
+ }
+ /* Calculate global offset used for error reporting */
+ dwarf_ptr_CU_offset(sibling->di_cu_context,
+ dis->de_last_di_ptr,sibling->di_is_info,offset);
+ return (DW_DLV_ERROR);
+}
+
+/* This function does two slightly different things
+ depending on the input flag want_AT_sibling. If
+ this flag is true, it checks if the input die has
+ a DW_AT_sibling attribute. If it does it returns
+ a pointer to the start of the sibling die in the
+ .debug_info section. Otherwise it behaves the
+ same as the want_AT_sibling false case.
+
+ If the want_AT_sibling flag is false, it returns
+ a pointer to the immediately adjacent die in the
+ .debug_info section.
+
+ Die_info_end points to the end of the .debug_info
+ portion for the cu the die belongs to. It is used
+ to check that the search for the next die does not
+ cross the end of the current cu. Cu_info_start points
+ to the start of the .debug_info portion for the
+ current cu, and is used to add to the offset for
+ DW_AT_sibling attributes. Finally, has_die_child
+ is a pointer to a Dwarf_Bool that is set true if
+ the present die has children, false otherwise.
+ However, in case want_AT_child is true and the die
+ has a DW_AT_sibling attribute *has_die_child is set
+ false to indicate that the children are being skipped.
+
+ die_info_end points to the last byte+1 of the cu. */
+static Dwarf_Byte_Ptr
+_dwarf_next_die_info_ptr(Dwarf_Byte_Ptr die_info_ptr,
+ Dwarf_CU_Context cu_context,
+ Dwarf_Byte_Ptr die_info_end,
+ Dwarf_Byte_Ptr cu_info_start,
+ Dwarf_Bool want_AT_sibling,
+ Dwarf_Bool * has_die_child)
+{
+ Dwarf_Byte_Ptr info_ptr = 0;
+ Dwarf_Byte_Ptr abbrev_ptr = 0;
+ Dwarf_Word abbrev_code = 0;
+ Dwarf_Abbrev_List abbrev_list;
+ Dwarf_Half attr = 0;
+ Dwarf_Half attr_form = 0;
+ Dwarf_Unsigned offset = 0;
+ Dwarf_Word leb128_length = 0;
+ Dwarf_Unsigned utmp = 0;
+ Dwarf_Debug dbg = 0;
+
+ info_ptr = die_info_ptr;
+ DECODE_LEB128_UWORD(info_ptr, utmp);
+ abbrev_code = (Dwarf_Word) utmp;
+ if (abbrev_code == 0) {
+ return NULL;
+ }
+
+
+ abbrev_list = _dwarf_get_abbrev_for_code(cu_context, abbrev_code);
+ if (abbrev_list == NULL) {
+ return (NULL);
+ }
+ dbg = cu_context->cc_dbg;
+
+ *has_die_child = abbrev_list->ab_has_child;
+
+ abbrev_ptr = abbrev_list->ab_abbrev_ptr;
+ do {
+ Dwarf_Unsigned utmp2;
+
+ DECODE_LEB128_UWORD(abbrev_ptr, utmp2);
+ attr = (Dwarf_Half) utmp2;
+ DECODE_LEB128_UWORD(abbrev_ptr, utmp2);
+ attr_form = (Dwarf_Half) utmp2;
+ if (attr_form == DW_FORM_indirect) {
+ Dwarf_Unsigned utmp6;
+
+ /* DECODE_LEB128_UWORD updates info_ptr */
+ DECODE_LEB128_UWORD(info_ptr, utmp6);
+ attr_form = (Dwarf_Half) utmp6;
+
+ }
+
+ if (want_AT_sibling && attr == DW_AT_sibling) {
+ switch (attr_form) {
+ case DW_FORM_ref1:
+ offset = *(Dwarf_Small *) info_ptr;
+ break;
+ case DW_FORM_ref2:
+ /* READ_UNALIGNED does not update info_ptr */
+ READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
+ info_ptr, sizeof(Dwarf_Half));
+ break;
+ case DW_FORM_ref4:
+ READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
+ info_ptr, sizeof(Dwarf_ufixed));
+ break;
+ case DW_FORM_ref8:
+ READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
+ info_ptr, sizeof(Dwarf_Unsigned));
+ break;
+ case DW_FORM_ref_udata:
+ offset =
+ _dwarf_decode_u_leb128(info_ptr, &leb128_length);
+ break;
+ case DW_FORM_ref_addr:
+ /* Very unusual. The FORM is intended to refer to
+ a different CU, but a different CU cannot
+ be a sibling, can it?
+ We could ignore this and treat as if no DW_AT_sibling
+ present. Or derive the offset from it and if
+ it is in the same CU use it directly.
+ The offset here is *supposed* to be a global offset,
+ so adding cu_info_start is wrong to any offset
+ we find here unless cu_info_start
+ is zero! Lets pretend there is no DW_AT_sibling
+ attribute. */
+ goto no_sibling_attr;
+ default:
+ return (NULL);
+ }
+
+ /* Reset *has_die_child to indicate children skipped. */
+ *has_die_child = false;
+
+ /* A value beyond die_info_end indicates an error. Exactly
+ at die_info_end means 1-past-cu-end and simply means we
+ are at the end, do not return NULL. Higher level code
+ will detect that we are at the end. */
+ if (cu_info_start + offset > die_info_end) {
+ /* Error case, bad DWARF. */
+ return (NULL);
+ }
+ /* At or before end-of-cu */
+ return (cu_info_start + offset);
+ }
+
+ no_sibling_attr:
+ if (attr_form != 0) {
+ info_ptr += _dwarf_get_size_of_val(cu_context->cc_dbg,
+ attr_form,
+ cu_context->cc_address_size,
+ info_ptr,
+ cu_context->cc_length_size);
+ /* It is ok for info_ptr == die_info_end, as we will test
+ later before using a too-large info_ptr */
+ if (info_ptr > die_info_end) {
+ /* More than one-past-end indicates a bug somewhere,
+ likely bad dwarf generation. */
+ return (NULL);
+ }
+ }
+ } while (attr != 0 || attr_form != 0);
+ return (info_ptr);
+}
+
+/* Multiple TAGs are in fact compile units.
+ Allow them all.
+ Return non-zero if a CU tag.
+ Else return 0.
+*/
+static int
+is_cu_tag(int t)
+{
+ if(t == DW_TAG_compile_unit ||
+ t == DW_TAG_partial_unit ||
+ t == DW_TAG_imported_unit ||
+ t == DW_TAG_type_unit) {
+ return 1;
+ }
+ return 0;
+}
+
+/* Given a Dwarf_Debug dbg, and a Dwarf_Die die, it returns
+ a Dwarf_Die for the sibling of die. In case die is NULL,
+ it returns (thru ptr) a Dwarf_Die for the first die in the current
+ cu in dbg. Returns DW_DLV_ERROR on error.
+
+ It is assumed that every sibling chain including those with
+ only one element is terminated with a NULL die, except a
+ chain with only a NULL die.
+
+ The algorithm moves from one die to the adjacent one. It
+ returns when the depth of children it sees equals the number
+ of sibling chain terminations. A single count, child_depth
+ is used to track the depth of children and sibling terminations
+ encountered. Child_depth is incremented when a die has the
+ Has-Child flag set unless the child happens to be a NULL die.
+ Child_depth is decremented when a die has Has-Child false,
+ and the adjacent die is NULL. Algorithm returns when
+ child_depth is 0.
+
+ **NOTE: Do not modify input die, since it is used at the end. */
+int
+dwarf_siblingof(Dwarf_Debug dbg,
+ Dwarf_Die die,
+ Dwarf_Die * caller_ret_die, Dwarf_Error * error)
+{
+ Dwarf_Bool is_info = true;
+ return dwarf_siblingof_b(dbg,die,is_info,caller_ret_die,error);
+}
+/* This is the new form, October 2011. On calling with 'die' NULL,
+ we cannot tell if this is debug_info or debug_types, so
+ we must be informed!. */
+int
+dwarf_siblingof_b(Dwarf_Debug dbg,
+ Dwarf_Die die,
+ Dwarf_Bool is_info,
+ Dwarf_Die * caller_ret_die, Dwarf_Error * error)
+{
+ Dwarf_Die ret_die = 0;
+ Dwarf_Byte_Ptr die_info_ptr = 0;
+ Dwarf_Byte_Ptr cu_info_start = 0;
+
+ /* die_info_end points 1-past end of die (once set) */
+ Dwarf_Byte_Ptr die_info_end = 0;
+ Dwarf_Word abbrev_code = 0;
+ Dwarf_Unsigned utmp = 0;
+ /* Since die may be NULL, we rely on the input argument. */
+ Dwarf_Debug_InfoTypes dis = is_info? &dbg->de_info_reading:
+ &dbg->de_types_reading;
+ Dwarf_Small *dataptr = is_info? dbg->de_debug_info.dss_data:
+ dbg->de_debug_types.dss_data;
+
+
+
+ if (dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ if (die == NULL) {
+ /* Find root die of cu */
+ /* die_info_end is untouched here, need not be set in this
+ branch. */
+ Dwarf_Off off2;
+ Dwarf_CU_Context context=0;
+
+ /* If we've not loaded debug_info, de_cu_context will be NULL,
+ so no need to laod */
+
+ context = dis->de_cu_context;
+ if (context == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_DBG_NO_CU_CONTEXT);
+ return (DW_DLV_ERROR);
+ }
+
+ off2 = context->cc_debug_offset;
+ cu_info_start = dataptr + off2;
+ die_info_ptr = cu_info_start +
+ _dwarf_length_of_cu_header(dbg, off2,is_info);
+ die_info_end = cu_info_start + context->cc_length +
+ context->cc_length_size +
+ context->cc_extension_size;
+ } else {
+ /* Find sibling die. */
+ Dwarf_Bool has_child = false;
+ Dwarf_Sword child_depth = 0;
+ Dwarf_CU_Context context=0;
+
+ /* We cannot have a legal die unless debug_info was loaded, so
+ no need to load debug_info here. */
+ CHECK_DIE(die, DW_DLV_ERROR);
+
+ die_info_ptr = die->di_debug_ptr;
+ if (*die_info_ptr == 0) {
+ return (DW_DLV_NO_ENTRY);
+ }
+ context = die->di_cu_context;
+ cu_info_start = dataptr+ context->cc_debug_offset;
+ die_info_end = cu_info_start + context->cc_length +
+ context->cc_length_size +
+ context->cc_extension_size;
+
+ if ((*die_info_ptr) == 0) {
+ return (DW_DLV_NO_ENTRY);
+ }
+ child_depth = 0;
+ do {
+ die_info_ptr = _dwarf_next_die_info_ptr(die_info_ptr,
+ die->di_cu_context, die_info_end,
+ cu_info_start, true, &has_child);
+ if (die_info_ptr == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_NEXT_DIE_PTR_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ /* die_info_end is one past end. Do not read it!
+ A test for ``!= die_info_end'' would work as well,
+ but perhaps < reads more like the meaning. */
+ if(die_info_ptr < die_info_end) {
+ if ((*die_info_ptr) == 0 && has_child) {
+ die_info_ptr++;
+ has_child = false;
+ }
+ }
+
+ /* die_info_ptr can be one-past-end. */
+ if ((die_info_ptr == die_info_end) ||
+ ((*die_info_ptr) == 0)) {
+ for (; child_depth > 0 && *die_info_ptr == 0;
+ child_depth--, die_info_ptr++);
+ } else {
+ child_depth = has_child ? child_depth + 1 : child_depth;
+ }
+
+ } while (child_depth != 0);
+ }
+
+ /* die_info_ptr > die_info_end is really a bug (possibly in dwarf
+ generation)(but we are past end, no more DIEs here), whereas
+ die_info_ptr == die_info_end means 'one past end, no more DIEs
+ here'. */
+ if (die_info_ptr >= die_info_end) {
+ return (DW_DLV_NO_ENTRY);
+ }
+
+ if ((*die_info_ptr) == 0) {
+ return (DW_DLV_NO_ENTRY);
+ }
+
+ ret_die = (Dwarf_Die) _dwarf_get_alloc(dbg, DW_DLA_DIE, 1);
+ if (ret_die == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ ret_die->di_is_info = is_info;
+ ret_die->di_debug_ptr = die_info_ptr;
+ ret_die->di_cu_context =
+ die == NULL ? dis->de_cu_context : die->di_cu_context;
+
+ DECODE_LEB128_UWORD(die_info_ptr, utmp);
+ if (die_info_ptr > die_info_end) {
+ /* We managed to go past the end of the CU!.
+ Something is badly wrong. */
+ dwarf_dealloc(dbg, ret_die, DW_DLA_DIE);
+ _dwarf_error(dbg, error, DW_DLE_ABBREV_DECODE_ERROR);
+ return (DW_DLV_ERROR);
+ }
+ abbrev_code = (Dwarf_Word) utmp;
+ if (abbrev_code == 0) {
+ /* Zero means a null DIE */
+ dwarf_dealloc(dbg, ret_die, DW_DLA_DIE);
+ return (DW_DLV_NO_ENTRY);
+ }
+ ret_die->di_abbrev_code = abbrev_code;
+ ret_die->di_abbrev_list =
+ _dwarf_get_abbrev_for_code(ret_die->di_cu_context, abbrev_code);
+ if (ret_die->di_abbrev_list == NULL ) {
+ dwarf_dealloc(dbg, ret_die, DW_DLA_DIE);
+ _dwarf_error(dbg, error, DW_DLE_DIE_ABBREV_LIST_NULL);
+ return (DW_DLV_ERROR);
+ }
+ if (die == NULL && !is_cu_tag(ret_die->di_abbrev_list->ab_tag)) {
+ dwarf_dealloc(dbg, ret_die, DW_DLA_DIE);
+ _dwarf_error(dbg, error, DW_DLE_FIRST_DIE_NOT_CU);
+ return (DW_DLV_ERROR);
+ }
+
+ *caller_ret_die = ret_die;
+ return (DW_DLV_OK);
+}
+
+
+int
+dwarf_child(Dwarf_Die die,
+ Dwarf_Die * caller_ret_die, Dwarf_Error * error)
+{
+ Dwarf_Byte_Ptr die_info_ptr = 0;
+
+ /* die_info_end points one-past-end of die area. */
+ Dwarf_Byte_Ptr die_info_end = 0;
+ Dwarf_Die ret_die = 0;
+ Dwarf_Bool has_die_child = 0;
+ Dwarf_Debug dbg;
+ Dwarf_Word abbrev_code = 0;
+ Dwarf_Unsigned utmp = 0;
+ Dwarf_Small *dataptr = 0;
+ Dwarf_Debug_InfoTypes dis = 0;
+
+ CHECK_DIE(die, DW_DLV_ERROR);
+ dbg = die->di_cu_context->cc_dbg;
+ dis = die->di_is_info? &dbg->de_info_reading:
+ &dbg->de_types_reading;
+ die_info_ptr = die->di_debug_ptr;
+
+ dataptr = die->di_is_info? dbg->de_debug_info.dss_data:
+ dbg->de_debug_types.dss_data;
+
+
+ /* We are saving a DIE pointer here, but the pointer
+ will not be presumed live later, when it is tested. */
+ dis->de_last_die = die;
+ dis->de_last_di_ptr = die_info_ptr;
+
+ /* NULL die has no child. */
+ if ((*die_info_ptr) == 0)
+ return (DW_DLV_NO_ENTRY);
+
+ die_info_end = dataptr +
+ die->di_cu_context->cc_debug_offset +
+ die->di_cu_context->cc_length +
+ die->di_cu_context->cc_length_size +
+ die->di_cu_context->cc_extension_size;
+
+ die_info_ptr =
+ _dwarf_next_die_info_ptr(die_info_ptr, die->di_cu_context,
+ die_info_end, NULL, false,
+ &has_die_child);
+ if (die_info_ptr == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_NEXT_DIE_PTR_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ dis->de_last_di_ptr = die_info_ptr;
+
+ if (!has_die_child) {
+ /* Look for end of sibling chain. */
+ while ( dis->de_last_di_ptr < die_info_end) {
+ if (*dis->de_last_di_ptr) {
+ break;
+ }
+ ++dis->de_last_di_ptr;
+ }
+ return (DW_DLV_NO_ENTRY);
+ }
+
+ ret_die = (Dwarf_Die) _dwarf_get_alloc(dbg, DW_DLA_DIE, 1);
+ if (ret_die == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ ret_die->di_debug_ptr = die_info_ptr;
+ ret_die->di_cu_context = die->di_cu_context;
+ ret_die->di_is_info = die->di_is_info;
+
+ DECODE_LEB128_UWORD(die_info_ptr, utmp);
+ abbrev_code = (Dwarf_Word) utmp;
+
+ dis->de_last_di_ptr = die_info_ptr;
+
+ if (abbrev_code == 0) {
+ /* Look for end of sibling chain */
+ while ( dis->de_last_di_ptr < die_info_end) {
+ if (*dis->de_last_di_ptr) {
+ break;
+ }
+ ++dis->de_last_di_ptr;
+ }
+
+ /* We have arrived at a null DIE, at the end of a CU or the end
+ of a list of siblings. */
+ *caller_ret_die = 0;
+ dwarf_dealloc(dbg, ret_die, DW_DLA_DIE);
+ return DW_DLV_NO_ENTRY;
+ }
+ ret_die->di_abbrev_code = abbrev_code;
+ ret_die->di_abbrev_list =
+ _dwarf_get_abbrev_for_code(die->di_cu_context, abbrev_code);
+ if (ret_die->di_abbrev_list == NULL) {
+ dwarf_dealloc(dbg, ret_die, DW_DLA_DIE);
+ _dwarf_error(dbg, error, DW_DLE_DIE_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ *caller_ret_die = ret_die;
+ return (DW_DLV_OK);
+}
+
+/* Given a (global, not cu_relative) die offset, this returns
+ a pointer to a DIE thru *new_die.
+ It is up to the caller to do a
+ dwarf_dealloc(dbg,*new_die,DW_DLE_DIE);
+ The old form only works with debug_info.
+ The new _b form works with debug_info or debug_types.
+ */
+int
+dwarf_offdie(Dwarf_Debug dbg,
+ Dwarf_Off offset, Dwarf_Die * new_die, Dwarf_Error * error)
+{
+ Dwarf_Bool is_info = true;
+ return dwarf_offdie_b(dbg,offset,is_info,new_die,error);
+}
+
+int
+dwarf_offdie_b(Dwarf_Debug dbg,
+ Dwarf_Off offset, Dwarf_Bool is_info,
+ Dwarf_Die * new_die, Dwarf_Error * error)
+{
+ Dwarf_CU_Context cu_context = 0;
+ Dwarf_Off new_cu_offset = 0;
+ Dwarf_Die die = 0;
+ Dwarf_Byte_Ptr info_ptr = 0;
+ Dwarf_Unsigned abbrev_code = 0;
+ Dwarf_Unsigned utmp = 0;
+ Dwarf_Debug_InfoTypes dis = 0;
+
+
+ if (dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+ dis = is_info? &dbg->de_info_reading:
+ &dbg->de_types_reading;
+
+ cu_context = _dwarf_find_CU_Context(dbg, offset,is_info);
+ if (cu_context == NULL)
+ cu_context = _dwarf_find_offdie_CU_Context(dbg, offset,is_info);
+
+ if (cu_context == NULL) {
+ Dwarf_Unsigned section_size = is_info? dbg->de_debug_info.dss_size:
+ dbg->de_debug_types.dss_size;
+ int res = is_info?_dwarf_load_debug_info(dbg, error):
+ _dwarf_load_debug_types(dbg,error);
+
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ if (dis->de_offdie_cu_context_end != NULL) {
+ Dwarf_CU_Context lcu_context =
+ dis->de_offdie_cu_context_end;
+ new_cu_offset =
+ lcu_context->cc_debug_offset +
+ lcu_context->cc_length +
+ lcu_context->cc_length_size +
+ lcu_context->cc_extension_size;
+ }
+
+
+ do {
+ if ((new_cu_offset +
+ _dwarf_length_of_cu_header_simple(dbg,is_info)) >= section_size) {
+ _dwarf_error(dbg, error, DW_DLE_OFFSET_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ cu_context =
+ _dwarf_make_CU_Context(dbg, new_cu_offset,is_info, error);
+ if (cu_context == NULL) {
+ /* Error if CU Context could not be made. Since
+ _dwarf_make_CU_Context has already registered an
+ error we do not do that here: we let the lower error
+ pass thru. */
+
+ return (DW_DLV_ERROR);
+ }
+
+ if (dis->de_offdie_cu_context == NULL) {
+ dis->de_offdie_cu_context = cu_context;
+ dis->de_offdie_cu_context_end = cu_context;
+ } else {
+ dis->de_offdie_cu_context_end->cc_next = cu_context;
+ dis->de_offdie_cu_context_end = cu_context;
+ }
+
+ new_cu_offset = new_cu_offset + cu_context->cc_length +
+ cu_context->cc_length_size;
+
+ } while (offset >= new_cu_offset);
+ }
+
+ die = (Dwarf_Die) _dwarf_get_alloc(dbg, DW_DLA_DIE, 1);
+ if (die == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ die->di_cu_context = cu_context;
+ die->di_is_info = is_info;
+
+ {
+ Dwarf_Small *dataptr = is_info? dbg->de_debug_info.dss_data:
+ dbg->de_debug_types.dss_data;
+ info_ptr = dataptr + offset;
+ }
+ die->di_debug_ptr = info_ptr;
+ DECODE_LEB128_UWORD(info_ptr, utmp);
+ abbrev_code = utmp;
+ if (abbrev_code == 0) {
+ /* we are at a null DIE (or there is a bug). */
+ *new_die = 0;
+ dwarf_dealloc(dbg, die, DW_DLA_DIE);
+ return DW_DLV_NO_ENTRY;
+ }
+ die->di_abbrev_code = abbrev_code;
+ die->di_abbrev_list =
+ _dwarf_get_abbrev_for_code(cu_context, abbrev_code);
+ if (die->di_abbrev_list == NULL) {
+ dwarf_dealloc(dbg, die, DW_DLA_DIE);
+ _dwarf_error(dbg, error, DW_DLE_DIE_ABBREV_LIST_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ *new_die = die;
+ return (DW_DLV_OK);
+}
diff --git a/libdwarf/dwarf_die_deliv.h b/libdwarf/dwarf_die_deliv.h
new file mode 100644
index 0000000..0c4bf2a
--- /dev/null
+++ b/libdwarf/dwarf_die_deliv.h
@@ -0,0 +1,55 @@
+/*
+
+ Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2008-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+
+/*
+ This struct holds information about a abbreviation.
+ It is put in the hash table for abbreviations for
+ a compile-unit.
+*/
+struct Dwarf_Abbrev_List_s {
+ Dwarf_Unsigned ab_code;
+ Dwarf_Half ab_tag;
+ Dwarf_Half ab_has_child;
+
+ /* Points to start of attribute and form pairs in the .debug_abbrev
+ section for the abbrev. */
+ Dwarf_Byte_Ptr ab_abbrev_ptr;
+
+ struct Dwarf_Abbrev_List_s *ab_next;
+};
diff --git a/libdwarf/dwarf_elf_access.c b/libdwarf/dwarf_elf_access.c
new file mode 100644
index 0000000..4ca66ae
--- /dev/null
+++ b/libdwarf/dwarf_elf_access.c
@@ -0,0 +1,1027 @@
+/*
+ Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2008-2010 Arxan Technologies, Inc. All Rights Reserved.
+ Portions Copyright 2009-2011 David Anderson. All rights reserved.
+ Portions Copyright 2009-2010 Novell Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include "dwarf_elf_access.h"
+
+#ifdef HAVE_ELF_H
+#include <elf.h>
+#endif
+#ifdef HAVE_LIBELF_H
+#include <libelf.h>
+#else
+#ifdef HAVE_LIBELF_LIBELF_H
+#include <libelf/libelf.h>
+#endif
+#endif
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define FALSE 0
+#define TRUE 1
+
+#ifndef EM_MIPS
+/* This is the standard elf value EM_MIPS. */
+#define EM_MIPS 8
+#endif
+
+
+#ifdef HAVE_ELF64_GETEHDR
+extern Elf64_Ehdr *elf64_getehdr(Elf *);
+#endif
+#ifdef HAVE_ELF64_GETSHDR
+extern Elf64_Shdr *elf64_getshdr(Elf_Scn *);
+#endif
+#ifdef WORDS_BIGENDIAN
+#define WRITE_UNALIGNED(dbg,dest,source, srclength,len_out) \
+ { \
+ dbg->de_copy_word(dest, \
+ ((char *)source) +srclength-len_out, \
+ len_out) ; \
+ }
+
+
+#else /* LITTLE ENDIAN */
+
+#define WRITE_UNALIGNED(dbg,dest,source, srclength,len_out) \
+ { \
+ dbg->de_copy_word( (dest) , \
+ ((char *)source) , \
+ len_out) ; \
+ }
+#endif
+
+
+
+typedef struct {
+ dwarf_elf_handle elf;
+ int is_64bit;
+ Dwarf_Small length_size;
+ Dwarf_Small pointer_size;
+ Dwarf_Unsigned section_count;
+ Dwarf_Endianness endianness;
+ Dwarf_Small machine;
+ int libdwarf_owns_elf;
+ Elf32_Ehdr *ehdr32;
+
+#ifdef HAVE_ELF64_GETEHDR
+ Elf64_Ehdr *ehdr64;
+#endif
+ /* Elf symtab and its strtab. Initialized at first
+ call to do relocations, the actual data is in the Dwarf_Debug
+ struct, not allocated locally here. */
+ struct Dwarf_Section_s *symtab;
+ struct Dwarf_Section_s *strtab;
+
+} dwarf_elf_object_access_internals_t;
+
+struct Dwarf_Elf_Rela {
+ Dwarf_ufixed64 r_offset;
+ /*Dwarf_ufixed64 r_info; */
+ Dwarf_ufixed64 r_type;
+ Dwarf_ufixed64 r_symidx;
+ Dwarf_ufixed64 r_addend;
+};
+
+
+static int dwarf_elf_object_access_load_section(void* obj_in,
+ Dwarf_Half section_index,
+ Dwarf_Small** section_data,
+ int* error);
+
+/* dwarf_elf_object_access_internals_init() */
+static int
+dwarf_elf_object_access_internals_init(void* obj_in,
+ dwarf_elf_handle elf,
+ int* error)
+{
+ dwarf_elf_object_access_internals_t*obj =
+ (dwarf_elf_object_access_internals_t*)obj_in;
+ char *ehdr_ident = 0;
+ Dwarf_Half machine = 0;
+ obj->elf = elf;
+
+ if ((ehdr_ident = elf_getident(elf, NULL)) == NULL) {
+ *error = DW_DLE_ELF_GETIDENT_ERROR;
+ return DW_DLV_ERROR;
+ }
+
+ obj->is_64bit = (ehdr_ident[EI_CLASS] == ELFCLASS64);
+
+
+ if(ehdr_ident[EI_DATA] == ELFDATA2LSB){
+ obj->endianness = DW_OBJECT_LSB;
+ } else if(ehdr_ident[EI_DATA] == ELFDATA2MSB){
+ obj->endianness = DW_OBJECT_MSB;
+ }
+
+ if (obj->is_64bit) {
+#ifdef HAVE_ELF64_GETEHDR
+ obj->ehdr64 = elf64_getehdr(elf);
+ if (obj->ehdr64 == NULL) {
+ *error = DW_DLE_ELF_GETEHDR_ERROR;
+ return DW_DLV_ERROR;
+ }
+ obj->section_count = obj->ehdr64->e_shnum;
+ machine = obj->ehdr64->e_machine;
+ obj->machine = machine;
+#else
+ *error = DW_DLE_NO_ELF64_SUPPORT;
+ return DW_DLV_ERROR;
+#endif
+ } else {
+ obj->ehdr32 = elf32_getehdr(elf);
+ if (obj->ehdr32 == NULL) {
+ *error = DW_DLE_ELF_GETEHDR_ERROR;
+ return DW_DLV_ERROR;
+ }
+ obj->section_count = obj->ehdr32->e_shnum;
+ machine = obj->ehdr32->e_machine;
+ obj->machine = machine;
+ }
+
+ /* The following length_size is Not Too Significant. Only used
+ one calculation, and an approximate one at that. */
+ obj->length_size = obj->is_64bit ? 8 : 4;
+ obj->pointer_size = obj->is_64bit ? 8 : 4;
+
+ if (obj->is_64bit && machine != EM_MIPS) {
+ /* MIPS/IRIX makes pointer size and length size 8 for -64.
+ Other platforms make length 4 always. */
+ /* 4 here supports 32bit-offset dwarf2, as emitted by cygnus
+ tools, and the dwarfv2.1 64bit extension setting.
+ This is not the same as the size-of-an-offset, which
+ is 4 in 32bit dwarf and 8 in 64bit dwarf. */
+ obj->length_size = 4;
+ }
+ return DW_DLV_OK;
+}
+
+/* dwarf_elf_object_access_get_byte_order */
+static
+Dwarf_Endianness
+dwarf_elf_object_access_get_byte_order(void* obj_in)
+{
+ dwarf_elf_object_access_internals_t*obj =
+ (dwarf_elf_object_access_internals_t*)obj_in;
+ return obj->endianness;
+}
+
+/* dwarf_elf_object_access_get_section_count() */
+static
+Dwarf_Unsigned
+dwarf_elf_object_access_get_section_count(void * obj_in)
+{
+ dwarf_elf_object_access_internals_t*obj =
+ (dwarf_elf_object_access_internals_t*)obj_in;
+ return obj->section_count;
+}
+
+
+/* dwarf_elf_object_access_get_section()
+
+ If writing a function vaguely like this for a non-elf object,
+ be sure that when section-index is passed in as zero that
+ you set the fields in *ret_scn to reflect an empty section
+ with an empty string as the section name. Adjust your
+ section indexes of your non-elf-reading-code
+ for all the necessary functions in Dwarf_Obj_Access_Methods_s
+ accordingly.
+*/
+static
+int
+dwarf_elf_object_access_get_section_info(
+ void* obj_in,
+ Dwarf_Half section_index,
+ Dwarf_Obj_Access_Section* ret_scn,
+ int* error)
+{
+ dwarf_elf_object_access_internals_t*obj =
+ (dwarf_elf_object_access_internals_t*)obj_in;
+
+ Elf32_Shdr *shdr32 = 0;
+
+#ifdef HAVE_ELF64_GETSHDR
+ Elf64_Shdr *shdr64 = 0;
+#endif
+ Elf_Scn *scn = 0;
+
+
+ scn = elf_getscn(obj->elf, section_index);
+ if (scn == NULL) {
+ *error = DW_DLE_MDE;
+ return DW_DLV_ERROR;
+ }
+ if (obj->is_64bit) {
+#ifdef HAVE_ELF64_GETSHDR
+ shdr64 = elf64_getshdr(scn);
+ if (shdr64 == NULL) {
+ *error = DW_DLE_ELF_GETSHDR_ERROR;
+ return DW_DLV_ERROR;
+ }
+
+ ret_scn->size = shdr64->sh_size;
+ ret_scn->addr = shdr64->sh_addr;
+ ret_scn->link = shdr64->sh_link;
+ ret_scn->entrysize = shdr64->sh_entsize;
+ ret_scn->name = elf_strptr(obj->elf, obj->ehdr64->e_shstrndx,
+ shdr64->sh_name);
+ if(ret_scn->name == NULL) {
+ *error = DW_DLE_ELF_STRPTR_ERROR;
+ return DW_DLV_ERROR;
+ }
+ return DW_DLV_OK;
+#else
+ *error = DW_DLE_MISSING_ELF64_SUPPORT;
+ return DW_DLV_ERROR;
+#endif /* HAVE_ELF64_GETSHDR */
+ }
+ if ((shdr32 = elf32_getshdr(scn)) == NULL) {
+ *error = DW_DLE_ELF_GETSHDR_ERROR;
+ return DW_DLV_ERROR;
+ }
+
+ ret_scn->size = shdr32->sh_size;
+ ret_scn->addr = shdr32->sh_addr;
+ ret_scn->link = shdr32->sh_link;
+ ret_scn->entrysize = shdr32->sh_entsize;
+ ret_scn->name = elf_strptr(obj->elf, obj->ehdr32->e_shstrndx,
+ shdr32->sh_name);
+ if (ret_scn->name == NULL) {
+ *error = DW_DLE_ELF_STRPTR_ERROR;
+ return DW_DLV_ERROR;
+ }
+ return DW_DLV_OK;
+}
+
+/* dwarf_elf_object_access_get_length_size */
+static
+Dwarf_Small
+dwarf_elf_object_access_get_length_size(void* obj_in)
+{
+ dwarf_elf_object_access_internals_t*obj =
+ (dwarf_elf_object_access_internals_t*)obj_in;
+ return obj->length_size;
+}
+
+/* dwarf_elf_object_access_get_pointer_size */
+static
+Dwarf_Small
+dwarf_elf_object_access_get_pointer_size(void* obj_in)
+{
+ dwarf_elf_object_access_internals_t*obj =
+ (dwarf_elf_object_access_internals_t*)obj_in;
+ return obj->pointer_size;
+}
+
+#define MATCH_REL_SEC(i_,s_,r_) \
+if(i_ == s_.dss_index) { \
+ *r_ = &s_; \
+ return DW_DLV_OK; \
+}
+
+static int
+find_section_to_relocate(Dwarf_Debug dbg,Dwarf_Half section_index,
+ struct Dwarf_Section_s **relocatablesec, int *error)
+{
+ MATCH_REL_SEC(section_index,dbg->de_debug_info,relocatablesec);
+ MATCH_REL_SEC(section_index,dbg->de_debug_abbrev,relocatablesec);
+ MATCH_REL_SEC(section_index,dbg->de_debug_line,relocatablesec);
+ MATCH_REL_SEC(section_index,dbg->de_debug_loc,relocatablesec);
+ MATCH_REL_SEC(section_index,dbg->de_debug_aranges,relocatablesec);
+ MATCH_REL_SEC(section_index,dbg->de_debug_macinfo,relocatablesec);
+ MATCH_REL_SEC(section_index,dbg->de_debug_pubnames,relocatablesec);
+ MATCH_REL_SEC(section_index,dbg->de_debug_ranges,relocatablesec);
+ MATCH_REL_SEC(section_index,dbg->de_debug_frame,relocatablesec);
+ MATCH_REL_SEC(section_index,dbg->de_debug_frame_eh_gnu,relocatablesec);
+ MATCH_REL_SEC(section_index,dbg->de_debug_pubtypes,relocatablesec);
+ MATCH_REL_SEC(section_index,dbg->de_debug_funcnames,relocatablesec);
+ MATCH_REL_SEC(section_index,dbg->de_debug_typenames,relocatablesec);
+ MATCH_REL_SEC(section_index,dbg->de_debug_varnames,relocatablesec);
+ MATCH_REL_SEC(section_index,dbg->de_debug_weaknames,relocatablesec);
+ MATCH_REL_SEC(section_index,dbg->de_debug_types,relocatablesec);
+ /* dbg-> de_debug_str,syms); */
+ /* de_elf_symtab,syms); */
+ /* de_elf_strtab,syms); */
+ *error = DW_DLE_RELOC_SECTION_MISMATCH;
+ return DW_DLV_ERROR;
+
+}
+#undef MATCH_REL_SEC
+
+static void
+get_rela_elf32(Dwarf_Small *data, unsigned int i,
+ int endianness,
+ int machine,
+ struct Dwarf_Elf_Rela *relap)
+{
+ Elf32_Rela *relp = (Elf32_Rela*)(data + (i * sizeof(Elf32_Rela)));
+ relap->r_offset = relp->r_offset;
+ /*
+ relap->r_info = relp->r_info;
+ */
+ relap->r_type = ELF32_R_TYPE(relp->r_info);
+ relap->r_symidx = ELF32_R_SYM(relp->r_info);
+ relap->r_addend = relp->r_addend;
+}
+
+static void
+get_rela_elf64(Dwarf_Small *data, unsigned int i,
+ int endianness,
+ int machine,
+ struct Dwarf_Elf_Rela *relap)
+{
+#ifdef HAVE_ELF64_RELA
+ Elf64_Rela * relp = (Elf64_Rela*)(data + (i * sizeof(Elf64_Rela)));
+ relap->r_offset = relp->r_offset;
+ /*
+ relap->r_info = relp->r_info;
+ */
+#define ELF64MIPS_REL_SYM(i) ((i) & 0xffffffff)
+#define ELF64MIPS_REL_TYPE(i) ((i >> 56) &0xff)
+ if(machine == EM_MIPS && endianness == DW_OBJECT_LSB ){
+ /* This is really wierd. Treat this very specially.
+ The Elf64 LE MIPS object used for
+ testing (that has rela) wants the
+ values as sym ssym type3 type2 type, treating
+ each value as independent value. But libelf xlate
+ treats it as something else so we fudge here.
+ It is unclear
+ how to precisely characterize where these relocations
+ were used.
+ SGI MIPS on IRIX never used .rela relocations.
+ The BE 64bit elf MIPS test object with rela uses traditional
+ elf relocation layouts, not this special case. */
+ /* We ignore the special TYPE2 and TYPE3, they should be
+ value R_MIPS_NONE in rela. */
+ relap->r_type = ELF64MIPS_REL_TYPE(relp->r_info);
+ relap->r_symidx = ELF64MIPS_REL_SYM(relp->r_info);
+#undef MIPS64SYM
+#undef MIPS64TYPE
+ } else
+ {
+ relap->r_type = ELF64_R_TYPE(relp->r_info);
+ relap->r_symidx = ELF64_R_SYM(relp->r_info);
+ }
+ relap->r_addend = relp->r_addend;
+#endif
+}
+
+static void
+get_relocations_array(Dwarf_Bool is_64bit,
+ int endianness,
+ int machine,
+ Dwarf_Small *data,
+ unsigned int num_relocations,
+ struct Dwarf_Elf_Rela *relap)
+{
+ unsigned int i = 0;
+ void (*get_relocations)(Dwarf_Small *data, unsigned int i,
+ int endianness,
+ int machine,
+ struct Dwarf_Elf_Rela *relap);
+
+ /* Handle 32/64 bit issue */
+ if (is_64bit) {
+ get_relocations = get_rela_elf64;
+ } else {
+ get_relocations = get_rela_elf32;
+ }
+
+ for (i=0; i < num_relocations; i++) {
+ get_relocations(data, i,endianness,machine,
+ &(relap[i]));
+ }
+
+}
+
+static int
+get_relocation_entries(Dwarf_Bool is_64bit,
+ int endianness,
+ int machine,
+ Dwarf_Small *relocation_section,
+ Dwarf_Unsigned relocation_section_size,
+ Dwarf_Unsigned relocation_section_entrysize,
+ struct Dwarf_Elf_Rela **relas,
+ unsigned int *nrelas,
+ int *error)
+{
+ unsigned int relocation_size = 0;
+
+ if (is_64bit) {
+#ifdef HAVE_ELF64_RELA
+ relocation_size = sizeof(Elf64_Rela);
+#else
+ *error = DW_DLE_MISSING_ELF64_SUPPORT;
+ return DW_DLV_ERROR;
+#endif
+ } else {
+ relocation_size = sizeof(Elf32_Rela);
+ }
+ if( relocation_size != relocation_section_entrysize) {
+ /* Means our struct definition does not match the
+ real object. */
+ *error = DW_DLE_RELOC_SECTION_LENGTH_ODD;
+ return DW_DLV_ERROR;
+ }
+
+ if (relocation_section == NULL) {
+ *error = DW_DLE_RELOC_SECTION_PTR_NULL;
+ return(DW_DLV_ERROR);
+ }
+
+ if ((relocation_section_size != 0)) {
+ size_t bytescount = 0;
+ if(relocation_section_size%relocation_size) {
+ *error = DW_DLE_RELOC_SECTION_LENGTH_ODD;
+ return DW_DLV_ERROR;
+ }
+ *nrelas = relocation_section_size/relocation_size;
+ bytescount = (*nrelas) * sizeof(struct Dwarf_Elf_Rela);
+ *relas = malloc(bytescount);
+ if (!*relas) {
+ *error = DW_DLE_MAF;
+ return(DW_DLV_ERROR);
+ }
+ memset(*relas,0,bytescount);
+ get_relocations_array(is_64bit,endianness,machine,
+ relocation_section,
+ *nrelas, *relas);
+ }
+ return(DW_DLV_OK);
+}
+
+/* We have a EM_QUALCOMM_DSP6 relocatable object
+ test case in dwarf regression tests, atefail/ig_server.
+ Values for QUALCOMM were derived from this executable.
+*/
+
+#define EM_QUALCOMM_DSP6 0xa4
+#define QUALCOMM_REL32 6
+
+static Dwarf_Bool
+is_32bit_abs_reloc(unsigned int type, Dwarf_Half machine)
+{
+ Dwarf_Bool r = 0;
+ switch (machine) {
+#if defined(EM_MIPS) && defined (R_MIPS_32)
+ case EM_MIPS:
+ r = (type == R_MIPS_32);
+ break;
+#endif
+#if defined(EM_SPARC32PLUS) && defined (R_SPARC_UA32)
+ case EM_SPARC32PLUS:
+ r = (type == R_SPARC_UA32);
+ break;
+#endif
+#if defined(EM_SPARCV9) && defined (R_SPARC_UA32)
+ case EM_SPARCV9:
+ r = (type == R_SPARC_UA32);
+ break;
+#endif
+#if defined(EM_SPARC) && defined (R_SPARC_UA32)
+ case EM_SPARC:
+ r = (type == R_SPARC_UA32);
+ break;
+#endif
+#if defined(EM_386) && defined (R_386_32)
+ case EM_386:
+ r = (type == R_386_32);
+ break;
+#endif
+#if defined(EM_IA_64) && defined (R_IA64_SECREL32LSB)
+ case EM_IA_64:
+ r = (type == R_IA64_SECREL32LSB);
+ break;
+#endif
+#if defined(EM_PPC64) && defined (R_PPC64_ADDR32)
+ case EM_PPC64:
+ r = (type == R_PPC64_ADDR32);
+ break;
+#endif
+#if defined(EM_PPC) && defined (R_PPC_ADDR32)
+ case EM_PPC:
+ r = (type == R_PPC_ADDR32);
+ break;
+#endif
+#if defined(EM_S390) && defined (R_390_32)
+ case EM_S390:
+ r = (type == R_390_32);
+ break;
+#endif
+#if defined(EM_X86_64) && defined (R_X86_64_32)
+ case EM_X86_64:
+ r = (type == R_X86_64_32);
+ break;
+#endif
+ case EM_QUALCOMM_DSP6:
+ r = (type == QUALCOMM_REL32);
+ break;
+ }
+ return r;
+}
+
+static Dwarf_Bool
+is_64bit_abs_reloc(unsigned int type, Dwarf_Half machine)
+{
+ Dwarf_Bool r = 0;
+ switch (machine) {
+#if defined(EM_MIPS) && defined (R_MIPS_64)
+ case EM_MIPS:
+ r = (type == R_MIPS_64);
+ break;
+#endif
+#if defined(EM_SPARC32PLUS) && defined (R_SPARC_UA64)
+ case EM_SPARC32PLUS:
+ r = (type == R_SPARC_UA64);
+ break;
+#endif
+#if defined(EM_SPARCV9) && defined (R_SPARC_UA64)
+ case EM_SPARCV9:
+ r = (type == R_SPARC_UA64);
+ break;
+#endif
+#if defined(EM_SPARC) && defined (R_SPARC_UA64)
+ case EM_SPARC:
+ r = (type == R_SPARC_UA64);
+ break;
+#endif
+#if defined(EM_IA_64) && defined (R_IA64_SECREL32LSB)
+ case EM_IA_64:
+ r = (type == R_IA64_DIR64LSB);
+ break;
+#endif
+#if defined(EM_PPC64) && defined (R_PPC64_ADDR64)
+ case EM_PPC64:
+ r = (type == R_PPC64_ADDR64);
+ break;
+#endif
+#if defined(EM_S390) && defined (R_390_64)
+ case EM_S390:
+ r = (type == R_390_64);
+ break;
+#endif
+#if defined(EM_X86_64) && defined (R_X86_64_64)
+ case EM_X86_64:
+ r = (type == R_X86_64_64);
+ break;
+#endif
+ }
+ return r;
+}
+
+
+/* Returns DW_DLV_OK if it works, else DW_DLV_ERROR.
+ The caller may decide to ignre the errors or report them. */
+static int
+update_entry(Dwarf_Debug dbg,
+ Dwarf_Bool is_64bit, Dwarf_Endianness endianess,
+ Dwarf_Half machine, struct Dwarf_Elf_Rela *rela,
+ Dwarf_Small *target_section,
+ Dwarf_Small *symtab_section_data,
+ Dwarf_Unsigned symtab_section_size,
+ Dwarf_Unsigned symtab_section_entrysize,
+ int *error)
+{
+ unsigned int type = 0;
+ unsigned int sym_idx = 0;
+#ifdef HAVE_ELF64_SYM
+ Elf64_Sym sym_buf;
+ Elf64_Sym *sym = 0;
+#else
+ Elf32_Sym sym_buf;
+ Elf32_Sym *sym = 0;
+#endif
+ Elf32_Sym *sym32 = 0;
+ Dwarf_ufixed64 offset = 0;
+ Dwarf_sfixed64 addend = 0;
+ Dwarf_Unsigned reloc_size = 0;
+ Dwarf_Unsigned symtab_entry_count = 0;
+
+ if( symtab_section_entrysize == 0) {
+ *error = DW_DLE_SYMTAB_SECTION_ENTRYSIZE_ZERO;
+ return DW_DLV_ERROR;
+ }
+ symtab_entry_count = symtab_section_size/symtab_section_entrysize;
+
+ /* Dwarf_Elf_Rela dereferencing */
+ offset = rela->r_offset;
+ addend = rela->r_addend;
+ type = rela->r_type;
+ sym_idx = rela->r_symidx;
+ if (sym_idx >= symtab_entry_count) {
+ *error = DW_DLE_RELOC_SECTION_SYMBOL_INDEX_BAD;
+ return DW_DLV_ERROR;
+ }
+
+
+
+ if (is_64bit) {
+#ifdef HAVE_ELF64_SYM
+ sym = &((Elf64_Sym*)symtab_section_data)[sym_idx];
+#endif
+ } else {
+ sym32 = &((Elf32_Sym*)symtab_section_data)[sym_idx];
+
+ /* Convert Elf32_Sym struct to Elf64_Sym struct. We point at
+ an Elf64_Sym local variable (sym_buf) to allow us to use the
+ same pointer (sym) for both 32-bit and 64-bit instances. */
+ sym = &sym_buf;
+ sym->st_name = sym32->st_name;
+ sym->st_info = sym32->st_info;
+ sym->st_other = sym32->st_other;
+ sym->st_shndx = sym32->st_shndx;
+ sym->st_value = sym32->st_value;
+ sym->st_size = sym32->st_size;
+ }
+
+ /* Determine relocation size */
+ if (is_32bit_abs_reloc(type, machine)) {
+ reloc_size = 4;
+ } else if (is_64bit_abs_reloc(type, machine)) {
+ reloc_size = 8;
+ } else {
+ *error = DW_DLE_RELOC_SECTION_RELOC_TARGET_SIZE_UNKNOWN;
+ return DW_DLV_ERROR;
+ }
+
+
+ {
+ /* Assuming we do not need to do a READ_UNALIGNED here
+ at target_section + offset and add its value to
+ outval. Some ABIs say no read (for example MIPS),
+ but if some do then which ones? */
+ Dwarf_Unsigned outval = sym->st_value + addend;
+ WRITE_UNALIGNED(dbg,target_section + offset,
+ &outval,sizeof(outval),reloc_size);
+ }
+ return DW_DLV_OK;
+}
+
+
+
+/* Somewhat arbitrarily, we attempt to apply all the relocations we can
+ and still notify the caller of at least one error if we found
+ any errors. */
+static int
+apply_rela_entries(Dwarf_Debug dbg,
+ Dwarf_Bool is_64bit,
+ Dwarf_Endianness endianess,
+ Dwarf_Half machine,
+ Dwarf_Small *target_section,
+ Dwarf_Small *symtab_section,
+ Dwarf_Unsigned symtab_section_size,
+ Dwarf_Unsigned symtab_section_entrysize,
+ struct Dwarf_Elf_Rela *relas, unsigned int nrelas,
+ int *error)
+{
+ int return_res = DW_DLV_OK;
+ if ((target_section != NULL) && (relas != NULL)) {
+ unsigned int i;
+ if( symtab_section_entrysize == 0) {
+ *error = DW_DLE_SYMTAB_SECTION_ENTRYSIZE_ZERO;
+ return DW_DLV_ERROR;
+ }
+ if(symtab_section_size%symtab_section_entrysize) {
+ *error = DW_DLE_SYMTAB_SECTION_LENGTH_ODD;
+ return DW_DLV_ERROR;
+ }
+ for (i = 0; i < nrelas; i++) {
+ int res = update_entry(dbg, is_64bit,
+ endianess,
+ machine,
+ &(relas)[i],
+ target_section,
+ symtab_section,
+ symtab_section_size,
+ symtab_section_entrysize,
+ error);
+ if (res != DW_DLV_OK) {
+ return_res = res;
+ }
+ }
+ }
+ return return_res;
+}
+
+
+static int
+loop_through_relocations(
+ Dwarf_Debug dbg,
+ dwarf_elf_object_access_internals_t* obj,
+ struct Dwarf_Section_s *relocatablesec,
+ int *error)
+{
+ Dwarf_Small *target_section = 0;
+ Dwarf_Small *symtab_section = obj->symtab->dss_data;
+ Dwarf_Unsigned symtab_section_entrysize = obj->symtab->dss_entrysize;
+ Dwarf_Unsigned symtab_section_size = obj->symtab->dss_size;
+ Dwarf_Small *relocation_section = relocatablesec->dss_reloc_data;
+ Dwarf_Unsigned relocation_section_size =
+ relocatablesec->dss_reloc_size;
+ Dwarf_Unsigned relocation_section_entrysize = relocatablesec->dss_reloc_entrysize;
+
+ int ret = DW_DLV_ERROR;
+ struct Dwarf_Elf_Rela *relas = 0;
+ unsigned int nrelas = 0;
+ Dwarf_Small *mspace = 0;
+
+ ret = get_relocation_entries(obj->is_64bit,
+ obj->endianness,
+ obj->machine,
+ relocation_section,
+ relocation_section_size,
+ relocation_section_entrysize,
+ &relas, &nrelas, error);
+ if(ret != DW_DLV_OK) {
+ free(relas);
+ return ret;
+ }
+
+ /* Some systems read Elf in read-only memory via mmap or the like.
+ So the only safe thing is to copy the current data into
+ malloc space and refer to the malloc space instead of the
+ space returned by the elf library */
+ mspace = malloc(relocatablesec->dss_size);
+ if(!mspace) {
+ *error = DW_DLE_RELOC_SECTION_MALLOC_FAIL;
+ return DW_DLV_ERROR;
+ }
+ memcpy(mspace,relocatablesec->dss_data,relocatablesec->dss_size);
+ relocatablesec->dss_data = mspace;
+ target_section = relocatablesec->dss_data;
+ relocatablesec->dss_data_was_malloc = 1;
+
+ ret = apply_rela_entries(
+ dbg,
+ obj->is_64bit,
+ obj->endianness, obj->machine,
+ target_section,
+ symtab_section,
+ symtab_section_size,
+ symtab_section_entrysize,
+ relas, nrelas, error);
+ free(relas);
+ return ret;
+}
+
+/* Find the section data in dbg and find all the relevant
+ sections. Then do relocations.
+*/
+static int
+dwarf_elf_object_relocate_a_section(void* obj_in,
+ Dwarf_Half section_index,
+ Dwarf_Debug dbg,
+ int* error)
+{
+ int res = DW_DLV_ERROR;
+ dwarf_elf_object_access_internals_t*obj = 0;
+ struct Dwarf_Section_s * relocatablesec = 0;
+ if (section_index == 0) {
+ return DW_DLV_NO_ENTRY;
+ }
+ obj = (dwarf_elf_object_access_internals_t*)obj_in;
+
+ /* The section to relocate must already be loaded into memory. */
+ res = find_section_to_relocate(dbg, section_index,&relocatablesec,error);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+
+ /* Sun and possibly others do not always set sh_link in .debug_* sections.
+ So we cannot do full consistency checks. */
+ if(relocatablesec->dss_reloc_index == 0 ) {
+ /* Something is wrong. */
+ *error = DW_DLE_RELOC_SECTION_MISSING_INDEX;
+ return DW_DLV_ERROR;
+ }
+ /* Now load the relocations themselves. */
+ res = dwarf_elf_object_access_load_section(obj_in,
+ relocatablesec->dss_reloc_index,
+ &relocatablesec->dss_reloc_data, error);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+
+ /* Now get the symtab. */
+ if (!obj->symtab) {
+ obj->symtab = &dbg->de_elf_symtab;
+ obj->strtab = &dbg->de_elf_strtab;
+ }
+ if( obj->symtab->dss_index != relocatablesec->dss_reloc_link) {
+ /* Something is wrong. */
+ *error = DW_DLE_RELOC_MISMATCH_RELOC_INDEX;
+ return DW_DLV_ERROR;
+ }
+ if( obj->strtab->dss_index != obj->symtab->dss_link) {
+ /* Something is wrong. */
+ *error = DW_DLE_RELOC_MISMATCH_STRTAB_INDEX;
+ return DW_DLV_ERROR;
+ }
+ if(!obj->symtab->dss_data) {
+ /* Now load the symtab */
+ res = dwarf_elf_object_access_load_section(obj_in,
+ obj->symtab->dss_index,
+ &obj->symtab->dss_data, error);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ }
+ if(! obj->strtab->dss_data) {
+ /* Now load the strtab */
+ res = dwarf_elf_object_access_load_section(obj_in,
+ obj->strtab->dss_index,
+ &obj->strtab->dss_data,error);
+ if(res != DW_DLV_OK){
+ return res;
+ }
+ }
+
+ /* We have all the data we need in memory. */
+ res = loop_through_relocations(dbg,obj,relocatablesec,error);
+
+ return res;
+}
+
+/* dwarf_elf_object_access_load_section */
+static int
+dwarf_elf_object_access_load_section(void* obj_in,
+ Dwarf_Half section_index,
+ Dwarf_Small** section_data,
+ int* error)
+{
+ dwarf_elf_object_access_internals_t*obj =
+ (dwarf_elf_object_access_internals_t*)obj_in;
+ if (section_index == 0) {
+ return DW_DLV_NO_ENTRY;
+ }
+
+ {
+ Elf_Scn *scn = 0;
+ Elf_Data *data = 0;
+
+ scn = elf_getscn(obj->elf, section_index);
+ if (scn == NULL) {
+ *error = DW_DLE_MDE;
+ return DW_DLV_ERROR;
+ }
+
+ /* When using libelf as a producer, section data may be stored
+ in multiple buffers. In libdwarf however, we only use libelf
+ as a consumer (there is a dwarf producer API, but it doesn't
+ use libelf). Because of this, this single call to elf_getdata
+ will retrieve the entire section in a single contiguous
+ buffer. */
+ data = elf_getdata(scn, NULL);
+ if (data == NULL) {
+ *error = DW_DLE_MDE;
+ return DW_DLV_ERROR;
+ }
+ *section_data = data->d_buf;
+ }
+ return DW_DLV_OK;
+}
+
+
+/* dwarf_elf_access method table. */
+static const struct Dwarf_Obj_Access_Methods_s dwarf_elf_object_access_methods =
+{
+ dwarf_elf_object_access_get_section_info,
+ dwarf_elf_object_access_get_byte_order,
+ dwarf_elf_object_access_get_length_size,
+ dwarf_elf_object_access_get_pointer_size,
+ dwarf_elf_object_access_get_section_count,
+ dwarf_elf_object_access_load_section,
+ dwarf_elf_object_relocate_a_section
+};
+
+
+/* Interface for the ELF object file implementation. */
+int
+dwarf_elf_object_access_init(dwarf_elf_handle elf,
+ int libdwarf_owns_elf,
+ Dwarf_Obj_Access_Interface** ret_obj,
+ int *err)
+{
+ int res = 0;
+ dwarf_elf_object_access_internals_t *internals = 0;
+ Dwarf_Obj_Access_Interface *intfc = 0;
+
+ internals = malloc(sizeof(dwarf_elf_object_access_internals_t));
+ if(!internals) {
+ /* Impossible case, we hope. Give up. */
+ return DW_DLV_ERROR;
+ }
+ memset(internals,0,sizeof(*internals));
+ res = dwarf_elf_object_access_internals_init(internals, elf, err);
+ if(res != DW_DLV_OK){
+ free(internals);
+ return DW_DLV_ERROR;
+ }
+ internals->libdwarf_owns_elf = libdwarf_owns_elf;
+
+ intfc = malloc(sizeof(Dwarf_Obj_Access_Interface));
+ if(!intfc) {
+ /* Impossible case, we hope. Give up. */
+ free(internals);
+ return DW_DLV_ERROR;
+ }
+ /* Initialize the interface struct */
+ intfc->object = internals;
+ intfc->methods = &dwarf_elf_object_access_methods;
+
+ *ret_obj = intfc;
+ return DW_DLV_OK;
+}
+
+
+
+/* Clean up the Dwarf_Obj_Access_Interface returned by elf_access_init. */
+void
+dwarf_elf_object_access_finish(Dwarf_Obj_Access_Interface* obj)
+{
+ if(!obj) {
+ return;
+ }
+ if(obj->object) {
+ dwarf_elf_object_access_internals_t *internals =
+ (dwarf_elf_object_access_internals_t *)obj->object;
+ if(internals->libdwarf_owns_elf){
+ elf_end(internals->elf);
+ }
+ }
+ free(obj->object);
+ free(obj);
+}
+
+/* This function returns the Elf * pointer
+ associated with a Dwarf_Debug.
+
+ This function only makes sense if ELF is implied. */
+int
+dwarf_get_elf(Dwarf_Debug dbg, dwarf_elf_handle * elf,
+ Dwarf_Error * error)
+{
+ struct Dwarf_Obj_Access_Interface_s * obj = 0;
+ if (dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ obj = dbg->de_obj_file;
+ if(obj) {
+ dwarf_elf_object_access_internals_t *internals =
+ (dwarf_elf_object_access_internals_t*)obj->object;
+ if(internals->elf == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_FNO);
+ return (DW_DLV_ERROR);
+ }
+ *elf = internals->elf;
+ return DW_DLV_OK;
+
+ }
+ _dwarf_error(dbg, error, DW_DLE_FNO);
+ return DW_DLV_ERROR;
+}
+
+
diff --git a/libdwarf/dwarf_elf_access.h b/libdwarf/dwarf_elf_access.h
new file mode 100644
index 0000000..4608a27
--- /dev/null
+++ b/libdwarf/dwarf_elf_access.h
@@ -0,0 +1,55 @@
+#ifndef _DWARF_ELF_PORT_H
+#define _DWARF_ELF_PORT_H
+/*
+
+ Copyright (C) 2008-2011 David Anderson. All rights reserved.
+ Portions Copyright 2008-2010 Arxan Technologies, Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+/* ELF (usually libelf) object access for the generic object file interface */
+
+int
+dwarf_elf_object_access_init(dwarf_elf_handle elf ,
+ int libdwarf_owns_elf,
+ Dwarf_Obj_Access_Interface** ret_obj,
+ int *err );
+
+void
+dwarf_elf_object_access_finish(Dwarf_Obj_Access_Interface* obj );
+
+/* End ELF object access for the generic object file interface */
+
+
+#endif
diff --git a/libdwarf/dwarf_error.c b/libdwarf/dwarf_error.c
new file mode 100644
index 0000000..69031b7
--- /dev/null
+++ b/libdwarf/dwarf_error.c
@@ -0,0 +1,418 @@
+/*
+
+ Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2008-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#ifdef HAVE_ELF_H
+#include <elf.h>
+#endif
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <stdlib.h>
+
+/* Array to hold string representation of errors. Any time a
+ define is added to the list in libdwarf.h, a string should be
+ added to this Array
+*/
+
+const char *_dwarf_errmsgs[] = {
+
+ "No error (0)\n",
+ "DW_DLE_VMM 1 dwarf format/library version mismatch",
+ "DW_DLE_MAP 2 memory map failure",
+ "DW_DLE_LEE 3 libelf error",
+ "DW_DLE_NDS 4 no debug section",
+ "DW_DLE_NLS 5 no line section ",
+ "DW_DLE_ID 6 invalid descriptor for query ",
+ "DW_DLE_IOF 7 I/O failure ",
+ "DW_DLE_MAF 8 memory allocation failure ",
+ "DW_DLE_IA 9 invalid argument ",
+ "DW_DLE_MDE 10 mangled debugging entry ",
+ "DW_DLE_MLE 11 mangled line number entry ",
+ "DW_DLE_FNO 12 file not open ",
+ "DW_DLE_FNR 13 file not a regular file ",
+ "DW_DLE_FWA 14 file open with wrong access ",
+ "DW_DLE_NOB 15 not an object file ",
+ "DW_DLE_MOF 16 mangled object file header ",
+ "DW_DLE_EOLL 17 end of location list entries ",
+ "DW_DLE_NOLL 18 no location list section ",
+ "DW_DLE_BADOFF 19 Invalid offset ",
+ "DW_DLE_EOS 20 end of section ",
+ "DW_DLE_ATRUNC 21 abbreviations section appears truncated",
+ "DW_DLE_BADBITC 22 Address size passed to dwarf bad",
+
+ "DW_DLE_DBG_ALLOC 23 Unable to malloc a Dwarf_Debug structure",
+ "DW_DLE_FSTAT_ERROR 24 The file fd passed to dwarf_init "
+ "cannot be fstat()ed",
+ "DW_DLE_FSTAT_MODE_ERROR 25 The file mode bits do not "
+ "indicate that the file being opened via "
+ "dwarf_init() is a normal file",
+ "DW_DLE_INIT_ACCESS_WRONG 26 A call to dwarf_init had an "
+ "access of other than DW_DLC_READ",
+ "DW_DLE_ELF_BEGIN_ERROR 27 a call to "
+ "elf_begin(... ELF_C_READ_MMAP... ) failed",
+ "DW_DLE_ELF_GETEHDR_ERROR 28 a call to "
+ "elf32_getehdr() or elf64_getehdr() failed",
+ "DW_DLE_ELF_GETSHDR_ERROR 29 a call to "
+ "elf32_getshdr() or elf64_getshdr() failed",
+ "DW_DLE_ELF_STRPTR_ERROR 30 a call to "
+ "elf_strptr() failed trying to get a section name",
+ "DW_DLE_DEBUG_INFO_DUPLICATE 31 Only one .debug_info "
+ "section is allowed",
+ "DW_DLE_DEBUG_INFO_NULL 32 .debug_info section present but "
+ "elf_getdata() failed or section is zero-length",
+ "DW_DLE_DEBUG_ABBREV_DUPLICATE 33 Only one .debug_abbrev "
+ "section is allowed",
+ "DW_DLE_DEBUG_ABBREV_NULL 34 .debug_abbrev section present but "
+ "elf_getdata() failed or section is zero-length",
+ "DW_DLE_DEBUG_ARANGES_DUPLICATE 35 Only one .debug_aranges "
+ "section is allowed",
+ "DW_DLE_DEBUG_ARANGES_NULL 36 .debug_aranges section present but "
+ "elf_getdata() failed or section is zero-length",
+ "DW_DLE_DEBUG_LINE_DUPLICATE 37 Only one .debug_line "
+ "section is allowed",
+ "DW_DLE_DEBUG_LINE_NULL (38) .debug_line section present but "
+ "elf_getdata() failed or section is zero-length",
+ "DW_DLE_DEBUG_LOC_DUPLICATE (39) Only one .debug_loc "
+ "section is allowed",
+ "DW_DLE_DEBUG_LOC_NULL (40) .debug_loc section present but "
+ "elf_getdata() failed or section is zero-length",
+ "DW_DLE_DEBUG_MACINFO_DUPLICATE (41) Only one .debug_macinfo "
+ "section is allowed",
+ "DW_DLE_DEBUG_MACINFO_NULL (42) .debug_macinfo section present but "
+ "elf_getdata() failed or section is zero-length",
+ "DW_DLE_DEBUG_PUBNAMES_DUPLICATE (43) Only one .debug_pubnames "
+ "section is allowed",
+ "DW_DLE_DEBUG_PUBNAMES_NULL (44) .debug_pubnames section present but "
+ "elf_getdata() failed or section is zero-length",
+ "DW_DLE_DEBUG_STR_DUPLICATE (45) Only one .debug_str "
+ "section is allowed",
+ "DW_DLE_DEBUG_STR_NULL (46) .debug_str section present but "
+ "elf_getdata() failed or section is zero-length",
+ "DW_DLE_CU_LENGTH_ERROR (47)",
+ "DW_DLE_VERSION_STAMP_ERROR (48)",
+ "DW_DLE_ABBREV_OFFSET_ERROR (49)",
+ "DW_DLE_ADDRESS_SIZE_ERROR (50)",
+ "DW_DLE_DEBUG_INFO_PTR_NULL (51)",
+ "DW_DLE_DIE_NULL (52)",
+ "DW_DLE_STRING_OFFSET_BAD (53)",
+ "DW_DLE_DEBUG_LINE_LENGTH_BAD (54)",
+ "DW_DLE_LINE_PROLOG_LENGTH_BAD (55)",
+ "DW_DLE_LINE_NUM_OPERANDS_BAD",
+ "DW_DLE_LINE_SET_ADDR_ERROR",
+ "DW_DLE_LINE_EXT_OPCODE_BAD",
+ "DW_DLE_DWARF_LINE_NULL",
+ "DW_DLE_INCL_DIR_NUM_BAD",
+ "DW_DLE_LINE_FILE_NUM_BAD",
+ "DW_DLE_ALLOC_FAIL",
+ "DW_DLE_NO_CALLBACK_FUNC",
+ "DW_DLE_SECT_ALLOC",
+ "DW_DLE_FILE_ENTRY_ALLOC",
+ "DW_DLE_LINE_ALLOC",
+ "DW_DLE_FPGM_ALLOC",
+ "DW_DLE_INCDIR_ALLOC",
+ "DW_DLE_STRING_ALLOC",
+ "DW_DLE_CHUNK_ALLOC",
+ "DW_DLE_BYTEOFF_ERR",
+ "DW_DLE_CIE_ALLOC",
+ "DW_DLE_FDE_ALLOC",
+ "DW_DLE_REGNO_OVFL",
+ "DW_DLE_CIE_OFFS_ALLOC",
+ "DW_DLE_WRONG_ADDRESS",
+ "DW_DLE_EXTRA_NEIGHBORS",
+ "DW_DLE_WRONG_TAG",
+ "DW_DLE_DIE_ALLOC",
+ "DW_DLE_PARENT_EXISTS",
+ "DW_DLE_DBG_NULL",
+ "DW_DLE_DEBUGLINE_ERROR",
+ "DW_DLE_DEBUGFRAME_ERROR",
+ "DW_DLE_DEBUGINFO_ERROR",
+ "DW_DLE_ATTR_ALLOC",
+ "DW_DLE_ABBREV_ALLOC",
+ "DW_DLE_OFFSET_UFLW",
+ "DW_DLE_ELF_SECT_ERR",
+ "DW_DLE_DEBUG_FRAME_LENGTH_BAD",
+ "DW_DLE_FRAME_VERSION_BAD",
+ "DW_DLE_CIE_RET_ADDR_REG_ERROR",
+ "DW_DLE_FDE_NULL",
+ "DW_DLE_FDE_DBG_NULL",
+ "DW_DLE_CIE_NULL",
+ "DW_DLE_CIE_DBG_NULL",
+ "DW_DLE_FRAME_TABLE_COL_BAD",
+ "DW_DLE_PC_NOT_IN_FDE_RANGE",
+ "DW_DLE_CIE_INSTR_EXEC_ERROR",
+ "DW_DLE_FRAME_INSTR_EXEC_ERROR",
+ "DW_DLE_FDE_PTR_NULL",
+ "DW_DLE_RET_OP_LIST_NULL",
+ "DW_DLE_LINE_CONTEXT_NULL",
+ "DW_DLE_DBG_NO_CU_CONTEXT",
+ "DW_DLE_DIE_NO_CU_CONTEXT",
+ "DW_DLE_FIRST_DIE_NOT_CU",
+ "DW_DLE_NEXT_DIE_PTR_NULL",
+ "DW_DLE_DEBUG_FRAME_DUPLICATE Only one .debug_frame "
+ "section is allowed",
+ "DW_DLE_DEBUG_FRAME_NULL .debug_frame section present but "
+ "elf_getdata() failed or section is zero-length",
+ "DW_DLE_ABBREV_DECODE_ERROR",
+ "DW_DLE_DWARF_ABBREV_NULL",
+ "DW_DLE_ATTR_NULL",
+ "DW_DLE_DIE_BAD",
+ "DW_DLE_DIE_ABBREV_BAD",
+ "DW_DLE_ATTR_FORM_BAD",
+ "DW_DLE_ATTR_NO_CU_CONTEXT",
+ "DW_DLE_ATTR_FORM_SIZE_BAD",
+ "DW_DLE_ATTR_DBG_NULL",
+ "DW_DLE_BAD_REF_FORM",
+ "DW_DLE_ATTR_FORM_OFFSET_BAD",
+ "DW_DLE_LINE_OFFSET_BAD",
+ "DW_DLE_DEBUG_STR_OFFSET_BAD",
+ "DW_DLE_STRING_PTR_NULL",
+ "DW_DLE_PUBNAMES_VERSION_ERROR",
+ "DW_DLE_PUBNAMES_LENGTH_BAD",
+ "DW_DLE_GLOBAL_NULL",
+ "DW_DLE_GLOBAL_CONTEXT_NULL",
+ "DW_DLE_DIR_INDEX_BAD",
+ "DW_DLE_LOC_EXPR_BAD",
+ "DW_DLE_DIE_LOC_EXPR_BAD",
+ "DW_DLE_ADDR_ALLOC",
+ "DW_DLE_OFFSET_BAD",
+ "DW_DLE_MAKE_CU_CONTEXT_FAIL",
+ "DW_DLE_REL_ALLOC",
+ "DW_DLE_ARANGE_OFFSET_BAD",
+ "DW_DLE_SEGMENT_SIZE_BAD (135) Size of a segment selector should usually be less than 8 (bytes).",
+ "DW_DLE_ARANGE_LENGTH_BAD",
+ "DW_DLE_ARANGE_DECODE_ERROR",
+ "DW_DLE_ARANGES_NULL",
+ "DW_DLE_ARANGE_NULL",
+ "DW_DLE_NO_FILE_NAME",
+ "DW_DLE_NO_COMP_DIR",
+ "DW_DLE_CU_ADDRESS_SIZE_BAD",
+ "DW_DLE_INPUT_ATTR_BAD",
+ "DW_DLE_EXPR_NULL",
+ "DW_DLE_BAD_EXPR_OPCODE",
+ "DW_DLE_EXPR_LENGTH_BAD",
+ "DW_DLE_MULTIPLE_RELOC_IN_EXPR",
+ "DW_DLE_ELF_GETIDENT_ERROR",
+ "DW_DLE_NO_AT_MIPS_FDE",
+ "DW_DLE_NO_CIE_FOR_FDE",
+ "DW_DLE_DIE_ABBREV_LIST_NULL",
+ "DW_DLE_DEBUG_FUNCNAMES_DUPLICATE",
+ "DW_DLE_DEBUG_FUNCNAMES_NULL .debug_funcnames section present but "
+ "elf_getdata() failed or section is zero-length",
+ "DW_DLE_DEBUG_FUNCNAMES_VERSION_ERROR",
+ "DW_DLE_DEBUG_FUNCNAMES_LENGTH_BAD",
+ "DW_DLE_FUNC_NULL",
+ "DW_DLE_FUNC_CONTEXT_NULL",
+ "DW_DLE_DEBUG_TYPENAMES_DUPLICATE",
+ "DW_DLE_DEBUG_TYPENAMES_NULL .debug_typenames section present but "
+ "elf_getdata() failed or section is zero-length",
+ "DW_DLE_DEBUG_TYPENAMES_VERSION_ERROR",
+ "DW_DLE_DEBUG_TYPENAMES_LENGTH_BAD",
+ "DW_DLE_TYPE_NULL",
+ "DW_DLE_TYPE_CONTEXT_NULL",
+ "DW_DLE_DEBUG_VARNAMES_DUPLICATE",
+ "DW_DLE_DEBUG_VARNAMES_NULL .debug_varnames section present but "
+ "elf_getdata() failed or section is zero-length",
+ "DW_DLE_DEBUG_VARNAMES_VERSION_ERROR",
+ "DW_DLE_DEBUG_VARNAMES_LENGTH_BAD",
+ "DW_DLE_VAR_NULL",
+ "DW_DLE_VAR_CONTEXT_NULL",
+ "DW_DLE_DEBUG_WEAKNAMES_DUPLICATE",
+ "DW_DLE_DEBUG_WEAKNAMES_NULL .debug_weaknames section present but "
+ "elf_getdata() failed or section is zero-length",
+
+ "DW_DLE_DEBUG_WEAKNAMES_VERSION_ERROR",
+ "DW_DLE_DEBUG_WEAKNAMES_LENGTH_BAD",
+ "DW_DLE_WEAK_NULL",
+ "DW_DLE_WEAK_CONTEXT_NULL (175)",
+ "DW_DLE_LOCDESC_COUNT_WRONG (176)",
+ "DW_DLE_MACINFO_STRING_NULL (177)",
+ "DW_DLE_MACINFO_STRING_EMPTY (178)",
+ "DW_DLE_MACINFO_INTERNAL_ERROR_SPACE (179)",
+ "DW_DLE_MACINFO_MALLOC_FAIL (180)",
+ "DW_DLE_DEBUGMACINFO_ERROR (181)",
+ "DW_DLE_DEBUG_MACRO_LENGTH_BAD (182)",
+ "DW_DLE_DEBUG_MACRO_MAX_BAD (183)",
+ "DW_DLE_DEBUG_MACRO_INTERNAL_ERR (184)",
+ "DW_DLE_DEBUG_MACRO_MALLOC_SPACE (185)",
+ "DW_DLE_DEBUG_MACRO_INCONSISTENT (186)",
+ "DW_DLE_DF_NO_CIE_AUGMENTATION(187)",
+ "DW_DLE_DF_REG_NUM_TOO_HIGH(188)",
+ "DW_DLE_DF_MAKE_INSTR_NO_INIT(189)",
+ "DW_DLE_DF_NEW_LOC_LESS_OLD_LOC(190)",
+ "DW_DLE_DF_POP_EMPTY_STACK(191)",
+ "DW_DLE_DF_ALLOC_FAIL(192)",
+ "DW_DLE_DF_FRAME_DECODING_ERROR(193)",
+ "DW_DLE_DEBUG_LOC_SECTION_SHORT(194)",
+ "DW_DLE_FRAME_AUGMENTATION_UNKNOWN(195)",
+ "DW_DLE_PUBTYPE_CONTEXT(196)",
+ "DW_DLE_DEBUG_PUBTYPES_LENGTH_BAD(197)",
+ "DW_DLE_DEBUG_PUBTYPES_VERSION_ERROR(198)",
+ "DW_DLE_DEBUG_PUBTYPES_DUPLICATE(199)",
+ "DW_DLE_FRAME_CIE_DECODE_ERROR(200)",
+ "DW_DLE_FRAME_REGISTER_UNREPRESENTABLE(201)",
+ "DW_DLE_FRAME_REGISTER_COUNT_MISMATCH(202)",
+ "DW_DLE_LINK_LOOP(203)",
+ "DW_DLE_STRP_OFFSET_BAD(204)",
+ "DW_DLE_DEBUG_RANGES_DUPLICATE(205)",
+ "DW_DLE_DEBUG_RANGES_OFFSET_BAD(206)",
+ "DW_DLE_DEBUG_RANGES_MISSING_END(207)",
+ "DW_DLE_DEBUG_RANGES_OUT_OF_MEM(208)",
+ "DW_DLE_DEBUG_SYMTAB_ERR(209)",
+ "DW_DLE_DEBUG_STRTAB_ERR(210)",
+ "DW_DLE_RELOC_MISMATCH_INDEX(211)",
+ "DW_DLE_RELOC_MISMATCH_RELOC_INDEX(212)",
+ "DW_DLE_RELOC_MISMATCH_STRTAB_INDEX(213)",
+ "DW_DLE_RELOC_SECTION_MISMATCH(214)",
+ "DW_DLE_RELOC_SECTION_MISSING_INDEX(215)",
+ "DW_DLE_RELOC_SECTION_LENGTH_ODD(216)",
+ "DW_DLE_RELOC_SECTION_PTR_NULL(217)",
+ "DW_DLE_RELOC_SECTION_MALLOC_FAIL(218)",
+ "DW_DLE_NO_ELF64_SUPPORT(219)",
+ "DW_DLE_MISSING_ELF64_SUPPORT(220)",
+ "DW_DLE_ORPHAN_FDE(221)",
+ "DW_DLE_DUPLICATE_INST_BLOCK(222)",
+ "DW_DLE_BAD_REF_SIG8_FORM(223)",
+ "DW_DLE_ATTR_EXPRLOC_FORM_BAD(224)",
+ "DW_DLE_FORM_SEC_OFFSET_LENGTH_BAD(225)",
+ "DW_DLE_NOT_REF_FORM(226)",
+ "DW_DLE_DEBUG_FRAME_LENGTH_NOT_MULTIPLE(227)",
+ "DW_DLE_REF_SIG8_NOT_HANDLED (228)",
+ "DW_DLE_DEBUG_FRAME_POSSIBLE_ADDRESS_BOTCH (229)",
+ "DW_DLE_LOC_BAD_TERMINATION (230) the last location operator in an expression is missing some associated data, an operator ended too soon",
+ "DW_DLE_SYMTAB_SECTION_LENGTH_ODD (231) so doing relocations seems unsafe",
+ "DW_DLE_RELOC_SECTION_SYMBOL_INDEX_BAD (232) so doing a relocation seems unsafe",
+ "DW_DLE_RELOC_SECTION_RELOC_TARGET_SIZE_UNKNOWN (233) so doing a relocation is unsafe",
+ "DW_DLE_SYMTAB_SECTION_ENTRYSIZE_ZERO(234)",
+ "DW_DLE_LINE_NUMBER_HEADER_ERROR (235), a line number program header seems incomplete (perhaps the header_length is wrong?).",
+ "DW_DLE_DEBUG_TYPES_NULL (236)",
+ "DW_DLE_DEBUG_TYPES_DUPLICATE (237)",
+ "DW_DLE_DEBUG_TYPES_ONLY_DWARF4 (238)",
+ "DW_DLE_DEBUG_TYPEOFFSET_BAD (239)",
+ "DW_DLE_GNU_OPCODE_ERROR (240)",
+};
+
+
+
+
+/* This function performs error handling as described in the
+ libdwarf consumer document section 3. Dbg is the Dwarf_debug
+ structure being processed. Error is a pointer to the pointer
+ to the error descriptor that will be returned. Errval is an
+ error code listed in dwarf_error.h. */
+void
+_dwarf_error(Dwarf_Debug dbg, Dwarf_Error * error, Dwarf_Sword errval)
+{
+ Dwarf_Error errptr;
+
+ /* Allow NULL dbg on entry, since sometimes that can happen and we
+ want to report the upper-level error, not this one. */
+ if (error != NULL) {
+ /* If dbg is NULL, use the alternate error struct. However,
+ this will overwrite the earlier error. */
+ if (dbg != NULL) {
+ errptr =
+ (Dwarf_Error) _dwarf_get_alloc(dbg, DW_DLA_ERROR, 1);
+ if (errptr == NULL) {
+ fprintf(stderr,
+ "Could not allocate Dwarf_Error structure, "
+ "abort() in libdwarf.\n");
+ abort();
+ }
+ } else {
+ /* We have no dbg to work with. dwarf_init failed. We hack
+ up a special area. */
+ errptr = _dwarf_special_no_dbg_error_malloc();
+ if (errptr == NULL) {
+ fprintf(stderr,
+ "Could not allocate Dwarf_Error structure, "
+ "abort() in libdwarf..\n");
+ abort();
+ }
+ }
+
+ errptr->er_errval = errval;
+ *error = errptr;
+ return;
+ }
+
+ if (dbg != NULL && dbg->de_errhand != NULL) {
+ errptr = (Dwarf_Error) _dwarf_get_alloc(dbg, DW_DLA_ERROR, 1);
+ if (errptr == NULL) {
+ fprintf(stderr, "Could not allocate Dwarf_Error structure,"
+ " abort() in libdwarf.\n");
+ abort();
+ }
+ errptr->er_errval = errval;
+ dbg->de_errhand(errptr, dbg->de_errarg);
+ return;
+ }
+ fprintf(stderr,
+ "abort() in libdwarf. No error argument, no handler.\n");
+ abort();
+}
+
+
+Dwarf_Unsigned
+dwarf_errno(Dwarf_Error error)
+{
+ if (error == NULL) {
+ return (0);
+ }
+
+ return (error->er_errval);
+}
+
+
+/*
+*/
+char *
+dwarf_errmsg(Dwarf_Error error)
+{
+ if (error == NULL) {
+ return "Dwarf_Error is NULL";
+ }
+
+ if (error->er_errval >= (sizeof(_dwarf_errmsgs) / sizeof(char *))) {
+ return "Dwarf_Error value out of range";
+ }
+
+ return ((char *) _dwarf_errmsgs[error->er_errval]);
+}
diff --git a/libdwarf/dwarf_error.h b/libdwarf/dwarf_error.h
new file mode 100644
index 0000000..4a4923e
--- /dev/null
+++ b/libdwarf/dwarf_error.h
@@ -0,0 +1,44 @@
+/*
+
+ Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+void _dwarf_error(Dwarf_Debug dbg, Dwarf_Error * error,
+ Dwarf_Sword errval);
+
+struct Dwarf_Error_s {
+ Dwarf_Sword er_errval;
+};
diff --git a/libdwarf/dwarf_form.c b/libdwarf/dwarf_form.c
new file mode 100644
index 0000000..c09b610
--- /dev/null
+++ b/libdwarf/dwarf_form.c
@@ -0,0 +1,931 @@
+/*
+
+ Copyright (C) 2000,2002,2004,2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson. All rights reserved.
+ Portions Copyright 2010 SN Systems Ltd. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include "dwarf_die_deliv.h"
+
+/* This code was repeated many times, now it
+ is all in one place. */
+static int
+get_attr_dbg(Dwarf_Debug *dbg,
+ Dwarf_CU_Context * cu_context,
+ Dwarf_Attribute attr,
+ Dwarf_Error *error)
+{
+ Dwarf_CU_Context cup;
+ if (attr == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_ATTR_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ cup = attr->ar_cu_context;
+ if (cup == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT);
+ return (DW_DLV_ERROR);
+ }
+
+ if (cup->cc_dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+ *cu_context = cup;
+ *dbg = cup->cc_dbg;
+ return DW_DLV_OK;
+
+}
+
+int
+dwarf_hasform(Dwarf_Attribute attr,
+ Dwarf_Half form,
+ Dwarf_Bool * return_bool, Dwarf_Error * error)
+{
+ Dwarf_Debug dbg = 0;
+ Dwarf_CU_Context cu_context = 0;
+
+ int res =get_attr_dbg(&dbg,&cu_context, attr,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ *return_bool = (attr->ar_attribute_form == form);
+ return DW_DLV_OK;
+}
+
+/* Not often called, we do not worry about efficiency here.
+ The dwarf_whatform() call does the sanity checks for us.
+*/
+int
+dwarf_whatform_direct(Dwarf_Attribute attr,
+ Dwarf_Half * return_form, Dwarf_Error * error)
+{
+ int res = dwarf_whatform(attr, return_form, error);
+
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ *return_form = attr->ar_attribute_form_direct;
+ return (DW_DLV_OK);
+}
+void *
+dwarf_uncompress_integer_block(
+ Dwarf_Debug dbg,
+ Dwarf_Bool unit_is_signed,
+ Dwarf_Small unit_length_in_bits,
+ void* input_block,
+ Dwarf_Unsigned input_length_in_bytes,
+ Dwarf_Unsigned* output_length_in_units_ptr,
+ Dwarf_Error* error
+)
+{
+ Dwarf_Unsigned output_length_in_units = 0;
+ void * output_block = 0;
+ int i = 0;
+ char * ptr = 0;
+ int remain = 0;
+ Dwarf_sfixed * array = 0;
+
+ if (dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
+ return((void *)DW_DLV_BADADDR);
+ }
+
+ if (unit_is_signed == false ||
+ unit_length_in_bits != 32 ||
+ input_block == NULL ||
+ input_length_in_bytes == 0 ||
+ output_length_in_units_ptr == NULL) {
+
+ _dwarf_error(NULL, error, DW_DLE_BADBITC);
+ return ((void *) DW_DLV_BADADDR);
+ }
+
+ /* At this point we assume the format is: signed 32 bit */
+
+ /* first uncompress everything to find the total size. */
+
+ output_length_in_units = 0;
+ remain = input_length_in_bytes;
+ ptr = input_block;
+ while (remain > 0) {
+ Dwarf_Signed num;
+ Dwarf_Word len;
+ num = _dwarf_decode_s_leb128((unsigned char *)ptr, &len);
+ ptr += len;
+ remain -= len;
+ output_length_in_units++;
+ }
+
+ if (remain != 0) {
+ _dwarf_error(NULL, error, DW_DLE_ALLOC_FAIL);
+ return((void *)DW_DLV_BADADDR);
+ }
+
+ /* then alloc */
+
+ output_block = (void *)
+ _dwarf_get_alloc(dbg,
+ DW_DLA_STRING,
+ output_length_in_units * (unit_length_in_bits / 8));
+ if (output_block == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return((void*)DW_DLV_BADADDR);
+ }
+
+ /* then uncompress again and copy into new buffer */
+
+ array = (Dwarf_sfixed *) output_block;
+ remain = input_length_in_bytes;
+ ptr = input_block;
+ for (i=0; i<output_length_in_units && remain>0; i++) {
+ Dwarf_Signed num;
+ Dwarf_Word len;
+ num = _dwarf_decode_s_leb128((unsigned char *)ptr, &len);
+ ptr += len;
+ remain -= len;
+ array[i] = num;
+ }
+
+ if (remain != 0) {
+ dwarf_dealloc(dbg, (unsigned char *)output_block, DW_DLA_STRING);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return((Dwarf_P_Attribute)DW_DLV_BADADDR);
+ }
+
+ *output_length_in_units_ptr = output_length_in_units;
+ return output_block;
+}
+
+void
+dwarf_dealloc_uncompressed_block(Dwarf_Debug dbg, void * space)
+{
+ dwarf_dealloc(dbg, space, DW_DLA_STRING);
+}
+
+
+int
+dwarf_whatform(Dwarf_Attribute attr,
+ Dwarf_Half * return_form, Dwarf_Error * error)
+{
+ Dwarf_CU_Context cu_context = 0;
+ Dwarf_Debug dbg = 0;
+
+ int res =get_attr_dbg(&dbg,&cu_context, attr,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ *return_form = attr->ar_attribute_form;
+ return (DW_DLV_OK);
+}
+
+
+/*
+ This function is analogous to dwarf_whatform.
+ It returns the attribute in attr instead of
+ the form.
+*/
+int
+dwarf_whatattr(Dwarf_Attribute attr,
+ Dwarf_Half * return_attr, Dwarf_Error * error)
+{
+ Dwarf_CU_Context cu_context = 0;
+ Dwarf_Debug dbg = 0;
+
+ int res =get_attr_dbg(&dbg,&cu_context, attr,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ *return_attr = (attr->ar_attribute);
+ return DW_DLV_OK;
+}
+
+
+/* Convert an offset within the local CU into a section-relative
+ debug_info offset. See dwarf_global_formref() and dwarf_formref()
+ for additional information on conversion rules.
+*/
+int
+dwarf_convert_to_global_offset(Dwarf_Attribute attr,
+ Dwarf_Off offset, Dwarf_Off * ret_offset, Dwarf_Error * error)
+{
+ Dwarf_Debug dbg = 0;
+ Dwarf_CU_Context cu_context = 0;
+
+ int res = get_attr_dbg(&dbg,&cu_context,attr,error);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+
+ switch (attr->ar_attribute_form) {
+ case DW_FORM_ref1:
+ case DW_FORM_ref2:
+ case DW_FORM_ref4:
+ case DW_FORM_ref8:
+ case DW_FORM_ref_udata:
+ /* It would be nice to put some code to check
+ legality of the offset */
+ /* globalize the offset */
+ offset += cu_context->cc_debug_offset;
+ break;
+
+ case DW_FORM_ref_addr:
+ /* This offset is defined to be debug_info global already, so
+ use this value unaltered. */
+ break;
+
+ default:
+ _dwarf_error(dbg, error, DW_DLE_BAD_REF_FORM);
+ return (DW_DLV_ERROR);
+ }
+
+ *ret_offset = (offset);
+ return DW_DLV_OK;
+}
+
+
+/* A global offset cannot be returned by this interface:
+ see dwarf_global_formref().
+
+ DW_FORM_ref_addr is considered an incorrect form
+ for this call because DW_FORM_ref_addr is a global-offset into
+ the debug_info section.
+
+ For the same reason DW_FORM_data4/data8 are not returned
+ from this function.
+
+ For the same reason DW_FORM_sec_offset is not returned
+ from this function, DW_FORM_sec_offset is a global offset
+ (to various sections, not a CU relative offset.
+
+ DW_FORM_ref_addr has a value which was documented in
+ DWARF2 as address-size but which was always an offset
+ so should have always been offset size (wording
+ corrected in DWARF3).
+
+ November, 2010: *ret_offset is always set now.
+ Even in case of error.
+ Set to zero for most errors, but for
+ DW_DLE_ATTR_FORM_OFFSET_BAD
+ *ret_offset is set to the bad offset. */
+int
+dwarf_formref(Dwarf_Attribute attr,
+ Dwarf_Off * ret_offset, Dwarf_Error * error)
+{
+ Dwarf_Debug dbg = 0;
+ Dwarf_Unsigned offset = 0;
+ Dwarf_CU_Context cu_context = 0;
+ Dwarf_Unsigned maximumoffset = 0;
+ int res = DW_DLV_ERROR;
+
+
+ *ret_offset = 0;
+ res = get_attr_dbg(&dbg,&cu_context,attr,error);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ switch (attr->ar_attribute_form) {
+
+ case DW_FORM_ref1:
+ offset = *(Dwarf_Small *) attr->ar_debug_ptr;
+ break;
+
+ case DW_FORM_ref2:
+ READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
+ attr->ar_debug_ptr, sizeof(Dwarf_Half));
+ break;
+
+ case DW_FORM_ref4:
+ READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
+ attr->ar_debug_ptr, sizeof(Dwarf_ufixed));
+ break;
+
+ case DW_FORM_ref8:
+ READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
+ attr->ar_debug_ptr, sizeof(Dwarf_Unsigned));
+ break;
+
+ case DW_FORM_ref_udata:
+ offset = _dwarf_decode_u_leb128(attr->ar_debug_ptr, NULL);
+ break;
+ case DW_FORM_ref_sig8:
+ /* We cannot handle this here.
+ The reference is to .debug_types
+ not a .debug_info CU local offset. */
+ _dwarf_error(dbg, error, DW_DLE_REF_SIG8_NOT_HANDLED);
+ return (DW_DLV_ERROR);
+ default:
+ _dwarf_error(dbg, error, DW_DLE_BAD_REF_FORM);
+ return (DW_DLV_ERROR);
+ }
+
+ /* Check that offset is within current cu portion of .debug_info. */
+
+ maximumoffset = cu_context->cc_length +
+ cu_context->cc_length_size +
+ cu_context->cc_extension_size;
+ if (offset >= maximumoffset) {
+ /* For the DW_TAG_compile_unit is legal to have the
+ DW_AT_sibling attribute outside the current cu portion of
+ .debug_info.
+ In other words, sibling points to the end of the CU.
+ It is used for precompiled headers.
+ The valid condition will be: 'offset == maximumoffset'. */
+ Dwarf_Half tag = 0;
+ if (DW_DLV_OK != dwarf_tag(attr->ar_die,&tag,error)) {
+ _dwarf_error(dbg, error, DW_DLE_DIE_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ if (DW_TAG_compile_unit != tag &&
+ DW_AT_sibling != attr->ar_attribute &&
+ offset > maximumoffset) {
+ _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_OFFSET_BAD);
+ /* Return the incorrect offset for better error reporting */
+ *ret_offset = (offset);
+ return (DW_DLV_ERROR);
+ }
+ }
+ *ret_offset = (offset);
+ return DW_DLV_OK;
+}
+
+/* dwarf_formsig8 returns in the caller-provided 8 byte area
+ the 8 bytes of a DW_FORM_ref_sig8 (copying the bytes
+ directly to the caller). Not a string, an 8 byte
+ MD5 hash. This function is new in DWARF4 libdwarf.
+*/
+int dwarf_formsig8(Dwarf_Attribute attr,
+ Dwarf_Sig8 * returned_sig_bytes,
+ Dwarf_Error* error)
+{
+ Dwarf_Debug dbg = 0;
+ Dwarf_Unsigned field_end_offset = 0;
+ Dwarf_CU_Context cu_context = 0;
+ Dwarf_Small *dataptr = 0;
+
+ int res = get_attr_dbg(&dbg,&cu_context,attr,error);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+
+ if(attr->ar_attribute_form != DW_FORM_ref_sig8 ) {
+ _dwarf_error(dbg, error, DW_DLE_BAD_REF_SIG8_FORM);
+ return (DW_DLV_ERROR);
+ }
+
+ dataptr = cu_context->cc_is_info? dbg->de_debug_info.dss_data:
+ dbg->de_debug_types.dss_data;
+
+ field_end_offset = attr->ar_debug_ptr + sizeof(Dwarf_Sig8) -
+ (dataptr + cu_context->cc_debug_offset);
+ /* Check that offset is within current cu portion of .debug_info. */
+ if (field_end_offset > cu_context->cc_length +
+ cu_context->cc_length_size + cu_context->cc_extension_size) {
+ _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_OFFSET_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ memcpy(returned_sig_bytes, attr->ar_debug_ptr,
+ sizeof(Dwarf_Sig8));
+ return DW_DLV_OK;
+}
+
+/* Since this returns section-relative debug_info offsets,
+ this can represent all REFERENCE forms correctly
+ and allows all applicable forms.
+
+ DW_FORM_ref_addr has a value which was documented in
+ DWARF2 as address-size but which was always an offset
+ so should have always been offset size (wording
+ corrected in DWARF3).
+
+ See the DWARF4 document for the 3 cases fitting
+ reference forms. The caller must determine which section the
+ reference 'points' to. The function added in November 2009,
+ dwarf_get_form_class(), helps in this regard. */
+int
+dwarf_global_formref(Dwarf_Attribute attr,
+ Dwarf_Off * ret_offset, Dwarf_Error * error)
+{
+ Dwarf_Debug dbg = 0;
+ Dwarf_Unsigned offset = 0;
+ Dwarf_CU_Context cu_context = 0;
+ Dwarf_Half context_version = 0;
+
+ int res = get_attr_dbg(&dbg,&cu_context,attr,error);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ context_version = cu_context->cc_version_stamp;
+ switch (attr->ar_attribute_form) {
+
+ case DW_FORM_ref1:
+ offset = *(Dwarf_Small *) attr->ar_debug_ptr;
+ goto fixoffset;
+
+ case DW_FORM_ref2:
+ READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
+ attr->ar_debug_ptr, sizeof(Dwarf_Half));
+ goto fixoffset;
+
+ case DW_FORM_ref4:
+ READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
+ attr->ar_debug_ptr, sizeof(Dwarf_ufixed));
+ goto fixoffset;
+
+ case DW_FORM_ref8:
+ READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
+ attr->ar_debug_ptr, sizeof(Dwarf_Unsigned));
+ goto fixoffset;
+
+ case DW_FORM_ref_udata:
+ offset = _dwarf_decode_u_leb128(attr->ar_debug_ptr, NULL);
+
+ fixoffset: /* we have a local offset, make it global */
+
+ /* check legality of offset */
+ if (offset >= cu_context->cc_length +
+ cu_context->cc_length_size +
+ cu_context->cc_extension_size) {
+ _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_OFFSET_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ /* globalize the offset */
+ offset += cu_context->cc_debug_offset;
+ break;
+
+ /* The DWARF2 document did not make clear that
+ DW_FORM_data4( and 8) were references with
+ global offsets to some section.
+ That was first clearly documented in DWARF3.
+ In DWARF4 these two forms are no longer references. */
+ case DW_FORM_data4:
+ if(context_version == DW_CU_VERSION4) {
+ _dwarf_error(dbg, error, DW_DLE_NOT_REF_FORM);
+ return (DW_DLV_ERROR);
+ }
+ READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
+ attr->ar_debug_ptr, sizeof(Dwarf_ufixed));
+ /* The offset is global. */
+ break;
+ case DW_FORM_data8:
+ if(context_version == DW_CU_VERSION4) {
+ _dwarf_error(dbg, error, DW_DLE_NOT_REF_FORM);
+ return (DW_DLV_ERROR);
+ }
+ READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
+ attr->ar_debug_ptr, sizeof(Dwarf_Unsigned));
+ /* The offset is global. */
+ break;
+ case DW_FORM_ref_addr:
+ case DW_FORM_sec_offset:
+ {
+ /* DW_FORM_sec_offset first exists in DWARF4.*/
+ /* It is up to the caller to know what the offset
+ of DW_FORM_sec_offset refers to,
+ the offset is not going to refer to .debug_info! */
+ unsigned length_size = cu_context->cc_length_size;
+ if(length_size == 4) {
+ READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
+ attr->ar_debug_ptr, sizeof(Dwarf_ufixed));
+ } else if (length_size == 8) {
+ READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
+ attr->ar_debug_ptr, sizeof(Dwarf_Unsigned));
+ } else {
+ _dwarf_error(dbg, error, DW_DLE_FORM_SEC_OFFSET_LENGTH_BAD);
+ return (DW_DLV_ERROR);
+ }
+ }
+ break;
+ case DW_FORM_ref_sig8: /* FIXME */
+ /* We cannot handle this yet.
+ The reference is to .debug_types, and
+ this function only returns an offset in
+ .debug_info at this point. */
+ _dwarf_error(dbg, error, DW_DLE_REF_SIG8_NOT_HANDLED);
+ return (DW_DLV_ERROR);
+ default:
+ _dwarf_error(dbg, error, DW_DLE_BAD_REF_FORM);
+ return (DW_DLV_ERROR);
+ }
+
+ /* We do not know what section the offset refers to, so
+ we have no way to check it for correctness. */
+ *ret_offset = offset;
+ return DW_DLV_OK;
+}
+
+
+int
+dwarf_formaddr(Dwarf_Attribute attr,
+ Dwarf_Addr * return_addr, Dwarf_Error * error)
+{
+ Dwarf_Debug dbg = 0;
+ Dwarf_Addr ret_addr = 0;
+ Dwarf_CU_Context cu_context = 0;
+
+ int res = get_attr_dbg(&dbg,&cu_context,attr,error);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ if (attr->ar_attribute_form == DW_FORM_addr
+ /* || attr->ar_attribute_form == DW_FORM_ref_addr Allowance of
+ DW_FORM_ref_addr was a mistake. The value returned in that
+ case is NOT an address it is a global debug_info offset (ie,
+ not CU-relative offset within the CU in debug_info). The
+ Dwarf document refers to it as an address (misleadingly) in
+ sec 6.5.4 where it describes the reference form. It is
+ address-sized so that the linker can easily update it, but
+ it is a reference inside the debug_info section. No longer
+ allowed. */
+ ) {
+
+ READ_UNALIGNED(dbg, ret_addr, Dwarf_Addr,
+ attr->ar_debug_ptr,
+ cu_context->cc_address_size);
+ *return_addr = ret_addr;
+ return (DW_DLV_OK);
+ }
+
+ _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_BAD);
+ return (DW_DLV_ERROR);
+}
+
+
+int
+dwarf_formflag(Dwarf_Attribute attr,
+ Dwarf_Bool * ret_bool, Dwarf_Error * error)
+{
+ Dwarf_CU_Context cu_context = 0;
+
+ if (attr == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_ATTR_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ cu_context = attr->ar_cu_context;
+ if (cu_context == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT);
+ return (DW_DLV_ERROR);
+ }
+
+ if (cu_context->cc_dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+ if (attr->ar_attribute_form == DW_FORM_flag_present) {
+ /* Implicit means we don't read any data at all. Just
+ the existence of the Form does it. DWARF4. */
+ *ret_bool = 1;
+ return (DW_DLV_OK);
+ }
+
+ if (attr->ar_attribute_form == DW_FORM_flag) {
+ *ret_bool = (*(Dwarf_Small *) attr->ar_debug_ptr != 0);
+ return (DW_DLV_OK);
+ }
+ _dwarf_error(cu_context->cc_dbg, error, DW_DLE_ATTR_FORM_BAD);
+ return (DW_DLV_ERROR);
+}
+
+
+int
+dwarf_formudata(Dwarf_Attribute attr,
+ Dwarf_Unsigned * return_uval, Dwarf_Error * error)
+{
+ Dwarf_Unsigned ret_value = 0;
+ Dwarf_Debug dbg = 0;
+ Dwarf_CU_Context cu_context = 0;
+
+ int res = get_attr_dbg(&dbg,&cu_context,attr,error);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ switch (attr->ar_attribute_form) {
+
+ case DW_FORM_data1:
+ READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
+ attr->ar_debug_ptr, sizeof(Dwarf_Small));
+ *return_uval = ret_value;
+ return DW_DLV_OK;
+
+ /* READ_UNALIGNED does the right thing as it reads
+ the right number bits and generates host order.
+ So we can just assign to *return_uval. */
+ case DW_FORM_data2:{
+ READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
+ attr->ar_debug_ptr, sizeof(Dwarf_Half));
+ *return_uval = ret_value;
+ return DW_DLV_OK;
+ }
+
+ case DW_FORM_data4:{
+ READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
+ attr->ar_debug_ptr,
+ sizeof(Dwarf_ufixed));
+ *return_uval = ret_value;
+ return DW_DLV_OK;
+ }
+
+ case DW_FORM_data8:{
+ READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
+ attr->ar_debug_ptr,
+ sizeof(Dwarf_Unsigned));
+ *return_uval = ret_value;
+ return DW_DLV_OK;
+ }
+ break;
+ case DW_FORM_udata:
+ ret_value =
+ (_dwarf_decode_u_leb128(attr->ar_debug_ptr, NULL));
+ *return_uval = ret_value;
+ return DW_DLV_OK;
+
+
+ /* IRIX bug 583450. We do not allow reading sdata from a udata
+ value. Caller can retry, calling sdata */
+
+
+ default:
+ break;
+ }
+ _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_BAD);
+ return (DW_DLV_ERROR);
+}
+
+
+int
+dwarf_formsdata(Dwarf_Attribute attr,
+ Dwarf_Signed * return_sval, Dwarf_Error * error)
+{
+ Dwarf_Signed ret_value = 0;
+ Dwarf_Debug dbg = 0;
+ Dwarf_CU_Context cu_context = 0;
+
+ int res = get_attr_dbg(&dbg,&cu_context,attr,error);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ switch (attr->ar_attribute_form) {
+
+ case DW_FORM_data1:
+ *return_sval = (*(Dwarf_Sbyte *) attr->ar_debug_ptr);
+ return DW_DLV_OK;
+
+ /* READ_UNALIGNED does not sign extend.
+ So we have to use a cast to get the
+ value sign extended in the right way for each case. */
+ case DW_FORM_data2:{
+ READ_UNALIGNED(dbg, ret_value, Dwarf_Signed,
+ attr->ar_debug_ptr,
+ sizeof(Dwarf_Shalf));
+ *return_sval = (Dwarf_Shalf) ret_value;
+ return DW_DLV_OK;
+
+ }
+
+ case DW_FORM_data4:{
+ READ_UNALIGNED(dbg, ret_value, Dwarf_Signed,
+ attr->ar_debug_ptr,
+ sizeof(Dwarf_sfixed));
+ *return_sval = (Dwarf_sfixed) ret_value;
+ return DW_DLV_OK;
+ }
+
+ case DW_FORM_data8:{
+ READ_UNALIGNED(dbg, ret_value, Dwarf_Signed,
+ attr->ar_debug_ptr,
+ sizeof(Dwarf_Signed));
+ *return_sval = (Dwarf_Signed) ret_value;
+ return DW_DLV_OK;
+ }
+
+ case DW_FORM_sdata:
+ ret_value =
+ (_dwarf_decode_s_leb128(attr->ar_debug_ptr, NULL));
+ *return_sval = ret_value;
+ return DW_DLV_OK;
+
+ /* IRIX bug 583450. We do not allow reading sdata from a udata
+ value. Caller can retry, calling udata */
+
+ default:
+ break;
+ }
+ _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_BAD);
+ return (DW_DLV_ERROR);
+}
+
+
+int
+dwarf_formblock(Dwarf_Attribute attr,
+ Dwarf_Block ** return_block, Dwarf_Error * error)
+{
+ Dwarf_CU_Context cu_context = 0;
+ Dwarf_Debug dbg = 0;
+ Dwarf_Unsigned length = 0;
+ Dwarf_Small *data = 0;
+ Dwarf_Word leb128_length = 0;
+ Dwarf_Block *ret_block = 0;
+
+ int res = get_attr_dbg(&dbg,&cu_context,attr,error);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ switch (attr->ar_attribute_form) {
+
+ case DW_FORM_block1:
+ length = *(Dwarf_Small *) attr->ar_debug_ptr;
+ data = attr->ar_debug_ptr + sizeof(Dwarf_Small);
+ break;
+
+ case DW_FORM_block2:
+ READ_UNALIGNED(dbg, length, Dwarf_Unsigned,
+ attr->ar_debug_ptr, sizeof(Dwarf_Half));
+ data = attr->ar_debug_ptr + sizeof(Dwarf_Half);
+ break;
+
+ case DW_FORM_block4:
+ READ_UNALIGNED(dbg, length, Dwarf_Unsigned,
+ attr->ar_debug_ptr, sizeof(Dwarf_ufixed));
+ data = attr->ar_debug_ptr + sizeof(Dwarf_ufixed);
+ break;
+
+ case DW_FORM_block:
+ length = _dwarf_decode_u_leb128(attr->ar_debug_ptr,
+ &leb128_length);
+ data = attr->ar_debug_ptr + leb128_length;
+ break;
+
+ default:
+ _dwarf_error(cu_context->cc_dbg, error, DW_DLE_ATTR_FORM_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ /* Check that block lies within current cu in .debug_info. */
+ if (attr->ar_debug_ptr + length >=
+ dbg->de_debug_info.dss_data + cu_context->cc_debug_offset +
+ cu_context->cc_length + cu_context->cc_length_size +
+ cu_context->cc_extension_size) {
+ _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_SIZE_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ ret_block = (Dwarf_Block *) _dwarf_get_alloc(dbg, DW_DLA_BLOCK, 1);
+ if (ret_block == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ ret_block->bl_len = length;
+ ret_block->bl_data = (Dwarf_Ptr) data;
+ ret_block->bl_from_loclist = 0;
+ ret_block->bl_section_offset = data - dbg->de_debug_info.dss_data;
+
+
+ *return_block = ret_block;
+ return (DW_DLV_OK);
+}
+
+
+/* Contrary to long standing documentation,
+ The string pointer returned thru return_str must
+ never have dwarf_dealloc() applied to it.
+ Documentation fixed July 2005.
+*/
+int
+dwarf_formstring(Dwarf_Attribute attr,
+ char **return_str, Dwarf_Error * error)
+{
+ Dwarf_CU_Context cu_context = 0;
+ Dwarf_Debug dbg = 0;
+ Dwarf_Unsigned offset = 0;
+ int res = DW_DLV_ERROR;
+
+ res = get_attr_dbg(&dbg,&cu_context,attr,error);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ if (attr->ar_attribute_form == DW_FORM_string) {
+
+ void *begin = attr->ar_debug_ptr;
+
+ if (0 == dbg->de_assume_string_in_bounds) {
+ /* Check that string lies within current cu in .debug_info.
+ */
+ void *end = dbg->de_debug_info.dss_data +
+ cu_context->cc_debug_offset +
+ cu_context->cc_length + cu_context->cc_length_size +
+ cu_context->cc_extension_size;
+ if (0 == _dwarf_string_valid(begin, end)) {
+ _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_SIZE_BAD);
+ return (DW_DLV_ERROR);
+ }
+ }
+ *return_str = (char *) (begin);
+ return DW_DLV_OK;
+ }
+
+ if (attr->ar_attribute_form == DW_FORM_strp) {
+ READ_UNALIGNED(dbg, offset, Dwarf_Unsigned,
+ attr->ar_debug_ptr,
+ cu_context->cc_length_size);
+
+ res = _dwarf_load_section(dbg, &dbg->de_debug_str,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ if (0 == dbg->de_assume_string_in_bounds) {
+ /* Check that string lies within current cu in .debug_info.
+ */
+ void *end = dbg->de_debug_str.dss_data +
+ dbg->de_debug_str.dss_size;
+ void*begin = dbg->de_debug_str.dss_data + offset;
+ if (0 == _dwarf_string_valid(begin, end)) {
+ _dwarf_error(dbg, error, DW_DLE_STRP_OFFSET_BAD);
+ return (DW_DLV_ERROR);
+ }
+ }
+
+ /* Ensure the offset lies within the .debug_str */
+ if (offset >= dbg->de_debug_str.dss_size) {
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_STR_OFFSET_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ *return_str = (char *) (dbg->de_debug_str.dss_data + offset);
+ return DW_DLV_OK;
+ }
+
+ _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_BAD);
+ return (DW_DLV_ERROR);
+}
+
+int
+dwarf_formexprloc(Dwarf_Attribute attr,
+ Dwarf_Unsigned * return_exprlen,
+ Dwarf_Ptr * block_ptr,
+ Dwarf_Error * error)
+{
+ Dwarf_Debug dbg = 0;
+ Dwarf_CU_Context cu_context = 0;
+
+ int res = get_attr_dbg(&dbg,&cu_context,attr,error);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ if (dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+ if (attr->ar_attribute_form == DW_FORM_exprloc ) {
+ Dwarf_Word leb_len = 0;
+ Dwarf_Unsigned exprlen =
+ (_dwarf_decode_u_leb128(attr->ar_debug_ptr, &leb_len));
+ Dwarf_Small * addr = attr->ar_debug_ptr;
+ *return_exprlen = exprlen;
+ *block_ptr = addr + leb_len;
+ return DW_DLV_OK;
+
+ }
+ _dwarf_error(dbg, error, DW_DLE_ATTR_EXPRLOC_FORM_BAD);
+ return (DW_DLV_ERROR);
+}
diff --git a/libdwarf/dwarf_frame.c b/libdwarf/dwarf_frame.c
new file mode 100644
index 0000000..1d327f0
--- /dev/null
+++ b/libdwarf/dwarf_frame.c
@@ -0,0 +1,2431 @@
+/*
+
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "dwarf_frame.h"
+#include "dwarf_arange.h" /* Using Arange as a way to build a list */
+
+#define FDE_NULL_CHECKS_AND_SET_DBG(fde,dbg ) \
+ do { \
+ if ((fde) == NULL) { \
+ _dwarf_error(NULL, error, DW_DLE_FDE_NULL);\
+ return (DW_DLV_ERROR); \
+ } \
+ (dbg)= (fde)->fd_dbg; \
+ if ((dbg) == NULL) { \
+ _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL);\
+ return (DW_DLV_ERROR); \
+ } } while (0)
+
+
+#define MIN(a,b) (((a) < (b))? a:b)
+
+static int dwarf_initialize_fde_table(Dwarf_Debug dbg,
+ struct Dwarf_Frame_s *fde_table,
+ unsigned table_real_data_size,
+ Dwarf_Error * error);
+static void dwarf_free_fde_table(struct Dwarf_Frame_s *fde_table);
+static void dwarf_init_reg_rules_ru(struct Dwarf_Reg_Rule_s *base,
+ unsigned first, unsigned last,int initial_value);
+static void dwarf_init_reg_rules_dw(struct Dwarf_Regtable_Entry_s *base,
+ unsigned first, unsigned last,int initial_value);
+static void dwarf_init_reg_rules_dw3(struct Dwarf_Regtable_Entry3_s *base,
+ unsigned first, unsigned last,int initial_value);
+
+
+#if 0
+/* Only used for debugging libdwarf. */
+static void dump_frame_rule(char *msg,
+ struct Dwarf_Reg_Rule_s *reg_rule);
+#endif
+
+
+
+/*
+ This function is the heart of the debug_frame stuff. Don't even
+ think of reading this without reading both the Libdwarf and
+ consumer API carefully first. This function basically executes
+ frame instructions contained in a Cie or an Fde, but does in a
+ number of different ways depending on the information sought.
+ Start_instr_ptr points to the first byte of the frame instruction
+ stream, and final_instr_ptr to the to the first byte after the
+ last.
+
+ The offsets returned in the frame instructions are factored. That
+ is they need to be multiplied by either the code_alignment_factor
+ or the data_alignment_factor, as appropriate to obtain the actual
+ offset. This makes it possible to expand an instruction stream
+ without the corresponding Cie. However, when an Fde frame instr
+ sequence is being expanded there must be a valid Cie with a pointer
+ to an initial table row.
+
+
+ If successful, returns DW_DLV_OK
+ And sets returned_count thru the pointer
+ if make_instr is true.
+ If make_instr is false returned_count
+ should NOT be used by the caller (returned_count
+ is set to 0 thru the pointer by this routine...)
+ If unsuccessful, returns DW_DLV_ERROR
+ and sets returned_error to the error code
+
+ It does not do a whole lot of input validation being a private
+ function. Please make sure inputs are valid.
+
+ (1) If make_instr is true, it makes a list of pointers to
+ Dwarf_Frame_Op structures containing the frame instructions
+ executed. A pointer to this list is returned in ret_frame_instr.
+ Make_instr is true only when a list of frame instructions is to be
+ returned. In this case since we are not interested in the contents
+ of the table, the input Cie can be NULL. This is the only case
+ where the inpute Cie can be NULL.
+
+ (2) If search_pc is true, frame instructions are executed till
+ either a location is reached that is greater than the search_pc_val
+ provided, or all instructions are executed. At this point the
+ last row of the table generated is returned in a structure.
+ A pointer to this structure is supplied in table.
+
+ (3) This function is also used to create the initial table row
+ defined by a Cie. In this case, the Dwarf_Cie pointer cie, is
+ NULL. For an FDE, however, cie points to the associated Cie.
+
+ make_instr - make list of frame instr? 0/1
+ ret_frame_instr - Ptr to list of ptrs to frame instrs
+ search_pc - Search for a pc value? 0/1
+ search_pc_val - Search for this pc value
+ initial_loc - Initial code location value.
+ start_instr_ptr - Ptr to start of frame instrs.
+ final_instr_ptr - Ptr just past frame instrs.
+ table - Ptr to struct with last row.
+ cie - Ptr to Cie used by the Fde.
+
+ Different cies may have distinct address-sizes, so the cie
+ is used, not de_pointer_size.
+
+*/
+
+int
+_dwarf_exec_frame_instr(Dwarf_Bool make_instr,
+ Dwarf_Frame_Op ** ret_frame_instr,
+ Dwarf_Bool search_pc,
+ Dwarf_Addr search_pc_val,
+ Dwarf_Addr initial_loc,
+ Dwarf_Small * start_instr_ptr,
+ Dwarf_Small * final_instr_ptr,
+ Dwarf_Frame table,
+ Dwarf_Cie cie,
+ Dwarf_Debug dbg,
+ Dwarf_Half reg_num_of_cfa,
+ Dwarf_Sword * returned_count,
+ int *returned_error)
+{
+#define ERROR_IF_REG_NUM_TOO_HIGH(macreg,machigh_reg) \
+ do { \
+ if ((macreg) >= (machigh_reg) || (macreg) < 0) { \
+ SIMPLE_ERROR_RETURN(DW_DLE_DF_REG_NUM_TOO_HIGH); \
+ } \
+ } /*CONSTCOND */ while(0)
+#define SIMPLE_ERROR_RETURN(code) \
+ free(localregtab); \
+ *returned_error = code; \
+ return DW_DLV_ERROR
+
+ /* Sweeps the frame instructions. */
+ Dwarf_Small *instr_ptr;
+
+ /* Register numbers not limited to just 255, thus not using
+ Dwarf_Small. */
+ typedef int reg_num_type;
+
+ Dwarf_Unsigned factored_N_value;
+ Dwarf_Signed signed_factored_N_value;
+ Dwarf_Addr current_loc = initial_loc; /* code location/
+ pc-value corresponding to the frame instructions.
+ Starts at zero when the caller has no value to pass in. */
+
+ /* Must be min de_pointer_size bytes and must be at least sizeof
+ Dwarf_ufixed */
+ Dwarf_Unsigned adv_loc = 0;
+
+ int reg_count = dbg->de_frame_reg_rules_entry_count;
+ struct Dwarf_Reg_Rule_s *localregtab = calloc(reg_count,
+ sizeof(struct Dwarf_Reg_Rule_s));
+
+ struct Dwarf_Reg_Rule_s cfa_reg;
+
+
+ /* This is used to end executing frame instructions. */
+ /* Becomes true when search_pc is true and current_loc */
+ /* is greater than search_pc_val. */
+ Dwarf_Bool search_over = false;
+
+ /* Used by the DW_FRAME_advance_loc instr */
+ /* to hold the increment in pc value. */
+ Dwarf_Addr adv_pc;
+
+ /* Contains the length in bytes of */
+ /* an leb128 encoded number. */
+ Dwarf_Word leb128_length;
+
+ Dwarf_Half address_size = (cie)? cie->ci_address_size:
+ dbg->de_pointer_size;
+
+ /* Counts the number of frame instructions executed. */
+ Dwarf_Word instr_count = 0;
+
+ /* These contain the current fields of the current frame
+ instruction. */
+ Dwarf_Small fp_base_op = 0;
+ Dwarf_Small fp_extended_op;
+ reg_num_type fp_register;
+
+ /* The value in fp_offset may be signed, though we call it
+ unsigned. This works ok for 2-s complement arithmetic. */
+ Dwarf_Unsigned fp_offset;
+ Dwarf_Off fp_instr_offset;
+
+ /* Stack_table points to the row (Dwarf_Frame ie) being pushed or
+ popped by a remember or restore instruction. Top_stack points to
+ the top of the stack of rows. */
+ Dwarf_Frame stack_table = NULL;
+ Dwarf_Frame top_stack = NULL;
+
+ /* These are used only when make_instr is true. Curr_instr is a
+ pointer to the current frame instruction executed.
+ Curr_instr_ptr, head_instr_list, and curr_instr_list are used to
+ form a chain of Dwarf_Frame_Op structs. Dealloc_instr_ptr is
+ used to deallocate the structs used to form the chain.
+ Head_instr_block points to a contiguous list of pointers to the
+ Dwarf_Frame_Op structs executed. */
+ Dwarf_Frame_Op *curr_instr;
+ Dwarf_Chain curr_instr_item, dealloc_instr_item;
+ Dwarf_Chain head_instr_chain = NULL;
+ Dwarf_Chain tail_instr_chain = NULL;
+ Dwarf_Frame_Op *head_instr_block;
+
+ /* These are the alignment_factors taken from the Cie provided.
+ When no input Cie is provided they are set to 1, because only
+ factored offsets are required. */
+ Dwarf_Sword code_alignment_factor = 1;
+ Dwarf_Sword data_alignment_factor = 1;
+
+ /* This flag indicates when an actual alignment factor is needed.
+ So if a frame instruction that computes an offset using an
+ alignment factor is encountered when this flag is set, an error
+ is returned because the Cie did not have a valid augmentation. */
+ Dwarf_Bool need_augmentation = false;
+
+ Dwarf_Word i;
+
+ /* Initialize first row from associated Cie. Using temp regs
+ explicity */
+
+ if (localregtab == 0) {
+ SIMPLE_ERROR_RETURN(DW_DLE_ALLOC_FAIL);
+ }
+ {
+ struct Dwarf_Reg_Rule_s *t1reg = localregtab;
+ if (cie != NULL && cie->ci_initial_table != NULL) {
+ unsigned minregcount = 0;
+ unsigned curreg = 0;
+ struct Dwarf_Reg_Rule_s *t2reg = cie->ci_initial_table->fr_reg;
+
+ if (reg_count != cie->ci_initial_table->fr_reg_count) {
+ /* Should never happen, it makes no sense to have the
+ table sizes change. There is no real allowance for
+ the set of registers to change dynamically in a
+ single Dwarf_Debug (except the size can be set near
+ initial Dwarf_Debug creation time). */
+ SIMPLE_ERROR_RETURN
+ (DW_DLE_FRAME_REGISTER_COUNT_MISMATCH);
+ }
+ minregcount = MIN(reg_count,cie->ci_initial_table->fr_reg_count);
+ for (; curreg < minregcount ;curreg++, t1reg++, t2reg++) {
+ *t1reg = *t2reg;
+ }
+ cfa_reg = cie->ci_initial_table->fr_cfa_rule;
+ } else {
+ dwarf_init_reg_rules_ru(localregtab,0,reg_count,
+ dbg->de_frame_rule_initial_value);
+ dwarf_init_reg_rules_ru(&cfa_reg,0, 1,
+ dbg->de_frame_rule_initial_value);
+ }
+ }
+
+ /* The idea here is that the code_alignment_factor and
+ data_alignment_factor which are needed for certain instructions
+ are valid only when the Cie has a proper augmentation string. So
+ if the augmentation is not right, only Frame instruction can be
+ read. */
+ if (cie != NULL && cie->ci_augmentation != NULL) {
+ code_alignment_factor = cie->ci_code_alignment_factor;
+ data_alignment_factor = cie->ci_data_alignment_factor;
+ } else {
+ need_augmentation = !make_instr;
+ }
+
+ instr_ptr = start_instr_ptr;
+ while ((instr_ptr < final_instr_ptr) && (!search_over)) {
+ Dwarf_Small instr = 0;
+ Dwarf_Small opcode = 0;
+ reg_num_type reg_no = 0;
+
+ fp_instr_offset = instr_ptr - start_instr_ptr;
+ instr = *(Dwarf_Small *) instr_ptr;
+ instr_ptr += sizeof(Dwarf_Small);
+
+ fp_base_op = (instr & 0xc0) >> 6;
+ if ((instr & 0xc0) == 0x00) {
+ opcode = instr; /* is really extended op */
+ fp_extended_op = (instr & (~(0xc0))) & 0xff;
+ } else {
+ opcode = instr & 0xc0; /* is base op */
+ fp_extended_op = 0;
+ }
+
+ fp_register = 0;
+ fp_offset = 0;
+ switch (opcode) {
+ case DW_CFA_advance_loc:
+ {
+ /* base op */
+ fp_offset = adv_pc = instr & DW_FRAME_INSTR_OFFSET_MASK;
+
+ if (need_augmentation) {
+ SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION);
+ }
+ adv_pc = adv_pc * code_alignment_factor;
+
+ search_over = search_pc &&
+ (current_loc + adv_pc > search_pc_val);
+ /* If gone past pc needed, retain old pc. */
+ if (!search_over) {
+ current_loc = current_loc + adv_pc;
+ }
+ break;
+ }
+
+ case DW_CFA_offset:
+ { /* base op */
+ reg_no =
+ (reg_num_type) (instr & DW_FRAME_INSTR_OFFSET_MASK);
+ ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
+
+ factored_N_value =
+ _dwarf_decode_u_leb128(instr_ptr, &leb128_length);
+ instr_ptr = instr_ptr + leb128_length;
+
+ fp_register = reg_no;
+ fp_offset = factored_N_value;
+
+ if (need_augmentation) {
+ SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION);
+ }
+
+ localregtab[reg_no].ru_is_off = 1;
+ localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET;
+ localregtab[reg_no].ru_register = reg_num_of_cfa;
+ localregtab[reg_no].ru_offset_or_block_len =
+ factored_N_value * data_alignment_factor;
+
+ break;
+ }
+
+ case DW_CFA_restore:
+ { /* base op */
+ reg_no = (instr & DW_FRAME_INSTR_OFFSET_MASK);
+ ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
+
+ fp_register = reg_no;
+
+ if (cie != NULL && cie->ci_initial_table != NULL)
+ localregtab[reg_no] =
+ cie->ci_initial_table->fr_reg[reg_no];
+ else if (!make_instr) {
+ SIMPLE_ERROR_RETURN(DW_DLE_DF_MAKE_INSTR_NO_INIT);
+ }
+
+ break;
+ }
+ case DW_CFA_set_loc:
+ {
+ Dwarf_Addr new_loc = 0;
+
+ READ_UNALIGNED(dbg, new_loc, Dwarf_Addr,
+ instr_ptr, address_size);
+ instr_ptr += address_size;
+ if (new_loc != 0 && current_loc != 0) {
+ /* Pre-relocation or before current_loc is set the
+ test comparing new_loc and current_loc makes no
+ sense. Testing for non-zero (above) is a way
+ (fallible) to check that current_loc, new_loc
+ are already relocated. */
+ if (new_loc <= current_loc) {
+ /* Within a frame, address must increase.
+ Seemingly it has not. Seems to be an error. */
+
+ SIMPLE_ERROR_RETURN
+ (DW_DLE_DF_NEW_LOC_LESS_OLD_LOC);
+ }
+ }
+
+ search_over = search_pc && (new_loc > search_pc_val);
+
+ /* If gone past pc needed, retain old pc. */
+ if (!search_over) {
+ current_loc = new_loc;
+ }
+ fp_offset = new_loc;
+ break;
+ }
+
+ case DW_CFA_advance_loc1:
+ {
+ fp_offset = adv_loc = *(Dwarf_Small *) instr_ptr;
+ instr_ptr += sizeof(Dwarf_Small);
+
+ if (need_augmentation) {
+ SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION);
+ }
+ adv_loc *= code_alignment_factor;
+
+ search_over = search_pc &&
+ (current_loc + adv_loc > search_pc_val);
+
+ /* If gone past pc needed, retain old pc. */
+ if (!search_over) {
+ current_loc = current_loc + adv_loc;
+ }
+ break;
+ }
+
+ case DW_CFA_advance_loc2:
+ {
+ READ_UNALIGNED(dbg, adv_loc, Dwarf_Unsigned,
+ instr_ptr, sizeof(Dwarf_Half));
+ instr_ptr += sizeof(Dwarf_Half);
+ fp_offset = adv_loc;
+
+ if (need_augmentation) {
+ SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION);
+ }
+ adv_loc *= code_alignment_factor;
+
+ search_over = search_pc &&
+ (current_loc + adv_loc > search_pc_val);
+
+ /* If gone past pc needed, retain old pc. */
+ if (!search_over) {
+ current_loc = current_loc + adv_loc;
+ }
+ break;
+ }
+
+ case DW_CFA_advance_loc4:
+ {
+ READ_UNALIGNED(dbg, adv_loc, Dwarf_Unsigned,
+ instr_ptr, sizeof(Dwarf_ufixed));
+ instr_ptr += sizeof(Dwarf_ufixed);
+ fp_offset = adv_loc;
+
+ if (need_augmentation) {
+ SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION);
+ }
+ adv_loc *= code_alignment_factor;
+
+ search_over = search_pc &&
+ (current_loc + adv_loc > search_pc_val);
+
+ /* If gone past pc needed, retain old pc. */
+ if (!search_over) {
+ current_loc = current_loc + adv_loc;
+ }
+ break;
+ }
+
+ case DW_CFA_offset_extended:
+ {
+ Dwarf_Unsigned lreg;
+
+ DECODE_LEB128_UWORD(instr_ptr, lreg);
+ reg_no = (reg_num_type) lreg;
+ ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);;
+ factored_N_value =
+ _dwarf_decode_u_leb128(instr_ptr, &leb128_length);
+ instr_ptr += leb128_length;
+
+ if (need_augmentation) {
+ SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION);
+ }
+ localregtab[reg_no].ru_is_off = 1;
+ localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET;
+ localregtab[reg_no].ru_register = reg_num_of_cfa;
+ localregtab[reg_no].ru_offset_or_block_len = factored_N_value *
+ data_alignment_factor;
+
+ fp_register = reg_no;
+ fp_offset = factored_N_value;
+ break;
+ }
+
+ case DW_CFA_restore_extended:
+ {
+ Dwarf_Unsigned lreg;
+
+ DECODE_LEB128_UWORD(instr_ptr, lreg);
+ reg_no = (reg_num_type) lreg;
+
+ ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
+
+ if (cie != NULL && cie->ci_initial_table != NULL) {
+ localregtab[reg_no] = cie->ci_initial_table->fr_reg[reg_no];
+ } else {
+ if (!make_instr) {
+ SIMPLE_ERROR_RETURN
+ (DW_DLE_DF_MAKE_INSTR_NO_INIT);
+ }
+ }
+
+ fp_register = reg_no;
+ break;
+ }
+
+ case DW_CFA_undefined:
+ {
+ Dwarf_Unsigned lreg;
+
+ DECODE_LEB128_UWORD(instr_ptr, lreg);
+ reg_no = (reg_num_type) lreg;
+ ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
+
+ localregtab[reg_no].ru_is_off = 0;
+ localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET;
+ localregtab[reg_no].ru_register =
+ dbg->de_frame_undefined_value_number;
+ localregtab[reg_no].ru_offset_or_block_len = 0;
+
+ fp_register = reg_no;
+ break;
+ }
+
+ case DW_CFA_same_value:
+ {
+ Dwarf_Unsigned lreg;
+
+ DECODE_LEB128_UWORD(instr_ptr, lreg);
+ reg_no = (reg_num_type) lreg;
+ ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
+
+ localregtab[reg_no].ru_is_off = 0;
+ localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET;
+ localregtab[reg_no].ru_register =
+ dbg->de_frame_same_value_number;
+ localregtab[reg_no].ru_offset_or_block_len = 0;
+ fp_register = reg_no;
+ break;
+ }
+
+ case DW_CFA_register:
+ {
+ Dwarf_Unsigned lreg;
+ reg_num_type reg_noA = 0;
+ reg_num_type reg_noB = 0;
+
+ DECODE_LEB128_UWORD(instr_ptr, lreg);
+ reg_noA = (reg_num_type) lreg;
+
+ ERROR_IF_REG_NUM_TOO_HIGH(reg_noA, reg_count);
+
+ DECODE_LEB128_UWORD(instr_ptr, lreg);
+ reg_noB = (reg_num_type) lreg;
+
+ if (reg_noB > reg_count) {
+ SIMPLE_ERROR_RETURN(DW_DLE_DF_REG_NUM_TOO_HIGH);
+ }
+
+
+ localregtab[reg_noA].ru_is_off = 0;
+ localregtab[reg_noA].ru_value_type = DW_EXPR_OFFSET;
+ localregtab[reg_noA].ru_register = reg_noB;
+ localregtab[reg_noA].ru_offset_or_block_len = 0;
+
+ fp_register = reg_noA;
+ fp_offset = reg_noB;
+ break;
+ }
+
+ case DW_CFA_remember_state:
+ {
+ stack_table = (Dwarf_Frame)
+ _dwarf_get_alloc(dbg, DW_DLA_FRAME, 1);
+ if (stack_table == NULL) {
+ SIMPLE_ERROR_RETURN(DW_DLE_DF_ALLOC_FAIL);
+ }
+
+ for (i = 0; i < reg_count; i++)
+ stack_table->fr_reg[i] = localregtab[i];
+ stack_table->fr_cfa_rule = cfa_reg;
+
+ if (top_stack != NULL)
+ stack_table->fr_next = top_stack;
+ top_stack = stack_table;
+
+ break;
+ }
+
+ case DW_CFA_restore_state:
+ {
+ if (top_stack == NULL) {
+ SIMPLE_ERROR_RETURN(DW_DLE_DF_POP_EMPTY_STACK);
+ }
+ stack_table = top_stack;
+ top_stack = stack_table->fr_next;
+
+ for (i = 0; i < reg_count; i++)
+ localregtab[i] = stack_table->fr_reg[i];
+ cfa_reg = stack_table->fr_cfa_rule;
+
+ dwarf_dealloc(dbg, stack_table, DW_DLA_FRAME);
+ break;
+ }
+
+ case DW_CFA_def_cfa:
+ {
+ Dwarf_Unsigned lreg;
+
+ DECODE_LEB128_UWORD(instr_ptr, lreg);
+ reg_no = (reg_num_type) lreg;
+
+ ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
+
+ factored_N_value =
+ _dwarf_decode_u_leb128(instr_ptr, &leb128_length);
+ instr_ptr += leb128_length;
+
+ if (need_augmentation) {
+ SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION);
+ }
+ cfa_reg.ru_is_off = 1;
+ cfa_reg.ru_value_type = DW_EXPR_OFFSET;
+ cfa_reg.ru_register = reg_no;
+ cfa_reg.ru_offset_or_block_len = factored_N_value;
+
+ fp_register = reg_no;
+ fp_offset = factored_N_value;
+ break;
+ }
+
+ case DW_CFA_def_cfa_register:
+ {
+ Dwarf_Unsigned lreg;
+
+ DECODE_LEB128_UWORD(instr_ptr, lreg);
+ reg_no = (reg_num_type) lreg;
+ ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
+
+ cfa_reg.ru_register = reg_no;
+ /* Do NOT set ru_offset_or_block_len or ru_is_off here.
+ See dwarf2/3 spec. */
+ fp_register = reg_no;
+ break;
+ }
+
+ case DW_CFA_def_cfa_offset:
+ {
+ factored_N_value =
+ _dwarf_decode_u_leb128(instr_ptr, &leb128_length);
+ instr_ptr += leb128_length;
+
+ if (need_augmentation) {
+ SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION);
+ }
+ /* Do set ru_is_off here, as here factored_N_value
+ counts. */
+ cfa_reg.ru_is_off = 1;
+ cfa_reg.ru_value_type = DW_EXPR_OFFSET;
+ cfa_reg.ru_offset_or_block_len = factored_N_value;
+
+ fp_offset = factored_N_value;
+ break;
+ }
+ case DW_CFA_nop:
+ {
+ break;
+ }
+ /* DWARF3 ops begin here. */
+ case DW_CFA_def_cfa_expression:
+ {
+ /* A single DW_FORM_block representing a dwarf
+ expression. The form block establishes the way to
+ compute the CFA. */
+ Dwarf_Unsigned block_len = 0;
+
+ DECODE_LEB128_UWORD(instr_ptr, block_len);
+ cfa_reg.ru_is_off = 0; /* arbitrary */
+ cfa_reg.ru_value_type = DW_EXPR_EXPRESSION;
+ cfa_reg.ru_offset_or_block_len = block_len;
+ cfa_reg.ru_block = instr_ptr;
+ fp_offset = (Dwarf_Unsigned) instr_ptr;
+ instr_ptr += block_len;
+ }
+ break;
+ case DW_CFA_expression:
+ {
+ /* An unsigned leb128 value is the first operand (a
+ register number). The second operand is single
+ DW_FORM_block representing a dwarf expression. The
+ evaluator pushes the CFA on the evaluation stack
+ then evaluates the expression to compute the value
+ of the register contents. */
+ Dwarf_Unsigned lreg = 0;
+ Dwarf_Unsigned block_len = 0;
+
+ DECODE_LEB128_UWORD(instr_ptr, lreg);
+ reg_no = (reg_num_type) lreg;
+ ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
+ DECODE_LEB128_UWORD(instr_ptr, block_len);
+ localregtab[lreg].ru_is_off = 0; /* arbitrary */
+ localregtab[lreg].ru_value_type = DW_EXPR_EXPRESSION;
+ localregtab[lreg].ru_offset_or_block_len = block_len;
+ localregtab[lreg].ru_block = instr_ptr;
+ fp_offset = (Dwarf_Unsigned) instr_ptr;
+ fp_register = reg_no;
+ instr_ptr += block_len;
+ }
+ break;
+ case DW_CFA_offset_extended_sf:
+ {
+ /* The first operand is an unsigned leb128 register
+ number. The second is a signed factored offset.
+ Identical to DW_CFA_offset_extended except the
+ second operand is signed */
+ Dwarf_Unsigned lreg;
+
+ DECODE_LEB128_UWORD(instr_ptr, lreg);
+ reg_no = (reg_num_type) lreg;
+ ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
+ signed_factored_N_value =
+ _dwarf_decode_s_leb128(instr_ptr, &leb128_length);
+ instr_ptr += leb128_length;
+
+ if (need_augmentation) {
+ SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION);
+ }
+ localregtab[reg_no].ru_is_off = 1;
+ localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET;
+ localregtab[reg_no].ru_register = reg_num_of_cfa;
+ localregtab[reg_no].ru_offset_or_block_len =
+ signed_factored_N_value * data_alignment_factor;
+
+ fp_register = reg_no;
+ fp_offset = signed_factored_N_value;
+ }
+ break;
+ case DW_CFA_def_cfa_sf:
+ {
+ /* The first operand is an unsigned leb128 register
+ number. The second is a signed leb128 factored
+ offset. Identical to DW_CFA_def_cfa except that the
+ second operand is signed and factored. */
+ Dwarf_Unsigned lreg;
+
+ DECODE_LEB128_UWORD(instr_ptr, lreg);
+ reg_no = (reg_num_type) lreg;
+ ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
+
+ signed_factored_N_value =
+ _dwarf_decode_s_leb128(instr_ptr, &leb128_length);
+ instr_ptr += leb128_length;
+
+ if (need_augmentation) {
+ SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION);
+ }
+ cfa_reg.ru_is_off = 1;
+ cfa_reg.ru_value_type = DW_EXPR_OFFSET;
+ cfa_reg.ru_register = reg_no;
+ cfa_reg.ru_offset_or_block_len =
+ signed_factored_N_value * data_alignment_factor;
+
+ fp_register = reg_no;
+ fp_offset = signed_factored_N_value;
+ }
+ break;
+ case DW_CFA_def_cfa_offset_sf:
+ {
+ /* The operand is a signed leb128 operand representing
+ a factored offset. Identical to
+ DW_CFA_def_cfa_offset excep the operand is signed
+ and factored. */
+
+ signed_factored_N_value =
+ _dwarf_decode_s_leb128(instr_ptr, &leb128_length);
+ instr_ptr += leb128_length;
+
+ if (need_augmentation) {
+ SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION);
+ }
+ /* Do set ru_is_off here, as here factored_N_value
+ counts. */
+ cfa_reg.ru_is_off = 1;
+ cfa_reg.ru_value_type = DW_EXPR_OFFSET;
+ cfa_reg.ru_offset_or_block_len =
+ signed_factored_N_value * data_alignment_factor;
+
+ fp_offset = signed_factored_N_value;
+ }
+ break;
+ case DW_CFA_val_offset:
+ {
+ /* The first operand is an unsigned leb128 register
+ number. The second is a factored unsigned offset.
+ Makes the register be a val_offset(N) rule with N =
+ factored_offset*data_alignment_factor. */
+
+ Dwarf_Unsigned lreg;
+
+ DECODE_LEB128_UWORD(instr_ptr, lreg);
+ reg_no = (reg_num_type) lreg;
+
+ ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
+
+ factored_N_value =
+ _dwarf_decode_u_leb128(instr_ptr, &leb128_length);
+ instr_ptr += leb128_length;
+
+ if (need_augmentation) {
+ SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION);
+ }
+ /* Do set ru_is_off here, as here factored_N_value
+ counts. */
+ localregtab[reg_no].ru_is_off = 1;
+ localregtab[reg_no].ru_register = reg_num_of_cfa;
+ localregtab[reg_no].ru_value_type = DW_EXPR_VAL_OFFSET;
+ localregtab[reg_no].ru_offset_or_block_len =
+ factored_N_value * data_alignment_factor;
+
+ fp_offset = factored_N_value;
+ break;
+ }
+ case DW_CFA_val_offset_sf:
+ {
+ /* The first operand is an unsigned leb128 register
+ number. The second is a factored signed offset.
+ Makes the register be a val_offset(N) rule with N =
+ factored_offset*data_alignment_factor. */
+ Dwarf_Unsigned lreg;
+
+ DECODE_LEB128_UWORD(instr_ptr, lreg);
+ reg_no = (reg_num_type) lreg;
+
+ ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
+ signed_factored_N_value =
+ _dwarf_decode_s_leb128(instr_ptr, &leb128_length);
+ instr_ptr += leb128_length;
+
+ if (need_augmentation) {
+ SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION);
+ }
+ /* Do set ru_is_off here, as here factored_N_value
+ counts. */
+ localregtab[reg_no].ru_is_off = 1;
+ localregtab[reg_no].ru_value_type = DW_EXPR_VAL_OFFSET;
+ localregtab[reg_no].ru_offset_or_block_len =
+ signed_factored_N_value * data_alignment_factor;
+
+ fp_offset = signed_factored_N_value;
+
+ }
+ break;
+ case DW_CFA_val_expression:
+ {
+ /* The first operand is an unsigned leb128 register
+ number. The second is a DW_FORM_block representing a
+ DWARF expression. The rule for the register number
+ becomes a val_expression(E) rule. */
+ Dwarf_Unsigned lreg = 0;
+ Dwarf_Unsigned block_len = 0;
+
+ DECODE_LEB128_UWORD(instr_ptr, lreg);
+ reg_no = (reg_num_type) lreg;
+ ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
+ DECODE_LEB128_UWORD(instr_ptr, block_len);
+ localregtab[lreg].ru_is_off = 0; /* arbitrary */
+ localregtab[lreg].ru_value_type = DW_EXPR_VAL_EXPRESSION;
+ localregtab[lreg].ru_offset_or_block_len = block_len;
+ localregtab[lreg].ru_block = instr_ptr;
+ fp_offset = (Dwarf_Unsigned) instr_ptr;
+
+ instr_ptr += block_len;
+ fp_register = reg_no;
+
+ }
+ break;
+
+ /* END DWARF3 new ops. */
+
+
+#ifdef DW_CFA_GNU_window_save
+ case DW_CFA_GNU_window_save:
+ {
+ /* No information: this just tells unwinder to restore
+ the window registers from the previous frame's
+ window save area */
+ break;
+ }
+#endif
+#ifdef DW_CFA_GNU_args_size
+ /* Single uleb128 is the current arg area size in bytes. No
+ register exists yet to save this in */
+ case DW_CFA_GNU_args_size:
+ {
+ Dwarf_Unsigned lreg;
+
+ DECODE_LEB128_UWORD(instr_ptr, lreg);
+ reg_no = (reg_num_type) lreg;
+
+ break;
+ }
+#endif
+ default:
+ /* ERROR, we have an opcode we know nothing about. Memory
+ leak here, but an error like this is not supposed to
+ happen so we ignore the leak. These used to be ignored,
+ now we notice and report. */
+ SIMPLE_ERROR_RETURN(DW_DLE_DF_FRAME_DECODING_ERROR);
+
+ }
+
+ if (make_instr) {
+ instr_count++;
+
+ curr_instr = (Dwarf_Frame_Op *)
+ _dwarf_get_alloc(dbg, DW_DLA_FRAME_OP, 1);
+ if (curr_instr == NULL) {
+ SIMPLE_ERROR_RETURN(DW_DLE_DF_ALLOC_FAIL);
+ }
+
+ curr_instr->fp_base_op = fp_base_op;
+ curr_instr->fp_extended_op = fp_extended_op;
+ curr_instr->fp_register = fp_register;
+ curr_instr->fp_offset = fp_offset;
+ curr_instr->fp_instr_offset = fp_instr_offset;
+
+ curr_instr_item = (Dwarf_Chain)
+ _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (curr_instr_item == NULL) {
+ SIMPLE_ERROR_RETURN(DW_DLE_DF_ALLOC_FAIL);
+ }
+
+ curr_instr_item->ch_item = curr_instr;
+ if (head_instr_chain == NULL)
+ head_instr_chain = tail_instr_chain = curr_instr_item;
+ else {
+ tail_instr_chain->ch_next = curr_instr_item;
+ tail_instr_chain = curr_instr_item;
+ }
+ }
+ }
+
+ /* If frame instruction decoding was right we would stop exactly at
+ final_instr_ptr. */
+ if (instr_ptr > final_instr_ptr) {
+ SIMPLE_ERROR_RETURN(DW_DLE_DF_FRAME_DECODING_ERROR);
+ }
+
+ /* Fill in the actual output table, the space the caller passed in. */
+ if (table != NULL) {
+
+ struct Dwarf_Reg_Rule_s *t2reg = table->fr_reg;
+ struct Dwarf_Reg_Rule_s *t3reg = localregtab;
+ unsigned minregcount = MIN(table->fr_reg_count,reg_count);
+ unsigned curreg = 0;
+
+ table->fr_loc = current_loc;
+ for (; curreg < minregcount ; curreg++, t3reg++, t2reg++) {
+ *t2reg = *t3reg;
+ }
+
+ /* CONSTCOND */
+ /* Do not update the main table with the cfa_reg.
+ Just leave cfa_reg as cfa_reg. */
+ table->fr_cfa_rule = cfa_reg;
+ }
+
+ /* Dealloc anything remaining on stack. */
+ for (; top_stack != NULL;) {
+ stack_table = top_stack;
+ top_stack = top_stack->fr_next;
+ dwarf_dealloc(dbg, stack_table, DW_DLA_FRAME);
+ }
+
+ if (make_instr) {
+ /* Allocate list of pointers to Dwarf_Frame_Op's. */
+ head_instr_block = (Dwarf_Frame_Op *)
+ _dwarf_get_alloc(dbg, DW_DLA_FRAME_BLOCK, instr_count);
+ if (head_instr_block == NULL) {
+ SIMPLE_ERROR_RETURN(DW_DLE_DF_ALLOC_FAIL);
+ }
+
+ /* Store pointers to Dwarf_Frame_Op's in this list and
+ deallocate the structs that chain the Dwarf_Frame_Op's. */
+ curr_instr_item = head_instr_chain;
+ for (i = 0; i < instr_count; i++) {
+ *(head_instr_block + i) =
+ *(Dwarf_Frame_Op *) curr_instr_item->ch_item;
+ dealloc_instr_item = curr_instr_item;
+ curr_instr_item = curr_instr_item->ch_next;
+ dwarf_dealloc(dbg, dealloc_instr_item->ch_item,
+ DW_DLA_FRAME_OP);
+ dwarf_dealloc(dbg, dealloc_instr_item, DW_DLA_CHAIN);
+ }
+ *ret_frame_instr = head_instr_block;
+ *returned_count = (Dwarf_Sword) instr_count;
+ } else {
+ *returned_count = 0;
+ }
+ free(localregtab);
+ return DW_DLV_OK;
+#undef ERROR_IF_REG_NUM_TOO_HIGH
+#undef SIMPLE_ERROR_RETURN
+}
+
+/* Depending on version, either read the return address register
+ as a ubyte or as an leb number.
+ The form of this value changed for DWARF3.
+*/
+Dwarf_Unsigned
+_dwarf_get_return_address_reg(Dwarf_Small * frame_ptr,
+ int version, unsigned long *size)
+{
+ Dwarf_Unsigned uvalue = 0;
+ Dwarf_Word leb128_length = 0;
+
+ if (version == 1) {
+ *size = 1;
+ uvalue = *(unsigned char *) frame_ptr;
+ return uvalue;
+ }
+ uvalue = _dwarf_decode_u_leb128(frame_ptr, &leb128_length);
+ *size = leb128_length;
+ return uvalue;
+}
+
+
+/* Trivial consumer function.
+*/
+int
+dwarf_get_cie_of_fde(Dwarf_Fde fde,
+ Dwarf_Cie * cie_returned, Dwarf_Error * error)
+{
+ if (fde == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_FDE_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ *cie_returned = fde->fd_cie;
+ return DW_DLV_OK;
+
+}
+
+int dwarf_get_cie_index(
+ Dwarf_Cie cie,
+ Dwarf_Signed* index,
+ Dwarf_Error* error )
+{
+ if( cie == NULL )
+ {
+ _dwarf_error(NULL, error, DW_DLE_CIE_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ *index = cie->ci_index;
+ return (DW_DLV_OK);
+}
+
+/* For g++ .eh_frame fde and cie.
+ the cie id is different as the
+ definition of the cie_id in an fde
+ is the distance back from the address of the
+ value to the cie.
+ Or 0 if this is a true cie.
+ Non standard dwarf, designed this way to be
+ convenient at run time for an allocated
+ (mapped into memory as part of the running image) section.
+*/
+int
+dwarf_get_fde_list_eh(Dwarf_Debug dbg,
+ Dwarf_Cie ** cie_data,
+ Dwarf_Signed * cie_element_count,
+ Dwarf_Fde ** fde_data,
+ Dwarf_Signed * fde_element_count,
+ Dwarf_Error * error)
+{
+ int res = _dwarf_load_section(dbg, &dbg->de_debug_frame_eh_gnu,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ res = _dwarf_get_fde_list_internal(dbg,
+ cie_data,
+ cie_element_count,
+ fde_data,
+ fde_element_count,
+ dbg->de_debug_frame_eh_gnu.dss_data,
+ dbg->de_debug_frame_eh_gnu.dss_index,
+ dbg->de_debug_frame_eh_gnu.dss_size,
+ /* cie_id_value */ 0,
+ /* use_gnu_cie_calc= */ 1,
+ error);
+ return res;
+}
+
+
+
+/* For standard dwarf .debug_frame
+ cie_id is -1 in a cie, and
+ is the section offset in the .debug_frame section
+ of the cie otherwise. Standard dwarf
+*/
+int
+dwarf_get_fde_list(Dwarf_Debug dbg,
+ Dwarf_Cie ** cie_data,
+ Dwarf_Signed * cie_element_count,
+ Dwarf_Fde ** fde_data,
+ Dwarf_Signed * fde_element_count,
+ Dwarf_Error * error)
+{
+ int res = _dwarf_load_section(dbg, &dbg->de_debug_frame,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ res = _dwarf_get_fde_list_internal(dbg, cie_data,
+ cie_element_count,
+ fde_data,
+ fde_element_count,
+ dbg->de_debug_frame.dss_data,
+ dbg->de_debug_frame.dss_index,
+ dbg->de_debug_frame.dss_size,
+ DW_CIE_ID,
+ /* use_gnu_cie_calc= */ 0,
+ error);
+
+ return res;
+}
+
+
+/* Only works on dwarf sections, not eh_frame
+ Given a Dwarf_Die, see if it has a
+ DW_AT_MIPS_fde attribute and if so use that
+ to get an fde offset.
+ Then create a Dwarf_Fde to return thru the ret_fde pointer.
+ Also creates a cie (pointed at from the Dwarf_Fde). */
+int
+dwarf_get_fde_for_die(Dwarf_Debug dbg,
+ Dwarf_Die die,
+ Dwarf_Fde * ret_fde, Dwarf_Error * error)
+{
+ Dwarf_Attribute attr;
+ Dwarf_Unsigned fde_offset = 0;
+ Dwarf_Signed signdval = 0;
+ Dwarf_Fde new_fde = 0;
+ unsigned char *fde_ptr = 0;
+ unsigned char *cie_ptr = 0;
+ Dwarf_Unsigned cie_id = 0;
+
+ /* Fields for the current Cie being read. */
+ int res = 0;
+ int resattr = 0;
+ int sdatares = 0;
+
+ struct cie_fde_prefix_s prefix;
+ struct cie_fde_prefix_s prefix_c;
+
+ if (die == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DIE_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ resattr = dwarf_attr(die, DW_AT_MIPS_fde, &attr, error);
+ if (resattr != DW_DLV_OK) {
+ return resattr;
+ }
+
+ /* why is this formsdata? FIX */
+ sdatares = dwarf_formsdata(attr, &signdval, error);
+ if (sdatares != DW_DLV_OK) {
+ return sdatares;
+ }
+
+ res = _dwarf_load_section(dbg, &dbg->de_debug_frame,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ fde_offset = signdval;
+ fde_ptr = (dbg->de_debug_frame.dss_data + fde_offset);
+
+
+ /* First read in the 'common prefix' to figure out what * we are to
+ do with this entry. */
+ memset(&prefix_c, 0, sizeof(prefix_c));
+ memset(&prefix, 0, sizeof(prefix));
+ res = dwarf_read_cie_fde_prefix(dbg, fde_ptr,
+ dbg->de_debug_frame.dss_data,
+ dbg->de_debug_frame.dss_index,
+ dbg->de_debug_frame.dss_size,
+ &prefix,
+ error);
+ if (res == DW_DLV_ERROR) {
+ return res;
+ }
+ if (res == DW_DLV_NO_ENTRY)
+ return res;
+ fde_ptr = prefix.cf_addr_after_prefix;
+ cie_id = prefix.cf_cie_id;
+ /* Pass NULL, not section pointer, for 3rd argument.
+ de_debug_frame.dss_data has no eh_frame relevance. */
+ res = dwarf_create_fde_from_after_start(dbg, &prefix,
+ (Dwarf_Small *) NULL,
+ fde_ptr,
+ /* use_gnu_cie_calc= */ 0,
+ /* Dwarf_Cie = */ 0,
+ &new_fde, error);
+ if (res == DW_DLV_ERROR) {
+ return res;
+ } else if (res == DW_DLV_NO_ENTRY) {
+ return res;
+ }
+ /* DW_DLV_OK */
+
+ /* now read the cie corresponding to the fde */
+ cie_ptr = new_fde->fd_section_ptr + cie_id;
+ res = dwarf_read_cie_fde_prefix(dbg, cie_ptr,
+ dbg->de_debug_frame.dss_data,
+ dbg->de_debug_frame.dss_index,
+ dbg->de_debug_frame.dss_size,
+ &prefix_c, error);
+ if (res == DW_DLV_ERROR) {
+ return res;
+ }
+ if (res == DW_DLV_NO_ENTRY)
+ return res;
+
+ cie_ptr = prefix_c.cf_addr_after_prefix;
+ cie_id = prefix_c.cf_cie_id;
+
+ if (cie_id == DW_CIE_ID) {
+ int res2 = 0;
+ Dwarf_Cie new_cie = 0;
+
+ /* Pass NULL, not section pointer, for 3rd argument.
+ de_debug_frame.dss_data has no eh_frame relevance. */
+ res2 = dwarf_create_cie_from_after_start(dbg,
+ &prefix_c,
+ (Dwarf_Small *) NULL,
+ cie_ptr,
+ /* cie_count= */ 0,
+ /* use_gnu_cie_calc= */
+ 0, &new_cie, error);
+ if (res2 == DW_DLV_ERROR) {
+ dwarf_dealloc(dbg, new_fde, DW_DLA_FDE);
+ return res;
+ } else if (res2 == DW_DLV_NO_ENTRY) {
+ dwarf_dealloc(dbg, new_fde, DW_DLA_FDE);
+ return res;
+ }
+ new_fde->fd_cie = new_cie;
+ } else {
+ _dwarf_error(dbg, error, DW_DLE_NO_CIE_FOR_FDE);
+ return (DW_DLV_ERROR);
+ }
+
+ *ret_fde = new_fde;
+ return DW_DLV_OK;
+}
+
+/* A dwarf consumer operation, see the consumer library documentation.
+*/
+int
+dwarf_get_fde_range(Dwarf_Fde fde,
+ Dwarf_Addr * low_pc,
+ Dwarf_Unsigned * func_length,
+ Dwarf_Ptr * fde_bytes,
+ Dwarf_Unsigned * fde_byte_length,
+ Dwarf_Off * cie_offset,
+ Dwarf_Signed * cie_index,
+ Dwarf_Off * fde_offset, Dwarf_Error * error)
+{
+ Dwarf_Debug dbg;
+
+ if (fde == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_FDE_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ dbg = fde->fd_dbg;
+ if (dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+
+ /* We have always already done the section load here, so no need to
+ load the section. We did the section load in order to create the
+ Dwarf_Fde pointer passed in here. */
+
+
+ if (low_pc != NULL)
+ *low_pc = fde->fd_initial_location;
+ if (func_length != NULL)
+ *func_length = fde->fd_address_range;
+ if (fde_bytes != NULL)
+ *fde_bytes = fde->fd_fde_start;
+ if (fde_byte_length != NULL)
+ *fde_byte_length = fde->fd_length;
+ if (cie_offset != NULL)
+ *cie_offset = fde->fd_cie_offset;
+ if (cie_index != NULL)
+ *cie_index = fde->fd_cie_index;
+ if (fde_offset != NULL)
+ *fde_offset = fde->fd_fde_start - fde->fd_section_ptr;
+
+ return DW_DLV_OK;
+}
+
+/* IRIX specific function. The exception tables
+ have C++ destructor information and are
+ at present undocumented. */
+int
+dwarf_get_fde_exception_info(Dwarf_Fde fde,
+ Dwarf_Signed *
+ offset_into_exception_tables,
+ Dwarf_Error * error)
+{
+ Dwarf_Debug dbg;
+
+ dbg = fde->fd_dbg;
+ if (dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+ *offset_into_exception_tables =
+ fde->fd_offset_into_exception_tables;
+ return DW_DLV_OK;
+}
+
+
+/* A consumer code function.
+ Given a CIE pointer, return the normal CIE data thru
+ pointers.
+ Special augmentation data is not returned here.
+*/
+int
+dwarf_get_cie_info(Dwarf_Cie cie,
+ Dwarf_Unsigned * bytes_in_cie,
+ Dwarf_Small * ptr_to_version,
+ char **augmenter,
+ Dwarf_Unsigned * code_alignment_factor,
+ Dwarf_Signed * data_alignment_factor,
+ Dwarf_Half * return_address_register,
+ Dwarf_Ptr * initial_instructions,
+ Dwarf_Unsigned * initial_instructions_length,
+ Dwarf_Error * error)
+{
+ Dwarf_Debug dbg;
+
+ if (cie == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_CIE_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ dbg = cie->ci_dbg;
+ if (dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_CIE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ if (ptr_to_version != NULL)
+ *ptr_to_version = cie->ci_cie_version_number;
+ if (augmenter != NULL)
+ *augmenter = cie->ci_augmentation;
+ if (code_alignment_factor != NULL)
+ *code_alignment_factor = cie->ci_code_alignment_factor;
+ if (data_alignment_factor != NULL)
+ *data_alignment_factor = cie->ci_data_alignment_factor;
+ if (return_address_register != NULL)
+ *return_address_register = cie->ci_return_address_register;
+ if (initial_instructions != NULL)
+ *initial_instructions = cie->ci_cie_instr_start;
+ if (initial_instructions_length != NULL) {
+ *initial_instructions_length = cie->ci_length +
+ cie->ci_length_size +
+ cie->ci_extension_size -
+ (cie->ci_cie_instr_start - cie->ci_cie_start);
+
+ }
+ *bytes_in_cie = (cie->ci_length);
+ return (DW_DLV_OK);
+}
+
+/* Return the register rules for all registers at a given pc.
+*/
+static int
+_dwarf_get_fde_info_for_a_pc_row(Dwarf_Fde fde,
+ Dwarf_Addr pc_requested,
+ Dwarf_Frame table,
+ Dwarf_Half cfa_reg_col_num,
+ Dwarf_Error * error)
+{
+ Dwarf_Debug dbg = 0;
+ Dwarf_Cie cie = 0;
+ int dw_err = 0;
+ Dwarf_Sword icount = 0;
+ int res = 0;
+
+ if (fde == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_FDE_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ dbg = fde->fd_dbg;
+ if (dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ if (pc_requested < fde->fd_initial_location ||
+ pc_requested >=
+ fde->fd_initial_location + fde->fd_address_range) {
+ _dwarf_error(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
+ return (DW_DLV_ERROR);
+ }
+
+ cie = fde->fd_cie;
+ if (cie->ci_initial_table == NULL) {
+ cie->ci_initial_table = _dwarf_get_alloc(dbg, DW_DLA_FRAME, 1);
+
+ if (cie->ci_initial_table == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ dwarf_init_reg_rules_ru(cie->ci_initial_table->fr_reg,
+ 0, cie->ci_initial_table->fr_reg_count,dbg->de_frame_rule_initial_value);
+ dwarf_init_reg_rules_ru(&cie->ci_initial_table->fr_cfa_rule,
+ 0,1,dbg->de_frame_rule_initial_value);
+ res = _dwarf_exec_frame_instr( /* make_instr= */ false,
+ /* ret_frame_instr= */ NULL,
+ /* search_pc */ false,
+ /* search_pc_val */ 0,
+ /* location */ 0,
+ cie->ci_cie_instr_start,
+ cie->ci_cie_instr_start + (cie->ci_length +
+ cie->ci_length_size +
+ cie->ci_extension_size -
+ (cie->ci_cie_instr_start -
+ cie->ci_cie_start)),
+ cie->ci_initial_table, cie, dbg,
+ cfa_reg_col_num, &icount,
+ &dw_err);
+ if (res == DW_DLV_ERROR) {
+ _dwarf_error(dbg, error, dw_err);
+ return (res);
+ } else if (res == DW_DLV_NO_ENTRY) {
+ return res;
+ }
+ }
+
+ {
+ Dwarf_Small *instr_end = fde->fd_fde_instr_start +
+ fde->fd_length +
+ fde->fd_length_size +
+ fde->fd_extension_size - (fde->fd_fde_instr_start -
+ fde->fd_fde_start);
+
+ res = _dwarf_exec_frame_instr( /* make_instr= */ false,
+ /* ret_frame_instr= */ NULL,
+ /* search_pc */ true,
+ /* search_pc_val */ pc_requested,
+ fde->fd_initial_location,
+ fde->fd_fde_instr_start,
+ instr_end,
+ table,
+ cie, dbg,
+ cfa_reg_col_num, &icount,
+ &dw_err);
+ }
+ if (res == DW_DLV_ERROR) {
+ _dwarf_error(dbg, error, dw_err);
+ return (res);
+ } else if (res == DW_DLV_NO_ENTRY) {
+ return res;
+ }
+
+ return DW_DLV_OK;
+}
+
+/* A consumer call for efficiently getting the register info
+ for all registers in one call.
+
+ The output table rules array is size DW_REG_TABLE_SIZE.
+ The frame info rules array in fde_table is of size
+ DW_REG_TABLE_SIZE too.
+
+ This interface really only works well with MIPS/IRIX
+ where DW_FRAME_CFA_COL is zero (in that case it's safe).
+
+ It is also restricted to the case where
+ DW_REG_TABLE_SIZE == DW_FRAME_LAST_REG_NUM ==
+ dbg->de_frame_reg_rules_entry_count (true for MIPS/IRIX).
+ If this condition is not met calling this routine can result in
+ incorrect output or in memory corruption.
+
+ It is much better to use dwarf_get_fde_info_for_all_regs3()
+ instead of this interface.
+*/
+int
+dwarf_get_fde_info_for_all_regs(Dwarf_Fde fde,
+ Dwarf_Addr pc_requested,
+ Dwarf_Regtable * reg_table,
+ Dwarf_Addr * row_pc,
+ Dwarf_Error * error)
+{
+
+ /* Table size: DW_REG_TABLE_SIZE */
+ struct Dwarf_Frame_s fde_table;
+ Dwarf_Sword i = 0;
+ struct Dwarf_Reg_Rule_s *rule = NULL;
+ struct Dwarf_Regtable_Entry_s *out_rule = NULL;
+ int res = 0;
+ Dwarf_Debug dbg = 0;
+
+ /* For this interface the size is fixed at compile time. */
+ int output_table_real_data_size = DW_REG_TABLE_SIZE;
+
+ FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg);
+
+ res = dwarf_initialize_fde_table(dbg, &fde_table,
+ output_table_real_data_size,
+ error);
+ if (res != DW_DLV_OK)
+ return res;
+
+ /* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks
+ */
+ res = _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested,
+ &fde_table, dbg->de_frame_cfa_col_number, error);
+ if (res != DW_DLV_OK) {
+ dwarf_free_fde_table(&fde_table);
+ return res;
+ }
+
+ out_rule = &reg_table->rules[0];
+ rule = &fde_table.fr_reg[0];
+ for (i = 0; i < output_table_real_data_size;
+ i++, ++out_rule, ++rule) {
+ out_rule->dw_offset_relevant = rule->ru_is_off;
+ out_rule->dw_value_type = rule->ru_value_type;
+ out_rule->dw_regnum = rule->ru_register;
+ out_rule->dw_offset = rule->ru_offset_or_block_len;
+ }
+ dwarf_init_reg_rules_dw(&reg_table->rules[0],i,DW_REG_TABLE_SIZE,
+ dbg->de_frame_undefined_value_number);
+
+ /* The test is just in case it's not inside the table. For non-MIPS
+ it could be outside the table and that is just fine, it was
+ really a mistake to put it in the table in 1993. */
+ /* CONSTCOND */
+ if (dbg->de_frame_cfa_col_number < DW_REG_TABLE_SIZE) {
+ out_rule = &reg_table->rules[dbg->de_frame_cfa_col_number];
+ out_rule->dw_offset_relevant = fde_table.fr_cfa_rule.ru_is_off;
+ out_rule->dw_value_type = fde_table.fr_cfa_rule.ru_value_type;
+ out_rule->dw_regnum = fde_table.fr_cfa_rule.ru_register;
+ out_rule->dw_offset =
+ fde_table.fr_cfa_rule.ru_offset_or_block_len;
+ }
+
+ if (row_pc != NULL)
+ *row_pc = fde_table.fr_loc;
+ dwarf_free_fde_table(&fde_table);
+ return DW_DLV_OK;
+}
+
+/* A consumer call for efficiently getting the register info
+ for all registers in one call.
+
+ The output table rules array is size output_table_real_data_size.
+ (normally DW_REG_TABLE_SIZE).
+ The frame info rules array in fde_table is normally of size
+ DW_FRAME_LAST_REG_NUM. */
+int
+dwarf_get_fde_info_for_all_regs3(Dwarf_Fde fde,
+ Dwarf_Addr pc_requested,
+ Dwarf_Regtable3 * reg_table,
+ Dwarf_Addr * row_pc,
+ Dwarf_Error * error)
+{
+
+ struct Dwarf_Frame_s fde_table;
+ Dwarf_Sword i = 0;
+ int res = 0;
+ struct Dwarf_Reg_Rule_s *rule = NULL;
+ struct Dwarf_Regtable_Entry3_s *out_rule = NULL;
+ Dwarf_Debug dbg = 0;
+ int output_table_real_data_size = reg_table->rt3_reg_table_size;
+
+ FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg);
+
+ output_table_real_data_size =
+ MIN(output_table_real_data_size,
+ dbg->de_frame_reg_rules_entry_count);
+
+ res = dwarf_initialize_fde_table(dbg, &fde_table,
+ output_table_real_data_size,
+ error);
+
+ /* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks
+ */
+ res = _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested,
+ &fde_table,
+ dbg->de_frame_cfa_col_number,
+ error);
+ if (res != DW_DLV_OK) {
+ dwarf_free_fde_table(&fde_table);
+ return res;
+ }
+
+ out_rule = &reg_table->rt3_rules[0];
+ rule = &fde_table.fr_reg[0];
+ for (i = 0; i < output_table_real_data_size;
+ i++, ++out_rule, ++rule) {
+ out_rule->dw_offset_relevant = rule->ru_is_off;
+ out_rule->dw_value_type = rule->ru_value_type;
+ out_rule->dw_regnum = rule->ru_register;
+ out_rule->dw_offset_or_block_len = rule->ru_offset_or_block_len;
+ out_rule->dw_block_ptr = rule->ru_block;
+ }
+ dwarf_init_reg_rules_dw3(&reg_table->rt3_rules[0],i,reg_table->rt3_reg_table_size,
+ dbg->de_frame_undefined_value_number);
+
+ reg_table->rt3_cfa_rule.dw_offset_relevant =
+ fde_table.fr_cfa_rule.ru_is_off;
+ reg_table->rt3_cfa_rule.dw_value_type =
+ fde_table.fr_cfa_rule.ru_value_type;
+ reg_table->rt3_cfa_rule.dw_regnum =
+ fde_table.fr_cfa_rule.ru_register;
+ reg_table->rt3_cfa_rule.dw_offset_or_block_len =
+ fde_table.fr_cfa_rule.ru_offset_or_block_len;
+ reg_table->rt3_cfa_rule.dw_block_ptr =
+ fde_table.fr_cfa_rule.ru_block;
+
+ if (row_pc != NULL)
+ *row_pc = fde_table.fr_loc;
+
+ dwarf_free_fde_table(&fde_table);
+ return DW_DLV_OK;
+}
+
+
+/* Gets the register info for a single register at a given PC value
+ for the FDE specified.
+
+ This is the old MIPS interface and should no longer be used.
+ Use dwarf_get_fde_info_for_reg3() instead. */
+int
+dwarf_get_fde_info_for_reg(Dwarf_Fde fde,
+ Dwarf_Half table_column,
+ Dwarf_Addr pc_requested,
+ Dwarf_Signed * offset_relevant,
+ Dwarf_Signed * register_num,
+ Dwarf_Signed * offset,
+ Dwarf_Addr * row_pc, Dwarf_Error * error)
+{
+ struct Dwarf_Frame_s fde_table;
+ int res = DW_DLV_ERROR;
+ Dwarf_Debug dbg = 0;
+ int output_table_real_data_size = 0;
+
+ FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg);
+ output_table_real_data_size = dbg->de_frame_reg_rules_entry_count;
+
+ res = dwarf_initialize_fde_table(dbg, &fde_table,
+ output_table_real_data_size,
+ error);
+ if (res != DW_DLV_OK)
+ return res;
+
+ if (table_column >= output_table_real_data_size) {
+ dwarf_free_fde_table(&fde_table);
+ _dwarf_error(dbg, error, DW_DLE_FRAME_TABLE_COL_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ /* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks
+ */
+ res =
+ _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested, &fde_table,
+ dbg->de_frame_cfa_col_number, error);
+ if (res != DW_DLV_OK) {
+ dwarf_free_fde_table(&fde_table);
+ return res;
+ }
+
+ if (fde_table.fr_reg[table_column].ru_value_type != DW_EXPR_OFFSET) {
+ /* The problem here is that this interface cannot deal with
+ other sorts of (newer) dwarf frame values. Code must
+ use dwarf_get_fde_info_for_reg3() to get these
+ values correctly. We error rather than return
+ misleading incomplete data. */
+ dwarf_free_fde_table(&fde_table);
+ _dwarf_error(NULL, error,
+ DW_DLE_FRAME_REGISTER_UNREPRESENTABLE);
+ return (DW_DLV_ERROR);
+ }
+ if(table_column == dbg->de_frame_cfa_col_number) {
+ if (register_num != NULL)
+ *register_num = fde_table.fr_cfa_rule.ru_register;
+ if (offset != NULL)
+ *offset = fde_table.fr_cfa_rule.ru_offset_or_block_len;
+ if (row_pc != NULL)
+ *row_pc = fde_table.fr_loc;
+ *offset_relevant = fde_table.fr_cfa_rule.ru_is_off;
+
+ } else {
+ if (register_num != NULL)
+ *register_num = fde_table.fr_reg[table_column].ru_register;
+ if (offset != NULL)
+ *offset = fde_table.fr_reg[table_column].ru_offset_or_block_len;
+ if (row_pc != NULL)
+ *row_pc = fde_table.fr_loc;
+
+ *offset_relevant = fde_table.fr_reg[table_column].ru_is_off;
+ }
+ dwarf_free_fde_table(&fde_table);
+ return DW_DLV_OK;
+}
+
+/* In this interface, table_column of DW_FRAME_CFA_COL
+ is not meaningful.
+ Use dwarf_get_fde_info_for_cfa_reg3() to get the CFA.
+ Call dwarf_set_frame_cfa_value() to set the correct column
+ after calling dwarf_init()
+ (DW_FRAME_CFA_COL3 is a sensible column to use).
+*/
+int
+dwarf_get_fde_info_for_reg3(Dwarf_Fde fde,
+ Dwarf_Half table_column,
+ Dwarf_Addr pc_requested,
+ Dwarf_Small * value_type,
+ Dwarf_Signed * offset_relevant,
+ Dwarf_Signed * register_num,
+ Dwarf_Signed * offset_or_block_len,
+ Dwarf_Ptr * block_ptr,
+ Dwarf_Addr * row_pc_out,
+ Dwarf_Error * error)
+{
+ struct Dwarf_Frame_s fde_table;
+ int res = DW_DLV_ERROR;
+
+ Dwarf_Debug dbg = 0;
+ int table_real_data_size = 0;
+
+ FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg);
+ table_real_data_size = dbg->de_frame_reg_rules_entry_count;
+ res = dwarf_initialize_fde_table(dbg, &fde_table,
+ table_real_data_size, error);
+ if (res != DW_DLV_OK)
+ return res;
+ if (table_column >= table_real_data_size) {
+ dwarf_free_fde_table(&fde_table);
+ _dwarf_error(dbg, error, DW_DLE_FRAME_TABLE_COL_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ /* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks
+ */
+ res = _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested, &fde_table,
+ dbg->de_frame_cfa_col_number,
+ error);
+ if (res != DW_DLV_OK) {
+ dwarf_free_fde_table(&fde_table);
+ return res;
+ }
+
+ if (register_num != NULL)
+ *register_num = fde_table.fr_reg[table_column].ru_register;
+ if (offset_or_block_len != NULL)
+ *offset_or_block_len =
+ fde_table.fr_reg[table_column].ru_offset_or_block_len;
+ if (row_pc_out != NULL)
+ *row_pc_out = fde_table.fr_loc;
+ if (block_ptr)
+ *block_ptr = fde_table.fr_reg[table_column].ru_block;
+
+ /* Without value_type the data cannot be understood, so we insist
+ on it being present, we don't test it. */
+ *value_type = fde_table.fr_reg[table_column].ru_value_type;
+ *offset_relevant = (fde_table.fr_reg[table_column].ru_is_off);
+ dwarf_free_fde_table(&fde_table);
+ return DW_DLV_OK;
+
+}
+
+/* For latest DWARF, this is the preferred interface.
+ It more portably deals with the CFA by not
+ making the CFA a column number, which means
+ DW_FRAME_CFA_COL3 becomes, like DW_CFA_SAME_VALUE,
+ a special value, not something one uses as an index.
+
+ Call dwarf_set_frame_cfa_value() to set the correct column
+ after calling dwarf_init()
+ (DW_FRAME_CFA_COL3 is a sensible column to use, and
+ is the default unless '--enable-oldframecol'
+ is used to configure libdwarf). */
+int
+dwarf_get_fde_info_for_cfa_reg3(Dwarf_Fde fde,
+ Dwarf_Addr pc_requested,
+ Dwarf_Small * value_type,
+ Dwarf_Signed * offset_relevant,
+ Dwarf_Signed * register_num,
+ Dwarf_Signed * offset_or_block_len,
+ Dwarf_Ptr * block_ptr,
+ Dwarf_Addr * row_pc_out,
+ Dwarf_Error * error)
+{
+ struct Dwarf_Frame_s fde_table;
+ int res = DW_DLV_ERROR;
+ Dwarf_Debug dbg = 0;
+
+ int table_real_data_size = 0;
+
+ FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg);
+
+ table_real_data_size = dbg->de_frame_reg_rules_entry_count;
+ res = dwarf_initialize_fde_table(dbg, &fde_table,
+ table_real_data_size, error);
+ if (res != DW_DLV_OK)
+ return res;
+ res = _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested, &fde_table,
+ dbg->de_frame_cfa_col_number,error);
+ if (res != DW_DLV_OK) {
+ dwarf_free_fde_table(&fde_table);
+ return res;
+ }
+
+ if (register_num != NULL)
+ *register_num = fde_table.fr_cfa_rule.ru_register;
+ if (offset_or_block_len != NULL)
+ *offset_or_block_len =
+ fde_table.fr_cfa_rule.ru_offset_or_block_len;
+ if (row_pc_out != NULL)
+ *row_pc_out = fde_table.fr_loc;
+ if (block_ptr)
+ *block_ptr = fde_table.fr_cfa_rule.ru_block;
+
+ /* Without value_type the data cannot be understood, so we insist
+ on it being present, we don't test it. */
+ *value_type = fde_table.fr_cfa_rule.ru_value_type;
+ *offset_relevant = fde_table.fr_cfa_rule.ru_is_off;
+ dwarf_free_fde_table(&fde_table);
+ return DW_DLV_OK;
+}
+
+
+
+/* Return pointer to the instructions in the dwarf fde. */
+int
+dwarf_get_fde_instr_bytes(Dwarf_Fde inFde, Dwarf_Ptr * outinstraddr,
+ Dwarf_Unsigned * outaddrlen,
+ Dwarf_Error * error)
+{
+ Dwarf_Unsigned len = 0;
+ unsigned char *instrs = 0;
+ Dwarf_Debug dbg = 0;
+
+ if (inFde == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_FDE_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ dbg = inFde->fd_dbg;
+ if (dbg == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_FDE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ instrs = inFde->fd_fde_instr_start;
+
+ len = (inFde->fd_fde_start + inFde->fd_length +
+ inFde->fd_length_size + inFde->fd_extension_size) - instrs;
+
+ *outinstraddr = instrs;
+ *outaddrlen = len;
+ return DW_DLV_OK;
+}
+
+/* Allows getting an fde from its table via an index.
+ With more error checking than simply indexing oneself. */
+int
+dwarf_get_fde_n(Dwarf_Fde * fde_data,
+ Dwarf_Unsigned fde_index,
+ Dwarf_Fde * returned_fde, Dwarf_Error * error)
+{
+ Dwarf_Debug dbg = 0;
+ Dwarf_Signed fdecount = 0;
+
+ if (fde_data == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_FDE_PTR_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ FDE_NULL_CHECKS_AND_SET_DBG(*fde_data, dbg);
+ /* Assumes fde_data table has at least one entry. */
+ fdecount = fde_data[0]->fd_is_eh?
+ dbg->de_fde_count_eh:dbg->de_fde_count;
+ if (fde_index >= fdecount) {
+ return (DW_DLV_NO_ENTRY);
+ }
+ *returned_fde = (*(fde_data + fde_index));
+ return DW_DLV_OK;
+}
+
+
+/* Lopc and hipc are extensions to the interface to
+ return the range of addresses that are described
+ by the returned fde. */
+int
+dwarf_get_fde_at_pc(Dwarf_Fde * fde_data,
+ Dwarf_Addr pc_of_interest,
+ Dwarf_Fde * returned_fde,
+ Dwarf_Addr * lopc,
+ Dwarf_Addr * hipc, Dwarf_Error * error)
+{
+ Dwarf_Debug dbg = NULL;
+ Dwarf_Fde fde = NULL;
+ Dwarf_Fde entryfde = NULL;
+ Dwarf_Signed fdecount = 0;
+
+ if (fde_data == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_FDE_PTR_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ /* Assumes fde_data table has at least one entry. */
+ entryfde = *fde_data;
+ FDE_NULL_CHECKS_AND_SET_DBG(entryfde, dbg);
+
+ if (dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+ fdecount = entryfde->fd_is_eh?
+ dbg->de_fde_count_eh:dbg->de_fde_count;
+ {
+ /* The fdes are sorted by their addresses. Binary search to
+ find correct fde. */
+ Dwarf_Signed low = 0;
+ Dwarf_Signed high = fdecount - 1L;
+ Dwarf_Signed middle = 0;
+ Dwarf_Fde cur_fde;
+
+ while (low <= high) {
+ middle = (low + high) / 2;
+ cur_fde = fde_data[middle];
+ if (pc_of_interest < cur_fde->fd_initial_location) {
+ high = middle - 1;
+ } else if (pc_of_interest >=
+ (cur_fde->fd_initial_location +
+ cur_fde->fd_address_range)) {
+ low = middle + 1;
+ } else {
+ fde = fde_data[middle];
+ break;
+ }
+ }
+ }
+
+ if (fde) {
+ if (lopc != NULL)
+ *lopc = fde->fd_initial_location;
+ if (hipc != NULL)
+ *hipc =
+ fde->fd_initial_location + fde->fd_address_range - 1;
+ *returned_fde = fde;
+ return (DW_DLV_OK);
+ }
+
+ return (DW_DLV_NO_ENTRY);
+}
+
+
+/* Expands a single frame instruction block
+ from a specific cie
+ into a n array of Dwarf_Frame_Op-s.
+ This depends on having the cfa column set sensibly.
+
+ Call dwarf_set_frame_cfa_value() to set the correct column
+ after calling dwarf_init() unless you are using
+ the old MIPS frame interfaces (in which case the default
+ will be ok). (DW_FRAME_CFA_COL3 is a sensible column to use ).
+*/
+int
+dwarf_expand_frame_instructions(Dwarf_Cie cie,
+ Dwarf_Ptr instruction,
+ Dwarf_Unsigned i_length,
+ Dwarf_Frame_Op ** returned_op_list,
+ Dwarf_Signed * returned_op_count,
+ Dwarf_Error * error)
+{
+ Dwarf_Sword instr_count;
+ int res = DW_DLV_ERROR;
+ int dw_err;
+ Dwarf_Debug dbg = 0;
+
+ if (cie == 0) {
+ _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+ dbg = cie->ci_dbg;
+
+ if (returned_op_list == 0 || returned_op_count == 0) {
+ _dwarf_error(dbg, error, DW_DLE_RET_OP_LIST_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ /* The cast to Dwarf_Ptr may get a compiler warning, but it is safe
+ as it is just an i_length offset from 'instruction' itself. A
+ caller has made a big mistake if the result is not a valid
+ pointer. */
+ res = _dwarf_exec_frame_instr( /* make_instr= */ true,
+ returned_op_list,
+ /* search_pc */ false,
+ /* search_pc_val */ 0,
+ /* location */ 0,
+ instruction,
+ (Dwarf_Ptr) ((Dwarf_Unsigned) instruction + i_length),
+ /* Dwarf_Frame */ NULL,
+ cie,
+ dbg,
+ dbg->de_frame_cfa_col_number, &instr_count,
+ &dw_err);
+ if (res != DW_DLV_OK) {
+ if (res == DW_DLV_ERROR) {
+ _dwarf_error(dbg, error, dw_err);
+ }
+ return (res);
+ }
+
+ *returned_op_count = instr_count;
+ return DW_DLV_OK;
+}
+
+
+/* Used by dwarfdump -v to print offsets, for debugging
+ dwarf info.
+ The dwarf_ version is preferred over the obsolete _dwarf version.
+ _dwarf version kept for compatibility.
+*/
+/* ARGSUSED 4 */
+int
+_dwarf_fde_section_offset(Dwarf_Debug dbg, Dwarf_Fde in_fde,
+ Dwarf_Off * fde_off, Dwarf_Off * cie_off,
+ Dwarf_Error * err)
+{
+ return dwarf_fde_section_offset(dbg,in_fde,fde_off,
+ cie_off,err);
+}
+/* ARGSUSED 4 */
+int
+dwarf_fde_section_offset(Dwarf_Debug dbg, Dwarf_Fde in_fde,
+ Dwarf_Off * fde_off, Dwarf_Off * cie_off,
+ Dwarf_Error * err)
+{
+ char *start = 0;
+ char *loc = 0;
+
+
+
+ start = (char *) in_fde->fd_section_ptr;
+ loc = (char *) in_fde->fd_fde_start;
+
+ *fde_off = (loc - start);
+ *cie_off = in_fde->fd_cie_offset;
+ return DW_DLV_OK;
+}
+
+/* Used by dwarfdump -v to print offsets, for debugging
+ dwarf info.
+ The dwarf_ version is preferred over the obsolete _dwarf version.
+ _dwarf version kept for compatibility.
+*/
+/* ARGSUSED 4 */
+int
+_dwarf_cie_section_offset(Dwarf_Debug dbg, Dwarf_Cie in_cie,
+ Dwarf_Off * cie_off, Dwarf_Error * err)
+{
+ return dwarf_cie_section_offset(dbg,in_cie,cie_off,err);
+}
+/* ARGSUSED 4 */
+int
+dwarf_cie_section_offset(Dwarf_Debug dbg, Dwarf_Cie in_cie,
+ Dwarf_Off * cie_off, Dwarf_Error * err)
+{
+ char *start = 0;
+ char *loc = 0;
+
+ start = (char *) in_cie->ci_section_ptr;
+ loc = (char *) in_cie->ci_cie_start;
+
+ *cie_off = (loc - start);
+ return DW_DLV_OK;
+}
+
+/* Returns a pointer to target-specific augmentation data thru augdata
+ and returns the length of the data thru augdata_len.
+
+ It's up to the consumer code to know how to interpret the bytes
+ of target-specific data (endian issues apply too, these
+ are just raw bytes pointed to).
+ See Linux Standard Base Core Specification version 3.0 for
+ the details on .eh_frame info.
+
+ Returns DW_DLV_ERROR if fde is NULL or some other serious
+ error.
+ Returns DW_DLV_NO_ENTRY if there is no target-specific
+ augmentation data.
+
+ The bytes pointed to are in the Dwarf_Cie, and as long as that
+ is valid the bytes are there. No 'dealloc' call is needed
+ for the bytes. */
+int
+dwarf_get_cie_augmentation_data(Dwarf_Cie cie,
+ Dwarf_Small ** augdata,
+ Dwarf_Unsigned * augdata_len,
+ Dwarf_Error * error)
+{
+ if (cie == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_CIE_NULL);
+ return (DW_DLV_ERROR);
+ }
+ if (cie->ci_gnu_eh_augmentation_len == 0) {
+ return DW_DLV_NO_ENTRY;
+ }
+ *augdata = (Dwarf_Small *) (cie->ci_gnu_eh_augmentation_bytes);
+ *augdata_len = cie->ci_gnu_eh_augmentation_len;
+ return DW_DLV_OK;
+}
+
+
+/* Returns a pointer to target-specific augmentation data thru augdata
+ and returns the length of the data thru augdata_len.
+
+ It's up to the consumer code to know how to interpret the bytes
+ of target-specific data (endian issues apply too, these
+ are just raw bytes pointed to).
+ See Linux Standard Base Core Specification version 3.0 for
+ the details on .eh_frame info.
+
+ Returns DW_DLV_ERROR if fde is NULL or some other serious
+ error.
+ Returns DW_DLV_NO_ENTRY if there is no target-specific
+ augmentation data.
+
+ The bytes pointed to are in the Dwarf_Fde, and as long as that
+ is valid the bytes are there. No 'dealloc' call is needed
+ for the bytes. */
+int
+dwarf_get_fde_augmentation_data(Dwarf_Fde fde,
+ Dwarf_Small * *augdata,
+ Dwarf_Unsigned * augdata_len,
+ Dwarf_Error * error)
+{
+ Dwarf_Cie cie = 0;
+
+ if (fde == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_FDE_NULL);
+ return (DW_DLV_ERROR);
+ }
+ cie = fde->fd_cie;
+ if (cie == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_CIE_NULL);
+ return (DW_DLV_ERROR);
+ }
+ if (cie->ci_gnu_eh_augmentation_len == 0) {
+ return DW_DLV_NO_ENTRY;
+ }
+ *augdata = (Dwarf_Small *) fde->fd_gnu_eh_augmentation_bytes;
+ *augdata_len = fde->fd_gnu_eh_augmentation_len;
+ return DW_DLV_OK;
+}
+
+
+#if 0
+/* Used solely for debugging libdwarf. */
+static void
+dump_frame_rule(char *msg, struct Dwarf_Reg_Rule_s *reg_rule)
+{
+ printf
+ ("%s type %s (0x%" DW_PR_XZEROS DW_PR_DUx
+ "), is_off %" DW_PR_DUu
+ " reg %" DW_PR_DUu " offset 0x%" DW_PR_XZEROS DW_PR_DUx
+ " blockp 0x%" DW_PR_XZEROS DW_PR_DUx "\n",
+ msg,
+ (reg_rule->ru_value_type == DW_EXPR_OFFSET) ?
+ "DW_EXPR_OFFSET" :
+ (reg_rule->ru_value_type == DW_EXPR_VAL_OFFSET) ?
+ "DW_EXPR_VAL_OFFSET" :
+ (reg_rule->ru_value_type == DW_EXPR_VAL_EXPRESSION) ?
+ "DW_EXPR_VAL_EXPRESSION" :
+ (reg_rule->ru_value_type == DW_EXPR_EXPRESSION) ?
+ "DW_EXPR_EXPRESSION" : "Unknown",
+ (Dwarf_Unsigned) reg_rule->ru_value_type,
+ (Dwarf_Unsigned) reg_rule->ru_is_off,
+ (Dwarf_Unsigned) reg_rule->ru_register,
+ (Dwarf_Unsigned) reg_rule->ru_offset_or_block_len,
+ (Dwarf_Unsigned) reg_rule->ru_block);
+ return;
+}
+#endif
+
+/* This allows consumers to set the 'initial value' so that
+ an ISA/ABI specific default can be used, dynamically,
+ at run time. Useful for dwarfdump and non-MIPS architectures..
+ The value defaults to one of
+ DW_FRAME_SAME_VALUE or DW_FRAME_UNKNOWN_VALUE
+ but dwarfdump can dump multiple ISA/ABI objects so
+ we may want to get this set to what the ABI says is correct.
+
+ Returns the value that was present before we changed it here. */
+Dwarf_Half
+dwarf_set_frame_rule_initial_value(Dwarf_Debug dbg, Dwarf_Half value)
+{
+ Dwarf_Half orig = dbg->de_frame_rule_initial_value;
+ dbg->de_frame_rule_initial_value = value;
+ return orig;
+}
+
+/* The following spelling for backwards compatibility. */
+Dwarf_Half
+dwarf_set_frame_rule_inital_value(Dwarf_Debug dbg, Dwarf_Half value)
+{
+ return dwarf_set_frame_rule_initial_value(dbg,value);
+}
+
+/* This allows consumers to set the array size of the reg rules
+ table so that
+ an ISA/ABI specific value can be used, dynamically,
+ at run time. Useful for non-MIPS archtectures.
+ The value defaults to DW_FRAME_LAST_REG_NUM.
+ but dwarfdump can dump multiple ISA/ABI objects so
+ consumers want to get this set to what the ABI says is correct.
+
+ Returns the value that was present before we changed it here.
+*/
+
+Dwarf_Half
+dwarf_set_frame_rule_table_size(Dwarf_Debug dbg, Dwarf_Half value)
+{
+ Dwarf_Half orig = dbg->de_frame_reg_rules_entry_count;
+ dbg->de_frame_reg_rules_entry_count = value;
+
+ /* Take the caller-specified value, but do not
+ let the value be too small. Keep it at least to
+ DW_FRAME_LAST_REG_NUM.
+ This helps prevent libdwarf (mistakenly) indexing outside
+ of of a register array when the ABI reg count is really small. */
+ if (value < DW_FRAME_LAST_REG_NUM) {
+ dbg->de_frame_reg_rules_entry_count = DW_FRAME_LAST_REG_NUM;
+ }
+ return orig;
+}
+/* This allows consumers to set the CFA register value
+ so that an ISA/ABI specific value can be used, dynamically,
+ at run time. Useful for non-MIPS archtectures.
+ The value defaults to DW_FRAME_CFA_COL3 and should be
+ higher than any real register in the ABI.
+ Dwarfdump can dump multiple ISA/ABI objects so
+ consumers want to get this set to what the ABI says is correct.
+
+ Returns the value that was present before we changed it here. */
+
+Dwarf_Half
+dwarf_set_frame_cfa_value(Dwarf_Debug dbg, Dwarf_Half value)
+{
+ Dwarf_Half orig = dbg->de_frame_cfa_col_number;
+ dbg->de_frame_cfa_col_number = value;
+ return orig;
+}
+/* Similar to above, but for the other crucial fields for frames. */
+Dwarf_Half
+dwarf_set_frame_same_value(Dwarf_Debug dbg, Dwarf_Half value)
+{
+ Dwarf_Half orig = dbg->de_frame_same_value_number;
+ dbg->de_frame_same_value_number = value;
+ return orig;
+}
+Dwarf_Half
+dwarf_set_frame_undefined_value(Dwarf_Debug dbg, Dwarf_Half value)
+{
+ Dwarf_Half orig = dbg->de_frame_same_value_number;
+ dbg->de_frame_undefined_value_number = value;
+ return orig;
+}
+
+/* Does something only if value passed in is greater than 0 and
+ a size than we can handle (in number of bytes). */
+Dwarf_Small dwarf_set_default_address_size(Dwarf_Debug dbg,
+ Dwarf_Small value )
+{
+ Dwarf_Small orig = dbg->de_pointer_size;
+ if (value > 0 && value <= sizeof(Dwarf_Addr)) {
+ dbg->de_pointer_size = value;
+ }
+ return orig;
+}
+
+static int
+init_reg_rules_alloc(Dwarf_Debug dbg,struct Dwarf_Frame_s *f,
+ unsigned count, Dwarf_Error * error)
+{
+ f->fr_reg_count = count;
+ f->fr_reg = (struct Dwarf_Reg_Rule_s *)
+ calloc(sizeof(struct Dwarf_Reg_Rule_s), count);
+ if (f->fr_reg == 0) {
+ if(error) {
+ _dwarf_error(dbg, error, DW_DLE_DF_ALLOC_FAIL);
+ }
+ return (DW_DLV_ERROR);
+ }
+ dwarf_init_reg_rules_ru(f->fr_reg,0, count,
+ dbg->de_frame_rule_initial_value);
+ return DW_DLV_OK;
+}
+static int
+dwarf_initialize_fde_table(Dwarf_Debug dbg,
+ struct Dwarf_Frame_s *fde_table,
+ unsigned table_real_data_size,
+ Dwarf_Error * error)
+{
+ unsigned entry_size = sizeof(struct Dwarf_Frame_s);
+ memset(fde_table,0,entry_size);
+ fde_table->fr_loc = 0;
+ fde_table->fr_next = 0;
+
+ return init_reg_rules_alloc(dbg,fde_table,table_real_data_size,error);
+}
+static void
+dwarf_free_fde_table(struct Dwarf_Frame_s *fde_table)
+{
+ free(fde_table->fr_reg);
+ fde_table->fr_reg_count = 0;
+ fde_table->fr_reg = 0;
+}
+
+
+/* Return DW_DLV_OK if we succeed. else return DW_DLV_ERROR.
+*/
+int
+_dwarf_frame_constructor(Dwarf_Debug dbg, void *frame)
+{
+ struct Dwarf_Frame_s *fp = frame;
+
+ if (!dbg) {
+ return DW_DLV_ERROR;
+ }
+ return init_reg_rules_alloc(dbg,fp,dbg->de_frame_reg_rules_entry_count, 0);
+}
+
+void
+_dwarf_frame_destructor(void *frame)
+{
+ struct Dwarf_Frame_s *fp = frame;
+ dwarf_free_fde_table(fp);
+}
+
+static void
+dwarf_init_reg_rules_ru(struct Dwarf_Reg_Rule_s *base,
+ unsigned first, unsigned last,int initial_value)
+{
+ struct Dwarf_Reg_Rule_s *r = base+first;
+ unsigned i = first;
+ for( ; i < last; ++i,++r) {
+ r->ru_is_off = 0;
+ r->ru_value_type = DW_EXPR_OFFSET;
+ r->ru_register = initial_value;
+ r->ru_offset_or_block_len = 0;
+ r->ru_block = 0;
+ }
+}
+static void
+dwarf_init_reg_rules_dw(struct Dwarf_Regtable_Entry_s *base,
+ unsigned first, unsigned last,int initial_value)
+{
+ struct Dwarf_Regtable_Entry_s *r = base+first;
+ unsigned i = first;
+ for( ; i < last; ++i,++r) {
+ r->dw_offset_relevant = 0;
+ r->dw_value_type = DW_EXPR_OFFSET;
+ r->dw_regnum = initial_value;
+ r->dw_offset = 0;
+ }
+}
+static void
+dwarf_init_reg_rules_dw3(struct Dwarf_Regtable_Entry3_s *base,
+ unsigned first, unsigned last,int initial_value)
+{
+ struct Dwarf_Regtable_Entry3_s *r = base+first;
+ unsigned i = first;
+ for( ; i < last; ++i,++r) {
+ r->dw_offset_relevant = 0;
+ r->dw_value_type = DW_EXPR_OFFSET;
+ r->dw_regnum = initial_value;
+ r->dw_offset_or_block_len = 0;
+ r->dw_block_ptr = 0;
+ }
+}
diff --git a/libdwarf/dwarf_frame.h b/libdwarf/dwarf_frame.h
new file mode 100644
index 0000000..61d2a56
--- /dev/null
+++ b/libdwarf/dwarf_frame.h
@@ -0,0 +1,419 @@
+/*
+
+ Copyright (C) 2000, 2004, 2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+/* The dwarf 2.0 standard dictates that only the following
+ fields can be read when an unexpected augmentation string
+ (in the cie) is encountered: CIE length, CIE_id, version and
+ augmentation; FDE: length, CIE pointer, initial location and
+ address range. Unfortunately, with the above restrictions, it
+ is impossible to read the instruction table from a CIE or a FDE
+ when a new augmentation string is encountered.
+ To fix this problem, the following layout is used, if the
+ augmentation string starts with the string "z".
+ CIE FDE
+ length length
+ CIE_id CIE_pointer
+ version initial_location
+ augmentation address_range
+
+ - length_of_augmented_fields (*NEW*)
+ code_alignment_factor Any new fields as necessary
+ data_alignment_factor instruction_table
+ return_address
+ length_of_augmented fields
+ Any new fields as necessary
+ initial_instructions
+
+ The type of all the old data items are the same as what is
+ described in dwarf 2.0 standard. The length_of_augmented_fields
+ is an LEB128 data item that denotes the size (in bytes) of
+ the augmented fields (not including the size of
+ "length_of_augmented_fields" itself).
+
+ Handling of cie augmentation strings is necessarly a heuristic.
+ See dwarf_frame.c for the currently known augmentation strings.
+
+
+ ---START SGI-ONLY COMMENT:
+ SGI-IRIX versions of cie or fde were intended to use "z1", "z2" as the
+ augmenter strings if required for new augmentation.
+ However, that never happened (as of March 2005).
+
+ The fde's augmented by the string "z" have a new field
+ (signed constant, 4 byte field)
+ called offset_into_exception_tables, following the
+ length_of_augmented field. This field contains an offset
+ into the "_MIPS_eh_region", which describes
+ the IRIX CC exception handling tables.
+ ---END SGI-ONLY COMMENT
+
+
+ GNU .eh_frame has an augmentation string of z[RLP]* (gcc 3.4)
+ The similarity to IRIX 'z' (and proposed but never
+ implemented IRIX z1, z2 etc) was confusing things.
+ If the section is .eh_frame then 'z' means GNU exception
+ information 'Augmentation Data' not IRIX 'z'.
+ See The Linux Standard Base Core Specification version 3.0
+*/
+
+#define DW_DEBUG_FRAME_VERSION 1 /* DWARF2 */
+#define DW_DEBUG_FRAME_VERSION3 3 /* DWARF3 */
+#define DW_DEBUG_FRAME_VERSION4 4 /* DWARF4 */
+/* The following is SGI/IRIX specific, and probably no longer
+ in use anywhere. */
+#define DW_DEBUG_FRAME_AUGMENTER_STRING "mti v1"
+
+/* The value of the offset field for Cie's. */
+#define DW_CIE_OFFSET ~(0x0)
+
+/* The augmentation string may be NULL. */
+#define DW_EMPTY_STRING ""
+
+#define DW_FRAME_INSTR_OPCODE_SHIFT 6
+#define DW_FRAME_INSTR_OFFSET_MASK 0x3f
+
+/*
+ This struct denotes the rule for a register in a row of
+ the frame table. In other words, it is one element of
+ the table.
+*/
+struct Dwarf_Reg_Rule_s {
+
+ /* Is a flag indicating whether the rule includes the offset
+ field, ie whether the ru_offset field is valid or not.
+ Applies only if DW_EXPR_OFFSET or DW_EXPR_VAL_OFFSET.
+ It is important, since reg+offset (offset of 0) is different from
+ just 'register' since the former means 'read memory at address
+ given by the sum of register contents plus offset to get the
+ value'. whereas the latter means 'the value is in the register'.
+
+ The 'register' numbers are either real registers (ie, table
+ columns defined as real registers) or defined entries that are
+ not really hardware registers, such as DW_FRAME_SAME_VAL or
+ DW_FRAME_CFA_COL. */
+ Dwarf_Sbyte ru_is_off;
+
+ /* DW_EXPR_OFFSET (0, DWARF2)
+ DW_EXPR_VAL_OFFSET 1 (dwarf2/3)
+ DW_EXPR_EXPRESSION 2 (dwarf2/3)
+ DW_EXPR_VAL_EXPRESSION 3 (dwarf2/3)
+ See dwarf_frame.h. */
+ Dwarf_Sbyte ru_value_type;
+
+ /* Register involved in this rule. */
+ Dwarf_Half ru_register;
+
+ /* Offset to add to register, if indicated by ru_is_offset
+ and if DW_EXPR_OFFSET or DW_EXPR_VAL_OFFSET.
+ If DW_EXPR_EXPRESSION or DW_EXPR_VAL_EXPRESSION
+ this is DW_FORM_block block-length, not offset. */
+ Dwarf_Unsigned ru_offset_or_block_len;
+
+ /* For DW_EXPR_EXPRESSION DW_EXPR_VAL_EXPRESSION these is set,
+ else 0. */
+ Dwarf_Small *ru_block;
+};
+
+typedef struct Dwarf_Frame_s *Dwarf_Frame;
+
+/*
+ This structure represents a row of the frame table.
+ Fr_loc is the pc value for this row, and Fr_reg
+ contains the rule for each column.
+
+ Entry DW_FRAME_CFA_COL of fr_reg was the tradional MIPS
+ way of setting CFA. cfa_rule is the new one.
+*/
+struct Dwarf_Frame_s {
+
+ /* Pc value corresponding to this row of the frame table. */
+ Dwarf_Addr fr_loc;
+
+ /* Rules for all the registers in this row. */
+ struct Dwarf_Reg_Rule_s fr_cfa_rule;
+
+ /* fr_reg_count is the the number of
+ entries of the fr_reg array. */
+ unsigned long fr_reg_count;
+ struct Dwarf_Reg_Rule_s *fr_reg;
+
+ Dwarf_Frame fr_next;
+};
+
+typedef struct Dwarf_Frame_Op_List_s *Dwarf_Frame_Op_List;
+
+/* This is used to chain together Dwarf_Frame_Op structures. */
+struct Dwarf_Frame_Op_List_s {
+ Dwarf_Frame_Op *fl_frame_instr;
+ Dwarf_Frame_Op_List fl_next;
+};
+
+/* See dwarf_frame.c for the heuristics used to set the
+ Dwarf_Cie ci_augmentation_type.
+
+ This succinctly helps interpret the size and meaning of .debug_frame
+ and (for gcc) .eh_frame.
+
+ In the case of gcc .eh_frame (gcc 3.3, 3.4)
+ z may be followed by one or more of
+ L R P.
+
+*/
+enum Dwarf_augmentation_type {
+ aug_empty_string, /* Default empty augmentation string. */
+ aug_irix_exception_table, /* IRIX plain "z",
+ for exception handling, IRIX CC compiler.
+ Proposed z1 z2 ... never implemented. */
+ aug_gcc_eh_z, /* gcc z augmentation, (including
+ L R P variations). gcc 3.3 3.4 exception
+ handling in eh_frame. */
+ aug_irix_mti_v1, /* IRIX "mti v1" augmentation string. Probably
+ never in any released SGI-IRIX compiler. */
+ aug_eh, /* For gcc .eh_frame, "eh" is the string.,
+ gcc 1,2, egcs. Older values. */
+ aug_armcc, /* "armcc+" meaning the cfa calculation
+ is corrected to be standard (output by
+ Arm C RVCT 3.0 SP1 and later). See
+ http://sourceware.org/ml/gdb-patches/2006-12/msg00249.html
+ for details. */
+ aug_unknown, /* Unknown augmentation, we cannot do much. */
+ aug_past_last
+};
+
+
+/*
+ This structure contains all the pertinent info for a Cie. Most
+ of the fields are taken straight from the definition of a Cie.
+ Ci_cie_start points to the address (in .debug_frame) where this
+ Cie begins. Ci_cie_instr_start points to the first byte of the
+ frame instructions for this Cie. Ci_dbg points to the associated
+ Dwarf_Debug structure. Ci_initial_table is a pointer to the table
+ row generated by the instructions for this Cie.
+*/
+struct Dwarf_Cie_s {
+ Dwarf_Unsigned ci_length;
+ char *ci_augmentation;
+ Dwarf_Small ci_code_alignment_factor;
+ Dwarf_Sbyte ci_data_alignment_factor;
+ Dwarf_Small ci_return_address_register;
+ Dwarf_Small *ci_cie_start;
+ Dwarf_Small *ci_cie_instr_start;
+ Dwarf_Debug ci_dbg;
+ Dwarf_Frame ci_initial_table;
+ Dwarf_Cie ci_next;
+ Dwarf_Small ci_length_size;
+ Dwarf_Small ci_extension_size;
+ Dwarf_Half ci_cie_version_number;
+ enum Dwarf_augmentation_type ci_augmentation_type;
+
+ /* The following 2 for GNU .eh_frame exception handling
+ Augmentation Data. Set if ci_augmentation_type
+ is aug_gcc_eh_z. Zero if unused. */
+ Dwarf_Unsigned ci_gnu_eh_augmentation_len;
+ Dwarf_Ptr ci_gnu_eh_augmentation_bytes;
+
+ /* These are extracted from the gnu eh_frame
+ augmentation if the
+ augmentation begins with 'z'. See Linux LSB documents.
+ Otherwize these are zero. */
+ unsigned char ci_gnu_personality_handler_encoding;
+ unsigned char ci_gnu_lsda_encoding;
+ unsigned char ci_gnu_fde_begin_encoding;
+
+ /* If 'P' augmentation present, is handler addr. Else
+ is zero. */
+ Dwarf_Addr ci_gnu_personality_handler_addr;
+
+
+ /* In creating list of cie's (which will become an array)
+ record the position so fde can get it on fde creation. */
+ Dwarf_Unsigned ci_index;
+ Dwarf_Small * ci_section_ptr;
+ /* DWARF4 adds address size and segment size to the CIE: the .debug_info
+ section may not always be present to allow libdwarf to
+ find address_size from the compilation-unit. */
+ Dwarf_Half ci_address_size;
+ Dwarf_Half ci_segment_size;
+
+};
+
+/*
+ This structure contains all the pertinent info for a Fde.
+ Most of the fields are taken straight from the definition.
+ fd_cie_index is the index of the Cie associated with this
+ Fde in the list of Cie's for this debug_frame. Fd_cie
+ points to the corresponsing Dwarf_Cie structure. Fd_fde_start
+ points to the start address of the Fde. Fd_fde_instr_start
+ points to the start of the instructions for this Fde. Fd_dbg
+ points to the associated Dwarf_Debug structure.
+*/
+struct Dwarf_Fde_s {
+ Dwarf_Unsigned fd_length;
+ Dwarf_Addr fd_cie_offset;
+ Dwarf_Unsigned fd_cie_index;
+ Dwarf_Cie fd_cie;
+ Dwarf_Addr fd_initial_location;
+ Dwarf_Small *fd_initial_loc_pos;
+ Dwarf_Addr fd_address_range;
+ Dwarf_Small *fd_fde_start;
+ Dwarf_Small *fd_fde_instr_start;
+ Dwarf_Debug fd_dbg;
+
+ /* fd_offset_into_exception_tables is SGI/IRIX exception table
+ offset. Unused and zero if not IRIX .debug_frame. */
+ Dwarf_Signed fd_offset_into_exception_tables;
+
+ Dwarf_Fde fd_next;
+ Dwarf_Small fd_length_size;
+ Dwarf_Small fd_extension_size;
+ /* So we know from an fde which 'count' of fde-s in
+ Dwarf_Debug applies: eh or standard. */
+ Dwarf_Small fd_is_eh;
+ /* The following 2 for GNU .eh_frame exception handling
+ Augmentation Data. Set if CIE ci_augmentation_type
+ is aug_gcc_eh_z. Zero if unused. */
+ Dwarf_Unsigned fd_gnu_eh_augmentation_len;
+ Dwarf_Ptr fd_gnu_eh_augmentation_bytes;
+ Dwarf_Addr fd_gnu_eh_lsda; /* If 'L' augmentation letter
+ present: is address of the
+ Language Specific Data Area (LSDA). If not 'L" is zero. */
+
+ /* The following 3 are about the Elf section the FDEs come from. */
+ Dwarf_Small * fd_section_ptr;
+ Dwarf_Unsigned fd_section_length;
+ Dwarf_Unsigned fd_section_index;
+
+};
+
+
+int
+_dwarf_frame_address_offsets(Dwarf_Debug dbg, Dwarf_Addr ** addrlist,
+ Dwarf_Off ** offsetlist,
+ Dwarf_Signed * returncount,
+ Dwarf_Error * err);
+
+int
+_dwarf_get_fde_list_internal(Dwarf_Debug dbg,
+ Dwarf_Cie ** cie_data,
+ Dwarf_Signed * cie_element_count,
+ Dwarf_Fde ** fde_data,
+ Dwarf_Signed * fde_element_count,
+ Dwarf_Small * section_ptr,
+ Dwarf_Unsigned section_index,
+ Dwarf_Unsigned section_length,
+ Dwarf_Unsigned cie_id_value,
+ int use_gnu_cie_calc, /* If non-zero,
+ this is gcc eh_frame. */
+ Dwarf_Error * error);
+
+enum Dwarf_augmentation_type
+_dwarf_get_augmentation_type(Dwarf_Debug dbg,
+ Dwarf_Small *augmentation_string,
+ int is_gcc_eh_frame);
+
+Dwarf_Unsigned _dwarf_get_return_address_reg(Dwarf_Small *frame_ptr,
+ int version,
+ unsigned long *size);
+
+/* Temporary recording of crucial cie/fde prefix data.
+ Vastly simplifies some argument lists. */
+struct cie_fde_prefix_s {
+ /* cf_start_addr is a pointer to the first byte of this fde/cie
+ we are reading now. */
+ Dwarf_Small * cf_start_addr;
+ Dwarf_Small * cf_addr_after_prefix;
+ Dwarf_Unsigned cf_length;
+ int cf_local_length_size;
+ int cf_local_extension_size;
+ Dwarf_Unsigned cf_cie_id;
+ Dwarf_Small * cf_cie_id_addr; /* used for eh_frame calculations. */
+
+ /* Simplifies passing around these values to create fde having
+ these here. */
+ /* cf_section_ptr is a pointer to the first byte
+ of the object section the prefix is read from. */
+ Dwarf_Small * cf_section_ptr;
+ Dwarf_Unsigned cf_section_index;
+ Dwarf_Unsigned cf_section_length;
+};
+
+int
+_dwarf_exec_frame_instr(Dwarf_Bool make_instr,
+ Dwarf_Frame_Op ** ret_frame_instr,
+ Dwarf_Bool search_pc,
+ Dwarf_Addr search_pc_val,
+ Dwarf_Addr initial_loc,
+ Dwarf_Small * start_instr_ptr,
+ Dwarf_Small * final_instr_ptr,
+ Dwarf_Frame table,
+ Dwarf_Cie cie,
+ Dwarf_Debug dbg,
+ Dwarf_Half reg_num_of_cfa,
+ Dwarf_Sword * returned_count,
+ int *returned_error);
+
+
+int dwarf_read_cie_fde_prefix(Dwarf_Debug dbg,
+ Dwarf_Small *frame_ptr_in,
+ Dwarf_Small *section_ptr_in,
+ Dwarf_Unsigned section_index_in,
+ Dwarf_Unsigned section_length_in,
+ struct cie_fde_prefix_s *prefix_out,
+ Dwarf_Error *error);
+
+int dwarf_create_fde_from_after_start(Dwarf_Debug dbg,
+ struct cie_fde_prefix_s * prefix,
+ Dwarf_Small *section_pointer,
+ Dwarf_Small *frame_ptr,
+ int use_gnu_cie_calc,
+ Dwarf_Cie cie_ptr_in,
+ Dwarf_Fde *fde_ptr_out,
+ Dwarf_Error *error);
+
+int dwarf_create_cie_from_after_start(Dwarf_Debug dbg,
+ struct cie_fde_prefix_s *prefix,
+ Dwarf_Small* section_pointer,
+ Dwarf_Small* frame_ptr,
+ Dwarf_Unsigned cie_count,
+ int use_gnu_cie_calc,
+ Dwarf_Cie *cie_ptr_out,
+ Dwarf_Error *error);
+
+
+int _dwarf_frame_constructor(Dwarf_Debug dbg,void * );
+void _dwarf_frame_destructor (void *);
diff --git a/libdwarf/dwarf_frame2.c b/libdwarf/dwarf_frame2.c
new file mode 100644
index 0000000..870442d
--- /dev/null
+++ b/libdwarf/dwarf_frame2.c
@@ -0,0 +1,1531 @@
+/*
+
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
+ Portions Copyright (C) 2010 SN Systems Ltd. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+
+/* This implements _dwarf_get_fde_list_internal()
+ and related helper functions for reading cie/fde data. */
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "dwarf_frame.h"
+#include "dwarf_arange.h" /* using Arange as a way to build a list */
+
+
+static int dwarf_find_existing_cie_ptr(Dwarf_Small * cie_ptr,
+ Dwarf_Cie cur_cie_ptr,
+ Dwarf_Cie * cie_ptr_to_use_out,
+ Dwarf_Cie head_cie_ptr);
+static void dealloc_fde_cie_list_internal(Dwarf_Fde head_fde_ptr,
+ Dwarf_Cie head_cie_ptr);
+static int dwarf_create_cie_from_start(Dwarf_Debug dbg,
+ Dwarf_Small * cie_ptr_val,
+ Dwarf_Small * section_ptr,
+ Dwarf_Unsigned section_index,
+ Dwarf_Unsigned section_length,
+ Dwarf_Small * frame_ptr_end,
+ Dwarf_Unsigned cie_id_value,
+ Dwarf_Unsigned cie_count,
+int use_gnu_cie_calc,
+Dwarf_Cie * cie_ptr_to_use_out,
+Dwarf_Error * error);
+
+static Dwarf_Small *get_cieptr_given_offset(Dwarf_Unsigned cie_id_value,
+ int use_gnu_cie_calc,
+ Dwarf_Small * section_ptr,
+ Dwarf_Small * cie_id_addr);
+static int get_gcc_eh_augmentation(Dwarf_Debug dbg,
+ Dwarf_Small * frame_ptr,
+ unsigned long
+ *size_of_augmentation_data,
+ enum Dwarf_augmentation_type augtype,
+ Dwarf_Small * section_pointer,
+ Dwarf_Small * fde_eh_encoding_out,
+ char *augmentation);
+
+static int
+gnu_aug_encodings(Dwarf_Debug dbg, char *augmentation,
+ Dwarf_Small * aug_data, Dwarf_Unsigned aug_data_len,
+ Dwarf_Half address_size,
+ unsigned char *pers_hand_enc_out,
+ unsigned char *lsda_enc_out,
+ unsigned char *fde_begin_enc_out,
+ Dwarf_Addr * gnu_pers_addr_out);
+
+
+static int read_encoded_ptr(Dwarf_Debug dbg,
+ Dwarf_Small * section_pointer,
+ Dwarf_Small * input_field,
+ int gnu_encoding,
+ Dwarf_Half address_size,
+ Dwarf_Unsigned * addr,
+ Dwarf_Small ** input_field_out);
+
+
+
+static int qsort_compare(const void *elem1, const void *elem2);
+
+
+/* Adds 'newone' to the end of the list starting at 'head'
+ and makes the new one 'cur'rent. */
+static void
+chain_up_fde(Dwarf_Fde newone, Dwarf_Fde * head, Dwarf_Fde * cur)
+{
+ if (*head == NULL)
+ *head = newone;
+ else {
+ (*cur)->fd_next = newone;
+ }
+ *cur = newone;
+
+}
+
+/* Adds 'newone' to the end of the list starting at 'head'
+ and makes the new one 'cur'rent. */
+static void
+chain_up_cie(Dwarf_Cie newone, Dwarf_Cie * head, Dwarf_Cie * cur)
+{
+ if (*head == NULL) {
+ *head = newone;
+ } else {
+ (*cur)->ci_next = newone;
+ }
+ *cur = newone;
+}
+
+/* The size of the length field plus the
+ value of length must be an integral
+ multiple of the address size. Dwarf4 standard.
+
+ A constant that gives the number of bytes of the CIE
+ structure, not including the length field itself
+ (where length mod <size of an address> == 0)
+ (see Section 7.2.2). Dwarf3 standard.
+
+ A uword constant that gives the number of bytes of
+ the CIE structure, not including the
+ length field, itself (length mod <addressing unit size> == 0).
+ Dwarf2 standard.*/
+static void
+validate_length(Dwarf_Debug dbg,
+ Dwarf_Cie cieptr, Dwarf_Unsigned length,
+ Dwarf_Unsigned length_size,
+ Dwarf_Unsigned extension_size,
+ Dwarf_Small * section_ptr,
+ Dwarf_Small * ciefde_start,
+ const char * cieorfde)
+{
+ Dwarf_Unsigned address_size = cieptr->ci_address_size;
+ Dwarf_Unsigned length_field_summed = length_size + extension_size;
+ Dwarf_Unsigned total_len = length + length_field_summed;
+ Dwarf_Unsigned mod = total_len % address_size;
+
+ if (mod != 0) {
+ char msg[DW_HARMLESS_ERROR_MSG_STRING_SIZE];
+ Dwarf_Unsigned sectionoffset = ciefde_start - section_ptr;
+ snprintf(msg,sizeof(msg),
+ "DW_DLE_DEBUG_FRAME_LENGTH_NOT_MULTIPLE"
+ " len=0x%" DW_PR_XZEROS DW_PR_DUx
+ ", len size=0x%" DW_PR_XZEROS DW_PR_DUx
+ ", extn size=0x%" DW_PR_XZEROS DW_PR_DUx
+ ", totl length=0x%" DW_PR_XZEROS DW_PR_DUx
+ ", addr size=0x%" DW_PR_XZEROS DW_PR_DUx
+ ", mod=0x%" DW_PR_XZEROS DW_PR_DUx " must be zero"
+ " in %s"
+ ", offset 0x%" DW_PR_XZEROS DW_PR_DUx ".",
+ length,
+ length_size,
+ extension_size,
+ total_len,address_size, mod,
+ cieorfde,
+ sectionoffset);
+ dwarf_insert_harmless_error(dbg,msg);
+ }
+ return;
+}
+
+
+#if 0
+/* For debugging only. */
+static void
+print_prefix(struct cie_fde_prefix_s *prefix, int line)
+{
+ printf("prefix-print, prefix at 0x%lx, line %d\n",
+ (long) prefix, line);
+ printf(" start addr 0x%lx after prefix 0x%lx\n",
+ (long) prefix->cf_start_addr,
+ (long) prefix->cf_addr_after_prefix);
+ printf(" length 0x%" DW_PR_DUx ", len size %d ext size %d\n",
+ (Dwarf_Unsigned) prefix->cf_length,
+ prefix->cf_local_length_size,
+ prefix->cf_local_extension_size);
+ printf(" cie_id 0x%" DW_PR_DUx " cie_id cie_id_addr 0x%lx\n",
+ (Dwarf_Unsigned) prefix->cf_cie_id,
+ (long) prefix->cf_cie_id_addr);
+ printf
+ (" sec ptr 0x%lx sec index %" DW_PR_DSd " sec len 0x%" DW_PR_DUx " sec past end 0x%lx\n",
+ (long) prefix->cf_section_ptr,
+ (Dwarf_Signed) prefix->cf_section_index,
+ (Dwarf_Unsigned) prefix->cf_section_length,
+ (long) prefix->cf_section_ptr + prefix->cf_section_length);
+}
+#endif
+
+
+
+/* Internal function called from various places to create
+ lists of CIEs and FDEs. Not directly called
+ by consumer code */
+int
+_dwarf_get_fde_list_internal(Dwarf_Debug dbg, Dwarf_Cie ** cie_data,
+ Dwarf_Signed * cie_element_count,
+ Dwarf_Fde ** fde_data,
+ Dwarf_Signed * fde_element_count,
+ Dwarf_Small * section_ptr,
+ Dwarf_Unsigned section_index,
+ Dwarf_Unsigned section_length,
+ Dwarf_Unsigned cie_id_value,
+ int use_gnu_cie_calc, Dwarf_Error * error)
+{
+ /* Scans the debug_frame section. */
+ Dwarf_Small *frame_ptr = section_ptr;
+ Dwarf_Small *frame_ptr_end = section_ptr + section_length;
+
+
+
+ /* New_cie points to the Cie being read, and head_cie_ptr and
+ cur_cie_ptr are used for chaining them up in sequence.
+ In case cie's are reused aggressively we need tail_cie_ptr
+ to add to the chain. If we re-use an early cie
+ later on, that does not mean we chain a new cie to the early one,
+ we always chain it to the tail. */
+ Dwarf_Cie head_cie_ptr = NULL;
+ Dwarf_Cie cur_cie_ptr = NULL;
+ Dwarf_Cie tail_cie_ptr = NULL;
+ Dwarf_Word cie_count = 0;
+
+ /* Points to a list of contiguous pointers to Dwarf_Cie structures.
+ */
+ Dwarf_Cie *cie_list_ptr = 0;
+
+
+ /* New_fde points to the Fde being created, and head_fde_ptr and
+ cur_fde_ptr are used to chain them up. */
+ Dwarf_Fde head_fde_ptr = NULL;
+ Dwarf_Fde cur_fde_ptr = NULL;
+ Dwarf_Word fde_count = 0;
+
+ /* Points to a list of contiguous pointers to Dwarf_Fde structures.
+ */
+ Dwarf_Fde *fde_list_ptr = NULL;
+
+ Dwarf_Word i = 0;
+ int res = DW_DLV_ERROR;
+
+ if (frame_ptr == 0) {
+ return DW_DLV_NO_ENTRY;
+ }
+
+ /* We create the fde and cie arrays. Processing each CIE as we come
+ to it or as an FDE refers to it. We cannot process 'late' CIEs
+ late as GNU .eh_frame complexities mean we need the whole CIE
+ before we can process the FDE correctly. */
+ while (frame_ptr < frame_ptr_end) {
+
+ struct cie_fde_prefix_s prefix;
+
+ /* First read in the 'common prefix' to figure out what we are
+ to do with this entry. */
+ memset(&prefix, 0, sizeof(prefix));
+ res = dwarf_read_cie_fde_prefix(dbg,
+ frame_ptr, section_ptr,
+ section_index,
+ section_length, &prefix, error);
+ if (res == DW_DLV_ERROR) {
+ dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
+ return res;
+ }
+ if (res == DW_DLV_NO_ENTRY)
+ break;
+ frame_ptr = prefix.cf_addr_after_prefix;
+ if (frame_ptr >= frame_ptr_end) {
+ dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
+ return DW_DLV_ERROR;
+
+ }
+
+ if (prefix.cf_cie_id == cie_id_value) {
+ /* This is a CIE. */
+ Dwarf_Cie cie_ptr_to_use = 0;
+
+ int res = dwarf_find_existing_cie_ptr(prefix.cf_start_addr,
+ cur_cie_ptr,
+ &cie_ptr_to_use,
+ head_cie_ptr);
+ if (res == DW_DLV_OK) {
+ cur_cie_ptr = cie_ptr_to_use;
+ /* Ok. Seen already. */
+ } else if (res == DW_DLV_NO_ENTRY) {
+ /* CIE before its FDE in this case. */
+ res = dwarf_create_cie_from_after_start(dbg,
+ &prefix,
+ section_ptr,
+ frame_ptr,
+ cie_count,
+ use_gnu_cie_calc,
+ &cie_ptr_to_use,
+ error);
+ /* ASSERT: res==DW_DLV_NO_ENTRY impossible. */
+ if (res == DW_DLV_ERROR) {
+ dealloc_fde_cie_list_internal(head_fde_ptr,
+ head_cie_ptr);
+ return res;
+ }
+ /* ASSERT res != DW_DLV_NO_ENTRY */
+ cie_count++;
+ chain_up_cie(cie_ptr_to_use, &head_cie_ptr,
+ &tail_cie_ptr);
+ cur_cie_ptr = tail_cie_ptr;
+ } else { /* res == DW_DLV_ERROR */
+
+ dealloc_fde_cie_list_internal(head_fde_ptr,
+ head_cie_ptr);
+ return res;
+ }
+ frame_ptr = cie_ptr_to_use->ci_cie_start +
+ cie_ptr_to_use->ci_length +
+ cie_ptr_to_use->ci_length_size +
+ cie_ptr_to_use->ci_extension_size;
+ continue;
+ } else {
+ /* This is an FDE, Frame Description Entry, see the Dwarf
+ Spec, section 6.4.1 */
+ int res = DW_DLV_ERROR;
+ Dwarf_Cie cie_ptr_to_use = 0;
+ Dwarf_Fde fde_ptr_to_use = 0;
+
+ /* Do not call this twice on one prefix, as
+ prefix.cf_cie_id_addr is altered as a side effect. */
+ Dwarf_Small *cieptr_val =
+ get_cieptr_given_offset(prefix.cf_cie_id,
+ use_gnu_cie_calc,
+ section_ptr,
+ prefix.cf_cie_id_addr);
+
+ res = dwarf_find_existing_cie_ptr(cieptr_val,
+ cur_cie_ptr,
+ &cie_ptr_to_use,
+ head_cie_ptr);
+ if (res == DW_DLV_OK) {
+ cur_cie_ptr = cie_ptr_to_use;
+ /* Ok. Seen CIE already. */
+ } else if (res == DW_DLV_NO_ENTRY) {
+ res = dwarf_create_cie_from_start(dbg,
+ cieptr_val,
+ section_ptr,
+ section_index,
+ section_length,
+ frame_ptr_end,
+ cie_id_value,
+ cie_count,
+ use_gnu_cie_calc,
+ &cie_ptr_to_use,
+ error);
+ if (res == DW_DLV_ERROR) {
+ dealloc_fde_cie_list_internal(head_fde_ptr,
+ head_cie_ptr);
+ return res;
+ } else if (res == DW_DLV_NO_ENTRY) {
+ return res;
+ }
+ ++cie_count;
+ chain_up_cie(cie_ptr_to_use, &head_cie_ptr,
+ &tail_cie_ptr);
+ cur_cie_ptr = tail_cie_ptr;
+
+ } else {
+ /* DW_DLV_ERROR */
+ return res;
+ }
+
+ res = dwarf_create_fde_from_after_start(dbg,
+ &prefix,
+ section_ptr,
+ frame_ptr,
+ use_gnu_cie_calc,
+ cie_ptr_to_use,
+ &fde_ptr_to_use,
+ error);
+ if (res == DW_DLV_ERROR) {
+ return res;
+ }
+ chain_up_fde(fde_ptr_to_use, &head_fde_ptr, &cur_fde_ptr);
+ fde_count++;
+ /* ASSERT: DW_DLV_OK. */
+ frame_ptr = fde_ptr_to_use->fd_fde_start +
+ fde_ptr_to_use->fd_length +
+ fde_ptr_to_use->fd_length_size +
+ fde_ptr_to_use->fd_extension_size;
+ if (frame_ptr < fde_ptr_to_use->fd_fde_instr_start) {
+ /* Sanity check. With a really short fde instruction
+ set and address_size we think is 8
+ as it is ELF64 (but is
+ really 4, as in DWARF{2,3} where we have
+ no FDE address_size) we emit an error.
+ This error means things will not go well. */
+ _dwarf_error(dbg,error,
+ DW_DLE_DEBUG_FRAME_POSSIBLE_ADDRESS_BOTCH);
+ return DW_DLV_ERROR;
+ }
+
+
+ continue;
+ }
+ }
+ /* Now build list of CIEs from the list. If there are no CIEs
+ there should be no FDEs. */
+ if (cie_count > 0) {
+ cie_list_ptr = (Dwarf_Cie *)
+ _dwarf_get_alloc(dbg, DW_DLA_LIST, cie_count);
+ } else {
+ if(fde_count > 0) {
+ dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
+ _dwarf_error(dbg, error, DW_DLE_ORPHAN_FDE);
+ return DW_DLV_ERROR;
+ }
+ dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
+ return DW_DLV_NO_ENTRY;
+ }
+ if (cie_list_ptr == NULL) {
+ dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return DW_DLV_ERROR;
+ }
+ cur_cie_ptr = head_cie_ptr;
+ for (i = 0; i < cie_count; i++) {
+ *(cie_list_ptr + i) = cur_cie_ptr;
+ cur_cie_ptr = cur_cie_ptr->ci_next;
+ }
+
+ /* Now build array of FDEs from the list.
+ With orphan CIEs (meaning no FDEs)
+ lets not return DW_DLV_NO_ENTRY */
+ if (fde_count > 0) {
+ fde_list_ptr = (Dwarf_Fde *)
+ _dwarf_get_alloc(dbg, DW_DLA_LIST, fde_count);
+ }
+
+ // It is ok if fde_list_ptr is NULL, we just have no fdes.
+ cur_fde_ptr = head_fde_ptr;
+ for (i = 0; i < fde_count; i++) {
+ *(fde_list_ptr + i) = cur_fde_ptr;
+ cur_fde_ptr = cur_fde_ptr->fd_next;
+ }
+
+
+ /* Return arguments. */
+ *cie_data = cie_list_ptr;
+ *cie_element_count = cie_count;
+
+ *fde_data = fde_list_ptr;
+ *fde_element_count = fde_count;
+ if(use_gnu_cie_calc) {
+ dbg->de_fde_data_eh = fde_list_ptr;
+ dbg->de_fde_count_eh = fde_count;
+ dbg->de_cie_data_eh = cie_list_ptr;
+ dbg->de_cie_count_eh = cie_count;
+ } else {
+ dbg->de_fde_data = fde_list_ptr;
+ dbg->de_fde_count = fde_count;
+ dbg->de_cie_data = cie_list_ptr;
+ dbg->de_cie_count = cie_count;
+ }
+
+ /* Sort the list by the address so that dwarf_get_fde_at_pc() can
+ binary search this list. */
+ if(fde_count > 0) {
+ qsort((void *) fde_list_ptr, fde_count, sizeof(Dwarf_Ptr),
+ qsort_compare);
+ }
+
+ return (DW_DLV_OK);
+}
+
+/* Internal function, not called by consumer code.
+ 'prefix' has accumulated the info up thru the cie-id
+ and now we consume the rest and build a Dwarf_Cie_s structure.
+*/
+int
+dwarf_create_cie_from_after_start(Dwarf_Debug dbg,
+ struct cie_fde_prefix_s *prefix,
+ Dwarf_Small * section_pointer,
+ Dwarf_Small * frame_ptr,
+ Dwarf_Unsigned cie_count,
+ int use_gnu_cie_calc,
+ Dwarf_Cie * cie_ptr_out,
+ Dwarf_Error * error)
+{
+ Dwarf_Cie new_cie = 0;
+
+ /* egcs-1.1.2 .eh_frame uses 0 as the distinguishing id. sgi uses
+ -1 (in .debug_frame). .eh_frame not quite identical to
+ .debug_frame */
+ /* We here default the address size as it is not present
+ in DWARF2 or DWARF3 cie data, below we set it right if
+ it is present. */
+ Dwarf_Half address_size = dbg->de_pointer_size;
+ Dwarf_Small eh_fde_encoding = 0;
+ Dwarf_Small *augmentation = 0;
+ Dwarf_Half segment_size = 0;
+ Dwarf_Sword data_alignment_factor = -1;
+ Dwarf_Word code_alignment_factor = 4;
+ Dwarf_Unsigned return_address_register = 31;
+ int local_length_size = 0;
+ Dwarf_Word leb128_length = 0;
+ Dwarf_Unsigned cie_aug_data_len = 0;
+ Dwarf_Small *cie_aug_data = 0;
+ Dwarf_Addr gnu_personality_handler_addr = 0;
+ unsigned char gnu_personality_handler_encoding = 0;
+ unsigned char gnu_lsda_encoding = 0;
+ unsigned char gnu_fde_begin_encoding = 0;
+
+
+ enum Dwarf_augmentation_type augt = aug_unknown;
+
+
+ /* This is a CIE, Common Information Entry: See the dwarf spec,
+ section 6.4.1 */
+ Dwarf_Small version = *(Dwarf_Small *) frame_ptr;
+
+ frame_ptr++;
+ if (version != DW_CIE_VERSION && version != DW_CIE_VERSION3 &&
+ version != DW_CIE_VERSION4) {
+ _dwarf_error(dbg, error, DW_DLE_FRAME_VERSION_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ augmentation = frame_ptr;
+ frame_ptr = frame_ptr + strlen((char *) frame_ptr) + 1;
+ augt = _dwarf_get_augmentation_type(dbg,
+ augmentation, use_gnu_cie_calc);
+ if (augt == aug_eh) {
+ /* REFERENCED *//* Not used in this instance */
+ Dwarf_Unsigned exception_table_addr;
+
+ /* this is per egcs-1.1.2 as on RH 6.0 */
+ READ_UNALIGNED(dbg, exception_table_addr,
+ Dwarf_Unsigned, frame_ptr, local_length_size);
+ frame_ptr += local_length_size;
+ }
+ {
+ Dwarf_Unsigned lreg = 0;
+ unsigned long size = 0;
+
+ if( version == DW_CIE_VERSION4) {
+ address_size = *((unsigned char *)frame_ptr);
+ if(address_size > sizeof(Dwarf_Addr)) {
+ _dwarf_error(dbg, error, DW_DLE_ADDRESS_SIZE_ERROR);
+ return (DW_DLV_ERROR);
+ }
+ ++frame_ptr;
+ segment_size = *((unsigned char *)frame_ptr);
+ ++frame_ptr;
+ if(segment_size > sizeof(Dwarf_Addr)) {
+ _dwarf_error(dbg, error, DW_DLE_SEGMENT_SIZE_BAD);
+ return (DW_DLV_ERROR);
+ }
+ }
+
+ DECODE_LEB128_UWORD(frame_ptr, lreg);
+ code_alignment_factor = (Dwarf_Word) lreg;
+ data_alignment_factor =
+ (Dwarf_Sword) _dwarf_decode_s_leb128(frame_ptr,
+ &leb128_length);
+ frame_ptr = frame_ptr + leb128_length;
+ return_address_register =
+ _dwarf_get_return_address_reg(frame_ptr, version, &size);
+ if (return_address_register > dbg->de_frame_reg_rules_entry_count) {
+ _dwarf_error(dbg, error, DW_DLE_CIE_RET_ADDR_REG_ERROR);
+ return (DW_DLV_ERROR);
+ }
+ frame_ptr += size;
+ }
+ switch (augt) {
+ case aug_empty_string:
+ break;
+ case aug_irix_mti_v1:
+ break;
+ case aug_irix_exception_table:{
+ Dwarf_Unsigned lreg = 0;
+ Dwarf_Word length_of_augmented_fields;
+
+ /* Decode the length of augmented fields. */
+ DECODE_LEB128_UWORD(frame_ptr, lreg);
+ length_of_augmented_fields = (Dwarf_Word) lreg;
+ /* set the frame_ptr to point at the instruction start. */
+ frame_ptr += length_of_augmented_fields;
+ }
+ break;
+
+ case aug_eh:{
+ int err = 0;
+ unsigned long increment = 0;
+
+ if (!use_gnu_cie_calc) {
+ /* This should be impossible. */
+ _dwarf_error(dbg, error,
+ DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
+ return DW_DLV_ERROR;
+ }
+
+ err = get_gcc_eh_augmentation(dbg, frame_ptr, &increment,
+ augt,
+ prefix->cf_section_ptr,
+ &eh_fde_encoding,
+ (char *) augmentation);
+ if (err == DW_DLV_ERROR) {
+ _dwarf_error(dbg, error,
+ DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
+ return DW_DLV_ERROR;
+ }
+ frame_ptr += increment;
+ }
+ break;
+ case aug_gcc_eh_z:{
+ /* Here we have Augmentation Data Length (uleb128) followed
+ by Augmentation Data bytes. */
+ int res = DW_DLV_ERROR;
+ Dwarf_Unsigned adlen = 0;
+
+ DECODE_LEB128_UWORD(frame_ptr, adlen);
+ cie_aug_data_len = adlen;
+ cie_aug_data = frame_ptr;
+ res = gnu_aug_encodings(dbg,
+ (char *) augmentation,
+ cie_aug_data,
+ cie_aug_data_len,
+ address_size,
+ &gnu_personality_handler_encoding,
+ &gnu_lsda_encoding,
+ &gnu_fde_begin_encoding,
+ &gnu_personality_handler_addr);
+ if (res != DW_DLV_OK) {
+ _dwarf_error(dbg, error,
+ DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
+ return res;
+ }
+ frame_ptr += adlen;
+ }
+ break;
+ case aug_armcc:
+ break;
+ default:{
+ /* We do not understand the augmentation string. No
+ assumption can be made about any fields other than what
+ we have already read. */
+ frame_ptr = prefix->cf_start_addr +
+ prefix->cf_length + prefix->cf_local_length_size
+ + prefix->cf_local_extension_size;
+ /* FIX -- What are the values of data_alignment_factor,
+ code_alignement_factor, return_address_register and
+ instruction start? They were clearly uninitalized in the
+ previous version and I am leaving them the same way. */
+ }
+ break;
+ } /* End switch on augmentation type. */
+
+ new_cie = (Dwarf_Cie) _dwarf_get_alloc(dbg, DW_DLA_CIE, 1);
+ if (new_cie == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ new_cie->ci_cie_version_number = version;
+ new_cie->ci_initial_table = NULL;
+ new_cie->ci_length = (Dwarf_Word) prefix->cf_length;
+ new_cie->ci_length_size = prefix->cf_local_length_size;
+ new_cie->ci_extension_size = prefix->cf_local_extension_size;
+ new_cie->ci_augmentation = (char *) augmentation;
+
+ new_cie->ci_data_alignment_factor =
+ (Dwarf_Sbyte) data_alignment_factor;
+ new_cie->ci_code_alignment_factor =
+ (Dwarf_Small) code_alignment_factor;
+ new_cie->ci_return_address_register = return_address_register;
+ new_cie->ci_cie_start = prefix->cf_start_addr;
+ new_cie->ci_cie_instr_start = frame_ptr;
+ new_cie->ci_dbg = dbg;
+ new_cie->ci_augmentation_type = augt;
+ new_cie->ci_gnu_eh_augmentation_len = cie_aug_data_len;
+ new_cie->ci_gnu_eh_augmentation_bytes = cie_aug_data;
+ new_cie->ci_gnu_personality_handler_encoding =
+ gnu_personality_handler_encoding;
+ new_cie->ci_gnu_personality_handler_addr =
+ gnu_personality_handler_addr;
+ new_cie->ci_gnu_lsda_encoding = gnu_lsda_encoding;
+ new_cie->ci_gnu_fde_begin_encoding = gnu_fde_begin_encoding;
+
+ new_cie->ci_index = cie_count;
+ new_cie->ci_section_ptr = prefix->cf_section_ptr;
+ /* The Following new in DWARF4 */
+ new_cie->ci_address_size = address_size;
+ new_cie->ci_segment_size = segment_size;
+ validate_length(dbg,new_cie,new_cie->ci_length,
+ new_cie->ci_length_size, new_cie->ci_extension_size,
+ new_cie->ci_section_ptr,
+ new_cie->ci_cie_start,"cie");
+
+ *cie_ptr_out = new_cie;
+ return DW_DLV_OK;
+
+}
+
+
+/* Internal function, not called by consumer code.
+ 'prefix' has accumulated the info up thru the cie-id
+ and now we consume the rest and build a Dwarf_Fde_s structure. */
+
+int
+dwarf_create_fde_from_after_start(Dwarf_Debug dbg,
+ struct cie_fde_prefix_s *prefix,
+ Dwarf_Small * section_pointer,
+ Dwarf_Small * frame_ptr,
+ int use_gnu_cie_calc,
+ Dwarf_Cie cie_ptr_in,
+ Dwarf_Fde * fde_ptr_out,
+ Dwarf_Error * error)
+{
+ Dwarf_Fde new_fde = 0;
+ Dwarf_Cie cieptr = cie_ptr_in;
+ Dwarf_Small *saved_frame_ptr = 0;
+
+ Dwarf_Small *initloc = frame_ptr;
+ Dwarf_Signed offset_into_exception_tables
+ /* must be min dwarf_sfixed in size */
+ = (Dwarf_Signed) DW_DLX_NO_EH_OFFSET;
+ Dwarf_Small *fde_aug_data = 0;
+ Dwarf_Unsigned fde_aug_data_len = 0;
+ Dwarf_Addr cie_base_offset = prefix->cf_cie_id;
+ Dwarf_Addr initial_location = 0; /* must be min de_pointer_size
+ bytes in size */
+ Dwarf_Addr address_range = 0; /* must be min de_pointer_size
+ bytes in size */
+ Dwarf_Half address_size = cie_ptr_in->ci_address_size;
+
+ enum Dwarf_augmentation_type augt = cieptr->ci_augmentation_type;
+
+ if (augt == aug_gcc_eh_z) {
+ /* If z augmentation this is eh_frame, and initial_location and
+ address_range in the FDE are read according to the CIE
+ augmentation string instructions. */
+
+ {
+ Dwarf_Small *fp_updated = 0;
+ int res = read_encoded_ptr(dbg,
+ section_pointer,
+ frame_ptr,
+ cieptr-> ci_gnu_fde_begin_encoding,
+ address_size,
+ &initial_location,
+ &fp_updated);
+ if (res != DW_DLV_OK) {
+ _dwarf_error(dbg, error,
+ DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
+ return DW_DLV_ERROR;
+ }
+ frame_ptr = fp_updated;
+ /* For the address-range it makes no sense to be
+ pc-relative, so we turn it off with a section_pointer of
+ NULL. Masking off DW_EH_PE_pcrel from the
+ ci_gnu_fde_begin_encoding in this call would also work
+ to turn off DW_EH_PE_pcrel. */
+ res = read_encoded_ptr(dbg, (Dwarf_Small *) NULL,
+ frame_ptr,
+ cieptr->ci_gnu_fde_begin_encoding,
+ address_size,
+ &address_range, &fp_updated);
+ if (res != DW_DLV_OK) {
+ _dwarf_error(dbg, error,
+ DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
+ return DW_DLV_ERROR;
+ }
+ frame_ptr = fp_updated;
+ }
+ {
+ Dwarf_Unsigned adlen = 0;
+
+ DECODE_LEB128_UWORD(frame_ptr, adlen);
+ fde_aug_data_len = adlen;
+ fde_aug_data = frame_ptr;
+ frame_ptr += adlen;
+ }
+
+ } else {
+ READ_UNALIGNED(dbg, initial_location, Dwarf_Addr,
+ frame_ptr, address_size);
+ frame_ptr += address_size;
+ READ_UNALIGNED(dbg, address_range, Dwarf_Addr,
+ frame_ptr, address_size);
+ frame_ptr += address_size;
+ }
+ switch (augt) {
+ case aug_irix_mti_v1:
+ case aug_empty_string:
+ break;
+ case aug_irix_exception_table:{
+ Dwarf_Unsigned lreg = 0;
+ Dwarf_Word length_of_augmented_fields = 0;
+
+ DECODE_LEB128_UWORD(frame_ptr, lreg);
+ length_of_augmented_fields = (Dwarf_Word) lreg;
+
+ saved_frame_ptr = frame_ptr;
+ /* The first word is an offset into exception tables.
+ Defined as a 32bit offset even for CC -64. */
+ READ_UNALIGNED(dbg, offset_into_exception_tables,
+ Dwarf_Addr, frame_ptr, sizeof(Dwarf_sfixed));
+ SIGN_EXTEND(offset_into_exception_tables,
+ sizeof(Dwarf_sfixed));
+ frame_ptr = saved_frame_ptr + length_of_augmented_fields;
+ }
+ break;
+ case aug_eh:{
+ Dwarf_Unsigned eh_table_value = 0;
+
+ if (!use_gnu_cie_calc) {
+ /* This should be impossible. */
+ _dwarf_error(dbg, error,
+ DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
+ return DW_DLV_ERROR;
+ }
+
+ /* gnu eh fde case. we do not need to do anything */
+ /*REFERENCED*/ /* Not used in this instance of the macro */
+ READ_UNALIGNED(dbg, eh_table_value,
+ Dwarf_Unsigned, frame_ptr,
+ address_size);
+ frame_ptr += address_size;
+ }
+ break;
+
+ case aug_gcc_eh_z:{
+ /* The Augmentation Data Length is here, followed by the
+ Augmentation Data bytes themselves. */
+ }
+ break;
+ case aug_armcc:
+ break;
+ case aug_past_last:
+ break;
+ case aug_unknown:
+ _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
+ return DW_DLV_ERROR;
+ } /* End switch on augmentation type */
+ new_fde = (Dwarf_Fde) _dwarf_get_alloc(dbg, DW_DLA_FDE, 1);
+ if (new_fde == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ new_fde->fd_length = prefix->cf_length;
+ new_fde->fd_length_size = prefix->cf_local_length_size;
+ new_fde->fd_extension_size = prefix->cf_local_extension_size;
+ new_fde->fd_is_eh = use_gnu_cie_calc;
+ new_fde->fd_cie_offset = cie_base_offset;
+ new_fde->fd_cie_index = cieptr->ci_index;
+ new_fde->fd_cie = cieptr;
+ new_fde->fd_initial_location = initial_location;
+ new_fde->fd_initial_loc_pos = initloc;
+ new_fde->fd_address_range = address_range;
+ new_fde->fd_fde_start = prefix->cf_start_addr;
+ new_fde->fd_fde_instr_start = frame_ptr;
+ new_fde->fd_dbg = dbg;
+ new_fde->fd_offset_into_exception_tables =
+ offset_into_exception_tables;
+
+ new_fde->fd_section_ptr = prefix->cf_section_ptr;
+ new_fde->fd_section_index = prefix->cf_section_index;
+ new_fde->fd_section_length = prefix->cf_section_length;
+
+ new_fde->fd_gnu_eh_augmentation_bytes = fde_aug_data;
+ new_fde->fd_gnu_eh_augmentation_len = fde_aug_data_len;
+ validate_length(dbg,cieptr,new_fde->fd_length,
+ new_fde->fd_length_size, new_fde->fd_extension_size,
+ new_fde->fd_section_ptr,new_fde->fd_fde_start,"fde");
+
+
+ *fde_ptr_out = new_fde;
+ return DW_DLV_OK;
+}
+
+/* Called by qsort to compare FDE entries.
+ Consumer code expects the array of FDE pointers to be
+ in address order.
+*/
+static int
+qsort_compare(const void *elem1, const void *elem2)
+{
+ Dwarf_Fde fde1 = *(Dwarf_Fde *) elem1;
+ Dwarf_Fde fde2 = *(Dwarf_Fde *) elem2;
+ Dwarf_Addr addr1 = fde1->fd_initial_location;
+ Dwarf_Addr addr2 = fde2->fd_initial_location;
+
+ if (addr1 < addr2) {
+ return -1;
+ } else if (addr1 > addr2) {
+ return 1;
+ }
+ return 0;
+}
+
+
+/* Read in the common cie/fde prefix, including reading
+ the cie-value which shows which this is: cie or fde. */
+int
+dwarf_read_cie_fde_prefix(Dwarf_Debug dbg,
+ Dwarf_Small * frame_ptr_in,
+ Dwarf_Small * section_ptr_in,
+ Dwarf_Unsigned section_index_in,
+ Dwarf_Unsigned section_length_in,
+ struct cie_fde_prefix_s *data_out,
+ Dwarf_Error * error)
+{
+ Dwarf_Unsigned length = 0;
+ int local_length_size = 0;
+ int local_extension_size = 0;
+ Dwarf_Small *frame_ptr = frame_ptr_in;
+ Dwarf_Small *cie_ptr_addr = 0;
+ Dwarf_Unsigned cie_id = 0;
+
+ /* READ_AREA_LENGTH updates frame_ptr for consumed bytes */
+ READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
+ frame_ptr, local_length_size,
+ local_extension_size);
+
+ if (length == 0) {
+ /* nul bytes at end of section, seen at end of egcs eh_frame
+ sections (in a.out). Take this as meaning no more CIE/FDE
+ data. We should be very close to end of section. */
+ return DW_DLV_NO_ENTRY;
+ }
+
+ cie_ptr_addr = frame_ptr;
+ READ_UNALIGNED(dbg, cie_id, Dwarf_Unsigned,
+ frame_ptr, local_length_size);
+ SIGN_EXTEND(cie_id, local_length_size);
+ frame_ptr += local_length_size;
+
+ data_out->cf_start_addr = frame_ptr_in;
+ data_out->cf_addr_after_prefix = frame_ptr;
+
+ data_out->cf_length = length;
+ data_out->cf_local_length_size = local_length_size;
+ data_out->cf_local_extension_size = local_extension_size;
+ data_out->cf_cie_id = cie_id;
+ data_out->cf_cie_id_addr = cie_ptr_addr;
+ data_out->cf_section_ptr = section_ptr_in;
+ data_out->cf_section_index = section_index_in;
+ data_out->cf_section_length = section_length_in;
+ return DW_DLV_OK;
+}
+
+/* On various errors previously-allocated CIEs and FDEs
+ must be cleaned up.
+ This helps avoid leaks in case of errors.
+*/
+static void
+dealloc_fde_cie_list_internal(Dwarf_Fde head_fde_ptr,
+ Dwarf_Cie head_cie_ptr)
+{
+ Dwarf_Fde curfde = 0;
+ Dwarf_Cie curcie = 0;
+ Dwarf_Fde nextfde = 0;
+ Dwarf_Cie nextcie = 0;
+
+ for (curfde = head_fde_ptr; curfde; curfde = nextfde) {
+ nextfde = curfde->fd_next;
+ dwarf_dealloc(curfde->fd_dbg, curfde, DW_DLA_FDE);
+ }
+ for (curcie = head_cie_ptr; curcie; curcie = nextcie) {
+ Dwarf_Frame frame = curcie->ci_initial_table;
+
+ nextcie = curcie->ci_next;
+ if (frame)
+ dwarf_dealloc(curcie->ci_dbg, frame, DW_DLA_FRAME);
+ dwarf_dealloc(curcie->ci_dbg, curcie, DW_DLA_CIE);
+ }
+}
+
+/* Find the cie whose id value is given: the id
+ value is, per DWARF2/3, an offset in the section.
+ For .debug_frame, zero is a legal offset. For
+ GNU .eh_frame it is not a legal offset.
+ 'cie_ptr' is a pointer into our section, not an offset. */
+static int
+dwarf_find_existing_cie_ptr(Dwarf_Small * cie_ptr,
+ Dwarf_Cie cur_cie_ptr,
+ Dwarf_Cie * cie_ptr_to_use_out,
+ Dwarf_Cie head_cie_ptr)
+{
+ Dwarf_Cie next = 0;
+
+ if (cur_cie_ptr && cie_ptr == cur_cie_ptr->ci_cie_start) {
+ /* Usually, we use the same cie again and again. */
+ *cie_ptr_to_use_out = cur_cie_ptr;
+ return DW_DLV_OK;
+ }
+ for (next = head_cie_ptr; next; next = next->ci_next) {
+ if (cie_ptr == next->ci_cie_start) {
+ *cie_ptr_to_use_out = next;
+ return DW_DLV_OK;
+ }
+ }
+ return DW_DLV_NO_ENTRY;
+}
+
+
+/* We have a valid cie_ptr_val that has not been
+ turned into an internal Cie yet. Do so now.
+ Returns DW_DLV_OK or DW_DLV_ERROR, never
+ DW_DLV_NO_ENTRY.
+
+ 'section_ptr' - Points to first byte of section data.
+ 'section_length' - Length of the section, in bytes.
+ 'frame_ptr_end' - Points 1-past last byte of section data. */
+static int
+dwarf_create_cie_from_start(Dwarf_Debug dbg,
+ Dwarf_Small * cie_ptr_val,
+ Dwarf_Small * section_ptr,
+ Dwarf_Unsigned section_index,
+ Dwarf_Unsigned section_length,
+ Dwarf_Small * frame_ptr_end,
+ Dwarf_Unsigned cie_id_value,
+ Dwarf_Unsigned cie_count,
+ int use_gnu_cie_calc,
+ Dwarf_Cie * cie_ptr_to_use_out,
+ Dwarf_Error * error)
+{
+ struct cie_fde_prefix_s prefix;
+ int res = DW_DLV_ERROR;
+ Dwarf_Small *frame_ptr = cie_ptr_val;
+
+ if (frame_ptr < section_ptr || frame_ptr > frame_ptr_end) {
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
+ return DW_DLV_ERROR;
+ }
+ /* First read in the 'common prefix' to figure out what * we are to
+ do with this entry. If it is not a cie * we are in big trouble. */
+ memset(&prefix, 0, sizeof(prefix));
+ res = dwarf_read_cie_fde_prefix(dbg, frame_ptr, section_ptr,
+ section_index, section_length,
+ &prefix, error);
+ if (res == DW_DLV_ERROR) {
+ return res;
+ }
+ if (res == DW_DLV_NO_ENTRY) {
+ /* error. */
+ _dwarf_error(dbg, error, DW_DLE_FRAME_CIE_DECODE_ERROR);
+ return DW_DLV_ERROR;
+
+ }
+
+ if (prefix.cf_cie_id != cie_id_value) {
+ _dwarf_error(dbg, error, DW_DLE_FRAME_CIE_DECODE_ERROR);
+ return DW_DLV_ERROR;
+ }
+ frame_ptr = prefix.cf_addr_after_prefix;
+ res = dwarf_create_cie_from_after_start(dbg,
+ &prefix,
+ section_ptr,
+ frame_ptr,
+ cie_count,
+ use_gnu_cie_calc,
+ cie_ptr_to_use_out, error);
+ return res;
+
+}
+
+
+/* This is for gnu eh frames, the 'z' case.
+ We find the letter involved
+ Return the augmentation character and, if applicable,
+ the personality routine address.
+
+ personality_routine_out -
+ if 'P' is augchar, is personality handler addr.
+ Otherwise is not set.
+ aug_data - if 'P' points to data space of the
+ aug_data_len - length of areas aug_data points to.
+
+*/
+#if 0
+/* For debugging only. */
+void
+dump_bytes(Dwarf_Small * start, long len)
+{
+ Dwarf_Small *end = start + len;
+ Dwarf_Small *cur = start;
+
+ for (; cur < end; cur++) {
+ printf(" byte %d, data %02x\n", (int) (cur - start), *cur);
+ }
+
+}
+#endif
+static int
+gnu_aug_encodings(Dwarf_Debug dbg, char *augmentation,
+ Dwarf_Small * aug_data, Dwarf_Unsigned aug_data_len,
+ Dwarf_Half address_size,
+ unsigned char *pers_hand_enc_out,
+ unsigned char *lsda_enc_out,
+ unsigned char *fde_begin_enc_out,
+ Dwarf_Addr * gnu_pers_addr_out)
+{
+ char *nc = 0;
+ Dwarf_Small *cur_aug_p = aug_data;
+ Dwarf_Small *end_aug_p = aug_data + aug_data_len;
+
+ for (nc = augmentation; *nc; ++nc) {
+ char c = *nc;
+
+ switch (c) {
+ case 'z':
+ /* Means that the augmentation data is present. */
+ continue;
+
+ case 'S':
+ /* Indicates this is a signal stack frame.
+ Debuggers have to do
+ special handling. We don't need to do more than
+ print this flag at the right time, though
+ (see dwarfdump where it prints the augmentation
+ string).
+ A signal stack frame (in some OS's) can only be
+ unwound (backtraced) by knowing it is a signal
+ stack frame (perhaps by noticing the name of the
+ function for the stack frame if the name can be
+ found somehow) and figuring
+ out (or knowing) how the kernel and libc
+ pushed a structure
+ onto the stack and loading registers from that structure.
+ Totally different from normal stack unwinding.
+ This flag gives an unwinder a big leg up by
+ decoupling the 'hint: this is a stack frame'
+ from knowledge like
+ the function name (the name might be
+ unavailable at unwind time).
+ */
+ break;
+
+ case 'L':
+ if (cur_aug_p > end_aug_p) {
+ return DW_DLV_ERROR;
+ }
+ *lsda_enc_out = *(unsigned char *) cur_aug_p;
+ ++cur_aug_p;
+ break;
+ case 'R':
+ /* Followed by a one byte argument giving the
+ pointer encoding for the address pointers in the fde. */
+ if (cur_aug_p >= end_aug_p) {
+ return DW_DLV_ERROR;
+ }
+ *fde_begin_enc_out = *(unsigned char *) cur_aug_p;
+ ++cur_aug_p;
+ break;
+ case 'P':{
+ int res = DW_DLV_ERROR;
+ Dwarf_Small *updated_aug_p = 0;
+ unsigned char encoding = 0;
+
+ if (cur_aug_p >= end_aug_p) {
+ return DW_DLV_ERROR;
+ }
+ encoding = *(unsigned char *) cur_aug_p;
+ *pers_hand_enc_out = encoding;
+ ++cur_aug_p;
+ if (cur_aug_p > end_aug_p) {
+ return DW_DLV_ERROR;
+ }
+ /* DW_EH_PE_pcrel makes no sense here, so we turn it
+ off via a section pointer of NULL. */
+ res = read_encoded_ptr(dbg,
+ (Dwarf_Small *) NULL,
+ cur_aug_p,
+ encoding,
+ address_size,
+ gnu_pers_addr_out,
+ &updated_aug_p);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ cur_aug_p = updated_aug_p;
+ if (cur_aug_p > end_aug_p) {
+ return DW_DLV_ERROR;
+ }
+ }
+ break;
+ default:
+ return DW_DLV_ERROR;
+
+ }
+ }
+
+ return DW_DLV_OK;
+}
+
+/* Given augmentation character (the encoding) giving the
+ address format, read the address from input_field
+ and return an incremented value 1 past the input bytes of the
+ address.
+ Push the address read back thru the *addr pointer.
+ See LSB (Linux Standard Base) exception handling documents. */
+static int
+read_encoded_ptr(Dwarf_Debug dbg,
+ Dwarf_Small * section_pointer,
+ Dwarf_Small * input_field,
+ int gnu_encoding,
+ Dwarf_Half address_size,
+ Dwarf_Unsigned * addr,
+ Dwarf_Small ** input_field_updated)
+{
+ Dwarf_Word length = 0;
+ int value_type = gnu_encoding & 0xf;
+ Dwarf_Small *input_field_original = input_field;
+
+ if (gnu_encoding == 0xff) {
+ /* There is no data here. */
+
+ *addr = 0;
+ *input_field_updated = input_field;
+ /* Should we return DW_DLV_NO_ENTRY? */
+ return DW_DLV_OK;
+ }
+ switch (value_type) {
+ case DW_EH_PE_absptr:{
+ /* value_type is zero. Treat as pointer size of the object.
+ */
+ Dwarf_Unsigned ret_value = 0;
+
+ READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
+ input_field, address_size);
+ *addr = ret_value;
+ *input_field_updated = input_field + address_size;
+ }
+ break;
+ case DW_EH_PE_uleb128:{
+ Dwarf_Unsigned val = _dwarf_decode_u_leb128(input_field,
+ &length);
+
+ *addr = val;
+ *input_field_updated = input_field + length;
+ }
+ break;
+ case DW_EH_PE_udata2:{
+ Dwarf_Unsigned ret_value = 0;
+
+ READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
+ input_field, 2);
+ *addr = ret_value;
+ *input_field_updated = input_field + 2;
+ }
+ break;
+
+ case DW_EH_PE_udata4:{
+ Dwarf_Unsigned ret_value = 0;
+
+ /* ASSERT: sizeof(Dwarf_ufixed) == 4 */
+ READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
+ input_field, sizeof(Dwarf_ufixed));
+ *addr = ret_value;
+ *input_field_updated = input_field + sizeof(Dwarf_ufixed);
+ }
+ break;
+
+ case DW_EH_PE_udata8:{
+ Dwarf_Unsigned ret_value = 0;
+
+ /* ASSERT: sizeof(Dwarf_Unsigned) == 8 */
+ READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
+ input_field, sizeof(Dwarf_Unsigned));
+ *addr = ret_value;
+ *input_field_updated = input_field + sizeof(Dwarf_Unsigned);
+ }
+ break;
+
+ case DW_EH_PE_sleb128:{
+ Dwarf_Signed val = _dwarf_decode_s_leb128(input_field,
+ &length);
+
+ *addr = (Dwarf_Unsigned) val;
+ *input_field_updated = input_field + length;
+ }
+ break;
+ case DW_EH_PE_sdata2:{
+ Dwarf_Unsigned val = 0;
+
+ READ_UNALIGNED(dbg, val, Dwarf_Unsigned, input_field, 2);
+ SIGN_EXTEND(val, 2);
+ *addr = (Dwarf_Unsigned) val;
+ *input_field_updated = input_field + 2;
+ }
+ break;
+
+ case DW_EH_PE_sdata4:{
+ Dwarf_Unsigned val = 0;
+
+ /* ASSERT: sizeof(Dwarf_ufixed) == 4 */
+ READ_UNALIGNED(dbg, val,
+ Dwarf_Unsigned, input_field,
+ sizeof(Dwarf_ufixed));
+ SIGN_EXTEND(val, sizeof(Dwarf_ufixed));
+ *addr = (Dwarf_Unsigned) val;
+ *input_field_updated = input_field + sizeof(Dwarf_ufixed);
+ }
+ break;
+ case DW_EH_PE_sdata8:{
+ Dwarf_Unsigned val = 0;
+
+ /* ASSERT: sizeof(Dwarf_Unsigned) == 8 */
+ READ_UNALIGNED(dbg, val,
+ Dwarf_Unsigned, input_field,
+ sizeof(Dwarf_Unsigned));
+ *addr = (Dwarf_Unsigned) val;
+ *input_field_updated = input_field + sizeof(Dwarf_Unsigned);
+ }
+ break;
+ default:
+ return DW_DLV_ERROR;
+
+ };
+ /* The ELF ABI for gnu does not document the meaning of
+ DW_EH_PE_pcrel, which is awkward. It apparently means the value
+ we got above is pc-relative (meaning section-relative), so we
+ adjust the value. Section_pointer may be null if it is known
+ DW_EH_PE_pcrel cannot apply, such as for .debug_frame or for an
+ address-range value. */
+ if (section_pointer && ((gnu_encoding & 0x70) == DW_EH_PE_pcrel)) {
+ /* Address (*addr) above is pc relative with respect to a
+ section. Add to the offset the base address (from elf) of
+ section and the distance of the field we are reading from
+ the section-beginning to get the actual address. */
+ /* ASSERT: input_field_original >= section_pointer */
+ Dwarf_Unsigned distance =
+ input_field_original - section_pointer;
+ *addr += dbg->de_debug_frame_eh_gnu.dss_addr + distance;
+ }
+ return DW_DLV_OK;
+}
+
+
+
+
+/* All augmentation string checking done here now.
+
+ For .eh_frame, gcc from 3.3 uses the z style, earlier used
+ only "eh" as augmentation. We don't yet handle
+ decoding .eh_frame with the z style extensions like L P.
+
+ These are nasty heuristics, but then that's life
+ as augmentations are implementation specific. */
+/* ARGSUSED */
+enum Dwarf_augmentation_type
+_dwarf_get_augmentation_type(Dwarf_Debug dbg,
+ Dwarf_Small * augmentation_string,
+ int is_gcc_eh_frame)
+{
+ enum Dwarf_augmentation_type t = aug_unknown;
+ char *ag_string = (char *) augmentation_string;
+
+ if (ag_string[0] == 0) {
+ /* Empty string. We'll just guess that we know what this means:
+ standard dwarf2/3 with no implementation-defined fields. */
+ t = aug_empty_string;
+ } else if (strcmp(ag_string, DW_DEBUG_FRAME_AUGMENTER_STRING) == 0) {
+ /* The string is "mti v1". Used internally at SGI, probably
+ never shipped. Replaced by "z". Treat like 'nothing
+ special'. */
+ t = aug_irix_mti_v1;
+ } else if (ag_string[0] == 'z') {
+ /* If it's IRIX cc, z means aug_irix_exception_table. z1 z2
+ were designed as for IRIX CC, but never implemented */
+ /* If it's gcc, z may be any of several things. "z" or z
+ followed optionally followed by one or more of L R P, each
+ of which means a value may be present. Should be in eh_frame
+ only, I think. */
+ if (is_gcc_eh_frame) {
+ t = aug_gcc_eh_z;
+ } else if (ag_string[1] == 0) {
+ /* This is the normal IRIX C++ case, where there is an
+ offset into a table in each fde. The table being for
+ IRIX CC exception handling. */
+ /* DW_CIE_AUGMENTER_STRING_V0 "z" */
+ t = aug_irix_exception_table;
+ } /* Else unknown. */
+ } else if (strncmp(ag_string, "eh", 2) == 0) {
+ /* gcc .eh_frame augmentation for egcs and gcc 2.x, at least
+ for x86. */
+ t = aug_eh;
+ } else if (strcmp(ag_string, "armcc+") == 0) {
+ /* Arm uses this string to mean a bug in
+ in Arm compilers was fixed, changing to the standard
+ calculation of the CFA. See
+ http://sourceware.org/ml/gdb-patches/2006-12/msg00249.html
+ for details. */
+ t = aug_armcc;
+ } else {
+
+ }
+ return t;
+}
+
+/* Using augmentation, and version
+ read in the augmentation data for GNU eh.
+
+ Return DW_DLV_OK if we succeeded,
+ DW_DLV_ERR if we fail.
+
+ On success, update 'size_of_augmentation_data' with
+ the length of the fields that are part of augmentation (so the
+ caller can increment frame_ptr appropriately).
+
+ 'frame_ptr' points within section.
+ 'section_pointer' points to section base address in memory.
+*/
+/* ARGSUSED */
+static int
+get_gcc_eh_augmentation(Dwarf_Debug dbg, Dwarf_Small * frame_ptr,
+ unsigned long *size_of_augmentation_data,
+ enum Dwarf_augmentation_type augtype,
+ Dwarf_Small * section_pointer,
+ Dwarf_Small * fde_eh_encoding_out,
+ char *augmentation)
+{
+ char *suffix = 0;
+ unsigned long augdata_size = 0;
+
+ if (augtype == aug_gcc_eh_z) {
+ /* Has leading 'z'. */
+ Dwarf_Word leb128_length = 0;
+
+ /* Dwarf_Unsigned eh_value = */
+ _dwarf_decode_u_leb128(frame_ptr, &leb128_length);
+ augdata_size += leb128_length;
+ frame_ptr += leb128_length;
+ suffix = augmentation + 1;
+ } else {
+ /* Prefix is 'eh'. As in gcc 3.2. No suffix present
+ apparently. */
+ suffix = augmentation + 2;
+ }
+ for (; *suffix; ++suffix) {
+ /* We have no idea what this is as yet. Some extensions beyond
+ dwarf exist which we do not yet handle. */
+ return DW_DLV_ERROR;
+
+ }
+
+ *size_of_augmentation_data = augdata_size;
+ return DW_DLV_OK;
+}
+
+
+/* Make the 'cie_id_addr' consistent across .debug_frame and .eh_frame.
+ Calculate a pointer into section bytes given a cie_id, which is
+ trivial for .debug_frame, but a bit more work for .eh_frame.
+*/
+static Dwarf_Small *
+get_cieptr_given_offset(Dwarf_Unsigned cie_id_value,
+ int use_gnu_cie_calc,
+ Dwarf_Small * section_ptr,
+ Dwarf_Small * cie_id_addr)
+{
+ Dwarf_Small *cieptr = 0;
+
+ if (use_gnu_cie_calc) {
+ /* cie_id value is offset, in section, of the cie_id itself, to
+ use vm ptr of the value, less the value, to get to the cie
+ itself. In addition, munge *cie_id_addr to look *as if* it
+ was from real dwarf. */
+ cieptr = (Dwarf_Small *) ((Dwarf_Unsigned) cie_id_addr) -
+ ((Dwarf_Unsigned) cie_id_value);
+ } else {
+ /* Traditional dwarf section offset is in cie_id */
+ cieptr = (section_ptr + cie_id_value);
+ }
+ return cieptr;
+}
+
+/* To properly release all spaced used.
+ Earlier approaches (before July 15, 2005)
+ letting client do the dealloc directly left
+ some data allocated.
+ This is directly called by consumer code.
+*/
+void
+dwarf_fde_cie_list_dealloc(Dwarf_Debug dbg,
+ Dwarf_Cie * cie_data,
+ Dwarf_Signed cie_element_count,
+ Dwarf_Fde * fde_data,
+ Dwarf_Signed fde_element_count)
+{
+ Dwarf_Signed i = 0;
+
+ for (i = 0; i < cie_element_count; ++i) {
+ Dwarf_Frame frame = cie_data[i]->ci_initial_table;
+
+ if (frame)
+ dwarf_dealloc(dbg, frame, DW_DLA_FRAME);
+ dwarf_dealloc(dbg, cie_data[i], DW_DLA_CIE);
+ }
+ for (i = 0; i < fde_element_count; ++i) {
+ dwarf_dealloc(dbg, fde_data[i], DW_DLA_FDE);
+ }
+ if (cie_data)
+ dwarf_dealloc(dbg, cie_data, DW_DLA_LIST);
+ if (fde_data)
+ dwarf_dealloc(dbg, fde_data, DW_DLA_LIST);
+}
diff --git a/libdwarf/dwarf_frame3.c b/libdwarf/dwarf_frame3.c
new file mode 100644
index 0000000..6f6e25d
--- /dev/null
+++ b/libdwarf/dwarf_frame3.c
@@ -0,0 +1,292 @@
+/*
+
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "dwarf_frame.h"
+#include "dwarf_arange.h" /* using Arange as a way to build a list */
+
+/* Used by rqs (an IRIX application).
+ Not needed except for that one application.
+ Should be moved to its own source file since
+ it is so rarely needed.
+ Returns DW_DLV_OK if returns the arrays.
+ Returns DW_DLV_NO_ENTRY if no section. ?? (How do I tell?)
+ Returns DW_DLV_ERROR if there is an error.
+
+ Uses DW_FRAME_CFA_COL because IRIX is only DWARF2
+ and that is what IRIX compilers and compatible
+ compilers support on IRIX.
+*/
+int
+_dwarf_frame_address_offsets(Dwarf_Debug dbg, Dwarf_Addr ** addrlist,
+ Dwarf_Off ** offsetlist,
+ Dwarf_Signed * returncount,
+ Dwarf_Error * err)
+{
+ int retval = DW_DLV_OK;
+ int res = DW_DLV_ERROR;
+ Dwarf_Cie *cie_data;
+ Dwarf_Signed cie_count;
+ Dwarf_Fde *fde_data;
+ Dwarf_Signed fde_count;
+ Dwarf_Signed i;
+ Dwarf_Frame_Op *frame_inst;
+ Dwarf_Fde fdep;
+ Dwarf_Cie ciep;
+ Dwarf_Chain curr_chain = 0;
+ Dwarf_Chain head_chain = 0;
+ Dwarf_Chain prev_chain = 0;
+ Dwarf_Arange arange;
+ Dwarf_Unsigned arange_count = 0;
+ Dwarf_Addr *arange_addrs = 0;
+ Dwarf_Off *arange_offsets = 0;
+
+ res = dwarf_get_fde_list(dbg, &cie_data, &cie_count,
+ &fde_data, &fde_count, err);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ res = _dwarf_load_section(dbg, &dbg->de_debug_frame, err);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ if (!dbg->de_debug_frame.dss_size) {
+ return (DW_DLV_NO_ENTRY);
+ }
+
+ for (i = 0; i < cie_count; i++) {
+ Dwarf_Off instoff = 0;
+ Dwarf_Signed initial_instructions_length = 0;
+ Dwarf_Small *instr_end = 0;
+ Dwarf_Sword icount = 0;
+ int j = 0;
+ int dw_err;
+
+ ciep = cie_data[i];
+ instoff = ciep->ci_cie_instr_start - dbg->de_debug_frame.dss_data;
+ initial_instructions_length = ciep->ci_length +
+ ciep->ci_length_size + ciep->ci_extension_size -
+ (ciep->ci_cie_instr_start - ciep->ci_cie_start);
+ instr_end = ciep->ci_cie_instr_start +
+ initial_instructions_length;
+ res = _dwarf_exec_frame_instr( /* make_instr */ true,
+ &frame_inst,
+ /* search_pc= */ false,
+ /* search_pc_val= */ 0,
+ /* location */ 0,
+ ciep->ci_cie_instr_start,
+ instr_end,
+ /* Dwarf_frame= */ 0,
+ /* cie= */ 0,
+ dbg,
+ DW_FRAME_CFA_COL,
+ &icount, &dw_err);
+ if (res == DW_DLV_ERROR) {
+ _dwarf_error(dbg, err, dw_err);
+ return (res);
+ } else if (res == DW_DLV_NO_ENTRY) {
+ continue;
+ }
+
+ for (j = 0; j < icount; ++j) {
+ Dwarf_Frame_Op *finst = frame_inst + j;
+
+ if (finst->fp_base_op == 0 && finst->fp_extended_op == 1) {
+ /* is DW_CFA_set_loc */
+ Dwarf_Addr add = (Dwarf_Addr) finst->fp_offset;
+ Dwarf_Off off = finst->fp_instr_offset + instoff;
+
+ arange = (Dwarf_Arange)
+ _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1);
+ if (arange == NULL) {
+ _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ arange->ar_address = add;
+ arange->ar_info_offset = off;
+ arange_count++;
+ curr_chain = (Dwarf_Chain)
+ _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (curr_chain == NULL) {
+ _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ curr_chain->ch_item = arange;
+ if (head_chain == NULL)
+ head_chain = prev_chain = curr_chain;
+ else {
+ prev_chain->ch_next = curr_chain;
+ prev_chain = curr_chain;
+ }
+ }
+ }
+ dwarf_dealloc(dbg, frame_inst, DW_DLA_FRAME_BLOCK);
+
+ }
+ for (i = 0; i < fde_count; i++) {
+ Dwarf_Small *instr_end = 0;
+ Dwarf_Sword icount = 0;
+ Dwarf_Signed instructions_length = 0;
+ Dwarf_Off instoff = 0;
+ Dwarf_Off off = 0;
+ Dwarf_Addr addr = 0;
+ int j = 0;
+ int dw_err;
+
+ fdep = fde_data[i];
+ off = fdep->fd_initial_loc_pos - dbg->de_debug_frame.dss_data;
+ addr = fdep->fd_initial_location;
+ arange = (Dwarf_Arange)
+ _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1);
+ if (arange == NULL) {
+ _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ arange->ar_address = addr;
+ arange->ar_info_offset = off;
+ arange_count++;
+ curr_chain = (Dwarf_Chain)
+ _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (curr_chain == NULL) {
+ _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ curr_chain->ch_item = arange;
+ if (head_chain == NULL)
+ head_chain = prev_chain = curr_chain;
+ else {
+ prev_chain->ch_next = curr_chain;
+ prev_chain = curr_chain;
+ }
+
+
+ instoff = fdep->fd_fde_instr_start - dbg->de_debug_frame.dss_data;
+ instructions_length = fdep->fd_length +
+ fdep->fd_length_size + fdep->fd_extension_size -
+ (fdep->fd_fde_instr_start - fdep->fd_fde_start);
+ instr_end = fdep->fd_fde_instr_start + instructions_length;
+ res = _dwarf_exec_frame_instr( /* make_instr */ true,
+ &frame_inst,
+ /* search_pc= */ false,
+ /* search_pc_val= */ 0,
+ /* location */ 0,
+ fdep->fd_fde_instr_start,
+ instr_end,
+ /* Dwarf_frame= */ 0,
+ /* cie= */ 0,
+ dbg,
+ DW_FRAME_CFA_COL,
+ &icount, &dw_err);
+ if (res == DW_DLV_ERROR) {
+ _dwarf_error(dbg, err, dw_err);
+ return (res);
+ } else if (res == DW_DLV_NO_ENTRY) {
+ continue;
+ }
+
+ for (j = 0; j < icount; ++j) {
+ Dwarf_Frame_Op *finst2 = frame_inst + j;
+
+ if (finst2->fp_base_op == 0 && finst2->fp_extended_op == 1) {
+ /* is DW_CFA_set_loc */
+ Dwarf_Addr add = (Dwarf_Addr) finst2->fp_offset;
+ Dwarf_Off off = finst2->fp_instr_offset + instoff;
+
+ arange = (Dwarf_Arange)
+ _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1);
+ if (arange == NULL) {
+ _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ arange->ar_address = add;
+ arange->ar_info_offset = off;
+ arange_count++;
+ curr_chain = (Dwarf_Chain)
+ _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (curr_chain == NULL) {
+ _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ curr_chain->ch_item = arange;
+ if (head_chain == NULL)
+ head_chain = prev_chain = curr_chain;
+ else {
+ prev_chain->ch_next = curr_chain;
+ prev_chain = curr_chain;
+ }
+
+ }
+ }
+ dwarf_dealloc(dbg, frame_inst, DW_DLA_FRAME_BLOCK);
+
+ }
+ dwarf_dealloc(dbg, fde_data, DW_DLA_LIST);
+ dwarf_dealloc(dbg, cie_data, DW_DLA_LIST);
+ arange_addrs = (Dwarf_Addr *)
+ _dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count);
+ if (arange_addrs == NULL) {
+ _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ arange_offsets = (Dwarf_Off *)
+ _dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count);
+ if (arange_offsets == NULL) {
+ _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ curr_chain = head_chain;
+ for (i = 0; i < arange_count; i++) {
+ Dwarf_Arange ar = curr_chain->ch_item;
+
+ arange_addrs[i] = ar->ar_address;
+ arange_offsets[i] = ar->ar_info_offset;
+ prev_chain = curr_chain;
+ curr_chain = curr_chain->ch_next;
+ dwarf_dealloc(dbg, ar, DW_DLA_ARANGE);
+ dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
+ }
+ *returncount = arange_count;
+ *offsetlist = arange_offsets;
+ *addrlist = arange_addrs;
+ return retval;
+}
diff --git a/libdwarf/dwarf_funcs.c b/libdwarf/dwarf_funcs.c
new file mode 100644
index 0000000..83ebb58
--- /dev/null
+++ b/libdwarf/dwarf_funcs.c
@@ -0,0 +1,134 @@
+/*
+
+ Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include "dwarf_funcs.h"
+#include "dwarf_global.h"
+
+int
+dwarf_get_funcs(Dwarf_Debug dbg,
+ Dwarf_Func ** funcs,
+ Dwarf_Signed * ret_func_count, Dwarf_Error * error)
+{
+ int res = _dwarf_load_section(dbg, &dbg->de_debug_funcnames,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ if (!dbg->de_debug_funcnames.dss_size) {
+ return (DW_DLV_NO_ENTRY);
+ }
+
+
+ return _dwarf_internal_get_pubnames_like_data(dbg,
+ dbg->de_debug_funcnames.dss_data,
+ dbg->de_debug_funcnames.dss_size,
+ (Dwarf_Global **) funcs, /* Type punning for sections with identical format. */
+ ret_func_count,
+ error,
+ DW_DLA_FUNC_CONTEXT,
+ DW_DLA_FUNC,
+ DW_DLE_DEBUG_FUNCNAMES_LENGTH_BAD,
+ DW_DLE_DEBUG_FUNCNAMES_VERSION_ERROR);
+}
+
+/* Deallocating fully requires deallocating the list
+ and all entries. But some internal data is
+ not exposed, so we need a function with internal knowledge.
+*/
+
+void
+dwarf_funcs_dealloc(Dwarf_Debug dbg, Dwarf_Func * dwgl,
+ Dwarf_Signed count)
+{
+ _dwarf_internal_globals_dealloc(dbg, (Dwarf_Global *) dwgl,
+ count,
+ DW_DLA_FUNC_CONTEXT,
+ DW_DLA_FUNC, DW_DLA_LIST);
+ return;
+}
+
+
+
+int
+dwarf_funcname(Dwarf_Func func_in, char **ret_name, Dwarf_Error * error)
+{
+ Dwarf_Global func = (Dwarf_Global) func_in;
+
+ if (func == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_FUNC_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ *ret_name = (char *) (func->gl_name);
+ return DW_DLV_OK;
+}
+
+int
+dwarf_func_die_offset(Dwarf_Func func_in,
+ Dwarf_Off * return_offset, Dwarf_Error * error)
+{
+ Dwarf_Global func = (Dwarf_Global) func_in;
+
+ return dwarf_global_die_offset(func, return_offset, error);
+}
+
+
+int
+dwarf_func_cu_offset(Dwarf_Func func_in,
+ Dwarf_Off * return_offset, Dwarf_Error * error)
+{
+ Dwarf_Global func = (Dwarf_Global) func_in;
+
+ return dwarf_global_cu_offset(func, return_offset, error);
+}
+
+
+int
+dwarf_func_name_offsets(Dwarf_Func func_in,
+ char **ret_func_name,
+ Dwarf_Off * die_offset,
+ Dwarf_Off * cu_die_offset, Dwarf_Error * error)
+{
+ Dwarf_Global func = (Dwarf_Global) func_in;
+
+ return dwarf_global_name_offsets(func,
+ ret_func_name,
+ die_offset, cu_die_offset, error);
+}
diff --git a/libdwarf/dwarf_funcs.h b/libdwarf/dwarf_funcs.h
new file mode 100644
index 0000000..bf91c32
--- /dev/null
+++ b/libdwarf/dwarf_funcs.h
@@ -0,0 +1,42 @@
+/*
+
+ Copyright (C) 2000, 2004 Silicon Graphics, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+
+typedef struct Dwarf_Func_Context_s *Dwarf_Func_Context;
+
+
+/* struct never completed: see dwarf_global.h */
diff --git a/libdwarf/dwarf_global.c b/libdwarf/dwarf_global.c
new file mode 100644
index 0000000..1b4486b
--- /dev/null
+++ b/libdwarf/dwarf_global.c
@@ -0,0 +1,614 @@
+/*
+
+ Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include "dwarf_global.h"
+
+
+#ifdef __sgi /* __sgi should only be defined for IRIX/MIPS. */
+/* The 'fixup' here intended for IRIX targets only.
+ With a 2+GB Elf64 IRIX executable (under 4GB in size),
+ some DIE offsets wrongly
+ got the 32bit upper bit sign extended. For the cu-header
+ offset in the .debug_pubnames section and in the
+ .debug_aranges section.
+ the 'varp' here is a pointer to an offset into .debug_info.
+ We fix up the offset here if it seems advisable..
+
+ As of June 2005 we have identified a series of mistakes
+ in ldx64 that can cause this (64 bit values getting passed
+ thru 32-bit signed knothole).
+*/
+void
+_dwarf_fix_up_offset_irix(Dwarf_Debug dbg,
+ Dwarf_Unsigned * varp, char *caller_site_name)
+{
+
+ Dwarf_Unsigned var = *varp;
+
+#define UPPER33 0xffffffff80000000LL
+#define LOWER32 0xffffffffLL
+ /* Restrict the hack to the known case. Upper 32 bits erroneously
+ sign extended from lower 32 upper bit. */
+ if ((var & UPPER33) == UPPER33) {
+ var &= LOWER32;
+ /* Apply the fix. Dreadful hack. */
+ *varp = var;
+ }
+#undef UPPER33
+#undef LOWER32
+ return;
+}
+#endif
+
+
+int
+dwarf_get_globals(Dwarf_Debug dbg,
+ Dwarf_Global ** globals,
+ Dwarf_Signed * return_count, Dwarf_Error * error)
+{
+ int res = _dwarf_load_section(dbg, &dbg->de_debug_pubnames,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ if (!dbg->de_debug_pubnames.dss_size) {
+ return (DW_DLV_NO_ENTRY);
+ }
+
+
+ return _dwarf_internal_get_pubnames_like_data(dbg,
+ dbg->de_debug_pubnames.dss_data,
+ dbg->de_debug_pubnames.dss_size,
+ globals,
+ return_count,
+ error,
+ DW_DLA_GLOBAL_CONTEXT,
+ DW_DLA_GLOBAL,
+ DW_DLE_PUBNAMES_LENGTH_BAD,
+ DW_DLE_PUBNAMES_VERSION_ERROR);
+
+}
+
+/* Deallocating fully requires deallocating the list
+ and all entries. But some internal data is
+ not exposed, so we need a function with internal knowledge.
+*/
+
+void
+dwarf_globals_dealloc(Dwarf_Debug dbg, Dwarf_Global * dwgl,
+ Dwarf_Signed count)
+{
+ _dwarf_internal_globals_dealloc(dbg, dwgl,
+ count,
+ DW_DLA_GLOBAL_CONTEXT,
+ DW_DLA_GLOBAL, DW_DLA_LIST);
+ return;
+}
+
+void
+_dwarf_internal_globals_dealloc(Dwarf_Debug dbg, Dwarf_Global * dwgl,
+ Dwarf_Signed count,
+ int context_code,
+ int global_code, int list_code)
+{
+ Dwarf_Signed i;
+ struct Dwarf_Global_Context_s *gcp = 0;
+ struct Dwarf_Global_Context_s *lastgcp = 0;
+
+ for (i = 0; i < count; i++) {
+ Dwarf_Global dgb = dwgl[i];
+
+ gcp = dgb->gl_context;
+
+ if (lastgcp != gcp) {
+ lastgcp = gcp;
+ dwarf_dealloc(dbg, gcp, context_code);
+ }
+ dwarf_dealloc(dbg, dgb, global_code);
+ }
+ dwarf_dealloc(dbg, dwgl, list_code);
+ return;
+}
+
+
+/* Sweeps the complete section. */
+int
+_dwarf_internal_get_pubnames_like_data(Dwarf_Debug dbg,
+ Dwarf_Small * section_data_ptr,
+ Dwarf_Unsigned section_length,
+ Dwarf_Global ** globals,
+ Dwarf_Signed * return_count,
+ Dwarf_Error * error,
+ int context_code,
+ int global_code,
+ int length_err_num,
+ int version_err_num)
+{
+ Dwarf_Small *pubnames_like_ptr = 0;
+
+ /* Points to the context for the current set of global names, and
+ contains information to identify the compilation-unit that the
+ set refers to. */
+ Dwarf_Global_Context pubnames_context = 0;
+
+ Dwarf_Half version = 0;
+
+ /* Offset from the start of compilation-unit for the current
+ global. */
+ Dwarf_Off die_offset_in_cu = 0;
+
+ Dwarf_Unsigned global_count = 0;
+
+ /* Points to the current global read. */
+ Dwarf_Global global = 0;
+
+ /* Used to chain the Dwarf_Global_s structs for creating contiguous
+ list of pointers to the structs. */
+ Dwarf_Chain curr_chain = 0;
+ Dwarf_Chain prev_chain = 0;
+ Dwarf_Chain head_chain = 0;
+
+ /* Points to contiguous block of Dwarf_Global's to be returned. */
+ Dwarf_Global *ret_globals = 0;
+
+ /* Temporary counter. */
+ Dwarf_Unsigned i = 0;
+
+ if (dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+ /* We will eventually need the .debug_info data. Load it now. */
+ if (!dbg->de_debug_info.dss_data) {
+ int res = _dwarf_load_debug_info(dbg, error);
+
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ }
+ if (section_data_ptr == NULL) {
+ return (DW_DLV_NO_ENTRY);
+ }
+ pubnames_like_ptr = section_data_ptr;
+ do {
+ Dwarf_Unsigned length = 0;
+ int local_extension_size = 0;
+ int local_length_size = 0;
+
+ /* Some compilers emit padding at the end of each cu's area.
+ pubnames_ptr_past_end_cu records the true area end for this
+ cu's data. Essentially the length in the header and the 0
+ terminator of the data are redundant information. The
+ dwarf2/3 spec does not mention what to do if the length is
+ past the 0 terminator. So we take any bytes left after the 0
+ as padding and ignore them. */
+ Dwarf_Small *pubnames_ptr_past_end_cu = 0;
+
+
+ pubnames_context = (Dwarf_Global_Context)
+ _dwarf_get_alloc(dbg, context_code, 1);
+ if (pubnames_context == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ /* READ_AREA_LENGTH updates pubnames_like_ptr for consumed
+ bytes. */
+ READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
+ pubnames_like_ptr, local_length_size,
+ local_extension_size);
+ pubnames_context->pu_length_size = local_length_size;
+ pubnames_context->pu_extension_size = local_extension_size;
+ pubnames_context->pu_dbg = dbg;
+
+ pubnames_ptr_past_end_cu = pubnames_like_ptr + length;
+
+ READ_UNALIGNED(dbg, version, Dwarf_Half,
+ pubnames_like_ptr, sizeof(Dwarf_Half));
+ pubnames_like_ptr += sizeof(Dwarf_Half);
+ if (version != CURRENT_VERSION_STAMP) {
+ _dwarf_error(dbg, error, version_err_num);
+ return (DW_DLV_ERROR);
+ }
+
+ /* Offset of CU header in debug section. */
+ READ_UNALIGNED(dbg, pubnames_context->pu_offset_of_cu_header,
+ Dwarf_Off, pubnames_like_ptr,
+ pubnames_context->pu_length_size);
+ pubnames_like_ptr += pubnames_context->pu_length_size;
+
+ FIX_UP_OFFSET_IRIX_BUG(dbg,
+ pubnames_context->pu_offset_of_cu_header,
+ "pubnames cu header offset");
+
+
+ READ_UNALIGNED(dbg, pubnames_context->pu_info_length,
+ Dwarf_Unsigned, pubnames_like_ptr,
+ pubnames_context->pu_length_size);
+ pubnames_like_ptr += pubnames_context->pu_length_size;
+
+ if (pubnames_like_ptr > (section_data_ptr + section_length)) {
+ _dwarf_error(dbg, error, length_err_num);
+ return (DW_DLV_ERROR);
+ }
+
+ /* Read initial offset (of DIE within CU) of a pubname, final
+ entry is not a pair, just a zero offset. */
+ READ_UNALIGNED(dbg, die_offset_in_cu, Dwarf_Off,
+ pubnames_like_ptr,
+ pubnames_context->pu_length_size);
+ pubnames_like_ptr += pubnames_context->pu_length_size;
+ FIX_UP_OFFSET_IRIX_BUG(dbg,
+ die_offset_in_cu, "offset of die in cu");
+
+ /* Loop thru pairs. DIE off with CU followed by string. */
+ while (die_offset_in_cu != 0) {
+
+ /* Already read offset, pubnames_like_ptr now points to the
+ string. */
+ global =
+ (Dwarf_Global) _dwarf_get_alloc(dbg, global_code, 1);
+ if (global == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ global_count++;
+
+ global->gl_context = pubnames_context;
+
+ global->gl_named_die_offset_within_cu = die_offset_in_cu;
+
+ global->gl_name = pubnames_like_ptr;
+
+ pubnames_like_ptr = pubnames_like_ptr +
+ strlen((char *) pubnames_like_ptr) + 1;
+
+
+ /* Finish off current entry chain */
+ curr_chain =
+ (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (curr_chain == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ /* Put current global on singly_linked list. */
+ curr_chain->ch_item = (Dwarf_Global) global;
+
+ if (head_chain == NULL)
+ head_chain = prev_chain = curr_chain;
+ else {
+ prev_chain->ch_next = curr_chain;
+ prev_chain = curr_chain;
+ }
+
+ /* Fead offset for the *next* entry */
+ READ_UNALIGNED(dbg, die_offset_in_cu, Dwarf_Off,
+ pubnames_like_ptr, pubnames_context->pu_length_size);
+
+ pubnames_like_ptr += pubnames_context->pu_length_size;
+ FIX_UP_OFFSET_IRIX_BUG(dbg,
+ die_offset_in_cu, "offset of next die in cu");
+
+ if (pubnames_like_ptr > (section_data_ptr + section_length)) {
+ _dwarf_error(dbg, error, length_err_num);
+ return (DW_DLV_ERROR);
+ }
+ }
+ /* ASSERT: die_offset_in_cu == 0 */
+ if (pubnames_like_ptr > pubnames_ptr_past_end_cu) {
+ /* This is some kind of error. This simply cannot happen.
+ The encoding is wrong or the length in the header for
+ this cu's contribution is wrong. */
+ _dwarf_error(dbg, error, length_err_num);
+ return (DW_DLV_ERROR);
+ }
+ /* If there is some kind of padding at the end of the section,
+ as emitted by some compilers, skip over that padding and
+ simply ignore the bytes thus passed-over. With most
+ compilers, pubnames_like_ptr == pubnames_ptr_past_end_cu at
+ this point */
+ pubnames_like_ptr = pubnames_ptr_past_end_cu;
+
+ } while (pubnames_like_ptr < (section_data_ptr + section_length));
+
+ /* Points to contiguous block of Dwarf_Global's. */
+ ret_globals = (Dwarf_Global *)
+ _dwarf_get_alloc(dbg, DW_DLA_LIST, global_count);
+ if (ret_globals == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ /* Store pointers to Dwarf_Global_s structs in contiguous block,
+ and deallocate the chain. */
+ curr_chain = head_chain;
+ for (i = 0; i < global_count; i++) {
+ *(ret_globals + i) = curr_chain->ch_item;
+ prev_chain = curr_chain;
+ curr_chain = curr_chain->ch_next;
+ dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
+ }
+
+ *globals = ret_globals;
+ *return_count = (Dwarf_Signed) global_count;
+ return DW_DLV_OK;
+}
+
+
+/* Given a pubnames entry (or other like section entry)
+ return thru the ret_name pointer
+ a pointer to the string which is the entry name. */
+int
+dwarf_globname(Dwarf_Global glob, char **ret_name, Dwarf_Error * error)
+{
+ if (glob == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ *ret_name = (char *) (glob->gl_name);
+ return DW_DLV_OK;
+}
+
+
+/* Given a pubnames entry (or other like section entry)
+ return thru the ret_off pointer the
+ global offset of the DIE for this entry.
+ The global offset is the offset within the .debug_info
+ section as a whole. */
+int
+dwarf_global_die_offset(Dwarf_Global global,
+ Dwarf_Off * ret_off, Dwarf_Error * error)
+{
+ if (global == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ if (global->gl_context == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ *ret_off = (global->gl_named_die_offset_within_cu +
+ global->gl_context->pu_offset_of_cu_header);
+ return DW_DLV_OK;
+}
+
+/* Given a pubnames entry (or other like section entry)
+ return thru the ret_off pointer the
+ offset of the compilation unit header of the
+ compilation unit the global is part of.
+
+ In early versions of this, the value returned was
+ the offset of the compilation unit die, and
+ other cu-local die offsets were faked so adding this to
+ such a cu-local offset got a true section offset.
+ Now things do as they say (adding *cu_header_offset to
+ a cu-local offset gets the section offset). */
+int
+dwarf_global_cu_offset(Dwarf_Global global,
+ Dwarf_Off * cu_header_offset,
+ Dwarf_Error * error)
+{
+ Dwarf_Global_Context con = 0;
+
+ if (global == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ con = global->gl_context;
+
+ if (con == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ /* In early libdwarf, this incorrectly returned the offset of the
+ CU DIE. Now correctly returns the header offset. */
+ *cu_header_offset = con->pu_offset_of_cu_header;
+
+ return DW_DLV_OK;
+}
+
+/*
+ Give back the pubnames entry (or any other like section)
+ name, symbol DIE offset, and the cu-DIE offset.
+
+ Various errors are possible.
+
+ The string pointer returned thru ret_name is not
+ dwarf_get_alloc()ed, so no dwarf_dealloc()
+ DW_DLA_STRING should be applied to it.
+
+*/
+int
+dwarf_global_name_offsets(Dwarf_Global global,
+ char **ret_name,
+ Dwarf_Off * die_offset,
+ Dwarf_Off * cu_die_offset,
+ Dwarf_Error * error)
+{
+ Dwarf_Global_Context con = 0;
+ Dwarf_Debug dbg = 0;
+ Dwarf_Off off = 0;
+
+ if (global == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ con = global->gl_context;
+
+ if (con == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ off = con->pu_offset_of_cu_header;
+ /* The offset had better not be too close to the end. If it is,
+ _dwarf_length_of_cu_header() will step off the end and therefore
+ must not be used. 10 is a meaningless heuristic, but no CU
+ header is that small so it is safe. An erroneous offset is due
+ to a bug in the tool chain. A bug like this has been seen on
+ IRIX with MIPSpro 7.3.1.3 and an executable > 2GB in size and
+ with 2 million pubnames entries. */
+#define MIN_CU_HDR_SIZE 10
+ dbg = con->pu_dbg;
+ if (dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+ /* Cannot refer to debug_types */
+ if (dbg->de_debug_info.dss_size &&
+ ((off + MIN_CU_HDR_SIZE) >= dbg->de_debug_info.dss_size)) {
+ _dwarf_error(NULL, error, DW_DLE_OFFSET_BAD);
+ return (DW_DLV_ERROR);
+ }
+#undef MIN_CU_HDR_SIZE
+ if (die_offset != NULL) {
+ *die_offset = global->gl_named_die_offset_within_cu + off;
+ }
+
+ *ret_name = (char *) global->gl_name;
+
+ if (cu_die_offset != NULL) {
+ /* Globals cannot refer to debug_types */
+ int res = _dwarf_load_debug_info(dbg, error);
+
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ /* The offset had better not be too close to the end. If it is,
+ _dwarf_length_of_cu_header() will step off the end and
+ therefore must not be used. 10 is a meaningless heuristic,
+ but no CU header is that small so it is safe. */
+ /* Globals cannot refer to debug_types */
+ if ((off + 10) >= dbg->de_debug_info.dss_size) {
+ _dwarf_error(NULL, error, DW_DLE_OFFSET_BAD);
+ return (DW_DLV_ERROR);
+ }
+ *cu_die_offset = off + _dwarf_length_of_cu_header(dbg, off,true);
+ }
+
+
+ return DW_DLV_OK;
+}
+
+/* We have the offset to a CU header.
+ Return thru outFileOffset the offset of the CU DIE.
+
+ New June, 2001.
+ Used by SGI IRIX debuggers.
+ No error is possible.
+
+ See also dwarf_CU_dieoffset_given_die().
+
+ This is assumed to never apply to data in .debug_types, it
+ only refers to .debug_info.
+
+*/
+
+/* ARGSUSED */
+int
+dwarf_get_cu_die_offset_given_cu_header_offset(Dwarf_Debug dbg,
+ Dwarf_Off in_cu_header_offset,
+ Dwarf_Off * out_cu_die_offset,
+ Dwarf_Error * err)
+{
+ Dwarf_Off len =
+ _dwarf_length_of_cu_header(dbg, in_cu_header_offset,true);
+
+ Dwarf_Off newoff = in_cu_header_offset + len;
+
+ *out_cu_die_offset = newoff;
+ return DW_DLV_OK;
+}
+
+/* The following version new in October 2011, does allow finding
+ the offset if one knows whether debug_info or debug_types.
+ */
+int
+dwarf_get_cu_die_offset_given_cu_header_offset_b(Dwarf_Debug dbg,
+ Dwarf_Off in_cu_header_offset,
+ Dwarf_Bool is_info,
+ Dwarf_Off * out_cu_die_offset,
+ Dwarf_Error * err)
+{
+ Dwarf_Off len =
+ _dwarf_length_of_cu_header(dbg, in_cu_header_offset,is_info);
+
+ Dwarf_Off newoff = in_cu_header_offset + len;
+
+ *out_cu_die_offset = newoff;
+ return DW_DLV_OK;
+}
+/* dwarf_CU_dieoffset_given_die returns
+ the global debug_info section offset of the CU die
+ that is the CU containing the given (passed-in) die.
+ This information makes it possible for a consumer to
+ find and print context information for any die.
+
+ Use dwarf_offdie() passing in the offset this returns
+ to get a die pointer to the CU die. */
+int
+dwarf_CU_dieoffset_given_die(Dwarf_Die die,
+ Dwarf_Off* return_offset,
+ Dwarf_Error* error)
+{
+ Dwarf_Off dieoff = 0;
+ Dwarf_CU_Context cucontext = 0;
+
+ CHECK_DIE(die, DW_DLV_ERROR);
+ cucontext = die->di_cu_context;
+ dieoff = cucontext->cc_debug_offset;
+ /* The following call cannot fail, so no error check. */
+ dwarf_get_cu_die_offset_given_cu_header_offset_b(
+ cucontext->cc_dbg, dieoff,
+ die->di_is_info, return_offset,error);
+ return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_global.h b/libdwarf/dwarf_global.h
new file mode 100644
index 0000000..f1a8e93
--- /dev/null
+++ b/libdwarf/dwarf_global.h
@@ -0,0 +1,126 @@
+/*
+
+ Copyright (C) 2000,2004,2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2011 David Anderson. All Rights Reserved.
+
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+
+typedef struct Dwarf_Global_Context_s *Dwarf_Global_Context;
+
+/*
+ This struct contains header information for a set of pubnames.
+ Essentially, they contain the context for a set of pubnames
+ belonging to a compilation-unit.
+
+ This is also used for the sgi-specific
+ weaknames, typenames, varnames, funcnames data:
+ the structs for those are incomplete and
+ instances of this are used instead.
+
+ Also used for DWARF3 .debug_pubtypes.
+
+ These never refer to .debug_types, only to .debug_info.
+
+*/
+struct Dwarf_Global_Context_s {
+
+ /* Length in .debug_pubnames (etc) of a set of names for a
+ compilation-unit. Dwarf_Word pu_length; The value is not made
+ available outside libdwarf and not used inside, so no need to
+ record it. */
+
+ /* For this context, size of a length. 4 or 8 */
+ unsigned char pu_length_size;
+
+ /* For this CU, size of the extension 0 except for dwarf2 extension
+ 64bit, in which case is 4. */
+ unsigned char pu_extension_size;
+
+ /* Offset into .debug_info of the compilation-unit header (not DIE)
+ for this set of pubnames. */
+ Dwarf_Off pu_offset_of_cu_header;
+
+ /* Size of compilation-unit that these pubnames are in. */
+ Dwarf_Unsigned pu_info_length;
+
+ Dwarf_Debug pu_dbg;
+};
+
+
+/* This struct contains information for a single pubname. */
+struct Dwarf_Global_s {
+
+ /* Offset from the start of the corresponding compilation-unit of
+ the DIE for the given pubname CU. */
+ Dwarf_Off gl_named_die_offset_within_cu;
+
+ /* Points to the given pubname. */
+ Dwarf_Small *gl_name;
+
+ /* Context for this pubname. */
+ Dwarf_Global_Context gl_context;
+};
+
+int _dwarf_internal_get_pubnames_like_data(Dwarf_Debug dbg,
+ Dwarf_Small *
+ section_data_ptr,
+ Dwarf_Unsigned
+ section_length,
+ Dwarf_Global ** globals,
+ Dwarf_Signed * return_count,
+ Dwarf_Error * error,
+ int context_code,
+ int global_code,
+ int length_err_num,
+ int version_err_num);
+
+void
+_dwarf_internal_globals_dealloc( Dwarf_Debug dbg, Dwarf_Global *dwgl,
+ Dwarf_Signed count,
+ int context_code,
+ int global_code,
+ int list_code);
+
+
+#ifdef __sgi /* __sgi should only be defined for IRIX/MIPS. */
+void _dwarf_fix_up_offset_irix(Dwarf_Debug dbg,
+ Dwarf_Unsigned *varp,
+ char *caller_site_name);
+#define FIX_UP_OFFSET_IRIX_BUG(ldbg,var,name) _dwarf_fix_up_offset_irix(ldbg,&var,name)
+#else
+#define FIX_UP_OFFSET_IRIX_BUG(ldbg,var,name)
+#endif
+
diff --git a/libdwarf/dwarf_harmless.c b/libdwarf/dwarf_harmless.c
new file mode 100644
index 0000000..0329bc9
--- /dev/null
+++ b/libdwarf/dwarf_harmless.c
@@ -0,0 +1,226 @@
+/*
+
+ Copyright (C) 2010-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+*/
+
+/* This implements _dwarf_insert_harmless_error
+ and related helper functions for recording
+ compiler errors that need not make the input
+ unusable.
+
+ Applications can use dwarf_get_harmless_error_list to
+ find (and possibly print) a warning about such errors.
+
+ The initial error reported here is
+ DW_DLE_DEBUG_FRAME_LENGTH_NOT_MULTIPLE which was a
+ bug in a specific compiler.
+
+ It is a fixed length circular list to constrain
+ the space used for errors.
+
+ The assumption is that these errors are exceedingly
+ rare, and indicate a broken compiler (the one that
+ produced the object getting the error(s)).
+
+ dh_maxcount is recorded internally as 1 greater than
+ requested. Hiding the fact we always leave one
+ slot unused (at least). So a user request for
+ N slots really gives the user N usable slots. */
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "dwarf_frame.h"
+#include "dwarf_harmless.h"
+
+
+/* The pointers returned here through errmsg_ptrs_array
+ become invalidated by any call to libdwarf. Any call.
+*/
+int dwarf_get_harmless_error_list(Dwarf_Debug dbg,
+ unsigned count,
+ const char ** errmsg_ptrs_array,
+ unsigned * errs_count)
+{
+ struct Dwarf_Harmless_s *dhp = &dbg->de_harmless_errors;
+ if(!dhp->dh_errors) {
+ dhp->dh_errs_count = 0;
+ return DW_DLV_NO_ENTRY;
+ }
+ if(dhp->dh_errs_count == 0) {
+ return DW_DLV_NO_ENTRY;
+ }
+ if(errs_count) {
+ *errs_count = dhp->dh_errs_count;
+ }
+ if(count) {
+ /* NULL terminate the array of pointers */
+ --count;
+ errmsg_ptrs_array[count] = 0;
+
+ if(dhp->dh_next_to_use != dhp->dh_first) {
+ unsigned i = 0;
+ unsigned cur = dhp->dh_first;
+ for(i = 0; cur != dhp->dh_next_to_use; ++i) {
+ if(i >= count ) {
+ /* All output spaces are used. */
+ break;
+ }
+ errmsg_ptrs_array[i] = dhp->dh_errors[cur];
+ cur = (cur +1) % dhp->dh_maxcount;
+ }
+ errmsg_ptrs_array[i] = 0;
+ }
+ }
+ dhp->dh_next_to_use = 0;
+ dhp->dh_first = 0;
+ dhp->dh_errs_count = 0;
+ return DW_DLV_OK;
+}
+
+/* strncpy does not null-terminate, this does it. */
+static void
+safe_strncpy(char *targ, char *src, unsigned spaceavail)
+{
+ unsigned goodcount = spaceavail-1;
+ if(spaceavail < 1) {
+ return; /* impossible */
+ }
+ strncpy(targ,src,goodcount);
+ targ[goodcount] = 0;
+}
+
+/* Insertion made public is only for testing the harmless error code,
+ it is not necessarily useful for libdwarf client code aside
+ from code testing libdwarf. */
+void dwarf_insert_harmless_error(Dwarf_Debug dbg,
+ char *newerror)
+{
+ struct Dwarf_Harmless_s *dhp = &dbg->de_harmless_errors;
+ unsigned next = 0;
+ unsigned cur = dhp->dh_next_to_use;
+ char *msgspace;
+ if(!dhp->dh_errors) {
+ dhp->dh_errs_count++;
+ return;
+ }
+ msgspace = dhp->dh_errors[cur];
+ safe_strncpy(msgspace, newerror,DW_HARMLESS_ERROR_MSG_STRING_SIZE);
+ next = (cur+1) % dhp->dh_maxcount;
+ dhp->dh_errs_count++;
+ dhp->dh_next_to_use = next;
+ if (dhp->dh_next_to_use == dhp->dh_first) {
+ /* Array is full set full invariant. */
+ dhp->dh_first = (dhp->dh_first+1) % dhp->dh_maxcount;
+ }
+}
+
+/* The size of the circular list of strings may be set
+ and reset as desired. Returns the previous size of
+ the list. If the list is shortened excess error entries
+ are simply dropped.
+ If the reallocation fails the list size is left unchanged.
+ Do not make this a long list!
+
+ Remember the maxcount we record is 1 > the user count,
+ so we adjust it so it looks like the user count.
+*/
+unsigned dwarf_set_harmless_error_list_size(Dwarf_Debug dbg,
+ unsigned maxcount )
+{
+ struct Dwarf_Harmless_s *dhp = &dbg->de_harmless_errors;
+ unsigned prevcount = dhp->dh_maxcount;
+ if(maxcount != 0) {
+ ++maxcount;
+ if(maxcount != dhp->dh_maxcount) {
+ /* Assign transfers 'ownership' of the malloc areas
+ to oldarray. */
+ struct Dwarf_Harmless_s oldarray = *dhp;
+ /* Do not double increment the max, the init() func
+ increments it too. */
+ dwarf_harmless_init(dhp,maxcount-1);
+ if(oldarray.dh_next_to_use != oldarray.dh_first) {
+ unsigned i = 0;
+ for(i = oldarray.dh_first; i != oldarray.dh_next_to_use;
+ i = (i+1)%oldarray.dh_maxcount) {
+ dwarf_insert_harmless_error(dbg,oldarray.dh_errors[i]);
+ }
+ if( oldarray.dh_errs_count > dhp->dh_errs_count) {
+ dhp->dh_errs_count = oldarray.dh_errs_count;
+ }
+ }
+ dwarf_harmless_cleanout(&oldarray);
+ }
+ }
+ return prevcount-1;
+}
+
+/* Only callable from within libdwarf (as a practical matter)
+*/
+void
+dwarf_harmless_init(struct Dwarf_Harmless_s *dhp,unsigned size)
+{
+ unsigned i = 0;
+ memset(dhp,0,sizeof(*dhp));
+ dhp->dh_maxcount = size +1;
+ dhp->dh_errors = (char **)malloc(sizeof( char *) *dhp->dh_maxcount);
+ if (!dhp->dh_errors) {
+ dhp->dh_maxcount = 0;
+ return;
+ }
+
+ for(i = 0; i < dhp->dh_maxcount; ++i) {
+ char *newstr =
+ (char *)malloc(DW_HARMLESS_ERROR_MSG_STRING_SIZE);
+ dhp->dh_errors[i] = newstr;
+ if(!newstr) {
+ dhp->dh_maxcount = 0;
+ /* Let it leak, the leak is a constrained amount. */
+ dhp->dh_errors = 0;
+ return;
+ }
+ /* We make the string content well-defined by an initial
+ NUL byte, but this is not really necessary. */
+ newstr[0] = 0;
+ }
+}
+
+void
+dwarf_harmless_cleanout(struct Dwarf_Harmless_s *dhp)
+{
+ unsigned i = 0;
+ if(!dhp->dh_errors) {
+ return;
+ }
+ for(i = 0; i < dhp->dh_maxcount; ++i) {
+ free(dhp->dh_errors[i]);
+ }
+ free(dhp->dh_errors);
+ dhp->dh_errors = 0;
+ dhp->dh_maxcount = 0;
+}
+
diff --git a/libdwarf/dwarf_harmless.h b/libdwarf/dwarf_harmless.h
new file mode 100644
index 0000000..3d4d910
--- /dev/null
+++ b/libdwarf/dwarf_harmless.h
@@ -0,0 +1,31 @@
+/*
+
+ Copyright (C) 2010 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+*/
+
+
+
+void dwarf_harmless_init(struct Dwarf_Harmless_s *dhp,unsigned size);
+void dwarf_harmless_cleanout(struct Dwarf_Harmless_s *dhp);
+
diff --git a/libdwarf/dwarf_incl.h b/libdwarf/dwarf_incl.h
new file mode 100644
index 0000000..58208e1
--- /dev/null
+++ b/libdwarf/dwarf_incl.h
@@ -0,0 +1,69 @@
+/*
+
+ Copyright (C) 2000, 2002, 2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2008-2010 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#ifndef DWARF_INCL_H
+#define DWARF_INCL_H
+#if (!defined(HAVE_RAW_LIBELF_OK) && defined(HAVE_LIBELF_OFF64_OK) )
+/* At a certain point libelf.h requires _GNU_SOURCE.
+ here we assume the criteria in configure determine that
+ usefully.
+*/
+#define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_STDAFX_H /* Windows specific. */
+#include "stdafx.h"
+#endif /* HAVE_STDAFX_H */
+
+#include "libdwarfdefs.h"
+#include <string.h>
+
+#ifdef HAVE_ELF_H
+#include <elf.h>
+#endif
+
+#include <limits.h>
+#include <dwarf.h>
+#include <libdwarf.h>
+
+#include "dwarf_base_types.h"
+#include "dwarf_alloc.h"
+#include "dwarf_opaque.h"
+#include "dwarf_error.h"
+#include "dwarf_util.h"
+#endif /* DWARF_INCL_H */
diff --git a/libdwarf/dwarf_init_finish.c b/libdwarf/dwarf_init_finish.c
new file mode 100644
index 0000000..ce73979
--- /dev/null
+++ b/libdwarf/dwarf_init_finish.c
@@ -0,0 +1,732 @@
+/*
+
+ Copyright (C) 2000,2002,2003,2004,2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2008-2010 Arxan Technologies, Inc. All Rights Reserved.
+ Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved.
+ Portions Copyright (C) 2010 SN Systems Ltd. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+#include "config.h"
+#include "dwarf_incl.h"
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "dwarf_incl.h"
+#include "dwarf_harmless.h"
+#include "malloc_check.h"
+
+#define DWARF_DBG_ERROR(dbg,errval,retval) \
+ _dwarf_error(dbg, error, errval); return(retval);
+
+#define FALSE 0
+#define TRUE 1
+
+
+
+/* This static is copied to the dbg on dbg init
+ so that the static need not be referenced at
+ run time, preserving better locality of
+ reference.
+ Value is 0 means do the string check.
+ Value non-zero means do not do the check.
+*/
+static Dwarf_Small _dwarf_assume_string_bad;
+static Dwarf_Small _dwarf_apply_relocs = 1;
+
+/* Call this after calling dwarf_init but before doing anything else.
+ It applies to all objects, not just the current object. */
+int
+dwarf_set_reloc_application(int apply)
+{
+ int oldval = _dwarf_apply_relocs;
+ _dwarf_apply_relocs = apply;
+ return oldval;
+}
+
+int
+dwarf_set_stringcheck(int newval)
+{
+ int oldval = _dwarf_assume_string_bad;
+
+ _dwarf_assume_string_bad = newval;
+ return oldval;
+}
+
+/* Unifies the basic duplicate/empty testing and section
+ data setting to one place. */
+static int
+get_basic_section_data(Dwarf_Debug dbg,
+ struct Dwarf_Section_s *secdata,
+ struct Dwarf_Obj_Access_Section_s *doas,
+ Dwarf_Half section_index,
+ Dwarf_Error* error,
+ int duperr, int emptyerr )
+{
+ /* There is an elf convention that section index 0 is reserved,
+ and that section is always empty.
+ Non-elf object formats must honor that by ensuring that
+ (when they assign numbers to 'sections' or 'section-like-things')
+ they never assign a real section section-number 0 to dss_index. */
+ if (secdata->dss_index != 0) {
+ DWARF_DBG_ERROR(dbg, duperr, DW_DLV_ERROR);
+ }
+ if (doas->size == 0) {
+ if (emptyerr == 0 ) {
+ /* Allow empty section. */
+ return DW_DLV_OK;
+ }
+ /* Know no reason to allow section */
+ DWARF_DBG_ERROR(dbg, emptyerr, DW_DLV_ERROR);
+ }
+ secdata->dss_index = section_index;
+ secdata->dss_size = doas->size;
+ secdata->dss_addr = doas->addr;
+ secdata->dss_link = doas->link;
+ secdata->dss_entrysize = doas->entrysize;
+ return DW_DLV_OK;
+}
+
+
+static void
+add_rela_data( struct Dwarf_Section_s *secdata,
+ struct Dwarf_Obj_Access_Section_s *doas,
+ Dwarf_Half section_index)
+{
+ secdata->dss_reloc_index = section_index;
+ secdata->dss_reloc_size = doas->size;
+ secdata->dss_reloc_entrysize = doas->entrysize;
+ secdata->dss_reloc_addr = doas->addr;
+ secdata->dss_reloc_symtab = doas->link;
+ secdata->dss_reloc_link = doas->link;
+}
+
+/* Given an Elf ptr, set up dbg with pointers
+ to all the Dwarf data sections.
+ Return NULL on error.
+
+ This function is also responsible for determining
+ whether the given object contains Dwarf information
+ or not. The test currently used is that it contains
+ either a .debug_info or a .debug_frame section. If
+ not, it returns DW_DLV_NO_ENTRY causing dwarf_init() also to
+ return DW_DLV_NO_ENTRY. Earlier, we had thought of using only
+ the presence/absence of .debug_info to test, but we
+ added .debug_frame since there could be stripped objects
+ that have only a .debug_frame section for exception
+ processing.
+ DW_DLV_NO_ENTRY or DW_DLV_OK or DW_DLV_ERROR */
+static int
+_dwarf_setup(Dwarf_Debug dbg, Dwarf_Error * error)
+{
+ const char *scn_name = 0;
+ int foundDwarf = 0;
+ struct Dwarf_Obj_Access_Interface_s * obj = 0;
+
+ Dwarf_Endianness endianness;
+
+ Dwarf_Unsigned section_size = 0;
+ Dwarf_Unsigned section_count = 0;
+ Dwarf_Half section_index = 0;
+ Dwarf_Addr section_addr = 0;
+
+ foundDwarf = FALSE;
+
+ dbg->de_assume_string_in_bounds = _dwarf_assume_string_bad;
+
+ dbg->de_same_endian = 1;
+ dbg->de_copy_word = memcpy;
+ obj = dbg->de_obj_file;
+ endianness = obj->methods->get_byte_order(obj->object);
+#ifdef WORDS_BIGENDIAN
+ dbg->de_big_endian_object = 1;
+ if (endianness == DW_OBJECT_LSB ) {
+ dbg->de_same_endian = 0;
+ dbg->de_big_endian_object = 0;
+ dbg->de_copy_word = _dwarf_memcpy_swap_bytes;
+ }
+#else /* little endian */
+ dbg->de_big_endian_object = 0;
+ if (endianness == DW_OBJECT_MSB ) {
+ dbg->de_same_endian = 0;
+ dbg->de_big_endian_object = 1;
+ dbg->de_copy_word = _dwarf_memcpy_swap_bytes;
+ }
+#endif /* !WORDS_BIGENDIAN */
+
+
+ /* The following de_length_size is Not Too Significant. Only used
+ one calculation, and an approximate one at that. */
+ dbg->de_length_size = obj->methods->get_length_size(obj->object);
+ dbg->de_pointer_size = obj->methods->get_pointer_size(obj->object);
+
+ /* For windows always is 4 ? */
+#ifdef WIN32
+ dbg->de_pointer_size = 4;
+#endif /* WIN32 */
+
+ section_count = obj->methods->get_section_count(obj->object);
+
+ /* We can skip index 0 when considering ELF files, but not other
+ object types. Indeed regardless of the object type we should
+ skip section 0 here.
+ This is a convention. We depend on it.
+ Non-elf object access code should
+ (in itself) understand we will index beginning at 1 and adjust
+ itself to deal with this Elf convention. Without this
+ convention various parts of the code in this file won't work correctly.
+ A dss_index of 0 must not be used, even though we start at 0
+ here. So the get_section_info() must adapt to the situation
+ (the elf version does automatically as a result of Elf having
+ a section zero with zero length and an empty name). */
+ for (section_index = 0; section_index < section_count;
+ ++section_index) {
+
+ struct Dwarf_Obj_Access_Section_s doas;
+ int res = DW_DLV_ERROR;
+ int err = 0;
+
+ memset(&doas,0,sizeof(doas));
+ res = obj->methods->get_section_info(obj->object,
+ section_index,
+ &doas, &err);
+ if(res == DW_DLV_ERROR){
+ DWARF_DBG_ERROR(dbg, err, DW_DLV_ERROR);
+ }
+
+ section_addr = doas.addr;
+ section_size = doas.size;
+ scn_name = doas.name;
+
+ if (strncmp(scn_name, ".debug_", 7)
+ && strcmp(scn_name, ".eh_frame")
+ && strcmp(scn_name, ".symtab")
+ && strcmp(scn_name, ".strtab")
+ && strncmp(scn_name, ".rela.",6)) {
+ continue;
+ }
+ else if (strcmp(scn_name, ".debug_info") == 0) {
+ res = get_basic_section_data(dbg,&dbg->de_debug_info, &doas,
+ section_index,error,
+ DW_DLE_DEBUG_INFO_DUPLICATE,DW_DLE_DEBUG_INFO_NULL);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ foundDwarf = TRUE;
+ }
+ else if (strcmp(scn_name, ".debug_types") == 0) {
+ res = get_basic_section_data(dbg,&dbg->de_debug_types, &doas,
+ section_index,error,
+ DW_DLE_DEBUG_TYPES_DUPLICATE,DW_DLE_DEBUG_TYPES_NULL);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ foundDwarf = TRUE;
+ }
+ else if (strcmp(scn_name, ".debug_abbrev") == 0) {
+ res = get_basic_section_data(dbg,&dbg->de_debug_abbrev, &doas,
+ section_index,error,
+ DW_DLE_DEBUG_ABBREV_DUPLICATE,DW_DLE_DEBUG_ABBREV_NULL);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ }
+ else if (strcmp(scn_name, ".debug_aranges") == 0) {
+ res = get_basic_section_data(dbg,&dbg->de_debug_aranges, &doas,
+ section_index,error, DW_DLE_DEBUG_ARANGES_DUPLICATE,0);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ }
+
+ else if (strcmp(scn_name, ".debug_line") == 0) {
+ res = get_basic_section_data(dbg,&dbg->de_debug_line, &doas,
+ section_index,error, DW_DLE_DEBUG_LINE_DUPLICATE,0);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ }
+ else if (strcmp(scn_name, ".debug_frame") == 0) {
+ res = get_basic_section_data(dbg,&dbg->de_debug_frame, &doas,
+ section_index,error, DW_DLE_DEBUG_FRAME_DUPLICATE,0);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ foundDwarf = TRUE;
+ } else if (strcmp(scn_name, ".eh_frame") == 0) {
+ /* gnu egcs-1.1.2 data */
+ res = get_basic_section_data(dbg,&dbg->de_debug_frame_eh_gnu,
+ &doas,
+ section_index,error, DW_DLE_DEBUG_FRAME_DUPLICATE,0);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ foundDwarf = TRUE;
+ }
+ else if (strcmp(scn_name, ".debug_loc") == 0) {
+ res = get_basic_section_data(dbg,&dbg->de_debug_loc, &doas,
+ section_index,error, DW_DLE_DEBUG_LOC_DUPLICATE,0);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ }
+ else if (strcmp(scn_name, ".debug_pubnames") == 0) {
+ res = get_basic_section_data(dbg,&dbg->de_debug_pubnames, &doas,
+ section_index,error, DW_DLE_DEBUG_PUBNAMES_DUPLICATE,0);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ }
+
+ else if (strcmp(scn_name, ".debug_str") == 0) {
+ res = get_basic_section_data(dbg,&dbg->de_debug_str, &doas,
+ section_index,error, DW_DLE_DEBUG_STR_DUPLICATE,0);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ }
+ else if (strcmp(scn_name, ".debug_funcnames") == 0) {
+ /* SGI IRIX-only. */
+ res = get_basic_section_data(dbg,&dbg->de_debug_funcnames,
+ &doas,
+ section_index,error, DW_DLE_DEBUG_FUNCNAMES_DUPLICATE,0);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ }
+ else if (strcmp(scn_name, ".debug_typenames") == 0) {
+ /* SGI IRIX-only, created years before DWARF3. Content
+ essentially identical to .debug_pubtypes. */
+ res = get_basic_section_data(dbg,&dbg->de_debug_typenames,
+ &doas,
+ section_index,error, DW_DLE_DEBUG_TYPENAMES_DUPLICATE,0);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ } else if (strcmp(scn_name, ".debug_pubtypes") == 0) {
+ /* Section new in DWARF3. */
+ res = get_basic_section_data(dbg,&dbg->de_debug_pubtypes, &doas,
+ section_index,error, DW_DLE_DEBUG_PUBTYPES_DUPLICATE,0);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ }
+ else if (strcmp(scn_name, ".debug_varnames") == 0) {
+ /* SGI IRIX-only. */
+ res = get_basic_section_data(dbg,&dbg->de_debug_varnames, &doas,
+ section_index,error, DW_DLE_DEBUG_VARNAMES_DUPLICATE,0);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ }
+ else if (strcmp(scn_name, ".debug_weaknames") == 0) {
+ /* SGI IRIX-only. */
+ res = get_basic_section_data(dbg,&dbg->de_debug_weaknames,
+ &doas, section_index,error,
+ DW_DLE_DEBUG_WEAKNAMES_DUPLICATE,0);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ } else if (strcmp(scn_name, ".debug_macinfo") == 0) {
+ res = get_basic_section_data(dbg,&dbg->de_debug_macinfo, &doas,
+ section_index,error, DW_DLE_DEBUG_MACINFO_DUPLICATE,0);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ }
+ else if (strcmp(scn_name, ".debug_ranges") == 0) {
+ res = get_basic_section_data(dbg,&dbg->de_debug_ranges, &doas,
+ section_index,error, DW_DLE_DEBUG_RANGES_DUPLICATE,0);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ foundDwarf = TRUE;
+ }
+ else if (strcmp(scn_name, ".symtab") == 0) {
+ res = get_basic_section_data(dbg,&dbg->de_elf_symtab, &doas,
+ section_index,error, DW_DLE_DEBUG_SYMTAB_ERR,0);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ }
+ else if (strcmp(scn_name, ".strtab") == 0) {
+ res = get_basic_section_data(dbg,&dbg->de_elf_strtab, &doas,
+ section_index,error, DW_DLE_DEBUG_STRTAB_ERR,0);
+ if(res != DW_DLV_OK) {
+ return res;
+ }
+ }
+ else if (strncmp(scn_name, ".rela.debug_",12) == 0) {
+ const char *rcn_name = scn_name + 5;
+ if (strcmp(rcn_name, ".debug_info") == 0) {
+ add_rela_data(&dbg->de_debug_info,&doas,section_index);
+ } else if (strcmp(rcn_name, ".debug_abbrev") == 0) {
+ add_rela_data(&dbg->de_debug_abbrev,&doas,section_index);
+ } else if (strcmp(rcn_name, ".debug_aranges") == 0) {
+ add_rela_data(&dbg->de_debug_aranges,&doas,section_index);
+ } else if (strcmp(rcn_name, ".debug_line") == 0) {
+ add_rela_data(&dbg->de_debug_line,&doas,section_index);
+ } else if (strcmp(rcn_name, ".debug_frame") == 0) {
+ add_rela_data(&dbg->de_debug_frame,&doas,section_index);
+ } else if (strcmp(rcn_name, ".eh_frame") == 0) {
+ add_rela_data(&dbg->de_debug_frame_eh_gnu,&doas,section_index);
+ } else if (strcmp(rcn_name, ".debug_loc") == 0) {
+ add_rela_data(&dbg->de_debug_loc,&doas,section_index);
+ } else if (strcmp(rcn_name, ".debug_pubnames") == 0) {
+ add_rela_data(&dbg->de_debug_pubnames,&doas,section_index);
+ } else if (strcmp(rcn_name, ".debug_str") == 0) {
+ add_rela_data(&dbg->de_debug_str,&doas,section_index);
+ } else if (strcmp(rcn_name, ".debug_funcnames") == 0) {
+ add_rela_data(&dbg->de_debug_funcnames,&doas,section_index);
+ } else if (strcmp(rcn_name, ".debug_typenames") == 0) {
+ add_rela_data(&dbg->de_debug_typenames,&doas,section_index);
+ } else if (strcmp(rcn_name, ".debug_pubtypes") == 0) {
+ add_rela_data(&dbg->de_debug_pubtypes,&doas,section_index);
+ } else if (strcmp(rcn_name, ".debug_varnames") == 0) {
+ add_rela_data(&dbg->de_debug_varnames,&doas,section_index);
+ } else if (strcmp(rcn_name, ".debug_weaknames") == 0) {
+ add_rela_data(&dbg->de_debug_weaknames,&doas,section_index);
+ } else if (strcmp(rcn_name, ".debug_macinfo") == 0) {
+ add_rela_data(&dbg->de_debug_macinfo,&doas,section_index);
+ }
+ }
+ }
+ if (foundDwarf) {
+ return DW_DLV_OK;
+ }
+ return DW_DLV_NO_ENTRY;
+}
+
+
+/*
+ Use a Dwarf_Obj_Access_Interface to kick things off. All other
+ init routines eventually use this one.
+ The returned Dwarf_Debug contains a copy of *obj
+ the callers copy of *obj may be freed whenever the caller
+ wishes.
+*/
+int
+dwarf_object_init(Dwarf_Obj_Access_Interface* obj, Dwarf_Handler errhand,
+ Dwarf_Ptr errarg, Dwarf_Debug* ret_dbg,
+ Dwarf_Error* error)
+{
+ Dwarf_Debug dbg = 0;
+ int setup_result = DW_DLV_OK;
+
+ dbg = _dwarf_get_debug();
+ if (dbg == NULL) {
+ DWARF_DBG_ERROR(dbg, DW_DLE_DBG_ALLOC, DW_DLV_ERROR);
+ }
+ dbg->de_errhand = errhand;
+ dbg->de_errarg = errarg;
+ dbg->de_frame_rule_initial_value = DW_FRAME_REG_INITIAL_VALUE;
+ dbg->de_frame_reg_rules_entry_count = DW_FRAME_LAST_REG_NUM;
+#ifdef HAVE_OLD_FRAME_CFA_COL
+ /* DW_FRAME_CFA_COL is really only suitable for old libdwarf frame
+ interfaces and its value of 0 there is only usable where
+ (as in MIPS) register 0 has no value other than 0 so
+ we can use the frame table column 0 for the CFA value
+ (and rely on client software to know when 'register 0'
+ is the cfa and when to just use a value 0 for register 0).
+ */
+ dbg->de_frame_cfa_col_number = DW_FRAME_CFA_COL;
+#else
+ dbg->de_frame_cfa_col_number = DW_FRAME_CFA_COL3;
+#endif
+ dbg->de_frame_same_value_number = DW_FRAME_SAME_VAL;
+ dbg->de_frame_undefined_value_number = DW_FRAME_UNDEFINED_VAL;
+
+ dbg->de_obj_file = obj;
+
+ setup_result = _dwarf_setup(dbg, error);
+ if (setup_result != DW_DLV_OK) {
+ /* The status we want to return here is of _dwarf_setup,
+ not of the _dwarf_free_all_of_one_debug(dbg) call.
+ So use a local status variable for the free. */
+ int freeresult = _dwarf_free_all_of_one_debug(dbg);
+ if (freeresult == DW_DLV_ERROR) {
+ DWARF_DBG_ERROR(dbg, DW_DLE_DBG_ALLOC, DW_DLV_ERROR);
+ }
+ dwarf_malloc_check_complete("After Final free");
+ return setup_result;
+ }
+
+ dwarf_harmless_init(&dbg->de_harmless_errors,
+ DW_HARMLESS_ERROR_CIRCULAR_LIST_DEFAULT_SIZE);
+
+ /* This call cannot fail: allocates nothing, releases nothing */
+ _dwarf_setup_debug(dbg);
+
+
+ *ret_dbg = dbg;
+ return DW_DLV_OK;
+}
+
+
+/* A finish routine that is completely unaware of ELF.
+
+ Frees all memory that was not previously freed by
+ dwarf_dealloc.
+ Aside frmo certain categories. */
+int
+dwarf_object_finish(Dwarf_Debug dbg, Dwarf_Error * error)
+{
+ int res = DW_DLV_OK;
+
+ res = _dwarf_free_all_of_one_debug(dbg);
+ if (res == DW_DLV_ERROR) {
+ DWARF_DBG_ERROR(dbg, DW_DLE_DBG_ALLOC, DW_DLV_ERROR);
+ }
+ dwarf_malloc_check_complete("After Final free");
+
+ return res;
+}
+
+
+/* Load the ELF section with the specified index and set the
+ pointer pointed to by section_data to the memory where it
+ was loaded. */
+int
+_dwarf_load_section(Dwarf_Debug dbg,
+ struct Dwarf_Section_s *section,
+ Dwarf_Error * error)
+{
+ int res = DW_DLV_ERROR;
+ int err = 0;
+ struct Dwarf_Obj_Access_Interface_s *o = 0;
+
+ /* check to see if the section is already loaded */
+ if (section->dss_data != NULL) {
+ return DW_DLV_OK;
+ }
+ o = dbg->de_obj_file;
+ /* There is an elf convention that section index 0 is reserved,
+ and that section is always empty.
+ Non-elf object formats must honor that by ensuring that
+ (when they assign numbers to 'sections' or 'section-like-things')
+ they never assign a real section section-number 0 to dss_index. */
+ res = o->methods->load_section(
+ o->object, section->dss_index,
+ &section->dss_data, &err);
+ if(res == DW_DLV_ERROR){
+ DWARF_DBG_ERROR(dbg, err, DW_DLV_ERROR);
+ }
+ if(_dwarf_apply_relocs == 0) {
+ return res;
+ }
+ if(section->dss_reloc_size == 0) {
+ return res;
+ }
+ if(!o->methods->relocate_a_section) {
+ return res;
+ }
+ /*apply relocations */
+ res = o->methods->relocate_a_section( o->object, section->dss_index,
+ dbg, &err);
+ if(res == DW_DLV_ERROR) {
+ DWARF_DBG_ERROR(dbg, err, DW_DLV_ERROR);
+ }
+ return res;
+}
+
+/* This is a hack so clients can verify offsets.
+ Added April 2005 so that debugger can detect broken offsets
+ (which happened in an IRIX -64 executable larger than 2GB
+ using MIPSpro 7.3.1.3 compilers. A couple .debug_pubnames
+ offsets were wrong.).
+*/
+int
+dwarf_get_section_max_offsets(Dwarf_Debug dbg,
+ Dwarf_Unsigned * debug_info_size,
+ Dwarf_Unsigned * debug_abbrev_size,
+ Dwarf_Unsigned * debug_line_size,
+ Dwarf_Unsigned * debug_loc_size,
+ Dwarf_Unsigned * debug_aranges_size,
+ Dwarf_Unsigned * debug_macinfo_size,
+ Dwarf_Unsigned * debug_pubnames_size,
+ Dwarf_Unsigned * debug_str_size,
+ Dwarf_Unsigned * debug_frame_size,
+ Dwarf_Unsigned * debug_ranges_size,
+ Dwarf_Unsigned * debug_typenames_size)
+{
+ *debug_info_size = dbg->de_debug_info.dss_size;
+ *debug_abbrev_size = dbg->de_debug_abbrev.dss_size;
+ *debug_line_size = dbg->de_debug_line.dss_size;
+ *debug_loc_size = dbg->de_debug_loc.dss_size;
+ *debug_aranges_size = dbg->de_debug_aranges.dss_size;
+ *debug_macinfo_size = dbg->de_debug_macinfo.dss_size;
+ *debug_pubnames_size = dbg->de_debug_pubnames.dss_size;
+ *debug_str_size = dbg->de_debug_str.dss_size;
+ *debug_frame_size = dbg->de_debug_frame.dss_size;
+ *debug_ranges_size = dbg->de_debug_ranges.dss_size;
+ *debug_typenames_size = dbg->de_debug_typenames.dss_size;
+ return DW_DLV_OK;
+}
+/* This adds the new types size (new section) to the output data.
+ Oct 27, 2011. */
+int
+dwarf_get_section_max_offsets_b(Dwarf_Debug dbg,
+ Dwarf_Unsigned * debug_info_size,
+ Dwarf_Unsigned * debug_abbrev_size,
+ Dwarf_Unsigned * debug_line_size,
+ Dwarf_Unsigned * debug_loc_size,
+ Dwarf_Unsigned * debug_aranges_size,
+ Dwarf_Unsigned * debug_macinfo_size,
+ Dwarf_Unsigned * debug_pubnames_size,
+ Dwarf_Unsigned * debug_str_size,
+ Dwarf_Unsigned * debug_frame_size,
+ Dwarf_Unsigned * debug_ranges_size,
+ Dwarf_Unsigned * debug_typenames_size,
+ Dwarf_Unsigned * debug_types_size)
+{
+ *debug_info_size = dbg->de_debug_info.dss_size;
+ *debug_abbrev_size = dbg->de_debug_abbrev.dss_size;
+ *debug_line_size = dbg->de_debug_line.dss_size;
+ *debug_loc_size = dbg->de_debug_loc.dss_size;
+ *debug_aranges_size = dbg->de_debug_aranges.dss_size;
+ *debug_macinfo_size = dbg->de_debug_macinfo.dss_size;
+ *debug_pubnames_size = dbg->de_debug_pubnames.dss_size;
+ *debug_str_size = dbg->de_debug_str.dss_size;
+ *debug_frame_size = dbg->de_debug_frame.dss_size;
+ *debug_ranges_size = dbg->de_debug_ranges.dss_size;
+ *debug_typenames_size = dbg->de_debug_typenames.dss_size;
+ *debug_types_size = dbg->de_debug_types.dss_size;
+ return DW_DLV_OK;
+}
+
+
+/* Given a section name, get its size and address */
+int
+dwarf_get_section_info_by_name(Dwarf_Debug dbg,
+ const char *section_name,
+ Dwarf_Addr *section_addr,
+ Dwarf_Unsigned *section_size,
+ Dwarf_Error * error)
+{
+ struct Dwarf_Obj_Access_Section_s doas;
+ struct Dwarf_Obj_Access_Interface_s * obj = 0;
+ Dwarf_Unsigned section_count = 0;
+ Dwarf_Half section_index = 0;
+
+ *section_addr = 0;
+ *section_size = 0;
+
+ obj = dbg->de_obj_file;
+ if (NULL == obj) {
+ return DW_DLV_NO_ENTRY;
+ }
+
+ section_count = obj->methods->get_section_count(obj->object);
+
+ /* We can skip index 0 when considering ELF files, but not other
+ object types. */
+ for (section_index = 0; section_index < section_count;
+ ++section_index) {
+ int err = 0;
+ int res = obj->methods->get_section_info(obj->object,
+ section_index, &doas, &err);
+ if (res == DW_DLV_ERROR) {
+ DWARF_DBG_ERROR(dbg, err, DW_DLV_ERROR);
+ }
+
+ if (!strcmp(section_name,doas.name)) {
+ *section_addr = doas.addr;
+ *section_size = doas.size;
+ return DW_DLV_OK;
+ }
+ }
+
+ return DW_DLV_NO_ENTRY;
+}
+
+/* Given a section index, get its size and address */
+int
+dwarf_get_section_info_by_index(Dwarf_Debug dbg,
+ int section_index,
+ const char **section_name,
+ Dwarf_Addr *section_addr,
+ Dwarf_Unsigned *section_size,
+ Dwarf_Error * error)
+{
+ *section_addr = 0;
+ *section_size = 0;
+ *section_name = NULL;
+
+ /* Check if we have a valid section index */
+ if (section_index >= 0 && section_index < dwarf_get_section_count(dbg)) {
+ int res = 0;
+ int err = 0;
+ struct Dwarf_Obj_Access_Section_s doas;
+ struct Dwarf_Obj_Access_Interface_s * obj = dbg->de_obj_file;
+ if (NULL == obj) {
+ return DW_DLV_NO_ENTRY;
+ }
+ res = obj->methods->get_section_info(obj->object,
+ section_index, &doas, &err);
+ if (res == DW_DLV_ERROR){
+ DWARF_DBG_ERROR(dbg, err, DW_DLV_ERROR);
+ }
+
+ *section_addr = doas.addr;
+ *section_size = doas.size;
+ *section_name = doas.name;
+ return DW_DLV_OK;
+ }
+ return DW_DLV_NO_ENTRY;
+}
+
+/* Get section count */
+int
+dwarf_get_section_count(Dwarf_Debug dbg)
+{
+ struct Dwarf_Obj_Access_Interface_s * obj = dbg->de_obj_file;
+ if (NULL == obj) {
+ return DW_DLV_NO_ENTRY;
+ }
+ return obj->methods->get_section_count(obj->object);
+}
+
+Dwarf_Cmdline_Options dwarf_cmdline_options = {
+ FALSE /* Use quiet mode by default. */
+};
+
+/* Lets libdwarf reflect a command line option, so we can get details
+ of some errors printed using libdwarf-internal information. */
+void
+dwarf_record_cmdline_options(Dwarf_Cmdline_Options options)
+{
+ dwarf_cmdline_options = options;
+}
diff --git a/libdwarf/dwarf_leb.c b/libdwarf/dwarf_leb.c
new file mode 100644
index 0000000..7e01d84
--- /dev/null
+++ b/libdwarf/dwarf_leb.c
@@ -0,0 +1,146 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+
+
+/* Decode ULEB */
+Dwarf_Unsigned
+_dwarf_decode_u_leb128(Dwarf_Small * leb128, Dwarf_Word * leb128_length)
+{
+ unsigned char byte;
+ Dwarf_Word word_number;
+ Dwarf_Unsigned number;
+ Dwarf_Sword shift;
+ Dwarf_Sword byte_length;
+
+ /* The following unrolls-the-loop for the first few bytes and
+ unpacks into 32 bits to make this as fast as possible.
+ word_number is assumed big enough that the shift has a defined
+ result. */
+ if ((*leb128 & 0x80) == 0) {
+ if (leb128_length != NULL)
+ *leb128_length = 1;
+ return (*leb128);
+ } else if ((*(leb128 + 1) & 0x80) == 0) {
+ if (leb128_length != NULL)
+ *leb128_length = 2;
+
+ word_number = *leb128 & 0x7f;
+ word_number |= (*(leb128 + 1) & 0x7f) << 7;
+ return (word_number);
+ } else if ((*(leb128 + 2) & 0x80) == 0) {
+ if (leb128_length != NULL)
+ *leb128_length = 3;
+
+ word_number = *leb128 & 0x7f;
+ word_number |= (*(leb128 + 1) & 0x7f) << 7;
+ word_number |= (*(leb128 + 2) & 0x7f) << 14;
+ return (word_number);
+ } else if ((*(leb128 + 3) & 0x80) == 0) {
+ if (leb128_length != NULL)
+ *leb128_length = 4;
+
+ word_number = *leb128 & 0x7f;
+ word_number |= (*(leb128 + 1) & 0x7f) << 7;
+ word_number |= (*(leb128 + 2) & 0x7f) << 14;
+ word_number |= (*(leb128 + 3) & 0x7f) << 21;
+ return (word_number);
+ }
+
+ /* The rest handles long numbers Because the 'number' may be larger
+ than the default int/unsigned, we must cast the 'byte' before
+ the shift for the shift to have a defined result. */
+ number = 0;
+ shift = 0;
+ byte_length = 1;
+ byte = *(leb128);
+ for (;;) {
+ number |= ((Dwarf_Unsigned) (byte & 0x7f)) << shift;
+
+ if ((byte & 0x80) == 0) {
+ if (leb128_length != NULL)
+ *leb128_length = byte_length;
+ return (number);
+ }
+ shift += 7;
+
+ byte_length++;
+ ++leb128;
+ byte = *leb128;
+ }
+}
+
+#define BITSINBYTE 8
+
+/* decode SLEB */
+Dwarf_Signed
+_dwarf_decode_s_leb128(Dwarf_Small * leb128, Dwarf_Word * leb128_length)
+{
+ Dwarf_Signed number = 0;
+ Dwarf_Bool sign = 0;
+ Dwarf_Sword shift = 0;
+ unsigned char byte = *leb128;
+ Dwarf_Sword byte_length = 1;
+
+ /* byte_length being the number of bytes of data absorbed so far in
+ turning the leb into a Dwarf_Signed. */
+
+ for (;;) {
+ sign = byte & 0x40;
+ number |= ((Dwarf_Signed) ((byte & 0x7f))) << shift;
+ shift += 7;
+
+ if ((byte & 0x80) == 0) {
+ break;
+ }
+ ++leb128;
+ byte = *leb128;
+ byte_length++;
+ }
+
+ if ((shift < sizeof(Dwarf_Signed) * BITSINBYTE) && sign) {
+ number |= -((Dwarf_Signed) 1 << shift);
+ }
+
+ if (leb128_length != NULL)
+ *leb128_length = byte_length;
+ return (number);
+}
diff --git a/libdwarf/dwarf_line.c b/libdwarf/dwarf_line.c
new file mode 100644
index 0000000..5f81e7c
--- /dev/null
+++ b/libdwarf/dwarf_line.c
@@ -0,0 +1,2059 @@
+/* .
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
+ Portions Copyright (C) 2010 SN Systems Ltd. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "dwarf_line.h"
+
+static int
+is_path_separator(Dwarf_Small s)
+{
+ if(s == '/') {
+ return 1;
+ }
+#ifdef HAVE_WINDOWS_PATH
+ if(s == '\\') {
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+/* Return 0 if false, 1 if true.
+ If HAVE_WINDOWS_PATH is defined we
+ attempt to handle windows full paths:
+ \\something or C:cwdpath.c
+*/
+static int
+file_name_is_full_path(Dwarf_Small *fname)
+{
+ Dwarf_Small firstc = *fname;
+ if(is_path_separator(firstc)) {
+ /* Full path. */
+ return 1;
+ }
+ if(!firstc) {
+ return 0;
+ }
+#ifdef HAVE_WINDOWS_PATH
+ if((firstc >= 'A' && firstc <= 'Z') ||
+ (firstc >= 'a' && firstc <= 'z')) {
+
+ Dwarf_Small secondc = fname[1];
+ if (secondc == ':') {
+ return 1;
+ }
+ }
+#endif
+ return 0;
+}
+
+/* Although source files is supposed to return the
+ source files in the compilation-unit, it does
+ not look for any in the statement program. In
+ other words, it ignores those defined using the
+ extended opcode DW_LNE_define_file. */
+int
+dwarf_srcfiles(Dwarf_Die die,
+ char ***srcfiles,
+ Dwarf_Signed * srcfilecount, Dwarf_Error * error)
+{
+ /* This pointer is used to scan the portion of the .debug_line
+ section for the current cu. */
+ Dwarf_Small *line_ptr;
+
+ /* Pointer to a DW_AT_stmt_list attribute in case it exists in the
+ die. */
+ Dwarf_Attribute stmt_list_attr;
+
+ /* Pointer to DW_AT_comp_dir attribute in die. */
+ Dwarf_Attribute comp_dir_attr;
+
+ /* Pointer to name of compilation directory. */
+ Dwarf_Small *comp_dir = 0;
+
+ /* Offset into .debug_line specified by a DW_AT_stmt_list
+ attribute. */
+ Dwarf_Unsigned line_offset = 0;
+
+ /* This points to a block of char *'s, each of which points to a
+ file name. */
+ char **ret_files = 0;
+
+ /* The Dwarf_Debug this die belongs to. */
+ Dwarf_Debug dbg = 0;
+
+ /* Used to chain the file names. */
+ Dwarf_Chain curr_chain = NULL;
+ Dwarf_Chain prev_chain = NULL;
+ Dwarf_Chain head_chain = NULL;
+ Dwarf_Half attrform = 0;
+ int resattr = DW_DLV_ERROR;
+ int lres = DW_DLV_ERROR;
+ struct Line_Table_Prefix_s line_prefix;
+ int i = 0;
+ int res = DW_DLV_ERROR;
+
+ /* ***** BEGIN CODE ***** */
+ /* Reset error. */
+ if (error != NULL) {
+ *error = NULL;
+ }
+
+ CHECK_DIE(die, DW_DLV_ERROR);
+ dbg = die->di_cu_context->cc_dbg;
+
+ resattr = dwarf_attr(die, DW_AT_stmt_list, &stmt_list_attr, error);
+ if (resattr != DW_DLV_OK) {
+ return resattr;
+ }
+
+ if (dbg->de_debug_line.dss_index == 0) {
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_LINE_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ res = _dwarf_load_section(dbg, &dbg->de_debug_line,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ if (!dbg->de_debug_line.dss_size) {
+ return (DW_DLV_NO_ENTRY);
+ }
+
+
+ lres = dwarf_whatform(stmt_list_attr,&attrform,error);
+ if (lres != DW_DLV_OK) {
+ return lres;
+ }
+ if (attrform != DW_FORM_data4 && attrform != DW_FORM_data8 &&
+ attrform != DW_FORM_sec_offset ) {
+ _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
+ return (DW_DLV_ERROR);
+ }
+ lres = dwarf_global_formref(stmt_list_attr, &line_offset, error);
+ if (lres != DW_DLV_OK) {
+ return lres;
+ }
+ if (line_offset >= dbg->de_debug_line.dss_size) {
+ _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
+ return (DW_DLV_ERROR);
+ }
+ line_ptr = dbg->de_debug_line.dss_data + line_offset;
+ dwarf_dealloc(dbg, stmt_list_attr, DW_DLA_ATTR);
+
+ /* If die has DW_AT_comp_dir attribute, get the string that names
+ the compilation directory. */
+ resattr = dwarf_attr(die, DW_AT_comp_dir, &comp_dir_attr, error);
+ if (resattr == DW_DLV_ERROR) {
+ return resattr;
+ }
+ if (resattr == DW_DLV_OK) {
+ int cres = DW_DLV_ERROR;
+ char *cdir = 0;
+
+ cres = dwarf_formstring(comp_dir_attr, &cdir, error);
+ if (cres == DW_DLV_ERROR) {
+ return cres;
+ } else if (cres == DW_DLV_OK) {
+ comp_dir = (Dwarf_Small *) cdir;
+ }
+ }
+ if (resattr == DW_DLV_OK) {
+ dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR);
+ }
+ dwarf_init_line_table_prefix(&line_prefix);
+ {
+ Dwarf_Small *line_ptr_out = 0;
+ int dres = dwarf_read_line_table_prefix(dbg,
+ line_ptr,
+ dbg->de_debug_line.dss_size,
+ &line_ptr_out,
+ &line_prefix,
+ NULL, NULL,error,
+ 0);
+
+ if (dres == DW_DLV_ERROR) {
+ dwarf_free_line_table_prefix(&line_prefix);
+ return dres;
+ }
+ if (dres == DW_DLV_NO_ENTRY) {
+ dwarf_free_line_table_prefix(&line_prefix);
+ return dres;
+ }
+
+ line_ptr = line_ptr_out;
+ }
+
+ for (i = 0; i < line_prefix.pf_files_count; ++i) {
+ struct Line_Table_File_Entry_s *fe =
+ line_prefix.pf_line_table_file_entries + i;
+ char *file_name = (char *) fe->lte_filename;
+ char *dir_name = 0;
+ char *full_name = 0;
+ Dwarf_Unsigned dir_index = fe->lte_directory_index;
+
+ if (dir_index == 0) {
+ dir_name = (char *) comp_dir;
+ } else {
+ dir_name =
+ (char *) line_prefix.pf_include_directories[
+ fe->lte_directory_index - 1];
+ }
+
+ /* dir_name can be NULL if there is no DW_AT_comp_dir.
+ file_name == fe->lte_filename aside from char signedness.
+ */
+ if(dir_name == 0 || file_name_is_full_path(fe->lte_filename)) {
+ /* This is safe because dwarf_dealloc is careful to not
+ dealloc strings which are part of the raw .debug_* data.
+ */
+ full_name = file_name;
+ } else {
+ full_name = (char *) _dwarf_get_alloc(dbg, DW_DLA_STRING,
+ strlen(dir_name) + 1 +
+ strlen(file_name) +
+ 1);
+ if (full_name == NULL) {
+ dwarf_free_line_table_prefix(&line_prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ /* This is not careful to avoid // in the output, Nothing
+ forces a 'canonical' name format here. Unclear if this
+ needs to be fixed. */
+#if defined (HAVE_WINDOWS_PATH)
+ /* Always '/' instead of '\\', this is a Windows -> Unix
+ issue. */
+ {
+ int index = 0;
+ int len = strlen(dir_name);
+ for (index = 0; index < len; ++index) {
+ full_name[index] = dir_name[index];
+ if (full_name[index] == '\\') {
+ full_name[index] = '/';
+ }
+ }
+ }
+#else
+ strcpy(full_name, dir_name);
+#endif /* HAVE_WINDOWS_PATH */
+ strcat(full_name, "/");
+ strcat(full_name, file_name);
+ }
+ curr_chain =
+ (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (curr_chain == NULL) {
+ dwarf_free_line_table_prefix(&line_prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ curr_chain->ch_item = full_name;
+ if (head_chain == NULL)
+ head_chain = prev_chain = curr_chain;
+ else {
+ prev_chain->ch_next = curr_chain;
+ prev_chain = curr_chain;
+ }
+ }
+
+ curr_chain = (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (curr_chain == NULL) {
+ dwarf_free_line_table_prefix(&line_prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ if (line_prefix.pf_files_count == 0) {
+ *srcfiles = NULL;
+ *srcfilecount = 0;
+ dwarf_free_line_table_prefix(&line_prefix);
+ return (DW_DLV_NO_ENTRY);
+ }
+
+ ret_files = (char **)
+ _dwarf_get_alloc(dbg, DW_DLA_LIST, line_prefix.pf_files_count);
+ if (ret_files == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ dwarf_free_line_table_prefix(&line_prefix);
+ return (DW_DLV_ERROR);
+ }
+
+ curr_chain = head_chain;
+ for (i = 0; i < line_prefix.pf_files_count; i++) {
+ *(ret_files + i) = curr_chain->ch_item;
+ prev_chain = curr_chain;
+ curr_chain = curr_chain->ch_next;
+ dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
+ }
+
+ *srcfiles = ret_files;
+ *srcfilecount = line_prefix.pf_files_count;
+ dwarf_free_line_table_prefix(&line_prefix);
+ return (DW_DLV_OK);
+}
+
+/* A function as this code is used twice. */
+static void
+update_file_entry(Dwarf_File_Entry cur_file_entry,
+ Dwarf_File_Entry *file_entries,
+ Dwarf_File_Entry *prev_file_entry,
+ Dwarf_Sword *file_entry_count)
+{
+ if (*file_entries == NULL) {
+ *file_entries = cur_file_entry;
+ } else {
+ (*prev_file_entry)->fi_next = cur_file_entry;
+ }
+ *prev_file_entry = cur_file_entry;
+ (*file_entry_count)++;
+}
+
+static void
+update_chain_list( Dwarf_Chain chain_line,
+ Dwarf_Chain *head_chain, Dwarf_Chain *curr_chain)
+{
+ if (*head_chain == NULL) {
+ *head_chain = chain_line;
+ } else {
+ (*curr_chain)->ch_next = chain_line;
+ }
+ *curr_chain = chain_line;
+}
+
+
+/* Feturn DW_DLV_OK if ok. else DW_DLV_NO_ENTRY or DW_DLV_ERROR */
+int
+_dwarf_internal_srclines(Dwarf_Die die,
+ Dwarf_Line ** linebuf,
+ Dwarf_Signed * count,
+ Dwarf_Bool doaddrs,
+ Dwarf_Bool dolines, Dwarf_Error * error)
+{
+ /* This pointer is used to scan the portion of the .debug_line
+ section for the current cu. */
+ Dwarf_Small *line_ptr = 0;
+
+ /* This points to the last byte of the .debug_line portion for the
+ current cu. */
+ Dwarf_Small *line_ptr_end = 0;
+
+ /* Pointer to a DW_AT_stmt_list attribute in case it exists in the
+ die. */
+ Dwarf_Attribute stmt_list_attr = 0;
+
+ /* Pointer to DW_AT_comp_dir attribute in die. */
+ Dwarf_Attribute comp_dir_attr = 0;
+
+ /* Pointer to name of compilation directory. */
+ Dwarf_Small *comp_dir = NULL;
+
+ /* Offset into .debug_line specified by a DW_AT_stmt_list
+ attribute. */
+ Dwarf_Unsigned line_offset = 0;
+
+ Dwarf_File_Entry file_entries = 0;
+
+ /* These are the state machine state variables. */
+ Dwarf_Addr address = 0;
+ Dwarf_Word file = 1;
+ Dwarf_Word line = 1;
+ Dwarf_Word column = 0;
+
+ /* Phony init. See below for true initialization. */
+ Dwarf_Bool is_stmt = false;
+ /* DWARF4: operation within a VLIW instruction. */
+ Dwarf_Unsigned op_index = 0;
+
+ Dwarf_Bool basic_block = false;
+ Dwarf_Bool prologue_end = false;
+ Dwarf_Bool epilogue_begin = false;
+ Dwarf_Small isa = 0;
+ Dwarf_Unsigned discriminator = 0;
+ Dwarf_Bool end_sequence = false;
+
+ /* These pointers are used to build the list of files names by this
+ cu. cur_file_entry points to the file name being added, and
+ prev_file_entry to the previous one. */
+ Dwarf_File_Entry cur_file_entry = 0;
+ Dwarf_File_Entry prev_file_entry = 0;
+
+ Dwarf_Sword i = 0;
+ Dwarf_Sword file_entry_count = 0;
+
+ /* This is the current opcode read from the statement program. */
+ Dwarf_Small opcode = 0;
+
+ /* Pointer to a Dwarf_Line_Context_s structure that contains the
+ context such as file names and include directories for the set
+ of lines being generated. */
+ Dwarf_Line_Context line_context = 0;
+
+ /* This is a pointer to the current line being added to the line
+ matrix. */
+ Dwarf_Line curr_line = 0;
+
+ /* These variables are used to decode leb128 numbers. Leb128_num
+ holds the decoded number, and leb128_length is its length in
+ bytes. */
+ Dwarf_Word leb128_num = 0;
+ Dwarf_Word leb128_length = 0;
+ Dwarf_Sword advance_line = 0;
+
+ /* This is the operand of the latest fixed_advance_pc extended
+ opcode. */
+ Dwarf_Half fixed_advance_pc = 0;
+
+ /* Counts the number of lines in the line matrix. */
+ Dwarf_Sword line_count = 0;
+
+ /* This is the length of an extended opcode instr. */
+ Dwarf_Word instr_length = 0;
+ Dwarf_Small ext_opcode = 0;
+ struct Line_Table_Prefix_s prefix;
+
+ /* Used to chain together pointers to line table entries that are
+ later used to create a block of Dwarf_Line entries. */
+ Dwarf_Chain chain_line = NULL;
+ Dwarf_Chain head_chain = NULL;
+ Dwarf_Chain curr_chain = NULL;
+
+ /* This points to a block of Dwarf_Lines, a pointer to which is
+ returned in linebuf. */
+ Dwarf_Line *block_line = 0;
+
+ /* The Dwarf_Debug this die belongs to. */
+ Dwarf_Debug dbg = 0;
+ int resattr = DW_DLV_ERROR;
+ int lres = DW_DLV_ERROR;
+ Dwarf_Half address_size = 0;
+
+ int res = DW_DLV_ERROR;
+
+ /* Mark a line record as being DW_LNS_set_address */
+ Dwarf_Bool is_addr_set = false;
+
+ /* ***** BEGIN CODE ***** */
+ if (error != NULL)
+ *error = NULL;
+
+ CHECK_DIE(die, DW_DLV_ERROR);
+ dbg = die->di_cu_context->cc_dbg;
+
+ res = _dwarf_load_section(dbg, &dbg->de_debug_line,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ if (!dbg->de_debug_line.dss_size) {
+ return (DW_DLV_NO_ENTRY);
+ }
+
+ address_size = _dwarf_get_address_size(dbg, die);
+ resattr = dwarf_attr(die, DW_AT_stmt_list, &stmt_list_attr, error);
+ if (resattr != DW_DLV_OK) {
+ return resattr;
+ }
+
+ lres = dwarf_global_formref(stmt_list_attr, &line_offset, error);
+ if (lres != DW_DLV_OK) {
+ return lres;
+ }
+
+ if (line_offset >= dbg->de_debug_line.dss_size) {
+ _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
+ return (DW_DLV_ERROR);
+ }
+ line_ptr = dbg->de_debug_line.dss_data + line_offset;
+ dwarf_dealloc(dbg, stmt_list_attr, DW_DLA_ATTR);
+
+ /* If die has DW_AT_comp_dir attribute, get the string that names
+ the compilation directory. */
+ resattr = dwarf_attr(die, DW_AT_comp_dir, &comp_dir_attr, error);
+ if (resattr == DW_DLV_ERROR) {
+ return resattr;
+ }
+ if (resattr == DW_DLV_OK) {
+ int cres = DW_DLV_ERROR;
+ char *cdir = 0;
+
+ cres = dwarf_formstring(comp_dir_attr, &cdir, error);
+ if (cres == DW_DLV_ERROR) {
+ return cres;
+ } else if (cres == DW_DLV_OK) {
+ comp_dir = (Dwarf_Small *) cdir;
+ }
+ }
+ if (resattr == DW_DLV_OK) {
+ dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR);
+ }
+ dwarf_init_line_table_prefix(&prefix);
+
+ {
+ Dwarf_Small *newlinep = 0;
+ int res = dwarf_read_line_table_prefix(dbg,
+ line_ptr,
+ dbg->de_debug_line.dss_size,
+ &newlinep,
+ &prefix,
+ NULL,NULL,
+ error,
+ 0);
+
+ if (res == DW_DLV_ERROR) {
+ dwarf_free_line_table_prefix(&prefix);
+ return res;
+ }
+ if (res == DW_DLV_NO_ENTRY) {
+ dwarf_free_line_table_prefix(&prefix);
+ return res;
+ }
+ line_ptr_end = prefix.pf_line_ptr_end;
+ line_ptr = newlinep;
+ }
+
+
+ /* Set up context structure for this set of lines. */
+ line_context = (Dwarf_Line_Context)
+ _dwarf_get_alloc(dbg, DW_DLA_LINE_CONTEXT, 1);
+ if (line_context == NULL) {
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ /* Fill out a Dwarf_File_Entry list as we use that to implement the
+ define_file operation. */
+ file_entries = prev_file_entry = NULL;
+ for (i = 0; i < prefix.pf_files_count; ++i) {
+ struct Line_Table_File_Entry_s *pfxfile =
+ prefix.pf_line_table_file_entries + i;
+
+ cur_file_entry = (Dwarf_File_Entry)
+ _dwarf_get_alloc(dbg, DW_DLA_FILE_ENTRY, 1);
+ if (cur_file_entry == NULL) {
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ cur_file_entry->fi_file_name = pfxfile->lte_filename;
+ cur_file_entry->fi_dir_index = pfxfile->lte_directory_index;
+ cur_file_entry->fi_time_last_mod =
+ pfxfile->lte_last_modification_time;
+
+ cur_file_entry->fi_file_length = pfxfile->lte_length_of_file;
+
+ update_file_entry(cur_file_entry,&file_entries,
+ &prev_file_entry,&file_entry_count);
+ }
+
+
+ /* Initialize the one state machine variable that depends on the
+ prefix. */
+ is_stmt = prefix.pf_default_is_stmt;
+
+
+ /* Start of statement program. */
+ while (line_ptr < line_ptr_end) {
+ int type = 0;
+
+ opcode = *(Dwarf_Small *) line_ptr;
+ line_ptr++;
+ /* 'type' is the output */
+ WHAT_IS_OPCODE(type, opcode, prefix.pf_opcode_base,
+ prefix.pf_opcode_length_table, line_ptr,
+ prefix.pf_std_op_count);
+
+ if (type == LOP_DISCARD) {
+ int oc = 0;
+ int opcnt = prefix.pf_opcode_length_table[opcode];
+
+ for (oc = 0; oc < opcnt; oc++) {
+ /* Read and discard operands we don't
+ understand.
+ arbitrary choice of unsigned read.
+ signed read would work as well. */
+ Dwarf_Unsigned utmp2 = 0;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ }
+ } else if (type == LOP_SPECIAL) {
+ /* This op code is a special op in the object, no matter
+ that it might fall into the standard op range in this
+ compile. That is, these are special opcodes between
+ opcode_base and MAX_LINE_OP_CODE. (including
+ opcode_base and MAX_LINE_OP_CODE) */
+ Dwarf_Unsigned operation_advance = 0;
+
+ opcode = opcode - prefix.pf_opcode_base;
+ operation_advance = (opcode / prefix.pf_line_range);
+
+ if (prefix.pf_maximum_ops_per_instruction < 2) {
+ address = address + (operation_advance *
+ prefix.pf_minimum_instruction_length);
+ } else {
+ address = address + (prefix.pf_minimum_instruction_length *
+ ((op_index + operation_advance)/
+ prefix.pf_maximum_ops_per_instruction));
+ op_index = (op_index +operation_advance)%
+ prefix.pf_maximum_ops_per_instruction;
+ }
+
+ line = line + prefix.pf_line_base +
+ opcode % prefix.pf_line_range;
+
+ if (dolines) {
+ curr_line =
+ (Dwarf_Line) _dwarf_get_alloc(dbg, DW_DLA_LINE, 1);
+ if (curr_line == NULL) {
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ /* Mark a line record as being DW_LNS_set_address */
+ curr_line->li_addr_line.li_l_data.li_is_addr_set = is_addr_set;
+ is_addr_set = false;
+
+ curr_line->li_address = address;
+ curr_line->li_addr_line.li_l_data.li_file =
+ (Dwarf_Sword) file;
+ curr_line->li_addr_line.li_l_data.li_line =
+ (Dwarf_Sword) line;
+ curr_line->li_addr_line.li_l_data.li_column =
+ (Dwarf_Half) column;
+ curr_line->li_addr_line.li_l_data.li_is_stmt = is_stmt;
+ curr_line->li_addr_line.li_l_data.li_basic_block =
+ basic_block;
+ curr_line->li_addr_line.li_l_data.li_end_sequence =
+ curr_line->li_addr_line.li_l_data.
+ li_epilogue_begin = epilogue_begin;
+ curr_line->li_addr_line.li_l_data.li_prologue_end =
+ prologue_end;
+ curr_line->li_addr_line.li_l_data.li_isa = isa;
+ curr_line->li_addr_line.li_l_data.li_discriminator = discriminator;
+ curr_line->li_context = line_context;
+ line_count++;
+
+ chain_line = (Dwarf_Chain)
+ _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (chain_line == NULL) {
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ chain_line->ch_item = curr_line;
+ update_chain_list(chain_line,&head_chain,&curr_chain);
+ }
+
+ basic_block = false;
+ prologue_end = false;
+ epilogue_begin = false;
+ discriminator = 0;
+ } else if (type == LOP_STANDARD) {
+ switch (opcode) {
+
+ case DW_LNS_copy:{
+ if (dolines) {
+ curr_line = (Dwarf_Line) _dwarf_get_alloc(dbg,
+ DW_DLA_LINE, 1);
+ if (curr_line == NULL) {
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ /* Mark a line record as being DW_LNS_set_address */
+ curr_line->li_addr_line.li_l_data.li_is_addr_set =
+ is_addr_set;
+ is_addr_set = false;
+
+ curr_line->li_address = address;
+ curr_line->li_addr_line.li_l_data.li_file =
+ (Dwarf_Sword) file;
+ curr_line->li_addr_line.li_l_data.li_line =
+ (Dwarf_Sword) line;
+ curr_line->li_addr_line.li_l_data.li_column =
+ (Dwarf_Half) column;
+ curr_line->li_addr_line.li_l_data.li_is_stmt =
+ is_stmt;
+ curr_line->li_addr_line.li_l_data.
+ li_basic_block = basic_block;
+ curr_line->li_addr_line.li_l_data.
+ li_end_sequence = end_sequence;
+ curr_line->li_context = line_context;
+ curr_line->li_addr_line.li_l_data.
+ li_epilogue_begin = epilogue_begin;
+ curr_line->li_addr_line.li_l_data.
+ li_prologue_end = prologue_end;
+ curr_line->li_addr_line.li_l_data.li_isa = isa;
+ curr_line->li_addr_line.li_l_data.li_discriminator = discriminator;
+ line_count++;
+
+ chain_line = (Dwarf_Chain)
+ _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (chain_line == NULL) {
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ chain_line->ch_item = curr_line;
+ update_chain_list(chain_line,&head_chain,&curr_chain);
+ }
+
+ basic_block = false;
+ prologue_end = false;
+ epilogue_begin = false;
+ discriminator = 0;
+ }
+ break;
+ case DW_LNS_advance_pc:{
+ Dwarf_Unsigned utmp2 = 0;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ leb128_num = (Dwarf_Word) utmp2;
+ address = address +
+ prefix.pf_minimum_instruction_length *
+ leb128_num;
+ }
+ break;
+ case DW_LNS_advance_line:{
+ Dwarf_Signed stmp = 0;
+
+ DECODE_LEB128_SWORD(line_ptr, stmp);
+ advance_line = (Dwarf_Sword) stmp;
+ line = line + advance_line;
+ }
+ break;
+ case DW_LNS_set_file:{
+ Dwarf_Unsigned utmp2 = 0;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ file = (Dwarf_Word) utmp2;
+ }
+ break;
+ case DW_LNS_set_column:{
+ Dwarf_Unsigned utmp2 = 0;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ column = (Dwarf_Word) utmp2;
+ }
+ break;
+ case DW_LNS_negate_stmt:{
+ is_stmt = !is_stmt;
+ }
+ break;
+ case DW_LNS_set_basic_block:{
+ basic_block = true;
+ }
+ break;
+
+ case DW_LNS_const_add_pc:{
+ opcode = MAX_LINE_OP_CODE - prefix.pf_opcode_base;
+ if (prefix.pf_maximum_ops_per_instruction < 2) {
+ Dwarf_Unsigned operation_advance =
+ (opcode / prefix.pf_line_range);
+ address = address +
+ prefix.pf_minimum_instruction_length *
+ operation_advance;
+ } else {
+ Dwarf_Unsigned operation_advance =
+ (opcode / prefix.pf_line_range);
+ address = address + prefix.pf_minimum_instruction_length *
+ ((op_index + operation_advance)/
+ prefix.pf_maximum_ops_per_instruction);
+ op_index = (op_index +operation_advance)%
+ prefix.pf_maximum_ops_per_instruction;
+ }
+ }
+ break;
+ case DW_LNS_fixed_advance_pc:{
+ READ_UNALIGNED(dbg, fixed_advance_pc, Dwarf_Half,
+ line_ptr, sizeof(Dwarf_Half));
+ line_ptr += sizeof(Dwarf_Half);
+ address = address + fixed_advance_pc;
+ op_index = 0;
+ }
+ break;
+
+ /* New in DWARF3 */
+ case DW_LNS_set_prologue_end:{
+ prologue_end = true;
+ }
+ break;
+ /* New in DWARF3 */
+ case DW_LNS_set_epilogue_begin:{
+ epilogue_begin = true;
+ }
+ break;
+
+ /* New in DWARF3 */
+ case DW_LNS_set_isa:{
+ Dwarf_Unsigned utmp2;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ isa = utmp2;
+ if (isa != utmp2) {
+ /* The value of the isa did not fit in our
+ local so we record it wrong. declare an
+ error. */
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_NUM_OPERANDS_BAD);
+ return (DW_DLV_ERROR);
+ }
+ }
+ break;
+ } /* End switch(opcode) */
+
+ } else if (type == LOP_EXTENDED) {
+ Dwarf_Unsigned utmp3 = 0;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp3);
+ instr_length = (Dwarf_Word) utmp3;
+ /* Dwarf_Small is a ubyte and the extended opcode is a
+ ubyte, though not stated as clearly in the 2.0.0 spec as
+ one might hope. */
+ ext_opcode = *(Dwarf_Small *) line_ptr;
+ line_ptr++;
+ switch (ext_opcode) {
+
+ case DW_LNE_end_sequence:{
+ end_sequence = true;
+ if (dolines) {
+ curr_line = (Dwarf_Line)
+ _dwarf_get_alloc(dbg, DW_DLA_LINE, 1);
+ if (curr_line == NULL) {
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ curr_line->li_address = address;
+ curr_line->li_addr_line.li_l_data.li_file =
+ (Dwarf_Sword) file;
+ curr_line->li_addr_line.li_l_data.li_line =
+ (Dwarf_Sword) line;
+ curr_line->li_addr_line.li_l_data.li_column =
+ (Dwarf_Half) column;
+ curr_line->li_addr_line.li_l_data.li_is_stmt =
+ is_stmt;
+ curr_line->li_addr_line.li_l_data.
+ li_basic_block = basic_block;
+ curr_line->li_addr_line.li_l_data.
+ li_end_sequence = end_sequence;
+ curr_line->li_context = line_context;
+ curr_line->li_addr_line.li_l_data.
+ li_epilogue_begin = epilogue_begin;
+ curr_line->li_addr_line.li_l_data.
+ li_prologue_end = prologue_end;
+ curr_line->li_addr_line.li_l_data.li_isa = isa;
+ curr_line->li_addr_line.li_l_data.li_discriminator = discriminator;
+ line_count++;
+ chain_line = (Dwarf_Chain)
+ _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (chain_line == NULL) {
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ chain_line->ch_item = curr_line;
+
+ update_chain_list(chain_line,&head_chain,&curr_chain);
+ }
+
+ address = 0;
+ file = 1;
+ line = 1;
+ column = 0;
+ is_stmt = prefix.pf_default_is_stmt;
+ basic_block = false;
+ end_sequence = false;
+ prologue_end = false;
+ epilogue_begin = false;
+ isa = 0;
+ discriminator = 0;
+ op_index = 0;
+ }
+ break;
+
+ case DW_LNE_set_address:{
+ READ_UNALIGNED(dbg, address, Dwarf_Addr,
+ line_ptr, address_size);
+ /* Mark a line record as being DW_LNS_set_address */
+ is_addr_set = true;
+
+ if (doaddrs) {
+ curr_line = (Dwarf_Line) _dwarf_get_alloc(dbg,
+ DW_DLA_LINE, 1);
+ if (curr_line == NULL) {
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ /* Mark a line record as being DW_LNS_set_address */
+ curr_line->li_addr_line.li_l_data.li_is_addr_set =
+ is_addr_set;
+ is_addr_set = false;
+ curr_line->li_address = address;
+ curr_line->li_addr_line.li_offset =
+ line_ptr - dbg->de_debug_line.dss_data;
+ line_count++;
+ chain_line = (Dwarf_Chain)
+ _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (chain_line == NULL) {
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ chain_line->ch_item = curr_line;
+
+ update_chain_list(chain_line,&head_chain,&curr_chain);
+ }
+ op_index = 0;
+ line_ptr += address_size;
+ }
+ break;
+
+ case DW_LNE_define_file:{
+ if (dolines) {
+ cur_file_entry = (Dwarf_File_Entry)
+ _dwarf_get_alloc(dbg, DW_DLA_FILE_ENTRY, 1);
+ if (cur_file_entry == NULL) {
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ cur_file_entry->fi_file_name = (Dwarf_Small *) line_ptr;
+ line_ptr = line_ptr + strlen((char *) line_ptr) + 1;
+ cur_file_entry->fi_dir_index = (Dwarf_Sword)
+ _dwarf_decode_u_leb128(line_ptr, &leb128_length);
+ line_ptr = line_ptr + leb128_length;
+ cur_file_entry->fi_time_last_mod =
+ _dwarf_decode_u_leb128(line_ptr, &leb128_length);
+ line_ptr = line_ptr + leb128_length;
+ cur_file_entry->fi_file_length =
+ _dwarf_decode_u_leb128(line_ptr, &leb128_length);
+ line_ptr = line_ptr + leb128_length;
+ update_file_entry(cur_file_entry,&file_entries,
+ &prev_file_entry,&file_entry_count);
+ }
+ }
+ break;
+ case DW_LNE_set_discriminator:{
+ /* New in DWARF4 */
+ Dwarf_Unsigned utmp2 = 0;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ discriminator = (Dwarf_Word) utmp2;
+ }
+ break;
+ default:{
+ /* This is an extended op code we do not know about,
+ other than we know now many bytes it is
+ and the op code and the bytes of operand. */
+ Dwarf_Unsigned remaining_bytes = instr_length -1;
+ if(instr_length < 1 || remaining_bytes > DW_LNE_LEN_MAX) {
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_EXT_OPCODE_BAD);
+ return (DW_DLV_ERROR);
+ }
+ line_ptr += remaining_bytes;
+ }
+ break;
+ } /* End switch. */
+ }
+ }
+
+ block_line = (Dwarf_Line *)
+ _dwarf_get_alloc(dbg, DW_DLA_LIST, line_count);
+ if (block_line == NULL) {
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ curr_chain = head_chain;
+ for (i = 0; i < line_count; i++) {
+ *(block_line + i) = curr_chain->ch_item;
+ head_chain = curr_chain;
+ curr_chain = curr_chain->ch_next;
+ dwarf_dealloc(dbg, head_chain, DW_DLA_CHAIN);
+ }
+
+ line_context->lc_file_entries = file_entries;
+ line_context->lc_file_entry_count = file_entry_count;
+ line_context->lc_include_directories_count =
+ prefix.pf_include_directories_count;
+ if (prefix.pf_include_directories_count > 0) {
+ /* This gets a pointer to the *first* include dir. The others
+ follow directly with the standard DWARF2/3 NUL byte
+ following the last. */
+ line_context->lc_include_directories =
+ prefix.pf_include_directories[0];
+ }
+
+ line_context->lc_line_count = line_count;
+ line_context->lc_compilation_directory = comp_dir;
+ line_context->lc_version_number = prefix.pf_version;
+ line_context->lc_dbg = dbg;
+ *count = line_count;
+
+ *linebuf = block_line;
+ dwarf_free_line_table_prefix(&prefix);
+ return (DW_DLV_OK);
+}
+
+int
+dwarf_srclines(Dwarf_Die die,
+ Dwarf_Line ** linebuf,
+ Dwarf_Signed * linecount, Dwarf_Error * error)
+{
+ Dwarf_Signed count = 0;
+ int res = _dwarf_internal_srclines(die, linebuf, &count,
+ /* addrlist= */ false,
+ /* linelist= */ true, error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ *linecount = count;
+ return res;
+}
+
+
+
+/* Every line table entry (except DW_DLE_end_sequence,
+ which is returned using dwarf_lineendsequence())
+ potentially has the begin-statement
+ flag marked 'on'. This returns thru *return_bool,
+ the begin-statement flag. */
+
+int
+dwarf_linebeginstatement(Dwarf_Line line,
+ Dwarf_Bool * return_bool, Dwarf_Error * error)
+{
+ if (line == NULL || return_bool == 0) {
+ _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ *return_bool = (line->li_addr_line.li_l_data.li_is_stmt);
+ return DW_DLV_OK;
+}
+
+/* At the end of any contiguous line-table there may be
+ a DW_LNE_end_sequence operator.
+ This returns non-zero thru *return_bool
+ if and only if this 'line' entry was a DW_LNE_end_sequence.
+
+ Within a compilation unit or function there may be multiple
+ line tables, each ending with a DW_LNE_end_sequence.
+ Each table describes a contiguous region.
+ Because compilers may split function code up in arbitrary ways
+ compilers may need to emit multiple contigous regions (ie
+ line tables) for a single function.
+ See the DWARF3 spec section 6.2. */
+int
+dwarf_lineendsequence(Dwarf_Line line,
+ Dwarf_Bool * return_bool, Dwarf_Error * error)
+{
+ if (line == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ *return_bool = (line->li_addr_line.li_l_data.li_end_sequence);
+ return DW_DLV_OK;
+}
+
+
+/* Each 'line' entry has a line-number.
+ If the entry is a DW_LNE_end_sequence the line-number is
+ meaningless (see dwarf_lineendsequence(), just above). */
+int
+dwarf_lineno(Dwarf_Line line,
+ Dwarf_Unsigned * ret_lineno, Dwarf_Error * error)
+{
+ if (line == NULL || ret_lineno == 0) {
+ _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ *ret_lineno = (line->li_addr_line.li_l_data.li_line);
+ return DW_DLV_OK;
+}
+
+/* Each 'line' entry has a file-number, and index into the file table.
+ If the entry is a DW_LNE_end_sequence the index is
+ meaningless (see dwarf_lineendsequence(), just above).
+ The file number returned is an index into the file table
+ produced by dwarf_srcfiles(), but care is required: the
+ li_file begins with 1 for real files, so that the li_file returned here
+ is 1 greater than its index into the dwarf_srcfiles() output array.
+ And entries from DW_LNE_define_file don't appear in
+ the dwarf_srcfiles() output so file indexes from here may exceed
+ the size of the dwarf_srcfiles() output array size.
+*/
+int
+dwarf_line_srcfileno(Dwarf_Line line,
+ Dwarf_Unsigned * ret_fileno, Dwarf_Error * error)
+{
+ if (line == NULL || ret_fileno == 0) {
+ _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL);
+ return (DW_DLV_ERROR);
+ }
+ /* li_file must be <= line->li_context->lc_file_entry_count else it
+ is trash. li_file 0 means not attributable to any source file
+ per dwarf2/3 spec. */
+
+ *ret_fileno = (line->li_addr_line.li_l_data.li_file);
+ return DW_DLV_OK;
+}
+
+/* Each 'line' entry has an is_addr_set attribute.
+ If the entry is a DW_LNE_set_address, return TRUE through
+ the *is_addr_set pointer. */
+int
+dwarf_line_is_addr_set(Dwarf_Line line,
+ Dwarf_Bool *is_addr_set, Dwarf_Error * error)
+{
+ if (line == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ *is_addr_set = (line->li_addr_line.li_l_data.li_is_addr_set);
+ return DW_DLV_OK;
+}
+
+/* Each 'line' entry has a line-address.
+ If the entry is a DW_LNE_end_sequence the adddress
+ is one-beyond the last address this contigous region
+ covers, so the address is not inside the region,
+ but is just outside it. */
+int
+dwarf_lineaddr(Dwarf_Line line,
+ Dwarf_Addr * ret_lineaddr, Dwarf_Error * error)
+{
+ if (line == NULL || ret_lineaddr == 0) {
+ _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ *ret_lineaddr = (line->li_address);
+ return DW_DLV_OK;
+}
+
+
+/* Obsolete: do not use this function.
+ December 2011: For reasons lost in the mists of history,
+ this returned -1, not zero (through the pointer
+ ret_lineoff), if the column was zero.
+ That was always bogus, even in DWARF2.
+ It is also bogus that the column value is signed, but
+ it is painful to change the argument type in 2011, so leave it.
+ */
+int
+dwarf_lineoff(Dwarf_Line line,
+ Dwarf_Signed * ret_lineoff, Dwarf_Error * error)
+{
+ if (line == NULL || ret_lineoff == 0) {
+ _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL);
+ return (DW_DLV_ERROR);
+ }
+ *ret_lineoff = (
+ (line->li_addr_line.li_l_data.li_column == 0) ?
+ -1 : line->li_addr_line.li_l_data.li_column);
+ return DW_DLV_OK;
+}
+/* Each 'line' entry has a column-within-line (offset
+ within the line) where the
+ source text begins.
+ If the entry is a DW_LNE_end_sequence the line-number is
+ meaningless (see dwarf_lineendsequence(), just above).
+ Lines of text begin at column 1. The value 0
+ means the line begins at the left edge of the line.
+ (See the DWARF3 spec, section 6.2.2).
+ So 0 and 1 mean essentially the same thing.
+ dwarf_lineoff_b() is new in December 2011.
+ */
+int
+dwarf_lineoff_b(Dwarf_Line line,
+ Dwarf_Unsigned * ret_lineoff, Dwarf_Error * error)
+{
+ if (line == NULL || ret_lineoff == 0) {
+ _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ *ret_lineoff = line->li_addr_line.li_l_data.li_column;
+ return DW_DLV_OK;
+}
+
+
+int
+dwarf_linesrc(Dwarf_Line line, char **ret_linesrc, Dwarf_Error * error)
+{
+ Dwarf_Signed i = 0;
+ Dwarf_File_Entry file_entry;
+ Dwarf_Small *name_buffer = 0;
+ Dwarf_Small *include_directories = 0;
+ Dwarf_Small include_direc_full_path = 0;
+ Dwarf_Small file_name_full_path = 0;
+ Dwarf_Debug dbg = 0;
+ unsigned int comp_dir_len = 0;
+
+ if (line == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ if (line->li_context == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_LINE_CONTEXT_NULL);
+ return (DW_DLV_ERROR);
+ }
+ dbg = line->li_context->lc_dbg;
+
+ if (line->li_addr_line.li_l_data.li_file >
+ line->li_context->lc_file_entry_count) {
+ _dwarf_error(dbg, error, DW_DLE_LINE_FILE_NUM_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ if (line->li_addr_line.li_l_data.li_file == 0) {
+ /* No file name known: see dwarf2/3 spec. */
+ _dwarf_error(dbg, error, DW_DLE_NO_FILE_NAME);
+ return (DW_DLV_ERROR);
+ }
+ file_entry = line->li_context->lc_file_entries;
+ /* ASSERT: li_file > 0, dwarf correctness issue, see line table
+ definition of dwarf2/3 spec. */
+ /* Example: if li_file is 2 and lc_file_entry_count is 3,
+ file_entry is file 3 (1 based), aka 2( 0 based) file_entry->next
+ is file 2 (1 based), aka 1( 0 based) file_entry->next->next is
+ file 1 (1 based), aka 0( 0 based) file_entry->next->next->next
+ is NULL.
+
+ and this loop finds the file_entry we need (2 (1 based) in this
+ case). Because lc_file_entries are in reverse order and
+ effectively zero based as a count whereas li_file is 1 based. */
+ for (i = line->li_addr_line.li_l_data.li_file - 1; i > 0; i--) {
+ file_entry = file_entry->fi_next;
+ }
+
+ if (file_entry->fi_file_name == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_NO_FILE_NAME);
+ return (DW_DLV_ERROR);
+ }
+
+ file_name_full_path = file_name_is_full_path(file_entry->fi_file_name);
+ if (file_name_full_path) {
+ *ret_linesrc = ((char *) file_entry->fi_file_name);
+ return DW_DLV_OK;
+ }
+
+ if (file_entry->fi_dir_index == 0) {
+
+ /* dir_index of 0 means that the compilation was in the
+ 'current directory of compilation' */
+ if (line->li_context->lc_compilation_directory == NULL) {
+ /* We don't actually *have* a current directory of
+ compilation: DW_AT_comp_dir was not present Rather than
+ emitting DW_DLE_NO_COMP_DIR lets just make an empty name
+ here. In other words, do the best we can with what we do
+ have instead of reporting an error. _dwarf_error(dbg,
+ error, DW_DLE_NO_COMP_DIR); return(DW_DLV_ERROR); */
+ comp_dir_len = 0;
+ } else {
+ comp_dir_len = strlen((char *)
+ (line->li_context->lc_compilation_directory));
+ }
+
+ name_buffer =
+ _dwarf_get_alloc(line->li_context->lc_dbg, DW_DLA_STRING,
+ comp_dir_len + 1 +
+ strlen((char *) file_entry->fi_file_name) + 1);
+ if (name_buffer == NULL) {
+ _dwarf_error(line->li_context->lc_dbg, error,
+ DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ if (comp_dir_len > 0) {
+ /* If comp_dir_len is 0 we do not want to put a / in front
+ of the fi_file_name as we just don't know anything. */
+ strcpy((char *) name_buffer,
+ (char *) (line->li_context->lc_compilation_directory));
+ strcat((char *) name_buffer, "/");
+ }
+ strcat((char *) name_buffer, (char *) file_entry->fi_file_name);
+ *ret_linesrc = ((char *) name_buffer);
+ return DW_DLV_OK;
+ }
+
+ if (file_entry->fi_dir_index >
+ line->li_context->lc_include_directories_count) {
+ _dwarf_error(dbg, error, DW_DLE_INCL_DIR_NUM_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ include_directories = line->li_context->lc_include_directories;
+ for (i = file_entry->fi_dir_index - 1; i > 0; i--)
+ include_directories += strlen((char *) include_directories) + 1;
+
+ if (line->li_context->lc_compilation_directory) {
+ comp_dir_len = strlen((char *)
+ (line->li_context->lc_compilation_directory));
+ } else {
+ /* No DW_AT_comp_dir present. Do the best we can without it. */
+ comp_dir_len = 0;
+ }
+
+ include_direc_full_path = file_name_is_full_path(include_directories);
+ name_buffer = _dwarf_get_alloc(dbg, DW_DLA_STRING,
+ (include_direc_full_path ? 0 : comp_dir_len + 1) +
+ strlen((char *)include_directories) + 1 +
+ strlen((char *)file_entry->fi_file_name) + 1);
+ if (name_buffer == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ if (!include_direc_full_path) {
+ if (comp_dir_len > 0) {
+ strcpy((char *)name_buffer,
+ (char *)line->li_context->lc_compilation_directory);
+ /* Who provides the / needed after the compilation
+ directory? */
+ if (!is_path_separator(name_buffer[comp_dir_len - 1])) {
+ /* Here we provide the / separator. It
+ should work ok for Windows */
+ /* Overwrite previous nul terminator with needed / */
+ name_buffer[comp_dir_len] = '/';
+ name_buffer[comp_dir_len + 1] = 0;
+ }
+ }
+ } else {
+ strcpy((char *) name_buffer, "");
+ }
+ strcat((char *) name_buffer, (char *) include_directories);
+ strcat((char *) name_buffer, "/");
+ strcat((char *) name_buffer, (char *) file_entry->fi_file_name);
+ *ret_linesrc = ((char *) name_buffer);
+ return DW_DLV_OK;
+}
+
+/* Every line table entry potentially has the basic-block-start
+ flag marked 'on'. This returns thru *return_bool,
+ the basic-block-start flag.
+*/
+int
+dwarf_lineblock(Dwarf_Line line,
+ Dwarf_Bool * return_bool, Dwarf_Error * error)
+{
+ if (line == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL);
+ return (DW_DLV_ERROR);
+ }
+ *return_bool = (line->li_addr_line.li_l_data.li_basic_block);
+ return DW_DLV_OK;
+}
+
+/* We gather these into one call as it's likely one
+ will want all or none of them. */
+int dwarf_prologue_end_etc(Dwarf_Line line,
+ Dwarf_Bool * prologue_end,
+ Dwarf_Bool * epilogue_begin,
+ Dwarf_Unsigned * isa,
+ Dwarf_Unsigned * discriminator,
+ Dwarf_Error * error)
+{
+ if (line == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL);
+ return (DW_DLV_ERROR);
+ }
+ *prologue_end = (line->li_addr_line.li_l_data.li_prologue_end);
+ *epilogue_begin = (line->li_addr_line.li_l_data.li_epilogue_begin);
+ *isa = (line->li_addr_line.li_l_data.li_isa);
+ *discriminator = (line->li_addr_line.li_l_data.li_discriminator);
+ return DW_DLV_OK;
+}
+
+
+
+#if 0 /* Ignore this. This needs major re-work. */
+/* This routine works by looking for exact matches between
+ the current line address and pc, and crossovers from
+ from less than pc value to greater than. At each line
+ that satisfies the above, it records a pointer to the
+ line, and the difference between the address and pc.
+ It then scans these pointers and picks out those with
+ the smallest difference between pc and address.
+*/
+int
+dwarf_pclines(Dwarf_Debug dbg,
+ Dwarf_Addr pc,
+ Dwarf_Line ** linebuf,
+ Dwarf_Signed slide,
+ Dwarf_Signed * linecount, Dwarf_Error * error)
+{
+ /* Scans the line matrix for the current cu to which a pointer
+ exists in dbg. */
+ Dwarf_Line line;
+ Dwarf_Line prev_line;
+
+ /* These flags are for efficiency reasons. Check_line is true
+ initially, but set false when the address of the current line is
+ greater than pc. It is set true only when the address of the
+ current line falls below pc. This assumes that addresses within
+ the same segment increase, and we are only interested in the
+ switch from a less than pc address to a greater than. First_line
+ is set true initially, but set false after the first line is
+ scanned. This is to prevent looking at the address of previous
+ line when slide is DW_DLS_BACKWARD, and the first line is being
+ scanned. */
+ Dwarf_Bool check_line, first_line;
+
+ /* Diff tracks the smallest difference a line address and the input
+ pc value. */
+ Dwarf_Signed diff, i;
+
+ /* For the slide = DW_DLS_BACKWARD case, pc_less is the value of
+ the address of the line immediately preceding the first line
+ that has value greater than pc. For the slide = DW_DLS_FORWARD
+ case, pc_more is the values of address for the first line that
+ is greater than pc. Diff is the difference between either of the
+ these values and pc. */
+ Dwarf_Addr pc_less, pc_more;
+
+ /* Pc_line_buf points to a chain of pointers to lines of which
+ those with a diff equal to the smallest difference will be
+ returned. */
+ Dwarf_Line *pc_line_buf, *pc_line;
+
+ /* Chain_count counts the number of lines in the above chain for
+ which the diff is equal to the smallest difference This is the
+ number returned by this routine. */
+ Dwarf_Signed chain_count;
+
+ chain_head = NULL;
+
+ check_line = true;
+ first_line = true;
+ diff = MAX_LINE_DIFF;
+
+ for (i = 0; i < dbg->de_cu_line_count; i++) {
+
+ line = *(dbg->de_cu_line_ptr + i);
+ prev_line = first_line ? NULL : *(dbg->de_cu_line_ptr + i - 1);
+
+ if (line->li_address == pc) {
+ chain_ptr = (struct chain *)
+ _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (chain_ptr == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ chain_ptr->line = line;
+ chain_ptr->diff = diff = 0;
+ chain_ptr->next = chain_head;
+ chain_head = chain_ptr;
+ } else {
+ /* Look for crossover from less than pc address to greater
+ than. */
+ if (check_line && line->li_address > pc &&
+ (first_line ? 0 : prev_line->li_address) < pc) {
+ if (slide == DW_DLS_BACKWARD && !first_line) {
+ pc_less = prev_line->li_address;
+ if (pc - pc_less <= diff) {
+ chain_ptr = (struct chain *)
+ _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (chain_ptr == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ chain_ptr->line = prev_line;
+ chain_ptr->diff = diff = pc - pc_less;
+ chain_ptr->next = chain_head;
+ chain_head = chain_ptr;
+ }
+ check_line = false;
+ } else if (slide == DW_DLS_FORWARD) {
+ pc_more = line->li_address;
+ if (pc_more - pc <= diff) {
+ chain_ptr = (struct chain *)
+ _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (chain_ptr == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ chain_ptr->line = line;
+ chain_ptr->diff = diff = pc_more - pc;
+ chain_ptr->next = chain_head;
+ chain_head = chain_ptr;
+ }
+ check_line = false;
+ } else {
+ /* Check addresses only when they go */
+ /* below pc. */
+ if (line->li_address < pc) {
+ check_line = true;
+ }
+ }
+ }
+ }
+ first_line = false;
+ }
+ chain_count = 0;
+ for (chain_ptr = chain_head; chain_ptr != NULL;
+ chain_ptr = chain_ptr->next) {
+ if (chain_ptr->diff == diff) {
+ chain_count++;
+ }
+ }
+ pc_line_buf = pc_line = (Dwarf_Line)
+ _dwarf_get_alloc(dbg, DW_DLA_LIST, chain_count);
+ for (chain_ptr = chain_head; chain_ptr != NULL;
+ chain_ptr = chain_ptr->next) {
+ if (chain_ptr->diff == diff) {
+ *pc_line = chain_ptr->line;
+ pc_line++;
+ }
+ }
+ for (chain_ptr = chain_head; chain_ptr != NULL;) {
+ chain_head = chain_ptr;
+ chain_ptr = chain_ptr->next;
+ dwarf_dealloc(dbg, chain_head, DW_DLA_CHAIN);
+ }
+ *linebuf = pc_line_buf;
+ return (chain_count);
+}
+#endif
+
+
+
+/*
+ It's impossible for callers of dwarf_srclines() to get to and
+ free all the resources (in particular, the li_context and its
+ lc_file_entries).
+ So this function, new July 2005, does it.
+*/
+
+void
+dwarf_srclines_dealloc(Dwarf_Debug dbg, Dwarf_Line * linebuf,
+ Dwarf_Signed count)
+{
+
+ Dwarf_Signed i = 0;
+ struct Dwarf_Line_Context_s *context = 0;
+
+ if (count > 0) {
+ /* All these entries share a single context */
+ context = linebuf[0]->li_context;
+ }
+ for (i = 0; i < count; ++i) {
+ dwarf_dealloc(dbg, linebuf[i], DW_DLA_LINE);
+ }
+ dwarf_dealloc(dbg, linebuf, DW_DLA_LIST);
+
+ if (context) {
+ Dwarf_File_Entry fe = context->lc_file_entries;
+
+ while (fe) {
+ Dwarf_File_Entry fenext = fe->fi_next;
+
+ dwarf_dealloc(dbg, fe, DW_DLA_FILE_ENTRY);
+ fe = fenext;
+ }
+ dwarf_dealloc(dbg, context, DW_DLA_LINE_CONTEXT);
+ }
+
+ return;
+}
+
+/* Operand counts per standard operand.
+ The initial zero is for DW_LNS_copy.
+ This is an economical way to verify we understand the table
+ of standard-opcode-lengths in the line table prologue. */
+#define STANDARD_OPERAND_COUNT_DWARF2 9
+#define STANDARD_OPERAND_COUNT_DWARF3 12
+static unsigned char
+dwarf_standard_opcode_operand_count[STANDARD_OPERAND_COUNT_DWARF3] = {
+ /* DWARF2 */
+ 0,
+ 1, 1, 1, 1,
+ 0, 0, 0,
+ 1,
+ /* Following are new for DWARF3. */
+ 0, 0, 1
+};
+
+/* We have a normal standard opcode base, but
+ an arm compiler emitted a non-standard table!
+ This could lead to problems...
+ ARM C/C++ Compiler, RVCT4.0 [Build 4
+ 00] seems to get the table wrong . */
+static unsigned char
+dwarf_arm_standard_opcode_operand_count[STANDARD_OPERAND_COUNT_DWARF3] = {
+ /* DWARF2 */
+ 0,
+ 1, 1, 1, 1,
+ 0, 0, 0,
+ 0, /* <<< --- this is wrong */
+ /* Following are new for DWARF3. */
+ 0, 0, 1
+};
+
+/* There is an error, so count it. If we are printing
+ errors by command line option, print the details. */
+static void
+print_header_issue(Dwarf_Debug dbg,
+ char *specific_msg,
+ Dwarf_Small *data_start,
+ int *err_count_out)
+{
+ if(!err_count_out) {
+ return;
+ }
+ /* Are we in verbose mode */
+ if (dwarf_cmdline_options.check_verbose_mode) {
+ /* When redirecting stderr into stdout or vice versa,
+ ensure lines come out at the 'right time' with fflush. */
+ fflush(stderr);
+ fflush(stdout);
+ printf("\n*** DWARF CHECK: "
+ ".debug_line: %s", specific_msg);
+ if( data_start >= dbg->de_debug_line.dss_data &&
+ (data_start < (dbg->de_debug_line.dss_data +
+ dbg->de_debug_line.dss_size))) {
+ Dwarf_Unsigned off = data_start - dbg->de_debug_line.dss_data;
+ printf(" at offset 0x%" DW_PR_XZEROS DW_PR_DUx
+ " ( %" DW_PR_DUu " ) ",
+ off,off);
+ } else {
+ printf(" (unknown section location) ");
+ }
+ printf("***\n");
+ fflush(stdout);
+ }
+ *err_count_out += 1;
+}
+
+
+
+/* Common line table prefix reading code.
+ Returns DW_DLV_OK, DW_DLV_ERROR.
+ DW_DLV_NO_ENTRY cannot be returned, but callers should
+ assume it is possible.
+
+ The prefix_out area must be initialized properly before calling this.
+
+ Has the side effect of allocating arrays which
+ must be freed (see the Line_Table_Prefix_s struct which
+ holds the pointers to space we allocate here).
+
+ bogus_bytes_ptr and bogus_bytes are output values which
+ let a print-program notify the user of some surprising bytes
+ after a line table header and before the line table instructions.
+ These can be ignored unless one is printing.
+ And are ignored if NULL passed as the pointer.
+*/
+
+/* err_count_out may be NULL, in which case we
+ make no attempt to count checking-type errors.
+ Checking-type errors do not stop us, we just report them.
+*/
+int
+dwarf_read_line_table_prefix(Dwarf_Debug dbg,
+ Dwarf_Small * data_start,
+ Dwarf_Unsigned data_length,
+ Dwarf_Small ** updated_data_start_out,
+ struct Line_Table_Prefix_s *prefix_out,
+ Dwarf_Small ** bogus_bytes_ptr,
+ Dwarf_Unsigned *bogus_bytes,
+ Dwarf_Error * err,
+ int *err_count_out)
+{
+ Dwarf_Small *line_ptr = data_start;
+ Dwarf_Unsigned total_length = 0;
+ int local_length_size = 0;
+ int local_extension_size = 0;
+ Dwarf_Unsigned prologue_length = 0;
+ Dwarf_Half version = 0;
+ Dwarf_Unsigned directories_count = 0;
+ Dwarf_Unsigned directories_malloc = 0;
+ Dwarf_Unsigned files_count = 0;
+ Dwarf_Unsigned files_malloc = 0;
+ Dwarf_Small *line_ptr_end = 0;
+ Dwarf_Small *lp_begin = 0;
+ if(bogus_bytes_ptr) *bogus_bytes_ptr = 0;
+ if(bogus_bytes) *bogus_bytes= 0;
+
+ prefix_out->pf_line_ptr_start = line_ptr;
+ /* READ_AREA_LENGTH updates line_ptr for consumed bytes */
+ READ_AREA_LENGTH(dbg, total_length, Dwarf_Unsigned,
+ line_ptr, local_length_size, local_extension_size);
+
+
+ line_ptr_end = line_ptr + total_length;
+ prefix_out->pf_line_ptr_end = line_ptr_end;
+ prefix_out->pf_length_field_length = local_length_size +
+ local_extension_size;
+ /* ASSERT: prefix_out->pf_length_field_length == line_ptr
+ -prefix_out->pf_line_ptr_start; */
+ if (line_ptr_end > dbg->de_debug_line.dss_data +
+ dbg->de_debug_line.dss_size) {
+ _dwarf_error(dbg, err, DW_DLE_DEBUG_LINE_LENGTH_BAD);
+ return (DW_DLV_ERROR);
+ }
+ if (line_ptr_end > data_start + data_length) {
+ _dwarf_error(dbg, err, DW_DLE_DEBUG_LINE_LENGTH_BAD);
+ return (DW_DLV_ERROR);
+ }
+ prefix_out->pf_total_length = total_length;
+
+ READ_UNALIGNED(dbg, version, Dwarf_Half,
+ line_ptr, sizeof(Dwarf_Half));
+ prefix_out->pf_version = version;
+ line_ptr += sizeof(Dwarf_Half);
+ if (version != CURRENT_VERSION_STAMP &&
+ version != CURRENT_VERSION_STAMP3 &&
+ version != CURRENT_VERSION_STAMP4) {
+ _dwarf_error(dbg, err, DW_DLE_VERSION_STAMP_ERROR);
+ return (DW_DLV_ERROR);
+ }
+
+ READ_UNALIGNED(dbg, prologue_length, Dwarf_Unsigned,
+ line_ptr, local_length_size);
+ prefix_out->pf_prologue_length = prologue_length;
+ line_ptr += local_length_size;
+ prefix_out->pf_line_prologue_start = line_ptr;
+
+ prefix_out->pf_minimum_instruction_length =
+ *(unsigned char *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+
+ prefix_out->pf_default_is_stmt = *(unsigned char *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+
+ if(version == CURRENT_VERSION_STAMP4) {
+ prefix_out->pf_maximum_ops_per_instruction =
+ *(unsigned char *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+ }
+
+ prefix_out->pf_line_base = *(signed char *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Sbyte);
+
+ prefix_out->pf_line_range = *(unsigned char *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+
+ prefix_out->pf_opcode_base = *(unsigned char *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+
+ /* Set up the array of standard opcode lengths. */
+ /* We think this works ok even for cross-endian processing of
+ objects. It might be wrong, we might need to specially process
+ the array of ubyte into host order. */
+ prefix_out->pf_opcode_length_table = line_ptr;
+
+ /* pf_opcode_base is one greater than the size of the array. */
+ line_ptr += prefix_out->pf_opcode_base - 1;
+
+ {
+ /* Determine (as best we can) whether the
+ pf_opcode_length_table holds 9 or 12 standard-conforming
+ entries. gcc4 upped to DWARF3's 12 without updating the
+ version number. */
+ int operand_ck_fail = true;
+
+ if (prefix_out->pf_opcode_base >= STANDARD_OPERAND_COUNT_DWARF3) {
+ int mismatch = memcmp(dwarf_standard_opcode_operand_count,
+ prefix_out->pf_opcode_length_table,
+ STANDARD_OPERAND_COUNT_DWARF3);
+ if(mismatch) {
+ if(err_count_out) {
+ print_header_issue(dbg,
+ "standard-operands did not match",
+ data_start,err_count_out);
+ }
+ mismatch = memcmp(dwarf_arm_standard_opcode_operand_count,
+ prefix_out->pf_opcode_length_table,
+ STANDARD_OPERAND_COUNT_DWARF3);
+ if(!mismatch && err_count_out) {
+ print_header_issue(dbg,
+ "arm (incorrect) operands in use",
+ data_start,err_count_out);
+ }
+ }
+ if (!mismatch) {
+ if (version == 2) {
+ if(err_count_out) {
+ print_header_issue(dbg,
+ "standard DWARF3 operands matched, but is DWARF2 linetable",
+ data_start,err_count_out);
+ }
+ }
+ operand_ck_fail = false;
+ prefix_out->pf_std_op_count =
+ STANDARD_OPERAND_COUNT_DWARF3;
+ }
+ }
+ if (operand_ck_fail) {
+ if (prefix_out->pf_opcode_base >=
+ STANDARD_OPERAND_COUNT_DWARF2) {
+ int mismatch = memcmp(dwarf_standard_opcode_operand_count,
+ prefix_out->pf_opcode_length_table,
+ STANDARD_OPERAND_COUNT_DWARF2);
+
+ if(mismatch) {
+ if(err_count_out) {
+ print_header_issue(dbg,
+ "standard-operands-lengths did not match",
+ data_start,err_count_out);
+ }
+ mismatch = memcmp(dwarf_arm_standard_opcode_operand_count,
+ prefix_out->pf_opcode_length_table,
+ STANDARD_OPERAND_COUNT_DWARF2);
+ if(!mismatch && err_count_out) {
+ print_header_issue(dbg,
+ "arm (incorrect) operand in use",
+ data_start,err_count_out);
+ }
+ }
+
+ if (!mismatch) {
+ operand_ck_fail = false;
+ prefix_out->pf_std_op_count =
+ STANDARD_OPERAND_COUNT_DWARF2;
+ }
+ }
+ }
+ if (operand_ck_fail) {
+ /* Here we are not sure what the pf_std_op_count is. */
+ _dwarf_error(dbg, err, DW_DLE_LINE_NUM_OPERANDS_BAD);
+ return (DW_DLV_ERROR);
+ }
+ }
+ /* At this point we no longer need to check operand counts. */
+
+
+ directories_count = 0;
+ directories_malloc = 5;
+ prefix_out->pf_include_directories = malloc(sizeof(Dwarf_Small *) *
+ directories_malloc);
+ if (prefix_out->pf_include_directories == NULL) {
+ _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ memset(prefix_out->pf_include_directories, 0,
+ sizeof(Dwarf_Small *) * directories_malloc);
+
+ if (line_ptr >= line_ptr_end) {
+ _dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR);
+ return (DW_DLV_ERROR);
+ }
+ while ((*(char *) line_ptr) != '\0') {
+ if (directories_count >= directories_malloc) {
+ Dwarf_Unsigned expand = 2 * directories_malloc;
+ Dwarf_Unsigned bytesalloc = sizeof(Dwarf_Small *) * expand;
+ Dwarf_Small **newdirs =
+ realloc(prefix_out->pf_include_directories,
+ bytesalloc);
+
+ if (!newdirs) {
+ _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ /* Doubled size, zero out second half. */
+ memset(newdirs + directories_malloc, 0,
+ sizeof(Dwarf_Small *) * directories_malloc);
+ directories_malloc = expand;
+ prefix_out->pf_include_directories = newdirs;
+ }
+ prefix_out->pf_include_directories[directories_count] =
+ line_ptr;
+ line_ptr = line_ptr + strlen((char *) line_ptr) + 1;
+ directories_count++;
+ if (line_ptr >= line_ptr_end) {
+ _dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR);
+ return (DW_DLV_ERROR);
+ }
+ }
+ prefix_out->pf_include_directories_count = directories_count;
+ line_ptr++;
+
+ files_count = 0;
+ files_malloc = 5;
+ prefix_out->pf_line_table_file_entries =
+ malloc(sizeof(struct Line_Table_File_Entry_s) * files_malloc);
+ if (prefix_out->pf_line_table_file_entries == NULL) {
+ _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ memset(prefix_out->pf_line_table_file_entries, 0,
+ sizeof(struct Line_Table_File_Entry_s) * files_malloc);
+
+ if (line_ptr >= line_ptr_end) {
+ _dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR);
+ return (DW_DLV_ERROR);
+ }
+ while (*(char *) line_ptr != '\0') {
+ Dwarf_Unsigned utmp;
+ Dwarf_Unsigned dir_index = 0;
+ Dwarf_Unsigned lastmod = 0;
+ Dwarf_Unsigned file_length = 0;
+ struct Line_Table_File_Entry_s *curline;
+ Dwarf_Word leb128_length = 0;
+
+
+ if (files_count >= files_malloc) {
+ Dwarf_Unsigned expand = 2 * files_malloc;
+ struct Line_Table_File_Entry_s *newfiles =
+ realloc(prefix_out->pf_line_table_file_entries,
+ sizeof(struct Line_Table_File_Entry_s) *
+ expand);
+ if (!newfiles) {
+ _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ memset(newfiles + files_malloc, 0,
+ sizeof(struct Line_Table_File_Entry_s) *
+ files_malloc);
+ files_malloc = expand;
+ prefix_out->pf_line_table_file_entries = newfiles;
+ }
+ curline = prefix_out->pf_line_table_file_entries + files_count;
+
+ curline->lte_filename = line_ptr;
+ line_ptr = line_ptr + strlen((char *) line_ptr) + 1;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp);
+ dir_index = (Dwarf_Sword) utmp;
+ if (dir_index > directories_count) {
+ _dwarf_error(dbg, err, DW_DLE_DIR_INDEX_BAD);
+ return (DW_DLV_ERROR);
+ }
+ curline->lte_directory_index = dir_index;
+
+ lastmod = _dwarf_decode_u_leb128(line_ptr, &leb128_length);
+ line_ptr = line_ptr + leb128_length;
+ curline->lte_last_modification_time = lastmod;
+
+ /* Skip over file length. */
+ file_length = _dwarf_decode_u_leb128(line_ptr, &leb128_length);
+ line_ptr = line_ptr + leb128_length;
+ curline->lte_length_of_file = file_length;
+
+ ++files_count;
+ if (line_ptr >= line_ptr_end) {
+ _dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR);
+ return (DW_DLV_ERROR);
+ }
+
+ }
+ prefix_out->pf_files_count = files_count;
+ /* Skip trailing nul byte */
+ ++line_ptr;
+
+
+ lp_begin = prefix_out->pf_line_prologue_start +
+ prefix_out->pf_prologue_length;
+ if (line_ptr != lp_begin) {
+ if(line_ptr > lp_begin) {
+ _dwarf_error(dbg, err, DW_DLE_LINE_PROLOG_LENGTH_BAD);
+ return (DW_DLV_ERROR);
+ } else {
+ /* Bug in compiler. These
+ bytes are really part of the instruction
+ stream. The prefix_out->pf_prologue_length is
+ wrong (12 too high). */
+ if(bogus_bytes_ptr) {
+ *bogus_bytes_ptr = line_ptr;
+ }
+ if(bogus_bytes) {
+ /* How far off things are. We expect the
+ value 12 ! */
+ *bogus_bytes = (lp_begin - line_ptr);
+ }
+ }
+ /* Ignore the lp_begin calc. Assume line_ptr right.
+ Making up for compiler bug. */
+ lp_begin = line_ptr;
+
+ }
+
+ *updated_data_start_out = lp_begin;
+ return DW_DLV_OK;
+}
+
+
+/* Initialize the Line_Table_Prefix_s struct.
+ memset is not guaranteed a portable initializer, but works
+ fine for current architectures. AFAIK.
+*/
+void
+dwarf_init_line_table_prefix(struct Line_Table_Prefix_s *pf)
+{
+ memset(pf, 0, sizeof(*pf));
+}
+
+/* Free any malloc'd area. of the Line_Table_Prefix_s struct. */
+void
+dwarf_free_line_table_prefix(struct Line_Table_Prefix_s *pf)
+{
+ if (pf->pf_include_directories) {
+ free(pf->pf_include_directories);
+ pf->pf_include_directories = 0;
+ }
+ if (pf->pf_line_table_file_entries) {
+ free(pf->pf_line_table_file_entries);
+ pf->pf_line_table_file_entries = 0;
+ }
+ return;
+}
diff --git a/libdwarf/dwarf_line.h b/libdwarf/dwarf_line.h
new file mode 100644
index 0000000..7bbcd5b
--- /dev/null
+++ b/libdwarf/dwarf_line.h
@@ -0,0 +1,326 @@
+/*
+
+ Copyright (C) 2000, 2004, 2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved.
+ Portions Copyright (C) 2010 SN Systems Ltd. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#define DW_EXTENDED_OPCODE 0
+
+/*
+ This is used as the starting value for an algorithm
+ to get the minimum difference between 2 values.
+ UINT_MAX is used as our approximation to infinity.
+*/
+#define MAX_LINE_DIFF UINT_MAX
+
+/* This is for a sanity check on line
+ table extended opcodes.
+ It is entirely arbitrary, and 100 is surely too small if
+ someone was inserting strings in the opcode. */
+#define DW_LNE_LEN_MAX 100
+
+
+/*
+ This structure is used to build a list of all the
+ files that are used in the current compilation unit.
+ All of the fields execpt fi_next have meanings that
+ are obvious from section 6.2.4 of the Libdwarf Doc.
+*/
+struct Dwarf_File_Entry_s {
+ /* Points to string naming the file. */
+ Dwarf_Small *fi_file_name;
+
+ /* Index into the list of directories of the directory in which
+ this file exits. */
+ Dwarf_Sword fi_dir_index;
+
+ /* Time of last modification of the file. */
+ Dwarf_Unsigned fi_time_last_mod;
+
+ /* Length in bytes of the file. */
+ Dwarf_Unsigned fi_file_length;
+
+ /* Pointer for chaining file entries. */
+ Dwarf_File_Entry fi_next;
+};
+
+
+typedef struct Dwarf_Line_Context_s *Dwarf_Line_Context;
+
+/*
+ This structure provides the context in which the fields of
+ a Dwarf_Line structure are interpreted. They come from the
+ statement program prologue. **Updated by dwarf_srclines in
+ dwarf_line.c.
+*/
+struct Dwarf_Line_Context_s {
+ /* Points to a chain of entries providing info about source files
+ for the current set of Dwarf_Line structures. File number
+ 'li_file 1' is last on the list, the first list entry is the
+ file numbered lc_file_entry_count. The numbering of the file
+ names matches the dwarf2/3 line table specification file table
+ and DW_LNE_define_file numbering rules. */
+ Dwarf_File_Entry lc_file_entries;
+ /* Count of number of source files for this set of Dwarf_Line
+ structures. */
+ Dwarf_Sword lc_file_entry_count;
+ /* Points to the portion of .debug_line section that contains a
+ list of strings naming the included directories. */
+ Dwarf_Small *lc_include_directories;
+
+ /* Count of the number of included directories. */
+ Dwarf_Sword lc_include_directories_count;
+
+ /* Count of the number of lines for this cu. */
+ Dwarf_Sword lc_line_count;
+
+ /* Points to name of compilation directory. */
+ Dwarf_Small *lc_compilation_directory;
+
+ Dwarf_Debug lc_dbg;
+
+ Dwarf_Half lc_version_number; /* DWARF2/3 version number, 2
+ for DWARF2, 3 for DWARF3. */
+};
+
+
+/*
+ This structure defines a row of the line table.
+ All of the fields except li_offset have the exact
+ same meaning that is defined in Section 6.2.2
+ of the Libdwarf Document.
+
+ li_offset is used by _dwarf_addr_finder() which is called
+ by rqs(1), an sgi utility for 'moving' shared libraries
+ as if the static linker (ld) had linked the shared library
+ at the newly-specified address. Most libdwarf-using
+ apps will ignore li_offset and _dwarf_addr_finder().
+
+*/
+struct Dwarf_Line_s {
+ Dwarf_Addr li_address; /* pc value of machine instr */
+ union addr_or_line_s {
+ struct li_inner_s {
+ Dwarf_Unsigned li_discriminator; /* New as of DWARF4 */
+ Dwarf_Sword li_file; /* int identifying src file */
+ /* li_file is a number 1-N, indexing into a conceptual
+ source file table as described in dwarf2/3 spec line
+ table doc. (see Dwarf_File_Entry lc_file_entries; and
+ Dwarf_Sword lc_file_entry_count;) */
+ Dwarf_Sword li_line; /* source file line number. */
+ Dwarf_Half li_column; /* source file column number */
+ Dwarf_Small li_isa; /* New as of DWARF4. */
+
+ /* To save space, use bit flags. */
+ /* indicate start of stmt */
+ unsigned char li_is_stmt:1;
+
+ /* indicate start basic block */
+ unsigned char li_basic_block:1;
+
+ /* first post sequence instr */
+ unsigned char li_end_sequence:1;
+
+ unsigned char li_prologue_end:1;
+ unsigned char li_epilogue_begin:1;
+
+ /* Mark a line record as being DW_LNS_set_address. */
+ unsigned char li_is_addr_set:1;
+ } li_l_data;
+ Dwarf_Off li_offset; /* for rqs */
+ } li_addr_line;
+ Dwarf_Line_Context li_context; /* assoc Dwarf_Line_Context_s */
+};
+
+
+int _dwarf_line_address_offsets(Dwarf_Debug dbg,
+ Dwarf_Die die,
+ Dwarf_Addr ** addrs,
+ Dwarf_Off ** offs,
+ Dwarf_Unsigned * returncount,
+ Dwarf_Error * err);
+int _dwarf_internal_srclines(Dwarf_Die die,
+ Dwarf_Line ** linebuf,
+ Dwarf_Signed * count,
+ Dwarf_Bool doaddrs,
+ Dwarf_Bool dolines, Dwarf_Error * error);
+
+
+
+/* The LOP, WHAT_IS_OPCODE stuff is here so it can
+ be reused in 3 places. Seemed hard to keep
+ the 3 places the same without an inline func or
+ a macro.
+
+ Handling the line section where the header and the
+ file being processed do not match (unusual, but
+ planned for in the design of .debug_line)
+ is too tricky to recode this several times and keep
+ it right.
+
+ As it is the code starting up line-reading is duplicated
+ and that is just wrong to do. FIXME!
+*/
+#define LOP_EXTENDED 1
+#define LOP_DISCARD 2
+#define LOP_STANDARD 3
+#define LOP_SPECIAL 4
+
+#define WHAT_IS_OPCODE(type,opcode,base,opcode_length,line_ptr,highest_std) \
+ if( (opcode) < (base) ) { \
+ /* we know we must treat as a standard op \
+ or a special case. */ \
+ if((opcode) == DW_EXTENDED_OPCODE) { \
+ type = LOP_EXTENDED; \
+ } else if( ((highest_std)+1) >= (base)) { \
+ /* == Standard case: compile of \
+ dwarf_line.c and object \
+ have same standard op codes set. \
+ == Special case: compile of dwarf_line.c \
+ has things in standard op codes list \
+ in dwarf.h header not \
+ in the object: handle this as a standard \
+ op code in switch below. \
+ The header special ops overlap the \
+ object standard ops. \
+ The new standard op codes will not \
+ appear in the object. */ \
+ type = LOP_STANDARD; \
+ } else { \
+ /* These are standard opcodes in the object \
+ ** that were not defined in the header \
+ ** at the time dwarf_line.c \
+ ** was compiled. Provides the ability of \
+ ** out-of-date dwarf reader to read newer \
+ ** line table data transparently. \
+ */ \
+ type = LOP_DISCARD; \
+ } \
+ } else { \
+ /* Is a special op code. */ \
+ type = LOP_SPECIAL; \
+ }
+
+/* The following is from the dwarf definition of 'ubyte'
+ and is specifically mentioned in section 6.2.5.1, page 54
+ of the Rev 2.0.0 dwarf specification.
+*/
+
+#define MAX_LINE_OP_CODE 255
+
+
+/* The following structs (Line_Table_File_Entry_s,Line_Table_Prefix_s)
+ and functions allow refactoring common code into a single
+ reader routine.
+*/
+/* There can be zero of more of these needed for 1 line prologue. */
+struct Line_Table_File_Entry_s {
+ Dwarf_Small *lte_filename;
+ Dwarf_Unsigned lte_directory_index;
+ Dwarf_Unsigned lte_last_modification_time;
+ Dwarf_Unsigned lte_length_of_file;
+};
+
+/* Data picked up from the line table prologue for a single
+CU. */
+struct Line_Table_Prefix_s {
+
+ /* pf_total_length is the value of the length field for the line
+ table of this CU. So it does not count the length of itself (the
+ length value) for consistency with the say lenghts recorded in
+ DWARF2/3. */
+ Dwarf_Unsigned pf_total_length;
+
+ /* Length of the initial length field itself. */
+ Dwarf_Half pf_length_field_length;
+
+ /* The version is 2 for DWARF2, 3 for DWARF3 */
+ Dwarf_Half pf_version;
+
+ Dwarf_Unsigned pf_prologue_length;
+ Dwarf_Small pf_minimum_instruction_length;
+
+ /* Start and end of this CU line area. pf_line_ptr_start +
+ pf_total_length + pf_length_field_length == pf_line_ptr_end.
+ Meaning pf_line_ptr_start is before the length info. */
+ Dwarf_Small *pf_line_ptr_start;
+ Dwarf_Small *pf_line_ptr_end;
+
+ /* Used to check that decoding of the line prologue is done right. */
+ Dwarf_Small *pf_line_prologue_start;
+
+ Dwarf_Small pf_default_is_stmt;
+ Dwarf_Ubyte pf_maximum_ops_per_instruction;
+ Dwarf_Sbyte pf_line_base;
+ Dwarf_Small pf_line_range;
+
+ /* Highest std opcode (+1). */
+ Dwarf_Small pf_opcode_base;
+ /* pf_opcode_base -1 entries (each a count, normally the value of
+ each entry is 0 or 1). */
+ Dwarf_Small *pf_opcode_length_table;
+
+ Dwarf_Unsigned pf_include_directories_count;
+ /* Array of pointers to dir strings. pf_include_directories_count
+ entriesin the array. */
+ Dwarf_Small **pf_include_directories;
+
+ /* Count of entries in line_table_file_entries array. */
+ Dwarf_Unsigned pf_files_count;
+ struct Line_Table_File_Entry_s *pf_line_table_file_entries;
+
+ /* The number to treat as standard ops. This is a special
+ accomodation of gcc using the new standard opcodes but not
+ updating the version number. It's legal dwarf2, but much better
+ for the user to understand as dwarf3 when 'it looks ok'. */
+ Dwarf_Bool pf_std_op_count;
+
+};
+
+void dwarf_init_line_table_prefix(struct Line_Table_Prefix_s *pf);
+void dwarf_free_line_table_prefix(struct Line_Table_Prefix_s *pf);
+
+int dwarf_read_line_table_prefix(Dwarf_Debug dbg,
+ Dwarf_Small * data_start,
+ Dwarf_Unsigned data_length,
+ Dwarf_Small ** updated_data_start_out,
+ struct Line_Table_Prefix_s *prefix_out,
+ /* The following 2 arguments are solely for warning users
+ when there is a surprising 'gap' in the .debug_line info. */
+ Dwarf_Small ** bogus_bytes_ptr,
+ Dwarf_Unsigned * bogus_bytes_count,
+ Dwarf_Error * err,
+ int * err_count_out);
diff --git a/libdwarf/dwarf_line2.c b/libdwarf/dwarf_line2.c
new file mode 100644
index 0000000..ba384c7
--- /dev/null
+++ b/libdwarf/dwarf_line2.c
@@ -0,0 +1,107 @@
+/*
+
+ Copyright (C) 2000,2002,2004,2005,2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2008-2011 David Anderson, Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+/* This source file used for SGI-IRIX rqs processing.
+ Unused otherwise.
+*/
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include "dwarf_line.h"
+
+/* Return DW_DLV_OK or, if error,
+ DW_DLV_ERROR.
+
+ Thru pointers, return 2 arrays and a count
+ for rqs (IRIX run-time linker). */
+int
+_dwarf_line_address_offsets(Dwarf_Debug dbg,
+ Dwarf_Die die,
+ Dwarf_Addr ** addrs,
+ Dwarf_Off ** offs,
+ Dwarf_Unsigned * returncount,
+ Dwarf_Error * err)
+{
+ Dwarf_Addr *laddrs;
+ Dwarf_Off *loffsets;
+ Dwarf_Signed lcount;
+ Dwarf_Signed i;
+ int res;
+ Dwarf_Line *linebuf;
+
+ res = _dwarf_internal_srclines(die, &linebuf, &lcount,
+ /* addrlist= */ true, /* linelist= */ false, err);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ laddrs = (Dwarf_Addr *)
+ _dwarf_get_alloc(dbg, DW_DLA_ADDR, lcount);
+ if (laddrs == NULL) {
+ dwarf_srclines_dealloc(dbg, linebuf, lcount);
+ _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ loffsets = (Dwarf_Off *)
+ _dwarf_get_alloc(dbg, DW_DLA_ADDR, lcount);
+ if (loffsets == NULL) {
+ dwarf_srclines_dealloc(dbg, linebuf, lcount);
+ /* We already allocated what laddrs points at, so we'e better
+ deallocate that space since we are not going to return the
+ pointer to the caller. */
+ dwarf_dealloc(dbg, laddrs, DW_DLA_ADDR);
+ _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ for (i = 0; i < lcount; i++) {
+ laddrs[i] = linebuf[i]->li_address;
+ loffsets[i] = linebuf[i]->li_addr_line.li_offset;
+ }
+ dwarf_srclines_dealloc(dbg, linebuf, lcount);
+ *returncount = lcount;
+ *offs = loffsets;
+ *addrs = laddrs;
+ return DW_DLV_OK;
+}
+
+/*
+ It's impossible for callers of dwarf_srclines() to get to and
+ free all the resources (in particular, the li_context and its
+ lc_file_entries).
+ So this function, new July 2005, does it.
+*/
diff --git a/libdwarf/dwarf_loc.c b/libdwarf/dwarf_loc.c
new file mode 100644
index 0000000..3a2025a
--- /dev/null
+++ b/libdwarf/dwarf_loc.c
@@ -0,0 +1,1197 @@
+/*
+
+ Copyright (C) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
+ Portions Copyright (C) 2010 SN Systems Ltd. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include "dwarf_loc.h"
+#include <stdio.h> /* for debugging only. */
+
+/* Richard Henderson: The operand is an absolute
+ address. The first byte of the value
+ is an encoding length: 0 2 4 or 8. If zero
+ it means the following is address-size.
+ The address then follows immediately for
+ that number of bytes. */
+static int
+read_encoded_addr(Dwarf_Small *loc_ptr, Dwarf_Debug dbg,
+ Dwarf_Unsigned * val_out,
+ int * len_out,
+ Dwarf_Error *error)
+{
+ int totallen = 0;
+ int oplen = 0;
+ int len = 0;
+ Dwarf_Small op = *loc_ptr;
+ Dwarf_Unsigned operand = 0;
+ len++;
+ if(op == 0) {
+ /* FIXME: should be CU specific. */
+ op = dbg->de_pointer_size;
+ }
+ switch(op) {
+ case 1:
+ *val_out = *loc_ptr;
+ len++;
+ break;
+
+ case 2:
+ READ_UNALIGNED(dbg, operand, Dwarf_Unsigned, loc_ptr, 2);
+ *val_out = operand;
+ len +=2;
+ break;
+ case 4:
+ READ_UNALIGNED(dbg, operand, Dwarf_Unsigned, loc_ptr, 4);
+ *val_out = operand;
+ len +=4;
+ break;
+ case 8:
+ READ_UNALIGNED(dbg, operand, Dwarf_Unsigned, loc_ptr, 8);
+ *val_out = operand;
+ len +=8;
+ break;
+ default:
+ /* We do not know how much to read. */
+ _dwarf_error(dbg, error, DW_DLE_GNU_OPCODE_ERROR);
+ return DW_DLV_ERROR;
+ };
+ *len_out = len;
+ return DW_DLV_OK;
+}
+
+
+
+/* Given a Dwarf_Block that represents a location expression,
+ this function returns a pointer to a Dwarf_Locdesc struct
+ that has its ld_cents field set to the number of location
+ operators in the block, and its ld_s field pointing to a
+ contiguous block of Dwarf_Loc structs. However, the
+ ld_lopc and ld_hipc values are uninitialized. Returns
+ NULL on error. This function assumes that the length of
+ the block is greater than 0. Zero length location expressions
+ to represent variables that have been optimized away are
+ handled in the calling function.
+*/
+static Dwarf_Locdesc *
+_dwarf_get_locdesc(Dwarf_Debug dbg,
+ Dwarf_Block * loc_block,
+ Dwarf_Half address_size,
+ Dwarf_Addr lowpc,
+ Dwarf_Addr highpc,
+ Dwarf_Error * error)
+{
+ /* Size of the block containing the location expression. */
+ Dwarf_Unsigned loc_len = 0;
+
+ /* Sweeps the block containing the location expression. */
+ Dwarf_Small *loc_ptr = 0;
+
+ /* Offset of current operator from start of block. */
+ Dwarf_Unsigned offset = 0;
+
+ /* Used to chain the Dwarf_Loc_Chain_s structs. */
+ Dwarf_Loc_Chain curr_loc = NULL;
+ Dwarf_Loc_Chain prev_loc = NULL;
+ Dwarf_Loc_Chain head_loc = NULL;
+
+ /* Count of the number of location operators. */
+ Dwarf_Unsigned op_count = 0;
+
+ /* Contiguous block of Dwarf_Loc's for Dwarf_Locdesc. */
+ Dwarf_Loc *block_loc = 0;
+
+ /* Dwarf_Locdesc pointer to be returned. */
+ Dwarf_Locdesc *locdesc = 0;
+
+ Dwarf_Word leb128_length = 0;
+ Dwarf_Unsigned i = 0;
+
+ /* ***** BEGIN CODE ***** */
+
+ loc_len = loc_block->bl_len;
+ loc_ptr = loc_block->bl_data;
+
+ offset = 0;
+ op_count = 0;
+ while (offset < loc_len) {
+ Dwarf_Unsigned operand1 = 0;
+ Dwarf_Unsigned operand2 = 0;
+ Dwarf_Small atom = 0;
+
+ op_count++;
+ atom = *(Dwarf_Small *) loc_ptr;
+ loc_ptr++;
+ offset++;
+ curr_loc =
+ (Dwarf_Loc_Chain) _dwarf_get_alloc(dbg, DW_DLA_LOC_CHAIN,
+ 1);
+ if (curr_loc == NULL) {
+ /* Some memory may leak here. */
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (NULL);
+ }
+ curr_loc->lc_offset = offset;
+ curr_loc->lc_atom = atom;
+ switch (atom) {
+
+ case DW_OP_reg0:
+ case DW_OP_reg1:
+ case DW_OP_reg2:
+ case DW_OP_reg3:
+ case DW_OP_reg4:
+ case DW_OP_reg5:
+ case DW_OP_reg6:
+ case DW_OP_reg7:
+ case DW_OP_reg8:
+ case DW_OP_reg9:
+ case DW_OP_reg10:
+ case DW_OP_reg11:
+ case DW_OP_reg12:
+ case DW_OP_reg13:
+ case DW_OP_reg14:
+ case DW_OP_reg15:
+ case DW_OP_reg16:
+ case DW_OP_reg17:
+ case DW_OP_reg18:
+ case DW_OP_reg19:
+ case DW_OP_reg20:
+ case DW_OP_reg21:
+ case DW_OP_reg22:
+ case DW_OP_reg23:
+ case DW_OP_reg24:
+ case DW_OP_reg25:
+ case DW_OP_reg26:
+ case DW_OP_reg27:
+ case DW_OP_reg28:
+ case DW_OP_reg29:
+ case DW_OP_reg30:
+ case DW_OP_reg31:
+ break;
+
+ case DW_OP_regx:
+ operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length);
+ loc_ptr = loc_ptr + leb128_length;
+ offset = offset + leb128_length;
+ break;
+
+ case DW_OP_lit0:
+ case DW_OP_lit1:
+ case DW_OP_lit2:
+ case DW_OP_lit3:
+ case DW_OP_lit4:
+ case DW_OP_lit5:
+ case DW_OP_lit6:
+ case DW_OP_lit7:
+ case DW_OP_lit8:
+ case DW_OP_lit9:
+ case DW_OP_lit10:
+ case DW_OP_lit11:
+ case DW_OP_lit12:
+ case DW_OP_lit13:
+ case DW_OP_lit14:
+ case DW_OP_lit15:
+ case DW_OP_lit16:
+ case DW_OP_lit17:
+ case DW_OP_lit18:
+ case DW_OP_lit19:
+ case DW_OP_lit20:
+ case DW_OP_lit21:
+ case DW_OP_lit22:
+ case DW_OP_lit23:
+ case DW_OP_lit24:
+ case DW_OP_lit25:
+ case DW_OP_lit26:
+ case DW_OP_lit27:
+ case DW_OP_lit28:
+ case DW_OP_lit29:
+ case DW_OP_lit30:
+ case DW_OP_lit31:
+ operand1 = atom - DW_OP_lit0;
+ break;
+
+ case DW_OP_addr:
+ READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned,
+ loc_ptr, address_size);
+ loc_ptr += address_size;
+ offset += address_size;
+ break;
+
+ case DW_OP_const1u:
+ operand1 = *(Dwarf_Small *) loc_ptr;
+ loc_ptr = loc_ptr + 1;
+ offset = offset + 1;
+ break;
+
+ case DW_OP_const1s:
+ operand1 = *(Dwarf_Sbyte *) loc_ptr;
+ SIGN_EXTEND(operand1,1);
+ loc_ptr = loc_ptr + 1;
+ offset = offset + 1;
+ break;
+
+ case DW_OP_const2u:
+ READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 2);
+ loc_ptr = loc_ptr + 2;
+ offset = offset + 2;
+ break;
+
+ case DW_OP_const2s:
+ READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 2);
+ SIGN_EXTEND(operand1,2);
+ loc_ptr = loc_ptr + 2;
+ offset = offset + 2;
+ break;
+
+ case DW_OP_const4u:
+ READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 4);
+ loc_ptr = loc_ptr + 4;
+ offset = offset + 4;
+ break;
+
+ case DW_OP_const4s:
+ READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 4);
+ SIGN_EXTEND(operand1,4);
+ loc_ptr = loc_ptr + 4;
+ offset = offset + 4;
+ break;
+
+ case DW_OP_const8u:
+ READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 8);
+ loc_ptr = loc_ptr + 8;
+ offset = offset + 8;
+ break;
+
+ case DW_OP_const8s:
+ READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 8);
+ loc_ptr = loc_ptr + 8;
+ offset = offset + 8;
+ break;
+
+ case DW_OP_constu:
+ operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length);
+ loc_ptr = loc_ptr + leb128_length;
+ offset = offset + leb128_length;
+ break;
+
+ case DW_OP_consts:
+ operand1 = _dwarf_decode_s_leb128(loc_ptr, &leb128_length);
+ loc_ptr = loc_ptr + leb128_length;
+ offset = offset + leb128_length;
+ break;
+
+ case DW_OP_fbreg:
+ operand1 = _dwarf_decode_s_leb128(loc_ptr, &leb128_length);
+ loc_ptr = loc_ptr + leb128_length;
+ offset = offset + leb128_length;
+ break;
+
+ case DW_OP_breg0:
+ case DW_OP_breg1:
+ case DW_OP_breg2:
+ case DW_OP_breg3:
+ case DW_OP_breg4:
+ case DW_OP_breg5:
+ case DW_OP_breg6:
+ case DW_OP_breg7:
+ case DW_OP_breg8:
+ case DW_OP_breg9:
+ case DW_OP_breg10:
+ case DW_OP_breg11:
+ case DW_OP_breg12:
+ case DW_OP_breg13:
+ case DW_OP_breg14:
+ case DW_OP_breg15:
+ case DW_OP_breg16:
+ case DW_OP_breg17:
+ case DW_OP_breg18:
+ case DW_OP_breg19:
+ case DW_OP_breg20:
+ case DW_OP_breg21:
+ case DW_OP_breg22:
+ case DW_OP_breg23:
+ case DW_OP_breg24:
+ case DW_OP_breg25:
+ case DW_OP_breg26:
+ case DW_OP_breg27:
+ case DW_OP_breg28:
+ case DW_OP_breg29:
+ case DW_OP_breg30:
+ case DW_OP_breg31:
+ operand1 = _dwarf_decode_s_leb128(loc_ptr, &leb128_length);
+ loc_ptr = loc_ptr + leb128_length;
+ offset = offset + leb128_length;
+ break;
+
+ case DW_OP_bregx:
+ /* uleb reg num followed by sleb offset */
+ operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length);
+ loc_ptr = loc_ptr + leb128_length;
+ offset = offset + leb128_length;
+
+ operand2 = _dwarf_decode_s_leb128(loc_ptr, &leb128_length);
+ loc_ptr = loc_ptr + leb128_length;
+ offset = offset + leb128_length;
+ break;
+
+ case DW_OP_dup:
+ case DW_OP_drop:
+ break;
+
+ case DW_OP_pick:
+ operand1 = *(Dwarf_Small *) loc_ptr;
+ loc_ptr = loc_ptr + 1;
+ offset = offset + 1;
+ break;
+
+ case DW_OP_over:
+ case DW_OP_swap:
+ case DW_OP_rot:
+ case DW_OP_deref:
+ break;
+
+ case DW_OP_deref_size:
+ operand1 = *(Dwarf_Small *) loc_ptr;
+ loc_ptr = loc_ptr + 1;
+ offset = offset + 1;
+ break;
+
+ case DW_OP_xderef:
+ break;
+
+ case DW_OP_xderef_size:
+ operand1 = *(Dwarf_Small *) loc_ptr;
+ loc_ptr = loc_ptr + 1;
+ offset = offset + 1;
+ break;
+
+ 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:
+ break;
+
+ case DW_OP_plus_uconst:
+ operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length);
+ loc_ptr = loc_ptr + leb128_length;
+ offset = offset + leb128_length;
+ break;
+
+ case DW_OP_shl:
+ case DW_OP_shr:
+ case DW_OP_shra:
+ case DW_OP_xor:
+ break;
+
+ case DW_OP_le:
+ case DW_OP_ge:
+ case DW_OP_eq:
+ case DW_OP_lt:
+ case DW_OP_gt:
+ case DW_OP_ne:
+ break;
+
+ case DW_OP_skip:
+ case DW_OP_bra:
+ READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 2);
+ loc_ptr = loc_ptr + 2;
+ offset = offset + 2;
+ break;
+
+ case DW_OP_piece:
+ operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length);
+ loc_ptr = loc_ptr + leb128_length;
+ offset = offset + leb128_length;
+ break;
+
+ case DW_OP_nop:
+ break;
+ case DW_OP_push_object_address: /* DWARF3 */
+ break;
+ case DW_OP_call2: /* DWARF3 */
+ READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 2);
+ loc_ptr = loc_ptr + 2;
+ offset = offset + 2;
+ break;
+
+ case DW_OP_call4: /* DWARF3 */
+ READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr, 4);
+ loc_ptr = loc_ptr + 4;
+ offset = offset + 4;
+ break;
+ case DW_OP_call_ref: /* DWARF3 */
+ READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr,
+ dbg->de_length_size);
+ loc_ptr = loc_ptr + dbg->de_length_size;
+ offset = offset + dbg->de_length_size;
+ break;
+
+ case DW_OP_form_tls_address: /* DWARF3f */
+ break;
+ case DW_OP_call_frame_cfa: /* DWARF3f */
+ break;
+ case DW_OP_bit_piece: /* DWARF3f */
+ /* uleb size in bits followed by uleb offset in bits */
+ operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length);
+ loc_ptr = loc_ptr + leb128_length;
+ offset = offset + leb128_length;
+
+ operand2 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length);
+ loc_ptr = loc_ptr + leb128_length;
+ offset = offset + leb128_length;
+ break;
+
+ /* The operator means: push the currently computed
+ (by the operations encountered so far in this
+ expression) onto the expression stack as the offset
+ in thread-local-storage of the variable. */
+ case DW_OP_GNU_push_tls_address:
+ break;
+
+ case DW_OP_implicit_value: /* DWARF4 */
+ /* uleb length of value bytes followed by that
+ number of bytes of the value. */
+ operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length);
+ loc_ptr = loc_ptr + leb128_length;
+ offset = offset + leb128_length;
+
+ /* Second operand is block of 'operand1' bytes of stuff. */
+ /* This using the second operand as a pointer
+ is quite ugly. */
+ /* This gets an ugly compiler warning. Sorry. */
+ operand2 = (Dwarf_Unsigned)loc_ptr;
+ offset = offset + operand1;
+ loc_ptr = loc_ptr + operand1;
+ break;
+ case DW_OP_stack_value: /* DWARF4 */
+ break;
+ case DW_OP_GNU_uninit: /* 0xf0 GNU */
+ /* Carolyn Tice: Follws a DW_OP_reg or DW_OP_regx
+ and marks the reg as being uninitialized. */
+ break;
+ case DW_OP_GNU_encoded_addr: { /* 0xf1 GNU */
+ /* Richard Henderson: The operand is an absolute
+ address. The first byte of the value
+ is an encoding length: 0 2 4 or 8. If zero
+ it means the following is address-size.
+ The address then follows immediately for
+ that number of bytes. */
+ int length = 0;
+ int reares = read_encoded_addr(loc_ptr,dbg,&operand1,
+ &length,error);
+ if(reares != DW_DLV_OK) {
+ /* Oops. The caller will notice and
+ will issue DW_DLV_ERROR. */
+ return NULL;
+ }
+ loc_ptr += length;
+ offset += length;
+ }
+ break;
+ case DW_OP_GNU_implicit_pointer: /* 0xf2 GNU */
+ /* Jakub Jelinek: The value is an optimized-out
+ pointer value. Represented as
+ an offset_size (address_size) DIE offset
+ (as simple unsigned integer) followed by
+ a signed leb128 offset.
+ http://www.dwarfstd.org/ShowIssue.php?issue=100831.1 */
+ READ_UNALIGNED(dbg, operand1, Dwarf_Unsigned, loc_ptr,
+ dbg->de_length_size);
+ loc_ptr = loc_ptr + dbg->de_length_size;
+ offset = offset + dbg->de_length_size;
+
+ operand2 = _dwarf_decode_s_leb128(loc_ptr, &leb128_length);
+ loc_ptr = loc_ptr + leb128_length;
+ offset = offset + leb128_length;
+
+ break;
+ case DW_OP_GNU_entry_value: /* 0xf3 GNU */
+ /* Jakub Jelinek: A register reused really soon,
+ but the value is unchanged. So to represent
+ that value we have a uleb128 size followed
+ by a DWARF expression block that size.
+ http://www.dwarfstd.org/ShowIssue.php?issue=100909.1 */
+
+ /* uleb length of value bytes followed by that
+ number of bytes of the value. */
+ operand1 = _dwarf_decode_u_leb128(loc_ptr, &leb128_length);
+ loc_ptr = loc_ptr + leb128_length;
+ offset = offset + leb128_length;
+
+ /* Second operand is block of 'operand1' bytes of stuff. */
+ /* This using the second operand as a pointer
+ is quite ugly. */
+ /* This gets an ugly compiler warning. Sorry. */
+ operand2 = (Dwarf_Unsigned)loc_ptr;
+ offset = offset + operand1;
+ loc_ptr = loc_ptr + operand1;
+ break;
+
+ default:
+ /* Some memory does leak here. */
+
+ _dwarf_error(dbg, error, DW_DLE_LOC_EXPR_BAD);
+ return (NULL);
+ }
+
+ /* If offset == loc_len this would be normal end-of-expression. */
+ if (offset > loc_len) {
+ /* We stepped past the end of the expression.
+ This has to be a compiler bug.
+ Operators missing their values cannot be detected
+ as such except at the end of an expression (like this).
+ The results would be wrong if returned.
+ Some memory may leak here.
+ */
+ _dwarf_error(dbg, error, DW_DLE_LOC_BAD_TERMINATION);
+ return (NULL);
+ }
+
+ curr_loc->lc_number = operand1;
+ curr_loc->lc_number2 = operand2;
+
+ if (head_loc == NULL)
+ head_loc = prev_loc = curr_loc;
+ else {
+ prev_loc->lc_next = curr_loc;
+ prev_loc = curr_loc;
+ }
+ }
+
+ block_loc =
+ (Dwarf_Loc *) _dwarf_get_alloc(dbg, DW_DLA_LOC_BLOCK, op_count);
+ if (block_loc == NULL) {
+ /* Some memory does leak here. */
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (NULL);
+ }
+
+ curr_loc = head_loc;
+ for (i = 0; i < op_count; i++) {
+ (block_loc + i)->lr_atom = curr_loc->lc_atom;
+ (block_loc + i)->lr_number = curr_loc->lc_number;
+ (block_loc + i)->lr_number2 = curr_loc->lc_number2;
+ (block_loc + i)->lr_offset = curr_loc->lc_offset;
+
+ prev_loc = curr_loc;
+ curr_loc = curr_loc->lc_next;
+ dwarf_dealloc(dbg, prev_loc, DW_DLA_LOC_CHAIN);
+ }
+
+ locdesc =
+ (Dwarf_Locdesc *) _dwarf_get_alloc(dbg, DW_DLA_LOCDESC, 1);
+ if (locdesc == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (NULL);
+ }
+
+ locdesc->ld_cents = op_count;
+ locdesc->ld_s = block_loc;
+ locdesc->ld_from_loclist = loc_block->bl_from_loclist;
+ locdesc->ld_section_offset = loc_block->bl_section_offset;
+ locdesc->ld_lopc = lowpc;
+ locdesc->ld_hipc = highpc;
+
+ return (locdesc);
+}
+
+/* Using a loclist offset to get the in-memory
+ address of .debug_loc data to read, returns the loclist
+ 'header' info in return_block.
+*/
+
+#define MAX_ADDR ((address_size == 8)?0xffffffffffffffffULL:0xffffffff)
+
+static int
+_dwarf_read_loc_section(Dwarf_Debug dbg,
+ Dwarf_Block * return_block,
+ Dwarf_Addr * lowpc, Dwarf_Addr * hipc,
+ Dwarf_Off sec_offset,
+ Dwarf_Half address_size,
+ Dwarf_Error * error)
+{
+ Dwarf_Small *beg = dbg->de_debug_loc.dss_data + sec_offset;
+
+ Dwarf_Addr start_addr = 0;
+ Dwarf_Addr end_addr = 0;
+ Dwarf_Half exprblock_size = 0;
+ Dwarf_Unsigned exprblock_off =
+ 2 * address_size + sizeof(Dwarf_Half);
+
+ if (sec_offset >= dbg->de_debug_loc.dss_size) {
+ /* We're at the end. No more present. */
+ return DW_DLV_NO_ENTRY;
+ }
+
+ /* If it goes past end, error */
+ if (exprblock_off > dbg->de_debug_loc.dss_size) {
+ _dwarf_error(NULL, error, DW_DLE_DEBUG_LOC_SECTION_SHORT);
+ return DW_DLV_ERROR;
+ }
+
+ READ_UNALIGNED(dbg, start_addr, Dwarf_Addr, beg, address_size);
+ READ_UNALIGNED(dbg, end_addr, Dwarf_Addr,
+ beg + address_size, address_size);
+ if (start_addr == 0 && end_addr == 0) {
+ /* If start_addr and end_addr are 0, it's the end and no
+ exprblock_size field follows. */
+ exprblock_size = 0;
+ exprblock_off -= sizeof(Dwarf_Half);
+ } else if (start_addr == MAX_ADDR) {
+ /* End address is a base address, no exprblock_size field here
+ either */
+ exprblock_size = 0;
+ exprblock_off -= sizeof(Dwarf_Half);
+ } else {
+
+ READ_UNALIGNED(dbg, exprblock_size, Dwarf_Half,
+ beg + 2 * address_size, sizeof(Dwarf_Half));
+ /* exprblock_size can be zero, means no expression */
+ if ((exprblock_off + exprblock_size) > dbg->de_debug_loc.dss_size) {
+ _dwarf_error(NULL, error, DW_DLE_DEBUG_LOC_SECTION_SHORT);
+ return DW_DLV_ERROR;
+ }
+ }
+#undef MAX_ADDR
+ *lowpc = start_addr;
+ *hipc = end_addr;
+
+ return_block->bl_len = exprblock_size;
+ return_block->bl_from_loclist = 1;
+ return_block->bl_data = beg + exprblock_off;
+ return_block->bl_section_offset =
+ ((Dwarf_Small *) return_block->bl_data) - dbg->de_debug_loc.dss_data;
+
+ return DW_DLV_OK;
+
+}
+static int
+_dwarf_get_loclist_count(Dwarf_Debug dbg,
+ Dwarf_Off loclist_offset,
+ Dwarf_Half address_size,
+ int *loclist_count, Dwarf_Error * error)
+{
+ int count = 0;
+ Dwarf_Off offset = loclist_offset;
+
+
+ for (;;) {
+ Dwarf_Block b;
+ Dwarf_Addr lowpc;
+ Dwarf_Addr highpc;
+ int res = _dwarf_read_loc_section(dbg, &b,
+ &lowpc, &highpc,
+ offset, address_size,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ offset = b.bl_len + b.bl_section_offset;
+ if (lowpc == 0 && highpc == 0) {
+ break;
+ }
+ count++;
+ }
+ *loclist_count = count;
+ return DW_DLV_OK;
+}
+
+/* Helper routine to avoid code duplication.
+*/
+static int
+_dwarf_setup_loc(Dwarf_Attribute attr,
+ Dwarf_Debug * dbg_ret,
+ Dwarf_CU_Context *cucontext_ret,
+ Dwarf_Half * form_ret, Dwarf_Error * error)
+{
+ Dwarf_Debug dbg = 0;
+ Dwarf_Half form = 0;
+ int blkres = DW_DLV_ERROR;
+
+ if (attr == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_ATTR_NULL);
+ return (DW_DLV_ERROR);
+ }
+ if (attr->ar_cu_context == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_ATTR_NO_CU_CONTEXT);
+ return (DW_DLV_ERROR);
+ }
+ *cucontext_ret = attr->ar_cu_context;
+
+ dbg = attr->ar_cu_context->cc_dbg;
+ if (dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_ATTR_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+ *dbg_ret = dbg;
+ blkres = dwarf_whatform(attr, &form, error);
+ if (blkres != DW_DLV_OK) {
+ _dwarf_error(dbg, error, DW_DLE_LOC_EXPR_BAD);
+ return blkres;
+ }
+ *form_ret = form;
+ return DW_DLV_OK;
+}
+
+/* Helper routine to avoid code duplication.
+*/
+static int
+_dwarf_get_loclist_header_start(Dwarf_Debug dbg,
+ Dwarf_Attribute attr,
+ Dwarf_Unsigned * loclist_offset,
+ Dwarf_Error * error)
+{
+ int blkres = dwarf_global_formref(attr, loclist_offset, error);
+ if (blkres != DW_DLV_OK) {
+ return (blkres);
+ }
+
+ if (!dbg->de_debug_loc.dss_data) {
+ int secload = _dwarf_load_section(dbg, &dbg->de_debug_loc,error);
+ if (secload != DW_DLV_OK) {
+ return secload;
+ }
+ if (!dbg->de_debug_loc.dss_size) {
+ return (DW_DLV_NO_ENTRY);
+ }
+ }
+ return DW_DLV_OK;
+}
+
+/* When llbuf (see dwarf_loclist_n) is partially set up
+ and an error is encountered, tear it down as it
+ won't be used.
+*/
+static void
+_dwarf_cleanup_llbuf(Dwarf_Debug dbg, Dwarf_Locdesc ** llbuf, int count)
+{
+ int i;
+ for (i = 0; i < count; ++i) {
+ dwarf_dealloc(dbg, llbuf[i]->ld_s, DW_DLA_LOC_BLOCK);
+ dwarf_dealloc(dbg, llbuf[i], DW_DLA_LOCDESC);
+ }
+ dwarf_dealloc(dbg, llbuf, DW_DLA_LIST);
+}
+
+/* Handles simple location entries and loclists.
+ Returns all the Locdesc's thru llbuf. */
+int
+dwarf_loclist_n(Dwarf_Attribute attr,
+ Dwarf_Locdesc *** llbuf_out,
+ Dwarf_Signed * listlen_out, Dwarf_Error * error)
+{
+ Dwarf_Debug dbg;
+
+ /* Dwarf_Attribute that describes the DW_AT_location in die, if
+ present. */
+ Dwarf_Attribute loc_attr = attr;
+
+ /* Dwarf_Block that describes a single location expression. */
+ Dwarf_Block loc_block;
+
+ /* A pointer to the current Dwarf_Locdesc read. */
+ Dwarf_Locdesc *locdesc = 0;
+
+ Dwarf_Half form = 0;
+ Dwarf_Addr lowpc = 0;
+ Dwarf_Addr highpc = 0;
+ Dwarf_Signed listlen = 0;
+ Dwarf_Locdesc **llbuf = 0;
+ Dwarf_CU_Context cucontext = 0;
+ unsigned address_size = 0;
+
+ int blkres = DW_DLV_ERROR;
+ int setup_res = DW_DLV_ERROR;
+
+ /* ***** BEGIN CODE ***** */
+ setup_res = _dwarf_setup_loc(attr, &dbg,&cucontext, &form, error);
+ if (setup_res != DW_DLV_OK) {
+ return setup_res;
+ }
+ address_size = cucontext->cc_address_size;
+ /* If this is a form_block then it's a location expression. If it's
+ DW_FORM_data4 or DW_FORM_data8 it's a loclist offset */
+ if (((cucontext->cc_version_stamp == CURRENT_VERSION_STAMP ||
+ cucontext->cc_version_stamp == CURRENT_VERSION_STAMP3) &&
+ (form == DW_FORM_data4 || form == DW_FORM_data8)) ||
+ (cucontext->cc_version_stamp == CURRENT_VERSION_STAMP4 &&
+ form == DW_FORM_sec_offset)) {
+
+
+ /* A reference to .debug_loc, with an offset in .debug_loc of a
+ loclist */
+ Dwarf_Unsigned loclist_offset = 0;
+ int off_res = DW_DLV_ERROR;
+ int count_res = DW_DLV_ERROR;
+ int loclist_count;
+ int lli;
+
+ off_res = _dwarf_get_loclist_header_start(dbg,
+ attr, &loclist_offset, error);
+ if (off_res != DW_DLV_OK) {
+ return off_res;
+ }
+ count_res = _dwarf_get_loclist_count(dbg, loclist_offset,
+ address_size, &loclist_count, error);
+ listlen = loclist_count;
+ if (count_res != DW_DLV_OK) {
+ return count_res;
+ }
+ if (loclist_count == 0) {
+ return DW_DLV_NO_ENTRY;
+ }
+
+ llbuf = (Dwarf_Locdesc **)
+ _dwarf_get_alloc(dbg, DW_DLA_LIST, loclist_count);
+ if (!llbuf) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ for (lli = 0; lli < loclist_count; ++lli) {
+ blkres = _dwarf_read_loc_section(dbg, &loc_block,
+ &lowpc,
+ &highpc,
+ loclist_offset,
+ address_size,
+ error);
+ if (blkres != DW_DLV_OK) {
+ _dwarf_cleanup_llbuf(dbg, llbuf, lli);
+ return (blkres);
+ }
+ locdesc = _dwarf_get_locdesc(dbg, &loc_block,
+ address_size,
+ lowpc, highpc, error);
+ if (locdesc == NULL) {
+ _dwarf_cleanup_llbuf(dbg, llbuf, lli);
+ /* low level error already set: let it be passed back */
+ return (DW_DLV_ERROR);
+ }
+ llbuf[lli] = locdesc;
+
+ /* Now get to next loclist entry offset. */
+ loclist_offset = loc_block.bl_section_offset +
+ loc_block.bl_len;
+ }
+
+
+ } else {
+ Dwarf_Block *tblock = 0;
+
+ blkres = dwarf_formblock(loc_attr, &tblock, error);
+ if (blkres != DW_DLV_OK) {
+ return (blkres);
+ }
+ loc_block = *tblock;
+ /* We copied tblock contents to the stack var, so can dealloc
+ tblock now. Avoids leaks. */
+ dwarf_dealloc(dbg, tblock, DW_DLA_BLOCK);
+ listlen = 1; /* One by definition of a location entry. */
+ lowpc = 0; /* HACK */
+ highpc = (Dwarf_Unsigned) (-1LL); /* HACK */
+
+ /* An empty location description (block length 0) means the
+ code generator emitted no variable, the variable was not
+ generated, it was unused or perhaps never tested after being
+ set. Dwarf2, section 2.4.1 In other words, it is not an
+ error, and we don't test for block length 0 specially here. */
+ locdesc = _dwarf_get_locdesc(dbg, &loc_block,
+ address_size,
+ lowpc, highpc, error);
+ if (locdesc == NULL) {
+ /* low level error already set: let it be passed back */
+ return (DW_DLV_ERROR);
+ }
+ llbuf = (Dwarf_Locdesc **)
+ _dwarf_get_alloc(dbg, DW_DLA_LIST, listlen);
+ if (!llbuf) {
+ /* Free the locdesc we allocated but won't use. */
+ dwarf_dealloc(dbg, locdesc, DW_DLA_LOCDESC);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ llbuf[0] = locdesc;
+ }
+
+ *llbuf_out = llbuf;
+ *listlen_out = listlen;
+ return (DW_DLV_OK);
+}
+
+
+/* Handles only a location expression.
+ If called on a loclist, just returns one of those.
+ Cannot not handle a real loclist.
+ It returns the location expression as a loclist with
+ a single entry.
+ See dwarf_loclist_n() which handles any number
+ of location list entries.
+
+ This is the original definition, and it simply
+ does not work for loclists. Kept for compatibility.
+*/
+int
+dwarf_loclist(Dwarf_Attribute attr,
+ Dwarf_Locdesc ** llbuf,
+ Dwarf_Signed * listlen, Dwarf_Error * error)
+{
+ Dwarf_Debug dbg;
+
+ /* Dwarf_Attribute that describes the DW_AT_location in die, if
+ present. */
+ Dwarf_Attribute loc_attr = attr;
+
+ /* Dwarf_Block that describes a single location expression. */
+ Dwarf_Block loc_block;
+
+ /* A pointer to the current Dwarf_Locdesc read. */
+ Dwarf_Locdesc *locdesc = 0;
+
+ Dwarf_Half form = 0;
+ Dwarf_Addr lowpc = 0;
+ Dwarf_Addr highpc = 0;
+ Dwarf_CU_Context cucontext = 0;
+ unsigned address_size = 0;
+
+ int blkres = DW_DLV_ERROR;
+ int setup_res = DW_DLV_ERROR;
+
+ /* ***** BEGIN CODE ***** */
+ setup_res = _dwarf_setup_loc(attr, &dbg, &cucontext, &form, error);
+ if (setup_res != DW_DLV_OK) {
+ return setup_res;
+ }
+ address_size = cucontext->cc_address_size;
+ /* If this is a form_block then it's a location expression. If it's
+ DW_FORM_data4 or DW_FORM_data8 it's a loclist offset */
+ if (((cucontext->cc_version_stamp == CURRENT_VERSION_STAMP ||
+ cucontext->cc_version_stamp == CURRENT_VERSION_STAMP3) &&
+ (form == DW_FORM_data4 || form == DW_FORM_data8)) ||
+ (cucontext->cc_version_stamp == CURRENT_VERSION_STAMP4 &&
+ form == DW_FORM_sec_offset))
+ {
+
+ /* A reference to .debug_loc, with an offset in .debug_loc of a
+ loclist. */
+ Dwarf_Unsigned loclist_offset = 0;
+ int off_res = DW_DLV_ERROR;
+
+ off_res = _dwarf_get_loclist_header_start(dbg,
+ attr, &loclist_offset,
+ error);
+ if (off_res != DW_DLV_OK) {
+ return off_res;
+ }
+
+ /* With dwarf_loclist, just read a single entry */
+ blkres = _dwarf_read_loc_section(dbg, &loc_block,
+ &lowpc,
+ &highpc,
+ loclist_offset,
+ address_size,
+ error);
+ if (blkres != DW_DLV_OK) {
+ return (blkres);
+ }
+ } else {
+ Dwarf_Block *tblock = 0;
+
+ blkres = dwarf_formblock(loc_attr, &tblock, error);
+ if (blkres != DW_DLV_OK) {
+ return (blkres);
+ }
+ loc_block = *tblock;
+ /* We copied tblock contents to the stack var, so can dealloc
+ tblock now. Avoids leaks. */
+ dwarf_dealloc(dbg, tblock, DW_DLA_BLOCK);
+ lowpc = 0; /* HACK */
+ highpc = (Dwarf_Unsigned) (-1LL); /* HACK */
+ }
+
+ /* An empty location description (block length 0) means the code
+ generator emitted no variable, the variable was not generated,
+ it was unused or perhaps never tested after being set. Dwarf2,
+ section 2.4.1 In other words, it is not an error, and we don't
+ test for block length 0 specially here.
+ See *dwarf_loclist_n() which handles the general case, this case
+ handles only a single location expression. */
+ locdesc = _dwarf_get_locdesc(dbg, &loc_block,
+ address_size,
+ lowpc, highpc, error);
+ if (locdesc == NULL) {
+ /* low level error already set: let it be passed back */
+ return (DW_DLV_ERROR);
+ }
+
+ *llbuf = locdesc;
+ *listlen = 1;
+ return (DW_DLV_OK);
+}
+
+
+
+/* Handles only a location expression.
+ It returns the location expression as a loclist with
+ a single entry.
+
+ Usable to access dwarf expressions from any source, but
+ specifically from
+ DW_CFA_def_cfa_expression
+ DW_CFA_expression
+ DW_CFA_val_expression
+
+ expression_in must point to a valid dwarf expression
+ set of bytes of length expression_length. Not
+ a DW_FORM_block*, just the expression bytes.
+
+ If the address_size != de_pointer_size this will not work
+ right. FIXME.
+*/
+int
+dwarf_loclist_from_expr(Dwarf_Debug dbg,
+ Dwarf_Ptr expression_in,
+ Dwarf_Unsigned expression_length,
+ Dwarf_Locdesc ** llbuf,
+ Dwarf_Signed * listlen, Dwarf_Error * error)
+{
+ int res = 0;
+ Dwarf_Half addr_size = dbg->de_pointer_size;
+ res = dwarf_loclist_from_expr_a(dbg,expression_in,
+ expression_length, addr_size,llbuf,listlen,error);
+ return res;
+}
+
+/* New April 27 2009. Adding addr_size argument for the rare
+ cases where an object has CUs with a different address_size. */
+int
+dwarf_loclist_from_expr_a(Dwarf_Debug dbg,
+ Dwarf_Ptr expression_in,
+ Dwarf_Unsigned expression_length,
+ Dwarf_Half addr_size,
+ Dwarf_Locdesc ** llbuf,
+ Dwarf_Signed * listlen, Dwarf_Error * error)
+{
+ /* Dwarf_Block that describes a single location expression. */
+ Dwarf_Block loc_block;
+
+ /* A pointer to the current Dwarf_Locdesc read. */
+ Dwarf_Locdesc *locdesc = 0;
+ Dwarf_Addr lowpc = 0;
+ Dwarf_Addr highpc = (Dwarf_Unsigned) (-1LL);
+
+ memset(&loc_block,0,sizeof(loc_block));
+ loc_block.bl_len = expression_length;
+ loc_block.bl_data = expression_in;
+ loc_block.bl_from_loclist = 0; /* Not from loclist. */
+ loc_block.bl_section_offset = 0; /* Fake. Not meaningful. */
+
+ /* An empty location description (block length 0) means the code
+ generator emitted no variable, the variable was not generated,
+ it was unused or perhaps never tested after being set. Dwarf2,
+ section 2.4.1 In other words, it is not an error, and we don't
+ test for block length 0 specially here. */
+ locdesc = _dwarf_get_locdesc(dbg, &loc_block,
+ addr_size,lowpc, highpc, error);
+ if (locdesc == NULL) {
+ /* low level error already set: let it be passed back */
+ return (DW_DLV_ERROR);
+ }
+
+ *llbuf = locdesc;
+ *listlen = 1;
+ return (DW_DLV_OK);
+}
+
+/* Usable to read a single loclist or to read a block of them
+ or to read an entire section's loclists.
+
+ It's broken because it's not safe to read a loclist entry
+ when we do not know the address size (in any object where
+ address size can vary by compilation unit).
+*/
+
+/*ARGSUSED*/ int
+dwarf_get_loclist_entry(Dwarf_Debug dbg,
+ Dwarf_Unsigned offset,
+ Dwarf_Addr * hipc_offset,
+ Dwarf_Addr * lopc_offset,
+ Dwarf_Ptr * data,
+ Dwarf_Unsigned * entry_len,
+ Dwarf_Unsigned * next_entry,
+ Dwarf_Error * error)
+{
+ Dwarf_Block b;
+ Dwarf_Addr lowpc = 0;
+ Dwarf_Addr highpc = 0;
+ Dwarf_Half address_size = 0;
+ int res = DW_DLV_ERROR;
+
+ if (!dbg->de_debug_loc.dss_data) {
+ int secload = _dwarf_load_section(dbg, &dbg->de_debug_loc,error);
+ if (secload != DW_DLV_OK) {
+ return secload;
+ }
+ }
+
+ /* FIXME: address_size is not necessarily the same in every frame. */
+ address_size = dbg->de_pointer_size;
+ res = _dwarf_read_loc_section(dbg,
+ &b, &lowpc, &highpc, offset,
+ address_size,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ *hipc_offset = highpc;
+ *lopc_offset = lowpc;
+ *entry_len = b.bl_len;
+ *data = b.bl_data;
+ *next_entry = b.bl_len + b.bl_section_offset;
+ return DW_DLV_OK;
+}
+
+
diff --git a/libdwarf/dwarf_loc.h b/libdwarf/dwarf_loc.h
new file mode 100644
index 0000000..685d199
--- /dev/null
+++ b/libdwarf/dwarf_loc.h
@@ -0,0 +1,46 @@
+/*
+
+ Copyright (C) 2000, 2004 Silicon Graphics, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+typedef struct Dwarf_Loc_Chain_s *Dwarf_Loc_Chain;
+
+struct Dwarf_Loc_Chain_s {
+ Dwarf_Small lc_atom;
+ Dwarf_Unsigned lc_number;
+ Dwarf_Unsigned lc_number2;
+ Dwarf_Unsigned lc_offset;
+ Dwarf_Loc_Chain lc_next;
+};
diff --git a/libdwarf/dwarf_macro.c b/libdwarf/dwarf_macro.c
new file mode 100644
index 0000000..a3d5eb6
--- /dev/null
+++ b/libdwarf/dwarf_macro.c
@@ -0,0 +1,470 @@
+/*
+
+ Copyright (C) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include <limits.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif /* HAVE_STDLIB_H */
+#include "dwarf_macro.h"
+
+
+#define LEFTPAREN '('
+#define RIGHTPAREN ')'
+#define SPACE ' '
+
+/* Given the dwarf macro string, return a pointer to
+ the value. Returns pointer to 0 byte at end of string
+ if no value found (meaning the value is the empty string).
+
+ Only understands well-formed dwarf macinfo strings.
+*/
+char *
+dwarf_find_macro_value_start(char *str)
+{
+ char *lcp;
+ int funclike = 0;
+
+ for (lcp = str; *lcp; ++lcp) {
+ switch (*lcp) {
+ case LEFTPAREN:
+ funclike = 1;
+ break;
+ case RIGHTPAREN:
+ /* lcp+1 must be a space, and following char is the value */
+ return lcp + 2;
+ case SPACE:
+ /* We allow extraneous spaces inside macro parameter **
+ list, just in case... This is not really needed. */
+ if (!funclike) {
+ return lcp + 1;
+ }
+ break;
+ }
+ }
+ /* Never found value: returns pointer to the 0 byte at end of
+ string. */
+ return lcp;
+
+}
+
+
+/*
+ Try to keep fileindex correct in every Macro_Details
+ record by tracking file starts and ends.
+ Uses high water mark: space reused, not freed.
+ Presumption is that this makes sense for most uses.
+ STARTERMAX is set so that the array need not be expanded for
+ most files: it is the initial include file depth.
+*/
+struct macro_stack_s {
+ Dwarf_Signed *st_base;
+ long max;
+ long next_to_use;
+ int was_fault;
+};
+
+static void _dwarf_reset_index_macro_stack(struct macro_stack_s *ms);
+static void
+free_macro_stack(Dwarf_Debug dbg, struct macro_stack_s *ms)
+{
+ dwarf_dealloc(dbg,ms->st_base,DW_DLA_STRING);
+ _dwarf_reset_index_macro_stack(ms);
+}
+
+#define STARTERMAX 10
+static void
+_dwarf_reset_index_macro_stack(struct macro_stack_s *ms)
+{
+ ms->st_base = 0;
+ ms->max = 0;
+ ms->next_to_use = 0;
+ ms->was_fault = 0;
+}
+static int
+_dwarf_macro_stack_push_index(Dwarf_Debug dbg, Dwarf_Signed indx,
+ struct macro_stack_s *ms)
+{
+ Dwarf_Signed *newbase;
+
+ if (ms->next_to_use >= ms->max) {
+ long new_size;
+
+ if (ms->max == 0) {
+ ms->max = STARTERMAX;
+ }
+ new_size = ms->max * 2;
+ newbase =
+ _dwarf_get_alloc(dbg, DW_DLA_STRING,
+ new_size * sizeof(Dwarf_Signed));
+ if (newbase == 0) {
+ /* just leave the old array in place */
+ ms->was_fault = 1;
+ return DW_DLV_ERROR;
+ }
+ if(ms->st_base) {
+ memcpy(newbase, ms->st_base,
+ ms->next_to_use * sizeof(Dwarf_Signed));
+ dwarf_dealloc(dbg, ms->st_base, DW_DLA_STRING);
+ }
+ ms->st_base = newbase;
+ ms->max = new_size;
+ }
+ ms->st_base[ms->next_to_use] = indx;
+ ++ms->next_to_use;
+ return DW_DLV_OK;
+}
+
+static Dwarf_Signed
+_dwarf_macro_stack_pop_index(struct macro_stack_s *ms)
+{
+ if (ms->was_fault) {
+ return -1;
+ }
+ if (ms->next_to_use > 0) {
+ ms->next_to_use--;
+ return (ms->st_base[ms->next_to_use]);
+ } else {
+ ms->was_fault = 1;
+ }
+ return -1;
+}
+
+/* Starting at macro_offset in .debug_macinfo,
+ if maximum_count is 0, treat as if it is infinite.
+ get macro data up thru
+ maximum_count entries or the end of a compilation
+ unit's entries (whichever comes first). */
+
+int
+dwarf_get_macro_details(Dwarf_Debug dbg,
+ Dwarf_Off macro_offset,
+ Dwarf_Unsigned maximum_count,
+ Dwarf_Signed * entry_count,
+ Dwarf_Macro_Details ** details,
+ Dwarf_Error * error)
+{
+ Dwarf_Small *macro_base = 0;
+ Dwarf_Small *pnext = 0;
+ Dwarf_Unsigned endloc = 0;
+ unsigned char uc = 0;
+ unsigned long depth = 0;
+ /* By section 6.3.2 Dwarf3 draft 8/9,
+ the base file should appear as
+ DW_MACINFO_start_file. See
+ http://gcc.gnu.org/ml/gcc-bugs/2005-02/msg03442.html
+ on "[Bug debug/20253] New: [3.4/4.0 regression]:
+ Macro debug info broken due to lexer change" for how
+ gcc is broken in some versions. We no longer use
+ depth as a stopping point, it's not needed as a
+ stopping point anyway. */
+ int res = 0;
+ /* count space used by strings */
+ unsigned long str_space = 0;
+ int done = 0;
+ unsigned long space_needed = 0;
+ unsigned long string_offset = 0;
+ Dwarf_Small *return_data = 0;
+ Dwarf_Small *pdata = 0;
+ unsigned long final_count = 0;
+ Dwarf_Signed fileindex = -1;
+ Dwarf_Small *latest_str_loc = 0;
+ struct macro_stack_s msdata;
+
+ unsigned long count = 0;
+ unsigned long max_count = (unsigned long) maximum_count;
+
+ _dwarf_reset_index_macro_stack(&msdata);
+ if (dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
+ free_macro_stack(dbg,&msdata);
+ return (DW_DLV_ERROR);
+ }
+
+ res = _dwarf_load_section(dbg, &dbg->de_debug_macinfo,error);
+ if (res != DW_DLV_OK) {
+ free_macro_stack(dbg,&msdata);
+ return res;
+ }
+ if (!dbg->de_debug_abbrev.dss_size) {
+ free_macro_stack(dbg,&msdata);
+ return (DW_DLV_NO_ENTRY);
+ }
+
+ macro_base = dbg->de_debug_macinfo.dss_data;
+ if (macro_base == NULL) {
+ free_macro_stack(dbg,&msdata);
+ return (DW_DLV_NO_ENTRY);
+ }
+ if (macro_offset >= dbg->de_debug_macinfo.dss_size) {
+ free_macro_stack(dbg,&msdata);
+ return (DW_DLV_NO_ENTRY);
+ }
+
+ pnext = macro_base + macro_offset;
+ if (maximum_count == 0) {
+ max_count = ULONG_MAX;
+ }
+
+
+ /* how many entries and how much space will they take? */
+
+ endloc = (pnext - macro_base);
+ if (endloc >= dbg->de_debug_macinfo.dss_size) {
+ if (endloc == dbg->de_debug_macinfo.dss_size) {
+ /* normal: found last entry */
+ free_macro_stack(dbg,&msdata);
+ return DW_DLV_NO_ENTRY;
+ }
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD);
+ free_macro_stack(dbg,&msdata);
+ return (DW_DLV_ERROR);
+ }
+ for (count = 0; !done && count < max_count; ++count) {
+ unsigned long slen;
+ Dwarf_Word len;
+
+ uc = *pnext;
+ ++pnext; /* get past the type code */
+ switch (uc) {
+ case DW_MACINFO_define:
+ case DW_MACINFO_undef:
+ /* line, string */
+ case DW_MACINFO_vendor_ext:
+ /* number, string */
+ (void) _dwarf_decode_u_leb128(pnext, &len);
+
+ pnext += len;
+ if (((pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) {
+ free_macro_stack(dbg,&msdata);
+ _dwarf_error(dbg, error,
+ DW_DLE_DEBUG_MACRO_INCONSISTENT);
+ return (DW_DLV_ERROR);
+ }
+ slen = strlen((char *) pnext) + 1;
+ pnext += slen;
+ if (((pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) {
+ free_macro_stack(dbg,&msdata);
+ _dwarf_error(dbg, error,
+ DW_DLE_DEBUG_MACRO_INCONSISTENT);
+ return (DW_DLV_ERROR);
+ }
+ str_space += slen;
+ break;
+ case DW_MACINFO_start_file:
+ /* line, file index */
+ (void) _dwarf_decode_u_leb128(pnext, &len);
+ pnext += len;
+ if (((pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) {
+ free_macro_stack(dbg,&msdata);
+ _dwarf_error(dbg, error,
+ DW_DLE_DEBUG_MACRO_INCONSISTENT);
+ return (DW_DLV_ERROR);
+ }
+ (void) _dwarf_decode_u_leb128(pnext, &len);
+ pnext += len;
+ if (((pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) {
+ free_macro_stack(dbg,&msdata);
+ _dwarf_error(dbg, error,
+ DW_DLE_DEBUG_MACRO_INCONSISTENT);
+ return (DW_DLV_ERROR);
+ }
+ ++depth;
+ break;
+
+ case DW_MACINFO_end_file:
+ if (--depth == 0) {
+ /* done = 1; no, do not stop here, at least one gcc had
+ the wrong depth settings in the gcc 3.4 timeframe. */
+ }
+ /* no string or number here */
+ break;
+ case 0:
+ /* end of cu's entries */
+ done = 1;
+ break;
+ default:
+ free_macro_stack(dbg,&msdata);
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT);
+ return (DW_DLV_ERROR);
+ /* bogus macinfo! */
+ }
+
+ endloc = (pnext - macro_base);
+ if (endloc == dbg->de_debug_macinfo.dss_size) {
+ done = 1;
+ } else if (endloc > dbg->de_debug_macinfo.dss_size) {
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD);
+ free_macro_stack(dbg,&msdata);
+ return (DW_DLV_ERROR);
+ }
+ }
+ if (count == 0) {
+ free_macro_stack(dbg,&msdata);
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INTERNAL_ERR);
+ return (DW_DLV_ERROR);
+ }
+
+ /* We have 'count' array entries to allocate and str_space bytes of
+ string space to provide for. */
+
+ string_offset = count * sizeof(Dwarf_Macro_Details);
+
+ /* extra 2 not really needed */
+ space_needed = string_offset + str_space + 2;
+ return_data = pdata =
+ _dwarf_get_alloc(dbg, DW_DLA_STRING, space_needed);
+ latest_str_loc = pdata + string_offset;
+ if (pdata == 0) {
+ free_macro_stack(dbg,&msdata);
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_MALLOC_SPACE);
+ return (DW_DLV_ERROR);
+ }
+ pnext = macro_base + macro_offset;
+
+ done = 0;
+
+ /* A series ends with a type code of 0. */
+
+ for (final_count = 0; !done && final_count < count; ++final_count) {
+ unsigned long slen;
+ Dwarf_Word len;
+ Dwarf_Unsigned v1;
+ Dwarf_Macro_Details *pdmd = (Dwarf_Macro_Details *) (pdata +
+ (final_count * sizeof (Dwarf_Macro_Details)));
+
+ endloc = (pnext - macro_base);
+ if (endloc > dbg->de_debug_macinfo.dss_size) {
+ free_macro_stack(dbg,&msdata);
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD);
+ return (DW_DLV_ERROR);
+ }
+ uc = *pnext;
+ pdmd->dmd_offset = (pnext - macro_base);
+ pdmd->dmd_type = uc;
+ pdmd->dmd_fileindex = fileindex;
+ pdmd->dmd_lineno = 0;
+ pdmd->dmd_macro = 0;
+ ++pnext; /* get past the type code */
+ switch (uc) {
+ case DW_MACINFO_define:
+ case DW_MACINFO_undef:
+ /* line, string */
+ case DW_MACINFO_vendor_ext:
+ /* number, string */
+ v1 = _dwarf_decode_u_leb128(pnext, &len);
+ pdmd->dmd_lineno = v1;
+
+ pnext += len;
+ if (((pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) {
+ free_macro_stack(dbg,&msdata);
+ dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
+ _dwarf_error(dbg, error,
+ DW_DLE_DEBUG_MACRO_INCONSISTENT);
+ return (DW_DLV_ERROR);
+ }
+ slen = strlen((char *) pnext) + 1;
+ strcpy((char *) latest_str_loc, (char *) pnext);
+ pdmd->dmd_macro = (char *) latest_str_loc;
+ latest_str_loc += slen;
+ pnext += slen;
+ if (((pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) {
+ free_macro_stack(dbg,&msdata);
+ dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
+ _dwarf_error(dbg, error,
+ DW_DLE_DEBUG_MACRO_INCONSISTENT);
+ return (DW_DLV_ERROR);
+ }
+ break;
+ case DW_MACINFO_start_file:
+ /* Line, file index */
+ v1 = _dwarf_decode_u_leb128(pnext, &len);
+ pdmd->dmd_lineno = v1;
+ pnext += len;
+ if (((pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) {
+ free_macro_stack(dbg,&msdata);
+ dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
+ _dwarf_error(dbg, error,
+ DW_DLE_DEBUG_MACRO_INCONSISTENT);
+ return (DW_DLV_ERROR);
+ }
+ v1 = _dwarf_decode_u_leb128(pnext, &len);
+ pdmd->dmd_fileindex = v1;
+ (void) _dwarf_macro_stack_push_index(dbg, fileindex,
+ &msdata);
+ /* We ignore the error, we just let fileindex ** be -1 when
+ we pop this one. */
+ fileindex = v1;
+ pnext += len;
+ if (((pnext - macro_base)) >= dbg->de_debug_macinfo.dss_size) {
+ free_macro_stack(dbg,&msdata);
+ dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
+ _dwarf_error(dbg, error,
+ DW_DLE_DEBUG_MACRO_INCONSISTENT);
+ return (DW_DLV_ERROR);
+ }
+ break;
+
+ case DW_MACINFO_end_file:
+ fileindex = _dwarf_macro_stack_pop_index(&msdata);
+ break; /* no string or number here */
+ case 0:
+ /* Type code of 0 means the end of cu's entries. */
+ done = 1;
+ break;
+ default:
+ /* Bogus macinfo! */
+ dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
+ free_macro_stack(dbg,&msdata);
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT);
+ return (DW_DLV_ERROR);
+ }
+ }
+ *entry_count = count;
+ *details = (Dwarf_Macro_Details *) return_data;
+ free_macro_stack(dbg,&msdata);
+ return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_macro.h b/libdwarf/dwarf_macro.h
new file mode 100644
index 0000000..31ea2e6
--- /dev/null
+++ b/libdwarf/dwarf_macro.h
@@ -0,0 +1,44 @@
+/*
+
+ Copyright (C) 2000, 2004 Silicon Graphics, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+/*
+
+
+ dwarf_macro.h
+
+ $Revision: 1.4 $ $Date: 2004/10/28 22:19:14 $
+
+*/
diff --git a/libdwarf/dwarf_opaque.h b/libdwarf/dwarf_opaque.h
new file mode 100644
index 0000000..88d1ce3
--- /dev/null
+++ b/libdwarf/dwarf_opaque.h
@@ -0,0 +1,364 @@
+/*
+
+ Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
+ Portions Copyright (C) 2008-2010 Arxan Technologies, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+/* The versions applicable by section are:
+ . DWARF2 DWARF3 DWARF4
+ .debug_abbrev - - -
+ .debug_aranges 2 2 2
+ .debug_frame 1 3 4
+ .debug_info 2 3 4
+ .debug_line 2 3 4
+ .debug_loc - - -
+ .debug_macinfo - - -
+ .debug_pubtypes x 2 2
+ .debug_pubnames 2 2 2
+ .debug_ranges x - -
+ .debug_str - - -
+ .debug_types x x 4
+*/
+
+#include <stddef.h>
+
+/* The 'debug_info' names below are non-zero (non-NULL) only
+ if we are processing a debug_info section. And vice versa
+ for a debug_types section. */
+
+struct Dwarf_Die_s {
+ Dwarf_Byte_Ptr di_debug_ptr;
+ Dwarf_Abbrev_List di_abbrev_list;
+ Dwarf_CU_Context di_cu_context;
+ int di_abbrev_code;
+
+ /* TRUE if part of debug_info. FALSE if part of .debug_types. */
+ Dwarf_Bool di_is_info;
+};
+
+struct Dwarf_Attribute_s {
+ Dwarf_Half ar_attribute; /* Attribute Value. */
+ Dwarf_Half ar_attribute_form; /* Attribute Form. */
+ Dwarf_Half ar_attribute_form_direct;
+ /* Identical to ar_attribute_form except that if
+ the original form uleb was DW_FORM_indirect,
+ ar_attribute_form_direct contains DW_FORM_indirect
+ but ar_attribute_form contains the true form. */
+ Dwarf_CU_Context ar_cu_context;
+ /* The following points to either debug_info or debug_types
+ depending on if context is cc_is_info or not. */
+ Dwarf_Small *ar_debug_ptr;
+
+ Dwarf_Die ar_die;/* Access to the DIE owning the attribute */
+ Dwarf_Attribute ar_next;
+};
+
+/*
+ This structure provides the context for a compilation unit.
+ Thus, it contains the Dwarf_Debug, cc_dbg, that this cu
+ belongs to. It contains the information in the compilation
+ unit header, cc_length, cc_version_stamp, cc_abbrev_offset,
+ and cc_address_size, in the .debug_info section for that cu.
+ In addition, it contains the count, cc_count_cu, of the cu
+ number of that cu in the list of cu's in the .debug_info.
+ The count starts at 1, ie cc_count_cu is 1 for the first cu,
+ 2 for the second and so on. This struct also contains a
+ pointer, cc_abbrev_table, to a list of pairs of abbrev code
+ and a pointer to the start of that abbrev
+ in the .debug_abbrev section.
+
+ Each die will also contain a pointer to such a struct to
+ record the context for that die.
+
+ Notice that a pointer to the CU DIE itself is
+ Dwarf_Off off2 = cu_context->cc_debug_info_offset;
+ cu_die_info_ptr = dbg->de_debug_info.dss_data +
+ off2 + _dwarf_length_of_cu_header(dbg, off2);
+ Or similar for de_debug_types.
+
+ **Updated by dwarf_next_cu_header in dwarf_die_deliv.c
+*/
+struct Dwarf_CU_Context_s {
+ Dwarf_Debug cc_dbg;
+ /* The sum of cc_length, cc_length_size, and cc_extension_size
+ is the total length of the CU including its header. */
+ Dwarf_Word cc_length;
+ /* cc_length_size is the size in bytes of an offset.
+ 4 for 32bit dwarf, 8 for 64bit dwarf (whether MIPS/IRIX
+ 64bit dwarf or standard 64bit dwarf using the extension
+ mechanism). */
+ Dwarf_Small cc_length_size;
+ /* cc_extension_size is zero unless this is standard
+ DWARF3 and later 64bit dwarf using the extension mechanism.
+ If it is the DWARF3 and later 64bit dwarf cc_extension
+ size is 4. So for 32bit dwarf and MIPS/IRIX 64bit dwarf
+ cc_extension_size is zero. */
+ Dwarf_Small cc_extension_size;
+ Dwarf_Half cc_version_stamp;
+ Dwarf_Sword cc_abbrev_offset;
+ Dwarf_Small cc_address_size;
+ /* cc_debug_offset is the offset in the section
+ of the CU header of this CU. Dwarf_Word
+ should be large enough. May be debug_info or debug_types
+ but those are distinct. See cc_is_info flag. */
+ Dwarf_Word cc_debug_offset;
+ Dwarf_Sig8 cc_signature;
+ Dwarf_Unsigned cc_typeoffset;
+
+ Dwarf_Byte_Ptr cc_last_abbrev_ptr;
+ Dwarf_Hash_Table cc_abbrev_hash_table;
+ Dwarf_CU_Context cc_next;
+ /*unsigned char cc_offset_length; */
+ Dwarf_Bool cc_is_info; /* TRUE means context is
+ in debug_info, FALSE means is in debug_types. */
+};
+
+/* Consolidates section-specific data in one place.
+ Section is an Elf specific term, intended as a general
+ term (for non-Elf objects some code must synthesize the
+ values somehow).
+ Makes adding more section-data much simpler. */
+struct Dwarf_Section_s {
+ Dwarf_Small * dss_data;
+ Dwarf_Unsigned dss_size;
+ /* Some Elf sections have a non-zero dss_entrysize which
+ is the size in bytes of a table entry in the section.
+ Relocations and symbols are both in tables, so have a
+ non-zero entrysize. Object formats which do not care
+ about this should leave this field zero. */
+ Dwarf_Unsigned dss_entrysize;
+ Dwarf_Word dss_index;
+ /* dss_addr is the 'section address' which is only
+ non-zero for a GNU eh section.
+ Purpose: to handle DW_EH_PE_pcrel encoding. Leaving
+ it zero is fine for non-elf. */
+ Dwarf_Addr dss_addr;
+ Dwarf_Small dss_data_was_malloc;
+
+ /* For non-elf, leaving the following fields zero
+ will mean they are ignored. */
+ /* dss_link should be zero unless a section has a link
+ to another (sh_link). Used to access relocation data for
+ a section (and for symtab section, access its strtab). */
+ Dwarf_Word dss_link;
+ /* The following is used when reading .rela sections
+ (such sections appear in some .o files). */
+ Dwarf_Half dss_reloc_index; /* Zero means ignore the reloc fields. */
+ Dwarf_Small * dss_reloc_data;
+ Dwarf_Unsigned dss_reloc_size;
+ Dwarf_Unsigned dss_reloc_entrysize;
+ Dwarf_Addr dss_reloc_addr;
+ /* dss_reloc_symtab is the sh_link of a .rela to its .symtab, leave
+ it 0 if non-meaningful. */
+ Dwarf_Addr dss_reloc_symtab;
+ /* dss_reloc_link should be zero unless a reloc section has a link
+ to another (sh_link). Used to access the symtab for relocations
+ a section. */
+ Dwarf_Word dss_reloc_link;
+ /* Pointer to the elf symtab, used for elf .rela. Leave it 0
+ if not relevant. */
+ struct Dwarf_Section_s *dss_symtab;
+};
+
+/* Overview: if next_to_use== first, no error slots are used.
+ If next_to_use+1 (mod maxcount) == first the slots are all used
+*/
+struct Dwarf_Harmless_s {
+ unsigned dh_maxcount;
+ unsigned dh_next_to_use;
+ unsigned dh_first;
+ unsigned dh_errs_count;
+ char ** dh_errors;
+};
+
+/* Data needed seperately for debug_info and debug_types
+ as we may be reading both interspersed. */
+
+struct Dwarf_Debug_InfoTypes_s {
+ /* Context for the compilation_unit just read by a call to
+ dwarf_next_cu_header. **Updated by dwarf_next_cu_header in
+ dwarf_die_deliv.c */
+ Dwarf_CU_Context de_cu_context;
+ /* Points to linked list of CU Contexts for the CU's already read.
+ These are only CU's read by dwarf_next_cu_header(). */
+ Dwarf_CU_Context de_cu_context_list;
+ /* Points to the last CU Context added to the list by
+ dwarf_next_cu_header(). */
+ Dwarf_CU_Context de_cu_context_list_end;
+ /* This is the list of CU contexts read for dwarf_offdie(). These
+ may read ahead of dwarf_next_cu_header(). */
+ Dwarf_CU_Context de_offdie_cu_context;
+ Dwarf_CU_Context de_offdie_cu_context_end;
+
+ /* Offset of last byte of last CU read. */
+ Dwarf_Word de_last_offset;
+ /* de_last_di_info_ptr and de_last_die are used with
+ dwarf_siblingof, dwarf_child, and dwarf_validate_die_sibling.
+ dwarf_validate_die_sibling will not give meaningful results
+ if called inappropriately. */
+ Dwarf_Byte_Ptr de_last_di_ptr;
+ Dwarf_Die de_last_die;
+};
+typedef struct Dwarf_Debug_InfoTypes_s *Dwarf_Debug_InfoTypes;
+
+struct Dwarf_Debug_s {
+ /* All file access methods and support data
+ are hidden in this structure.
+ We get a pointer, callers control the lifetime of the
+ structure and contents. */
+ struct Dwarf_Obj_Access_Interface_s *de_obj_file;
+
+ Dwarf_Handler de_errhand;
+ Dwarf_Ptr de_errarg;
+
+ struct Dwarf_Debug_InfoTypes_s de_info_reading;
+ struct Dwarf_Debug_InfoTypes_s de_types_reading;
+
+ /* Number of bytes in the length, and offset field in various
+ .debug_* sections. It's not very meaningful, and is
+ only used in one 'approximate' calculation. */
+ Dwarf_Small de_length_size;
+
+ /* number of bytes in a pointer of the target in various .debug_
+ sections. 4 in 32bit, 8 in MIPS 64, ia64. */
+ Dwarf_Small de_pointer_size;
+
+ /* set at creation of a Dwarf_Debug to say if form_string should be
+ checked for valid length at every call. 0 means do the check.
+ non-zero means do not do the check. */
+ Dwarf_Small de_assume_string_in_bounds;
+
+ /* Dwarf_Alloc_Hdr_s structs used to manage chunks that are
+ malloc'ed for each allocation type for structs. */
+ struct Dwarf_Alloc_Hdr_s de_alloc_hdr[ALLOC_AREA_REAL_TABLE_MAX];
+#ifdef DWARF_SIMPLE_MALLOC
+ struct simple_malloc_record_s * de_simple_malloc_base;
+#endif
+
+
+ /* These fields are used to process debug_frame section. **Updated
+ by dwarf_get_fde_list in dwarf_frame.h */
+ /* Points to contiguous block of pointers to Dwarf_Cie_s structs. */
+ Dwarf_Cie *de_cie_data;
+ /* Count of number of Dwarf_Cie_s structs. */
+ Dwarf_Signed de_cie_count;
+ /* Keep eh (GNU) separate!. */
+ Dwarf_Cie *de_cie_data_eh;
+ Dwarf_Signed de_cie_count_eh;
+ /* Points to contiguous block of pointers to Dwarf_Fde_s structs. */
+ Dwarf_Fde *de_fde_data;
+ /* Count of number of Dwarf_Fde_s structs. */
+ Dwarf_Signed de_fde_count;
+ /* Keep eh (GNU) separate!. */
+ Dwarf_Fde *de_fde_data_eh;
+ Dwarf_Signed de_fde_count_eh;
+
+ struct Dwarf_Section_s de_debug_info;
+ struct Dwarf_Section_s de_debug_types;
+ struct Dwarf_Section_s de_debug_abbrev;
+ struct Dwarf_Section_s de_debug_line;
+ struct Dwarf_Section_s de_debug_loc;
+ struct Dwarf_Section_s de_debug_aranges;
+ struct Dwarf_Section_s de_debug_macinfo;
+ struct Dwarf_Section_s de_debug_pubnames;
+ struct Dwarf_Section_s de_debug_str;
+ struct Dwarf_Section_s de_debug_frame;
+
+ /* gnu: the g++ eh_frame section */
+ struct Dwarf_Section_s de_debug_frame_eh_gnu;
+
+ struct Dwarf_Section_s de_debug_pubtypes; /* DWARF3 .debug_pubtypes */
+
+ struct Dwarf_Section_s de_debug_funcnames;
+ struct Dwarf_Section_s de_debug_typenames; /* SGI IRIX extension essentially
+ identical to DWARF3 .debug_pubtypes. */
+ struct Dwarf_Section_s de_debug_varnames;
+ struct Dwarf_Section_s de_debug_weaknames;
+ struct Dwarf_Section_s de_debug_ranges;
+
+ /* For non-elf, simply leave the following two structs zeroed and
+ they will be ignored. */
+ struct Dwarf_Section_s de_elf_symtab;
+ struct Dwarf_Section_s de_elf_strtab;
+
+
+ void *(*de_copy_word) (void *, const void *, size_t);
+ unsigned char de_same_endian;
+ unsigned char de_elf_must_close; /* If non-zero, then
+ it was dwarf_init (not dwarf_elf_init)
+ so must elf_end() */
+
+ /* Default is DW_FRAME_INITIAL_VALUE from header. */
+ Dwarf_Half de_frame_rule_initial_value;
+
+ /* Default is DW_FRAME_LAST_REG_NUM. */
+ Dwarf_Half de_frame_reg_rules_entry_count;
+
+ Dwarf_Half de_frame_cfa_col_number;
+ Dwarf_Half de_frame_same_value_number;
+ Dwarf_Half de_frame_undefined_value_number;
+
+ unsigned char de_big_endian_object; /* Non-zero if big-endian
+ object opened. */
+
+ struct Dwarf_Harmless_s de_harmless_errors;
+};
+
+typedef struct Dwarf_Chain_s *Dwarf_Chain;
+struct Dwarf_Chain_s {
+ void *ch_item;
+ Dwarf_Chain ch_next;
+};
+
+
+#define CURRENT_VERSION_STAMP 2 /* DWARF2 */
+#define CURRENT_VERSION_STAMP3 3 /* DWARF3 */
+#define CURRENT_VERSION_STAMP4 4 /* DWARF4 */
+
+ /* Size of cu header version stamp field. */
+#define CU_VERSION_STAMP_SIZE sizeof(Dwarf_Half)
+
+ /* Size of cu header address size field. */
+#define CU_ADDRESS_SIZE_SIZE sizeof(Dwarf_Small)
+
+void *_dwarf_memcpy_swap_bytes(void *s1, const void *s2, size_t len);
+
+#define ORIGINAL_DWARF_OFFSET_SIZE 4
+#define DISTINGUISHED_VALUE 0xffffffff
+#define DISTINGUISHED_VALUE_OFFSET_SIZE 8
+
+/* We don't load the sections until they are needed. This function is
+ used to load the section. */
+int _dwarf_load_section(Dwarf_Debug,
+ struct Dwarf_Section_s *,
+ Dwarf_Error *);
diff --git a/libdwarf/dwarf_original_elf_init.c b/libdwarf/dwarf_original_elf_init.c
new file mode 100644
index 0000000..1de0af9
--- /dev/null
+++ b/libdwarf/dwarf_original_elf_init.c
@@ -0,0 +1,194 @@
+/*
+
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2008-2010 Arxan Technologies, Inc. All rights reserved.
+ Portions Copyright 2011 David Anderson. All rights reserved.
+
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include "dwarf_elf_access.h"
+
+#ifdef HAVE_ELF_H
+#include <elf.h>
+#endif
+#ifdef HAVE_LIBELF_H
+#include <libelf.h>
+#else
+#ifdef HAVE_LIBELF_LIBELF_H
+#include <libelf/libelf.h>
+#endif
+#endif
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define DWARF_DBG_ERROR(dbg,errval,retval) \
+ _dwarf_error(dbg, error, errval); return(retval);
+
+#define FALSE 0
+#define TRUE 1
+
+static int
+dwarf_elf_init_file_ownership(dwarf_elf_handle elf_file_pointer,
+ int libdwarf_owns_elf,
+ Dwarf_Unsigned access,
+ Dwarf_Handler errhand,
+ Dwarf_Ptr errarg,
+ Dwarf_Debug * ret_dbg,
+ Dwarf_Error * error);
+
+
+/* The basic dwarf initializer function for consumers using
+ libelf.
+ Return a libdwarf error code on error, return DW_DLV_OK
+ if this succeeds. */
+int
+dwarf_init(int fd,
+ Dwarf_Unsigned access,
+ Dwarf_Handler errhand,
+ Dwarf_Ptr errarg, Dwarf_Debug * ret_dbg, Dwarf_Error * error)
+{
+ struct stat fstat_buf;
+ dwarf_elf_handle elf_file_pointer = 0;
+ /* ELF_C_READ is a portable value */
+ Elf_Cmd what_kind_of_elf_read = ELF_C_READ;
+
+#if !defined(S_ISREG)
+#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
+#endif
+ if (fstat(fd, &fstat_buf) != 0) {
+ DWARF_DBG_ERROR(NULL, DW_DLE_FSTAT_ERROR, DW_DLV_ERROR);
+ }
+ if (!S_ISREG(fstat_buf.st_mode)) {
+ DWARF_DBG_ERROR(NULL, DW_DLE_FSTAT_MODE_ERROR, DW_DLV_ERROR);
+ }
+
+ if (access != DW_DLC_READ) {
+ DWARF_DBG_ERROR(NULL, DW_DLE_INIT_ACCESS_WRONG, DW_DLV_ERROR);
+ }
+
+ elf_version(EV_CURRENT);
+ /* Changed to mmap request per bug 281217. 6/95 */
+#ifdef HAVE_ELF_C_READ_MMAP
+ /* ELF_C_READ_MMAP is an SGI IRIX specific enum value from IRIX
+ libelf.h meaning read but use mmap */
+ what_kind_of_elf_read = ELF_C_READ_MMAP;
+#endif /* !HAVE_ELF_C_READ_MMAP */
+
+ elf_file_pointer = elf_begin(fd, what_kind_of_elf_read, 0);
+ if (elf_file_pointer == NULL) {
+ DWARF_DBG_ERROR(NULL, DW_DLE_ELF_BEGIN_ERROR, DW_DLV_ERROR);
+ }
+ return dwarf_elf_init_file_ownership(elf_file_pointer,
+ TRUE, access, errhand, errarg, ret_dbg, error);
+}
+
+/* An alternate dwarf setup call for consumers using
+ libelf.
+ When the caller has opened libelf already, so the
+ caller must free libelf. */
+int
+dwarf_elf_init(dwarf_elf_handle elf_file_pointer,
+ Dwarf_Unsigned access,
+ Dwarf_Handler errhand,
+ Dwarf_Ptr errarg,
+ Dwarf_Debug * ret_dbg, Dwarf_Error * error)
+{
+ return dwarf_elf_init_file_ownership(elf_file_pointer,
+ FALSE, access, errhand, errarg, ret_dbg, error);
+}
+
+
+/* Initialize the ELF object access for libdwarf. */
+static int
+dwarf_elf_init_file_ownership(dwarf_elf_handle elf_file_pointer,
+ int libdwarf_owns_elf,
+ Dwarf_Unsigned access,
+ Dwarf_Handler errhand,
+ Dwarf_Ptr errarg,
+ Dwarf_Debug * ret_dbg,
+ Dwarf_Error * error)
+{
+ /* ELF is no longer tied to libdwarf. */
+ Dwarf_Obj_Access_Interface *binary_interface = 0;
+ int res = DW_DLV_OK;
+ int err = 0;
+
+ if (access != DW_DLC_READ) {
+ DWARF_DBG_ERROR(NULL, DW_DLE_INIT_ACCESS_WRONG, DW_DLV_ERROR);
+ }
+
+ /* This allocates and fills in *binary_interface. */
+ res = dwarf_elf_object_access_init(
+ elf_file_pointer,
+ libdwarf_owns_elf,
+ &binary_interface,
+ &err);
+ if(res != DW_DLV_OK){
+ DWARF_DBG_ERROR(NULL, err, DW_DLV_ERROR);
+ }
+
+ /* This mallocs space and returns pointer thru ret_dbg,
+ saving the binary interface in 'ret-dbg' */
+ res = dwarf_object_init(binary_interface, errhand, errarg,
+ ret_dbg, error);
+ if(res != DW_DLV_OK){
+ dwarf_elf_object_access_finish(binary_interface);
+ }
+ return res;
+}
+
+
+/*
+ Frees all memory that was not previously freed
+ by dwarf_dealloc.
+ Aside from certain categories.
+
+ This is only applicable when dwarf_init() or dwarf_elf_init()
+ was used to init 'dbg'.
+*/
+int
+dwarf_finish(Dwarf_Debug dbg, Dwarf_Error * error)
+{
+ dwarf_elf_object_access_finish(dbg->de_obj_file);
+
+ return dwarf_object_finish(dbg, error);
+}
+
diff --git a/libdwarf/dwarf_print_lines.c b/libdwarf/dwarf_print_lines.c
new file mode 100644
index 0000000..263752b
--- /dev/null
+++ b/libdwarf/dwarf_print_lines.c
@@ -0,0 +1,736 @@
+/*
+
+ Copyright (C) 2000,2002,2004,2005,2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include <time.h>
+#include "dwarf_line.h"
+
+/* FIXME Need to add prologue_end epilogue_begin isa fields. */
+static void
+print_line_header(void)
+{
+ printf
+ (" s b e p e i d\n"
+ " t l s r p s i\n"
+ " m c e o i a s\n"
+ " section op col t k q l l c\n"
+ " offset code address file line umn ? ? ? ? ? \n");
+}
+
+/* FIXME: print new line values: prologue_end epilogue_begin isa */
+static void
+print_line_detail(char *prefix,
+ int opcode,
+ Dwarf_Unsigned address,
+ unsigned long file,
+ unsigned long line,
+ unsigned long column,
+ int is_stmt, int basic_block, int end_sequence,
+ int prologue_end, int epilogue_begin, int isa,
+ Dwarf_Unsigned discriminator)
+{
+ printf("%-15s %2d 0x%" DW_PR_XZEROS DW_PR_DUx " "
+ "%2lu %4lu %2lu %1d %1d %1d",
+ prefix,
+ (int) opcode,
+ (Dwarf_Unsigned) address,
+ (unsigned long) file,
+ (unsigned long) line,
+ (unsigned long) column,
+ (int) is_stmt, (int) basic_block, (int) end_sequence);
+ if(discriminator || prologue_end || epilogue_begin || isa) {
+ printf(" %1d", prologue_end);
+ printf(" %1d", epilogue_begin);
+ printf(" %1d", isa);
+ printf(" 0x%" DW_PR_DUx , discriminator);
+ }
+ printf("\n");
+}
+
+
+/* return DW_DLV_OK if ok. else DW_DLV_NO_ENTRY or DW_DLV_ERROR
+ If err_count_out is non-NULL, this is a special 'check'
+ call. */
+int
+_dwarf_internal_printlines(Dwarf_Die die, Dwarf_Error * error,
+int * err_count_out, int only_line_header)
+{
+ /* This pointer is used to scan the portion of the .debug_line
+ section for the current cu. */
+ Dwarf_Small *line_ptr = 0;
+ Dwarf_Small *orig_line_ptr = 0;
+
+ /* This points to the last byte of the .debug_line portion for the
+ current cu. */
+ Dwarf_Small *line_ptr_end = 0;
+
+ /* Pointer to a DW_AT_stmt_list attribute in case it exists in the
+ die. */
+ Dwarf_Attribute stmt_list_attr = 0;
+
+ /* Pointer to DW_AT_comp_dir attribute in die. */
+ Dwarf_Attribute comp_dir_attr = 0;
+
+ /* Pointer to name of compilation directory. */
+ Dwarf_Small *comp_dir = NULL;
+
+ /* Offset into .debug_line specified by a DW_AT_stmt_list
+ attribute. */
+ Dwarf_Unsigned line_offset = 0;
+
+ struct Line_Table_Prefix_s prefix;
+
+
+ /* These are the state machine state variables. */
+ Dwarf_Addr address = 0;
+ Dwarf_Word file = 1;
+ Dwarf_Word line = 1;
+ Dwarf_Word column = 0;
+ Dwarf_Bool is_stmt = false;
+ Dwarf_Bool basic_block = false;
+ Dwarf_Bool end_sequence = false;
+ Dwarf_Bool prologue_end = false;
+ Dwarf_Bool epilogue_begin = false;
+ Dwarf_Small isa = 0;
+ Dwarf_Unsigned op_index = 0;
+ Dwarf_Unsigned discriminator = 0;
+
+
+ Dwarf_Sword i=0;
+
+ /* This is the current opcode read from the statement program. */
+ Dwarf_Small opcode=0;
+
+
+ /* These variables are used to decode leb128 numbers. Leb128_num
+ holds the decoded number, and leb128_length is its length in
+ bytes. */
+ Dwarf_Word leb128_num=0;
+ Dwarf_Word leb128_length=0;
+ Dwarf_Sword advance_line=0;
+ Dwarf_Half attrform = 0;
+ /* This is the operand of the latest fixed_advance_pc extended
+ opcode. */
+ Dwarf_Half fixed_advance_pc=0;
+
+ /* In case there are wierd bytes 'after' the line table
+ prologue this lets us print something. This is a gcc
+ compiler bug and we expect the bytes count to be 12. */
+ Dwarf_Small* bogus_bytes_ptr = 0;
+ Dwarf_Unsigned bogus_bytes_count = 0;
+
+
+ /* The Dwarf_Debug this die belongs to. */
+ Dwarf_Debug dbg=0;
+ int resattr = DW_DLV_ERROR;
+ int lres = DW_DLV_ERROR;
+ int res = DW_DLV_ERROR;
+
+ /* ***** BEGIN CODE ***** */
+
+ if (error != NULL) {
+ *error = NULL;
+ }
+
+ CHECK_DIE(die, DW_DLV_ERROR);
+ dbg = die->di_cu_context->cc_dbg;
+
+ res = _dwarf_load_section(dbg, &dbg->de_debug_line,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ if (!dbg->de_debug_line.dss_size) {
+ return (DW_DLV_NO_ENTRY);
+ }
+
+
+ resattr = dwarf_attr(die, DW_AT_stmt_list, &stmt_list_attr, error);
+ if (resattr != DW_DLV_OK) {
+ return resattr;
+ }
+
+
+ /* The list of relevant FORMs is small.
+ DW_FORM_data4, DW_FORM_data8, DW_FORM_sec_offset
+ */
+ lres = dwarf_whatform(stmt_list_attr,&attrform,error);
+ if (lres != DW_DLV_OK) {
+ return lres;
+ }
+ if (attrform != DW_FORM_data4 && attrform != DW_FORM_data8 &&
+ attrform != DW_FORM_sec_offset ) {
+ _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
+ return (DW_DLV_ERROR);
+ }
+ lres = dwarf_global_formref(stmt_list_attr, &line_offset, error);
+ if (lres != DW_DLV_OK) {
+ return lres;
+ }
+
+ if (line_offset >= dbg->de_debug_line.dss_size) {
+ _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
+ return (DW_DLV_ERROR);
+ }
+ orig_line_ptr = dbg->de_debug_line.dss_data;
+ line_ptr = dbg->de_debug_line.dss_data + line_offset;
+ dwarf_dealloc(dbg, stmt_list_attr, DW_DLA_ATTR);
+
+ /* If die has DW_AT_comp_dir attribute, get the string that names
+ the compilation directory. */
+ resattr = dwarf_attr(die, DW_AT_comp_dir, &comp_dir_attr, error);
+ if (resattr == DW_DLV_ERROR) {
+ return resattr;
+ }
+ if (resattr == DW_DLV_OK) {
+ int cres = DW_DLV_ERROR;
+ char *cdir = 0;
+
+ cres = dwarf_formstring(comp_dir_attr, &cdir, error);
+ if (cres == DW_DLV_ERROR) {
+ return cres;
+ } else if (cres == DW_DLV_OK) {
+ comp_dir = (Dwarf_Small *) cdir;
+ }
+ }
+ if (resattr == DW_DLV_OK) {
+ dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR);
+ }
+
+ dwarf_init_line_table_prefix(&prefix);
+ {
+ Dwarf_Small *line_ptr_out = 0;
+ int dres = dwarf_read_line_table_prefix(dbg,
+ line_ptr,dbg->de_debug_line.dss_size - line_offset,
+ &line_ptr_out,
+ &prefix,
+ &bogus_bytes_ptr,
+ &bogus_bytes_count,
+ error,
+ err_count_out);
+ if (dres == DW_DLV_ERROR) {
+ dwarf_free_line_table_prefix(&prefix);
+ return dres;
+ }
+ if (dres == DW_DLV_NO_ENTRY) {
+ dwarf_free_line_table_prefix(&prefix);
+ return dres;
+ }
+ line_ptr_end = prefix.pf_line_ptr_end;
+ line_ptr = line_ptr_out;
+ }
+ if(only_line_header) {
+ /* Just checking for header errors, nothing more here.*/
+ dwarf_free_line_table_prefix(&prefix);
+ return DW_DLV_OK;
+ }
+
+ printf("total line info length %ld bytes, "
+ "line offset 0x%" DW_PR_XZEROS DW_PR_DUx " %" DW_PR_DSd "\n",
+ (long) prefix.pf_total_length,
+ (Dwarf_Unsigned) line_offset, (Dwarf_Signed) line_offset);
+ printf("line table version %d\n",(int) prefix.pf_version);
+ printf("line table length field length %d prologue length %d\n",
+ (int)prefix.pf_length_field_length,
+ (int)prefix.pf_prologue_length);
+ printf("compilation_directory %s\n",
+ comp_dir ? ((char *) comp_dir) : "");
+
+ printf(" min instruction length %d\n",
+ (int) prefix.pf_minimum_instruction_length);
+ printf(" default is stmt %d\n", (int) prefix.pf_default_is_stmt);
+ printf(" line base %d\n", (int) prefix.pf_line_base);
+ printf(" line_range %d\n", (int) prefix.pf_line_range);
+ printf(" opcode base %d\n", (int) prefix.pf_opcode_base);
+ printf(" standard opcode count %d\n", (int) prefix.pf_std_op_count);
+
+ for (i = 1; i < prefix.pf_opcode_base; i++) {
+ printf(" opcode[%2d] length %d\n", (int) i,
+ (int) prefix.pf_opcode_length_table[i - 1]);
+ }
+ printf(" include directories count %d\n",
+ (int) prefix.pf_include_directories_count);
+ for (i = 0; i < prefix.pf_include_directories_count; ++i) {
+ printf(" include dir[%d] %s\n",
+ (int) i, prefix.pf_include_directories[i]);
+ }
+ printf(" files count %d\n",
+ (int) prefix.pf_files_count);
+
+ for (i = 0; i < prefix.pf_files_count; ++i) {
+ struct Line_Table_File_Entry_s *lfile =
+ prefix.pf_line_table_file_entries + i;
+ Dwarf_Unsigned tlm2 = lfile->lte_last_modification_time;
+ Dwarf_Unsigned di = lfile->lte_directory_index;
+ Dwarf_Unsigned fl = lfile->lte_length_of_file;
+
+ printf(" file[%d] %s (file-number: %d) \n",
+ (int) i, (char *) lfile->lte_filename,
+ (int)(i+1));
+ printf(" dir index %d\n", (int) di);
+ {
+ time_t tt = (time_t) tlm2;
+
+ /* ctime supplies newline */
+ printf(" last time 0x%x %s",
+ (unsigned) tlm2, ctime(&tt));
+ }
+ printf(" file length %ld 0x%lx\n",
+ (long) fl, (unsigned long) fl);
+
+ }
+
+
+ {
+ Dwarf_Unsigned offset = 0;
+ if(bogus_bytes_count > 0) {
+ Dwarf_Unsigned wcount = bogus_bytes_count;
+ Dwarf_Unsigned boffset = bogus_bytes_ptr - orig_line_ptr;
+ printf("*** DWARF CHECK: the line table prologue header_length "
+ " is %" DW_PR_DUu " too high, we pretend it is smaller."
+ "Section offset: 0x%" DW_PR_XZEROS DW_PR_DUx
+ " (%" DW_PR_DUu ") ***\n",
+ wcount, boffset,boffset);
+ *err_count_out += 1;
+ }
+ offset = line_ptr - orig_line_ptr;
+ printf(" statement prog offset in section: 0x%"
+ DW_PR_XZEROS DW_PR_DUx " (%" DW_PR_DUu ")\n",
+ offset, offset);
+ }
+
+ /* Initialize the part of the state machine dependent on the
+ prefix. */
+ is_stmt = prefix.pf_default_is_stmt;
+
+ print_line_header();
+ /* Start of statement program. */
+ while (line_ptr < line_ptr_end) {
+ int type = 0;
+
+ printf(" [0x%06" DW_PR_DSx "] ",
+ (Dwarf_Signed) (line_ptr - orig_line_ptr));
+ opcode = *(Dwarf_Small *) line_ptr;
+ line_ptr++;
+ /* 'type' is the output */
+ WHAT_IS_OPCODE(type, opcode, prefix.pf_opcode_base,
+ prefix.pf_opcode_length_table, line_ptr,
+ prefix.pf_std_op_count);
+ if (type == LOP_DISCARD) {
+ int oc = 0;
+ int opcnt = prefix.pf_opcode_length_table[opcode];
+
+ printf("*** DWARF CHECK: DISCARD standard opcode %d "
+ "with %d operands: "
+ "not understood.", opcode, opcnt);
+ *err_count_out += 1;
+ for (oc = 0; oc < opcnt; oc++) {
+ /* Read and discard operands we don't
+ understand.
+ Arbitrary choice of unsigned read.
+ Signed read would work as well. */
+ Dwarf_Unsigned utmp2 = 0;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ printf(" %" DW_PR_DUu
+ " (0x%" DW_PR_XZEROS DW_PR_DUx ")",
+ (Dwarf_Unsigned) utmp2,
+ (Dwarf_Unsigned) utmp2);
+ }
+ printf("***\n");
+ /* Do nothing, necessary ops done */
+ } else if (type == LOP_SPECIAL) {
+ /* This op code is a special op in the object, no matter
+ that it might fall into the standard op range in this
+ compile Thatis, these are special opcodes between
+ special_opcode_base and MAX_LINE_OP_CODE. (including
+ special_opcode_base and MAX_LINE_OP_CODE) */
+ char special[50];
+ Dwarf_Unsigned operation_advance = 0;
+ unsigned origop = opcode;
+
+ opcode = opcode - prefix.pf_opcode_base;
+ operation_advance = (opcode / prefix.pf_line_range);
+ if(prefix.pf_maximum_ops_per_instruction < 2) {
+ address = address + (prefix.pf_minimum_instruction_length *
+ operation_advance);
+ } else {
+ address = address + (prefix.pf_minimum_instruction_length *
+ ((op_index + operation_advance)/
+ prefix.pf_maximum_ops_per_instruction));
+ op_index = (op_index +operation_advance)%
+ prefix.pf_maximum_ops_per_instruction;
+ }
+ line = line + prefix.pf_line_base +
+ opcode % prefix.pf_line_range;
+ sprintf(special, "Specialop %3u", origop);
+ print_line_detail(special,
+ opcode, address, (int) file, line, column,
+ is_stmt, basic_block, end_sequence,
+ prologue_end, epilogue_begin, isa,discriminator);
+ basic_block = false;
+ prologue_end = false;
+ epilogue_begin = false;
+ discriminator = 0;
+ } else if (type == LOP_STANDARD) {
+ switch (opcode) {
+
+ case DW_LNS_copy:{
+ print_line_detail("DW_LNS_copy",
+ opcode, address, file, line,
+ column, is_stmt, basic_block,
+ end_sequence, prologue_end,
+ epilogue_begin, isa,discriminator);
+ basic_block = false;
+ prologue_end = false;
+ epilogue_begin = false;
+ discriminator = 0;
+ }
+ break;
+
+ case DW_LNS_advance_pc:{
+ Dwarf_Unsigned utmp2 = 0;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ printf("DW_LNS_advance_pc val %"
+ DW_PR_DSd " 0x%"
+ DW_PR_XZEROS DW_PR_DUx "\n",
+ (Dwarf_Signed) (Dwarf_Word) utmp2,
+ (Dwarf_Unsigned) (Dwarf_Word) utmp2);
+ leb128_num = (Dwarf_Word) utmp2;
+ address = address +
+ prefix.pf_minimum_instruction_length * leb128_num;
+ }
+ break;
+ case DW_LNS_advance_line:{
+ Dwarf_Signed stmp = 0;
+
+ DECODE_LEB128_SWORD(line_ptr, stmp);
+ advance_line = (Dwarf_Sword) stmp;
+ printf("DW_LNS_advance_line val %" DW_PR_DSd " 0x%"
+ DW_PR_XZEROS DW_PR_DSx "\n",
+ (Dwarf_Signed) advance_line,
+ (Dwarf_Signed) advance_line);
+ line = line + advance_line;
+ }
+ break;
+
+ case DW_LNS_set_file:{
+ Dwarf_Unsigned utmp2 = 0;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ file = (Dwarf_Word) utmp2;
+ printf("DW_LNS_set_file %ld\n", (long) file);
+ }
+ break;
+ case DW_LNS_set_column:{
+ Dwarf_Unsigned utmp2 = 0;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ column = (Dwarf_Word) utmp2;
+ printf("DW_LNS_set_column val %" DW_PR_DSd " 0x%"
+ DW_PR_XZEROS DW_PR_DSx "\n",
+ (Dwarf_Signed) column, (Dwarf_Signed) column);
+ }
+ break;
+ case DW_LNS_negate_stmt:{
+ is_stmt = !is_stmt;
+ printf("DW_LNS_negate_stmt\n");
+ }
+ break;
+ case DW_LNS_set_basic_block:{
+ printf("DW_LNS_set_basic_block\n");
+ basic_block = true;
+ }
+ break;
+
+ case DW_LNS_const_add_pc:{
+ opcode = MAX_LINE_OP_CODE - prefix.pf_opcode_base;
+ if(prefix.pf_maximum_ops_per_instruction < 2) {
+ Dwarf_Unsigned operation_advance =
+ (opcode / prefix.pf_line_range);
+ address = address +
+ prefix.pf_minimum_instruction_length *
+ operation_advance;
+ } else {
+ Dwarf_Unsigned operation_advance =
+ (opcode / prefix.pf_line_range);
+ address = address + prefix.pf_minimum_instruction_length *
+ ((op_index + operation_advance)/
+ prefix.pf_maximum_ops_per_instruction);
+ op_index = (op_index +operation_advance)%
+ prefix.pf_maximum_ops_per_instruction;
+ }
+
+ printf("DW_LNS_const_add_pc new address 0x%"
+ DW_PR_XZEROS DW_PR_DSx "\n",
+ (Dwarf_Signed) address);
+ }
+ break;
+ case DW_LNS_fixed_advance_pc:{
+ READ_UNALIGNED(dbg, fixed_advance_pc, Dwarf_Half,
+ line_ptr, sizeof(Dwarf_Half));
+ line_ptr += sizeof(Dwarf_Half);
+ address = address + fixed_advance_pc;
+ printf("DW_LNS_fixed_advance_pc val %" DW_PR_DSd
+ " 0x%" DW_PR_XZEROS DW_PR_DSx
+ " new address 0x%" DW_PR_XZEROS DW_PR_DSx "\n",
+ (Dwarf_Signed) fixed_advance_pc,
+ (Dwarf_Signed) fixed_advance_pc,
+ (Dwarf_Signed) address);
+ op_index = 0;
+ }
+ break;
+ case DW_LNS_set_prologue_end:{
+ prologue_end = true;
+ printf("DW_LNS_set_prologue_end set true.\n");
+ }
+ break;
+ /* New in DWARF3 */
+ case DW_LNS_set_epilogue_begin:{
+ epilogue_begin = true;
+ printf("DW_LNS_set_epilogue_begin set true.\n");
+ }
+ break;
+
+ /* New in DWARF3 */
+ case DW_LNS_set_isa:{
+ Dwarf_Unsigned utmp2;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ isa = utmp2;
+ printf("DW_LNS_set_isa new value 0x%"
+ DW_PR_XZEROS DW_PR_DUx ".\n",
+ (Dwarf_Unsigned) utmp2);
+ if (isa != utmp2) {
+ /* The value of the isa did not fit in our
+ local so we record it wrong. declare an
+ error. */
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_NUM_OPERANDS_BAD);
+ return (DW_DLV_ERROR);
+ }
+ }
+ break;
+ } /* end switch */
+ } else if (type == LOP_EXTENDED) {
+ Dwarf_Unsigned utmp3 = 0;
+ Dwarf_Word instr_length = 0;
+ Dwarf_Small ext_opcode = 0;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp3);
+ instr_length = (Dwarf_Word) utmp3;
+ ext_opcode = *(Dwarf_Small *) line_ptr;
+ line_ptr++;
+ switch (ext_opcode) {
+
+ case DW_LNE_end_sequence:{
+ end_sequence = true;
+
+ print_line_detail("DW_LNE_end_sequence extended",
+ opcode, address, file, line,
+ column, is_stmt, basic_block,
+ end_sequence, prologue_end,
+ epilogue_begin, isa,discriminator);
+
+ address = 0;
+ file = 1;
+ line = 1;
+ column = 0;
+ is_stmt = prefix.pf_default_is_stmt;
+ basic_block = false;
+ end_sequence = false;
+ prologue_end = false;
+ epilogue_begin = false;
+ isa = 0;
+ discriminator = 0;
+ op_index = 0;
+ }
+ break;
+ case DW_LNE_set_address:{
+ READ_UNALIGNED(dbg, address, Dwarf_Addr,
+ line_ptr,
+ die->di_cu_context->cc_address_size);
+
+ line_ptr += die->di_cu_context->cc_address_size;
+ printf("DW_LNE_set_address address 0x%"
+ DW_PR_XZEROS DW_PR_DUx "\n",
+ (Dwarf_Unsigned) address);
+
+ op_index = 0;
+ }
+ break;
+ case DW_LNE_define_file:{
+ Dwarf_Unsigned di = 0;
+ Dwarf_Unsigned tlm = 0;
+ Dwarf_Unsigned fl = 0;
+
+ Dwarf_Small *fn = (Dwarf_Small *) line_ptr;
+ line_ptr = line_ptr + strlen((char *) line_ptr) + 1;
+ di = _dwarf_decode_u_leb128(line_ptr,
+ &leb128_length);
+ line_ptr = line_ptr + leb128_length;
+ tlm = _dwarf_decode_u_leb128(line_ptr,
+ &leb128_length);
+ line_ptr = line_ptr + leb128_length;
+ fl = _dwarf_decode_u_leb128(line_ptr,
+ &leb128_length);
+ line_ptr = line_ptr + leb128_length;
+
+ printf("DW_LNE_define_file %s \n", fn);
+ printf(" dir index %d\n", (int) di);
+ {
+ time_t tt3 = (time_t) tlm;
+
+ /* ctime supplies newline */
+ printf(" last time 0x%x %s",
+ (unsigned) tlm, ctime(&tt3));
+ }
+ printf(" file length %ld 0x%lx\n",
+ (long) fl, (unsigned long) fl);
+
+ }
+ break;
+ case DW_LNE_set_discriminator:{
+ /* new in DWARF4 */
+ Dwarf_Unsigned utmp2 = 0;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ discriminator = (Dwarf_Word) utmp2;
+ printf("DW_LNE_set_discriminator 0x%"
+ DW_PR_XZEROS DW_PR_DUx "\n",utmp2);
+ }
+ break;
+
+ default:{
+ /* This is an extended op code we do not know about,
+ other than we know now many bytes it is
+ (and the op code and the bytes of operand). */
+
+ Dwarf_Unsigned remaining_bytes = instr_length -1;
+ if(instr_length < 1 || remaining_bytes > DW_LNE_LEN_MAX) {
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_EXT_OPCODE_BAD);
+ return (DW_DLV_ERROR);
+ }
+ printf("DW_LNE extended op 0x%x ",ext_opcode);
+ printf("Bytecount: %" DW_PR_DUu , (Dwarf_Unsigned)instr_length);
+ if(remaining_bytes > 0) {
+ printf(" linedata: 0x");
+ while (remaining_bytes > 0) {
+ printf("%02x",(unsigned char)(*(line_ptr)));
+ line_ptr++;
+ remaining_bytes--;
+ }
+ }
+ printf("\n");
+ }
+ break;
+ } /* Dnd switch */
+
+ }
+ }
+
+ dwarf_free_line_table_prefix(&prefix);
+ return (DW_DLV_OK);
+}
+
+/* This is support for dwarfdump: making it possible
+ for clients wanting line detail info on stdout
+ to get that detail without including internal libdwarf
+ header information.
+ Caller passes in compilation unit DIE.
+ The _dwarf_ version is obsolete (though supported for
+ compatibility).
+ The dwarf_ version is preferred.
+ The functions are intentionally identical: having
+ _dwarf_print_lines call dwarf_print_lines might
+ better emphasize they are intentionally identical, but
+ that seemed slightly silly given how short the functions are.
+ Interface adds error_count (output value) February 2009. */
+int
+dwarf_print_lines(Dwarf_Die die, Dwarf_Error * error,int *error_count)
+{
+ int only_line_header = 0;
+ int res = _dwarf_internal_printlines(die, error,
+ error_count,
+ only_line_header);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ return res;
+}
+int
+_dwarf_print_lines(Dwarf_Die die, Dwarf_Error * error)
+{
+ int only_line_header = 0;
+ int err_count = 0;
+ int res = _dwarf_internal_printlines(die, error,
+ &err_count,
+ only_line_header);
+ /* No way to get error count back in this interface */
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ return res;
+}
+
+/* The check is in case we are not printing full line data,
+ this gets some of the issues noted with .debug_line,
+ but not all. Call dwarf_print_lines() to get all issues.
+ Intended for apps like dwarfdump.
+*/
+void
+dwarf_check_lineheader(Dwarf_Die die, int *err_count_out)
+{
+ Dwarf_Error err;
+ int only_line_header = 1;
+ _dwarf_internal_printlines(die, &err,err_count_out,
+ only_line_header);
+ return;
+}
+
diff --git a/libdwarf/dwarf_pubtypes.c b/libdwarf/dwarf_pubtypes.c
new file mode 100644
index 0000000..adc1ce3
--- /dev/null
+++ b/libdwarf/dwarf_pubtypes.c
@@ -0,0 +1,142 @@
+/*
+
+ Copyright (C) 2000,2002,2004,2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+/* Reads DWARF3 .debug_pubtypes section. */
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include "dwarf_types.h"
+#include "dwarf_global.h"
+
+int
+dwarf_get_pubtypes(Dwarf_Debug dbg,
+ Dwarf_Type ** types,
+ Dwarf_Signed * ret_type_count, Dwarf_Error * error)
+{
+ int res = _dwarf_load_section(dbg, &dbg->de_debug_pubtypes,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ if (!dbg->de_debug_pubtypes.dss_size) {
+ return (DW_DLV_NO_ENTRY);
+ }
+
+
+ return _dwarf_internal_get_pubnames_like_data(dbg,
+ dbg->de_debug_pubtypes.dss_data,
+ dbg->de_debug_pubtypes.dss_size,
+ (Dwarf_Global **) types, /* Type punning for sections
+ with identical format. */
+ ret_type_count, error,
+ DW_DLA_PUBTYPES_CONTEXT,
+ DW_DLA_GLOBAL, /* We don't have DW_DLA_PUBTYPES,
+ so use DW_DLA_GLOBAL. */
+ DW_DLE_DEBUG_PUBTYPES_LENGTH_BAD,
+ DW_DLE_DEBUG_PUBTYPES_VERSION_ERROR);
+}
+
+/* Deallocating fully requires deallocating the list
+ and all entries. But some internal data is
+ not exposed, so we need a function with internal knowledge.
+*/
+
+void
+dwarf_pubtypes_dealloc(Dwarf_Debug dbg, Dwarf_Type * dwgl,
+ Dwarf_Signed count)
+{
+ _dwarf_internal_globals_dealloc(dbg,
+ (Dwarf_Global *) dwgl,
+ count,
+ DW_DLA_PUBTYPES_CONTEXT,
+ DW_DLA_GLOBAL, /* We don't have DW_DLA_PUBTYPES,
+ so use DW_DLA_GLOBAL. */
+ DW_DLA_LIST);
+ return;
+}
+
+
+
+int
+dwarf_pubtypename(Dwarf_Type type_in, char **ret_name,
+ Dwarf_Error * error)
+{
+ Dwarf_Global type = (Dwarf_Global) type_in;
+ if (type == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_TYPE_NULL);
+ return (DW_DLV_ERROR);
+ }
+ *ret_name = (char *) (type->gl_name);
+ return DW_DLV_OK;
+}
+
+
+int
+dwarf_pubtype_type_die_offset(Dwarf_Type type_in,
+ Dwarf_Off * ret_offset,
+ Dwarf_Error * error)
+{
+ Dwarf_Global type = (Dwarf_Global) type_in;
+
+ return dwarf_global_die_offset(type, ret_offset, error);
+}
+
+
+int
+dwarf_pubtype_cu_offset(Dwarf_Type type_in,
+ Dwarf_Off * ret_offset, Dwarf_Error * error)
+{
+ Dwarf_Global type = (Dwarf_Global) type_in;
+
+ return dwarf_global_cu_offset(type, ret_offset, error);
+
+}
+
+
+int
+dwarf_pubtype_name_offsets(Dwarf_Type type_in,
+ char **returned_name,
+ Dwarf_Off * die_offset,
+ Dwarf_Off * cu_die_offset,
+ Dwarf_Error * error)
+{
+ Dwarf_Global type = (Dwarf_Global) type_in;
+
+ return dwarf_global_name_offsets(type,
+ returned_name,
+ die_offset, cu_die_offset, error);
+}
diff --git a/libdwarf/dwarf_query.c b/libdwarf/dwarf_query.c
new file mode 100644
index 0000000..0992a90
--- /dev/null
+++ b/libdwarf/dwarf_query.c
@@ -0,0 +1,856 @@
+/*
+
+ Copyright (C) 2000,2002,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include "dwarf_die_deliv.h"
+
+/* This is normally reliable.
+But not always.
+If different compilation
+units have different address sizes
+this may not give the correct value in all contexts.
+If the Elf offset size != address_size
+(for example if address_size = 4 but recorded in elf64 object)
+this may not give the correct value in all contexts.
+*/
+int
+dwarf_get_address_size(Dwarf_Debug dbg,
+ Dwarf_Half * ret_addr_size, Dwarf_Error * error)
+{
+ Dwarf_Half address_size = 0;
+
+ if (dbg == 0) {
+ _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+ address_size = dbg->de_pointer_size;
+ *ret_addr_size = address_size;
+ return DW_DLV_OK;
+}
+
+/* This will be correct in all contexts where the
+ CU context of a DIE is known.
+*/
+int
+dwarf_get_die_address_size(Dwarf_Die die,
+ Dwarf_Half * ret_addr_size, Dwarf_Error * error)
+{
+ Dwarf_Half address_size = 0;
+ CHECK_DIE(die, DW_DLV_ERROR);
+ address_size = die->di_cu_context->cc_address_size;
+ *ret_addr_size = address_size;
+ return DW_DLV_OK;
+}
+
+int
+dwarf_dieoffset(Dwarf_Die die,
+ Dwarf_Off * ret_offset, Dwarf_Error * error)
+{
+ Dwarf_Small *dataptr = 0;
+ Dwarf_Debug dbg = 0;
+
+ CHECK_DIE(die, DW_DLV_ERROR);
+ dbg = die->di_cu_context->cc_dbg;
+ dataptr = die->di_is_info? dbg->de_debug_info.dss_data:
+ dbg->de_debug_types.dss_data;
+
+ *ret_offset = (die->di_debug_ptr - dataptr);
+ return DW_DLV_OK;
+}
+
+
+/* This function returns the offset of
+ the die relative to the start of its
+ compilation-unit rather than .debug_info.
+ Returns DW_DLV_ERROR on error. */
+int
+dwarf_die_CU_offset(Dwarf_Die die,
+ Dwarf_Off * cu_off, Dwarf_Error * error)
+{
+ Dwarf_CU_Context cu_context = 0;
+ Dwarf_Small *dataptr = 0;
+ Dwarf_Debug dbg = 0;
+
+ CHECK_DIE(die, DW_DLV_ERROR);
+ cu_context = die->di_cu_context;
+ dbg = die->di_cu_context->cc_dbg;
+ dataptr = die->di_is_info? dbg->de_debug_info.dss_data:
+ dbg->de_debug_types.dss_data;
+
+ *cu_off = (die->di_debug_ptr - dataptr - cu_context->cc_debug_offset);
+ return DW_DLV_OK;
+}
+
+/* A common function to get both offsets (local and global) */
+int
+dwarf_die_offsets(Dwarf_Die die,
+ Dwarf_Off *off,
+ Dwarf_Off *cu_off,
+ Dwarf_Error *error)
+{
+ *off = 0;
+ *cu_off = 0;
+ if (DW_DLV_OK == dwarf_dieoffset(die,off,error) &&
+ DW_DLV_OK == dwarf_die_CU_offset(die,cu_off,error)) {
+ return DW_DLV_OK;
+ }
+ return DW_DLV_ERROR;
+}
+
+/* This function returns the global offset
+ (meaning the section offset) and length of
+ the CU that this die is a part of.
+ Used for correctness checking by dwarfdump. */
+int
+dwarf_die_CU_offset_range(Dwarf_Die die,
+ Dwarf_Off * cu_off,
+ Dwarf_Off * cu_length,
+ Dwarf_Error * error)
+{
+ Dwarf_CU_Context cu_context = 0;
+
+ CHECK_DIE(die, DW_DLV_ERROR);
+ cu_context = die->di_cu_context;
+
+ *cu_off = cu_context->cc_debug_offset;
+ *cu_length = cu_context->cc_length + cu_context->cc_length_size
+ + cu_context->cc_extension_size;
+ return DW_DLV_OK;
+}
+
+
+
+int
+dwarf_tag(Dwarf_Die die, Dwarf_Half * tag, Dwarf_Error * error)
+{
+ CHECK_DIE(die, DW_DLV_ERROR);
+ *tag = (die->di_abbrev_list->ab_tag);
+ return DW_DLV_OK;
+}
+
+
+int
+dwarf_attrlist(Dwarf_Die die,
+ Dwarf_Attribute ** attrbuf,
+ Dwarf_Signed * attrcnt, Dwarf_Error * error)
+{
+ Dwarf_Word attr_count = 0;
+ Dwarf_Word i = 0;
+ Dwarf_Half attr = 0;
+ Dwarf_Half attr_form = 0;
+ Dwarf_Byte_Ptr abbrev_ptr = 0;
+ Dwarf_Abbrev_List abbrev_list = 0;
+ Dwarf_Attribute new_attr = 0;
+ Dwarf_Attribute head_attr = NULL;
+ Dwarf_Attribute curr_attr = NULL;
+ Dwarf_Attribute *attr_ptr = 0;
+ Dwarf_Debug dbg = 0;
+ Dwarf_Byte_Ptr info_ptr = 0;
+
+ CHECK_DIE(die, DW_DLV_ERROR);
+ dbg = die->di_cu_context->cc_dbg;
+
+ abbrev_list = _dwarf_get_abbrev_for_code(die->di_cu_context,
+ die->di_abbrev_list->ab_code);
+ if (abbrev_list == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_DIE_ABBREV_BAD);
+ return (DW_DLV_ERROR);
+ }
+ abbrev_ptr = abbrev_list->ab_abbrev_ptr;
+
+ info_ptr = die->di_debug_ptr;
+ SKIP_LEB128_WORD(info_ptr);
+
+ do {
+ Dwarf_Unsigned utmp2;
+
+ DECODE_LEB128_UWORD(abbrev_ptr, utmp2);
+ attr = (Dwarf_Half) utmp2;
+ DECODE_LEB128_UWORD(abbrev_ptr, utmp2);
+ attr_form = (Dwarf_Half) utmp2;
+
+ if (attr != 0) {
+ new_attr =
+ (Dwarf_Attribute) _dwarf_get_alloc(dbg, DW_DLA_ATTR, 1);
+ if (new_attr == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ new_attr->ar_attribute = attr;
+ new_attr->ar_attribute_form_direct = attr_form;
+ new_attr->ar_attribute_form = attr_form;
+ if (attr_form == DW_FORM_indirect) {
+ Dwarf_Unsigned utmp6;
+
+ /* DECODE_LEB128_UWORD does info_ptr update */
+ DECODE_LEB128_UWORD(info_ptr, utmp6);
+ attr_form = (Dwarf_Half) utmp6;
+ new_attr->ar_attribute_form = attr_form;
+ }
+ new_attr->ar_cu_context = die->di_cu_context;
+ new_attr->ar_debug_ptr = info_ptr;
+ new_attr->ar_die = die;
+ {
+ Dwarf_Unsigned sov = _dwarf_get_size_of_val(dbg,
+ attr_form,
+ die->di_cu_context->cc_address_size,
+ info_ptr,
+ die->di_cu_context->cc_length_size);
+ info_ptr += sov;
+ }
+
+
+ if (head_attr == NULL)
+ head_attr = curr_attr = new_attr;
+ else {
+ curr_attr->ar_next = new_attr;
+ curr_attr = new_attr;
+ }
+ attr_count++;
+ }
+ } while (attr != 0 || attr_form != 0);
+
+ if (attr_count == 0) {
+ *attrbuf = NULL;
+ *attrcnt = 0;
+ return (DW_DLV_NO_ENTRY);
+ }
+
+ attr_ptr = (Dwarf_Attribute *)
+ _dwarf_get_alloc(dbg, DW_DLA_LIST, attr_count);
+ if (attr_ptr == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ curr_attr = head_attr;
+ for (i = 0; i < attr_count; i++) {
+ *(attr_ptr + i) = curr_attr;
+ curr_attr = curr_attr->ar_next;
+ }
+
+ *attrbuf = attr_ptr;
+ *attrcnt = attr_count;
+ return (DW_DLV_OK);
+}
+
+
+/*
+ This function takes a die, and an attr, and returns
+ a pointer to the start of the value of that attr in
+ the given die in the .debug_info section. The form
+ is returned in *attr_form.
+
+ Returns NULL on error, or if attr is not found.
+ However, *attr_form is 0 on error, and positive
+ otherwise.
+*/
+static Dwarf_Byte_Ptr
+_dwarf_get_value_ptr(Dwarf_Die die,
+ Dwarf_Half attr, Dwarf_Half * attr_form)
+{
+ Dwarf_Byte_Ptr abbrev_ptr = 0;
+ Dwarf_Abbrev_List abbrev_list;
+ Dwarf_Half curr_attr = 0;
+ Dwarf_Half curr_attr_form = 0;
+ Dwarf_Byte_Ptr info_ptr = 0;
+
+ abbrev_list = _dwarf_get_abbrev_for_code(die->di_cu_context,
+ die->di_abbrev_list->ab_code);
+ if (abbrev_list == NULL) {
+ *attr_form = 0;
+ return (NULL);
+ }
+ abbrev_ptr = abbrev_list->ab_abbrev_ptr;
+
+ info_ptr = die->di_debug_ptr;
+ SKIP_LEB128_WORD(info_ptr);
+
+ do {
+ Dwarf_Unsigned utmp3;
+
+ DECODE_LEB128_UWORD(abbrev_ptr, utmp3);
+ curr_attr = (Dwarf_Half) utmp3;
+ DECODE_LEB128_UWORD(abbrev_ptr, utmp3);
+ curr_attr_form = (Dwarf_Half) utmp3;
+ if (curr_attr_form == DW_FORM_indirect) {
+ Dwarf_Unsigned utmp6;
+
+ /* DECODE_LEB128_UWORD updates info_ptr */
+ DECODE_LEB128_UWORD(info_ptr, utmp6);
+ curr_attr_form = (Dwarf_Half) utmp6;
+ }
+
+ if (curr_attr == attr) {
+ *attr_form = curr_attr_form;
+ return (info_ptr);
+ }
+
+ info_ptr += _dwarf_get_size_of_val(die->di_cu_context->cc_dbg,
+ curr_attr_form,
+ die->di_cu_context->cc_address_size,
+ info_ptr,
+ die->di_cu_context->cc_length_size);
+ } while (curr_attr != 0 || curr_attr_form != 0);
+
+ *attr_form = 1;
+ return (NULL);
+}
+
+
+int
+dwarf_diename(Dwarf_Die die, char **ret_name, Dwarf_Error * error)
+{
+ Dwarf_Half attr_form = 0;
+ Dwarf_Debug dbg = 0;
+ Dwarf_Byte_Ptr info_ptr = 0;
+ Dwarf_Unsigned string_offset = 0;
+ int res = DW_DLV_ERROR;
+
+ CHECK_DIE(die, DW_DLV_ERROR);
+
+ info_ptr = _dwarf_get_value_ptr(die, DW_AT_name, &attr_form);
+ if (info_ptr == NULL) {
+ if (attr_form == 0) {
+ _dwarf_error(die->di_cu_context->cc_dbg, error,
+ DW_DLE_DIE_BAD);
+ return (DW_DLV_ERROR);
+ }
+ return DW_DLV_NO_ENTRY;
+ }
+
+ if (attr_form == DW_FORM_string) {
+ *ret_name = (char *) (info_ptr);
+ return DW_DLV_OK;
+ }
+
+ dbg = die->di_cu_context->cc_dbg;
+ if (attr_form != DW_FORM_strp) {
+ _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ READ_UNALIGNED(dbg, string_offset, Dwarf_Unsigned,
+ info_ptr, die->di_cu_context->cc_length_size);
+
+ if (string_offset >= dbg->de_debug_str.dss_size) {
+ _dwarf_error(dbg, error, DW_DLE_STRING_OFFSET_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ res = _dwarf_load_section(dbg, &dbg->de_debug_str,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ if (!dbg->de_debug_str.dss_size) {
+ return (DW_DLV_NO_ENTRY);
+ }
+
+ *ret_name = (char *) (dbg->de_debug_str.dss_data + string_offset);
+ return DW_DLV_OK;
+}
+
+
+int
+dwarf_hasattr(Dwarf_Die die,
+ Dwarf_Half attr,
+ Dwarf_Bool * return_bool, Dwarf_Error * error)
+{
+ Dwarf_Half attr_form = 0;
+
+ CHECK_DIE(die, DW_DLV_ERROR);
+
+ if (_dwarf_get_value_ptr(die, attr, &attr_form) == NULL) {
+ if (attr_form == 0) {
+ _dwarf_error(die->di_cu_context->cc_dbg, error,
+ DW_DLE_DIE_BAD);
+ return (DW_DLV_ERROR);
+ }
+ *return_bool = false;
+ return DW_DLV_OK;
+ }
+
+ *return_bool = (true);
+ return DW_DLV_OK;
+}
+
+
+int
+dwarf_attr(Dwarf_Die die,
+ Dwarf_Half attr,
+ Dwarf_Attribute * ret_attr, Dwarf_Error * error)
+{
+ Dwarf_Half attr_form = 0;
+ Dwarf_Attribute attrib = 0;
+ Dwarf_Byte_Ptr info_ptr = 0;
+ Dwarf_Debug dbg = 0;
+
+ CHECK_DIE(die, DW_DLV_ERROR);
+ dbg = die->di_cu_context->cc_dbg;
+
+ info_ptr = _dwarf_get_value_ptr(die, attr, &attr_form);
+ if (info_ptr == NULL) {
+ if (attr_form == 0) {
+ _dwarf_error(dbg, error, DW_DLE_DIE_BAD);
+ return (DW_DLV_ERROR);
+ }
+ return DW_DLV_NO_ENTRY;
+ }
+
+ attrib = (Dwarf_Attribute) _dwarf_get_alloc(dbg, DW_DLA_ATTR, 1);
+ if (attrib == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ attrib->ar_attribute = attr;
+ attrib->ar_attribute_form = attr_form;
+ attrib->ar_attribute_form_direct = attr_form;
+ attrib->ar_cu_context = die->di_cu_context;
+ attrib->ar_debug_ptr = info_ptr;
+ attrib->ar_die = die;
+ *ret_attr = (attrib);
+ return DW_DLV_OK;
+}
+
+
+int
+dwarf_lowpc(Dwarf_Die die,
+ Dwarf_Addr * return_addr, Dwarf_Error * error)
+{
+ Dwarf_Addr ret_addr = 0;
+ Dwarf_Byte_Ptr info_ptr = 0;
+ Dwarf_Half attr_form = 0;
+ Dwarf_Debug dbg = 0;
+ Dwarf_Half address_size = 0;
+
+ CHECK_DIE(die, DW_DLV_ERROR);
+
+ dbg = die->di_cu_context->cc_dbg;
+ address_size = die->di_cu_context->cc_address_size;
+ info_ptr = _dwarf_get_value_ptr(die, DW_AT_low_pc, &attr_form);
+ if ((info_ptr == NULL && attr_form == 0) ||
+ (info_ptr != NULL && attr_form != DW_FORM_addr)) {
+ _dwarf_error(dbg, error, DW_DLE_DIE_BAD);
+ return (DW_DLV_ERROR);
+ }
+ if (info_ptr == NULL) {
+ return (DW_DLV_NO_ENTRY);
+ }
+
+
+ READ_UNALIGNED(dbg, ret_addr, Dwarf_Addr,
+ info_ptr, address_size);
+
+ *return_addr = ret_addr;
+ return (DW_DLV_OK);
+}
+
+
+int
+dwarf_highpc(Dwarf_Die die,
+ Dwarf_Addr * return_addr, Dwarf_Error * error)
+{
+ Dwarf_Addr ret_addr = 0;
+ Dwarf_Byte_Ptr info_ptr = 0;
+ Dwarf_Half attr_form = 0;
+ Dwarf_Debug dbg = 0;
+ Dwarf_Half address_size = 0;
+
+ CHECK_DIE(die, DW_DLV_ERROR);
+ dbg = die->di_cu_context->cc_dbg;
+ address_size = die->di_cu_context->cc_address_size;
+ info_ptr = _dwarf_get_value_ptr(die, DW_AT_high_pc, &attr_form);
+ if ((info_ptr == NULL && attr_form == 0) ||
+ (info_ptr != NULL && attr_form != DW_FORM_addr)) {
+ _dwarf_error(dbg, error, DW_DLE_DIE_BAD);
+ return (DW_DLV_ERROR);
+ }
+ if (info_ptr == NULL) {
+ return (DW_DLV_NO_ENTRY);
+ }
+
+ READ_UNALIGNED(dbg, ret_addr, Dwarf_Addr,
+ info_ptr, address_size);
+
+ *return_addr = ret_addr;
+ return (DW_DLV_OK);
+}
+
+
+/*
+ Takes a die, an attribute attr, and checks if attr
+ occurs in die. Attr is required to be an attribute
+ whose form is in the "constant" class. If attr occurs
+ in die, the value is returned.
+ Returns DW_DLV_OK, DW_DLV_ERROR, or DW_DLV_NO_ENTRY as
+ appropriate. Sets the value thru the pointer return_val.
+ This function is meant to do all the
+ processing for dwarf_bytesize, dwarf_bitsize, dwarf_bitoffset,
+ and dwarf_srclang.
+*/
+static int
+_dwarf_die_attr_unsigned_constant(Dwarf_Die die,
+ Dwarf_Half attr,
+ Dwarf_Unsigned * return_val,
+ Dwarf_Error * error)
+{
+ Dwarf_Byte_Ptr info_ptr = 0;
+ Dwarf_Half attr_form = 0;
+ Dwarf_Unsigned ret_value = 0;
+ Dwarf_Debug dbg = 0;
+
+ CHECK_DIE(die, DW_DLV_ERROR);
+
+ dbg = die->di_cu_context->cc_dbg;
+ info_ptr = _dwarf_get_value_ptr(die, attr, &attr_form);
+ if (info_ptr != NULL) {
+ switch (attr_form) {
+
+ case DW_FORM_data1:
+ *return_val = (*(Dwarf_Small *) info_ptr);
+ return (DW_DLV_OK);
+
+ case DW_FORM_data2:
+ READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
+ info_ptr, sizeof(Dwarf_Shalf));
+ *return_val = ret_value;
+ return (DW_DLV_OK);
+
+ case DW_FORM_data4:
+ READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
+ info_ptr, sizeof(Dwarf_sfixed));
+ *return_val = ret_value;
+ return (DW_DLV_OK);
+
+ case DW_FORM_data8:
+ READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
+ info_ptr, sizeof(Dwarf_Unsigned));
+ *return_val = ret_value;
+ return (DW_DLV_OK);
+
+ case DW_FORM_udata:
+ *return_val = (_dwarf_decode_u_leb128(info_ptr, NULL));
+ return (DW_DLV_OK);
+
+ default:
+ _dwarf_error(dbg, error, DW_DLE_DIE_BAD);
+ return (DW_DLV_ERROR);
+ }
+ }
+ if (attr_form == 0) {
+ _dwarf_error(dbg, error, DW_DLE_DIE_BAD);
+ return (DW_DLV_ERROR);
+ }
+ return DW_DLV_NO_ENTRY;
+}
+
+
+int
+dwarf_bytesize(Dwarf_Die die,
+ Dwarf_Unsigned * ret_size, Dwarf_Error * error)
+{
+ Dwarf_Unsigned luns = 0;
+ int res = _dwarf_die_attr_unsigned_constant(die, DW_AT_byte_size,
+ &luns, error);
+ *ret_size = luns;
+ return res;
+}
+
+
+int
+dwarf_bitsize(Dwarf_Die die,
+ Dwarf_Unsigned * ret_size, Dwarf_Error * error)
+{
+ Dwarf_Unsigned luns = 0;
+ int res = _dwarf_die_attr_unsigned_constant(die, DW_AT_bit_size,
+ &luns, error);
+ *ret_size = luns;
+ return res;
+}
+
+
+int
+dwarf_bitoffset(Dwarf_Die die,
+ Dwarf_Unsigned * ret_size, Dwarf_Error * error)
+{
+ Dwarf_Unsigned luns = 0;
+ int res = _dwarf_die_attr_unsigned_constant(die,
+ DW_AT_bit_offset, &luns, error);
+ *ret_size = luns;
+ return res;
+}
+
+
+/* Refer section 3.1, page 21 in Dwarf Definition. */
+int
+dwarf_srclang(Dwarf_Die die,
+ Dwarf_Unsigned * ret_size, Dwarf_Error * error)
+{
+ Dwarf_Unsigned luns = 0;
+ int res = _dwarf_die_attr_unsigned_constant(die, DW_AT_language,
+ &luns, error);
+ *ret_size = luns;
+ return res;
+}
+
+
+/* Refer section 5.4, page 37 in Dwarf Definition. */
+int
+dwarf_arrayorder(Dwarf_Die die,
+ Dwarf_Unsigned * ret_size, Dwarf_Error * error)
+{
+ Dwarf_Unsigned luns = 0;
+ int res = _dwarf_die_attr_unsigned_constant(die, DW_AT_ordering,
+ &luns, error);
+ *ret_size = luns;
+ return res;
+}
+
+/* Return DW_DLV_OK if ok
+ DW_DLV_ERROR if failure.
+
+ If the die and the attr are not related the result is
+ meaningless. */
+int
+dwarf_attr_offset(Dwarf_Die die, Dwarf_Attribute attr,
+ Dwarf_Off * offset /* return offset thru this ptr */,
+ Dwarf_Error * error)
+{
+ Dwarf_Off attroff = 0;
+ Dwarf_Small *dataptr = 0;
+ Dwarf_Debug dbg = 0;
+
+ CHECK_DIE(die, DW_DLV_ERROR);
+ dbg = die->di_cu_context->cc_dbg;
+ dataptr = die->di_is_info? dbg->de_debug_info.dss_data:
+ dbg->de_debug_types.dss_data;
+
+ attroff = (attr->ar_debug_ptr - dataptr);
+ *offset = attroff;
+ return DW_DLV_OK;
+}
+
+int
+dwarf_die_abbrev_code(Dwarf_Die die)
+{
+ return die->di_abbrev_code;
+}
+
+/* Returns a flag through ab_has_child. Non-zero if
+ the DIE has children, zero if it does not. */
+int
+dwarf_die_abbrev_children_flag(Dwarf_Die die,Dwarf_Half *ab_has_child)
+{
+ if (die->di_abbrev_list) {
+ *ab_has_child = die->di_abbrev_list->ab_has_child;
+ return DW_DLV_OK;
+ }
+ return DW_DLV_ERROR;
+}
+
+/* Helper function for finding form class. */
+static enum Dwarf_Form_Class
+dw_get_special_offset(Dwarf_Half attrnum)
+{
+ switch(attrnum) {
+ case DW_AT_stmt_list:
+ return DW_FORM_CLASS_LINEPTR;
+ case DW_AT_macro_info:
+ return DW_FORM_CLASS_MACPTR;
+ case DW_AT_ranges:
+ return DW_FORM_CLASS_RANGELISTPTR;
+ case DW_AT_location:
+ case DW_AT_string_length:
+ case DW_AT_return_addr:
+ case DW_AT_data_member_location:
+ case DW_AT_frame_base:
+ case DW_AT_segment:
+ case DW_AT_static_link:
+ case DW_AT_use_location:
+ case DW_AT_vtable_elem_location:
+ return DW_FORM_CLASS_LOCLISTPTR;
+ case DW_AT_sibling:
+ case DW_AT_byte_size :
+ case DW_AT_bit_offset :
+ case DW_AT_bit_size :
+ case DW_AT_discr :
+ case DW_AT_import :
+ case DW_AT_common_reference:
+ case DW_AT_containing_type:
+ case DW_AT_default_value:
+ case DW_AT_lower_bound:
+ case DW_AT_bit_stride:
+ case DW_AT_upper_bound:
+ case DW_AT_abstract_origin:
+ case DW_AT_base_types:
+ case DW_AT_count:
+ case DW_AT_friend:
+ case DW_AT_namelist_item:
+ case DW_AT_priority:
+ case DW_AT_specification:
+ case DW_AT_type:
+ case DW_AT_allocated:
+ case DW_AT_associated:
+ case DW_AT_byte_stride:
+ case DW_AT_extension:
+ case DW_AT_trampoline:
+ case DW_AT_small:
+ case DW_AT_object_pointer:
+ case DW_AT_signature:
+ return DW_FORM_CLASS_REFERENCE;
+ case DW_AT_MIPS_fde: /* SGI/IRIX extension */
+ return DW_FORM_CLASS_FRAMEPTR;
+ }
+ return DW_FORM_CLASS_UNKNOWN;
+}
+
+/* It takes 4 pieces of data (including the FORM)
+ to accurately determine the form 'class' as documented
+ in the DWARF spec. This is per DWARF4, but will work
+ for DWARF2 or 3 as well. */
+enum Dwarf_Form_Class dwarf_get_form_class(
+ Dwarf_Half dwversion,
+ Dwarf_Half attrnum,
+ Dwarf_Half offset_size,
+ Dwarf_Half form)
+{
+ switch(form) {
+ case DW_FORM_addr: return DW_FORM_CLASS_ADDRESS;
+
+ case DW_FORM_data2: return DW_FORM_CLASS_CONSTANT;
+
+ case DW_FORM_data4:
+ if(dwversion <= 3 && offset_size == 4) {
+ enum Dwarf_Form_Class class = dw_get_special_offset(attrnum);
+ if(class != DW_FORM_CLASS_UNKNOWN) {
+ return class;
+ }
+ }
+ return DW_FORM_CLASS_CONSTANT;
+ case DW_FORM_data8:
+ if(dwversion <= 3 && offset_size == 8) {
+ enum Dwarf_Form_Class class = dw_get_special_offset(attrnum);
+ if(class != DW_FORM_CLASS_UNKNOWN) {
+ return class;
+ }
+ }
+ return DW_FORM_CLASS_CONSTANT;
+
+ case DW_FORM_sec_offset:
+ {
+ enum Dwarf_Form_Class class = dw_get_special_offset(attrnum);
+ if(class != DW_FORM_CLASS_UNKNOWN) {
+ return class;
+ }
+ }
+ /* We do not know what this is. */
+ break;
+
+ case DW_FORM_string: return DW_FORM_CLASS_STRING;
+ case DW_FORM_strp: return DW_FORM_CLASS_STRING;
+
+ case DW_FORM_block: return DW_FORM_CLASS_BLOCK;
+ case DW_FORM_block1: return DW_FORM_CLASS_BLOCK;
+ case DW_FORM_block2: return DW_FORM_CLASS_BLOCK;
+ case DW_FORM_block4: return DW_FORM_CLASS_BLOCK;
+
+ case DW_FORM_data1: return DW_FORM_CLASS_CONSTANT;
+ case DW_FORM_sdata: return DW_FORM_CLASS_CONSTANT;
+ case DW_FORM_udata: return DW_FORM_CLASS_CONSTANT;
+
+ case DW_FORM_ref_addr: return DW_FORM_CLASS_REFERENCE;
+ case DW_FORM_ref1: return DW_FORM_CLASS_REFERENCE;
+ case DW_FORM_ref2: return DW_FORM_CLASS_REFERENCE;
+ case DW_FORM_ref4: return DW_FORM_CLASS_REFERENCE;
+ case DW_FORM_ref8: return DW_FORM_CLASS_REFERENCE;
+ case DW_FORM_ref_udata: return DW_FORM_CLASS_REFERENCE;
+ case DW_FORM_ref_sig8: return DW_FORM_CLASS_REFERENCE;
+
+ case DW_FORM_exprloc: return DW_FORM_CLASS_EXPRLOC;
+
+ case DW_FORM_flag: return DW_FORM_CLASS_FLAG;
+ case DW_FORM_flag_present: return DW_FORM_CLASS_FLAG;
+
+
+ case DW_FORM_indirect:
+ default:
+ break;
+ };
+ return DW_FORM_CLASS_UNKNOWN;
+};
+
+/* Given a DIE, figure out what the CU's DWARF version is
+ and the size of an offset
+ and return it through the *version pointer and return
+ DW_DLV_OK.
+
+ If we cannot find a CU,
+ return DW_DLV_ERROR on error.
+ In case of error no Dwarf_Debug was available,
+ so setting a Dwarf_Error is somewhat futile.
+ Never returns DW_DLV_NO_ENTRY.
+*/
+int
+dwarf_get_version_of_die(Dwarf_Die die,
+ Dwarf_Half *version,
+ Dwarf_Half *offset_size)
+{
+ Dwarf_CU_Context cucontext = 0;
+ if(!die) {
+ return DW_DLV_ERROR;
+ }
+ cucontext = die->di_cu_context;
+ if(!cucontext) {
+ return DW_DLV_ERROR;
+ }
+ *version = cucontext->cc_version_stamp;
+ *offset_size = cucontext->cc_length_size;
+ return DW_DLV_OK;
+}
+
+
diff --git a/libdwarf/dwarf_ranges.c b/libdwarf/dwarf_ranges.c
new file mode 100644
index 0000000..835a8d5
--- /dev/null
+++ b/libdwarf/dwarf_ranges.c
@@ -0,0 +1,172 @@
+/*
+
+ Copyright (C) 2008-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+
+
+#include "config.h"
+#include <stdlib.h>
+#include "dwarf_incl.h"
+
+struct ranges_entry {
+ struct ranges_entry *next;
+ Dwarf_Ranges cur;
+};
+
+
+#define MAX_ADDR ((address_size == 8)?0xffffffffffffffffULL:0xffffffff)
+int dwarf_get_ranges_a(Dwarf_Debug dbg,
+ Dwarf_Off rangesoffset,
+ Dwarf_Die die,
+ Dwarf_Ranges ** rangesbuf,
+ Dwarf_Signed * listlen,
+ Dwarf_Unsigned * bytecount,
+ Dwarf_Error * error)
+{
+ Dwarf_Small *rangeptr = 0;
+ Dwarf_Small *beginrangeptr = 0;
+ Dwarf_Small *section_end = 0;
+ unsigned entry_count = 0;
+ struct ranges_entry *base = 0;
+ struct ranges_entry *last = 0;
+ struct ranges_entry *curre = 0;
+ Dwarf_Ranges * ranges_data_out = 0;
+ unsigned copyindex = 0;
+ Dwarf_Half address_size = 0;
+ int res = DW_DLV_ERROR;
+
+ res = _dwarf_load_section(dbg, &dbg->de_debug_ranges,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+
+ if(rangesoffset >= dbg->de_debug_ranges.dss_size) {
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OFFSET_BAD);
+ return (DW_DLV_ERROR);
+
+ }
+ address_size = _dwarf_get_address_size(dbg, die);
+ section_end = dbg->de_debug_ranges.dss_data +
+ dbg->de_debug_ranges.dss_size;
+ rangeptr = dbg->de_debug_ranges.dss_data + rangesoffset;
+ beginrangeptr = rangeptr;
+
+ for(;;) {
+ struct ranges_entry * re = calloc(sizeof(struct ranges_entry),1);
+ if(!re) {
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OUT_OF_MEM);
+ return (DW_DLV_ERROR);
+ }
+ if(rangeptr >= section_end) {
+ return (DW_DLV_NO_ENTRY);
+ }
+ if((rangeptr + (2*address_size)) > section_end) {
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OFFSET_BAD);
+ return (DW_DLV_ERROR);
+ }
+ entry_count++;
+ READ_UNALIGNED(dbg,re->cur.dwr_addr1,
+ Dwarf_Addr, rangeptr,
+ address_size);
+ rangeptr += address_size;
+ READ_UNALIGNED(dbg,re->cur.dwr_addr2 ,
+ Dwarf_Addr, rangeptr,
+ address_size);
+ rangeptr += address_size;
+ if(!base) {
+ base = re;
+ last = re;
+ } else {
+ last->next = re;
+ last = re;
+ }
+ if(re->cur.dwr_addr1 == 0 && re->cur.dwr_addr2 == 0) {
+ re->cur.dwr_type = DW_RANGES_END;
+ break;
+ } else if ( re->cur.dwr_addr1 == MAX_ADDR) {
+ re->cur.dwr_type = DW_RANGES_ADDRESS_SELECTION;
+ } else {
+ re->cur.dwr_type = DW_RANGES_ENTRY;
+ }
+ }
+
+ ranges_data_out = (Dwarf_Ranges *)
+ _dwarf_get_alloc(dbg,DW_DLA_RANGES,entry_count);
+ if(!ranges_data_out) {
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OUT_OF_MEM);
+ return (DW_DLV_ERROR);
+ }
+ curre = base;
+ *rangesbuf = ranges_data_out;
+ *listlen = entry_count;
+ for( copyindex = 0; curre && (copyindex < entry_count);
+ ++copyindex,++ranges_data_out) {
+
+ struct ranges_entry *r = curre;
+ *ranges_data_out = curre->cur;
+ curre = curre->next;
+ free(r);
+ }
+ /* Callers will often not care about the bytes used. */
+ if(bytecount) {
+ *bytecount = rangeptr - beginrangeptr;
+ }
+ return DW_DLV_OK;
+}
+int dwarf_get_ranges(Dwarf_Debug dbg,
+ Dwarf_Off rangesoffset,
+ Dwarf_Ranges ** rangesbuf,
+ Dwarf_Signed * listlen,
+ Dwarf_Unsigned * bytecount,
+ Dwarf_Error * error)
+{
+ Dwarf_Die die = 0;
+ int res = dwarf_get_ranges_a(dbg,rangesoffset,die,
+ rangesbuf,listlen,bytecount,error);
+ return res;
+}
+
+void
+dwarf_ranges_dealloc(Dwarf_Debug dbg, Dwarf_Ranges * rangesbuf,
+ Dwarf_Signed rangecount)
+{
+ dwarf_dealloc(dbg,rangesbuf, DW_DLA_RANGES);
+
+}
+
diff --git a/libdwarf/dwarf_sort_line.c b/libdwarf/dwarf_sort_line.c
new file mode 100644
index 0000000..40e337c
--- /dev/null
+++ b/libdwarf/dwarf_sort_line.c
@@ -0,0 +1,676 @@
+/*
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+
+/* This file was designed for SGI IRIX compiler use.
+ The static linker can rearrange the order of functions
+ in the layout in memory
+ and provided each has the right form
+ this will (when called by the SGI IRIX
+ static linker) rearrange the table so the line table
+ is arranged in the same order as the memory layout. */
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "dwarf_line.h"
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#define MINIMUM_POSSIBLE_PROLOG_LEN 10 /* 10 is based on */
+/* the definition of the DWARF2/3 line table prolog. The value
+ here should be >8 (accounting for a 64 bit read) and <= the
+ length of a legal DWARF2/3 line prolog, which is at least 10
+ bytes long (but can be longer). What this constant helps
+ avoid is reading past the end of a malloc'd buffer in
+ _dwarf_update_line_sec(). */
+
+static int
+_dwarf_update_line_sec(Dwarf_Small * line_ptr,
+ unsigned long remaining_bytes,
+ int *any_change,
+ int length_size,
+ int *err_code, Dwarf_Small ** new_line_ptr);
+
+/* Used to construct
+ a linked list of so we can sort and reorder the line info. */
+struct a_line_area {
+ Dwarf_Addr ala_address; /* from DW_LNE_set_address */
+ Dwarf_Unsigned ala_offset; /* byte offset in buffer */
+ Dwarf_Unsigned ala_length; /* byte length in buffer */
+ long ala_entry_num; /* to guarantee stable sort */
+ struct a_line_area *ala_next;
+};
+
+
+/* Written to support the SGI IRIX static linker.
+ It helps SGI IRIX ld
+ rearrange lines in .debug_line in a .o created with a text
+ section per function. The SGI IRIX linker option is:
+ -OPT:procedure_reorder=ON
+ where ld-cord (cord(1)ing by ld,
+ not by cord(1)) may have changed the function order.
+
+ Returns
+ DW_DLV_OK if nothing went wrong.
+ DW_DLV_ERROR if could not do anything due to
+ error. the original buffer is unchanged.
+
+ is_64_bit must be passed in by caller and tells
+ if this is a 32 or 64bit pointer object section
+ being processed.
+
+ err_code must be a non-null pointer to integer.
+ If DW_DLV_ERROR is returned that integer is set
+ to a dwarf error code so the caller may
+ print it for diagnostic purposes.
+
+ *any_change is set here
+ set 0 if no sorting (movement) done.
+ set 1 if some sorting (movement) done.
+ on all returns. On error return sets to 0.
+
+ The _dwarf name form is now obsolete,
+ the dwarf_ name for is preferred.
+ Both names supported. */
+int
+_dwarf_ld_sort_lines(void *orig_buffer,
+ unsigned long buffer_len,
+ int is_64_bit, int *any_change, int *err_code)
+{
+ return dwarf_ld_sort_lines(orig_buffer,buffer_len,
+ is_64_bit,any_change,err_code);
+}
+int
+dwarf_ld_sort_lines(void *orig_buffer,
+ unsigned long buffer_len,
+ int is_64_bit, int *any_change, int *err_code)
+{
+
+ int length_size = 4;
+ Dwarf_Small *orig_line_ptr; /* our local copy of the user's input
+ buffer */
+ Dwarf_Small *line_ptr; /* starts at orig_line_ptr, gets
+ incremented thru to end of our copy
+ of the input buffer */
+ Dwarf_Small *new_line_ptr; /* output of _dwarf_update_line_sec(),
+ used to update line_ptr as we pass
+ thru compilation units in a .o
+ .debug_line */
+
+ unsigned long remaining_bytes = buffer_len; /* total length of
+ original area left to be processed. Changes as we pass
+ thru compilation units in a .o .debug_line */
+
+ int sec_res;
+ int lany_change = 0;
+ int did_change = 0;
+
+ if (is_64_bit)
+ length_size = 8;
+
+ *any_change = 0;
+ line_ptr = malloc(buffer_len);
+ if (!line_ptr) {
+ *err_code = DW_DLE_ALLOC_FAIL;
+ return DW_DLV_ERROR;
+ }
+ orig_line_ptr = line_ptr;
+ memcpy(line_ptr, orig_buffer, buffer_len);
+
+
+ /* We must iterate thru each of a set of prologues and line data.
+ We process each set in turn. If all pass, we update the
+ passed-in buffer. */
+ sec_res = DW_DLV_OK;
+
+ for (sec_res = _dwarf_update_line_sec(line_ptr,
+ remaining_bytes, &lany_change, length_size, err_code, &new_line_ptr);
+ (sec_res == DW_DLV_OK) && (remaining_bytes > 0);
+ sec_res = _dwarf_update_line_sec(line_ptr,
+ remaining_bytes, &lany_change, length_size,
+ err_code, &new_line_ptr)) {
+ long bytes_used = new_line_ptr - line_ptr;
+
+ line_ptr = new_line_ptr;
+ remaining_bytes -= bytes_used;
+ if (lany_change) {
+ did_change = 1;
+ }
+ if (remaining_bytes > 0) {
+ continue;
+ }
+ break;
+ }
+ if (sec_res == DW_DLV_ERROR) {
+ free(orig_line_ptr);
+ return sec_res;
+ }
+
+
+ /* all passed */
+ if (did_change) {
+ /* So update the passed in buffer orig_buffer is caller's input
+ area. orig_line_ptr is our modified copy of input area. */
+ memcpy(orig_buffer, orig_line_ptr, buffer_len);
+ *any_change = 1;
+ }
+ free(orig_line_ptr);
+
+ return sec_res;
+}
+
+
+/* By setting ala_entry_num we guarantee a stable sort,
+ no duplicates
+ Sorting in address order.
+*/
+static int
+cmpr(const void *lin, const void *rin)
+{
+ const struct a_line_area *l = lin;
+ const struct a_line_area *r = rin;
+
+ if (l->ala_address < r->ala_address) {
+ return -1;
+ }
+ if (l->ala_address > r->ala_address) {
+ return 1;
+ }
+ if (l->ala_entry_num < r->ala_entry_num) {
+ return -1;
+ }
+ if (l->ala_entry_num > r->ala_entry_num) {
+ return 1;
+ }
+ return 0; /* should never happen. */
+}
+
+/* The list of line area records is no longer needed.
+ Free the data allocated. */
+static void
+free_area_data(struct a_line_area *arp)
+{
+ while(arp) {
+ struct a_line_area *next = arp->ala_next;
+ free(arp);
+ arp = next;
+ }
+}
+
+/* On entry:
+ line_ptr must point to first
+ byte of a line group for one (original) .o
+
+ remaining_bytes is the size of the area pointed to
+ by line_ptr: may be larger than the
+ current original compilation unit .
+
+ length size is 4 for 32bit pointers, 8 for 64bit pointers
+ in the data pointed to.
+
+
+ On return:
+ return DW_DLV_OK if all ok. (ignore
+ *err_code in this case)
+
+ return DW_DLV_ERROR and set *err_code if an error.
+
+ If some line data was moved around, set *any_change to 1.
+ If error or no movement, set *any_change to 0;
+
+ Set *new_line_ptr to one-byte-past the end of the
+ current original compilation unit (not necessary
+ if returning DW_DLV_ERROR, but not harmful).
+
+ This copies the entire array to a malloc area, then
+ mallocs pieces of it (another malloc) for sorting a CU entries
+ and copying back. Then at end the whole new thing copied in.
+ The result is that on error, the input is not touched.
+
+ An alternative would be to just update a piece at a time
+ and on error stop updating but leave what was done, done.
+ This alternative would save some temporary malloc space. */
+static int
+_dwarf_update_line_sec(Dwarf_Small * line_ptr,
+ unsigned long remaining_bytes,
+ int *any_change,
+ int length_size,
+ int *err_code, Dwarf_Small ** new_line_ptr)
+{
+ /* This points to the last byte of the .debug_line portion for the
+ current cu. */
+ Dwarf_Small *line_ptr_end = 0;
+
+ /* This points to the end of the statement program prologue for the
+ current cu, and serves to check that the prologue was correctly
+ decoded. */
+
+ Dwarf_Small *orig_line_ptr = 0;
+
+ /* These are the fields of the statement program header. */
+ struct Dwarf_Debug_s dbg_data;
+ Dwarf_Debug dbg = &dbg_data;
+
+ /* These are the state machine state variables. */
+ Dwarf_Addr address = 0;
+ Dwarf_Word line = 1;
+ Dwarf_Bool is_stmt = false;
+
+ /* Dwarf_Bool prologue_end; Dwarf_Bool epilogue_begin; */
+ Dwarf_Small isa = 0;
+
+
+ struct a_line_area *area_base = 0;
+ struct a_line_area *area_current = 0;
+ long area_count = 0;
+
+ Dwarf_Addr last_address = 0;
+ int need_to_sort = 0;
+
+ /* This is the current opcode read from the statement program. */
+ Dwarf_Small opcode = 0;
+
+
+ /* These variables are used to decode leb128 numbers. Leb128_num
+ holds the decoded number, and leb128_length is its length in
+ bytes. */
+ Dwarf_Word leb128_num = 0;
+ Dwarf_Sword advance_line = 0;
+
+ /* This is the operand of the latest fixed_advance_pc extended
+ opcode. */
+ Dwarf_Half fixed_advance_pc = 0;
+
+ /* This is the length of an extended opcode instr. */
+ Dwarf_Word instr_length = 0;
+ Dwarf_Small ext_opcode = 0;
+ struct Line_Table_Prefix_s prefix;
+
+
+
+ memset(dbg, 0, sizeof(struct Dwarf_Debug_s));
+ dbg->de_copy_word = memcpy;
+ /* Following is a straightforward decoding of the statement program
+ prologue information. */
+ *any_change = 0;
+
+
+ orig_line_ptr = line_ptr;
+ if (remaining_bytes < MINIMUM_POSSIBLE_PROLOG_LEN) {
+ /* We are at the end. Remaining should be zero bytes, padding.
+ This is really just 'end of CU buffer' not an error. The is
+ no 'entry' left so report there is none. We don't want to
+ READ_UNALIGNED the total_length below and then belatedly
+ discover that we read off the end already. */
+ return (DW_DLV_NO_ENTRY);
+ }
+
+ dwarf_init_line_table_prefix(&prefix);
+ {
+ Dwarf_Small *line_ptr_out = 0;
+ Dwarf_Error error;
+ int dres = dwarf_read_line_table_prefix(dbg,
+ line_ptr,
+ remaining_bytes,
+ &line_ptr_out,
+ &prefix,
+ NULL, NULL,&error,
+ NULL);
+
+ if (dres == DW_DLV_ERROR) {
+ dwarf_free_line_table_prefix(&prefix);
+ *err_code = dwarf_errno(error);
+ dwarf_dealloc(dbg, error, DW_DLA_ERROR);
+ free_area_data(area_base);
+ return dres;
+ }
+ if (dres == DW_DLV_NO_ENTRY) {
+ dwarf_free_line_table_prefix(&prefix);
+ return dres;
+ }
+ line_ptr_end = prefix.pf_line_ptr_end;
+ line_ptr = line_ptr_out;
+ }
+
+ /* Initialize the state machine. */
+ /* file = 1; */
+ /* column = 0; */
+ is_stmt = prefix.pf_default_is_stmt;
+ /* basic_block = false; */
+ /* end_sequence = false; */
+ /* prologue_end = false; */
+ /* epilogue_begin = false; */
+ isa = 0;
+
+
+ /* Start of statement program. */
+ while (line_ptr < line_ptr_end) {
+ int type;
+ Dwarf_Small *stmt_prog_entry_start = line_ptr;
+
+ opcode = *(Dwarf_Small *) line_ptr;
+ line_ptr++;
+ /* 'type' is the output */
+ WHAT_IS_OPCODE(type, opcode, prefix.pf_opcode_base,
+ prefix.pf_opcode_length_table, line_ptr,
+ prefix.pf_std_op_count);
+
+ if (type == LOP_DISCARD) {
+ int oc;
+ int opcnt = prefix.pf_opcode_length_table[opcode];
+
+ for (oc = 0; oc < opcnt; oc++) {
+ /* Read and discard operands we don't
+ understand.
+ arbitrary choice of unsigned read.
+ signed read would work as well. */
+ Dwarf_Unsigned utmp2;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ }
+
+ } else if (type == LOP_SPECIAL) {
+ opcode = opcode - prefix.pf_opcode_base;
+ address = address + prefix.pf_minimum_instruction_length *
+ (opcode / prefix.pf_line_range);
+ line =
+ line + prefix.pf_line_base +
+ opcode % prefix.pf_line_range;
+
+ /* basic_block = false; */
+ } else if (type == LOP_STANDARD) {
+ switch (opcode) {
+ case DW_LNS_copy:{
+ /* basic_block = false; */
+ break;
+ }
+
+ case DW_LNS_advance_pc:{
+ Dwarf_Unsigned utmp2;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ leb128_num = (Dwarf_Word) utmp2;
+ address = address +
+ prefix.pf_minimum_instruction_length * leb128_num;
+ break;
+ }
+
+ case DW_LNS_advance_line:{
+ Dwarf_Signed stmp;
+
+ DECODE_LEB128_SWORD(line_ptr, stmp);
+ advance_line = (Dwarf_Sword) stmp;
+ line = line + advance_line;
+ break;
+ }
+
+ case DW_LNS_set_file:{
+ Dwarf_Unsigned utmp2;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ /* file = (Dwarf_Word)utmp2; */
+ break;
+ }
+
+ case DW_LNS_set_column:{
+ Dwarf_Unsigned utmp2;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ /* column = (Dwarf_Word)utmp2; */
+ break;
+ }
+
+ case DW_LNS_negate_stmt:{
+ is_stmt = !is_stmt;
+ break;
+ }
+
+ case DW_LNS_set_basic_block:{
+ /* basic_block = true; */
+ break;
+ }
+
+ case DW_LNS_const_add_pc:{
+ opcode = MAX_LINE_OP_CODE - prefix.pf_opcode_base;
+ address = address +
+ prefix.pf_minimum_instruction_length *
+ (opcode / prefix. pf_line_range);
+ break;
+ }
+
+ case DW_LNS_fixed_advance_pc:{
+
+ READ_UNALIGNED(dbg, fixed_advance_pc, Dwarf_Half,
+ line_ptr, sizeof(Dwarf_Half));
+ line_ptr += sizeof(Dwarf_Half);
+ address = address + fixed_advance_pc;
+ break;
+ }
+ /* New in DWARF3 */
+ case DW_LNS_set_prologue_end:{
+ /* prologue_end = true; */
+ break;
+
+
+ }
+ /* New in DWARF3 */
+ case DW_LNS_set_epilogue_begin:{
+ /* epilogue_begin = true; */
+ break;
+ }
+
+ /* New in DWARF3 */
+ case DW_LNS_set_isa:{
+ Dwarf_Unsigned utmp2;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ isa = utmp2;
+ if (isa != utmp2) {
+ /* The value of the isa did not fit in our
+ local so we record it wrong. declare an
+ error. */
+ dwarf_free_line_table_prefix(&prefix);
+ *err_code = DW_DLE_LINE_NUM_OPERANDS_BAD;
+ free_area_data(area_base);
+ return (DW_DLV_ERROR);
+ }
+ break;
+ }
+ }
+ } else if (type == LOP_EXTENDED) {
+ Dwarf_Unsigned utmp3 = 0;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp3);
+ instr_length = (Dwarf_Word) utmp3;
+ ext_opcode = *(Dwarf_Small *) line_ptr;
+ line_ptr++;
+ switch (ext_opcode) {
+
+ case DW_LNE_end_sequence:{
+ /* end_sequence = true; */
+
+ address = 0;
+ /* file = 1; */
+ line = 1;
+ /* column = 0; */
+ is_stmt = prefix.pf_default_is_stmt;
+ /* basic_block = false; */
+ /* end_sequence = false; */
+ /* prologue_end = false; */
+ /* epilogue_begin = false; */
+ }
+ break;
+ case DW_LNE_set_address:{
+ struct a_line_area *area = 0;
+
+ READ_UNALIGNED(dbg, address, Dwarf_Addr,
+ line_ptr, length_size);
+ /* Here we need to remember the offset into the
+ buffer and check to see if address went
+ down. */
+ if (address < last_address) {
+ need_to_sort = 1;
+ }
+ last_address = address;
+
+ area = malloc(sizeof(struct a_line_area));
+ area->ala_address = address;
+ area->ala_offset = stmt_prog_entry_start -
+ orig_line_ptr;
+ area->ala_entry_num = area_count;
+ area->ala_next = 0;
+ area->ala_length = 0;
+ if (area_current) {
+ area_current->ala_next = area;
+ area_current->ala_length =
+ area->ala_offset -
+ area_current->ala_offset;
+ }
+ ++area_count;
+ area_current = area;
+ if (area_base == 0) {
+ area_base = area;
+ }
+
+ line_ptr += length_size;
+ }
+ break;
+
+ case DW_LNE_define_file:{
+ break;
+ }
+
+ default:{
+ Dwarf_Unsigned remaining_bytes = instr_length -1;
+ line_ptr += remaining_bytes;
+ break;
+ }
+ }
+
+ }
+ }
+
+
+ *new_line_ptr = line_ptr;
+ if (!need_to_sort) {
+ dwarf_free_line_table_prefix(&prefix);
+ free_area_data(area_base);
+ return (DW_DLV_OK);
+ }
+
+ /* So now we have something to sort. First, finish off the last
+ area record: */
+ area_current->ala_length = (line_ptr - orig_line_ptr)
+ -area_current->ala_offset;
+
+ /* Build and sort a simple array of sections. Forcing a stable sort
+ by comparing on sequence number. We will use the sorted list to
+ move sections of this part of the line table. Each 'section'
+ starting with a DW_LNE_set_address opcode, on the assumption
+ that such only get out of order where there was an ld-cord
+ function rearrangement and that it is meaningful to restart the
+ line info there. */
+ {
+ struct a_line_area *ala_array;
+ struct a_line_area *local;
+ long start_len;
+ Dwarf_Small *new_area;
+ long i;
+
+ ala_array = malloc(area_count * sizeof(struct a_line_area));
+ if (!ala_array) {
+ dwarf_free_line_table_prefix(&prefix);
+ *err_code = DW_DLE_ALLOC_FAIL;
+ free_area_data(area_base);
+ return DW_DLV_ERROR;
+ }
+
+ for (local = area_base, i = 0; local;
+ local = local->ala_next, ++i) {
+
+ ala_array[i] = *local;
+ }
+ free_area_data(area_base);
+ /* Zero the stale pointers so we don't use them accidentally. */
+ area_base = 0;
+ area_current = 0;
+
+ qsort(ala_array, area_count, sizeof(struct a_line_area), cmpr);
+
+ /* Now we must rearrange the pieces of the line table. */
+
+ start_len =
+ (prefix.pf_line_prologue_start +
+ prefix.pf_prologue_length) - orig_line_ptr;
+ new_area = malloc(remaining_bytes);
+ if (!new_area) {
+ free(ala_array);
+ *err_code = DW_DLE_ALLOC_FAIL;
+ dwarf_free_line_table_prefix(&prefix);
+ return DW_DLV_ERROR;
+ }
+ memcpy(new_area, orig_line_ptr, start_len);
+ line_ptr = new_area + start_len;
+ for (i = 0; i < area_count; ++i) {
+ memcpy(line_ptr, orig_line_ptr +
+ ala_array[i].ala_offset, ala_array[i].ala_length);
+ line_ptr += ala_array[i].ala_length;
+ }
+
+ memcpy(orig_line_ptr, new_area, remaining_bytes);
+
+ free(new_area);
+ free(ala_array);
+ ala_array = 0;
+ new_area = 0;
+ }
+
+ *any_change = 1;
+ dwarf_free_line_table_prefix(&prefix);
+ return (DW_DLV_OK);
+}
diff --git a/libdwarf/dwarf_string.c b/libdwarf/dwarf_string.c
new file mode 100644
index 0000000..c73bc0a
--- /dev/null
+++ b/libdwarf/dwarf_string.c
@@ -0,0 +1,83 @@
+/*
+
+ Copyright (C) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+
+int
+dwarf_get_str(Dwarf_Debug dbg,
+ Dwarf_Off offset,
+ char **string,
+ Dwarf_Signed * returned_str_len, Dwarf_Error * error)
+{
+ int res = DW_DLV_ERROR;
+
+ if (dbg == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ if (offset == dbg->de_debug_str.dss_size) {
+ /* Normal (if we've iterated thru the set of strings using
+ dwarf_get_str and are at the end). */
+ return DW_DLV_NO_ENTRY;
+ }
+ if (offset > dbg->de_debug_str.dss_size) {
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_STR_OFFSET_BAD);
+ return (DW_DLV_ERROR);
+ }
+
+ if (string == NULL) {
+ _dwarf_error(dbg, error, DW_DLE_STRING_PTR_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ res = _dwarf_load_section(dbg, &dbg->de_debug_str,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ if (!dbg->de_debug_str.dss_size) {
+ return (DW_DLV_NO_ENTRY);
+ }
+
+
+ *string = (char *) dbg->de_debug_str.dss_data + offset;
+
+ *returned_str_len = (strlen(*string));
+ return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_stubs.c b/libdwarf/dwarf_stubs.c
new file mode 100644
index 0000000..939f3e1
--- /dev/null
+++ b/libdwarf/dwarf_stubs.c
@@ -0,0 +1,51 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+
+
+
+/*ARGSUSED*/ int
+dwarf_nextglob(Dwarf_Debug dbg,
+ Dwarf_Global glob,
+ Dwarf_Global * returned_nextglob, Dwarf_Error * error)
+{
+ return (DW_DLV_NO_ENTRY);
+}
diff --git a/libdwarf/dwarf_types.c b/libdwarf/dwarf_types.c
new file mode 100644
index 0000000..55967e8
--- /dev/null
+++ b/libdwarf/dwarf_types.c
@@ -0,0 +1,132 @@
+/*
+ Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include "dwarf_types.h"
+#include "dwarf_global.h"
+
+int
+dwarf_get_types(Dwarf_Debug dbg,
+ Dwarf_Type ** types,
+ Dwarf_Signed * ret_type_count, Dwarf_Error * error)
+{
+ int res = _dwarf_load_section(dbg, &dbg->de_debug_typenames,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ if (!dbg->de_debug_typenames.dss_size) {
+ return (DW_DLV_NO_ENTRY);
+ }
+
+
+ return _dwarf_internal_get_pubnames_like_data(dbg,
+ dbg->de_debug_typenames.dss_data,
+ dbg->de_debug_typenames.dss_size,
+ (Dwarf_Global **) types, /* type punning, Dwarf_Type is
+ never a completed type */
+ ret_type_count,
+ error,
+ DW_DLA_TYPENAME_CONTEXT,
+ DW_DLA_TYPENAME,
+ DW_DLE_DEBUG_TYPENAMES_LENGTH_BAD,
+ DW_DLE_DEBUG_TYPENAMES_VERSION_ERROR);
+}
+
+/* Deallocating fully requires deallocating the list
+ and all entries. But some internal data is
+ not exposed, so we need a function with internal knowledge. */
+
+void
+dwarf_types_dealloc(Dwarf_Debug dbg, Dwarf_Type * dwgl,
+ Dwarf_Signed count)
+{
+ _dwarf_internal_globals_dealloc(dbg, (Dwarf_Global *) dwgl,
+ count,
+ DW_DLA_TYPENAME_CONTEXT,
+ DW_DLA_TYPENAME, DW_DLA_LIST);
+ return;
+}
+
+
+int
+dwarf_typename(Dwarf_Type type_in, char **ret_name, Dwarf_Error * error)
+{
+ Dwarf_Global type = (Dwarf_Global) type_in;
+
+ if (type == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_TYPE_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ *ret_name = (char *) (type->gl_name);
+ return DW_DLV_OK;
+}
+
+
+int
+dwarf_type_die_offset(Dwarf_Type type_in,
+ Dwarf_Off * ret_offset, Dwarf_Error * error)
+{
+ Dwarf_Global type = (Dwarf_Global) type_in;
+
+ return dwarf_global_die_offset(type, ret_offset, error);
+}
+
+
+int
+dwarf_type_cu_offset(Dwarf_Type type_in,
+ Dwarf_Off * ret_offset, Dwarf_Error * error)
+{
+ Dwarf_Global type = (Dwarf_Global) type_in;
+
+ return dwarf_global_cu_offset(type, ret_offset, error);
+}
+
+
+int
+dwarf_type_name_offsets(Dwarf_Type type_in,
+ char **returned_name,
+ Dwarf_Off * die_offset,
+ Dwarf_Off * cu_die_offset, Dwarf_Error * error)
+{
+ Dwarf_Global type = (Dwarf_Global) type_in;
+ return dwarf_global_name_offsets(type,
+ returned_name,
+ die_offset, cu_die_offset, error);
+}
diff --git a/libdwarf/dwarf_types.h b/libdwarf/dwarf_types.h
new file mode 100644
index 0000000..ebd31c6
--- /dev/null
+++ b/libdwarf/dwarf_types.h
@@ -0,0 +1,41 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+
+typedef struct Dwarf_Type_Context_s *Dwarf_Type_Context;
+
+/* type never completed see dwarf_global.h */
diff --git a/libdwarf/dwarf_util.c b/libdwarf/dwarf_util.c
new file mode 100644
index 0000000..5af6232
--- /dev/null
+++ b/libdwarf/dwarf_util.c
@@ -0,0 +1,584 @@
+/*
+ Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include "dwarf_die_deliv.h"
+
+
+
+/* Given a form, and a pointer to the bytes encoding
+ a value of that form, val_ptr, this function returns
+ the length, in bytes, of a value of that form.
+ When using this function, check for a return of 0
+ a recursive DW_FORM_INDIRECT value. */
+Dwarf_Unsigned
+_dwarf_get_size_of_val(Dwarf_Debug dbg,
+ Dwarf_Unsigned form,
+ Dwarf_Half address_size,
+ Dwarf_Small * val_ptr, int v_length_size)
+{
+ Dwarf_Unsigned length = 0;
+ Dwarf_Word leb128_length = 0;
+ Dwarf_Unsigned form_indirect = 0;
+ Dwarf_Unsigned ret_value = 0;
+
+ switch (form) {
+
+ default: /* Handles form = 0. */
+ return (form);
+
+ case DW_FORM_addr:
+ if(address_size) {
+ return address_size;
+ }
+ /* This should never happen, address_size should be set. */
+ return (dbg->de_pointer_size);
+ case DW_FORM_ref_sig8:
+ return 8; /* sizeof Dwarf_Sig8 */
+
+ /* DWARF2 was wrong on the size of the attribute for
+ DW_FORM_ref_addr. We assume compilers are using the
+ corrected DWARF3 text (for 32bit pointer target objects pointer and
+ offsets are the same size anyway). */
+ case DW_FORM_ref_addr:
+ return (v_length_size);
+
+ case DW_FORM_block1:
+ return (*(Dwarf_Small *) val_ptr + 1);
+
+ case DW_FORM_block2:
+ READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
+ val_ptr, sizeof(Dwarf_Half));
+ return (ret_value + sizeof(Dwarf_Half));
+
+ case DW_FORM_block4:
+ READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
+ val_ptr, sizeof(Dwarf_ufixed));
+ return (ret_value + sizeof(Dwarf_ufixed));
+
+
+ case DW_FORM_data1:
+ return (1);
+
+ case DW_FORM_data2:
+ return (2);
+
+ case DW_FORM_data4:
+ return (4);
+
+ case DW_FORM_data8:
+ return (8);
+
+ case DW_FORM_string:
+ return (strlen((char *) val_ptr) + 1);
+
+ case DW_FORM_block:
+ case DW_FORM_exprloc:
+ length = _dwarf_decode_u_leb128(val_ptr, &leb128_length);
+ return (length + leb128_length);
+
+ case DW_FORM_flag_present:
+ return (0);
+ case DW_FORM_flag:
+ return (1);
+
+ case DW_FORM_sec_offset:
+ /* If 32bit dwarf, is 4. Else is 64bit dwarf and is 8. */
+ return (v_length_size);
+
+ case DW_FORM_ref_udata:
+ /* Discard the decoded value, we just want the length
+ of the value. */
+ _dwarf_decode_u_leb128(val_ptr, &leb128_length);
+ return (leb128_length);
+
+ case DW_FORM_indirect:
+ {
+ Dwarf_Word indir_len = 0;
+
+ form_indirect = _dwarf_decode_u_leb128(val_ptr, &indir_len);
+ if (form_indirect == DW_FORM_indirect) {
+ return (0); /* We are in big trouble: The true form
+ of DW_FORM_indirect is
+ DW_FORM_indirect? Nonsense. Should
+ never happen. */
+ }
+ return (indir_len + _dwarf_get_size_of_val(dbg,
+ form_indirect,
+ address_size,
+ val_ptr + indir_len,
+ v_length_size));
+ }
+
+ case DW_FORM_ref1:
+ return (1);
+
+ case DW_FORM_ref2:
+ return (2);
+
+ case DW_FORM_ref4:
+ return (4);
+
+ case DW_FORM_ref8:
+ return (8);
+
+ case DW_FORM_sdata:
+ /* Discard the decoded value, we just want the length
+ of the value. */
+ _dwarf_decode_s_leb128(val_ptr, &leb128_length);
+ return (leb128_length);
+
+ case DW_FORM_strp:
+ return (v_length_size);
+
+ case DW_FORM_udata:
+ /* Discard the decoded value, we just want the length
+ of the value. */
+ _dwarf_decode_u_leb128(val_ptr, &leb128_length);
+ return (leb128_length);
+ }
+}
+
+/* We allow an arbitrary number of HT_MULTIPLE entries
+ before resizing. It seems up to 20 or 30
+ would work nearly as well.
+ We could have a different resize multiple than 'resize now'
+ test multiple, but for now we don't do that. */
+#define HT_MULTIPLE 8
+
+/* Copy the old entries, updating each to be in
+ a new list. Don't delete anything. Leave the
+ htin with stale data. */
+static void
+copy_abbrev_table_to_new_table(Dwarf_Hash_Table htin,
+ Dwarf_Hash_Table htout)
+{
+ Dwarf_Hash_Table_Entry entry_in = htin->tb_entries;
+ unsigned entry_in_count = htin->tb_table_entry_count;
+ Dwarf_Hash_Table_Entry entry_out = htout->tb_entries;
+ unsigned entry_out_count = htout->tb_table_entry_count;
+ unsigned k = 0;
+ for ( ; k < entry_in_count; ++k,++entry_in) {
+ Dwarf_Abbrev_List listent = entry_in->at_head;
+ Dwarf_Abbrev_List nextlistent = 0;
+
+ for ( ; listent ; listent = nextlistent) {
+ unsigned newtmp = listent->ab_code;
+ unsigned newhash = newtmp%entry_out_count;
+ Dwarf_Hash_Table_Entry e;
+ nextlistent = listent->ab_next;
+ e = entry_out+newhash;
+ /* Move_entry_to_new_hash. This reverses the
+ order of the entries, effectively, but
+ that does not seem significant. */
+ listent->ab_next = e->at_head;
+ e->at_head = listent;
+
+ htout->tb_total_abbrev_count++;
+ }
+ }
+}
+
+/* This function returns a pointer to a Dwarf_Abbrev_List_s
+ struct for the abbrev with the given code. It puts the
+ struct on the appropriate hash table. It also adds all
+ the abbrev between the last abbrev added and this one to
+ the hash table. In other words, the .debug_abbrev section
+ is scanned sequentially from the top for an abbrev with
+ the given code. All intervening abbrevs are also put
+ into the hash table.
+
+ This function hashes the given code, and checks the chain
+ at that hash table entry to see if a Dwarf_Abbrev_List_s
+ with the given code exists. If yes, it returns a pointer
+ to that struct. Otherwise, it scans the .debug_abbrev
+ section from the last byte scanned for that CU till either
+ an abbrev with the given code is found, or an abbrev code
+ of 0 is read. It puts Dwarf_Abbrev_List_s entries for all
+ abbrev's read till that point into the hash table. The
+ hash table contains both a head pointer and a tail pointer
+ for each entry.
+
+ While the lists can move and entries can be moved between
+ lists on reallocation, any given Dwarf_Abbrev_list entry
+ never moves once allocated, so the pointer is safe to return.
+
+ Returns NULL on error. */
+Dwarf_Abbrev_List
+_dwarf_get_abbrev_for_code(Dwarf_CU_Context cu_context, Dwarf_Unsigned code)
+{
+ Dwarf_Debug dbg = cu_context->cc_dbg;
+ Dwarf_Hash_Table hash_table_base = cu_context->cc_abbrev_hash_table;
+ Dwarf_Hash_Table_Entry entry_base = 0;
+ Dwarf_Hash_Table_Entry entry_cur = 0;
+ Dwarf_Word hash_num = 0;
+ Dwarf_Unsigned abbrev_code = 0;
+ Dwarf_Unsigned abbrev_tag = 0;
+ Dwarf_Unsigned attr_name = 0;
+ Dwarf_Unsigned attr_form = 0;
+
+ Dwarf_Abbrev_List hash_abbrev_entry = 0;
+
+ Dwarf_Abbrev_List inner_list_entry = 0;
+ Dwarf_Hash_Table_Entry inner_hash_entry = 0;
+
+ Dwarf_Byte_Ptr abbrev_ptr = 0;
+ Dwarf_Byte_Ptr end_abbrev_ptr = 0;
+ unsigned hashable_val = 0;
+
+ if ( !hash_table_base->tb_entries ) {
+ hash_table_base->tb_table_entry_count = HT_MULTIPLE;
+ hash_table_base->tb_total_abbrev_count= 0;
+ hash_table_base->tb_entries = _dwarf_get_alloc(dbg,
+ DW_DLA_HASH_TABLE_ENTRY,
+ hash_table_base->tb_table_entry_count);
+ if(! hash_table_base->tb_entries) {
+ return NULL;
+ }
+
+ } else if (hash_table_base->tb_total_abbrev_count >
+ ( hash_table_base->tb_table_entry_count * HT_MULTIPLE) ) {
+ struct Dwarf_Hash_Table_s newht;
+ /* Effectively multiplies by >= HT_MULTIPLE */
+ newht.tb_table_entry_count = hash_table_base->tb_total_abbrev_count;
+ newht.tb_total_abbrev_count = 0;
+ newht.tb_entries = _dwarf_get_alloc(dbg,
+ DW_DLA_HASH_TABLE_ENTRY,
+ newht.tb_table_entry_count);
+
+ if(! newht.tb_entries) {
+ return NULL;
+ }
+ /* Copy the existing entries to the new table,
+ rehashing each. */
+ copy_abbrev_table_to_new_table(hash_table_base, &newht);
+ /* Dealloc only the entries hash table array, not the lists
+ of things pointed to by a hash table entry array. */
+ dwarf_dealloc(dbg, hash_table_base->tb_entries,DW_DLA_HASH_TABLE_ENTRY);
+ hash_table_base->tb_entries = 0;
+ /* Now overwrite the existing table descriptor with
+ the new, newly valid, contents. */
+ *hash_table_base = newht;
+ } /* Else is ok as is, add entry */
+
+
+ hashable_val = code;
+ hash_num = hashable_val %
+ hash_table_base->tb_table_entry_count;
+ entry_base = hash_table_base->tb_entries;
+ entry_cur = entry_base + hash_num;
+
+ /* Determine if the 'code' is the list of synonyms already. */
+ for (hash_abbrev_entry = entry_cur->at_head;
+ hash_abbrev_entry != NULL && hash_abbrev_entry->ab_code != code;
+ hash_abbrev_entry = hash_abbrev_entry->ab_next);
+ if (hash_abbrev_entry != NULL) {
+ /* This returns a pointer to an abbrev list entry, not
+ the list itself. */
+ return (hash_abbrev_entry);
+ }
+
+ abbrev_ptr = cu_context->cc_last_abbrev_ptr != NULL ?
+ cu_context->cc_last_abbrev_ptr :
+ dbg->de_debug_abbrev.dss_data + cu_context->cc_abbrev_offset;
+ end_abbrev_ptr = dbg->de_debug_abbrev.dss_data +
+ dbg->de_debug_abbrev.dss_size;
+
+ /* End of abbrev's as we are past the end entirely.
+ THis can happen */
+ if (abbrev_ptr > end_abbrev_ptr) {
+ return (NULL);
+ }
+ /* End of abbrev's for this cu, since abbrev code is 0. */
+ if (*abbrev_ptr == 0) {
+ return (NULL);
+ }
+
+ do {
+ unsigned new_hashable_val = 0;
+ DECODE_LEB128_UWORD(abbrev_ptr, abbrev_code);
+ DECODE_LEB128_UWORD(abbrev_ptr, abbrev_tag);
+
+ inner_list_entry = (Dwarf_Abbrev_List)
+ _dwarf_get_alloc(cu_context->cc_dbg, DW_DLA_ABBREV_LIST, 1);
+ if (inner_list_entry == NULL) {
+ return (NULL);
+ }
+
+ new_hashable_val = abbrev_code;
+ hash_num = new_hashable_val %
+ hash_table_base->tb_table_entry_count;
+ inner_hash_entry = entry_base + hash_num;
+ /* Move_entry_to_new_hash */
+ inner_list_entry->ab_next = inner_hash_entry->at_head;
+ inner_hash_entry->at_head = inner_list_entry;
+
+ hash_table_base->tb_total_abbrev_count++;
+
+ inner_list_entry->ab_code = abbrev_code;
+ inner_list_entry->ab_tag = abbrev_tag;
+ inner_list_entry->ab_has_child = *(abbrev_ptr++);
+ inner_list_entry->ab_abbrev_ptr = abbrev_ptr;
+
+ /* Cycle thru the abbrev content, ignoring the content except
+ to find the end of the content. */
+ do {
+ DECODE_LEB128_UWORD(abbrev_ptr, attr_name);
+ DECODE_LEB128_UWORD(abbrev_ptr, attr_form);
+ } while (attr_name != 0 && attr_form != 0);
+
+ /* We may have fallen off the end of content, that is not
+ a botch in the section, as there is no rule that the last
+ abbrev need have abbrev_code of 0. */
+ } while ( (abbrev_ptr < end_abbrev_ptr ) &&
+ *abbrev_ptr != 0 && abbrev_code != code);
+
+ cu_context->cc_last_abbrev_ptr = abbrev_ptr;
+ return (abbrev_code == code ? inner_list_entry : NULL);
+}
+
+
+/* return 1 if string ends before 'endptr' else
+** return 0 meaning string is not properly terminated.
+** Presumption is the 'endptr' pts to end of some dwarf section data.
+*/
+int
+_dwarf_string_valid(void *startptr, void *endptr)
+{
+
+ char *start = startptr;
+ char *end = endptr;
+
+ while (start < end) {
+ if (*start == 0) {
+ return 1; /* OK! */
+ }
+ ++start;
+ ++end;
+ }
+ return 0; /* FAIL! bad string! */
+}
+
+/*
+ A byte-swapping version of memcpy
+ for cross-endian use.
+ Only 2,4,8 should be lengths passed in.
+*/
+void *
+_dwarf_memcpy_swap_bytes(void *s1, const void *s2, size_t len)
+{
+ void *orig_s1 = s1;
+ unsigned char *targ = (unsigned char *) s1;
+ unsigned char *src = (unsigned char *) s2;
+
+ if (len == 4) {
+ targ[3] = src[0];
+ targ[2] = src[1];
+ targ[1] = src[2];
+ targ[0] = src[3];
+ } else if (len == 8) {
+ targ[7] = src[0];
+ targ[6] = src[1];
+ targ[5] = src[2];
+ targ[4] = src[3];
+ targ[3] = src[4];
+ targ[2] = src[5];
+ targ[1] = src[6];
+ targ[0] = src[7];
+ } else if (len == 2) {
+ targ[1] = src[0];
+ targ[0] = src[1];
+ }
+/* should NOT get below here: is not the intended use */
+ else if (len == 1) {
+ targ[0] = src[0];
+ } else {
+ memcpy(s1, s2, len);
+ }
+
+ return orig_s1;
+}
+
+
+/* This calculation used to be sprinkled all over.
+ Now brought to one place.
+
+ We try to accurately compute the size of a cu header
+ given a known cu header location ( an offset in .debug_info
+ or debug_types). */
+/* ARGSUSED */
+Dwarf_Unsigned
+_dwarf_length_of_cu_header(Dwarf_Debug dbg, Dwarf_Unsigned offset,
+ Dwarf_Bool is_info)
+{
+ int local_length_size = 0;
+ int local_extension_size = 0;
+ Dwarf_Unsigned length = 0;
+ Dwarf_Unsigned final_size = 0;
+ Dwarf_Small *cuptr =
+ is_info? dbg->de_debug_info.dss_data + offset:
+ dbg->de_debug_types.dss_data+ offset;
+
+ READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
+ cuptr, local_length_size, local_extension_size);
+
+ final_size = local_extension_size + /* initial extension, if present */
+ local_length_size + /* Size of cu length field. */
+ sizeof(Dwarf_Half) + /* Size of version stamp field. */
+ local_length_size + /* Size of abbrev offset field. */
+ sizeof(Dwarf_Small); /* Size of address size field. */
+
+ if(!is_info) {
+ final_size +=
+ /* type signature size */
+ sizeof (Dwarf_Sig8) +
+ /* type offset size */
+ local_length_size;
+ }
+ return final_size;
+}
+
+/* Pretend we know nothing about the CU
+ and just roughly compute the result. */
+Dwarf_Unsigned
+_dwarf_length_of_cu_header_simple(Dwarf_Debug dbg,
+ Dwarf_Bool dinfo)
+{
+ Dwarf_Unsigned finalsize = 0;
+ finalsize = dbg->de_length_size + /* Size of cu length field. */
+ sizeof(Dwarf_Half) + /* Size of version stamp field. */
+ dbg->de_length_size + /* Size of abbrev offset field. */
+ sizeof(Dwarf_Small); /* Size of address size field. */
+ if(!dinfo) {
+ finalsize +=
+ /* type signature size */
+ sizeof (Dwarf_Sig8) +
+ /* type offset size */
+ dbg->de_length_size;
+ }
+ return finalsize;
+}
+
+/* Now that we delay loading .debug_info, we need to do the
+ load in more places. So putting the load
+ code in one place now instead of replicating it in multiple
+ places. */
+int
+_dwarf_load_debug_info(Dwarf_Debug dbg, Dwarf_Error * error)
+{
+ int res = DW_DLV_ERROR;
+ if (dbg->de_debug_info.dss_data) {
+ return DW_DLV_OK;
+ }
+ res = _dwarf_load_section(dbg, &dbg->de_debug_abbrev,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ res = _dwarf_load_section(dbg, &dbg->de_debug_info, error);
+ return res;
+}
+int
+_dwarf_load_debug_types(Dwarf_Debug dbg, Dwarf_Error * error)
+{
+ int res = DW_DLV_ERROR;
+ if (dbg->de_debug_types.dss_data) {
+ return DW_DLV_OK;
+ }
+ res = _dwarf_load_section(dbg, &dbg->de_debug_abbrev,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ res = _dwarf_load_section(dbg, &dbg->de_debug_types, error);
+ return res;
+}
+void
+_dwarf_free_abbrev_hash_table_contents(Dwarf_Debug dbg,Dwarf_Hash_Table hash_table)
+{
+ /* A Hash Table is an array with tb_table_entry_count struct
+ Dwarf_Hash_Table_s entries in the array. */
+ int hashnum = 0;
+ for (; hashnum < hash_table->tb_table_entry_count; ++hashnum) {
+ struct Dwarf_Abbrev_List_s *abbrev = 0;
+ struct Dwarf_Abbrev_List_s *nextabbrev = 0;
+ struct Dwarf_Hash_Table_Entry_s *tb = &hash_table->tb_entries[hashnum];
+
+ abbrev = tb->at_head;
+ for (; abbrev; abbrev = nextabbrev) {
+ nextabbrev = abbrev->ab_next;
+ dwarf_dealloc(dbg, abbrev, DW_DLA_ABBREV_LIST);
+ }
+ }
+ /* Frees all the entries at once: an array. */
+ dwarf_dealloc(dbg,hash_table->tb_entries,DW_DLA_HASH_TABLE_ENTRY);
+}
+
+/*
+ If no die provided the size value returned might be wrong.
+ If different compilation units have different address sizes
+ this may not give the correct value in all contexts if the die
+ pointer is NULL.
+ If the Elf offset size != address_size
+ (for example if address_size = 4 but recorded in elf64 object)
+ this may not give the correct value in all contexts if the die
+ pointer is NULL.
+ If the die pointer is non-NULL (in which case it must point to
+ a valid DIE) this will return the correct size.
+*/
+int
+_dwarf_get_address_size(Dwarf_Debug dbg, Dwarf_Die die)
+{
+ Dwarf_CU_Context context = 0;
+ Dwarf_Half addrsize = 0;
+ if(!die) {
+ return dbg->de_pointer_size;
+ }
+ context = die->di_cu_context;
+ addrsize = context->cc_address_size;
+ return addrsize;
+}
+
+
+
diff --git a/libdwarf/dwarf_util.h b/libdwarf/dwarf_util.h
new file mode 100644
index 0000000..fb66916
--- /dev/null
+++ b/libdwarf/dwarf_util.h
@@ -0,0 +1,324 @@
+#ifndef DWARF_UTIL_H
+#define DWARF_UTIL_H
+/*
+
+ Copyright (C) 2000,2003,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved.
+ Portions Copyright (C) 2010 SN Systems Ltd. All Rights Reserved
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+
+
+
+/*
+ Decodes unsigned leb128 encoded numbers.
+ Make sure ptr is a pointer to a 1-byte type.
+ In 2003 and earlier this was a hand-inlined
+ version of _dwarf_decode_u_leb128() which did
+ not work correctly if Dwarf_Word was 64 bits.
+*/
+#define DECODE_LEB128_UWORD(ptr, value) \
+ do { \
+ Dwarf_Word uleblen; \
+ value = _dwarf_decode_u_leb128(ptr,&uleblen); \
+ ptr += uleblen; \
+ } while (0)
+
+/*
+ Decodes signed leb128 encoded numbers.
+ Make sure ptr is a pointer to a 1-byte type.
+ In 2003 and earlier this was a hand-inlined
+ version of _dwarf_decode_s_leb128() which did
+ not work correctly if Dwarf_Word was 64 bits.
+
+*/
+#define DECODE_LEB128_SWORD(ptr, value) \
+ do { \
+ Dwarf_Word sleblen; \
+ value = _dwarf_decode_s_leb128(ptr,&sleblen); \
+ ptr += sleblen; \
+ } while(0)
+
+
+/*
+ Skips leb128_encoded numbers that are guaranteed
+ to be no more than 4 bytes long. Same for both
+ signed and unsigned numbers.
+*/
+#define SKIP_LEB128_WORD(ptr) \
+ do{ if ((*(ptr++) & 0x80) != 0) { \
+ if ((*(ptr++) & 0x80) != 0) { \
+ if ((*(ptr++) & 0x80) != 0) { \
+ if ((*(ptr++) & 0x80) != 0) { \
+ } \
+ } \
+ } \
+ } } while (0)
+
+
+#define CHECK_DIE(die, error_ret_value) \
+do { \
+ if (die == NULL) { \
+ _dwarf_error(NULL, error, DW_DLE_DIE_NULL); \
+ return(error_ret_value); \
+ } \
+ if (die->di_cu_context == NULL) { \
+ _dwarf_error(NULL, error, DW_DLE_DIE_NO_CU_CONTEXT); \
+ return(error_ret_value); \
+ } \
+ if (die->di_cu_context->cc_dbg == NULL) { \
+ _dwarf_error(NULL, error, DW_DLE_DBG_NULL); \
+ return(error_ret_value); \
+ } \
+} while (0)
+
+
+/*
+ Reads 'source' for 'length' bytes from unaligned addr.
+
+ Avoids any constant-in-conditional warnings and
+ avoids a test in the generated code (for non-const cases,
+ which are in the majority.)
+ Uses a temp to avoid the test.
+ The decl here should avoid any problem of size in the temp.
+ This code is ENDIAN DEPENDENT
+ The memcpy args are the endian issue.
+*/
+typedef Dwarf_Unsigned BIGGEST_UINT;
+
+#ifdef WORDS_BIGENDIAN
+#define READ_UNALIGNED(dbg,dest,desttype, source, length) \
+ do { \
+ BIGGEST_UINT _ltmp = 0; \
+ dbg->de_copy_word( (((char *)(&_ltmp)) + sizeof(_ltmp) - length), \
+ source, length) ; \
+ dest = (desttype)_ltmp; \
+ } while (0)
+
+
+/*
+ This macro sign-extends a variable depending on the length.
+ It fills the bytes between the size of the destination and
+ the length with appropriate padding.
+ This code is ENDIAN DEPENDENT but dependent only
+ on host endianness, not object file endianness.
+ The memcpy args are the issue.
+*/
+#define SIGN_EXTEND(dest, length) \
+ do {if (*(Dwarf_Sbyte *)((char *)&dest + sizeof(dest) - length) < 0) {\
+ memcpy((char *)&dest, "\xff\xff\xff\xff\xff\xff\xff\xff", \
+ sizeof(dest) - length); \
+ } \
+ } while (0)
+#else /* LITTLE ENDIAN */
+
+#define READ_UNALIGNED(dbg,dest,desttype, source, length) \
+ do { \
+ BIGGEST_UINT _ltmp = 0; \
+ dbg->de_copy_word( (char *)(&_ltmp) , \
+ source, length) ; \
+ dest = (desttype)_ltmp; \
+ } while (0)
+
+
+/*
+ This macro sign-extends a variable depending on the length.
+ It fills the bytes between the size of the destination and
+ the length with appropriate padding.
+ This code is ENDIAN DEPENDENT but dependent only
+ on host endianness, not object file endianness.
+ The memcpy args are the issue.
+*/
+#define SIGN_EXTEND(dest, length) \
+ do {if (*(Dwarf_Sbyte *)((char *)&dest + (length-1)) < 0) {\
+ memcpy((char *)&dest+length, \
+ "\xff\xff\xff\xff\xff\xff\xff\xff", \
+ sizeof(dest) - length); \
+ } \
+ } while (0)
+
+#endif /* ! LITTLE_ENDIAN */
+
+
+
+/*
+ READ_AREA LENGTH reads the length (the older way
+ of pure 32 or 64 bit
+ or the dwarf v3 64bit-extension way)
+
+ It reads the bits from where rw_src_data_p points to
+ and updates the rw_src_data_p to point past what was just read.
+
+ It updates w_length_size (to the size of an offset, either 4 or 8)
+ and w_exten_size (set 0 unless this frame has the DWARF3,4 64bit
+ extension, in which case w_exten_size is set to 4).
+
+ r_dbg is just the current dbg pointer.
+ w_target is the output length field.
+ r_targtype is the output type. Always Dwarf_Unsigned so far.
+
+*/
+/* This one handles the v3 64bit extension
+ and 32bit (and SGI/MIPS fixed 64 bit via the
+ dwarf_init-set r_dbg->de_length_size)..
+ It does not recognize any but the one distingushed value
+ (the only one with defined meaning).
+ It assumes that no CU will have a length
+ 0xffffffxx (32bit length)
+ or
+ 0xffffffxx xxxxxxxx (64bit length)
+ which makes possible auto-detection of the extension.
+
+ This depends on knowing that only a non-zero length
+ is legitimate (AFAICT), and for IRIX non-standard -64
+ dwarf that the first 32 bits of the 64bit offset will be
+ zero (because the compiler could not handle a truly large
+ value as of Jan 2003 and because no app has that much debug
+ info anyway, at least not in the IRIX case).
+
+ At present not testing for '64bit elf' here as that
+ does not seem necessary (none of the 64bit length seems
+ appropriate unless it's ident[EI_CLASS] == ELFCLASS64).
+*/
+# define READ_AREA_LENGTH(r_dbg,w_target,r_targtype, \
+ rw_src_data_p,w_length_size,w_exten_size) \
+do { \
+ READ_UNALIGNED(r_dbg,w_target,r_targtype, \
+ rw_src_data_p, ORIGINAL_DWARF_OFFSET_SIZE); \
+ if(w_target == DISTINGUISHED_VALUE) { \
+ /* dwarf3 64bit extension */ \
+ w_length_size = DISTINGUISHED_VALUE_OFFSET_SIZE; \
+ rw_src_data_p += ORIGINAL_DWARF_OFFSET_SIZE; \
+ w_exten_size = ORIGINAL_DWARF_OFFSET_SIZE; \
+ READ_UNALIGNED(r_dbg,w_target,r_targtype, \
+ rw_src_data_p, DISTINGUISHED_VALUE_OFFSET_SIZE); \
+ rw_src_data_p += DISTINGUISHED_VALUE_OFFSET_SIZE; \
+ } else { \
+ if(w_target == 0 && r_dbg->de_big_endian_object) { \
+ /* Might be IRIX: We have to distinguish between */ \
+ /* 32-bit DWARF format and IRIX 64-bit DWARF format. */ \
+ if (r_dbg->de_length_size == 8) { \
+ /* IRIX 64 bit, big endian. This test */ \
+ /* is not a truly precise test, a precise test */ \
+ /* would check if the target was IRIX. */ \
+ READ_UNALIGNED(r_dbg,w_target,r_targtype, \
+ rw_src_data_p, DISTINGUISHED_VALUE_OFFSET_SIZE); \
+ w_length_size = DISTINGUISHED_VALUE_OFFSET_SIZE; \
+ rw_src_data_p += DISTINGUISHED_VALUE_OFFSET_SIZE; \
+ w_exten_size = 0; \
+ } else { \
+ /* 32 bit, big endian */ \
+ w_length_size = ORIGINAL_DWARF_OFFSET_SIZE; \
+ rw_src_data_p += w_length_size; \
+ w_exten_size = 0; \
+ } \
+ } else { \
+ /* Standard 32 bit dwarf2/dwarf3 */ \
+ w_exten_size = 0; \
+ w_length_size = ORIGINAL_DWARF_OFFSET_SIZE; \
+ rw_src_data_p += w_length_size; \
+ } \
+ } } while(0)
+
+Dwarf_Unsigned
+_dwarf_decode_u_leb128(Dwarf_Small * leb128,
+ Dwarf_Word * leb128_length);
+
+Dwarf_Signed
+_dwarf_decode_s_leb128(Dwarf_Small * leb128,
+ Dwarf_Word * leb128_length);
+
+Dwarf_Unsigned
+_dwarf_get_size_of_val(Dwarf_Debug dbg,
+ Dwarf_Unsigned form,
+ Dwarf_Half address_size,
+ Dwarf_Small * val_ptr,
+ int v_length_size);
+
+struct Dwarf_Hash_Table_Entry_s;
+/* This single struct is the base for the hash table.
+ The intent is that once the total_abbrev_count across
+ all the entries is greater than 10*current_table_entry_count
+ one should build a new Dwarf_Hash_Table_Base_s, rehash
+ all the existing entries, and delete the old table and entries.
+ (10 is a heuristic, nothing magic about it, but once the
+ count gets to 30 or 40 times current_table_entry_count
+ things really slow down a lot. One (500MB) application had
+ 127000 abbreviations in one compilation unit)
+ The incoming 'code' is an abbrev number and those simply
+ increase linearly so the hashing is perfect always.
+*/
+struct Dwarf_Hash_Table_s {
+ unsigned long tb_table_entry_count;
+ unsigned long tb_total_abbrev_count;
+ /* Each table entry is a list of abbreviations. */
+ struct Dwarf_Hash_Table_Entry_s *tb_entries;
+};
+
+/*
+ This struct is used to build a hash table for the
+ abbreviation codes for a compile-unit.
+*/
+struct Dwarf_Hash_Table_Entry_s {
+ Dwarf_Abbrev_List at_head;
+};
+
+
+
+Dwarf_Abbrev_List
+_dwarf_get_abbrev_for_code(Dwarf_CU_Context cu_context,
+ Dwarf_Unsigned code);
+
+
+/* return 1 if string ends before 'endptr' else
+** return 0 meaning string is not properly terminated.
+** Presumption is the 'endptr' pts to end of some dwarf section data.
+*/
+int _dwarf_string_valid(void *startptr, void *endptr);
+
+Dwarf_Unsigned _dwarf_length_of_cu_header(Dwarf_Debug,
+ Dwarf_Unsigned offset,Dwarf_Bool dinfo);
+Dwarf_Unsigned _dwarf_length_of_cu_header_simple(Dwarf_Debug,Dwarf_Bool dinfo);
+
+int _dwarf_load_debug_info(Dwarf_Debug dbg, Dwarf_Error *error);
+int _dwarf_load_debug_types(Dwarf_Debug dbg, Dwarf_Error *error);
+void _dwarf_free_abbrev_hash_table_contents(Dwarf_Debug dbg,
+ struct Dwarf_Hash_Table_s* hash_table);
+int _dwarf_get_address_size(Dwarf_Debug dbg, Dwarf_Die die);
+
+#endif /* DWARF_UTIL_H */
diff --git a/libdwarf/dwarf_vars.c b/libdwarf/dwarf_vars.c
new file mode 100644
index 0000000..4df0f5d
--- /dev/null
+++ b/libdwarf/dwarf_vars.c
@@ -0,0 +1,136 @@
+/*
+
+ Copyright (C) 2000,2002,2004,2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include "dwarf_vars.h"
+#include "dwarf_global.h"
+
+int
+dwarf_get_vars(Dwarf_Debug dbg,
+ Dwarf_Var ** vars,
+ Dwarf_Signed * ret_var_count, Dwarf_Error * error)
+{
+ int res = _dwarf_load_section(dbg, &dbg->de_debug_varnames,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ if (!dbg->de_debug_abbrev.dss_size) {
+ return (DW_DLV_NO_ENTRY);
+ }
+
+ return _dwarf_internal_get_pubnames_like_data(dbg,
+ dbg->de_debug_varnames.dss_data,
+ dbg->de_debug_varnames.dss_size,
+ (Dwarf_Global **) vars, /* Type punning for sections
+ with identical format. */
+ ret_var_count,
+ error,
+ DW_DLA_VAR_CONTEXT,
+ DW_DLA_VAR,
+ DW_DLE_DEBUG_VARNAMES_LENGTH_BAD,
+ DW_DLE_DEBUG_VARNAMES_VERSION_ERROR);
+}
+
+/* Deallocating fully requires deallocating the list
+ and all entries. But some internal data is
+ not exposed, so we need a function with internal knowledge.
+*/
+
+void
+dwarf_vars_dealloc(Dwarf_Debug dbg, Dwarf_Var * dwgl,
+ Dwarf_Signed count)
+{
+ _dwarf_internal_globals_dealloc(dbg, (Dwarf_Global *) dwgl,
+ count,
+ DW_DLA_VAR_CONTEXT,
+ DW_DLA_VAR, DW_DLA_LIST);
+ return;
+}
+
+
+int
+dwarf_varname(Dwarf_Var var_in, char **ret_varname, Dwarf_Error * error)
+{
+ Dwarf_Global var = (Dwarf_Global) var_in;
+
+ if (var == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_VAR_NULL);
+ return (DW_DLV_ERROR);
+ }
+
+ *ret_varname = (char *) (var->gl_name);
+ return DW_DLV_OK;
+}
+
+
+int
+dwarf_var_die_offset(Dwarf_Var var_in,
+ Dwarf_Off * returned_offset, Dwarf_Error * error)
+{
+ Dwarf_Global var = (Dwarf_Global) var_in;
+
+ return dwarf_global_die_offset(var, returned_offset, error);
+
+}
+
+
+int
+dwarf_var_cu_offset(Dwarf_Var var_in,
+ Dwarf_Off * returned_offset, Dwarf_Error * error)
+{
+ Dwarf_Global var = (Dwarf_Global) var_in;
+
+ return dwarf_global_cu_offset(var, returned_offset, error);
+}
+
+
+int
+dwarf_var_name_offsets(Dwarf_Var var_in,
+ char **returned_name,
+ Dwarf_Off * die_offset,
+ Dwarf_Off * cu_offset, Dwarf_Error * error)
+{
+ Dwarf_Global var = (Dwarf_Global) var_in;
+
+ return
+ dwarf_global_name_offsets(var,
+ returned_name, die_offset, cu_offset,
+ error);
+}
diff --git a/libdwarf/dwarf_vars.h b/libdwarf/dwarf_vars.h
new file mode 100644
index 0000000..bd5f967
--- /dev/null
+++ b/libdwarf/dwarf_vars.h
@@ -0,0 +1,41 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+
+typedef struct Dwarf_Var_Context_s *Dwarf_Var_Context;
+
+/* struct never completed: see dwarf_global.h */
diff --git a/libdwarf/dwarf_weaks.c b/libdwarf/dwarf_weaks.c
new file mode 100644
index 0000000..1d0c70d
--- /dev/null
+++ b/libdwarf/dwarf_weaks.c
@@ -0,0 +1,134 @@
+/*
+
+ Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "dwarf_incl.h"
+#include <stdio.h>
+#include "dwarf_weaks.h"
+#include "dwarf_global.h"
+
+int
+dwarf_get_weaks(Dwarf_Debug dbg,
+ Dwarf_Weak ** weaks,
+ Dwarf_Signed * ret_weak_count, Dwarf_Error * error)
+{
+ int res = _dwarf_load_section(dbg, &dbg->de_debug_weaknames,error);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ if (!dbg->de_debug_weaknames.dss_size) {
+ return (DW_DLV_NO_ENTRY);
+ }
+
+
+ return _dwarf_internal_get_pubnames_like_data(dbg,
+ dbg->de_debug_weaknames.dss_data,
+ dbg->de_debug_weaknames.dss_size,
+ (Dwarf_Global **) weaks, /* Type punning for sections
+ with identical format. */
+ ret_weak_count,
+ error,
+ DW_DLA_WEAK_CONTEXT,
+ DW_DLA_WEAK,
+ DW_DLE_DEBUG_WEAKNAMES_LENGTH_BAD,
+ DW_DLE_DEBUG_WEAKNAMES_VERSION_ERROR);
+}
+
+/* Deallocating fully requires deallocating the list
+ and all entries. But some internal data is
+ not exposed, so we need a function with internal knowledge.
+*/
+
+void
+dwarf_weaks_dealloc(Dwarf_Debug dbg, Dwarf_Weak * dwgl,
+ Dwarf_Signed count)
+{
+ _dwarf_internal_globals_dealloc(dbg, (Dwarf_Global *) dwgl,
+ count,
+ DW_DLA_WEAK_CONTEXT,
+ DW_DLA_WEAK, DW_DLA_LIST);
+ return;
+}
+
+
+
+int
+dwarf_weakname(Dwarf_Weak weak_in, char **ret_name, Dwarf_Error * error)
+{
+ Dwarf_Global weak = (Dwarf_Global) weak_in;
+
+ if (weak == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_WEAK_NULL);
+ return (DW_DLV_ERROR);
+ }
+ *ret_name = (char *) (weak->gl_name);
+ return DW_DLV_OK;
+}
+
+
+int
+dwarf_weak_die_offset(Dwarf_Weak weak_in,
+ Dwarf_Off * weak_off, Dwarf_Error * error)
+{
+ Dwarf_Global weak = (Dwarf_Global) weak_in;
+
+ return dwarf_global_die_offset(weak, weak_off, error);
+}
+
+
+int
+dwarf_weak_cu_offset(Dwarf_Weak weak_in,
+ Dwarf_Off * weak_off, Dwarf_Error * error)
+{
+ Dwarf_Global weak = (Dwarf_Global) weak_in;
+
+ return dwarf_global_cu_offset(weak, weak_off, error);
+}
+
+
+int
+dwarf_weak_name_offsets(Dwarf_Weak weak_in,
+ char **weak_name,
+ Dwarf_Off * die_offset,
+ Dwarf_Off * cu_offset, Dwarf_Error * error)
+{
+ Dwarf_Global weak = (Dwarf_Global) weak_in;
+
+ return dwarf_global_name_offsets(weak,
+ weak_name, die_offset, cu_offset, error);
+}
diff --git a/libdwarf/dwarf_weaks.h b/libdwarf/dwarf_weaks.h
new file mode 100644
index 0000000..d38f5f1
--- /dev/null
+++ b/libdwarf/dwarf_weaks.h
@@ -0,0 +1,41 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+
+typedef struct Dwarf_Weak_Context_s *Dwarf_Weak_Context;
+
+/* struct never completed: see dwarf_global.h */
diff --git a/libdwarf/gennames.c b/libdwarf/gennames.c
new file mode 100644
index 0000000..6cfe0a3
--- /dev/null
+++ b/libdwarf/gennames.c
@@ -0,0 +1,541 @@
+/*
+ Copyright 2009-2010 SN Systems Ltd. All rights reserved.
+ Portions Copyright 2009-2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+#include <stdio.h>
+#include <stdlib.h> /* For exit() declaration etc. */
+#include <errno.h> /* For errno declaration. */
+#include <ctype.h>
+#include <string.h>
+#include <unistd.h> /* For getopt */
+#include "dwarf.h"
+#include "common.h"
+
+/* gennames.c
+ Prints routines to return constant name for the associated value
+ (such as the TAG name string for a particular tag).
+
+ The input is dwarf.h
+ For each set of names with a common prefix, we create a routine
+ to return the name given the value.
+ Also print header file that gives prototypes of routines.
+ To handle cases where there are multiple names for a single
+ value (DW_AT_* has some due to ambiguities in the DWARF2 spec)
+ we take the first of a given value as the definitive name.
+ TAGs, Attributes, etc are given distinct checks.
+
+ There are multiple output files as some people find one
+ form more pleasant than the other.
+
+ The doprinting argument is so that when used by tag_tree.c,
+ and tag_attr.c that we don't get irritating messages on stderr
+ when those dwarfdump built-time applications are run.
+
+ Some compilers generate better code for switch statements than
+ others, so the -s and -t options let the user decide which
+ is better for their compiler (when building dwarfdump):
+ a simple switch or code doing binary search.
+ This choice affects the runtime speed of dwarfdump. */
+
+typedef int boolean;
+#define TRUE 1
+#define FALSE 0
+#define FAILED 1
+
+static void OpenAllFiles();
+static void WriteFileTrailers();
+static void CloseAllFiles();
+static void GenerateInitialFileLines();
+static void GenerateOneSet();
+#ifdef TRACE_ARRAY
+static void PrintArray(void);
+#endif /* TRACE_ARRAY */
+static boolean is_skippable_line(char *pLine);
+static void ParseDefinitionsAndWriteOutput();
+
+/* We don't need really long lines: the input file is simple. */
+#define MAX_LINE_SIZE 1000
+/* We don't need a variable array size, it just has to be big enough. */
+#define ARRAY_SIZE 256
+
+/* To store entries from dwarf.h */
+typedef struct {
+ char name[64]; /* short name */
+ unsigned value; /* value */
+} array_data;
+
+/* A group_array is a grouping from dwarf.h.
+ All the TAGs are one group, all the
+ FORMs are another group, and so on. */
+static array_data group_array[ARRAY_SIZE];
+static unsigned array_count = 0;
+
+typedef int (*compfn)(const void *,const void *);
+static int Compare(array_data *,array_data *);
+
+static char *prefix_root = "DW_";
+static unsigned prefix_root_len = 3;
+
+/* f_dwarf_in is the input dwarf.h. The others are output files. */
+static FILE *f_dwarf_in;
+static FILE *f_names_h;
+static FILE *f_names_c;
+static FILE *f_names_enum_h;
+static FILE *f_names_new_h;
+
+/* Size unchecked, but large enough. */
+static char prefix[200] = "";
+
+static const char *usage[] = {
+ "Usage: gennames <options>",
+ " -i input-table-path",
+ " -o output-table-path",
+ " -s use 'switch' in generation",
+ " -t use 'tables' in generation",
+ "",
+};
+
+char *program_name = 0;
+static char *input_name = 0;
+static char *output_name = 0;
+static boolean use_switch = TRUE;
+static boolean use_tables = FALSE;
+
+
+/* process arguments */
+static void
+process_args(int argc, char *argv[])
+{
+ int c = 0;
+ boolean usage_error = FALSE;
+
+ program_name = argv[0];
+
+ while ((c = getopt(argc, argv, "i:o:st")) != EOF) {
+ switch (c) {
+ case 'i':
+ input_name = optarg;
+ break;
+ case 'o':
+ output_name = optarg;
+ break;
+ case 's':
+ use_switch = TRUE;
+ use_tables = FALSE;
+ break;
+ case 't':
+ use_switch = FALSE;
+ use_tables = TRUE;
+ break;
+ default:
+ usage_error = TRUE;
+ break;
+ }
+ }
+
+ if (usage_error || 1 == optind || optind != argc) {
+ print_usage_message(usage);
+ exit(FAILED);
+ }
+}
+
+int
+main(int argc,char **argv)
+{
+ print_version(argv[0]);
+ process_args(argc,argv);
+ print_args(argc,argv);
+ OpenAllFiles();
+ GenerateInitialFileLines();
+ ParseDefinitionsAndWriteOutput();
+ WriteFileTrailers();
+ CloseAllFiles();
+ return 0;
+}
+
+/* Print the array used to hold the tags, attributes values */
+#ifdef TRACE_ARRAY
+static void
+PrintArray(void)
+{
+ int index;
+ for (index = 0; index < array_count; ++index) {
+ printf("%d: Name %s_%s, Value 0x%04x\n",
+ index,prefix,
+ array[index].name,
+ array[index].value);
+ }
+}
+#endif /* TRACE_ARRAY */
+
+static int
+Compare(array_data *elem1,array_data *elem2)
+{
+ if (elem1->value < elem2->value) {
+ return -1;
+ }
+ if (elem1->value > elem2->value) {
+ return 1;
+ }
+ return 0;
+}
+
+static FILE *
+open_path(const char *base, const char *file, const char *direction)
+{
+ FILE *f = 0;
+ /* POSIX PATH_MAX would suffice, normally stdio BUFSIZ is larger
+ than PATH_MAX */
+ char path_name[BUFSIZ];
+ snprintf(path_name,sizeof(path_name),"%s/%s",base,file);
+ f = fopen(path_name,direction);
+ if (!f) {
+ printf("Error openning '%s'\n",path_name);
+ exit(1);
+ }
+ return f;
+}
+
+/* Open files and write the basic headers */
+static void
+OpenAllFiles()
+{
+ char *dwarf_h = "dwarf.h";
+ char *names_h = "dwarf_names.h";
+ char *names_c = "dwarf_names.c";
+ char *names_enum_h = "dwarf_names_enum.h";
+ char *names_new_h = "dwarf_names_new.h";
+
+ f_dwarf_in = open_path(input_name,dwarf_h,"r");
+ f_names_enum_h = open_path(output_name,names_enum_h,"w");
+ f_names_new_h = open_path(output_name,names_new_h,"w");
+ f_names_h = open_path(output_name,names_h,"w");
+ f_names_c = open_path(output_name,names_c,"w");
+}
+
+static void
+GenerateInitialFileLines()
+{
+ /* Generate entries for 'dwarf_names_enum.h' */
+ fprintf(f_names_enum_h,"/* Automatically generated, do not edit. */\n");
+ fprintf(f_names_enum_h,"/* Generated on %s %s */\n",__DATE__,__TIME__);
+ fprintf(f_names_enum_h,"\n/* BEGIN FILE */\n\n");
+ fprintf(f_names_enum_h,"#ifndef __DWARF_NAMES_ENUM_H__\n");
+ fprintf(f_names_enum_h,"#define __DWARF_NAMES_ENUM_H__\n");
+
+ /* Generate entries for 'dwarf_names_new.h' */
+ fprintf(f_names_new_h,"/* Automatically generated, do not edit. */\n");
+ fprintf(f_names_new_h,"/* Generated on %s %s */\n",__DATE__,__TIME__);
+ fprintf(f_names_new_h,"\n/* BEGIN FILE */\n\n");
+ fprintf(f_names_new_h,"/* define DWARF_PRINT_PREFIX before this \n");
+ fprintf(f_names_new_h," point if you wish to. */\n");
+ fprintf(f_names_new_h,"#ifndef DWARF_PRINT_PREFIX \n");
+ fprintf(f_names_new_h,"#define DWARF_PRINT_PREFIX dwarf_\n");
+ fprintf(f_names_new_h,"#endif\n");
+ fprintf(f_names_new_h,"#define dw_glue(x,y) x##y\n");
+ fprintf(f_names_new_h,"#define dw_glue2(x,y) dw_glue(x,y)\n");
+ fprintf(f_names_new_h,"#define DWPREFIX(x) dw_glue2(DWARF_PRINT_PREFIX,x)\n");
+
+ /* Generate entries for 'dwarf_names.h' */
+ fprintf(f_names_h,"/* Generated routines, do not edit. */\n");
+ fprintf(f_names_h,"/* Generated on %s %s */\n",__DATE__,__TIME__);
+ fprintf(f_names_h,"\n/* BEGIN FILE */\n\n");
+
+ /* Generate entries for 'dwarf_names.c' */
+ fprintf(f_names_c,"/* Generated routines, do not edit. */\n");
+ fprintf(f_names_c,"/* Generated on %s %s */\n",__DATE__,__TIME__);
+ fprintf(f_names_c,"\n/* BEGIN FILE */\n\n");
+ fprintf(f_names_c,"#include \"dwarf.h\"\n\n");
+ fprintf(f_names_c,"#include \"libdwarf.h\"\n\n");
+
+ if (use_tables) {
+ fprintf(f_names_c,"typedef struct Names_Data {\n");
+ fprintf(f_names_c," const char *l_name; \n");
+ fprintf(f_names_c," unsigned value; \n");
+ fprintf(f_names_c,"} Names_Data;\n\n");
+
+ /* Generate code to find an entry */
+ fprintf(f_names_c,"/* Use standard binary search to get entry */\n");
+ fprintf(f_names_c,"static int\nfind_entry(Names_Data *table,"
+ "const int last,unsigned value, const char **s_out)\n");
+ fprintf(f_names_c,"{\n");
+ fprintf(f_names_c," int low = 0;\n");
+ fprintf(f_names_c," int high = last;\n");
+ fprintf(f_names_c," int mid;\n");
+ fprintf(f_names_c,"\n");
+ fprintf(f_names_c," while (low < high) {\n");
+ fprintf(f_names_c," mid = low + ((high - low) / 2);\n");
+ fprintf(f_names_c," if (table[mid].value < value) {\n");
+ fprintf(f_names_c," low = mid + 1;\n");
+ fprintf(f_names_c," }\n");
+ fprintf(f_names_c," else {\n");
+ fprintf(f_names_c," high = mid;\n");
+ fprintf(f_names_c," }\n");
+ fprintf(f_names_c," }\n");
+ fprintf(f_names_c,"\n");
+ fprintf(f_names_c," if (low < last && table[low].value == value) {\n");
+ fprintf(f_names_c," /* Found: low is the entry */\n");
+ fprintf(f_names_c," *s_out = table[low].l_name;\n");
+ fprintf(f_names_c," return DW_DLV_OK;\n");
+ fprintf(f_names_c," }\n");
+ fprintf(f_names_c," return DW_DLV_NO_ENTRY;\n");
+ fprintf(f_names_c,"}\n");
+ fprintf(f_names_c,"\n");
+ }
+}
+
+/* Close files and write basic trailers */
+static void
+WriteFileTrailers()
+{
+ /* Generate entries for 'dwarf_names_enum.h' */
+ fprintf(f_names_enum_h,"#endif /* __DWARF_NAMES_ENUM_H__ */\n");
+ fprintf(f_names_enum_h,"\n/* END FILE */\n");
+
+ /* Generate entries for 'dwarf_names_new.h' */
+ fprintf(f_names_new_h,"\n/* END FILE */\n");
+
+ /* Generate entries for 'dwarf_names.h' */
+ fprintf(f_names_h,"\n/* END FILE */\n");
+
+ /* Generate entries for 'dwarf_names.c' */
+ fprintf(f_names_c,"\n/* END FILE */\n");
+}
+
+static void
+CloseAllFiles()
+{
+ fclose(f_dwarf_in);
+ fclose(f_names_enum_h);
+ fclose(f_names_new_h);
+ fclose(f_names_h);
+ fclose(f_names_c);
+}
+
+/* Write the table and code for a common set of names */
+static void
+GenerateOneSet()
+{
+ unsigned index;
+ unsigned prev_value = 0;
+ size_t len;
+ char *prefix_id = prefix + prefix_root_len;
+
+#ifdef TRACE_ARRAY
+ printf("List before sorting:\n");
+ PrintArray();
+#endif /* TRACE_ARRAY */
+
+ /* Sort the array, because the values in 'libdwarf.h' are not in
+ ascending order; if we use '-t' we must be sure the values are
+ sorted, for the binary search to work properly */
+ qsort((void *)&group_array,array_count,sizeof(array_data),(compfn)Compare);
+
+#ifdef TRACE_ARRAY
+ printf("\nList after sorting:\n");
+ PrintArray();
+#endif /* TRACE_ARRAY */
+
+ /* Generate entries for 'dwarf_names_enum.h' */
+ fprintf(f_names_enum_h,"\nenum Dwarf_%s_e {\n",prefix_id);
+
+ /* Generate entries for 'dwarf_names_new.h' */
+ fprintf(f_names_new_h,"int DWPREFIX(get_%s_name) (unsigned int, const char **);\n",prefix_id);
+
+ /* Generate entries for 'dwarf_names.h' and libdwarf.h */
+ fprintf(f_names_h,"extern int dwarf_get_%s_name(unsigned int /*val_in*/, const char ** /*s_out */);\n",prefix_id);
+
+ /* Generate code for 'dwarf_names.c' */
+ fprintf(f_names_c,"/* ARGSUSED */\n");
+ fprintf(f_names_c,"int\n");
+ fprintf(f_names_c,"dwarf_get_%s_name (unsigned int val,const char ** s_out)\n",prefix_id);
+ fprintf(f_names_c,"{\n");
+ if (use_tables) {
+ fprintf(f_names_c," static Names_Data Dwarf_%s_n[] = {\n",prefix_id);
+ } else {
+ fprintf(f_names_c," switch (val) {\n");
+ }
+
+ for (index = 0; index < array_count; ++index) {
+ /* Check if value already dumped */
+ if (index > 0 && group_array[index].value == prev_value) {
+ continue;
+ }
+ prev_value = group_array[index].value;
+
+ len = 39 - strlen(prefix);
+ fprintf(f_names_enum_h," %s_%-*s = 0x%04x",
+ prefix,(int)len,group_array[index].name,group_array[index].value);
+ fprintf(f_names_enum_h,(index + 1 < array_count) ? ",\n" : "\n");
+
+ /* Generate entries for 'dwarf_names.c' */
+ if (use_tables) {
+ /* The 20 just makes nice formatting in the output. */
+ len = 20 - strlen(group_array[index].name);
+ fprintf(f_names_c," {/* %3d */ \"%s_%s\", ",
+ index,prefix,group_array[index].name);
+ fprintf(f_names_c," %s_%s}", prefix,group_array[index].name);
+ fprintf(f_names_c,(index + 1 < array_count) ? ",\n" : "\n");
+ } else {
+ fprintf(f_names_c," case %s_%s:\n",
+ prefix,group_array[index].name);
+ fprintf(f_names_c," *s_out = \"%s_%s\";\n",
+ prefix,group_array[index].name);
+ fprintf(f_names_c," return DW_DLV_OK;\n");
+ }
+ }
+
+ /* Closing entries for 'dwarf_names_enum.h' */
+ fprintf(f_names_enum_h,"};\n");
+
+ if (use_tables) {
+ /* Closing entries for 'dwarf_names.c' */
+ fprintf(f_names_c," };\n\n");
+
+ /* Closing code for 'dwarf_names.c' */
+ fprintf(f_names_c," const int last_entry = %d;\n",array_count);
+ fprintf(f_names_c," /* find the entry */\n");
+ fprintf(f_names_c," int r = find_entry(Dwarf_%s_n,last_entry,val,s_out);\n",prefix_id);
+ fprintf(f_names_c," return r; \n");
+ fprintf(f_names_c,"}\n");
+ } else {
+ fprintf(f_names_c," }\n");
+ fprintf(f_names_c," return DW_DLV_NO_ENTRY; \n");
+ fprintf(f_names_c,"}\n");
+ }
+
+ /* Mark the group_array as empty */
+ array_count = 0;
+}
+
+/* Detect empty lines (and other lines we do not want to read) */
+static boolean
+is_skippable_line(char *pLine)
+{
+ boolean empty = TRUE;
+
+ for (; *pLine && empty; ++pLine) {
+ empty = isspace(*pLine);
+ }
+ return empty;
+}
+
+static void safe_strncpy(char *out, unsigned out_len,
+char *in,unsigned in_len)
+{
+ if(in_len >= out_len) {
+ fprintf(stderr,"Impossible input line from dwarf.h. Giving up. \n");
+ fprintf(stderr,"Length %u is too large, limited to %u.\n",
+ in_len,out_len);
+ exit(1);
+ }
+ strncpy(out,in,in_len);
+}
+
+
+/* Parse the 'dwarf.h' file and generate the tables */
+static void
+ParseDefinitionsAndWriteOutput()
+{
+ char new_prefix[64];
+ char *second_underscore = NULL;
+ char type[1000];
+ char name[1000];
+ char value[1000];
+ char extra[1000];
+ char line_in[MAX_LINE_SIZE];
+ int pending = FALSE;
+ int prefix_len = 0;
+
+ /* Process each line from 'dwarf.h' */
+ while (!feof(f_dwarf_in)) {
+ errno = 0;
+ char *fgbad = fgets(line_in,sizeof(line_in),f_dwarf_in);
+ if(!fgbad) {
+ if(feof(f_dwarf_in)) {
+ break;
+ }
+ /* Is error. errno must be set. */
+ fprintf(stderr,"Error reading dwarf.h!. Errno %d\n",errno);
+ exit(1);
+ }
+ if (is_skippable_line(line_in)) {
+ continue;
+ }
+ sscanf(line_in,"%s %s %s %s",type,name,value,extra);
+ if (strcmp(type,"#define") ||
+ strncmp(name,prefix_root,prefix_root_len)) {
+ continue;
+ }
+
+ second_underscore = strchr(name + prefix_root_len,'_');
+ prefix_len = (int)(second_underscore - name);
+ safe_strncpy(new_prefix,sizeof(new_prefix),name,prefix_len);
+ new_prefix[prefix_len] = 0;
+
+ /* Check for new prefix set */
+ if (strcmp(prefix,new_prefix)) {
+ if (pending) {
+ /* Generate current prefix set */
+ GenerateOneSet();
+ }
+ pending = TRUE;
+ strcpy(prefix,new_prefix);
+ }
+
+ /* Be sure we have a valid entry */
+ if (array_count >= ARRAY_SIZE) {
+ printf("Too many entries for current group_array size");
+ exit(1);
+ }
+
+ /* Move past the second underscore */
+ ++second_underscore;
+
+ /* Record current entry */
+ strcpy(group_array[array_count].name,second_underscore);
+ group_array[array_count].value = strtoul(value,NULL,16);
+ ++array_count;
+ }
+ if (pending) {
+ /* Generate final prefix set */
+ GenerateOneSet();
+ }
+}
diff --git a/libdwarf/index.v2.mm b/libdwarf/index.v2.mm
new file mode 100644
index 0000000..c5fd9ac
--- /dev/null
+++ b/libdwarf/index.v2.mm
@@ -0,0 +1,266 @@
+.ds fB IN-%
+.PF "''\s10\\\\*(fB\s0''"
+.PH
+.ce
+\s12INDEX\s0
+
+.\" %W% %P% %E% %I% %U%
+.\" Copyright 1993 UNIX System Laboratories, Inc.
+.\" XX macro marks new index entry.
+.de XX
+. br
+. ti 0
+. ne 2
+. vs 12
+\s10\f1\\$1\0 \s8\fR\\$2\f1
+..
+.\" header between letters of the alphabet
+.de YY
+. sp 2
+. ne 4
+\fR\s16\\$2\s0\f1
+. sp 0.5
+..
+.\" markup surrounding book acronym
+.\" markup surrounding chapter number
+.vs 12
+.ps 8
+.CH "Index" IN
+.2C
+.in +2
+.\" SCCS path name: /lfs/doc/DMG/Projects/Indexing/sccs/bin/s.index.head
+.\" SCCS version SID: 1.8
+.\" Date this version: 92/08/10
+.\" Time this version: 13:06:03
+.YY a A
+.XX "\&abbreviations table" "\*(C{\*(}C4, 66\-67"
+.XX "\&ABI" "\*(C{\*(}C10, 60"
+.XX "\&accelerated access" "\*(C{\*(}C49"
+.XX "\&access declarations" "\*(C{\*(}C41"
+.XX "\&accessibility" "\*(C{\*(}C18, 41, 74"
+.XX "\&activations" "\*(C{\*(}C5, 59"
+.XX "\&address space" ""
+.XX "\&\0 contiguous" "\*(C{\*(}C23, 26"
+.XX "\&\0 flat" "\*(C{\*(}C19"
+.XX "\&\0 multiple" "\*(C{\*(}C13"
+.XX "\&\0 segmented" "\*(C{\*(}C5, 19, 26, 33, 50, 66"
+.XX "\&addresses" ""
+.XX "\&\0 class" "\*(C{\*(}C19, 26, 38, 75"
+.XX "\&\0 offset portion" "\*(C{\*(}C19, 50, 66, 77"
+.XX "\&\0 size of" "\*(C{\*(}C50, 66, 77"
+.XX "\&anonymous types" "\*(C{\*(}C30"
+.XX "\&anonymous unions" "\*(C{\*(}C33, 41"
+.XX "\&arrays" "\*(C{\*(}C5, 39"
+.XX "\&\0 dimensions" "\*(C{\*(}C39"
+.XX "\&\0 ordering" "\*(C{\*(}C39, 77"
+.XX "\&\0 stride" "\*(C{\*(}C39"
+.XX "\&artificial entries" "\*(C{\*(}C19"
+.XX "\&attributes" "\*(C{\*(}C3, 7, 67"
+.XX "\&\0 addresses" "\*(C{\*(}C8, 67"
+.XX "\&\0 blocks" "\*(C{\*(}C8, 67"
+.XX "\&\0 constants" "\*(C{\*(}C8, 68"
+.XX "\&\0 flags" "\*(C{\*(}C8, 69"
+.XX "\&\0 forms" "\*(C{\*(}C4, 7, 67"
+.XX "\&\0 names" "\*(C{\*(}C4, 7, 67"
+.XX "\&\0 ordering" "\*(C{\*(}C9, 27"
+.XX "\&\0 references" "\*(C{\*(}C8, 69"
+.XX "\&\0 strings" "\*(C{\*(}C9, 70"
+.XX "\&\0 values" "\*(C{\*(}C4, 7, 66"
+.YY b B
+.XX "\&base types" "\*(C{\*(}C18, 24, 37, 65, 74"
+.XX "\&bit fields" "\*(C{\*(}C42"
+.YY c C
+.XX "\&C " "\*(C{\*(}C3, 26, 33, 39\-40, 45, 47, 57"
+.XX "\&C++ " "\*(C{\*(}C3, 5, 18\-19, 21, 28, 32\-33, 40\-41, 43, 47, 49, 57"
+.XX "\&call frame information" "\*(C{\*(}C5, 59, 65, 78"
+.XX "\&\0 Common Information Entry" "\*(C{\*(}C61"
+.XX "\&\0 Frame Description Entry" "\*(C{\*(}C62"
+.XX "\&\0 instructions" "\*(C{\*(}C62, 78"
+.XX "\&\0 register rules" "\*(C{\*(}C61"
+.XX "\&\0 structure" "\*(C{\*(}C60"
+.XX "\&\0 usage" "\*(C{\*(}C64"
+.XX "\&calling conventions" "\*(C{\*(}C26, 65, 76"
+.XX "\&catch blocks" "\*(C{\*(}C32"
+.XX "\&classes" "\*(C{\*(}C33, 40"
+.XX "\&\0 derived" "\*(C{\*(}C40"
+.XX "\&\0 friends" "\*(C{\*(}C41"
+.XX "\&\0 incomplete" "\*(C{\*(}C40"
+.XX "\&\0 virtual base" "\*(C{\*(}C41"
+.XX "\&common blocks" "\*(C{\*(}C27, 35"
+.XX "\&compatibility" "\*(C{\*(}C3, 65"
+.XX "\&compilation units" "\*(C{\*(}C23, 28, 44, 66"
+.XX "\&\0 header" "\*(C{\*(}C66"
+.XX "\&constants" "\*(C{\*(}C33\-34"
+.YY d D
+.XX "\&\f(CW.debug\fP " "\*(C{\*(}C4"
+.XX "\&\f(CW.debug_abbrev\fP " "\*(C{\*(}C66\-67, 79"
+.XX "\&\f(CW.debug_aranges\fP " "\*(C{\*(}C49, 77, 79"
+.XX "\&\f(CW.debug_frame\fP " "\*(C{\*(}C61, 79"
+.XX "\&\f(CW.debug_info\fP " "\*(C{\*(}C3\-4, 7, 49\-50, 66, 79"
+.XX "\&\f(CW.debug_line\fP " "\*(C{\*(}C4, 50, 79"
+.XX "\&\f(CW.debug_loc\fP " "\*(C{\*(}C17, 79"
+.XX "\&\f(CW.debug_macinfo\fP " "\*(C{\*(}C57, 79"
+.XX "\&\f(CW.debug_pubnames\fP " "\*(C{\*(}C49, 77, 79"
+.XX "\&\f(CW.debug_str\fP " "\*(C{\*(}C70, 79"
+.XX "\&debugging information entries" "\*(C{\*(}C3, 7, 9, 66"
+.XX "\&\0 child entries" "\*(C{\*(}C4, 9, 67"
+.XX "\&\0 null entries" "\*(C{\*(}C9, 66\-67"
+.XX "\&\0 siblings" "\*(C{\*(}C4, 9, 67"
+.XX "\&declarations" ""
+.XX "\&\0 accessibility" "\*(C{\*(}C18, 74"
+.XX "\&\0 coordinates" "\*(C{\*(}C20, 28, 30, 44"
+.XX "\&\0 defining" "\*(C{\*(}C20, 33, 40, 43"
+.XX "\&\0 external" "\*(C{\*(}C25, 33"
+.XX "\&\0 imported" "\*(C{\*(}C35"
+.XX "\&\0 non-defining" "\*(C{\*(}C4, 20, 26, 33, 38, 40"
+.XX "\&\0 scope" "\*(C{\*(}C34, 37"
+.XX "\&\0 types of" "\*(C{\*(}C4, 18"
+.XX "\&\0 visibility" "\*(C{\*(}C18, 75"
+.XX "\&discriminants" "\*(C{\*(}C44, 77"
+.XX "\&discriminated unions" "\*(C{\*(}C40, 44, 77"
+.YY e E
+.XX "\&entry points" "\*(C{\*(}C25"
+.XX "\&\0 declarations owned by" "\*(C{\*(}C27"
+.XX "\&\0 locations" "\*(C{\*(}C26"
+.XX "\&\0 return types" "\*(C{\*(}C26"
+.XX "\&enumerations" "\*(C{\*(}C5, 39, 45"
+.XX "\&error values" "\*(C{\*(}C65"
+.XX "\&exceptions" "\*(C{\*(}C5, 28, 32"
+.YY f F
+.XX "\&file types" "\*(C{\*(}C48"
+.XX "\&flat address space" "\*(C{\*(}C19"
+.XX "\&Fortran" "\*(C{\*(}C3, 27, 35, 46\-47"
+.XX "\&FORTRAN77" "\*(C{\*(}C3"
+.XX "\&Fortran90" "\*(C{\*(}C3, 34\-35"
+.XX "\&friends" "\*(C{\*(}C41"
+.YY i I
+.XX "\&identifiers" ""
+.XX "\&\0 case" "\*(C{\*(}C24, 76"
+.XX "\&\0 names" "\*(C{\*(}C21, 49"
+.XX "\&imports" "\*(C{\*(}C35"
+.XX "\&inheritance" "\*(C{\*(}C40"
+.YY l L
+.XX "\&labels" "\*(C{\*(}C31"
+.XX "\&languages" "\*(C{\*(}C3, 23, 75"
+.XX "\&LEB128" "\*(C{\*(}C8, 51, 68, 70"
+.XX "\&lexical blocks" "\*(C{\*(}C31"
+.XX "\&line number information" "\*(C{\*(}C4, 20, 23, 50, 77"
+.XX "\&\0 definitions" "\*(C{\*(}C51, 77"
+.XX "\&\0 extended opcodes" "\*(C{\*(}C52, 56, 78"
+.XX "\&\0 general rules" "\*(C{\*(}C59"
+.XX "\&\0 prologue" "\*(C{\*(}C52"
+.XX "\&\0 special opcodes" "\*(C{\*(}C52, 54"
+.XX "\&\0 standard opcodes" "\*(C{\*(}C52, 55, 78"
+.XX "\&\0 state machine registers" "\*(C{\*(}C51"
+.XX "\&locations" ""
+.XX "\&\0 arithmetic operations" "\*(C{\*(}C13"
+.XX "\&\0 control flow operations" "\*(C{\*(}C14"
+.XX "\&\0 descriptions" "\*(C{\*(}C4, 10, 19, 41, 72"
+.XX "\&\0 examples" "\*(C{\*(}C15\-16"
+.XX "\&\0 expressions" "\*(C{\*(}C10, 41, 65, 72"
+.XX "\&\0 lists" "\*(C{\*(}C4, 10, 17, 74"
+.XX "\&\0 literal encodings" "\*(C{\*(}C11"
+.XX "\&\0 logical operations" "\*(C{\*(}C13"
+.XX "\&\0 register based addressing" "\*(C{\*(}C12"
+.XX "\&\0 register name operators" "\*(C{\*(}C10"
+.XX "\&\0 special operations" "\*(C{\*(}C15"
+.XX "\&\0 stack" "\*(C{\*(}C11\-12, 15"
+.XX "\&lookup" ""
+.XX "\&\0 by address" "\*(C{\*(}C49, 77"
+.XX "\&\0 by name" "\*(C{\*(}C49, 77"
+.YY m M
+.XX "\&macro information" "\*(C{\*(}C4, 24, 57, 78"
+.XX "\&\0 base source entries" "\*(C{\*(}C58"
+.XX "\&\0 command line options" "\*(C{\*(}C58"
+.XX "\&\0 define and undefine entries" "\*(C{\*(}C57"
+.XX "\&\0 end file entries" "\*(C{\*(}C58"
+.XX "\&\0 start file entries" "\*(C{\*(}C58"
+.XX "\&\0 vendor extensions" "\*(C{\*(}C58"
+.XX "\&main programs" "\*(C{\*(}C26"
+.XX "\&members" "\*(C{\*(}C30"
+.XX "\&\0 bit fields" "\*(C{\*(}C42"
+.XX "\&\0 data" "\*(C{\*(}C40\-41"
+.XX "\&\0 functions" "\*(C{\*(}C25, 40, 43"
+.XX "\&\0 locations" "\*(C{\*(}C11, 43"
+.XX "\&\0 pointers to" "\*(C{\*(}C47"
+.XX "\&\0 static data" "\*(C{\*(}C33, 40, 49"
+.XX "\&Modula2" "\*(C{\*(}C3, 18, 25, 32"
+.XX "\&modules" "\*(C{\*(}C25"
+.XX "\&\0 definition" "\*(C{\*(}C25"
+.XX "\&\0 priority" "\*(C{\*(}C25"
+.YY n N
+.XX "\&namelists" "\*(C{\*(}C35"
+.YY o O
+.XX "\&optimized code" "\*(C{\*(}C10, 18, 33"
+.YY p P
+.XX "\&parameters" ""
+.XX "\&\0 default value" "\*(C{\*(}C34"
+.XX "\&\0 formal" "\*(C{\*(}C27, 32\-33, 45"
+.XX "\&\0 optional" "\*(C{\*(}C34"
+.XX "\&\0 unspecified" "\*(C{\*(}C27, 32, 46"
+.XX "\&\0 variable" "\*(C{\*(}C34"
+.XX "\&Pascal" "\*(C{\*(}C3, 32, 40, 46, 48"
+.XX "\&pointers to members" "\*(C{\*(}C47"
+.XX "\&pre-processor" "\*(C{\*(}C4, 57"
+.YY r R
+.XX "\&records" "\*(C{\*(}C40"
+.YY s S
+.XX "\&scope" "\*(C{\*(}C34, 37"
+.XX "\&segmented address space" "\*(C{\*(}C5, 19, 26, 33, 50, 66"
+.XX "\&set types" "\*(C{\*(}C46"
+.XX "\&source" ""
+.XX "\&\0 columns" "\*(C{\*(}C20, 51"
+.XX "\&\0 files" "\*(C{\*(}C20, 23, 51, 53, 56, 58, 78"
+.XX "\&\0 lines" "\*(C{\*(}C20, 51, 57"
+.XX "\&string table" "\*(C{\*(}C70"
+.XX "\&string types" "\*(C{\*(}C46"
+.XX "\&structures" "\*(C{\*(}C33, 40"
+.XX "\&\0 derived" "\*(C{\*(}C40"
+.XX "\&\0 incomplete" "\*(C{\*(}C40"
+.XX "\&subranges" "\*(C{\*(}C39, 46"
+.XX "\&subroutines" "\*(C{\*(}C19, 25"
+.XX "\&\0 declarations owned by" "\*(C{\*(}C27"
+.XX "\&\0 frame base" "\*(C{\*(}C12, 27"
+.XX "\&\0 inline" "\*(C{\*(}C28, 76"
+.XX "\&\0 inlined" "\*(C{\*(}C29"
+.XX "\&\0 locations" "\*(C{\*(}C26"
+.XX "\&\0 members" "\*(C{\*(}C25, 43"
+.XX "\&\0 nested" "\*(C{\*(}C27"
+.XX "\&\0 out-of-line" "\*(C{\*(}C30"
+.XX "\&\0 prototypes" "\*(C{\*(}C26, 45"
+.XX "\&\0 return addresses" "\*(C{\*(}C27"
+.XX "\&\0 return types" "\*(C{\*(}C26, 45"
+.XX "\&\0 types" "\*(C{\*(}C19, 45"
+.YY t T
+.XX "\&tags" "\*(C{\*(}C4, 7, 65, 67"
+.XX "\&templates" "\*(C{\*(}C5, 28, 43"
+.XX "\&try blocks" "\*(C{\*(}C32"
+.XX "\&type modifiers" "\*(C{\*(}C18, 38"
+.XX "\&typedefs" "\*(C{\*(}C38"
+.XX "\&types" ""
+.XX "\&\0 base" "\*(C{\*(}C18, 24, 37, 65, 74"
+.XX "\&\0 constant" "\*(C{\*(}C18, 38"
+.XX "\&\0 modifiers" "\*(C{\*(}C18, 38"
+.XX "\&\0 packed" "\*(C{\*(}C18, 38"
+.XX "\&\0 pointer" "\*(C{\*(}C18\-19, 38"
+.XX "\&\0 reference" "\*(C{\*(}C18\-19, 38"
+.XX "\&\0 user-defined" "\*(C{\*(}C18"
+.XX "\&\0 volatile" "\*(C{\*(}C18, 38"
+.YY u U
+.XX "\&unions" "\*(C{\*(}C33, 40, 42"
+.XX "\&\0 anonymous" "\*(C{\*(}C33, 41"
+.XX "\&\0 incomplete" "\*(C{\*(}C40"
+.XX "\&user-defined types" "\*(C{\*(}C18"
+.YY v V
+.XX "\&variable length data" "\*(C{\*(}C4, 8, 68, 70"
+.XX "\&variables" "\*(C{\*(}C33"
+.XX "\&variants" "\*(C{\*(}C40, 44, 77"
+.XX "\&vendor extensions" "\*(C{\*(}C4, 58, 60, 65"
+.XX "\&Version 1" "\*(C{\*(}C3\-4, 10, 66"
+.XX "\&Version 2" "\*(C{\*(}C3, 10, 66, 78"
+.XX "\&virtual functions" "\*(C{\*(}C3, 19, 43"
+.XX "\&virtuality" "\*(C{\*(}C19, 41, 43, 75"
+.XX "\&visibility" "\*(C{\*(}C18, 75"
+.YY w W
+.XX "\&with statements" "\*(C{\*(}C32"
+.1C
diff --git a/libdwarf/index.v2.pdf b/libdwarf/index.v2.pdf
new file mode 100644
index 0000000..5d45154
--- /dev/null
+++ b/libdwarf/index.v2.pdf
Binary files differ
diff --git a/libdwarf/install.sh b/libdwarf/install.sh
new file mode 100755
index 0000000..0ff4b6a
--- /dev/null
+++ b/libdwarf/install.sh
@@ -0,0 +1,119 @@
+#!/bin/sh
+
+#
+# install - install a program, script, or datafile
+# This comes from X11R5; it is not part of GNU.
+#
+# $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+
+instcmd="$mvprog"
+chmodcmd=""
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+fi
+
+if [ x"$dst" = x ]
+then
+ echo "install: no destination specified"
+ exit 1
+fi
+
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+if [ -d $dst ]
+then
+ dst="$dst"/`basename $src`
+fi
+
+# Make a temp file name in the proper directory.
+
+dstdir=`dirname $dst`
+dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+$doit $instcmd $src $dsttmp
+
+# and set any options; do chmod last to preserve setuid bits
+
+if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi
+if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi
+if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi
+if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi
+
+# Now rename the file to the real destination.
+
+$doit $rmcmd $dst
+$doit $mvcmd $dsttmp $dst
+
+
+exit 0
diff --git a/libdwarf/libdwarf.h b/libdwarf/libdwarf.h
new file mode 100644
index 0000000..128bd1e
--- /dev/null
+++ b/libdwarf/libdwarf.h
@@ -0,0 +1,2964 @@
+/*
+
+ Copyright (C) 2000-2010 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson. All rights reserved.
+ Portions Copyright 2008-2010 Arxan Technologies, Inc. All rights reserved.
+ Portions Copyright 2010 SN Systems Ltd. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+#ifndef _LIBDWARF_H
+#define _LIBDWARF_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ libdwarf.h
+ $Revision: #9 $ $Date: 2008/01/17 $
+
+ For libdwarf producers and consumers
+
+ The interface is defined as having 8-byte signed and unsigned
+ values so it can handle 64-or-32bit target on 64-or-32bit host.
+ Addr is the native size: it represents pointers on
+ the host machine (not the target!).
+
+ This contains declarations for types and all producer
+ and consumer functions.
+
+ Function declarations are written on a single line each here
+ so one can use grep to each declaration in its entirety.
+ The declarations are a little harder to read this way, but...
+
+*/
+
+struct Elf;
+typedef struct Elf* dwarf_elf_handle;
+
+/* To enable printing with printf regardless of the
+ actual underlying data type, we define the DW_PR_xxx macros.
+ To ensure uses of DW_PR_DUx or DW_PR_DSx look the way you want
+ ensure the right DW_PR_XZEROS define is uncommented.
+*/
+/*#define DW_PR_XZEROS "" */
+#define DW_PR_XZEROS "08"
+#if (_MIPS_SZLONG == 64)
+/* Special case for MIPS, so -64 (LP64) build gets simple -long-.
+ Non-MIPS LP64 or ILP64 environments should probably ensure
+ _MIPS_SZLONG set to 64 everywhere this header is #included.
+*/
+typedef int Dwarf_Bool; /* boolean type */
+typedef unsigned long Dwarf_Off; /* 4 or 8 byte file offset */
+typedef unsigned long Dwarf_Unsigned; /* 4 or 8 byte unsigned value */
+typedef unsigned short Dwarf_Half; /* 2 byte unsigned value */
+typedef unsigned char Dwarf_Small; /* 1 byte unsigned value */
+typedef signed long Dwarf_Signed; /* 4 or 8 byte signed value */
+typedef unsigned long Dwarf_Addr; /* target memory address */
+#define DW_PR_DUx "lx"
+#define DW_PR_DSx "lx"
+#define DW_PR_DUu "lu"
+#define DW_PR_DSd "ld"
+
+#else /* 32-bit */
+/* This is for ILP32, allowing i/o of 64bit dwarf info.
+ Also should be fine for LP64 and ILP64 cases.
+*/
+typedef int Dwarf_Bool; /* boolean type */
+typedef unsigned long long Dwarf_Off; /* 8 byte file offset */
+typedef unsigned long long Dwarf_Unsigned; /* 8 byte unsigned value*/
+typedef unsigned short Dwarf_Half; /* 2 byte unsigned value */
+typedef unsigned char Dwarf_Small; /* 1 byte unsigned value */
+typedef signed long long Dwarf_Signed; /* 8 byte signed value */
+typedef unsigned long long Dwarf_Addr; /* target memory address */
+#define DW_PR_DUx "llx"
+#define DW_PR_DSx "llx"
+#define DW_PR_DUu "llu"
+#define DW_PR_DSd "lld"
+#endif
+#ifdef HAVE_NONSTANDARD_PRINTF_64_FORMAT
+/* Windows does not use std C formatting, so allow it. */
+#undef DW_PR_DUx
+#undef DW_PR_DSx
+#undef DW_PR_DUu
+#undef DW_PR_DSd
+#define DW_PR_DUx "I64x"
+#define DW_PR_DSx "I64x"
+#define DW_PR_DUu "I64u"
+#define DW_PR_DSd "I64d"
+#endif /* HAVE_NONSTANDARD_FORMAT */
+
+typedef void* Dwarf_Ptr; /* host machine pointer */
+
+/* Used for DW_FORM_ref_sig8. It is not a string, it
+ is 8 bytes of a signature one would use to find
+ a type unit. See dwarf_formsig8()
+*/
+typedef struct {
+ char signature[8];
+} Dwarf_Sig8;
+
+/* Contains info on an uninterpreted block of data
+*/
+typedef struct {
+ Dwarf_Unsigned bl_len; /* length of block */
+ Dwarf_Ptr bl_data; /* uninterpreted data */
+ Dwarf_Small bl_from_loclist; /*non-0 if loclist, else debug_info*/
+ Dwarf_Unsigned bl_section_offset; /* Section (not CU) offset
+ which 'data' comes from. */
+} Dwarf_Block;
+
+
+/* location record
+*/
+typedef struct {
+ Dwarf_Small lr_atom; /* location operation */
+ Dwarf_Unsigned lr_number; /* operand */
+ Dwarf_Unsigned lr_number2; /* for OP_BREGx */
+ Dwarf_Unsigned lr_offset; /* offset in locexpr for OP_BRA etc */
+} Dwarf_Loc;
+
+
+/* location description
+*/
+typedef struct {
+ Dwarf_Addr ld_lopc; /* beginning of active range */
+ Dwarf_Addr ld_hipc; /* end of active range */
+ Dwarf_Half ld_cents; /* count of location records */
+ Dwarf_Loc* ld_s; /* pointer to list of same */
+ Dwarf_Small ld_from_loclist;
+ /* non-0 if loclist, else debug_info*/
+
+ Dwarf_Unsigned ld_section_offset; /* Section (not CU) offset
+ where loc-expr begins*/
+} Dwarf_Locdesc;
+
+/* First appears in DWARF3.
+ The dwr_addr1/addr2 data is either an offset (DW_RANGES_ENTRY)
+ or an address (dwr_addr2 in DW_RANGES_ADDRESS_SELECTION) or
+ both are zero (DW_RANGES_END).
+*/
+enum Dwarf_Ranges_Entry_Type { DW_RANGES_ENTRY,
+ DW_RANGES_ADDRESS_SELECTION,
+ DW_RANGES_END
+};
+typedef struct {
+ Dwarf_Addr dwr_addr1;
+ Dwarf_Addr dwr_addr2;
+ enum Dwarf_Ranges_Entry_Type dwr_type;
+} Dwarf_Ranges;
+
+/* Frame description instructions expanded.
+*/
+typedef struct {
+ Dwarf_Small fp_base_op;
+ Dwarf_Small fp_extended_op;
+ Dwarf_Half fp_register;
+
+ /* Value may be signed, depends on op.
+ Any applicable data_alignment_factor has
+ not been applied, this is the raw offset. */
+ Dwarf_Unsigned fp_offset;
+ Dwarf_Off fp_instr_offset;
+} Dwarf_Frame_Op; /* DWARF2 */
+
+typedef struct {
+ Dwarf_Small fp_base_op;
+ Dwarf_Small fp_extended_op;
+ Dwarf_Half fp_register;
+
+ /* Value may be signed, depends on op.
+ Any applicable data_alignment_factor has
+ not been applied, this is the raw offset. */
+ Dwarf_Unsigned fp_offset_or_block_len;
+ Dwarf_Small *fp_expr_block;
+
+ Dwarf_Off fp_instr_offset;
+} Dwarf_Frame_Op3; /* DWARF3 and DWARF2 compatible */
+
+/* ***IMPORTANT NOTE, TARGET DEPENDENCY ****
+ DW_REG_TABLE_SIZE must be at least as large as
+ the number of registers
+ (DW_FRAME_LAST_REG_NUM) as defined in dwarf.h
+ Preferably identical to DW_FRAME_LAST_REG_NUM.
+ Ensure [0-DW_REG_TABLE_SIZE] does not overlap
+ DW_FRAME_UNDEFINED_VAL or DW_FRAME_SAME_VAL.
+ Also ensure DW_FRAME_REG_INITIAL_VALUE is set to what
+ is appropriate to your cpu.
+ For various CPUs DW_FRAME_UNDEFINED_VAL is correct
+ as the value for DW_FRAME_REG_INITIAL_VALUE.
+
+ For consumer apps, this can be set dynamically: see
+ dwarf_set_frame_rule_table_size(); */
+#ifndef DW_REG_TABLE_SIZE
+#define DW_REG_TABLE_SIZE 66
+#endif
+
+/* For MIPS, DW_FRAME_SAME_VAL is the correct default value
+ for a frame register value. For other CPUS another value
+ may be better, such as DW_FRAME_UNDEFINED_VAL.
+ See dwarf_set_frame_rule_table_size
+*/
+#ifndef DW_FRAME_REG_INITIAL_VALUE
+#define DW_FRAME_REG_INITIAL_VALUE DW_FRAME_SAME_VAL
+#endif
+
+/* Taken as meaning 'undefined value', this is not
+ a column or register number.
+ Only present at libdwarf runtime in the consumer
+ interfaces. Never on disk.
+ DW_FRAME_* Values present on disk are in dwarf.h
+ Ensure this is > DW_REG_TABLE_SIZE (the reg table
+ size is changeable at runtime with the *reg3() interfaces,
+ and this value must be greater than the reg table size).
+*/
+#define DW_FRAME_UNDEFINED_VAL 1034
+
+/* Taken as meaning 'same value' as caller had, not a column
+ or register number.
+ Only present at libdwarf runtime in the consumer
+ interfaces. Never on disk.
+ DW_FRAME_* Values present on disk are in dwarf.h
+ Ensure this is > DW_REG_TABLE_SIZE (the reg table
+ size is changeable at runtime with the *reg3() interfaces,
+ and this value must be greater than the reg table size).
+*/
+#define DW_FRAME_SAME_VAL 1035
+
+/* For DWARF3 consumer interfaces, make the CFA a column with no
+ real table number. This is what should have been done
+ for the DWARF2 interfaces. This actually works for
+ both DWARF2 and DWARF3, but see the libdwarf documentation
+ on Dwarf_Regtable3 and dwarf_get_fde_info_for_reg3()
+ and dwarf_get_fde_info_for_all_regs3()
+ Do NOT use this with the older dwarf_get_fde_info_for_reg()
+ or dwarf_get_fde_info_for_all_regs() consumer interfaces.
+ Must be higher than any register count for *any* ABI
+ (ensures maximum applicability with minimum effort).
+ Ensure this is > DW_REG_TABLE_SIZE (the reg table
+ size is changeable at runtime with the *reg3() interfaces,
+ and this value must be greater than the reg table size).
+ Only present at libdwarf runtime in the consumer
+ interfaces. Never on disk.
+*/
+#define DW_FRAME_CFA_COL3 1436
+
+/* The following are all needed to evaluate DWARF3 register rules.
+*/
+#define DW_EXPR_OFFSET 0 /* DWARF2 only sees this. */
+#define DW_EXPR_VAL_OFFSET 1
+#define DW_EXPR_EXPRESSION 2
+#define DW_EXPR_VAL_EXPRESSION 3
+
+typedef struct Dwarf_Regtable_Entry_s {
+ /* For each index i (naming a hardware register with dwarf number
+ i) the following is true and defines the value of that register:
+
+ If dw_regnum is Register DW_FRAME_UNDEFINED_VAL
+ it is not DWARF register number but
+ a place holder indicating the register has no defined value.
+ If dw_regnum is Register DW_FRAME_SAME_VAL
+ it is not DWARF register number but
+ a place holder indicating the register has the same
+ value in the previous frame.
+
+ DW_FRAME_UNDEFINED_VAL, DW_FRAME_SAME_VAL are
+ only present at libdwarf runtime. Never on disk.
+ DW_FRAME_* Values present on disk are in dwarf.h
+
+ Otherwise: the register number is a DWARF register number
+ (see ABI documents for how this translates to hardware/
+ software register numbers in the machine hardware)
+ and the following applies:
+
+ if dw_value_type == DW_EXPR_OFFSET (the only case for dwarf2):
+ If dw_offset_relevant is non-zero, then
+ the value is stored at at the address CFA+N where
+ N is a signed offset.
+ Rule: Offset(N)
+ If dw_offset_relevant is zero, then the value of the register
+ is the value of (DWARF) register number dw_regnum.
+ Rule: register(F)
+ Other values of dw_value_type are an error.
+ */
+ Dwarf_Small dw_offset_relevant;
+
+ /* For DWARF2, always 0 */
+ Dwarf_Small dw_value_type;
+
+ Dwarf_Half dw_regnum;
+
+ /* The data type here should the larger of Dwarf_Addr
+ and Dwarf_Unsigned and Dwarf_Signed. */
+ Dwarf_Addr dw_offset;
+} Dwarf_Regtable_Entry;
+
+typedef struct Dwarf_Regtable_s {
+ struct Dwarf_Regtable_Entry_s rules[DW_REG_TABLE_SIZE];
+} Dwarf_Regtable;
+
+/* opaque type. Functional interface shown later. */
+struct Dwarf_Reg_value3_s;
+typedef struct Dwarf_Reg_value3_s Dwarf_Reg_Value3;
+
+typedef struct Dwarf_Regtable_Entry3_s {
+/* For each index i (naming a hardware register with dwarf number
+ i) the following is true and defines the value of that register:
+
+ If dw_regnum is Register DW_FRAME_UNDEFINED_VAL
+ it is not DWARF register number but
+ a place holder indicating the register has no defined value.
+ If dw_regnum is Register DW_FRAME_SAME_VAL
+ it is not DWARF register number but
+ a place holder indicating the register has the same
+ value in the previous frame.
+
+ DW_FRAME_UNDEFINED_VAL, DW_FRAME_SAME_VAL and
+ DW_FRAME_CFA_COL3 are only present at libdwarf runtime.
+ Never on disk.
+ DW_FRAME_* Values present on disk are in dwarf.h
+ Because DW_FRAME_SAME_VAL and DW_FRAME_UNDEFINED_VAL
+ and DW_FRAME_CFA_COL3 are definable at runtime
+ consider the names symbolic in this comment, not absolute.
+
+ Otherwise: the register number is a DWARF register number
+ (see ABI documents for how this translates to hardware/
+ software register numbers in the machine hardware)
+ and the following applies:
+
+ In a cfa-defining entry (rt3_cfa_rule) the regnum is the
+ CFA 'register number'. Which is some 'normal' register,
+ not DW_FRAME_CFA_COL3, nor DW_FRAME_SAME_VAL, nor
+ DW_FRAME_UNDEFINED_VAL.
+
+ If dw_value_type == DW_EXPR_OFFSET (the only possible case for
+ dwarf2):
+ If dw_offset_relevant is non-zero, then
+ the value is stored at at the address
+ CFA+N where N is a signed offset.
+ dw_regnum is the cfa register rule which means
+ one ignores dw_regnum and uses the CFA appropriately.
+ So dw_offset_or_block_len is a signed value, really,
+ and must be printed/evaluated as such.
+ Rule: Offset(N)
+ If dw_offset_relevant is zero, then the value of the register
+ is the value of (DWARF) register number dw_regnum.
+ Rule: register(R)
+ If dw_value_type == DW_EXPR_VAL_OFFSET
+ the value of this register is CFA +N where N is a signed offset.
+ dw_regnum is the cfa register rule which means
+ one ignores dw_regnum and uses the CFA appropriately.
+ Rule: val_offset(N)
+ If dw_value_type == DW_EXPR_EXPRESSION
+ The value of the register is the value at the address
+ computed by evaluating the DWARF expression E.
+ Rule: expression(E)
+ The expression E byte stream is pointed to by dw_block_ptr.
+ The expression length in bytes is given by
+ dw_offset_or_block_len.
+ If dw_value_type == DW_EXPR_VAL_EXPRESSION
+ The value of the register is the value
+ computed by evaluating the DWARF expression E.
+ Rule: val_expression(E)
+ The expression E byte stream is pointed to by dw_block_ptr.
+ The expression length in bytes is given by
+ dw_offset_or_block_len.
+ Other values of dw_value_type are an error.
+*/
+ Dwarf_Small dw_offset_relevant;
+ Dwarf_Small dw_value_type;
+ Dwarf_Half dw_regnum;
+ Dwarf_Unsigned dw_offset_or_block_len;
+ Dwarf_Ptr dw_block_ptr;
+
+}Dwarf_Regtable_Entry3;
+
+/* For the DWARF3 version, moved the DW_FRAME_CFA_COL
+ out of the array and into its own struct.
+ Having it part of the array is not very easy to work
+ with from a portability point of view: changing
+ the number for every architecture is a pain (if one fails
+ to set it correctly a register rule gets clobbered when
+ setting CFA). With MIPS it just happened to be easy to use
+ DW_FRAME_CFA_COL (it was wrong conceptually but it was easy...).
+
+ rt3_rules and rt3_reg_table_size must be filled in before
+ calling libdwarf. Filled in with a pointer to an array
+ (pointer and array set up by the calling application)
+ of rt3_reg_table_size Dwarf_Regtable_Entry3_s structs.
+ libdwarf does not allocate or deallocate space for the
+ rules, you must do so. libdwarf will initialize the
+ contents rules array, you do not need to do so (though
+ if you choose to initialize the array somehow that is ok:
+ libdwarf will overwrite your initializations with its own).
+
+*/
+typedef struct Dwarf_Regtable3_s {
+ struct Dwarf_Regtable_Entry3_s rt3_cfa_rule;
+
+ Dwarf_Half rt3_reg_table_size;
+ struct Dwarf_Regtable_Entry3_s * rt3_rules;
+} Dwarf_Regtable3;
+
+
+/* Use for DW_EPXR_STANDARD., DW_EXPR_VAL_OFFSET.
+ Returns DW_DLV_OK if the value is available.
+ If DW_DLV_OK returns the regnum and offset thru the pointers
+ (which the consumer must use appropriately).
+*/
+int dwarf_frame_get_reg_register(struct Dwarf_Regtable_Entry3_s *reg_in,
+ Dwarf_Small *offset_relevant,
+ Dwarf_Half *regnum_out,
+ Dwarf_Signed *offset_out);
+
+/* Use for DW_EXPR_EXPRESSION, DW_EXPR_VAL_EXPRESSION.
+ Returns DW_DLV_OK if the value is available.
+ The caller must pass in the address of a valid
+ Dwarf_Block (the caller need not initialize it).
+*/
+int dwarf_frame_get_reg_expression(struct Dwarf_Regtable_Entry3_s *reg_in,
+ Dwarf_Block *block_out);
+
+
+/* For DW_DLC_SYMBOLIC_RELOCATIONS output to caller
+ v2, adding drd_length: some relocations are 4 and
+ some 8 bytes (pointers are 8, section offsets 4) in
+ some dwarf environments. (MIPS relocations are all one
+ size in any given ABI.) Changing drd_type to an unsigned char
+ to keep struct size down.
+*/
+enum Dwarf_Rel_Type {
+ dwarf_drt_none, /* Should not get to caller */
+ dwarf_drt_data_reloc, /* Simple normal relocation. */
+ dwarf_drt_segment_rel, /* Special reloc, exceptions. */
+ /* dwarf_drt_first_of_length_pair and drt_second
+ are for for the .word end - begin case. */
+ dwarf_drt_first_of_length_pair,
+ dwarf_drt_second_of_length_pair
+};
+
+typedef struct Dwarf_P_Marker_s * Dwarf_P_Marker;
+struct Dwarf_P_Marker_s {
+ Dwarf_Unsigned ma_marker;
+ Dwarf_Unsigned ma_offset;
+};
+
+typedef struct Dwarf_Relocation_Data_s * Dwarf_Relocation_Data;
+struct Dwarf_Relocation_Data_s {
+ unsigned char drd_type; /* Cast to/from Dwarf_Rel_Type
+ to keep size small in struct. */
+ unsigned char drd_length; /* Length in bytes of data being
+ relocated. 4 for 32bit data,
+ 8 for 64bit data. */
+ Dwarf_Unsigned drd_offset; /* Where the data to reloc is. */
+ Dwarf_Unsigned drd_symbol_index;
+};
+
+typedef struct Dwarf_P_String_Attr_s * Dwarf_P_String_Attr;
+struct Dwarf_P_String_Attr_s {
+ Dwarf_Unsigned sa_offset; /* Offset of string attribute data */
+ Dwarf_Unsigned sa_nbytes;
+};
+
+
+/* Opaque types for Consumer Library. */
+typedef struct Dwarf_Debug_s* Dwarf_Debug;
+typedef struct Dwarf_Die_s* Dwarf_Die;
+typedef struct Dwarf_Line_s* Dwarf_Line;
+typedef struct Dwarf_Global_s* Dwarf_Global;
+typedef struct Dwarf_Func_s* Dwarf_Func;
+typedef struct Dwarf_Type_s* Dwarf_Type;
+typedef struct Dwarf_Var_s* Dwarf_Var;
+typedef struct Dwarf_Weak_s* Dwarf_Weak;
+typedef struct Dwarf_Error_s* Dwarf_Error;
+typedef struct Dwarf_Attribute_s* Dwarf_Attribute;
+typedef struct Dwarf_Abbrev_s* Dwarf_Abbrev;
+typedef struct Dwarf_Fde_s* Dwarf_Fde;
+typedef struct Dwarf_Cie_s* Dwarf_Cie;
+typedef struct Dwarf_Arange_s* Dwarf_Arange;
+
+/* Opaque types for Producer Library. */
+typedef struct Dwarf_P_Debug_s* Dwarf_P_Debug;
+typedef struct Dwarf_P_Die_s* Dwarf_P_Die;
+typedef struct Dwarf_P_Attribute_s* Dwarf_P_Attribute;
+typedef struct Dwarf_P_Fde_s* Dwarf_P_Fde;
+typedef struct Dwarf_P_Expr_s* Dwarf_P_Expr;
+typedef Dwarf_Unsigned Dwarf_Tag;
+
+
+/* error handler function
+*/
+typedef void (*Dwarf_Handler)(Dwarf_Error /*error*/, Dwarf_Ptr /*errarg*/);
+
+
+/* Begin libdwarf Object File Interface declarations.
+
+As of February 2008 there are multiple dwarf_reader object access
+initialization methods available:
+The traditional dwarf_elf_init() and dwarf_init() and dwarf_finish()
+ which assume libelf and POSIX file access.
+An object-file and library agnostic dwarf_object_init() and dwarf_object_finish()
+ which allow the coder to provide object access routines
+ abstracting away the elf interface. So there is no dependence in the
+ reader code on the object format and no dependence on libelf.
+ See the code in dwarf_elf_access.c and dwarf_original_elf_init.c
+ to see an example of initializing the structures mentioned below.
+
+Projects using dwarf_elf_init() or dwarf_init() can ignore
+the Dwarf_Obj_Access* structures entirely as all these details
+are completed for you.
+
+*/
+
+typedef struct Dwarf_Obj_Access_Interface_s Dwarf_Obj_Access_Interface;
+typedef struct Dwarf_Obj_Access_Methods_s Dwarf_Obj_Access_Methods;
+typedef struct Dwarf_Obj_Access_Section_s Dwarf_Obj_Access_Section;
+
+
+/* Used in the get_section interface function
+ in Dwarf_Obj_Access_Section_s. Since libdwarf
+ depends on standard DWARF section names an object
+ format that has no such names (but has some
+ method of setting up 'sections equivalents')
+ must arrange to return standard DWARF section
+ names in the 'name' field. libdwarf does
+ not free the strings in 'name'. */
+struct Dwarf_Obj_Access_Section_s {
+ /* addr is the virtual address of the first byte of
+ the section data. Usually zero when the address
+ makes no sense for a given section. */
+ Dwarf_Addr addr;
+
+ /* Size in bytes of the section. */
+ Dwarf_Unsigned size;
+
+ /* Having an accurate section name makes debugging of libdwarf easier.
+ and is essential to find the .debug_ sections. */
+ const char* name;
+ /* Set link to zero if it is meaningless. If non-zero
+ it should be a link to a rela section or from symtab
+ to strtab. In Elf it is sh_link. */
+ Dwarf_Unsigned link;
+ /* Elf sections that are tables have a non-zero entrysize so
+ the count of entries can be calculated even without
+ the right structure definition. If your object format
+ does not have this data leave this zero. */
+ Dwarf_Unsigned entrysize;
+};
+
+/* Returned by the get_endianness function in
+ Dwarf_Obj_Access_Methods_s. */
+typedef enum {
+ DW_OBJECT_MSB,
+ DW_OBJECT_LSB
+} Dwarf_Endianness;
+
+/* The functions we need to access object data from libdwarf are declared here.
+
+ In these function pointer declarations
+ 'void *obj' is intended to be a pointer (the object field in
+ Dwarf_Obj_Access_Interface_s)
+ that hides the library-specific and object-specific data that makes
+ it possible to handle multiple object formats and multiple libraries.
+ It's not required that one handles multiple such in a single libdwarf
+ archive/shared-library (but not ruled out either).
+ See dwarf_elf_object_access_internals_t and dwarf_elf_access.c
+ for an example.
+
+*/
+struct Dwarf_Obj_Access_Methods_s {
+ /*
+ get_section_info
+
+ Get address, size, and name info about a section.
+
+ Parameters
+ section_index - Zero-based index.
+ return_section - Pointer to a structure in which section info
+ will be placed. Caller must provide a valid pointer to a
+ structure area. The structure's contents will be overwritten
+ by the call to get_section_info.
+ error - A pointer to an integer in which an error code may be stored.
+
+ Return
+ DW_DLV_OK - Everything ok.
+ DW_DLV_ERROR - Error occurred. Use 'error' to determine the
+ libdwarf defined error.
+ DW_DLV_NO_ENTRY - No such section. */
+ int (*get_section_info)(void* obj, Dwarf_Half section_index,
+ Dwarf_Obj_Access_Section* return_section, int* error);
+ /*
+ get_byte_order
+
+ Get whether the object file represented by this interface is big-endian
+ (DW_OBJECT_MSB) or little endian (DW_OBJECT_LSB).
+
+ Parameters
+ obj - Equivalent to 'this' in OO languages.
+
+ Return
+ Endianness of object. Cannot fail. */
+ Dwarf_Endianness (*get_byte_order)(void* obj);
+ /*
+ get_length_size
+
+ Get the size of a length field in the underlying object file.
+ libdwarf currently supports * 4 and 8 byte sizes, but may
+ support larger in the future.
+ Perhaps the return type should be an enumeration?
+
+ Parameters
+ obj - Equivalent to 'this' in OO languages.
+
+ Return
+ Size of length. Cannot fail. */
+ Dwarf_Small (*get_length_size)(void* obj);
+ /*
+ get_pointer_size
+
+ Get the size of a pointer field in the underlying object file.
+ libdwarf currently supports 4 and 8 byte sizes.
+ Perhaps the return type should be an enumeration?
+
+ Return
+ Size of pointer. Cannot fail. */
+ Dwarf_Small (*get_pointer_size)(void* obj);
+ /*
+ get_section_count
+
+ Get the number of sections in the object file.
+
+ Parameters
+
+ Return
+ Number of sections */
+ Dwarf_Unsigned (*get_section_count)(void* obj);
+ /*
+ load_section
+
+ Get a pointer to an array of bytes that represent the section.
+
+ Parameters
+ section_index - Zero-based index.
+ return_data - The address of a pointer to which the section data block
+ will be assigned.
+ error - Pointer to an integer for returning libdwarf-defined
+ error numbers.
+
+ Return
+ DW_DLV_OK - No error.
+ DW_DLV_ERROR - Error. Use 'error' to indicate a libdwarf-defined
+ error number.
+ DW_DLV_NO_ENTRY - No such section. */
+ int (*load_section)(void* obj, Dwarf_Half section_index,
+ Dwarf_Small** return_data, int* error);
+
+ /**
+ relocate_a_section
+ If relocations are not supported leave this pointer NULL.
+
+ Get a pointer to an array of bytes that represent the section.
+
+ Parameters
+ section_index - Zero-based index of the section to be relocated.
+ error - Pointer to an integer for returning libdwarf-defined
+ error numbers.
+
+ Return
+ DW_DLV_OK - No error.
+ DW_DLV_ERROR - Error. Use 'error' to indicate a libdwarf-defined
+ error number.
+ DW_DLV_NO_ENTRY - No such section. */
+ int (*relocate_a_section)(void* obj, Dwarf_Half section_index,
+ Dwarf_Debug dbg,
+ int* error);
+
+};
+
+
+
+/* These structures are allocated and deallocated by your code
+ when you are using the libdwarf Object File Interface
+ [dwarf_object_init() and dwarf_object_finish()] directly.
+ dwarf_object_finish() does not free
+ struct Dwarf_Obj_Access_Interface_s or its content.
+ (libdwarf does record a pointer to this struct: you must
+ ensure that pointer remains valid for as long as
+ a libdwarf instance is open (meaning
+ after dwarf_init() and before dwarf_finish()).
+
+ If you are reading Elf objects and libelf use dwarf_init()
+ or dwarf_elf_init() which take care of these details.
+*/
+struct Dwarf_Obj_Access_Interface_s {
+ /* object is a void* as it hides the data the object access routines
+ need (which varies by library in use and object format).
+ */
+ void* object;
+ const Dwarf_Obj_Access_Methods * methods;
+};
+
+/* End libdwarf Object File Interface */
+
+/*
+ Dwarf_dealloc() alloc_type arguments.
+ Argument points to:
+*/
+#define DW_DLA_STRING 0x01 /* char* */
+#define DW_DLA_LOC 0x02 /* Dwarf_Loc */
+#define DW_DLA_LOCDESC 0x03 /* Dwarf_Locdesc */
+#define DW_DLA_ELLIST 0x04 /* Dwarf_Ellist (not used)*/
+#define DW_DLA_BOUNDS 0x05 /* Dwarf_Bounds (not used) */
+#define DW_DLA_BLOCK 0x06 /* Dwarf_Block */
+#define DW_DLA_DEBUG 0x07 /* Dwarf_Debug */
+#define DW_DLA_DIE 0x08 /* Dwarf_Die */
+#define DW_DLA_LINE 0x09 /* Dwarf_Line */
+#define DW_DLA_ATTR 0x0a /* Dwarf_Attribute */
+#define DW_DLA_TYPE 0x0b /* Dwarf_Type (not used) */
+#define DW_DLA_SUBSCR 0x0c /* Dwarf_Subscr (not used) */
+#define DW_DLA_GLOBAL 0x0d /* Dwarf_Global */
+#define DW_DLA_ERROR 0x0e /* Dwarf_Error */
+#define DW_DLA_LIST 0x0f /* a list */
+#define DW_DLA_LINEBUF 0x10 /* Dwarf_Line* (not used) */
+#define DW_DLA_ARANGE 0x11 /* Dwarf_Arange */
+#define DW_DLA_ABBREV 0x12 /* Dwarf_Abbrev */
+#define DW_DLA_FRAME_OP 0x13 /* Dwarf_Frame_Op */
+#define DW_DLA_CIE 0x14 /* Dwarf_Cie */
+#define DW_DLA_FDE 0x15 /* Dwarf_Fde */
+#define DW_DLA_LOC_BLOCK 0x16 /* Dwarf_Loc Block (not used) */
+#define DW_DLA_FRAME_BLOCK 0x17 /* Dwarf_Frame Block (not used) */
+#define DW_DLA_FUNC 0x18 /* Dwarf_Func */
+#define DW_DLA_TYPENAME 0x19 /* Dwarf_Type */
+#define DW_DLA_VAR 0x1a /* Dwarf_Var */
+#define DW_DLA_WEAK 0x1b /* Dwarf_Weak */
+#define DW_DLA_ADDR 0x1c /* Dwarf_Addr sized entries */
+#define DW_DLA_RANGES 0x1d /* Dwarf_Ranges */
+
+/* The augmenter string for CIE */
+#define DW_CIE_AUGMENTER_STRING_V0 "z"
+
+/* dwarf_init() access arguments
+*/
+#define DW_DLC_READ 0 /* read only access */
+#define DW_DLC_WRITE 1 /* write only access */
+#define DW_DLC_RDWR 2 /* read/write access NOT SUPPORTED*/
+
+/* dwarf_producer_init*() access flag modifiers
+ If HAVE_DWARF2_99_EXTENSION is defined at libdwarf build time
+ and DW_DLC_OFFSET_SIZE_64 is passed in producer_init()
+ flags then the DWARF3 64 bit offset extension is used
+ to generate 64 bit offsets.
+*/
+#define DW_DLC_SIZE_64 0x40000000 /* 64-bit address-size target */
+#define DW_DLC_SIZE_32 0x20000000 /* 32-bit address-size target */
+#define DW_DLC_OFFSET_SIZE_64 0x10000000 /* 64-bit offset-size DWARF */
+
+/* dwarf_producer_init*() access flag modifiers
+*/
+#define DW_DLC_ISA_MIPS 0x00000000 /* MIPS target */
+#define DW_DLC_ISA_IA64 0x01000000 /* IA64 target */
+#define DW_DLC_STREAM_RELOCATIONS 0x02000000 /* Old style binary relocs */
+
+ /* Usable with assembly output because it is up to the producer to
+ deal with locations in whatever manner the producer code wishes.
+ Possibly emitting text an assembler will recognize. */
+#define DW_DLC_SYMBOLIC_RELOCATIONS 0x04000000
+
+#define DW_DLC_TARGET_BIGENDIAN 0x08000000 /* Big endian target */
+#define DW_DLC_TARGET_LITTLEENDIAN 0x00100000 /* Little endian target */
+
+#if 0
+ /*
+ The libdwarf producer interfaces jumble these two semantics together in
+ confusing ways. We *should* have flags like these...
+ But changing the code means a lot of diffs. So for now,
+ we leave things as they are
+ */
+ #define DW_DLC_SUN_OFFSET32 0x00010000 /* use 32-bit sec offsets */
+ #define DW_DLC_SUN_OFFSET64 0x00020000 /* use 64-bit sec offsets */
+ #define DW_DLC_SUN_POINTER32 0x00040000 /* use 4 for address_size */
+ #define DW_DLC_SUN_POINTER64 0x00080000 /* use 8 for address_size */
+#endif
+
+/* dwarf_pcline() slide arguments
+*/
+#define DW_DLS_BACKWARD -1 /* slide backward to find line */
+#define DW_DLS_NOSLIDE 0 /* match exactly without sliding */
+#define DW_DLS_FORWARD 1 /* slide forward to find line */
+
+/* libdwarf error numbers
+*/
+#define DW_DLE_NE 0 /* no error */
+#define DW_DLE_VMM 1 /* dwarf format/library version mismatch */
+#define DW_DLE_MAP 2 /* memory map failure */
+#define DW_DLE_LEE 3 /* libelf error */
+#define DW_DLE_NDS 4 /* no debug section */
+#define DW_DLE_NLS 5 /* no line section */
+#define DW_DLE_ID 6 /* invalid descriptor for query */
+#define DW_DLE_IOF 7 /* I/O failure */
+#define DW_DLE_MAF 8 /* memory allocation failure */
+#define DW_DLE_IA 9 /* invalid argument */
+#define DW_DLE_MDE 10 /* mangled debugging entry */
+#define DW_DLE_MLE 11 /* mangled line number entry */
+#define DW_DLE_FNO 12 /* file not open */
+#define DW_DLE_FNR 13 /* file not a regular file */
+#define DW_DLE_FWA 14 /* file open with wrong access */
+#define DW_DLE_NOB 15 /* not an object file */
+#define DW_DLE_MOF 16 /* mangled object file header */
+#define DW_DLE_EOLL 17 /* end of location list entries */
+#define DW_DLE_NOLL 18 /* no location list section */
+#define DW_DLE_BADOFF 19 /* Invalid offset */
+#define DW_DLE_EOS 20 /* end of section */
+#define DW_DLE_ATRUNC 21 /* abbreviations section appears truncated*/
+#define DW_DLE_BADBITC 22 /* Address size passed to dwarf bad*/
+ /* It is not an allowed size (64 or 32) */
+ /* Error codes defined by the current Libdwarf Implementation. */
+#define DW_DLE_DBG_ALLOC 23
+#define DW_DLE_FSTAT_ERROR 24
+#define DW_DLE_FSTAT_MODE_ERROR 25
+#define DW_DLE_INIT_ACCESS_WRONG 26
+#define DW_DLE_ELF_BEGIN_ERROR 27
+#define DW_DLE_ELF_GETEHDR_ERROR 28
+#define DW_DLE_ELF_GETSHDR_ERROR 29
+#define DW_DLE_ELF_STRPTR_ERROR 30
+#define DW_DLE_DEBUG_INFO_DUPLICATE 31
+#define DW_DLE_DEBUG_INFO_NULL 32
+#define DW_DLE_DEBUG_ABBREV_DUPLICATE 33
+#define DW_DLE_DEBUG_ABBREV_NULL 34
+#define DW_DLE_DEBUG_ARANGES_DUPLICATE 35
+#define DW_DLE_DEBUG_ARANGES_NULL 36
+#define DW_DLE_DEBUG_LINE_DUPLICATE 37
+#define DW_DLE_DEBUG_LINE_NULL 38
+#define DW_DLE_DEBUG_LOC_DUPLICATE 39
+#define DW_DLE_DEBUG_LOC_NULL 40
+#define DW_DLE_DEBUG_MACINFO_DUPLICATE 41
+#define DW_DLE_DEBUG_MACINFO_NULL 42
+#define DW_DLE_DEBUG_PUBNAMES_DUPLICATE 43
+#define DW_DLE_DEBUG_PUBNAMES_NULL 44
+#define DW_DLE_DEBUG_STR_DUPLICATE 45
+#define DW_DLE_DEBUG_STR_NULL 46
+#define DW_DLE_CU_LENGTH_ERROR 47
+#define DW_DLE_VERSION_STAMP_ERROR 48
+#define DW_DLE_ABBREV_OFFSET_ERROR 49
+#define DW_DLE_ADDRESS_SIZE_ERROR 50
+#define DW_DLE_DEBUG_INFO_PTR_NULL 51
+#define DW_DLE_DIE_NULL 52
+#define DW_DLE_STRING_OFFSET_BAD 53
+#define DW_DLE_DEBUG_LINE_LENGTH_BAD 54
+#define DW_DLE_LINE_PROLOG_LENGTH_BAD 55
+#define DW_DLE_LINE_NUM_OPERANDS_BAD 56
+#define DW_DLE_LINE_SET_ADDR_ERROR 57 /* No longer used. */
+#define DW_DLE_LINE_EXT_OPCODE_BAD 58
+#define DW_DLE_DWARF_LINE_NULL 59
+#define DW_DLE_INCL_DIR_NUM_BAD 60
+#define DW_DLE_LINE_FILE_NUM_BAD 61
+#define DW_DLE_ALLOC_FAIL 62
+#define DW_DLE_NO_CALLBACK_FUNC 63
+#define DW_DLE_SECT_ALLOC 64
+#define DW_DLE_FILE_ENTRY_ALLOC 65
+#define DW_DLE_LINE_ALLOC 66
+#define DW_DLE_FPGM_ALLOC 67
+#define DW_DLE_INCDIR_ALLOC 68
+#define DW_DLE_STRING_ALLOC 69
+#define DW_DLE_CHUNK_ALLOC 70
+#define DW_DLE_BYTEOFF_ERR 71
+#define DW_DLE_CIE_ALLOC 72
+#define DW_DLE_FDE_ALLOC 73
+#define DW_DLE_REGNO_OVFL 74
+#define DW_DLE_CIE_OFFS_ALLOC 75
+#define DW_DLE_WRONG_ADDRESS 76
+#define DW_DLE_EXTRA_NEIGHBORS 77
+#define DW_DLE_WRONG_TAG 78
+#define DW_DLE_DIE_ALLOC 79
+#define DW_DLE_PARENT_EXISTS 80
+#define DW_DLE_DBG_NULL 81
+#define DW_DLE_DEBUGLINE_ERROR 82
+#define DW_DLE_DEBUGFRAME_ERROR 83
+#define DW_DLE_DEBUGINFO_ERROR 84
+#define DW_DLE_ATTR_ALLOC 85
+#define DW_DLE_ABBREV_ALLOC 86
+#define DW_DLE_OFFSET_UFLW 87
+#define DW_DLE_ELF_SECT_ERR 88
+#define DW_DLE_DEBUG_FRAME_LENGTH_BAD 89
+#define DW_DLE_FRAME_VERSION_BAD 90
+#define DW_DLE_CIE_RET_ADDR_REG_ERROR 91
+#define DW_DLE_FDE_NULL 92
+#define DW_DLE_FDE_DBG_NULL 93
+#define DW_DLE_CIE_NULL 94
+#define DW_DLE_CIE_DBG_NULL 95
+#define DW_DLE_FRAME_TABLE_COL_BAD 96
+#define DW_DLE_PC_NOT_IN_FDE_RANGE 97
+#define DW_DLE_CIE_INSTR_EXEC_ERROR 98
+#define DW_DLE_FRAME_INSTR_EXEC_ERROR 99
+#define DW_DLE_FDE_PTR_NULL 100
+#define DW_DLE_RET_OP_LIST_NULL 101
+#define DW_DLE_LINE_CONTEXT_NULL 102
+#define DW_DLE_DBG_NO_CU_CONTEXT 103
+#define DW_DLE_DIE_NO_CU_CONTEXT 104
+#define DW_DLE_FIRST_DIE_NOT_CU 105
+#define DW_DLE_NEXT_DIE_PTR_NULL 106
+#define DW_DLE_DEBUG_FRAME_DUPLICATE 107
+#define DW_DLE_DEBUG_FRAME_NULL 108
+#define DW_DLE_ABBREV_DECODE_ERROR 109
+#define DW_DLE_DWARF_ABBREV_NULL 110
+#define DW_DLE_ATTR_NULL 111
+#define DW_DLE_DIE_BAD 112
+#define DW_DLE_DIE_ABBREV_BAD 113
+#define DW_DLE_ATTR_FORM_BAD 114
+#define DW_DLE_ATTR_NO_CU_CONTEXT 115
+#define DW_DLE_ATTR_FORM_SIZE_BAD 116
+#define DW_DLE_ATTR_DBG_NULL 117
+#define DW_DLE_BAD_REF_FORM 118
+#define DW_DLE_ATTR_FORM_OFFSET_BAD 119
+#define DW_DLE_LINE_OFFSET_BAD 120
+#define DW_DLE_DEBUG_STR_OFFSET_BAD 121
+#define DW_DLE_STRING_PTR_NULL 122
+#define DW_DLE_PUBNAMES_VERSION_ERROR 123
+#define DW_DLE_PUBNAMES_LENGTH_BAD 124
+#define DW_DLE_GLOBAL_NULL 125
+#define DW_DLE_GLOBAL_CONTEXT_NULL 126
+#define DW_DLE_DIR_INDEX_BAD 127
+#define DW_DLE_LOC_EXPR_BAD 128
+#define DW_DLE_DIE_LOC_EXPR_BAD 129
+#define DW_DLE_ADDR_ALLOC 130
+#define DW_DLE_OFFSET_BAD 131
+#define DW_DLE_MAKE_CU_CONTEXT_FAIL 132
+#define DW_DLE_REL_ALLOC 133
+#define DW_DLE_ARANGE_OFFSET_BAD 134
+#define DW_DLE_SEGMENT_SIZE_BAD 135
+#define DW_DLE_ARANGE_LENGTH_BAD 136
+#define DW_DLE_ARANGE_DECODE_ERROR 137
+#define DW_DLE_ARANGES_NULL 138
+#define DW_DLE_ARANGE_NULL 139
+#define DW_DLE_NO_FILE_NAME 140
+#define DW_DLE_NO_COMP_DIR 141
+#define DW_DLE_CU_ADDRESS_SIZE_BAD 142
+#define DW_DLE_INPUT_ATTR_BAD 143
+#define DW_DLE_EXPR_NULL 144
+#define DW_DLE_BAD_EXPR_OPCODE 145
+#define DW_DLE_EXPR_LENGTH_BAD 146
+#define DW_DLE_MULTIPLE_RELOC_IN_EXPR 147
+#define DW_DLE_ELF_GETIDENT_ERROR 148
+#define DW_DLE_NO_AT_MIPS_FDE 149
+#define DW_DLE_NO_CIE_FOR_FDE 150
+#define DW_DLE_DIE_ABBREV_LIST_NULL 151
+#define DW_DLE_DEBUG_FUNCNAMES_DUPLICATE 152
+#define DW_DLE_DEBUG_FUNCNAMES_NULL 153
+#define DW_DLE_DEBUG_FUNCNAMES_VERSION_ERROR 154
+#define DW_DLE_DEBUG_FUNCNAMES_LENGTH_BAD 155
+#define DW_DLE_FUNC_NULL 156
+#define DW_DLE_FUNC_CONTEXT_NULL 157
+#define DW_DLE_DEBUG_TYPENAMES_DUPLICATE 158
+#define DW_DLE_DEBUG_TYPENAMES_NULL 159
+#define DW_DLE_DEBUG_TYPENAMES_VERSION_ERROR 160
+#define DW_DLE_DEBUG_TYPENAMES_LENGTH_BAD 161
+#define DW_DLE_TYPE_NULL 162
+#define DW_DLE_TYPE_CONTEXT_NULL 163
+#define DW_DLE_DEBUG_VARNAMES_DUPLICATE 164
+#define DW_DLE_DEBUG_VARNAMES_NULL 165
+#define DW_DLE_DEBUG_VARNAMES_VERSION_ERROR 166
+#define DW_DLE_DEBUG_VARNAMES_LENGTH_BAD 167
+#define DW_DLE_VAR_NULL 168
+#define DW_DLE_VAR_CONTEXT_NULL 169
+#define DW_DLE_DEBUG_WEAKNAMES_DUPLICATE 170
+#define DW_DLE_DEBUG_WEAKNAMES_NULL 171
+#define DW_DLE_DEBUG_WEAKNAMES_VERSION_ERROR 172
+#define DW_DLE_DEBUG_WEAKNAMES_LENGTH_BAD 173
+#define DW_DLE_WEAK_NULL 174
+#define DW_DLE_WEAK_CONTEXT_NULL 175
+#define DW_DLE_LOCDESC_COUNT_WRONG 176
+#define DW_DLE_MACINFO_STRING_NULL 177
+#define DW_DLE_MACINFO_STRING_EMPTY 178
+#define DW_DLE_MACINFO_INTERNAL_ERROR_SPACE 179
+#define DW_DLE_MACINFO_MALLOC_FAIL 180
+#define DW_DLE_DEBUGMACINFO_ERROR 181
+#define DW_DLE_DEBUG_MACRO_LENGTH_BAD 182
+#define DW_DLE_DEBUG_MACRO_MAX_BAD 183
+#define DW_DLE_DEBUG_MACRO_INTERNAL_ERR 184
+#define DW_DLE_DEBUG_MACRO_MALLOC_SPACE 185
+#define DW_DLE_DEBUG_MACRO_INCONSISTENT 186
+#define DW_DLE_DF_NO_CIE_AUGMENTATION 187
+#define DW_DLE_DF_REG_NUM_TOO_HIGH 188
+#define DW_DLE_DF_MAKE_INSTR_NO_INIT 189
+#define DW_DLE_DF_NEW_LOC_LESS_OLD_LOC 190
+#define DW_DLE_DF_POP_EMPTY_STACK 191
+#define DW_DLE_DF_ALLOC_FAIL 192
+#define DW_DLE_DF_FRAME_DECODING_ERROR 193
+#define DW_DLE_DEBUG_LOC_SECTION_SHORT 194
+#define DW_DLE_FRAME_AUGMENTATION_UNKNOWN 195
+#define DW_DLE_PUBTYPE_CONTEXT 196 /* Unused. */
+#define DW_DLE_DEBUG_PUBTYPES_LENGTH_BAD 197
+#define DW_DLE_DEBUG_PUBTYPES_VERSION_ERROR 198
+#define DW_DLE_DEBUG_PUBTYPES_DUPLICATE 199
+#define DW_DLE_FRAME_CIE_DECODE_ERROR 200
+#define DW_DLE_FRAME_REGISTER_UNREPRESENTABLE 201
+#define DW_DLE_FRAME_REGISTER_COUNT_MISMATCH 202
+#define DW_DLE_LINK_LOOP 203
+#define DW_DLE_STRP_OFFSET_BAD 204
+#define DW_DLE_DEBUG_RANGES_DUPLICATE 205
+#define DW_DLE_DEBUG_RANGES_OFFSET_BAD 206
+#define DW_DLE_DEBUG_RANGES_MISSING_END 207
+#define DW_DLE_DEBUG_RANGES_OUT_OF_MEM 208
+#define DW_DLE_DEBUG_SYMTAB_ERR 209
+#define DW_DLE_DEBUG_STRTAB_ERR 210
+#define DW_DLE_RELOC_MISMATCH_INDEX 211
+#define DW_DLE_RELOC_MISMATCH_RELOC_INDEX 212
+#define DW_DLE_RELOC_MISMATCH_STRTAB_INDEX 213
+#define DW_DLE_RELOC_SECTION_MISMATCH 214
+#define DW_DLE_RELOC_SECTION_MISSING_INDEX 215
+#define DW_DLE_RELOC_SECTION_LENGTH_ODD 216
+#define DW_DLE_RELOC_SECTION_PTR_NULL 217
+#define DW_DLE_RELOC_SECTION_MALLOC_FAIL 218
+#define DW_DLE_NO_ELF64_SUPPORT 219
+#define DW_DLE_MISSING_ELF64_SUPPORT 220
+#define DW_DLE_ORPHAN_FDE 221
+#define DW_DLE_DUPLICATE_INST_BLOCK 222
+#define DW_DLE_BAD_REF_SIG8_FORM 223
+#define DW_DLE_ATTR_EXPRLOC_FORM_BAD 224
+#define DW_DLE_FORM_SEC_OFFSET_LENGTH_BAD 225
+#define DW_DLE_NOT_REF_FORM 226
+#define DW_DLE_DEBUG_FRAME_LENGTH_NOT_MULTIPLE 227
+#define DW_DLE_REF_SIG8_NOT_HANDLED 228
+#define DW_DLE_DEBUG_FRAME_POSSIBLE_ADDRESS_BOTCH 229
+#define DW_DLE_LOC_BAD_TERMINATION 230
+#define DW_DLE_SYMTAB_SECTION_LENGTH_ODD 231
+#define DW_DLE_RELOC_SECTION_SYMBOL_INDEX_BAD 232
+#define DW_DLE_RELOC_SECTION_RELOC_TARGET_SIZE_UNKNOWN 233
+#define DW_DLE_SYMTAB_SECTION_ENTRYSIZE_ZERO 234
+#define DW_DLE_LINE_NUMBER_HEADER_ERROR 235
+#define DW_DLE_DEBUG_TYPES_NULL 236
+#define DW_DLE_DEBUG_TYPES_DUPLICATE 237
+#define DW_DLE_DEBUG_TYPES_ONLY_DWARF4 238
+#define DW_DLE_DEBUG_TYPEOFFSET_BAD 239
+#define DW_DLE_GNU_OPCODE_ERROR 240
+
+
+ /* DW_DLE_LAST MUST EQUAL LAST ERROR NUMBER */
+#define DW_DLE_LAST 239
+#define DW_DLE_LO_USER 0x10000
+
+ /* Taken as meaning 'undefined value', this is not
+ a column or register number.
+ Only present at libdwarf runtime. Never on disk.
+ DW_FRAME_* Values present on disk are in dwarf.h
+ */
+#define DW_FRAME_UNDEFINED_VAL 1034
+
+ /* Taken as meaning 'same value' as caller had, not a column
+ or register number
+ Only present at libdwarf runtime. Never on disk.
+ DW_FRAME_* Values present on disk are in dwarf.h
+ */
+#define DW_FRAME_SAME_VAL 1035
+
+
+
+/* error return values
+*/
+#define DW_DLV_BADADDR (~(Dwarf_Addr)0)
+ /* for functions returning target address */
+
+#define DW_DLV_NOCOUNT ((Dwarf_Signed)-1)
+ /* for functions returning count */
+
+#define DW_DLV_BADOFFSET (~(Dwarf_Off)0)
+ /* for functions returning offset */
+
+/* standard return values for functions */
+#define DW_DLV_NO_ENTRY -1
+#define DW_DLV_OK 0
+#define DW_DLV_ERROR 1
+
+/* Special values for offset_into_exception_table field of dwarf fde's. */
+/* The following value indicates that there is no Exception table offset
+ associated with a dwarf frame. */
+#define DW_DLX_NO_EH_OFFSET (-1LL)
+/* The following value indicates that the producer was unable to analyse the
+ source file to generate Exception tables for this function. */
+#define DW_DLX_EH_OFFSET_UNAVAILABLE (-2LL)
+
+
+/*===========================================================================*/
+/* Dwarf consumer interface initialization and termination operations */
+
+/* Initialization based on Unix open fd (using libelf internally). */
+int dwarf_init(int /*fd*/,
+ Dwarf_Unsigned /*access*/,
+ Dwarf_Handler /*errhand*/,
+ Dwarf_Ptr /*errarg*/,
+ Dwarf_Debug* /*dbg*/,
+ Dwarf_Error* /*error*/);
+
+/* Initialization based on libelf/sgi-fastlibelf open pointer. */
+int dwarf_elf_init(dwarf_elf_handle /*elf*/,
+ Dwarf_Unsigned /*access*/,
+ Dwarf_Handler /*errhand*/,
+ Dwarf_Ptr /*errarg*/,
+ Dwarf_Debug* /*dbg*/,
+ Dwarf_Error* /*error*/);
+
+/* Undocumented function for memory allocator. */
+void dwarf_print_memory_stats(Dwarf_Debug /*dbg*/);
+
+int dwarf_get_elf(Dwarf_Debug /*dbg*/,
+ dwarf_elf_handle* /*return_elfptr*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_finish(Dwarf_Debug /*dbg*/, Dwarf_Error* /*error*/);
+
+
+int dwarf_object_init(Dwarf_Obj_Access_Interface* /* obj */,
+ Dwarf_Handler /* errhand */,
+ Dwarf_Ptr /* errarg */,
+ Dwarf_Debug* /* dbg */,
+ Dwarf_Error* /* error */);
+
+int dwarf_object_finish(Dwarf_Debug /* dbg */,
+ Dwarf_Error* /* error */);
+
+/* Die traversal operations.
+ dwarf_next_cu_header_b() traverses debug_info CU headers.
+ */
+int dwarf_next_cu_header_b(Dwarf_Debug /*dbg*/,
+ Dwarf_Unsigned* /*cu_header_length*/,
+ Dwarf_Half* /*version_stamp*/,
+ Dwarf_Off* /*abbrev_offset*/,
+ Dwarf_Half* /*address_size*/,
+ Dwarf_Half* /*length_size*/,
+ Dwarf_Half* /*extension_size*/,
+ Dwarf_Unsigned* /*next_cu_header_offset*/,
+ Dwarf_Error* /*error*/);
+
+/* dwarf_next_cu_header_types() traverses debug_types CU headers.
+ New in October, 2011
+ */
+int dwarf_next_cu_header_c(Dwarf_Debug /*dbg*/,
+ Dwarf_Bool /*is_info*/,
+ Dwarf_Unsigned* /*cu_header_length*/,
+ Dwarf_Half* /*version_stamp*/,
+ Dwarf_Off* /*abbrev_offset*/,
+ Dwarf_Half* /*address_size*/,
+ Dwarf_Half* /*length_size*/,
+ Dwarf_Half* /*extension_size*/,
+ Dwarf_Sig8* /*type signature*/,
+ Dwarf_Unsigned* /*typeoffset*/,
+ Dwarf_Unsigned* /*next_cu_header_offset*/,
+ Dwarf_Error* /*error*/);
+/* The following is obsolete, though supported. November 2009. */
+int dwarf_next_cu_header(Dwarf_Debug /*dbg*/,
+ Dwarf_Unsigned* /*cu_header_length*/,
+ Dwarf_Half* /*version_stamp*/,
+ Dwarf_Off* /*abbrev_offset*/,
+ Dwarf_Half* /*address_size*/,
+ Dwarf_Unsigned* /*next_cu_header_offset*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_siblingof(Dwarf_Debug /*dbg*/,
+ Dwarf_Die /*die*/,
+ Dwarf_Die* /*return_siblingdie*/,
+ Dwarf_Error* /*error*/);
+/* dwarf_siblingof_b new October 2011. */
+int dwarf_siblingof_b(Dwarf_Debug /*dbg*/,
+ Dwarf_Die /*die*/,
+ Dwarf_Bool /*is_info*/,
+ Dwarf_Die* /*return_siblingdie*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_child(Dwarf_Die /*die*/,
+ Dwarf_Die* /*return_childdie*/,
+ Dwarf_Error* /*error*/);
+
+/* Finding die given global (not CU-relative) offset.
+ Applies only to debug_info. */
+int dwarf_offdie(Dwarf_Debug /*dbg*/,
+ Dwarf_Off /*offset*/,
+ Dwarf_Die* /*return_die*/,
+ Dwarf_Error* /*error*/);
+
+/* dwarf_offdie_b() new October 2011 */
+/* Finding die given global (not CU-relative) offset.
+ Applies to debug_info (is_info true) or debug_types (is_info false). */
+int dwarf_offdie_b(Dwarf_Debug /*dbg*/,
+ Dwarf_Off /*offset*/,
+ Dwarf_Bool /*is_info*/,
+ Dwarf_Die* /*return_die*/,
+ Dwarf_Error* /*error*/);
+
+/* Returns the is_info flag through the pointer if the function returns
+ DW_DLV_OK. Needed so client software knows if a DIE is in debug_info
+ or debug_types.
+ New October 2011. */
+Dwarf_Bool dwarf_get_die_infotypes_flag(Dwarf_Die /*die*/);
+
+/* Higher level functions (Unimplemented) */
+int dwarf_pcfile(Dwarf_Debug /*dbg*/,
+ Dwarf_Addr /*pc*/,
+ Dwarf_Die* /*return_die*/,
+ Dwarf_Error* /*error*/);
+
+/* Unimplemented */
+int dwarf_pcsubr(Dwarf_Debug /*dbg*/,
+ Dwarf_Addr /*pc*/,
+ Dwarf_Die* /*return_die*/,
+ Dwarf_Error* /*error*/);
+
+/* Unimplemented */
+int dwarf_pcscope(Dwarf_Debug /*dbg*/,
+ Dwarf_Addr /*pc*/,
+ Dwarf_Die* /*return_die*/,
+ Dwarf_Error* /*error*/);
+
+/* operations on DIEs */
+int dwarf_tag(Dwarf_Die /*die*/,
+ Dwarf_Half* /*return_tag*/,
+ Dwarf_Error* /*error*/);
+
+/* utility? */
+/* dwarf_dieoffset returns the global debug_info
+ section offset, not the CU relative offset. */
+int dwarf_dieoffset(Dwarf_Die /*die*/,
+ Dwarf_Off* /*return_offset*/,
+ Dwarf_Error* /*error*/);
+
+/* dwarf_CU_dieoffset_given_die returns
+ the global debug_info section offset of the CU die
+ that is the CU containing the given_die
+ (the passed in DIE can be any DIE).
+ This information makes it possible for a consumer to
+ find and print CU context information for any die.
+ See also dwarf_get_cu_die_offset_given_cu_header_offset(). */
+int dwarf_CU_dieoffset_given_die(Dwarf_Die /*given_die*/,
+ Dwarf_Off* /*return_offset*/,
+ Dwarf_Error* /*error*/);
+
+/* dwarf_die_CU_offset returns the CU relative offset
+ not the global debug_info section offset, given
+ any DIE in the CU. See also dwarf_CU_dieoffset_given_die().
+ */
+int dwarf_die_CU_offset(Dwarf_Die /*die*/,
+ Dwarf_Off* /*return_offset*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_die_CU_offset_range(Dwarf_Die /*die*/,
+ Dwarf_Off* /*return_CU_header_offset*/,
+ Dwarf_Off* /*return_CU_length_bytes*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_attr (Dwarf_Die /*die*/,
+ Dwarf_Half /*attr*/,
+ Dwarf_Attribute * /*returned_attr*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_diename(Dwarf_Die /*die*/,
+ char ** /*diename*/,
+ Dwarf_Error* /*error*/);
+
+/* Returns the abbrev code of the die. Cannot fail. */
+int dwarf_die_abbrev_code(Dwarf_Die /*die */);
+
+/* Returns a flag through ab_has_child. Non-zero if
+ the DIE has children, zero if it does not. */
+int dwarf_die_abbrev_children_flag(Dwarf_Die /*die*/,
+ Dwarf_Half * /*ab_has_child*/);
+
+/* Validate the sibling DIE. This only makes sense to call
+ if the sibling's DIEs have been travsersed and
+ dwarf_child() called on each,
+ so that the last DIE dwarf_child saw was the last.
+ Essentially ensuring that (after such traversal) that we
+ are in the same place a sibling attribute would identify.
+ In case we return DW_DLV_ERROR, the global offset of the last
+ DIE traversed by dwarf_child is returned through *offset */
+int dwarf_validate_die_sibling(Dwarf_Die /*sibling*/,Dwarf_Off* /*offset*/);
+
+/* convenience functions, alternative to using dwarf_attrlist() */
+int dwarf_hasattr(Dwarf_Die /*die*/,
+ Dwarf_Half /*attr*/,
+ Dwarf_Bool * /*returned_bool*/,
+ Dwarf_Error* /*error*/);
+
+/* dwarf_loclist_n preferred over dwarf_loclist */
+int dwarf_loclist_n(Dwarf_Attribute /*attr*/,
+ Dwarf_Locdesc*** /*llbuf*/,
+ Dwarf_Signed * /*locCount*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_loclist(Dwarf_Attribute /*attr*/, /* inflexible! */
+ Dwarf_Locdesc** /*llbuf*/,
+ Dwarf_Signed * /*locCount*/,
+ Dwarf_Error* /*error*/);
+
+/* Extracts a dwarf expression from an expression byte stream.
+ Useful to get expressions from DW_CFA_def_cfa_expression
+ DW_CFA_expression DW_CFA_val_expression expression bytes.
+ 27 April 2009: dwarf_loclist_from_expr() interface with
+ no addr_size is obsolete but supported,
+ use dwarf_loclist_from_expr_a() instead.
+*/
+int dwarf_loclist_from_expr(Dwarf_Debug dbg,
+ Dwarf_Ptr expression_in,
+ Dwarf_Unsigned expression_length,
+ Dwarf_Locdesc ** llbuf,
+ Dwarf_Signed * listlen, Dwarf_Error * error);
+
+/* dwarf_loclist_from_expr_a() new 27 Apr 2009: added addr_size argument. */
+int dwarf_loclist_from_expr_a(Dwarf_Debug dbg,
+ Dwarf_Ptr expression_in,
+ Dwarf_Unsigned expression_length,
+ Dwarf_Half addr_size,
+ Dwarf_Locdesc ** llbuf,
+ Dwarf_Signed * listlen, Dwarf_Error * error);
+
+/* Unimplemented */
+int dwarf_stringlen(Dwarf_Die /*die*/,
+ Dwarf_Locdesc ** /*returned_locdesc*/,
+ Dwarf_Error* /*error*/);
+
+/* Unimplemented */
+int dwarf_subscrcnt(Dwarf_Die /*die*/,
+ Dwarf_Signed * /*returned_count*/,
+ Dwarf_Error* /*error*/);
+
+/* Unimplemented */
+int dwarf_nthsubscr(Dwarf_Die /*die*/,
+ Dwarf_Unsigned /*ssndx*/,
+ Dwarf_Die * /*returned_die*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_lowpc(Dwarf_Die /*die*/,
+ Dwarf_Addr * /*returned_addr*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_highpc(Dwarf_Die /*die*/,
+ Dwarf_Addr * /*returned_addr*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_bytesize(Dwarf_Die /*die*/,
+ Dwarf_Unsigned * /*returned_size*/,
+ Dwarf_Error* /*error*/);
+
+/* Unimplemented */
+int dwarf_isbitfield(Dwarf_Die /*die*/,
+ Dwarf_Bool * /*returned_bool*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_bitsize(Dwarf_Die /*die*/,
+ Dwarf_Unsigned * /*returned_size*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_bitoffset(Dwarf_Die /*die*/,
+ Dwarf_Unsigned * /*returned_offset*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_srclang(Dwarf_Die /*die*/,
+ Dwarf_Unsigned * /*returned_lang*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_arrayorder(Dwarf_Die /*die*/,
+ Dwarf_Unsigned * /*returned_order*/,
+ Dwarf_Error* /*error*/);
+
+/* end of convenience function list */
+
+/* this is the main interface to attributes of a DIE */
+int dwarf_attrlist(Dwarf_Die /*die*/,
+ Dwarf_Attribute** /*attrbuf*/,
+ Dwarf_Signed * /*attrcount*/,
+ Dwarf_Error* /*error*/);
+
+/* query operations for attributes */
+int dwarf_hasform(Dwarf_Attribute /*attr*/,
+ Dwarf_Half /*form*/,
+ Dwarf_Bool * /*returned_bool*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_whatform(Dwarf_Attribute /*attr*/,
+ Dwarf_Half * /*returned_form*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_whatform_direct(Dwarf_Attribute /*attr*/,
+ Dwarf_Half * /*returned_form*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_whatattr(Dwarf_Attribute /*attr*/,
+ Dwarf_Half * /*returned_attr_num*/,
+ Dwarf_Error* /*error*/);
+
+/*
+ The following are concerned with the Primary Interface: getting
+ the actual data values. One function per 'kind' of FORM.
+*/
+/* dwarf_formref returns, thru return_offset, a CU-relative offset
+ and does not allow DW_FORM_ref_addr*/
+int dwarf_formref(Dwarf_Attribute /*attr*/,
+ Dwarf_Off* /*return_offset*/,
+ Dwarf_Error* /*error*/);
+/* dwarf_global_formref returns, thru return_offset,
+ a debug_info-relative offset and does allow all reference forms*/
+int dwarf_global_formref(Dwarf_Attribute /*attr*/,
+ Dwarf_Off* /*return_offset*/,
+ Dwarf_Error* /*error*/);
+
+/* dwarf_formsig8 returns in the caller-provided 8 byte area
+ the 8 bytes of a DW_FORM_ref_sig8. Not a string. */
+int dwarf_formsig8(Dwarf_Attribute /*attr*/,
+ Dwarf_Sig8 * /*returned sig bytes*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_formaddr(Dwarf_Attribute /*attr*/,
+ Dwarf_Addr * /*returned_addr*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_formflag(Dwarf_Attribute /*attr*/,
+ Dwarf_Bool * /*returned_bool*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_formudata(Dwarf_Attribute /*attr*/,
+ Dwarf_Unsigned * /*returned_val*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_formsdata(Dwarf_Attribute /*attr*/,
+ Dwarf_Signed * /*returned_val*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_formblock(Dwarf_Attribute /*attr*/,
+ Dwarf_Block ** /*returned_block*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_formstring(Dwarf_Attribute /*attr*/,
+ char ** /*returned_string*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_formexprloc(Dwarf_Attribute /*attr*/,
+ Dwarf_Unsigned * /*return_exprlen*/,
+ Dwarf_Ptr * /*block_ptr*/,
+ Dwarf_Error * /*error*/);
+
+
+/* end attribute query operations. */
+
+/* line number operations */
+/* dwarf_srclines is the normal interface */
+int dwarf_srclines(Dwarf_Die /*die*/,
+ Dwarf_Line** /*linebuf*/,
+ Dwarf_Signed * /*linecount*/,
+ Dwarf_Error* /*error*/);
+
+/* dwarf_srclines_dealloc, created July 2005, is the new
+ method for deallocating what dwarf_srclines returns.
+ More complete free than using dwarf_dealloc directly. */
+void dwarf_srclines_dealloc(Dwarf_Debug /*dbg*/,
+ Dwarf_Line* /*linebuf*/,
+ Dwarf_Signed /*count */);
+
+
+int dwarf_srcfiles(Dwarf_Die /*die*/,
+ char*** /*srcfiles*/,
+ Dwarf_Signed * /*filecount*/,
+ Dwarf_Error* /*error*/);
+
+/* Unimplemented. */
+int dwarf_dieline(Dwarf_Die /*die*/,
+ Dwarf_Line * /*returned_line*/,
+ Dwarf_Error * /*error*/);
+
+int dwarf_linebeginstatement(Dwarf_Line /*line*/,
+ Dwarf_Bool * /*returned_bool*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_lineendsequence(Dwarf_Line /*line*/,
+ Dwarf_Bool * /*returned_bool*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_lineno(Dwarf_Line /*line*/,
+ Dwarf_Unsigned * /*returned_lineno*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_line_srcfileno(Dwarf_Line /*line*/,
+ Dwarf_Unsigned * /*ret_fileno*/,
+ Dwarf_Error * /*error*/);
+
+/* Is the line address from DW_LNS_set_address? */
+int dwarf_line_is_addr_set(Dwarf_Line /*line*/,
+ Dwarf_Bool * /*is_addr_set*/,
+ Dwarf_Error * /*error*/);
+
+int dwarf_lineaddr(Dwarf_Line /*line*/,
+ Dwarf_Addr * /*returned_addr*/,
+ Dwarf_Error* /*error*/);
+
+/* dwarf_lineoff() is OBSOLETE as of December 2011. Do not use. */
+int dwarf_lineoff(Dwarf_Line /*line*/,
+ Dwarf_Signed * /*returned_lineoffset*/,
+ Dwarf_Error* /*error*/);
+/* dwarf_lineoff_b() correctly returns an unsigned column number
+ through the pointer returned_offset.
+ dwarf_lineoff_b() is new in December 2011. */
+int dwarf_lineoff_b(Dwarf_Line /*line*/,
+ Dwarf_Unsigned * /*returned_lineoffset*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_linesrc(Dwarf_Line /*line*/,
+ char ** /*returned_name*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_lineblock(Dwarf_Line /*line*/,
+ Dwarf_Bool * /*returned_bool*/,
+ Dwarf_Error* /*error*/);
+
+/* We gather these into one call as it's likely one
+ will want all or none of them. */
+int dwarf_prologue_end_etc(Dwarf_Line /* line */,
+ Dwarf_Bool * /*prologue_end*/,
+ Dwarf_Bool * /*eplogue_begin*/,
+ Dwarf_Unsigned * /* isa */,
+ Dwarf_Unsigned * /* discriminator */,
+ Dwarf_Error * /*error*/);
+
+/* Tertiary interface to line info */
+/* Unimplemented */
+int dwarf_pclines(Dwarf_Debug /*dbg*/,
+ Dwarf_Addr /*pc*/,
+ Dwarf_Line** /*linebuf*/,
+ Dwarf_Signed * /*linecount*/,
+ Dwarf_Signed /*slide*/,
+ Dwarf_Error* /*error*/);
+/* end line number operations */
+
+/* global name space operations (.debug_pubnames access) */
+int dwarf_get_globals(Dwarf_Debug /*dbg*/,
+ Dwarf_Global** /*globals*/,
+ Dwarf_Signed * /*number_of_globals*/,
+ Dwarf_Error* /*error*/);
+void dwarf_globals_dealloc(Dwarf_Debug /*dbg*/,
+ Dwarf_Global* /*globals*/,
+ Dwarf_Signed /*number_of_globals*/);
+
+int dwarf_globname(Dwarf_Global /*glob*/,
+ char ** /*returned_name*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_global_die_offset(Dwarf_Global /*global*/,
+ Dwarf_Off* /*return_offset*/,
+ Dwarf_Error * /*error*/);
+
+/* This returns the CU die global offset if one knows the
+ CU header global offset.
+ See also dwarf_CU_dieoffset_given_die(). */
+int dwarf_get_cu_die_offset_given_cu_header_offset(
+ Dwarf_Debug /*dbg*/,
+ Dwarf_Off /*in_cu_header_offset*/,
+ Dwarf_Off * /*out_cu_die_offset*/,
+ Dwarf_Error * /*err*/);
+
+/* The _b form is new October 2011. */
+int dwarf_get_cu_die_offset_given_cu_header_offset_b(
+ Dwarf_Debug /*dbg*/,
+ Dwarf_Off /*in_cu_header_offset*/,
+ Dwarf_Bool /*is_info. True means look in debug_Info,
+ false use debug_types.*/,
+ Dwarf_Off * /*out_cu_die_offset*/,
+ Dwarf_Error * /*err*/);
+
+#ifdef __sgi /* pragma is sgi MIPS only */
+#pragma optional dwarf_get_cu_die_offset_given_cu_header_offset
+#endif
+
+int dwarf_global_cu_offset(Dwarf_Global /*global*/,
+ Dwarf_Off* /*return_offset*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_global_name_offsets(Dwarf_Global /*global*/,
+ char ** /*returned_name*/,
+ Dwarf_Off* /*die_offset*/,
+ Dwarf_Off* /*cu_offset*/,
+ Dwarf_Error* /*error*/);
+
+/* Static function name operations. */
+int dwarf_get_funcs(Dwarf_Debug /*dbg*/,
+ Dwarf_Func** /*funcs*/,
+ Dwarf_Signed * /*number_of_funcs*/,
+ Dwarf_Error* /*error*/);
+void dwarf_funcs_dealloc(Dwarf_Debug /*dbg*/,
+ Dwarf_Func* /*funcs*/,
+ Dwarf_Signed /*number_of_funcs*/);
+
+int dwarf_funcname(Dwarf_Func /*func*/,
+ char ** /*returned_name*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_func_die_offset(Dwarf_Func /*func*/,
+ Dwarf_Off* /*return_offset*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_func_cu_offset(Dwarf_Func /*func*/,
+ Dwarf_Off* /*return_offset*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_func_name_offsets(Dwarf_Func /*func*/,
+ char ** /*returned_name*/,
+ Dwarf_Off* /*die_offset*/,
+ Dwarf_Off* /*cu_offset*/,
+ Dwarf_Error* /*error*/);
+
+/* User-defined type name operations, SGI IRIX .debug_typenames section.
+ Same content as DWARF3 .debug_pubtypes, but defined years before
+ .debug_pubtypes was defined. SGI IRIX only. */
+int dwarf_get_types(Dwarf_Debug /*dbg*/,
+ Dwarf_Type** /*types*/,
+ Dwarf_Signed * /*number_of_types*/,
+ Dwarf_Error* /*error*/);
+void dwarf_types_dealloc(Dwarf_Debug /*dbg*/,
+ Dwarf_Type* /*types*/,
+ Dwarf_Signed /*number_of_types*/);
+
+
+int dwarf_typename(Dwarf_Type /*type*/,
+ char ** /*returned_name*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_type_die_offset(Dwarf_Type /*type*/,
+ Dwarf_Off* /*return_offset*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_type_cu_offset(Dwarf_Type /*type*/,
+ Dwarf_Off* /*return_offset*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_type_name_offsets(Dwarf_Type /*type*/,
+ char ** /*returned_name*/,
+ Dwarf_Off* /*die_offset*/,
+ Dwarf_Off* /*cu_offset*/,
+ Dwarf_Error* /*error*/);
+
+/* User-defined type name operations, DWARF3 .debug_pubtypes section.
+*/
+int dwarf_get_pubtypes(Dwarf_Debug /*dbg*/,
+ Dwarf_Type** /*types*/,
+ Dwarf_Signed * /*number_of_types*/,
+ Dwarf_Error* /*error*/);
+void dwarf_pubtypes_dealloc(Dwarf_Debug /*dbg*/,
+ Dwarf_Type* /*pubtypes*/,
+ Dwarf_Signed /*number_of_pubtypes*/);
+
+
+int dwarf_pubtypename(Dwarf_Type /*type*/,
+ char ** /*returned_name*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_pubtype_die_offset(Dwarf_Type /*type*/,
+ Dwarf_Off* /*return_offset*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_pubtype_cu_offset(Dwarf_Type /*type*/,
+ Dwarf_Off* /*return_offset*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_pubtype_name_offsets(Dwarf_Type /*type*/,
+ char ** /*returned_name*/,
+ Dwarf_Off* /*die_offset*/,
+ Dwarf_Off* /*cu_offset*/,
+ Dwarf_Error* /*error*/);
+
+/* File-scope static variable name operations. */
+int dwarf_get_vars(Dwarf_Debug /*dbg*/,
+ Dwarf_Var** /*vars*/,
+ Dwarf_Signed * /*number_of_vars*/,
+ Dwarf_Error* /*error*/);
+void dwarf_vars_dealloc(Dwarf_Debug /*dbg*/,
+ Dwarf_Var* /*vars*/,
+ Dwarf_Signed /*number_of_vars*/);
+
+
+int dwarf_varname(Dwarf_Var /*var*/,
+ char ** /*returned_name*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_var_die_offset(Dwarf_Var /*var*/,
+ Dwarf_Off* /*return_offset*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_var_cu_offset(Dwarf_Var /*var*/,
+ Dwarf_Off* /*return_offset*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_var_name_offsets(Dwarf_Var /*var*/,
+ char ** /*returned_name*/,
+ Dwarf_Off* /*die_offset*/,
+ Dwarf_Off* /*cu_offset*/,
+ Dwarf_Error* /*error*/);
+
+/* weak name operations. */
+int dwarf_get_weaks(Dwarf_Debug /*dbg*/,
+ Dwarf_Weak** /*weaks*/,
+ Dwarf_Signed * /*number_of_weaks*/,
+ Dwarf_Error* /*error*/);
+void dwarf_weaks_dealloc(Dwarf_Debug /*dbg*/,
+ Dwarf_Weak* /*weaks*/,
+ Dwarf_Signed /*number_of_weaks*/);
+
+
+int dwarf_weakname(Dwarf_Weak /*weak*/,
+ char ** /*returned_name*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_weak_die_offset(Dwarf_Weak /*weak*/,
+ Dwarf_Off* /*return_offset*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_weak_cu_offset(Dwarf_Weak /*weak*/,
+ Dwarf_Off* /*return_offset*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_weak_name_offsets(Dwarf_Weak /*weak*/,
+ char ** /*returned_name*/,
+ Dwarf_Off* /*die_offset*/,
+ Dwarf_Off* /*cu_offset*/,
+ Dwarf_Error* /*error*/);
+
+/* location list section operation. (.debug_loc access) */
+int dwarf_get_loclist_entry(Dwarf_Debug /*dbg*/,
+ Dwarf_Unsigned /*offset*/,
+ Dwarf_Addr* /*hipc*/,
+ Dwarf_Addr* /*lopc*/,
+ Dwarf_Ptr* /*data*/,
+ Dwarf_Unsigned* /*entry_len*/,
+ Dwarf_Unsigned* /*next_entry*/,
+ Dwarf_Error* /*error*/);
+
+/* abbreviation section operations */
+int dwarf_get_abbrev(Dwarf_Debug /*dbg*/,
+ Dwarf_Unsigned /*offset*/,
+ Dwarf_Abbrev * /*returned_abbrev*/,
+ Dwarf_Unsigned* /*length*/,
+ Dwarf_Unsigned* /*attr_count*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_get_abbrev_tag(Dwarf_Abbrev /*abbrev*/,
+ Dwarf_Half* /*return_tag_number*/,
+ Dwarf_Error* /*error*/);
+int dwarf_get_abbrev_code(Dwarf_Abbrev /*abbrev*/,
+ Dwarf_Unsigned* /*return_code_number*/,
+ Dwarf_Error* /*error*/);
+/* See comments in dwarf_abbrev.c. Not an entirely safe function. */
+int dwarf_get_abbrev_count(Dwarf_Debug /*dbg*/);
+
+int dwarf_get_abbrev_children_flag(Dwarf_Abbrev /*abbrev*/,
+ Dwarf_Signed* /*return_flag*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_get_abbrev_entry(Dwarf_Abbrev /*abbrev*/,
+ Dwarf_Signed /*index*/,
+ Dwarf_Half * /*returned_attr_num*/,
+ Dwarf_Signed* /*form*/,
+ Dwarf_Off* /*offset*/,
+ Dwarf_Error* /*error*/);
+
+/* consumer string section operation */
+int dwarf_get_str(Dwarf_Debug /*dbg*/,
+ Dwarf_Off /*offset*/,
+ char** /*string*/,
+ Dwarf_Signed * /*strlen_of_string*/,
+ Dwarf_Error* /*error*/);
+
+/* Consumer op on gnu .eh_frame info */
+int dwarf_get_fde_list_eh(
+ Dwarf_Debug /*dbg*/,
+ Dwarf_Cie** /*cie_data*/,
+ Dwarf_Signed* /*cie_element_count*/,
+ Dwarf_Fde** /*fde_data*/,
+ Dwarf_Signed* /*fde_element_count*/,
+ Dwarf_Error* /*error*/);
+
+
+/* consumer operations on frame info: .debug_frame */
+int dwarf_get_fde_list(Dwarf_Debug /*dbg*/,
+ Dwarf_Cie** /*cie_data*/,
+ Dwarf_Signed* /*cie_element_count*/,
+ Dwarf_Fde** /*fde_data*/,
+ Dwarf_Signed* /*fde_element_count*/,
+ Dwarf_Error* /*error*/);
+
+/* Release storage gotten by dwarf_get_fde_list_eh() or
+ dwarf_get_fde_list() */
+void dwarf_fde_cie_list_dealloc(Dwarf_Debug dbg,
+ Dwarf_Cie *cie_data,
+ Dwarf_Signed cie_element_count,
+ Dwarf_Fde *fde_data,
+ Dwarf_Signed fde_element_count);
+
+
+
+int dwarf_get_fde_range(Dwarf_Fde /*fde*/,
+ Dwarf_Addr* /*low_pc*/,
+ Dwarf_Unsigned* /*func_length*/,
+ Dwarf_Ptr* /*fde_bytes*/,
+ Dwarf_Unsigned* /*fde_byte_length*/,
+ Dwarf_Off* /*cie_offset*/,
+ Dwarf_Signed* /*cie_index*/,
+ Dwarf_Off* /*fde_offset*/,
+ Dwarf_Error* /*error*/);
+
+/* Useful for IRIX only: see dwarf_get_cie_augmentation_data()
+ dwarf_get_fde_augmentation_data() for GNU .eh_frame. */
+int dwarf_get_fde_exception_info(Dwarf_Fde /*fde*/,
+ Dwarf_Signed* /* offset_into_exception_tables */,
+ Dwarf_Error* /*error*/);
+
+
+int dwarf_get_cie_of_fde(Dwarf_Fde /*fde*/,
+ Dwarf_Cie * /*cie_returned*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_get_cie_info(Dwarf_Cie /*cie*/,
+ Dwarf_Unsigned * /*bytes_in_cie*/,
+ Dwarf_Small* /*version*/,
+ char ** /*augmenter*/,
+ Dwarf_Unsigned* /*code_alignment_factor*/,
+ Dwarf_Signed* /*data_alignment_factor*/,
+ Dwarf_Half* /*return_address_register_rule*/,
+ Dwarf_Ptr* /*initial_instructions*/,
+ Dwarf_Unsigned* /*initial_instructions_length*/,
+ Dwarf_Error* /*error*/);
+
+/* dwarf_get_cie_index new September 2009. */
+int dwarf_get_cie_index(
+ Dwarf_Cie /*cie*/,
+ Dwarf_Signed* /*index*/,
+ Dwarf_Error* /*error*/ );
+
+
+int dwarf_get_fde_instr_bytes(Dwarf_Fde /*fde*/,
+ Dwarf_Ptr * /*outinstrs*/, Dwarf_Unsigned * /*outlen*/,
+ Dwarf_Error * /*error*/);
+
+int dwarf_get_fde_info_for_all_regs(Dwarf_Fde /*fde*/,
+ Dwarf_Addr /*pc_requested*/,
+ Dwarf_Regtable* /*reg_table*/,
+ Dwarf_Addr* /*row_pc*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_get_fde_info_for_all_regs3(Dwarf_Fde /*fde*/,
+ Dwarf_Addr /*pc_requested*/,
+ Dwarf_Regtable3* /*reg_table*/,
+ Dwarf_Addr* /*row_pc*/,
+ Dwarf_Error* /*error*/);
+
+/* In this older interface DW_FRAME_CFA_COL is a meaningful
+ column (which does not work well with DWARF3 or
+ non-MIPS architectures). */
+int dwarf_get_fde_info_for_reg(Dwarf_Fde /*fde*/,
+ Dwarf_Half /*table_column*/,
+ Dwarf_Addr /*pc_requested*/,
+ Dwarf_Signed* /*offset_relevant*/,
+ Dwarf_Signed* /*register*/,
+ Dwarf_Signed* /*offset*/,
+ Dwarf_Addr* /*row_pc*/,
+ Dwarf_Error* /*error*/);
+
+/* See discussion of dw_value_type, libdwarf.h.
+ Use of DW_FRAME_CFA_COL is not meaningful in this interface.
+ See dwarf_get_fde_info_for_cfa_reg3().
+*/
+/* dwarf_get_fde_info_for_reg3 is useful on a single column, but
+ it is inefficient to iterate across all table_columns using this
+ function. Instead call dwarf_get_fde_info_for_all_regs3() and index
+ into the table it fills in. */
+int dwarf_get_fde_info_for_reg3(Dwarf_Fde /*fde*/,
+ Dwarf_Half /*table_column*/,
+ Dwarf_Addr /*pc_requested*/,
+ Dwarf_Small * /*value_type*/,
+ Dwarf_Signed * /*offset_relevant*/,
+ Dwarf_Signed* /*register*/,
+ Dwarf_Signed* /*offset_or_block_len*/,
+ Dwarf_Ptr * /*block_ptr */,
+ Dwarf_Addr* /*row_pc_out*/,
+ Dwarf_Error* /*error*/);
+
+/* Use this to get the cfa. */
+int dwarf_get_fde_info_for_cfa_reg3(Dwarf_Fde /*fde*/,
+ Dwarf_Addr /*pc_requested*/,
+ Dwarf_Small * /*value_type*/,
+ Dwarf_Signed * /*offset_relevant*/,
+ Dwarf_Signed* /*register*/,
+ Dwarf_Signed* /*offset_or_block_len*/,
+ Dwarf_Ptr * /*block_ptr */,
+ Dwarf_Addr* /*row_pc_out*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_get_fde_for_die(Dwarf_Debug /*dbg*/,
+ Dwarf_Die /*subr_die */,
+ Dwarf_Fde * /*returned_fde*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_get_fde_n(Dwarf_Fde* /*fde_data*/,
+ Dwarf_Unsigned /*fde_index*/,
+ Dwarf_Fde * /*returned_fde*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_get_fde_at_pc(Dwarf_Fde* /*fde_data*/,
+ Dwarf_Addr /*pc_of_interest*/,
+ Dwarf_Fde * /*returned_fde*/,
+ Dwarf_Addr* /*lopc*/,
+ Dwarf_Addr* /*hipc*/,
+ Dwarf_Error* /*error*/);
+
+/* GNU .eh_frame augmentation information, raw form, see
+ Linux Standard Base Core Specification version 3.0 . */
+int dwarf_get_cie_augmentation_data(Dwarf_Cie /* cie*/,
+ Dwarf_Small ** /* augdata */,
+ Dwarf_Unsigned * /* augdata_len */,
+ Dwarf_Error* /*error*/);
+/* GNU .eh_frame augmentation information, raw form, see
+ Linux Standard Base Core Specification version 3.0 . */
+int dwarf_get_fde_augmentation_data(Dwarf_Fde /* fde*/,
+ Dwarf_Small ** /* augdata */,
+ Dwarf_Unsigned * /* augdata_len */,
+ Dwarf_Error* /*error*/);
+
+int dwarf_expand_frame_instructions(Dwarf_Cie /*cie*/,
+ Dwarf_Ptr /*instruction*/,
+ Dwarf_Unsigned /*i_length*/,
+ Dwarf_Frame_Op** /*returned_op_list*/,
+ Dwarf_Signed* /*op_count*/,
+ Dwarf_Error* /*error*/);
+
+/* Operations on .debug_aranges. */
+int dwarf_get_aranges(Dwarf_Debug /*dbg*/,
+ Dwarf_Arange** /*aranges*/,
+ Dwarf_Signed * /*arange_count*/,
+ Dwarf_Error* /*error*/);
+
+
+
+int dwarf_get_arange(
+ Dwarf_Arange* /*aranges*/,
+ Dwarf_Unsigned /*arange_count*/,
+ Dwarf_Addr /*address*/,
+ Dwarf_Arange * /*returned_arange*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_get_cu_die_offset(
+ Dwarf_Arange /*arange*/,
+ Dwarf_Off* /*return_offset*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_get_arange_cu_header_offset(
+ Dwarf_Arange /*arange*/,
+ Dwarf_Off* /*return_cu_header_offset*/,
+ Dwarf_Error* /*error*/);
+#ifdef __sgi /* pragma is sgi MIPS only */
+#pragma optional dwarf_get_arange_cu_header_offset
+#endif
+
+/* DWARF2,3 interface. No longer really adequate (it was never
+ right for segmented address spaces, please switch
+ to using dwarf_get_arange_info_b instead.
+ There is no effective difference between these
+ functions if the address space
+ of the target is not segmented. */
+int dwarf_get_arange_info(
+ Dwarf_Arange /*arange*/,
+ Dwarf_Addr* /*start*/,
+ Dwarf_Unsigned* /*length*/,
+ Dwarf_Off* /*cu_die_offset*/,
+ Dwarf_Error* /*error*/ );
+
+/* New for DWARF4, entries may have segment information.
+ *segment is only meaningful if *segment_entry_size is non-zero. */
+int dwarf_get_arange_info_b(
+ Dwarf_Arange /*arange*/,
+ Dwarf_Unsigned* /*segment*/,
+ Dwarf_Unsigned* /*segment_entry_size*/,
+ Dwarf_Addr * /*start*/,
+ Dwarf_Unsigned* /*length*/,
+ Dwarf_Off * /*cu_die_offset*/,
+ Dwarf_Error * /*error*/ );
+
+
+/* consumer .debug_macinfo information interface.
+*/
+struct Dwarf_Macro_Details_s {
+ Dwarf_Off dmd_offset; /* offset, in the section,
+ of this macro info */
+ Dwarf_Small dmd_type; /* the type, DW_MACINFO_define etc*/
+ Dwarf_Signed dmd_lineno; /* the source line number where
+ applicable and vend_def number if
+ vendor_extension op */
+
+ Dwarf_Signed dmd_fileindex;/* the source file index:
+ applies to define undef start_file */
+ char * dmd_macro; /* macro name (with value for defineop)
+ string from vendor ext */
+};
+
+/* dwarf_print_lines is for use by dwarfdump: it prints
+ line info to stdout.
+ The _dwarf name is obsolete. Use dwarf_ instead.
+ Added extra argnument 2/2009 for better checking.
+*/
+int _dwarf_print_lines(Dwarf_Die /*cu_die*/,Dwarf_Error * /*error*/);
+int dwarf_print_lines(Dwarf_Die /*cu_die*/,Dwarf_Error * /*error*/,
+ int * /*error_count_out */);
+
+/* dwarf_check_lineheader lets dwarfdump get detailed messages
+ about some compiler errors we detect.
+ We return the count of detected errors through the
+ pointer.
+*/
+void dwarf_check_lineheader(Dwarf_Die /*cu_die*/,int *errcount_out);
+
+/* dwarf_ld_sort_lines helps SGI IRIX ld
+ rearrange lines in .debug_line in a .o created with a text
+ section per function.
+ -OPT:procedure_reorder=ON
+ where ld-cord (cord(1)ing by ld,
+ not by cord(1)) may have changed the function order.
+ The _dwarf name is obsolete. Use dwarf_ instead.
+*/
+int _dwarf_ld_sort_lines(
+ void * /*orig_buffer*/,
+ unsigned long /* buffer_len*/,
+ int /*is_64_bit*/,
+ int * /*any_change*/,
+ int * /*err_code*/);
+int dwarf_ld_sort_lines(
+ void * /*orig_buffer*/,
+ unsigned long /*buffer_len*/,
+ int /*is_64_bit*/,
+ int * /*any_change*/,
+ int * /*err_code*/);
+
+/* Used by dwarfdump -v to print fde offsets from debugging
+ info.
+ The _dwarf name is obsolete. Use dwarf_ instead.
+*/
+int _dwarf_fde_section_offset(Dwarf_Debug dbg,
+ Dwarf_Fde /*in_fde*/,
+ Dwarf_Off * /*fde_off*/,
+ Dwarf_Off * /*cie_off*/,
+ Dwarf_Error * /*err*/);
+int dwarf_fde_section_offset(Dwarf_Debug dbg,
+ Dwarf_Fde /*in_fde*/,
+ Dwarf_Off * /*fde_off*/,
+ Dwarf_Off * /*cie_off*/,
+ Dwarf_Error * /*err*/);
+
+/* Used by dwarfdump -v to print cie offsets from debugging
+ info.
+ The _dwarf name is obsolete. Use dwarf_ instead.
+*/
+int dwarf_cie_section_offset(Dwarf_Debug /*dbg*/,
+ Dwarf_Cie /*in_cie*/,
+ Dwarf_Off * /*cie_off */,
+ Dwarf_Error * /*err*/);
+int _dwarf_cie_section_offset(Dwarf_Debug /*dbg*/,
+ Dwarf_Cie /*in_cie*/,
+ Dwarf_Off * /*cie_off*/,
+ Dwarf_Error * /*err*/);
+
+typedef struct Dwarf_Macro_Details_s Dwarf_Macro_Details;
+
+int dwarf_get_macro(Dwarf_Debug /*dbg*/,
+ char * /*requested_macro_name*/,
+ Dwarf_Addr /*pc_of_request*/,
+ char ** /*returned_macro_value*/,
+ Dwarf_Error * /*error*/);
+
+int dwarf_get_all_defined_macros(Dwarf_Debug /*dbg*/,
+ Dwarf_Addr /*pc_of_request*/,
+ Dwarf_Signed * /*returned_count*/,
+ char *** /*returned_pointers_to_macros*/,
+ Dwarf_Error * /*error*/);
+
+char *dwarf_find_macro_value_start(char * /*macro_string*/);
+
+int dwarf_get_macro_details(Dwarf_Debug /*dbg*/,
+ Dwarf_Off /*macro_offset*/,
+ Dwarf_Unsigned /*maximum_count*/,
+ Dwarf_Signed * /*entry_count*/,
+ Dwarf_Macro_Details ** /*details*/,
+ Dwarf_Error * /*err*/);
+
+
+int dwarf_get_address_size(Dwarf_Debug /*dbg*/,
+ Dwarf_Half * /*addr_size*/,
+ Dwarf_Error * /*error*/);
+int dwarf_get_die_address_size(Dwarf_Die /*die*/,
+ Dwarf_Half * /*addr_size*/,
+ Dwarf_Error * /*error*/);
+
+/* The dwarf specification separates FORMs into
+different classes. To do the seperation properly
+requires 4 pieces of data as of DWARF4 (thus the
+function arguments listed here).
+The DWARF4 specification class definition suffices to
+describe all DWARF versions.
+See section 7.5.4, Attribute Encodings.
+A return of DW_FORM_CLASS_UNKNOWN means we could not properly figure
+out what form-class it is.
+
+ DW_FORM_CLASS_FRAMEPTR is MIPS/IRIX only, and refers
+ to the DW_AT_MIPS_fde attribute (a reference to the
+ .debug_frame section).
+*/
+enum Dwarf_Form_Class {
+ DW_FORM_CLASS_UNKNOWN, DW_FORM_CLASS_ADDRESS,
+ DW_FORM_CLASS_BLOCK, DW_FORM_CLASS_CONSTANT,
+ DW_FORM_CLASS_EXPRLOC, DW_FORM_CLASS_FLAG,
+ DW_FORM_CLASS_LINEPTR, DW_FORM_CLASS_LOCLISTPTR,
+ DW_FORM_CLASS_MACPTR, DW_FORM_CLASS_RANGELISTPTR,
+ DW_FORM_CLASS_REFERENCE, DW_FORM_CLASS_STRING,
+ DW_FORM_CLASS_FRAMEPTR
+};
+
+enum Dwarf_Form_Class dwarf_get_form_class(
+ Dwarf_Half /* dwversion */,
+ Dwarf_Half /* attrnum */,
+ Dwarf_Half /*offset_size */,
+ Dwarf_Half /*form*/);
+
+/* Utility operations */
+Dwarf_Unsigned dwarf_errno(Dwarf_Error /*error*/);
+
+char* dwarf_errmsg(Dwarf_Error /*error*/);
+
+/* stringcheck zero is default and means do all
+ string length validity checks.
+ Call with parameter value 1 to turn off many such checks (and
+ increase performance).
+ Call with zero for safest running.
+ Actual value saved and returned is only 8 bits! Upper bits
+ ignored by libdwarf (and zero on return).
+ Returns previous value. */
+int dwarf_set_stringcheck(int /*stringcheck*/);
+
+/* 'apply' defaults to 1 and means do all
+ 'rela' relocations on reading in a dwarf object section with
+ such relocations.
+ Call with parameter value 0 to turn off application of
+ such relocations.
+ Since the static linker leaves 'bogus' data in object sections
+ with a 'rela' relocation section such data cannot be read
+ sensibly without processing the relocations. Such relocations
+ do not exist in executables and shared objects (.so), the
+ relocations only exist in plain .o relocatable object files.
+ Actual value saved and returned is only 8 bits! Upper bits
+ ignored by libdwarf (and zero on return).
+ Returns previous value. */
+int dwarf_set_reloc_application(int /*apply*/);
+
+
+/* Unimplemented */
+Dwarf_Handler dwarf_seterrhand(Dwarf_Debug /*dbg*/, Dwarf_Handler /*errhand*/);
+
+/* Unimplemented */
+Dwarf_Ptr dwarf_seterrarg(Dwarf_Debug /*dbg*/, Dwarf_Ptr /*errarg*/);
+
+void dwarf_dealloc(Dwarf_Debug /*dbg*/, void* /*space*/,
+ Dwarf_Unsigned /*type*/);
+
+
+/* DWARF Producer Interface */
+
+/* New form June, 2011. Adds user_data argument. */
+typedef int (*Dwarf_Callback_Func_c)(
+ char* /*name*/,
+ int /*size*/,
+ Dwarf_Unsigned /*type*/,
+ Dwarf_Unsigned /*flags*/,
+ Dwarf_Unsigned /*link*/,
+ Dwarf_Unsigned /*info*/,
+ Dwarf_Unsigned* /*sect_name_index*/,
+ void * /*user_data*/,
+ int* /*error*/);
+
+/* New form June, 2011. Adds user_data */
+Dwarf_P_Debug dwarf_producer_init_c(
+ Dwarf_Unsigned /*flags*/,
+ Dwarf_Callback_Func_c /*func*/,
+ Dwarf_Handler /*errhand*/,
+ Dwarf_Ptr /*errarg*/,
+ void * /*user_data*/,
+ Dwarf_Error * /*error*/);
+
+typedef int (*Dwarf_Callback_Func_b)(
+ char* /*name*/,
+ int /*size*/,
+ Dwarf_Unsigned /*type*/,
+ Dwarf_Unsigned /*flags*/,
+ Dwarf_Unsigned /*link*/,
+ Dwarf_Unsigned /*info*/,
+ Dwarf_Unsigned* /*sect_name_index*/,
+ int* /*error*/);
+
+/* Intermediate form. Made obsolescent by dwarf_producer_init_c,
+ but supported. */
+Dwarf_P_Debug dwarf_producer_init_b(
+ Dwarf_Unsigned /*flags*/,
+ Dwarf_Callback_Func_b /*func*/,
+ Dwarf_Handler /*errhand*/,
+ Dwarf_Ptr /*errarg*/,
+ Dwarf_Error * /*error*/);
+
+/* Original, oldest form. From 1991. */
+typedef int (*Dwarf_Callback_Func)(
+ char* /*name*/,
+ int /*size*/,
+ Dwarf_Unsigned /*type*/,
+ Dwarf_Unsigned /*flags*/,
+ Dwarf_Unsigned /*link*/,
+ Dwarf_Unsigned /*info*/,
+ int* /*sect name index*/,
+ int* /*error*/);
+
+/* Original, oldest form. From 1991. */
+Dwarf_P_Debug dwarf_producer_init(
+ Dwarf_Unsigned /*creation_flags*/,
+ Dwarf_Callback_Func /*func*/,
+ Dwarf_Handler /*errhand*/,
+ Dwarf_Ptr /*errarg*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_Signed dwarf_transform_to_disk_form(Dwarf_P_Debug /*dbg*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_Ptr dwarf_get_section_bytes(Dwarf_P_Debug /*dbg*/,
+ Dwarf_Signed /*dwarf_section*/,
+ Dwarf_Signed* /*elf_section_index*/,
+ Dwarf_Unsigned* /*length*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_get_relocation_info_count(
+ Dwarf_P_Debug /*dbg*/,
+ Dwarf_Unsigned * /*count_of_relocation_sections*/,
+ int * /*drd_buffer_version*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_get_relocation_info(
+ Dwarf_P_Debug /*dbg*/,
+ Dwarf_Signed * /*elf_section_index*/,
+ Dwarf_Signed * /*elf_section_index_link*/,
+ Dwarf_Unsigned * /*relocation_buffer_count*/,
+ Dwarf_Relocation_Data * /*reldata_buffer*/,
+ Dwarf_Error* /*error*/);
+
+/* v1: no drd_length field, enum explicit */
+/* v2: has the drd_length field, enum value in uchar member */
+#define DWARF_DRD_BUFFER_VERSION 2
+
+/* Markers are not written to DWARF2/3/4, they are user
+ defined and may be used for any purpose.
+*/
+Dwarf_Signed dwarf_get_die_markers(
+ Dwarf_P_Debug /*dbg*/,
+ Dwarf_P_Marker * /*marker_list*/,
+ Dwarf_Unsigned * /*marker_count*/,
+ Dwarf_Error * /*error*/);
+
+int dwarf_get_string_attributes_count(Dwarf_P_Debug,
+ Dwarf_Unsigned *,
+ int *,
+ Dwarf_Error *);
+
+int dwarf_get_string_attributes_info(Dwarf_P_Debug,
+ Dwarf_Signed *,
+ Dwarf_Unsigned *,
+ Dwarf_P_String_Attr *,
+ Dwarf_Error *);
+
+void dwarf_reset_section_bytes(Dwarf_P_Debug /*dbg*/);
+
+Dwarf_Unsigned dwarf_producer_finish(Dwarf_P_Debug /*dbg*/,
+ Dwarf_Error* /*error*/);
+
+/* Producer attribute addition functions. */
+Dwarf_P_Attribute dwarf_add_AT_targ_address(Dwarf_P_Debug /*dbg*/,
+ Dwarf_P_Die /*ownerdie*/,
+ Dwarf_Half /*attr*/,
+ Dwarf_Unsigned /*pc_value*/,
+ Dwarf_Signed /*sym_index*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_P_Attribute dwarf_add_AT_block(Dwarf_P_Debug /*dbg*/,
+ Dwarf_P_Die /*ownerdie*/,
+ Dwarf_Half /*attr*/,
+ Dwarf_Small* /*block_data*/,
+ Dwarf_Unsigned /*block_len*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_P_Attribute dwarf_add_AT_targ_address_b(Dwarf_P_Debug /*dbg*/,
+ Dwarf_P_Die /*ownerdie*/,
+ Dwarf_Half /*attr*/,
+ Dwarf_Unsigned /*pc_value*/,
+ Dwarf_Unsigned /*sym_index*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_P_Attribute dwarf_add_AT_ref_address(Dwarf_P_Debug /*dbg*/,
+ Dwarf_P_Die /*ownerdie*/,
+ Dwarf_Half /*attr*/,
+ Dwarf_Unsigned /*pc_value*/,
+ Dwarf_Unsigned /*sym_index*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_P_Attribute dwarf_add_AT_unsigned_const(Dwarf_P_Debug /*dbg*/,
+ Dwarf_P_Die /*ownerdie*/,
+ Dwarf_Half /*attr*/,
+ Dwarf_Unsigned /*value*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_P_Attribute dwarf_add_AT_signed_const(Dwarf_P_Debug /*dbg*/,
+ Dwarf_P_Die /*ownerdie*/,
+ Dwarf_Half /*attr*/,
+ Dwarf_Signed /*value*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_P_Attribute dwarf_add_AT_reference(Dwarf_P_Debug /*dbg*/,
+ Dwarf_P_Die /*ownerdie*/,
+ Dwarf_Half /*attr*/,
+ Dwarf_P_Die /*otherdie*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_P_Attribute dwarf_add_AT_dataref(
+ Dwarf_P_Debug /* dbg*/,
+ Dwarf_P_Die /*ownerdie*/,
+ Dwarf_Half /*attr*/,
+ Dwarf_Unsigned /*pcvalue*/,
+ Dwarf_Unsigned /*sym_index*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_P_Attribute dwarf_add_AT_const_value_string(Dwarf_P_Die /*ownerdie*/,
+ char* /*string_value*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_P_Attribute dwarf_add_AT_location_expr(Dwarf_P_Debug /*dbg*/,
+ Dwarf_P_Die /*ownerdie*/,
+ Dwarf_Half /*attr*/,
+ Dwarf_P_Expr /*loc_expr*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_P_Attribute dwarf_add_AT_string(Dwarf_P_Debug /*dbg*/,
+ Dwarf_P_Die /*ownerdie*/,
+ Dwarf_Half /*attr*/,
+ char* /*string*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_P_Attribute dwarf_add_AT_flag(Dwarf_P_Debug /*dbg*/,
+ Dwarf_P_Die /*ownerdie*/,
+ Dwarf_Half /*attr*/,
+ Dwarf_Small /*flag*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_P_Attribute dwarf_add_AT_producer(Dwarf_P_Die /*ownerdie*/,
+ char* /*producer_string*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_P_Attribute dwarf_add_AT_const_value_signedint(Dwarf_P_Die /*ownerdie*/,
+ Dwarf_Signed /*signed_value*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_P_Attribute dwarf_add_AT_const_value_unsignedint(
+ Dwarf_P_Die /*ownerdie*/,
+ Dwarf_Unsigned /*unsigned_value*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_P_Attribute dwarf_add_AT_comp_dir(Dwarf_P_Die /*ownerdie*/,
+ char* /*current_working_directory*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_P_Attribute dwarf_add_AT_name(Dwarf_P_Die /*die*/,
+ char* /*name*/,
+ Dwarf_Error* /*error*/);
+
+/* Producer line creation functions (.debug_line) */
+Dwarf_Unsigned dwarf_add_directory_decl(Dwarf_P_Debug /*dbg*/,
+ char* /*name*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_Unsigned dwarf_add_file_decl(Dwarf_P_Debug /*dbg*/,
+ char* /*name*/,
+ Dwarf_Unsigned /*dir_index*/,
+ Dwarf_Unsigned /*time_last_modified*/,
+ Dwarf_Unsigned /*length*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_Unsigned dwarf_add_line_entry_b(Dwarf_P_Debug /*dbg*/,
+ Dwarf_Unsigned /*file_index*/,
+ Dwarf_Addr /*code_address*/,
+ Dwarf_Unsigned /*lineno*/,
+ Dwarf_Signed /*column_number*/,
+ Dwarf_Bool /*is_source_stmt_begin*/,
+ Dwarf_Bool /*is_basic_block_begin*/,
+ Dwarf_Bool /*is_epilogue_begin*/,
+ Dwarf_Bool /*is_prologue_end*/,
+ Dwarf_Unsigned /*isa*/,
+ Dwarf_Unsigned /*discriminator*/,
+ Dwarf_Error* /*error*/);
+Dwarf_Unsigned dwarf_add_line_entry(Dwarf_P_Debug /*dbg*/,
+ Dwarf_Unsigned /*file_index*/,
+ Dwarf_Addr /*code_address*/,
+ Dwarf_Unsigned /*lineno*/,
+ Dwarf_Signed /*column_number*/,
+ Dwarf_Bool /*is_source_stmt_begin*/,
+ Dwarf_Bool /*is_basic_block_begin*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_Unsigned dwarf_lne_set_address(Dwarf_P_Debug /*dbg*/,
+ Dwarf_Unsigned /*offset*/,
+ Dwarf_Unsigned /*symbol_index*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_Unsigned dwarf_lne_end_sequence(Dwarf_P_Debug /*dbg*/,
+ Dwarf_Addr /*end_address*/,
+ Dwarf_Error* /*error*/);
+
+/* Producer .debug_frame functions */
+Dwarf_Unsigned dwarf_add_frame_cie(Dwarf_P_Debug /*dbg*/,
+ char* /*augmenter*/,
+ Dwarf_Small /*code_alignment_factor*/,
+ Dwarf_Small /*data_alignment_factor*/,
+ Dwarf_Small /*return_address_reg*/,
+ Dwarf_Ptr /*initialization_bytes*/,
+ Dwarf_Unsigned /*init_byte_len*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_Unsigned dwarf_add_frame_fde(
+ Dwarf_P_Debug /*dbg*/,
+ Dwarf_P_Fde /*fde*/,
+ Dwarf_P_Die /*corresponding subprogram die*/,
+ Dwarf_Unsigned /*cie_to_use*/,
+ Dwarf_Unsigned /*virt_addr_of_described_code*/,
+ Dwarf_Unsigned /*length_of_code*/,
+ Dwarf_Unsigned /*symbol_index*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_Unsigned dwarf_add_frame_fde_b(
+ Dwarf_P_Debug /*dbg*/,
+ Dwarf_P_Fde /*fde*/,
+ Dwarf_P_Die /*die*/,
+ Dwarf_Unsigned /*cie*/,
+ Dwarf_Addr /*virt_addr*/,
+ Dwarf_Unsigned /*code_len*/,
+ Dwarf_Unsigned /*sym_idx*/,
+ Dwarf_Unsigned /*sym_idx_of_end*/,
+ Dwarf_Addr /*offset_from_end_sym*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_Unsigned dwarf_add_frame_info_b(
+ Dwarf_P_Debug dbg /*dbg*/,
+ Dwarf_P_Fde /*fde*/,
+ Dwarf_P_Die /*die*/,
+ Dwarf_Unsigned /*cie*/,
+ Dwarf_Addr /*virt_addr*/,
+ Dwarf_Unsigned /*code_len*/,
+ Dwarf_Unsigned /*symidx*/,
+ Dwarf_Unsigned /*end_symbol */,
+ Dwarf_Addr /*offset_from_end_symbol */,
+ Dwarf_Signed /*offset_into_exception_tables*/,
+ Dwarf_Unsigned /*exception_table_symbol*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_Unsigned dwarf_add_frame_info(
+ Dwarf_P_Debug dbg /*dbg*/,
+ Dwarf_P_Fde /*fde*/,
+ Dwarf_P_Die /*die*/,
+ Dwarf_Unsigned /*cie*/,
+ Dwarf_Addr /*virt_addr*/,
+ Dwarf_Unsigned /*code_len*/,
+ Dwarf_Unsigned /*symidx*/,
+ Dwarf_Signed /*offset_into_exception_tables*/,
+ Dwarf_Unsigned /*exception_table_symbol*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_P_Fde dwarf_add_fde_inst(
+ Dwarf_P_Fde /*fde*/,
+ Dwarf_Small /*op*/,
+ Dwarf_Unsigned /*val1*/,
+ Dwarf_Unsigned /*val2*/,
+ Dwarf_Error* /*error*/);
+
+/* New September 17, 2009 */
+int dwarf_insert_fde_inst_bytes(
+ Dwarf_P_Debug /*dbg*/,
+ Dwarf_P_Fde /*fde*/,
+ Dwarf_Unsigned /*len*/,
+ Dwarf_Ptr /*ibytes*/,
+ Dwarf_Error* /*error*/);
+
+
+Dwarf_P_Fde dwarf_new_fde(Dwarf_P_Debug /*dbg*/, Dwarf_Error* /*error*/);
+
+Dwarf_P_Fde dwarf_fde_cfa_offset(
+ Dwarf_P_Fde /*fde*/,
+ Dwarf_Unsigned /*register_number*/,
+ Dwarf_Signed /*offset*/,
+ Dwarf_Error* /*error*/);
+
+/* die creation & addition routines */
+Dwarf_P_Die dwarf_new_die(
+ Dwarf_P_Debug /*dbg*/,
+ Dwarf_Tag /*tag*/,
+ Dwarf_P_Die /*parent*/,
+ Dwarf_P_Die /*child*/,
+ Dwarf_P_Die /*left */,
+ Dwarf_P_Die /*right*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_Unsigned dwarf_add_die_to_debug(
+ Dwarf_P_Debug /*dbg*/,
+ Dwarf_P_Die /*die*/,
+ Dwarf_Error* /*error*/);
+
+/* Markers are not written to DWARF2/3/4, they are user
+ defined and may be used for any purpose.
+*/
+Dwarf_Unsigned dwarf_add_die_marker(
+ Dwarf_P_Debug /*dbg*/,
+ Dwarf_P_Die /*die*/,
+ Dwarf_Unsigned /*marker*/,
+ Dwarf_Error * /*error*/);
+
+Dwarf_Unsigned dwarf_get_die_marker(
+ Dwarf_P_Debug /*dbg*/,
+ Dwarf_P_Die /*die*/,
+ Dwarf_Unsigned * /*marker*/,
+ Dwarf_Error * /*error*/);
+
+Dwarf_P_Die dwarf_die_link(
+ Dwarf_P_Die /*die*/,
+ Dwarf_P_Die /*parent*/,
+ Dwarf_P_Die /*child*/,
+ Dwarf_P_Die /*left*/,
+ Dwarf_P_Die /*right*/,
+ Dwarf_Error* /*error*/);
+
+void dwarf_dealloc_compressed_block(
+ Dwarf_P_Debug,
+ void *
+);
+
+/* Call this passing in return value from dwarf_uncompress_integer_block()
+ to free the space the decompression allocated. */
+void dwarf_dealloc_uncompressed_block(
+ Dwarf_Debug,
+ void *
+);
+
+void * dwarf_compress_integer_block(
+ Dwarf_P_Debug, /* dbg */
+ Dwarf_Bool, /* signed==true (or unsigned) */
+ Dwarf_Small, /* size of integer units: 8, 16, 32, 64 */
+ void*, /* data */
+ Dwarf_Unsigned, /* number of elements */
+ Dwarf_Unsigned*, /* number of bytes in output block */
+ Dwarf_Error* /* error */
+);
+
+/* Decode an array of signed leb integers (so of course the
+ array is not composed of fixed length values, but is instead
+ a sequence of sleb values).
+ Returns a DW_DLV_BADADDR on error.
+ Otherwise returns a pointer to an array of 32bit integers.
+ The signed argument must be non-zero (the decode
+ assumes sleb integers in the input data) at this time.
+ Size of integer units must be 32 (32 bits each) at this time.
+ Number of bytes in block is a byte count (not array count).
+ Returns number of units in output block (ie, number of elements
+ of the array that the return value points to) thru the argument. */
+void * dwarf_uncompress_integer_block(
+ Dwarf_Debug, /* dbg */
+ Dwarf_Bool, /* signed==true (or unsigned) */
+ Dwarf_Small, /* size of integer units: 8, 16, 32, 64 */
+ void*, /* input data */
+ Dwarf_Unsigned, /* number of bytes in input */
+ Dwarf_Unsigned*, /* number of units in output block */
+ Dwarf_Error* /* error */
+);
+
+/* Operations to create location expressions. */
+Dwarf_P_Expr dwarf_new_expr(Dwarf_P_Debug /*dbg*/, Dwarf_Error* /*error*/);
+
+void dwarf_expr_reset(
+ Dwarf_P_Expr /*expr*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_Unsigned dwarf_add_expr_gen(
+ Dwarf_P_Expr /*expr*/,
+ Dwarf_Small /*opcode*/,
+ Dwarf_Unsigned /*val1*/,
+ Dwarf_Unsigned /*val2*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_Unsigned dwarf_add_expr_addr(
+ Dwarf_P_Expr /*expr*/,
+ Dwarf_Unsigned /*addr*/,
+ Dwarf_Signed /*sym_index*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_Unsigned dwarf_add_expr_addr_b(
+ Dwarf_P_Expr /*expr*/,
+ Dwarf_Unsigned /*addr*/,
+ Dwarf_Unsigned /*sym_index*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_Unsigned dwarf_expr_current_offset(
+ Dwarf_P_Expr /*expr*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_Addr dwarf_expr_into_block(
+ Dwarf_P_Expr /*expr*/,
+ Dwarf_Unsigned* /*length*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_Unsigned dwarf_add_arange(Dwarf_P_Debug /*dbg*/,
+ Dwarf_Addr /*begin_address*/,
+ Dwarf_Unsigned /*length*/,
+ Dwarf_Signed /*symbol_index*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_Unsigned dwarf_add_arange_b(
+ Dwarf_P_Debug /*dbg*/,
+ Dwarf_Addr /*begin_address*/,
+ Dwarf_Unsigned /*length*/,
+ Dwarf_Unsigned /*symbol_index*/,
+ Dwarf_Unsigned /*end_symbol_index*/,
+ Dwarf_Addr /*offset_from_end_symbol*/,
+ Dwarf_Error * /*error*/);
+
+Dwarf_Unsigned dwarf_add_pubname(
+ Dwarf_P_Debug /*dbg*/,
+ Dwarf_P_Die /*die*/,
+ char* /*pubname_name*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_Unsigned dwarf_add_funcname(
+ Dwarf_P_Debug /*dbg*/,
+ Dwarf_P_Die /*die*/,
+ char* /*func_name*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_Unsigned dwarf_add_typename(
+ Dwarf_P_Debug /*dbg*/,
+ Dwarf_P_Die /*die*/,
+ char* /*type_name*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_Unsigned dwarf_add_varname(
+ Dwarf_P_Debug /*dbg*/,
+ Dwarf_P_Die /*die*/,
+ char* /*var_name*/,
+ Dwarf_Error* /*error*/);
+
+Dwarf_Unsigned dwarf_add_weakname(
+ Dwarf_P_Debug /*dbg*/,
+ Dwarf_P_Die /*die*/,
+ char* /*weak_name*/,
+ Dwarf_Error* /*error*/);
+
+/* .debug_macinfo producer functions
+ Functions must be called in right order: the section is output
+ In the order these are presented.
+*/
+int dwarf_def_macro(Dwarf_P_Debug /*dbg*/,
+ Dwarf_Unsigned /*line*/,
+ char * /*macname, with (arglist), no space before (*/,
+ char * /*macvalue*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_undef_macro(Dwarf_P_Debug /*dbg*/,
+ Dwarf_Unsigned /*line*/,
+ char * /*macname, no arglist, of course*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_start_macro_file(Dwarf_P_Debug /*dbg*/,
+ Dwarf_Unsigned /*fileindex*/,
+ Dwarf_Unsigned /*linenumber*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_end_macro_file(Dwarf_P_Debug /*dbg*/,
+ Dwarf_Error* /*error*/);
+
+int dwarf_vendor_ext(Dwarf_P_Debug /*dbg*/,
+ Dwarf_Unsigned /*constant*/,
+ char * /*string*/,
+ Dwarf_Error* /*error*/);
+
+/* end macinfo producer functions */
+
+int dwarf_attr_offset(Dwarf_Die /*die*/,
+ Dwarf_Attribute /*attr of above die*/,
+ Dwarf_Off * /*returns offset thru this ptr */,
+ Dwarf_Error * /*error*/);
+
+/* This is a hack so clients can verify offsets.
+ Added April 2005 so that debugger can detect broken offsets
+ (which happened in an IRIX executable larger than 2GB
+ with MIPSpro 7.3.1.3 toolchain.).
+*/
+int
+dwarf_get_section_max_offsets(Dwarf_Debug /*dbg*/,
+ Dwarf_Unsigned * /*debug_info_size*/,
+ Dwarf_Unsigned * /*debug_abbrev_size*/,
+ Dwarf_Unsigned * /*debug_line_size*/,
+ Dwarf_Unsigned * /*debug_loc_size*/,
+ Dwarf_Unsigned * /*debug_aranges_size*/,
+ Dwarf_Unsigned * /*debug_macinfo_size*/,
+ Dwarf_Unsigned * /*debug_pubnames_size*/,
+ Dwarf_Unsigned * /*debug_str_size*/,
+ Dwarf_Unsigned * /*debug_frame_size*/,
+ Dwarf_Unsigned * /*debug_ranges_size*/,
+ Dwarf_Unsigned * /*debug_pubtypes_size*/);
+
+/* New October 2011., adds .debug_types section to the sizes
+ returned. */
+int
+dwarf_get_section_max_offsets_b(Dwarf_Debug /*dbg*/,
+
+ Dwarf_Unsigned * /*debug_info_size*/,
+ Dwarf_Unsigned * /*debug_abbrev_size*/,
+ Dwarf_Unsigned * /*debug_line_size*/,
+ Dwarf_Unsigned * /*debug_loc_size*/,
+ Dwarf_Unsigned * /*debug_aranges_size*/,
+ Dwarf_Unsigned * /*debug_macinfo_size*/,
+ Dwarf_Unsigned * /*debug_pubnames_size*/,
+ Dwarf_Unsigned * /*debug_str_size*/,
+ Dwarf_Unsigned * /*debug_frame_size*/,
+ Dwarf_Unsigned * /*debug_ranges_size*/,
+ Dwarf_Unsigned * /*debug_pubtypes_size*/,
+ Dwarf_Unsigned * /*debug_types_size*/);
+
+/* The 'set' calls here return the original (before any change
+ by these set routines) of the respective fields. */
+/* Multiple releases spelled 'initial' as 'inital' .
+ The 'inital' spelling should not be used. */
+Dwarf_Half dwarf_set_frame_rule_inital_value(Dwarf_Debug /*dbg*/,
+ Dwarf_Half /*value*/);
+/* Additional interface with correct 'initial' spelling. */
+/* It is likely you will want to call the following 6 functions
+ before accessing any frame information. All are useful
+ to tailor handling of pseudo-registers needed to turn
+ frame operation references into simpler forms and to
+ reflect ABI specific data. Of course altering libdwarf.h
+ and dwarf.h allow the same capabilities, but such header changes
+ do not let one change these values at runtime. */
+Dwarf_Half dwarf_set_frame_rule_initial_value(Dwarf_Debug /*dbg*/,
+ Dwarf_Half /*value*/);
+Dwarf_Half dwarf_set_frame_rule_table_size(Dwarf_Debug /*dbg*/,
+ Dwarf_Half /*value*/);
+Dwarf_Half dwarf_set_frame_cfa_value(Dwarf_Debug /*dbg*/,
+ Dwarf_Half /*value*/);
+Dwarf_Half dwarf_set_frame_same_value(Dwarf_Debug /*dbg*/,
+ Dwarf_Half /*value*/);
+Dwarf_Half dwarf_set_frame_undefined_value(Dwarf_Debug /*dbg*/,
+ Dwarf_Half /*value*/);
+/* dwarf_set_default_address_size only sets 'value' if value is
+ greater than zero. */
+Dwarf_Small dwarf_set_default_address_size(Dwarf_Debug /*dbg*/,
+ Dwarf_Small /* value */);
+
+/* As of April 27, 2009, this version with no diepointer is
+ obsolete though supported. Use dwarf_get_ranges_a() instead. */
+int dwarf_get_ranges(Dwarf_Debug /*dbg*/,
+ Dwarf_Off /*rangesoffset*/,
+ Dwarf_Ranges ** /*rangesbuf*/,
+ Dwarf_Signed * /*listlen*/,
+ Dwarf_Unsigned * /*bytecount*/,
+ Dwarf_Error * /*error*/);
+
+/* This adds the address_size argument. New April 27, 2009 */
+int dwarf_get_ranges_a(Dwarf_Debug /*dbg*/,
+ Dwarf_Off /*rangesoffset*/,
+ Dwarf_Die /* diepointer */,
+ Dwarf_Ranges ** /*rangesbuf*/,
+ Dwarf_Signed * /*listlen*/,
+ Dwarf_Unsigned * /*bytecount*/,
+ Dwarf_Error * /*error*/);
+
+void dwarf_ranges_dealloc(Dwarf_Debug /*dbg*/,
+ Dwarf_Ranges * /*rangesbuf*/,
+ Dwarf_Signed /*rangecount*/);
+
+/* The harmless error list is a circular buffer of
+ errors we note but which do not stop us from processing
+ the object. Created so dwarfdump or other tools
+ can report such inconsequential errors without causing
+ anything to stop early. */
+#define DW_HARMLESS_ERROR_CIRCULAR_LIST_DEFAULT_SIZE 4
+#define DW_HARMLESS_ERROR_MSG_STRING_SIZE 200
+/* User code supplies size of array of pointers errmsg_ptrs_array
+ in count and the array of pointers (the pointers themselves
+ need not be initialized).
+ The pointers returned in the array of pointers
+ are invalidated by ANY call to libdwarf.
+ Use them before making another libdwarf call!
+ The array of string pointers passed in always has
+ a final null pointer, so if there are N pointers the
+ and M actual strings, then MIN(M,N-1) pointers are
+ set to point to error strings. The array of pointers
+ to strings always terminates with a NULL pointer.
+ If 'count' is passed in zero then errmsg_ptrs_array
+ is not touched.
+
+ The function returns DW_DLV_NO_ENTRY if no harmless errors
+ were noted so far. Returns DW_DLV_OK if there are errors.
+ Never returns DW_DLV_ERROR.
+
+ Each call empties the error list (discarding all current entries).
+ If newerr_count is non-NULL the count of harmless errors
+ since the last call is returned through the pointer
+ (some may have been discarded or not returned, it is a circular
+ list...).
+ If DW_DLV_NO_ENTRY is returned none of the arguments
+ here are touched or used.
+ */
+int dwarf_get_harmless_error_list(Dwarf_Debug /*dbg*/,
+ unsigned /*count*/,
+ const char ** /*errmsg_ptrs_array*/,
+ unsigned * /*newerr_count*/);
+
+/* Insertion is only for testing the harmless error code, it is not
+ necessarily useful otherwise. */
+void dwarf_insert_harmless_error(Dwarf_Debug /*dbg*/,
+ char * /*newerror*/);
+
+/* The size of the circular list of strings may be set
+ and reset as needed. If it is shortened excess
+ messages are simply dropped. It returns the previous
+ size. If zero passed in the size is unchanged
+ and it simply returns the current size */
+unsigned dwarf_set_harmless_error_list_size(Dwarf_Debug /*dbg*/,
+ unsigned /*maxcount*/);
+/* The harmless error strings (if any) are freed when the dbg
+ is dwarf_finish()ed. */
+
+/* When the val_in is known these dwarf_get_TAG_name (etc)
+ functions return the string corresponding to the val_in passed in
+ through the pointer s_out and the value returned is DW_DLV_OK.
+ The strings are in static storage
+ and must not be freed.
+ If DW_DLV_NO_ENTRY is returned the val_in is not known and
+ *s_out is not set. DW_DLV_ERROR is never returned.*/
+
+/* The following copied from a generated dwarf_names.h */
+
+/* BEGIN FILE */
+
+extern int dwarf_get_TAG_name(unsigned int /*val_in*/, const char ** /*s_out */);
+extern int dwarf_get_children_name(unsigned int /*val_in*/, const char ** /*s_out */);
+extern int dwarf_get_FORM_name(unsigned int /*val_in*/, const char ** /*s_out */);
+extern int dwarf_get_AT_name(unsigned int /*val_in*/, const char ** /*s_out */);
+extern int dwarf_get_OP_name(unsigned int /*val_in*/, const char ** /*s_out */);
+extern int dwarf_get_ATE_name(unsigned int /*val_in*/, const char ** /*s_out */);
+extern int dwarf_get_DS_name(unsigned int /*val_in*/, const char ** /*s_out */);
+extern int dwarf_get_END_name(unsigned int /*val_in*/, const char ** /*s_out */);
+extern int dwarf_get_ATCF_name(unsigned int /*val_in*/, const char ** /*s_out */);
+extern int dwarf_get_ACCESS_name(unsigned int /*val_in*/, const char ** /*s_out */);
+extern int dwarf_get_VIS_name(unsigned int /*val_in*/, const char ** /*s_out */);
+extern int dwarf_get_VIRTUALITY_name(unsigned int /*val_in*/, const char ** /*s_out */);
+extern int dwarf_get_LANG_name(unsigned int /*val_in*/, const char ** /*s_out */);
+extern int dwarf_get_ID_name(unsigned int /*val_in*/, const char ** /*s_out */);
+extern int dwarf_get_CC_name(unsigned int /*val_in*/, const char ** /*s_out */);
+extern int dwarf_get_INL_name(unsigned int /*val_in*/, const char ** /*s_out */);
+extern int dwarf_get_ORD_name(unsigned int /*val_in*/, const char ** /*s_out */);
+extern int dwarf_get_DSC_name(unsigned int /*val_in*/, const char ** /*s_out */);
+extern int dwarf_get_LNS_name(unsigned int /*val_in*/, const char ** /*s_out */);
+extern int dwarf_get_LNE_name(unsigned int /*val_in*/, const char ** /*s_out */);
+extern int dwarf_get_ISA_name(unsigned int /*val_in*/, const char ** /*s_out */);
+extern int dwarf_get_MACINFO_name(unsigned int /*val_in*/, const char ** /*s_out */);
+extern int dwarf_get_CFA_name(unsigned int /*val_in*/, const char ** /*s_out */);
+extern int dwarf_get_EH_name(unsigned int /*val_in*/, const char ** /*s_out */);
+extern int dwarf_get_FRAME_name(unsigned int /*val_in*/, const char ** /*s_out */);
+extern int dwarf_get_CHILDREN_name(unsigned int /*val_in*/, const char ** /*s_out */);
+extern int dwarf_get_ADDR_name(unsigned int /*val_in*/, const char ** /*s_out */);
+
+/* END FILE */
+
+/* Convert local offset into global offset */
+int dwarf_convert_to_global_offset(Dwarf_Attribute /*attr*/,
+ Dwarf_Off /*offset*/,
+ Dwarf_Off* /*ret_offset*/,
+ Dwarf_Error* /*error*/);
+
+/* Get both offsets (local and global) */
+int dwarf_die_offsets(Dwarf_Die /*die*/,
+ Dwarf_Off* /*global_offset*/,
+ Dwarf_Off* /*local_offset*/,
+ Dwarf_Error* /*error*/);
+
+/* Giving a section name, get its size and address */
+int dwarf_get_section_info_by_name(Dwarf_Debug /*dbg*/,
+ const char * /*section_name*/,
+ Dwarf_Addr* /*section_addr*/,
+ Dwarf_Unsigned* /*section_size*/,
+ Dwarf_Error* /*error*/);
+
+/* Giving a section index, get its size and address */
+int dwarf_get_section_info_by_index(Dwarf_Debug /*dbg*/,
+ int /*section_index*/,
+ const char ** /*section_name*/,
+ Dwarf_Addr* /*section_addr*/,
+ Dwarf_Unsigned* /*section_size*/,
+ Dwarf_Error* /*error*/);
+
+/* Get section count, of object file sections. */
+int dwarf_get_section_count(Dwarf_Debug /*dbg*/);
+
+/* Get the version and offset size of a CU context.
+ This is useful as a precursor to
+ calling dwarf_get_form_class() at times. */
+int dwarf_get_version_of_die(Dwarf_Die /*die*/,
+ Dwarf_Half * /*version*/,
+ Dwarf_Half * /*offset_size*/);
+
+/* Record some application command line options in libdwarf.
+ This is not arc/argv processing, just precooked setting
+ of a flag in libdwarf based on something the application
+ wants. check_verbose_mode of TRUE means do more checking
+ and sometimes print errors (from libdwarf).
+ Not restricted to a single Dwarf_Debug, it applies
+ to the libdwarf the executable is using.
+*/
+typedef struct {
+ Dwarf_Bool check_verbose_mode;
+} Dwarf_Cmdline_Options;
+extern Dwarf_Cmdline_Options dwarf_cmdline_options;
+
+/* Set libdwarf to reflect some application command line options. */
+void dwarf_record_cmdline_options(Dwarf_Cmdline_Options /*options*/);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _LIBDWARF_H */
+
+
diff --git a/libdwarf/libdwarf2.1.mm b/libdwarf/libdwarf2.1.mm
new file mode 100644
index 0000000..d94f946
--- /dev/null
+++ b/libdwarf/libdwarf2.1.mm
@@ -0,0 +1,6626 @@
+n\."
+\." the following line may be removed if the ff ligature works on your machine
+.lg 0
+\." set up heading formats
+.ds HF 3 3 3 3 3 2 2
+.ds HP +2 +2 +1 +0 +0
+.nr Hs 5
+.nr Hb 5
+\." ==============================================
+\." Put current date in the following at each rev
+.ds vE rev 2.02, December 13, 2011
+\." ==============================================
+\." ==============================================
+.ds | |
+.ds ~ ~
+.ds ' '
+.if t .ds Cw \&\f(CW
+.if n .ds Cw \fB
+.de Cf \" Place every other arg in Cw font, beginning with first
+.if \\n(.$=1 \&\*(Cw\\$1\fP
+.if \\n(.$=2 \&\*(Cw\\$1\fP\\$2
+.if \\n(.$=3 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP
+.if \\n(.$=4 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP\\$4
+.if \\n(.$=5 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP\\$4\*(Cw\\$5\fP
+.if \\n(.$=6 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP\\$4\*(Cw\\$5\fP\\$6
+.if \\n(.$=7 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP\\$4\*(Cw\\$5\fP\\$6\*(Cw\\$7\fP
+.if \\n(.$=8 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP\\$4\*(Cw\\$5\fP\\$6\*(Cw\\$7\fP\\$8
+.if \\n(.$=9 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP\\$4\*(Cw\\$5\fP\\$6\*(Cw\\$7\fP\\$8\
+*(Cw
+..
+.nr Cl 4
+.SA 1
+.TL
+A Consumer Library Interface to DWARF
+.AF ""
+.AU "David Anderson"
+.PF "'\*(vE'- \\\\nP -''"
+.AS 1
+This document describes an interface to a library of functions
+.FS
+UNIX is a registered trademark of UNIX System Laboratories, Inc.
+in the United States and other countries.
+.FE
+to access DWARF debugging information entries and DWARF line number
+information (and other DWARF2/3 information).
+It does not make recommendations as to how the functions
+described in this document should be implemented nor does it
+suggest possible optimizations.
+.P
+The document is oriented to reading DWARF version 2
+and version 3.
+There are certain sections which are SGI-specific (those
+are clearly identified in the document).
+.P
+\*(vE
+
+.AE
+.MT 4
+
+.H 1 "INTRODUCTION"
+This document describes an interface to \fIlibdwarf\fP, a
+library of functions to provide access to DWARF debugging information
+records, DWARF line number information, DWARF address range and global
+names information, weak names information, DWARF frame description
+information, DWARF static function names, DWARF static variables, and
+DWARF type information.
+.P
+The document has long mentioned the
+"Unix International Programming Languages Special Interest Group"
+(PLSIG), under whose auspices the
+DWARF committee was formed around 1991.
+"Unix International"
+was disbanded in the 1990s and no longer exists.
+.P
+The DWARF committee published DWARF2 July 27, 1993.
+.P
+In the mid 1990s this document and the library it describes
+(which the committee never endorsed, having decided
+not to endorse or approve any particular library interface)
+was made available on the internet by Silicon Graphics, Inc.
+.P
+In 2005 the DWARF committee began an affiliation with FreeStandards.org.
+In 2007 FreeStandards.org merged with The Linux Foundation.
+The DWARF committee dropped its affiliation with FreeStandards.org
+in 2007 and established the dwarfstd.org website.
+See "http://www.dwarfstd.org" for current
+information on standardization activities
+and a copy of the standard.
+.H 2 "Copyright"
+Copyright 1993-2006 Silicon Graphics, Inc.
+
+Copyright 2007-2011 David Anderson.
+
+Permission is hereby granted to
+copy or republish or use any or all of this document without
+restriction except that when publishing more than a small amount
+of the document
+please acknowledge Silicon Graphics, Inc and David Anderson.
+
+This document is distributed in the hope that it would be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+.H 2 "Purpose and Scope"
+The purpose of this document is to document a library of functions
+to access DWARF debugging information. There is no effort made in
+this document to address the creation of these records as those
+issues are addressed separately
+(see "A Producer Library Interface to DWARF").
+
+.P
+Additionally, the focus of this document is the functional interface,
+and as such, implementation as well as optimization issues are
+intentionally ignored.
+
+
+.H 2 "Document History"
+.P
+A document was written about 1991 which had similar
+layout and interfaces.
+Written by people from Hal Corporation,
+That document described a library for reading DWARF1.
+The authors distributed paper copies to the committee
+with the clearly expressed intent to propose the document as
+a supported interface definition.
+The committee decided not to pursue a library definition.
+.P
+SGI wrote the document you are now reading in 1993
+with a similar layout and content and organization, but
+it was complete document rewrite with the intent to read DWARF2
+(the DWARF version then in existence).
+The intent was (and is) to also cover
+future revisions of DWARF.
+All the function interfaces were changed
+in 1994 to uniformly
+return a simple integer success-code (see DW_DLV_OK etc),
+generally following
+the recommendations in the chapter titled "Candy Machine Interfaces"
+of "Writing Solid Code", a book by
+Steve Maguire (published by Microsoft Press).
+.H 2 "Definitions"
+DWARF debugging information entries (DIEs) are the segments of information
+placed in the \f(CW.debug_*\fP sections by compilers, assemblers, and
+linkage editors that, in conjunction with line number entries, are
+necessary for symbolic source-level debugging.
+Refer to the latest
+"\fIDWARF Debugging Information Format\fP" from www.dwarfstd.org for a more
+complete description of these entries.
+
+.P
+This document adopts all the terms and definitions in "\fIDWARF Debugging
+Information Format\fP" versions 2,3, and 4.
+It originally focused on the implementation at
+Silicon Graphics, Inc., but now
+attempts to be more generally useful.
+
+.H 2 "Overview"
+The remaining sections of this document describe the proposed interface
+to \f(CWlibdwarf\fP, first by describing the purpose of additional types
+defined by the interface, followed by descriptions of the available
+operations. This document assumes you are thoroughly familiar with the
+information contained in the \fIDWARF Debugging Information Format\fP
+document.
+.P
+We separate the functions into several categories to emphasize that not
+all consumers want to use all the functions. We call the categories
+Debugger, Internal-level, High-level, and Miscellaneous not because one is more
+important than another but as a way of making the rather large set of
+function calls easier to understand.
+.P
+Unless otherwise specified, all functions and structures should be
+taken as being designed for Debugger consumers.
+.P
+The Debugger Interface of this library is intended to be used by debuggers.
+The interface is low-level (close to dwarf) but suppresses irrelevant detail.
+A debugger will want to absorb all of some sections at startup and will
+want to see little or nothing of some sections except at need. And even
+then will probably want to absorb only the information in a single compilation
+unit at a time. A debugger does not care about
+implementation details of the library.
+.P
+The Internal-level Interface is for a DWARF prettyprinter and checker.
+A
+thorough prettyprinter will want to know all kinds of internal things
+(like actual FORM numbers and actual offsets) so it can check for
+appropriate structure in the DWARF data and print (on request) all
+that internal information for human users and libdwarf authors and
+compiler-writers.
+Calls in this interface provide data a debugger
+does not care about.
+.P
+The High-level Interface is for higher level access
+(it is not really a high level interface!).
+Programs such as
+disassemblers will want to be able to display relevant information
+about functions and line numbers without having to invest too much
+effort in looking at DWARF.
+.P
+The miscellaneous interface is just what is left over: the error handler
+functions.
+.P
+The following is a brief mention of the changes in this libdwarf from
+the libdwarf draft for DWARF Version 1 and recent changes.
+.H 2 "Items Changed"
+.P
+Added new functions (some for libdwarf client code)
+and internal logic support for the
+DWARF4 .debug_types section.
+The new functions are
+dwarf_next_cu_header_c(),
+dwarf_siblingof_b(), dwarf_offdie_b(),
+dwarf_get_cu_die_offset_given_cu_header_offset_b(),
+dwarf_get_die_infotypes_flag(),
+dwarf_get_section_max_offsets_b().
+.P
+New functions and logic support additional detailed error reporting
+so that more compiler bugs can be reported sensibly
+by consumer code (as opposed
+to having libdwarf just assume
+things are ok and blindly continuing on
+with erroneous data).
+November 20, 2010
+.P
+It seems impossible to default to both DW_FRAME_CFA_COL
+and DW_FRAME_CFA_COL3 in a single build of libdwarf,
+so the default is now unambiguously DW_FRAME_CFA_COL3
+unless the configure option --enable-oldframecol
+is specified at configure time.
+The function dwarf_set_frame_cfa_value()
+may be used to override the default : using that function gives
+consumer applications full control (its use is highly
+recommended).
+(January 17,2010)
+.P
+Added dwarf_set_reloc_application() and the default
+automatic application of Elf 'rela' relocations
+to DWARF sections (such rela sections appear in .o files, not
+in executables or shared objects, in general).
+The dwarf_set_reloc_application() routine lets a consumer
+turn off the automatic application of 'rela' relocations
+if desired (it is not clear why anyone would really want to do that,
+but possibly a consumer could write its own relocation application).
+An example application that traverses a set of DIEs
+was added to the new dwarfexample directory (not
+in this libdwarf directory, but in parallel to it).
+(July 10, 2009)
+.P
+Added dwarf_get_TAG_name() (and the FORM AT and so on)
+interface functions so applications can get the string
+of the TAG, Attribute, etc as needed. (June 2009)
+.P
+Added dwarf_get_ranges_a() and dwarf_loclist_from_expr_a()
+functions which add arguments allowing a correct address_size
+when the address_size varies by compilation unit (a varying
+address_size is quite rare as of May 2009).
+(May 2009)
+.P
+Added dwarf_set_frame_same_value(), and
+dwarf_set_frame_undefined_value() to complete
+the set of frame-information functions needed to allow
+an application get all frame information
+returned correctly (meaning that it
+can be correctly interpreted) for all ABIs.
+Documented dwarf_set_frame_cfa_value().
+Corrected spelling to dwarf_set_frame_rule_initial_value().
+(April 2009).
+.P
+Added support for various DWARF3 features, but primarily
+a new frame-information interface tailorable at run-time
+to more than a single ABI.
+See dwarf_set_frame_rule_initial_value(), dwarf_set_frame_rule_table_size(),
+dwarf_set_frame_cfa_value().
+See also dwarf_get_fde_info_for_reg3() and
+dwarf_get_fde_info_for_cfa_reg3(). (April 2006)
+.P
+Added support for DWARF3 .debug_pubtypes section.
+Corrected various leaks (revising dealloc() calls, adding
+new functions) and corrected dwarf_formstring() documentation.
+.P
+Added dwarf_srclines_dealloc() as the previous deallocation
+method documented for data returned by
+dwarf_srclines() was incapable of freeing
+all the allocated storage (14 July 2005).
+.P
+dwarf_nextglob(), dwarf_globname(), and dwarf_globdie() were all changed
+to operate on the items in the .debug_pubnames section.
+.P
+All functions were modified to return solely an error code.
+Data is returned through pointer arguments.
+This makes writing safe and correct library-using-code far easier.
+For justification for this approach, see
+the chapter titled "Candy Machine Interfaces"
+in the book "Writing Solid Code" by
+Steve Maguire.
+
+.H 2 "Items Removed"
+.P
+Dwarf_Type
+was removed since types are no longer special.
+.P
+dwarf_typeof()
+was removed since types are no longer special.
+.P
+Dwarf_Ellist
+was removed since element lists no longer are a special format.
+.P
+Dwarf_Bounds
+was removed since bounds have been generalized.
+.P
+dwarf_nextdie()
+was replaced by dwarf_next_cu_header() to reflect the
+real way DWARF is organized.
+The dwarf_nextdie() was only useful for getting to compilation
+unit beginnings, so it does not seem harmful to remove it in favor
+of a more direct function.
+.P
+dwarf_childcnt() is removed on grounds
+that no good use was apparent.
+.P
+dwarf_prevline() and dwarf_nextline() were removed on grounds this
+is better left to a debugger to do.
+Similarly, dwarf_dieline() was removed.
+.P
+dwarf_is1stline() was removed as it was not meaningful for the
+revised DWARF line operations.
+.P
+Any libdwarf implementation might well decide to support all the
+removed functionality and to retain the DWARF Version 1 meanings
+of that functionality.
+This would be difficult because the
+original libdwarf draft
+specification used traditional C library interfaces which
+confuse the values returned by successful calls with
+exceptional conditions like failures and 'no more data' indications.
+
+.H 2 "Revision History"
+.VL 15
+.LI "October 2011"
+DWARF4 support for reading .debug_types added.
+.LI "March 93"
+Work on DWARF2 SGI draft begins
+.LI "June 94"
+The function returns are changed to return an error/success code
+only.
+.LI "April 2006:
+Support for DWARF3 consumer operations is close to completion.
+.LI "November 2010:
+Added various new functions and improved error checking.
+.LE
+
+.H 1 "Types Definitions"
+
+.H 2 "General Description"
+The \fIlibdwarf.h\fP header file contains typedefs and preprocessor
+definitions of types and symbolic names used to reference objects
+of \fIlibdwarf\fP. The types defined by typedefs contained in
+\fIlibdwarf.h\fP all use the convention of adding \f(CWDwarf_\fP
+as a prefix and can be placed in three categories:
+
+.BL
+.LI
+Scalar types : The scalar types defined in \fIlibdwarf.h\fP are
+defined primarily for notational convenience and identification.
+Depending on the individual definition, they are interpreted as a
+value, a pointer, or as a flag.
+.LI
+Aggregate types : Some values can not be represented by a single
+scalar type; they must be represented by a collection of, or as a
+union of, scalar and/or aggregate types.
+.LI
+Opaque types : The complete definition of these types is intentionally
+omitted; their use is as handles for query operations, which will yield
+either an instance of another opaque type to be used in another query, or
+an instance of a scalar or aggregate type, which is the actual result.
+.P
+
+.H 2 "Scalar Types"
+The following are the defined by \fIlibdwarf.h\fP:
+
+.DS
+\f(CW
+typedef int Dwarf_Bool;
+typedef unsigned long long Dwarf_Off;
+typedef unsigned long long Dwarf_Unsigned;
+typedef unsigned short Dwarf_Half;
+typedef unsigned char Dwarf_Small;
+typedef signed long long Dwarf_Signed;
+typedef unsigned long long Dwarf_Addr;
+typedef void *Dwarf_Ptr;
+typedef void (*Dwarf_Handler)(Dwarf_Error *error, Dwarf_Ptr errarg);
+.DE
+
+.nr aX \n(Fg+1
+Dwarf_Ptr is an address for use by the host program calling the library,
+not for representing pc-values/addresses within the target object file.
+Dwarf_Addr is for pc-values within the target object file. The sample
+scalar type assignments above are for a \fIlibdwarf.h\fP that can read
+and write
+32-bit or 64-bit binaries on a 32-bit or 64-bit host machine.
+The types must be defined appropriately
+for each implementation of libdwarf.
+A description of these scalar types in the SGI/MIPS
+environment is given in Figure \n(aX.
+
+.DS
+.TS
+center box, tab(:);
+lfB lfB lfB lfB
+l c c l.
+NAME:SIZE:ALIGNMENT:PURPOSE
+_
+Dwarf_Bool:4:4:Boolean states
+Dwarf_Off:8:8:Unsigned file offset
+Dwarf_Unsigned:8:8:Unsigned large integer
+Dwarf_Half:2:2:Unsigned medium integer
+Dwarf_Small:1:1:Unsigned small integer
+Dwarf_Signed:8:8:Signed large integer
+Dwarf_Addr:8:8:Program address
+:::(target program)
+Dwarf_Ptr:4|8:4|8:Dwarf section pointer
+:::(host program)
+Dwarf_Handler:4|8:4|8:Pointer to
+:::error handler function
+.TE
+.FG "Scalar Types"
+.DE
+
+.H 2 "Aggregate Types"
+The following aggregate types are defined by
+\fIlibdwarf.h\fP:
+\f(CWDwarf_Loc\fP,
+\f(CWDwarf_Locdesc\fP,
+\f(CWDwarf_Block\fP,
+\f(CWDwarf_Frame_Op\fP.
+\f(CWDwarf_Regtable\fP.
+\f(CWDwarf_Regtable3\fP.
+While most of \f(CWlibdwarf\fP acts on or returns simple values or
+opaque pointer types, this small set of structures seems useful.
+
+.H 3 "Location Record"
+The \f(CWDwarf_Loc\fP type identifies a single atom of a location description
+or a location expression.
+
+.DS
+\f(CWtypedef struct {
+ Dwarf_Small lr_atom;
+ Dwarf_Unsigned lr_number;
+ Dwarf_Unsigned lr_number2;
+ Dwarf_Unsigned lr_offset;
+} Dwarf_Loc;\fP
+.DE
+
+The \f(CWlr_atom\fP identifies the atom corresponding to the \f(CWDW_OP_*\fP
+definition in \fIdwarf.h\fP and it represents the operation to be performed
+in order to locate the item in question.
+
+.P
+The \f(CWlr_number\fP field is the operand to be used in the calculation
+specified by the \f(CWlr_atom\fP field; not all atoms use this field.
+Some atom operations imply signed numbers so it is necessary to cast
+this to a \f(CWDwarf_Signed\fP type for those operations.
+
+.P
+The \f(CWlr_number2\fP field is the second operand specified by the
+\f(CWlr_atom\fP field; only \f(CWDW_OP_BREGX\fP has this field. Some
+atom operations imply signed numbers so it may be necessary to cast
+this to a \f(CWDwarf_Signed\fP type for those operations.
+.P
+For a \f(CWDW_OP_implicit_value\fP operator the \f(CWlr_number2\fP
+field is a pointer to the bytes of the value. The field pointed to
+is \f(CWlr_number\fP bytes long. There is no explicit terminator.
+Do not attempt to \f(CWfree\fP the bytes which \f(CWlr_number2\fP
+points at and do not alter those bytes. The pointer value
+remains valid till the open Dwarf_Debug is closed.
+This is a rather ugly use of a host integer to hold a pointer.
+You will normally have to do a 'cast' operation to use the value.
+.P
+The \f(CWlr_offset\fP field is the byte offset (within the block the
+location record came from) of the atom specified by the \f(CWlr_atom\fP
+field. This is set on all atoms. This is useful for operations
+\f(CWDW_OP_SKIP\fP and \f(CWDW_OP_BRA\fP.
+
+.H 3 "Location Description"
+The \f(CWDwarf_Locdesc\fP type represents an ordered list of
+\f(CWDwarf_Loc\fP records used in the calculation to locate
+an item. Note that in many cases, the location can only be
+calculated at runtime of the associated program.
+
+.DS
+\f(CWtypedef struct {
+ Dwarf_Addr ld_lopc;
+ Dwarf_Addr ld_hipc;
+ Dwarf_Unsigned ld_cents;
+ Dwarf_Loc* ld_s;
+} Dwarf_Locdesc;\fP
+.DE
+
+The \f(CWld_lopc\fP and \f(CWld_hipc\fP fields provide an address range for
+which this location descriptor is valid. Both of these fields are set to
+\fIzero\fP if the location descriptor is valid throughout the scope of the
+item it is associated with. These addresses are virtual memory addresses,
+not offsets-from-something. The virtual memory addresses do not account
+for dso movement (none of the pc values from libdwarf do that, it is up to
+the consumer to do that).
+
+.P
+The \f(CWld_cents\fP field contains a count of the number of \f(CWDwarf_Loc\fP
+entries pointed to by the \f(CWld_s\fP field.
+
+.P
+The \f(CWld_s\fP field points to an array of \f(CWDwarf_Loc\fP records.
+
+.H 3 "Data Block"
+.SP
+The \f(CWDwarf_Block\fP type is used to contain the value of an attribute
+whose form is either \f(CWDW_FORM_block1\fP, \f(CWDW_FORM_block2\fP,
+\f(CWDW_FORM_block4\fP, \f(CWDW_FORM_block8\fP, or \f(CWDW_FORM_block\fP.
+Its intended use is to deliver the value for an attribute of any of these
+forms.
+
+.DS
+\f(CWtypedef struct {
+ Dwarf_Unsigned bl_len;
+ Dwarf_Ptr bl_data;
+} Dwarf_Block;\fP
+.DE
+
+.P
+The \f(CWbl_len\fP field contains the length in bytes of the data pointed
+to by the \f(CWbl_data\fP field.
+
+.P
+The \f(CWbl_data\fP field contains a pointer to the uninterpreted data.
+Since we use a \f(CWDwarf_Ptr\fP here one must copy the pointer to some
+other type (typically an \f(CWunsigned char *\fP) so one can add increments
+to index through the data. The data pointed to by \f(CWbl_data\fP is not
+necessarily at any useful alignment.
+
+.H 3 "Frame Operation Codes: DWARF 2"
+This interface is adequate for DWARF2 but not for DWARF3.
+A separate interface usable for DWARF3 and for DWARF2 is described below.
+This interface is deprecated. Use the interface for DWARF3 and DWARF2.
+See also the section "Low Level Frame Operations" below.
+.P
+The DWARF2 \f(CWDwarf_Frame_Op\fP type is used to contain the data of a single
+instruction of an instruction-sequence of low-level information from the
+section containing frame information. This is ordinarily used by
+Internal-level Consumers trying to print everything in detail.
+
+.DS
+\f(CWtypedef struct {
+ Dwarf_Small fp_base_op;
+ Dwarf_Small fp_extended_op;
+ Dwarf_Half fp_register;
+ Dwarf_Signed fp_offset;
+ Dwarf_Offset fp_instr_offset;
+} Dwarf_Frame_Op;
+.DE
+
+\f(CWfp_base_op\fP is the 2-bit basic op code. \f(CWfp_extended_op\fP is
+the 6-bit extended opcode (if \f(CWfp_base_op\fP indicated there was an
+extended op code) and is zero otherwise.
+.P
+\f(CWfp_register\fP
+is any (or the first) register value as defined
+in the \f(CWCall Frame Instruction Encodings\fP figure
+in the \f(CWdwarf\fP document.
+If not used with the Op it is 0.
+.P
+\f(CWfp_offset\fP
+is the address, delta, offset, or second register as defined
+in the \f(CWCall Frame Instruction Encodings\fP figure
+in the \f(CWdwarf\fP document.
+If this is an \f(CWaddress\fP then the value should be cast to
+\f(CW(Dwarf_Addr)\fP before being used.
+In any implementation this field *must* be as large as the
+larger of Dwarf_Signed and Dwarf_Addr for this to work properly.
+If not used with the op it is 0.
+.P
+\f(CWfp_instr_offset\fP is the byte_offset (within the instruction
+stream of the frame instructions) of this operation. It starts at 0
+for a given frame descriptor.
+
+.H 3 "Frame Regtable: DWARF 2"
+This interface is adequate for DWARF2
+and MIPS but not for DWARF3.
+A separate and preferred interface usable for DWARF3 and for DWARF2
+is described below.
+See also the section "Low Level Frame Operations" below.
+.P
+The \f(CWDwarf_Regtable\fP type is used to contain the
+register-restore information for all registers at a given
+PC value.
+Normally used by debuggers.
+If you wish to default to this interface and to the use
+of DW_FRAME_CFA_COL, specify --enable_oldframecol
+at libdwarf configure time.
+Or add a call dwarf_set_frame_cfa_value(dbg,DW_FRAME_CFA_COL)
+after your dwarf_init() call, this call replaces the
+default libdwarf-compile-time value with DW_FRAME_CFA_COL.
+.DS
+/* DW_REG_TABLE_SIZE must reflect the number of registers
+ *(DW_FRAME_LAST_REG_NUM) as defined in dwarf.h
+ */
+#define DW_REG_TABLE_SIZE <fill in size here, 66 for MIPS/IRIX>
+\f(CWtypedef struct {
+ struct {
+ Dwarf_Small dw_offset_relevant;
+ Dwarf_Half dw_regnum;
+ Dwarf_Addr dw_offset;
+ } rules[DW_REG_TABLE_SIZE];
+} Dwarf_Regtable;\fP
+.DE
+.P
+The array is indexed by register number.
+The field values for each index are described next.
+For clarity we describe the field values for index rules[M]
+(M being any legal array element index).
+.P
+\f(CWdw_offset_relevant\fP is non-zero to indicate the \f(CWdw_offset\fP
+field is meaningful. If zero then the \f(CWdw_offset\fP is zero
+and should be ignored.
+.P
+\f(CWdw_regnum \fPis the register number applicable.
+If \f(CWdw_offset_relevant\fP is zero, then this is the register
+number of the register containing the value for register M.
+If \f(CWdw_offset_relevant\fP is non-zero, then this is
+the register number of the register to use as a base (M may be
+DW_FRAME_CFA_COL, for example) and the \f(CWdw_offset\fP
+value applies. The value of register M is therefore
+the value of register \f(CWdw_regnum\fP.
+.P
+\f(CWdw_offset\fP should be ignored if \f(CWdw_offset_relevant\fP is zero.
+If \f(CWdw_offset_relevant\fP is non-zero, then
+the consumer code should add the value to
+the value of the register \f(CWdw_regnum\fP to produce the
+value.
+
+.H 3 "Frame Operation Codes: DWARF 3 (and DWARF2)"
+This interface is adequate for DWARF3 and for DWARF2 (and DWARF4).
+It is new in libdwarf in April 2006.
+See also the section "Low Level Frame Operations" below.
+.P
+The DWARF2 \f(CWDwarf_Frame_Op3\fP type is used to contain the data of a single
+instruction of an instruction-sequence of low-level information from the
+section containing frame information. This is ordinarily used by
+Internal-level Consumers trying to print everything in detail.
+
+.DS
+\f(CWtypedef struct {
+ Dwarf_Small fp_base_op;
+ Dwarf_Small fp_extended_op;
+ Dwarf_Half fp_register;
+
+ /* Value may be signed, depends on op.
+ Any applicable data_alignment_factor has
+ not been applied, this is the raw offset. */
+ Dwarf_Unsigned fp_offset_or_block_len;
+ Dwarf_Small *fp_expr_block;
+
+ Dwarf_Off fp_instr_offset;
+} Dwarf_Frame_Op3;\fP
+.DE
+
+\f(CWfp_base_op\fP is the 2-bit basic op code. \f(CWfp_extended_op\fP is
+the 6-bit extended opcode (if \f(CWfp_base_op\fP indicated there was an
+extended op code) and is zero otherwise.
+.P
+\f(CWfp_register\fP
+is any (or the first) register value as defined
+in the \f(CWCall Frame Instruction Encodings\fP figure
+in the \f(CWdwarf\fP document.
+If not used with the Op it is 0.
+.P
+\f(CWfp_offset_or_block_len\fP
+is the address, delta, offset, or second register as defined
+in the \f(CWCall Frame Instruction Encodings\fP figure
+in the \f(CWdwarf\fP document. Or (depending on the op, it
+may be the length of the dwarf-expression block pointed to
+by \f(CWfp_expr_block\fP.
+If this is an \f(CWaddress\fP then the value should be cast to
+\f(CW(Dwarf_Addr)\fP before being used.
+In any implementation this field *must* be as large as the
+larger of Dwarf_Signed and Dwarf_Addr for this to work properly.
+If not used with the op it is 0.
+.P
+\f(CWfp_expr_block\fP (if applicable to the op)
+points to a dwarf-expression block which is \f(CWfp_offset_or_block_len\fP
+bytes long.
+.P
+\f(CWfp_instr_offset\fP is the byte_offset (within the instruction
+stream of the frame instructions) of this operation. It starts at 0
+for a given frame descriptor.
+
+.H 3 "Frame Regtable: DWARF 3"
+This interface is adequate for DWARF3 and for DWARF2.
+It is new in libdwarf as of April 2006.
+The default configure of libdwarf
+inserts DW_FRAME_CFA_COL3 as the default CFA column.
+Or add a call dwarf_set_frame_cfa_value(dbg,DW_FRAME_CFA_COL3)
+after your dwarf_init() call, this call replaces the
+default libdwarf-compile-time value with DW_FRAME_CFA_COL3.
+.P
+The \f(CWDwarf_Regtable3\fP type is used to contain the
+register-restore information for all registers at a given
+PC value.
+Normally used by debuggers.
+.DS
+\f(CWtypedef struct Dwarf_Regtable_Entry3_s {
+ Dwarf_Small dw_offset_relevant;
+ Dwarf_Small dw_value_type;
+ Dwarf_Half dw_regnum;
+ Dwarf_Unsigned dw_offset_or_block_len;
+ Dwarf_Ptr dw_block_ptr;
+}Dwarf_Regtable_Entry3;
+
+typedef struct Dwarf_Regtable3_s {
+ struct Dwarf_Regtable_Entry3_s rt3_cfa_rule;
+
+ Dwarf_Half rt3_reg_table_size;
+ struct Dwarf_Regtable_Entry3_s * rt3_rules;
+} Dwarf_Regtable3;\fP
+
+.DE
+.P
+The array is indexed by register number.
+The field values for each index are described next.
+For clarity we describe the field values for index rules[M]
+(M being any legal array element index).
+(DW_FRAME_CFA_COL3 DW_FRAME_SAME_VAL, DW_FRAME_UNDEFINED_VAL
+are not legal array indexes, nor is any index < 0 or >=
+rt3_reg_table_size);
+The caller of routines using this
+struct must create data space for rt3_reg_table_size entries
+of struct Dwarf_Regtable_Entry3_s and arrange that
+rt3_rules points to that space and that rt3_reg_table_size
+is set correctly. The caller need not (but may)
+initialize the contents of the rt3_cfa_rule or the rt3_rules array.
+The following applies to each rt3_rules rule M:
+.P
+.in +4
+\f(CWdw_regnum\fP is the register number applicable.
+If \f(CWdw_regnum\fP is DW_FRAME_UNDEFINED_VAL, then the
+register I has undefined value.
+If \f(CWdw_regnum\fP is DW_FRAME_SAME_VAL, then the
+register I has the same value as in the previous frame.
+.P
+If \f(CWdw_regnum\fP is neither of these two, then the following apply:
+.P
+.P
+\f(CWdw_value_type\fP determines the meaning of the other fields.
+It is one of DW_EXPR_OFFSET (0),
+DW_EXPR_VAL_OFFSET(1), DW_EXPR_EXPRESSION(2) or
+DW_EXPR_VAL_EXPRESSION(3).
+
+.P
+If \f(CWdw_value_type\fP is DW_EXPR_OFFSET (0) then
+this is as in DWARF2 and the offset(N) rule or the register(R)
+rule
+of the DWARF3 and DWARF2 document applies.
+The value is either:
+.in +4
+If \f(CWdw_offset_relevant\fP is non-zero, then \f(CWdw_regnum\fP
+is effectively ignored but must be identical to
+DW_FRAME_CFA_COL3 (and the \f(CWdw_offset\fP value applies.
+The value of register M is therefore
+the value of CFA plus the value
+of \f(CWdw_offset\fP. The result of the calculation
+is the address in memory where the value of register M resides.
+This is the offset(N) rule of the DWARF2 and DWARF3 documents.
+.P
+\f(CWdw_offset_relevant\fP is zero it indicates the \f(CWdw_offset\fP
+field is not meaningful.
+The value of register M is
+the value currently in register \f(CWdw_regnum\fP (the
+value DW_FRAME_CFA_COL3 must not appear, only real registers).
+This is the register(R) rule of the DWARF3 spec.
+.in -4
+
+.P
+If \f(CWdw_value_type\fP is DW_EXPR_OFFSET (1) then
+this is the the val_offset(N) rule of the DWARF3 spec applies.
+The calculation is identical to that of DW_EXPR_OFFSET (0)
+but the value is interpreted as the value of register M
+(rather than the address where register M's value is stored).
+.P
+If \f(CWdw_value_type\fP is DW_EXPR_EXPRESSION (2) then
+this is the the expression(E) rule of the DWARF3 document.
+.P
+.in +4
+\f(CWdw_offset_or_block_len\fP is the length in bytes of
+the in-memory block pointed at by \f(CWdw_block_ptr\fP.
+\f(CWdw_block_ptr\fP is a DWARF expression.
+Evaluate that expression and the result is the address
+where the previous value of register M is found.
+.in -4
+.P
+If \f(CWdw_value_type\fP is DW_EXPR_VAL_EXPRESSION (3) then
+this is the the val_expression(E) rule of the DWARF3 spec.
+.P
+.in +4
+\f(CWdw_offset_or_block_len\fP is the length in bytes of
+the in-memory block pointed at by \f(CWdw_block_ptr\fP.
+\f(CWdw_block_ptr\fP is a DWARF expression.
+Evaluate that expression and the result is the
+previous value of register M.
+.in -4
+.P
+The rule \f(CWrt3_cfa_rule\fP is the current value of
+the CFA. It is interpreted exactly like
+any register M rule (as described just above) except that
+\f(CWdw_regnum\fP cannot be CW_FRAME_CFA_REG3 or
+DW_FRAME_UNDEFINED_VAL or DW_FRAME_SAME_VAL but must
+be a real register number.
+.in -4
+
+
+
+.H 3 "Macro Details Record"
+The \f(CWDwarf_Macro_Details\fP type gives information about
+a single entry in the .debug.macinfo section.
+.DS
+\f(CWstruct Dwarf_Macro_Details_s {
+ Dwarf_Off dmd_offset;
+ Dwarf_Small dmd_type;
+ Dwarf_Signed dmd_lineno;
+ Dwarf_Signed dmd_fileindex;
+ char * dmd_macro;
+};
+typedef struct Dwarf_Macro_Details_s Dwarf_Macro_Details;
+.DE
+.P
+\f(CWdmd_offset\fP is the byte offset, within the .debug_macinfo
+section, of this macro information.
+.P
+\f(CWdmd_type\fP is the type code of this macro info entry
+(or 0, the type code indicating that this is the end of
+macro information entries for a compilation unit.
+See \f(CWDW_MACINFO_define\fP, etc in the DWARF document.
+.P
+\f(CWdmd_lineno\fP is the line number where this entry was found,
+or 0 if there is no applicable line number.
+.P
+\f(CWdmd_fileindex\fP is the file index of the file involved.
+This is only guaranteed meaningful on a \f(CWDW_MACINFO_start_file\fP
+\f(CWdmd_type\fP. Set to -1 if unknown (see the functional
+interface for more details).
+.P
+\f(CWdmd_macro\fP is the applicable string.
+For a \f(CWDW_MACINFO_define\fP
+this is the macro name and value.
+For a
+\f(CWDW_MACINFO_undef\fP, or
+this is the macro name.
+For a
+\f(CWDW_MACINFO_vendor_ext\fP
+this is the vendor-defined string value.
+For other \f(CWdmd_type\fPs this is 0.
+
+.H 2 "Opaque Types"
+The opaque types declared in \fIlibdwarf.h\fP are used as descriptors
+for queries against DWARF information stored in various debugging
+sections. Each time an instance of an opaque type is returned as a
+result of a \fIlibdwarf\fP operation (\f(CWDwarf_Debug\fP excepted),
+it should be freed, using \f(CWdwarf_dealloc()\fP when it is no longer
+of use (read the following documentation for details, as in at least
+one case there is a special routine provided for deallocation
+and \f(CWdwarf_dealloc()\fP is not directly called:
+see \f(CWdwarf_srclines()\fP).
+Some functions return a number of instances of an opaque type
+in a block, by means of a pointer to the block and a count of the number
+of opaque descriptors in the block:
+see the function description for deallocation rules for such functions.
+The list of opaque types defined
+in \fIlibdwarf.h\fP that are pertinent to the Consumer Library, and their
+intended use is described below.
+
+.DS
+\f(CWtypedef struct Dwarf_Debug_s* Dwarf_Debug;\fP
+.DE
+An instance of the \f(CWDwarf_Debug\fP type is created as a result of a
+successful call to \f(CWdwarf_init()\fP, or \f(CWdwarf_elf_init()\fP,
+and is used as a descriptor for subsequent access to most \f(CWlibdwarf\fP
+functions on that object. The storage pointed to by this descriptor
+should be not be freed, using the \f(CWdwarf_dealloc()\fP function.
+Instead free it with \f(CWdwarf_finish()\fP.
+.P
+
+.DS
+\f(CWtypedef struct Dwarf_Die_s* Dwarf_Die;\fP
+.DE
+An instance of a \f(CWDwarf_Die\fP type is returned from a successful
+call to the \f(CWdwarf_siblingof()\fP, \f(CWdwarf_child\fP, or
+\f(CWdwarf_offdie_b()\fP function, and is used as a descriptor for queries
+about information related to that DIE. The storage pointed to by this
+descriptor should be freed, using \f(CWdwarf_dealloc()\fP with the allocation
+type \f(CWDW_DLA_DIE\fP when no longer needed.
+
+.DS
+\f(CWtypedef struct Dwarf_Line_s* Dwarf_Line;\fP
+.DE
+Instances of \f(CWDwarf_Line\fP type are returned from a successful call
+to the \f(CWdwarf_srclines()\fP function, and are used as descriptors for
+queries about source lines. The storage pointed to by these descriptors
+should be individually freed, using \f(CWdwarf_dealloc()\fP with the
+allocation type \f(CWDW_DLA_LINE\fP when no longer needed.
+
+.DS
+\f(CWtypedef struct Dwarf_Global_s* Dwarf_Global;\fP
+.DE
+Instances of \f(CWDwarf_Global\fP type are returned from a successful
+call to the \f(CWdwarf_get_globals()\fP function, and are used as
+descriptors for queries about global names (pubnames).
+
+.DS
+\f(CWtypedef struct Dwarf_Weak_s* Dwarf_Weak;\fP
+.DE
+Instances of \f(CWDwarf_Weak\fP type are returned from a successful call
+to the
+SGI-specific \f(CWdwarf_get_weaks()\fP
+function, and are used as descriptors for
+queries about weak names. The storage pointed to by these descriptors
+should be individually freed, using \f(CWdwarf_dealloc()\fP with the
+allocation type
+\f(CWDW_DLA_WEAK_CONTEXT\fP
+(or
+\f(CWDW_DLA_WEAK\fP, an older name, supported for compatibility)
+when no longer needed.
+
+.DS
+\f(CWtypedef struct Dwarf_Func_s* Dwarf_Func;\fP
+.DE
+Instances of \f(CWDwarf_Func\fP type are returned from a successful
+call to the
+SGI-specific \f(CWdwarf_get_funcs()\fP
+function, and are used as
+descriptors for queries about static function names.
+
+.DS
+\f(CWtypedef struct Dwarf_Type_s* Dwarf_Type;\fP
+.DE
+Instances of \f(CWDwarf_Type\fP type are returned from a successful call
+to the
+SGI-specific \f(CWdwarf_get_types()\fP
+function, and are used as descriptors for
+queries about user defined types.
+
+.DS
+\f(CWtypedef struct Dwarf_Var_s* Dwarf_Var;\fP
+.DE
+Instances of \f(CWDwarf_Var\fP type are returned from a successful call
+to the SGI-specific \f(CWdwarf_get_vars()\fP
+function, and are used as descriptors for
+queries about static variables.
+
+.DS
+\f(CWtypedef struct Dwarf_Error_s* Dwarf_Error;\fP
+.DE
+This descriptor points to a structure that provides detailed information
+about errors detected by \f(CWlibdwarf\fP. Users typically provide a
+location for \f(CWlibdwarf\fP to store this descriptor for the user to
+obtain more information about the error. The storage pointed to by this
+descriptor should be freed, using \f(CWdwarf_dealloc()\fP with the
+allocation type \f(CWDW_DLA_ERROR\fP when no longer needed.
+
+.DS
+\f(CWtypedef struct Dwarf_Attribute_s* Dwarf_Attribute;\fP
+.DE
+Instances of \f(CWDwarf_Attribute\fP type are returned from a successful
+call to the \f(CWdwarf_attrlist()\fP, or \f(CWdwarf_attr()\fP functions,
+and are used as descriptors for queries about attribute values. The storage
+pointed to by this descriptor should be individually freed, using
+\f(CWdwarf_dealloc()\fP with the allocation type \f(CWDW_DLA_ATTR\fP when
+no longer needed.
+
+.DS
+\f(CWtypedef struct Dwarf_Abbrev_s* Dwarf_Abbrev;\fP
+.DE
+An instance of a \f(CWDwarf_Abbrev\fP type is returned from a successful
+call to \f(CWdwarf_get_abbrev()\fP, and is used as a descriptor for queries
+about abbreviations in the .debug_abbrev section. The storage pointed to
+by this descriptor should be freed, using \f(CWdwarf_dealloc()\fP with the
+allocation type \f(CWDW_DLA_ABBREV\fP when no longer needed.
+
+.DS
+\f(CWtypedef struct Dwarf_Fde_s* Dwarf_Fde;\fP
+.DE
+Instances of \f(CWDwarf_Fde\fP type are returned from a successful call
+to the \f(CWdwarf_get_fde_list()\fP, \f(CWdwarf_get_fde_for_die()\fP, or
+\f(CWdwarf_get_fde_at_pc()\fP functions, and are used as descriptors for
+queries about frames descriptors.
+
+.DS
+\f(CWtypedef struct Dwarf_Cie_s* Dwarf_Cie;\fP
+.DE
+Instances of \f(CWDwarf_Cie\fP type are returned from a successful call
+to the \f(CWdwarf_get_fde_list()\fP function, and are used as descriptors
+for queries about information that is common to several frames.
+
+.DS
+\f(CWtypedef struct Dwarf_Arange_s* Dwarf_Arange;\fP
+.DE
+Instances of \f(CWDwarf_Arange\fP type are returned from successful calls
+to the \f(CWdwarf_get_aranges()\fP, or \f(CWdwarf_get_arange()\fP functions,
+and are used as descriptors for queries about address ranges. The storage
+pointed to by this descriptor should be individually freed, using
+\f(CWdwarf_dealloc()\fP with the allocation type \f(CWDW_DLA_ARANGE\fP when
+no longer needed.
+
+.H 1 "Error Handling"
+The method for detection and disposition of error conditions that arise
+during access of debugging information via \fIlibdwarf\fP is consistent
+across all \fIlibdwarf\fP functions that are capable of producing an
+error. This section describes the method used by \fIlibdwarf\fP in
+notifying client programs of error conditions.
+
+.P
+Most functions within \fIlibdwarf\fP accept as an argument a pointer to
+a \f(CWDwarf_Error\fP descriptor where a \f(CWDwarf_Error\fP descriptor
+is stored if an error is detected by the function. Routines in the client
+program that provide this argument can query the \f(CWDwarf_Error\fP
+descriptor to determine the nature of the error and perform appropriate
+processing.
+
+.P
+A client program can also specify a function to be invoked upon detection
+of an error at the time the library is initialized (see \f(CWdwarf_init()\fP).
+When a \fIlibdwarf\fP routine detects an error, this function is called
+with two arguments: a code indicating the nature of the error and a pointer
+provided by the client at initialization (again see \f(CWdwarf_init()\fP).
+This pointer argument can be used to relay information between the error
+handler and other routines of the client program. A client program can
+specify or change both the error handling function and the pointer argument
+after initialization using \f(CWdwarf_seterrhand()\fP and
+\f(CWdwarf_seterrarg()\fP.
+
+.P
+In the case where \fIlibdwarf\fP functions are not provided a pointer
+to a \f(CWDwarf_Error\fP descriptor, and no error handling function was
+provided at initialization, \fIlibdwarf\fP functions terminate execution
+by calling \f(CWabort(3C)\fP.
+
+.P
+The following lists the processing steps taken upon detection of an
+error:
+.AL 1
+.LI
+Check the \f(CWerror\fP argument; if not a \fINULL\fP pointer, allocate
+and initialize a \f(CWDwarf_Error\fP descriptor with information describing
+the error, place this descriptor in the area pointed to by \f(CWerror\fP,
+and return a value indicating an error condition.
+.LI
+If an \f(CWerrhand\fP argument was provided to \f(CWdwarf_init()\fP
+at initialization, call \f(CWerrhand()\fP passing it the error descriptor
+and the value of the \f(CWerrarg\fP argument provided to \f(CWdwarf_init()\fP.
+If the error handling function returns, return a value indicating an
+error condition.
+.LI
+Terminate program execution by calling \f(CWabort(3C)\fP.
+.LE
+.SP
+
+In all cases, it is clear from the value returned from a function
+that an error occurred in executing the function, since
+DW_DLV_ERROR is returned.
+.P
+As can be seen from the above steps, the client program can provide
+an error handler at initialization, and still provide an \f(CWerror\fP
+argument to \fIlibdwarf\fP functions when it is not desired to have
+the error handler invoked.
+
+.P
+If a \f(CWlibdwarf\fP function is called with invalid arguments, the
+behavior is undefined. In particular, supplying a \f(CWNULL\fP pointer
+to a \f(CWlibdwarf\fP function (except where explicitly permitted),
+or pointers to invalid addresses or uninitialized data causes undefined
+behavior; the return value in such cases is undefined, and the function
+may fail to invoke the caller supplied error handler or to return a
+meaningful error number. Implementations also may abort execution for
+such cases.
+
+.P
+Some errors are so inconsequential that it does not warrant
+rejecting an object or returning an error.
+An example would be a frame length not being a multiple of
+an address-size (right now this is the only such inconsequential
+error). To make it possible for a client to report such errors
+the function \f(CWdwarf_get_harmless_error_list\fP
+returns strings with error text in them. This function
+may be ignored if client code does not want to bother with
+such error reporting. See \f(CWDW_DLE_DEBUG_FRAME_LENGTH_NOT_MULTIPLE\fP
+in the libdwarf source code.
+
+.P
+.H 2 "Returned values in the functional interface"
+Values returned by \f(CWlibdwarf\fP functions to indicate
+success and errors
+.nr aX \n(Fg+1
+are enumerated in Figure \n(aX.
+The \f(CWDW_DLV_NO_ENTRY\fP
+case is useful for functions
+need to indicate that while there was no data to return
+there was no error either.
+For example, \f(CWdwarf_siblingof()\fP
+may return \f(CWDW_DLV_NO_ENTRY\fP to indicate that that there was
+no sibling to return.
+.DS
+.TS
+center box, tab(:);
+lfB cfB lfB
+l c l.
+SYMBOLIC NAME:VALUE:MEANING
+_
+DW_DLV_ERROR:1:Error
+DW_DLV_OK:0:Successful call
+DW_DLV_NO_ENTRY:-1:No applicable value
+.TE
+.FG "Error Indications"
+.DE
+.P
+Each function in the interface that returns a value returns one
+of the integers in the above figure.
+.P
+If \f(CWDW_DLV_ERROR\fP is returned and a pointer to a \f(CWDwarf_Error\fP
+pointer is passed to the function, then a Dwarf_Error handle is returned
+through the pointer. No other pointer value in the interface returns a value.
+After the \f(CWDwarf_Error\fP is no longer of interest,
+a \f(CWdwarf_dealloc(dbg,dw_err,DW_DLA_ERROR)\fP on the error
+pointer is appropriate to free any space used by the error information.
+.P
+If \f(CWDW_DLV_NO_ENTRY\fP is returned no pointer value in the
+interface returns a value.
+.P
+If \f(CWDW_DLV_OK\fP is returned, the \f(CWDwarf_Error\fP pointer, if
+supplied, is not touched, but any other values to be returned
+through pointers are returned.
+In this case calls (depending on the exact function
+returning the error) to \f(CWdwarf_dealloc()\fP may be appropriate
+once the particular pointer returned is no longer of interest.
+.P
+Pointers passed to allow values to be returned through them are
+uniformly the last pointers
+in each argument list.
+.P
+All the interface functions are defined from the point of view of
+the writer-of-the-library (as is traditional for UN*X library
+documentation), not from the point of view of the user of the library.
+The caller might code:
+.P
+.DS
+\f(CWDwarf_Line line;
+Dwarf_Signed ret_loff;
+Dwarf_Error err;
+int retval = dwarf_lineoff(line,&ret_loff,&err);\fP
+.DE
+for the function defined as
+.P
+.DS
+\f(CWint dwarf_lineoff(Dwarf_Line line,Dwarf_Signed *return_lineoff,
+ Dwarf_Error* err);\fP
+.DE
+and this document refers to the function as
+returning the value through *err or *return_lineoff or
+uses the phrase "returns in
+the location pointed to by err".
+Sometimes other similar phrases are used.
+
+.H 1 "Memory Management"
+Several of the functions that comprise \fIlibdwarf\fP return pointers
+(opaque descriptors) to structures that have been dynamically allocated
+by the library. To aid in the management of dynamic memory, the function
+\f(CWdwarf_dealloc()\fP is provided to free storage allocated as a result
+of a call to a \fIlibdwarf\fP function. This section describes the strategy
+that should be taken by a client program in managing dynamic storage.
+
+.H 2 "Read-only Properties"
+All pointers (opaque descriptors) returned by or as a result of a
+\fIlibdwarf Consumer Library\fP
+call should be assumed to point to read-only memory.
+The results are undefined for \fIlibdwarf\fP clients that attempt
+to write to a region pointed to by a value returned by a
+\fIlibdwarf Consumer Library\fP
+call.
+
+.H 2 "Storage Deallocation"
+See the section "Returned values in the functional interface",
+above, for the general rules where
+calls to \f(CWdwarf_dealloc()\fP
+is appropriate.
+.P
+In some cases the pointers returned by a \fIlibdwarf\fP call are pointers
+to data which is not freeable.
+The library knows from the allocation type
+provided to it whether the space is freeable or not and will not free
+inappropriately when \f(CWdwarf_dealloc()\fP is called.
+So it is vital
+that \f(CWdwarf_dealloc()\fP be called with the proper allocation type.
+.P
+For most storage allocated by \fIlibdwarf\fP, the client can free the
+storage for reuse by calling \f(CWdwarf_dealloc()\fP, providing it with
+the \f(CWDwarf_Debug\fP descriptor specifying the object for which the
+storage was allocated, a pointer to the area to be free-ed, and an
+identifier that specifies what the pointer points to (the allocation
+type). For example, to free a \f(CWDwarf_Die die\fP belonging the the
+object represented by \f(CWDwarf_Debug dbg\fP, allocated by a call to
+\f(CWdwarf_siblingof()\fP, the call to \f(CWdwarf_dealloc()\fP would be:
+.DS
+ \f(CWdwarf_dealloc(dbg, die, DW_DLA_DIE);\fP
+.DE
+
+To free storage allocated in the form of a list of pointers (opaque
+descriptors), each member of the list should be deallocated, followed
+by deallocation of the actual list itself. The following code fragment
+uses an invocation of \f(CWdwarf_attrlist()\fP as an example to illustrate
+a technique that can be used to free storage from any \fIlibdwarf\fP
+routine that returns a list:
+.DS
+\f(CWDwarf_Unsigned atcnt;
+Dwarf_Attribute *atlist;
+int errv;
+
+errv = dwarf_attrlist(somedie, &atlist,&atcnt, &error);
+if (errv == DW_DLV_OK) {
+
+ for (i = 0; i < atcnt; ++i) {
+ /* use atlist[i] */
+ dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);
+ }
+ dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
+}\fP
+.DE
+
+The \f(CWDwarf_Debug\fP returned from \f(CWdwarf_init()\fP
+or \f(CWdwarf_elf_init()\fP
+cannot be freed using \f(CWdwarf_dealloc()\fP.
+The function \f(CWdwarf_finish()\fP will deallocate all dynamic storage
+associated with an instance of a \f(CWDwarf_Debug\fP type. In particular,
+it will deallocate all dynamically allocated space associated with the
+\f(CWDwarf_Debug\fP descriptor, and finally make the descriptor invalid.
+
+An \f(CWDwarf_Error\fP returned from \f(CWdwarf_init()\fP
+or \f(CWdwarf_elf_init()\fP
+in case of a failure cannot be freed
+using \f(CWdwarf_dealloc()\fP.
+The only way to free the \f(CWDwarf_Error\fP from either of those
+calls is to use \f2free(3)\fP directly.
+Every \f(CWDwarf_Error\fP must be freed
+by \f(CWdwarf_dealloc()\fP except those
+returned by \f(CWdwarf_init()\fP
+or \f(CWdwarf_elf_init()\fP.
+
+.P
+The codes that identify the storage pointed to in calls to
+.nr aX \n(Fg+1
+\f(CWdwarf_dealloc()\fP are described in figure \n(aX.
+.DS
+.TS
+center box, tab(:);
+lfB lfB
+l l.
+IDENTIFIER:USED TO FREE
+_
+DW_DLA_STRING : char*
+DW_DLA_LOC : Dwarf_Loc
+DW_DLA_LOCDESC : Dwarf_Locdesc
+DW_DLA_ELLIST : Dwarf_Ellist (not used)
+DW_DLA_BOUNDS : Dwarf_Bounds (not used)
+DW_DLA_BLOCK : Dwarf_Block
+DW_DLA_DEBUG : Dwarf_Debug (do not use)
+DW_DLA_DIE : Dwarf_Die
+DW_DLA_LINE : Dwarf_Line
+DW_DLA_ATTR : Dwarf_Attribute
+DW_DLA_TYPE : Dwarf_Type (not used)
+DW_DLA_SUBSCR : Dwarf_Subscr (not used)
+DW_DLA_GLOBAL_CONTEXT : Dwarf_Global
+DW_DLA_ERROR : Dwarf_Error
+DW_DLA_LIST : a list of opaque descriptors
+DW_DLA_LINEBUF : Dwarf_Line* (not used)
+DW_DLA_ARANGE : Dwarf_Arange
+DW_DLA_ABBREV : Dwarf_Abbrev
+DW_DLA_FRAME_OP : Dwarf_Frame_Op
+DW_DLA_CIE : Dwarf_Cie
+DW_DLA_FDE : Dwarf_Fde
+DW_DLA_LOC_BLOCK : Dwarf_Loc Block
+DW_DLA_FRAME_BLOCK : Dwarf_Frame Block (not used)
+DW_DLA_FUNC_CONTEXT : Dwarf_Func
+DW_DLA_TYPENAME_CONTEXT : Dwarf_Type
+DW_DLA_VAR_CONTEXT : Dwarf_Var
+DW_DLA_WEAK_CONTEXT : Dwarf_Weak
+DW_DLA_PUBTYPES_CONTEXT : Dwarf_Pubtype
+.TE
+.FG "Allocation/Deallocation Identifiers"
+.DE
+
+.P
+.H 1 "Functional Interface"
+This section describes the functions available in the \fIlibdwarf\fP
+library. Each function description includes its definition, followed
+by one or more paragraph describing the function's operation.
+
+.P
+The following sections describe these functions.
+
+.H 2 "Initialization Operations"
+These functions are concerned with preparing an object file for subsequent
+access by the functions in \fIlibdwarf\fP and with releasing allocated
+resources when access is complete.
+
+.H 3 "dwarf_init()"
+
+.DS
+\f(CWint dwarf_init(
+ int fd,
+ Dwarf_Unsigned access,
+ Dwarf_Handler errhand,
+ Dwarf_Ptr errarg,
+ Dwarf_Debug * dbg,
+ Dwarf_Error *error)\fP
+.DE
+When it returns \f(CWDW_DLV_OK\fP,
+the function \f(CWdwarf_init()\fP returns through
+\f(CWdbg\fP a \f(CWDwarf_Debug\fP descriptor
+that represents a handle for accessing debugging records associated with
+the open file descriptor \f(CWfd\fP.
+\f(CWDW_DLV_NO_ENTRY\fP is returned if the object
+does not contain DWARF debugging information.
+\f(CWDW_DLV_ERROR\fP is returned if
+an error occurred.
+The
+\f(CWaccess\fP argument indicates what access is allowed for the section.
+The \f(CWDW_DLC_READ\fP parameter is valid
+for read access (only read access is defined or discussed in this
+document).
+The \f(CWerrhand\fP
+argument is a pointer to a function that will be invoked whenever an error
+is detected as a result of a \fIlibdwarf\fP operation. The \f(CWerrarg\fP
+argument is passed as an argument to the \f(CWerrhand\fP function.
+The file
+descriptor associated with the \f(CWfd\fP argument must refer to an ordinary
+file (i.e. not a pipe, socket, device, /proc entry, etc.), be opened with
+the at least as much permission as specified by the \f(CWaccess\fP argument,
+and cannot be closed or used as an argument to any system calls by the
+client until after \f(CWdwarf_finish()\fP is called.
+The seek position of
+the file associated with \f(CWfd\fP is undefined upon return of
+\f(CWdwarf_init()\fP.
+
+With SGI IRIX, by default it is allowed that the app
+\f(CWclose()\fP \f(CWfd\fP immediately after calling \f(CWdwarf_init()\fP,
+but that is not a portable approach (that it
+works is an accidental
+side effect of the fact that SGI IRIX uses \f(CWELF_C_READ_MMAP\fP
+in its hidden internal call to \f(CWelf_begin()\fP).
+The portable approach is to consider that \f(CWfd\fP
+must be left open till after the corresponding dwarf_finish() call
+has returned.
+
+Since \f(CWdwarf_init()\fP uses the same error handling processing as other
+\fIlibdwarf\fP functions (see \fIError Handling\fP above), client programs
+will generally supply an \f(CWerror\fP parameter to bypass the default actions
+during initialization unless the default actions are appropriate.
+
+.H 3 "dwarf_elf_init()"
+.DS
+\f(CWint dwarf_elf_init(
+ Elf * elf_file_pointer,
+ Dwarf_Unsigned access,
+ Dwarf_Handler errhand,
+ Dwarf_Ptr errarg,
+ Dwarf_Debug * dbg,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_elf_init()\fP is identical to \f(CWdwarf_init()\fP
+except that an open \f(CWElf *\fP pointer is passed instead of a file
+descriptor.
+In systems supporting \f(CWELF\fP object files this may be
+more space or time-efficient than using \f(CWdwarf_init()\fP.
+The client is allowed to use the \f(CWElf *\fP pointer
+for its own purposes without restriction during the time the
+\f(CWDwarf_Debug\fP
+is open, except that the client should not \f(CWelf_end()\fP the
+pointer till after \f(CWdwarf_finish\fP is called.
+
+.H 3 "dwarf_get_elf()"
+.DS
+\f(CWint dwarf_get_elf(
+ Dwarf_Debug dbg,
+ Elf ** elf,
+ Dwarf_Error *error)\fP
+.DE
+When it returns \f(CWDW_DLV_OK\fP,
+the function \f(CWdwarf_get_elf()\fP returns through the
+pointer \f(CWelf\fP the \f(CWElf *\fP handle
+used to access the object represented by the \f(CWDwarf_Debug\fP
+descriptor \f(CWdbg\fP. It returns \f(CWDW_DLV_ERROR\fP on error.
+
+Because \f(CWint dwarf_init()\fP opens an Elf descriptor
+on its fd and \f(CWdwarf_finish()\fP does not close that
+descriptor, an app should use \f(CWdwarf_get_elf\fP
+and should call \f(CWelf_end\fP with the pointer returned
+through the \f(CWElf**\fP handle created by \f(CWint dwarf_init()\fP.
+
+This function is not meaningful for a system that does not use the
+Elf format for objects.
+
+.H 3 "dwarf_finish()"
+.DS
+\f(CWint dwarf_finish(
+ Dwarf_Debug dbg,
+ Dwarf_Error *error)\fP
+.DE
+The function
+\f(CWdwarf_finish()\fP releases all \fILibdwarf\fP internal resources
+associated with the descriptor \f(CWdbg\fP, and invalidates \f(CWdbg\fP.
+It returns \f(CWDW_DLV_ERROR\fP if there is an error during the
+finishing operation. It returns \f(CWDW_DLV_OK\fP
+for a successful operation.
+
+Because \f(CWint dwarf_init()\fP opens an Elf descriptor
+on its fd and \f(CWdwarf_finish()\fP does not close that
+descriptor, an app should use \f(CWdwarf_get_elf\fP
+and should call \f(CWelf_end\fP with the pointer returned
+through the \f(CWElf**\fP handle created by \f(CWint dwarf_init()\fP.
+
+.H 3 "dwarf_set_stringcheck()"
+.DS
+\f(CWint dwarf_set_stringcheck(
+ int stringcheck)\fP
+.DE
+The function
+\f(CWint dwarf_set_stringcheck()\fP sets a global flag
+and returns the previous value of the global flag.
+
+If the stringcheck global flag is zero (the default)
+libdwarf does not do string length validity checks.
+If the stringcheck global flag is non-zero
+libdwarf does do string length validity checks (the checks
+do slow libdwarf down).
+
+The global flag is really just 8 bits long, upperbits are not noticed
+or recorded.
+
+.H 3 "dwarf_set_reloc_application()"
+.DS
+\f(CWint dwarf_set_reloc_application(
+ int apply)\fP
+.DE
+The function
+\f(CWint dwarf_set_reloc_application()\fP sets a global flag
+and returns the previous value of the global flag.
+
+If the reloc_application global flag is non-zero (the default)
+then the applicable .rela section (if one exists) will be
+processed and applied to any DWARF section when it is read in.
+If the reloc_application global flag is zero no such
+relocation-application is attempted.
+
+Not all
+machine types (elf header e_machine)
+or all relocations are supported, but then very few
+relocation types apply to DWARF debug sections.
+
+The global flag is really just 8 bits long, upperbits are not noticed
+or recorded.
+
+It seems unlikely anyone will need to call this function.
+
+.H 3 "dwarf_record_cmdline_options()"
+.DS
+\f(CWint dwarf_record_cmdline_options(
+ Dwarf_Cmdline_Options options)\fP
+.DE
+The function
+\f(CWint dwarf_record_cmdline_options()\fP
+copies a Dwarf_Cmdline_Options structure from
+consumer code to libdwarf.
+
+The structure is defined in \f(CWlibdwarf.h\fP.
+
+The initial version of this structure has a single field
+\f(CWcheck_verbose_mode\fP which, if non-zero, tells
+libdwarf to print some detailed messages to stdout in case
+certain errors are detected.
+
+The default for this value is FALSE (0) so the extra messages
+are off by default.
+
+.H 2 "Section size operations"
+.P
+These operations are informative but not normally needed.
+.H 3 "dwarf_get_section_max_offsets_b()"
+.DS
+\f(CWint dwarf_get_section_max_offsets_b(Dwarf_debug dbg,
+ Dwarf_Unsigned * /*debug_info_size*/,
+ Dwarf_Unsigned * /*debug_abbrev_size*/,
+ Dwarf_Unsigned * /*debug_line_size*/,
+ Dwarf_Unsigned * /*debug_loc_size*/,
+ Dwarf_Unsigned * /*debug_aranges_size*/,
+ Dwarf_Unsigned * /*debug_macinfo_size*/,
+ Dwarf_Unsigned * /*debug_pubnames_size*/,
+ Dwarf_Unsigned * /*debug_str_size*/,
+ Dwarf_Unsigned * /*debug_frame_size*/,
+ Dwarf_Unsigned * /*debug_ranges_size*/,
+ Dwarf_Unsigned * /*debug_pubtypes_size*/,
+ Dwarf_Unsigned * /*debug_types_size*/);
+.DE
+.P
+The function
+\f(CWdwarf_get_section_max_offsets_b()\fP an open
+Dwarf_Dbg and reports on the section sizes by pushing
+section size values back through the pointers.
+
+Created in October 2011.
+
+.H 3 "dwarf_get_section_max_offsets()"
+.DS
+\f(CWint dwarf_get_section_max_offsets(Dwarf_debug dbg,
+ Dwarf_Unsigned * /*debug_info_size*/,
+ Dwarf_Unsigned * /*debug_abbrev_size*/,
+ Dwarf_Unsigned * /*debug_line_size*/,
+ Dwarf_Unsigned * /*debug_loc_size*/,
+ Dwarf_Unsigned * /*debug_aranges_size*/,
+ Dwarf_Unsigned * /*debug_macinfo_size*/,
+ Dwarf_Unsigned * /*debug_pubnames_size*/,
+ Dwarf_Unsigned * /*debug_str_size*/,
+ Dwarf_Unsigned * /*debug_frame_size*/,
+ Dwarf_Unsigned * /*debug_ranges_size*/,
+ Dwarf_Unsigned * /*debug_pubtypes_size*/);
+.DE
+.P
+The function is the same as \f(CWdwarf_get_section_max_offsets_b()\fP
+except it is missing the \f(CWdebug_types_size()\fP argument.
+Though obsolete it is still supported.
+
+
+
+.H 2 "Debugging Information Entry Delivery Operations"
+These functions are concerned with accessing debugging information
+entries.
+
+.H 3 "dwarf_next_cu_header_c()"
+.DS
+\f(CWint dwarf_next_cu_header_c(
+ Dwarf_debug dbg,
+ Dwarf_Bool is_info,
+ Dwarf_Unsigned *cu_header_length,
+ Dwarf_Half *version_stamp,
+ Dwarf_Unsigned *abbrev_offset,
+ Dwarf_Half *address_size,
+ Dwarf_Half *offset_size,
+ Dwarf_Half *extension_size,
+ Dwarf_Sig8 *signature,
+ Dwarf_Unsigned *typeoffset
+ Dwarf_Unsigned *next_cu_header,
+ Dwarf_Error *error);
+.DE
+The function
+\f(CWdwarf_next_cu_header_c()\fP operates on
+the either the .debug_info section
+(if \f(CWis_info\fP is non-zero) or .debug_types
+section
+(if \f(CWis_info\fP is zero).
+It returns \f(CWDW_DLV_ERROR\fP
+if it fails, and
+\f(CWDW_DLV_OK\fP if it succeeds.
+.P
+If it succeeds, \f(CW*next_cu_header\fP is set to
+the offset in the .debug_info section of the next
+compilation-unit header if it succeeds. On reading the last
+compilation-unit header in the .debug_info section it contains
+the size of the .debug_info or debug_types section.
+The next call to
+\f(CWdwarf_next_cu_header_b()\fP returns \f(CWDW_DLV_NO_ENTRY\fP
+without reading a
+compilation-unit or setting \f(CW*next_cu_header\fP.
+Subsequent calls to \f(CWdwarf_next_cu_header()\fP
+repeat the cycle by reading the first compilation-unit and so on.
+.P
+The other
+values returned through pointers are the values in the compilation-unit
+header. If any of \f(CWcu_header_length\fP, \f(CWversion_stamp\fP,
+\f(CWabbrev_offset\fP, \f(CWaddress_size\fP,
+\f(CWoffset_size\fP, \f(CWextension_size\fP,
+\f(CWsignature\fP, or \f(CWtypeoffset\fP,
+is \f(CWNULL\fP, the
+argument is ignored (meaning it is not an error to provide a
+\f(CWNULL\fP pointer for any or all of these arguments).
+.P
+\f(CWcu_header_length\fP returns the length in bytes of the compilation
+unit header.
+.P
+\f(CWversion_stamp\fP returns the section version, which
+would be (for .debug_info) 2 for DWARF2, 3 for DWARF4, or
+4 for DWARF4.
+.P
+\f(CWabbrev_offset\fP returns the .debug_abbrev
+section offset of the abbreviations
+for this compilation unit.
+.P
+\f(CWaddress_size\fP returns the size of an address in this
+compilation unit. Which is usually 4 or 8.
+.P
+\f(CWoffset_size\fP returns the size in bytes of
+an offset for the compilation unit. The offset size
+is 4 for 32bit dwarf
+and 8 for 64bit dwarf.
+This is the offset size in dwarf data, not
+the address size inside the executable code.
+The offset size can be 4 even
+if embedded in a 64bit elf file (which
+is normal for 64bit elf), and can be 8 even in
+a 32bit elf file (which probably will never be seen
+in practice).
+.P
+The
+\f(CWextension_size\fP pointer is only relevant if
+the \f(CWoffset_size\fP pointer returns 8.
+The value is not normally useful but is returned
+through the pointer for completeness.
+The pointer \f(CWextension_size\fP returns 0
+if the CU is MIPS/IRIX non-standard 64bit dwarf
+(MIPS/IRIX 64bit dwarf was created years before DWARF3
+defined 64bit dwarf)
+and returns 4 if the dwarf uses the standard 64bit
+extension (the 4 is the size in bytes of the 0xffffffff
+in the initial length field
+which indicates the following 8 bytes in the .debug_info section
+are the real length).
+See the DWARF3 or DWARF4 standard, section 7.4.
+.P
+The
+\f(CWsignature\fP pointer is only relevant if
+\f(CWis_info\fP is zero, and if relevant the 8 byte type
+signature of the .debug_types CU header is assigned through
+the pointer.
+.P
+The
+\f(CWtypeoffset\fP pointer is only relevant if
+\f(CWis_info\fP is zero, and if relevant the local offset
+within the CU of the the type offset the .debug_types entry
+represents is assigned through the pointer.
+The
+\f(CWtypeoffset\fP matters because a
+DW_AT_type referencing the type unit may reference an inner type,
+such as a C++ class in a C++ namespace, but the type itself
+has the enclosing namespace in the .debug_type type_unit.
+
+.H 3 "dwarf_next_cu_header_b()"
+.DS
+\f(CWint dwarf_next_cu_header_b(
+ Dwarf_debug dbg,
+ Dwarf_Unsigned *cu_header_length,
+ Dwarf_Half *version_stamp,
+ Dwarf_Unsigned *abbrev_offset,
+ Dwarf_Half *address_size,
+ Dwarf_Half *offset_size,
+ Dwarf_Half *extension_size,
+ Dwarf_Unsigned *next_cu_header,
+ Dwarf_Error *error);
+.DE
+.P
+This is obsolete as of October 2011 though supported.
+.P
+The function
+\f(CWdwarf_next_cu_header_b()\fP operates on
+the .debug_info section. It operates exactly like
+\f(CWdwarf_next_cu_header_c()\fP but
+is missing the
+\f(CWsignature\fP, and \f(CWtypeoffset\fP
+fields.
+This is kept for compatibility.
+All code using this should be changed to use
+\f(CWdwarf_next_cu_header_c()\fP
+
+.H 3 "dwarf_next_cu_header()"
+.P
+The following is the original form, missing the
+\f(CWoffset_size\fP, \f(CWextension_size\fP,
+\f(CWsignature\fP, and \f(CWtypeoffset\fP
+fields in
+\f(CWdwarf_next_cu_header_c()\fP.
+This is kept for compatibility.
+All code using this should be changed to use
+\f(CWdwarf_next_cu_header_c()\fP
+.DS
+\f(CWint dwarf_next_cu_header(
+ Dwarf_debug dbg,
+ Dwarf_Unsigned *cu_header_length,
+ Dwarf_Half *version_stamp,
+ Dwarf_Unsigned *abbrev_offset,
+ Dwarf_Half *address_size,
+ Dwarf_Unsigned *next_cu_header,
+ Dwarf_Error *error);
+.DE
+
+.H 3 "dwarf_siblingof_b()"
+.DS
+\f(CWint dwarf_siblingof_b(
+ Dwarf_Debug dbg,
+ Dwarf_Die die,
+ Dwarf_Bool is_info,
+ Dwarf_Die *return_sib,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_siblingof_b()\fP
+returns \f(CWDW_DLV_ERROR\fP and sets the \f(CWerror\fP pointer on error.
+If there is no sibling it returns \f(CWDW_DLV_NO_ENTRY\fP.
+When it succeeds,
+\f(CWdwarf_siblingof_b()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_sib\fP to the \f(CWDwarf_Die\fP
+descriptor of the sibling of \f(CWdie\fP.
+
+If \f(CWis_info\fP is non-zero then the \f(CWdie\fP
+is assumed to refer to a .debug_info DIE.
+If \f(CWis_info\fP is zero then the \f(CWdie\fP
+is assumed to refer to a .debug_types DIE.
+Note that the first call (the call that gets the compilation-unit
+DIE in a compilation unit) passes in a NULL \f(CWdie\fP
+so having the caller pass in \f(CWis_info\fP is essential.
+And if \f(CWdie\fP is non-NULL it is still essential for the
+call to pass in \f(CWis_info\fP set properly to reflect the
+section the DIE came from.
+The function
+\f(CWdwarf_get_die_infotypes_flag()\fP is of interest as
+it returns the proper is_info value from any non-NULL \f(CWdie\fP
+pointer.
+
+
+If \f(CWdie\fP is \fINULL\fP, the \f(CWDwarf_Die\fP descriptor of the
+first die in the compilation-unit is returned.
+This die has the
+\f(CWDW_TAG_compile_unit\fP,
+\f(CWDW_TAG_partial_unit\fP,
+or \f(CWDW_TAG_type_unit\fP
+tag.
+
+.in +2
+.DS
+\f(CWDwarf_Die return_sib = 0;
+Dwarf_Error error = 0;
+int res;
+Dwarf_Bool is_info = 1;
+/* in_die might be NULL or a valid Dwarf_Die */
+res = dwarf_siblingof_b(dbg,in_die,is_info,&return_sib, &error);
+if (res == DW_DLV_OK) {
+ /* Use return_sib here. */
+ dwarf_dealloc(dbg, return_sib, DW_DLA_DIE);
+ /* return_sib is no longer usable for anything, we
+ ensure we do not use it accidentally with: */
+ return_sib = 0;
+}\fP
+.DE
+.in -2
+
+.H 3 "dwarf_siblingof()"
+.DS
+\f(CWint dwarf_siblingof(
+ Dwarf_Debug dbg,
+ Dwarf_Die die,
+ Dwarf_Die *return_sib,
+ Dwarf_Error *error)\fP
+.DE
+.P
+\f(CWint dwarf_siblingof()\fP operates exactly the same as
+\f(CWint dwarf_siblingof_b()\fP, but
+\f(CWint dwarf_siblingof()\fP refers only to .debug_info
+DIEs.
+
+
+.H 3 "dwarf_child()"
+.DS
+\f(CWint dwarf_child(
+ Dwarf_Die die,
+ Dwarf_Die *return_kid,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_child()\fP
+returns \f(CWDW_DLV_ERROR\fP and sets the \f(CWerror\fP die on error.
+If there is no child it returns \f(CWDW_DLV_NO_ENTRY\fP.
+When it succeeds,
+\f(CWdwarf_child()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_kid\fP
+to the \f(CWDwarf_Die\fP descriptor
+of the first child of \f(CWdie\fP.
+The function
+\f(CWdwarf_siblingof()\fP can be used with the return value of
+\f(CWdwarf_child()\fP to access the other children of \f(CWdie\fP.
+
+.in +2
+.DS
+\f(CWDwarf_Die return_kid = 0;
+Dwarf_Error error = 0;
+int res;
+
+res = dwarf_child(dbg,in_die,&return_kid, &error);
+if (res == DW_DLV_OK) {
+ /* Use return_kid here. */
+ dwarf_dealloc(dbg, return_kid, DW_DLA_DIE);
+ /* return_die is no longer usable for anything, we
+ ensure we do not use it accidentally with: */
+ return_kid = 0;
+}\fP
+.DE
+.in -2
+
+.H 3 "dwarf_offdie_b()"
+.DS
+\f(CWint dwarf_offdie_b(
+ Dwarf_Debug dbg,
+ Dwarf_Off offset,
+ Dwarf_Bool is_info,
+ Dwarf_Die *return_die,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_offdie_b()\fP
+returns \f(CWDW_DLV_ERROR\fP and sets the \f(CWerror\fP die on error.
+When it succeeds,
+\f(CWdwarf_offdie_b()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_die\fP
+to the
+the \f(CWDwarf_Die\fP
+descriptor of the debugging information entry at \f(CWoffset\fP in
+the section containing debugging information entries i.e the .debug_info
+section.
+A return of \f(CWDW_DLV_NO_ENTRY\fP
+means that the \f(CWoffset\fP in the section is of a byte containing
+all 0 bits, indicating that there
+is no abbreviation code. Meaning this 'die offset' is not
+the offset of a real die, but is instead an offset of a null die,
+a padding die, or of some random zero byte: this should
+not be returned in normal use.
+.P
+It is the user's
+responsibility to make sure that \f(CWoffset\fP is the start of a valid
+debugging information entry. The result of passing it an invalid
+offset could be chaos.
+.P
+If \f(CWis_info\fP is non-zero the \f(CWoffset\fP must refer
+to a .debug_info section offset.
+If \f(CWis_info\fP zero the \f(CWoffset\fP must refer
+to a .debug_types section offset.
+Error returns or misleading
+values may result if the
+\f(CWis_info\fP flag
+or the \f(CWoffset\fP value
+are incorrect.
+
+.in +2
+.DS
+\f(CWDwarf_Error error = 0;
+Dwarf_Die return_die = 0;
+int res;
+
+res = dwarf_offdie_b(dbg,die_offset,&return_die, &error);
+if (res == DW_DLV_OK) {
+ /* Use return_die here. */
+ dwarf_dealloc(dbg, return_die, DW_DLA_DIE);
+ /* return_die is no longer usable for anything, we
+ ensure we do not use it accidentally with: */
+ return_die = 0;
+}\fP
+.DE
+.in -2
+
+.H 3 "dwarf_offdie()"
+.DS
+\f(CWint dwarf_offdie(
+ Dwarf_Debug dbg,
+ Dwarf_Off offset,
+ Dwarf_Die *return_die,
+ Dwarf_Error *error)\fP
+.DE
+.P
+The function \f(CWdwarf_offdie()\fP is obsolete, use
+\f(CWdwarf_offdie_b()\fP instead.
+The function is still supported in the library, but only
+references the .debug_info section.
+
+
+.H 3 "dwarf_validate_die_sibling()"
+.DS
+\f(CWint validate_die_sibling(
+ Dwarf_Die sibling,
+ Dwarf_Off *offset)\fP
+.DE
+When used correctly in a depth-first walk of a DIE tree this
+function validates that any DW_AT_sibling attribute gives
+the same offset as the direct tree walk.
+That is the only purpose of this function.
+
+The function \f(CWdwarf_validate_die_sibling()\fP
+returns \f(CWDW_DLV_OK\fP if the last die processed
+in a depth-first DIE tree walk was the same offset as
+generated by a call to \f(CWdwarf_siblingof()\fP.
+Meaning that the DW_AT_sibling attribute value, if any, was correct.
+
+If the conditions are not met then DW_DLV_ERROR is returned
+and \f(CW*offset\fP is set to the offset
+in the .debug_info section of the last DIE processed.
+If the application prints the offset a knowledgeable
+user may be able to figure out what the compiler did wrong.
+
+.H 2 "Debugging Information Entry Query Operations"
+These queries return specific information about debugging information
+entries or a descriptor that can be used on subsequent queries when
+given a \f(CWDwarf_Die\fP descriptor. Note that some operations are
+specific to debugging information entries that are represented by a
+\f(CWDwarf_Die\fP descriptor of a specific type.
+For example, not all
+debugging information entries contain an attribute having a name, so
+consequently, a call to \f(CWdwarf_diename()\fP using a \f(CWDwarf_Die\fP
+descriptor that does not have a name attribute will return
+\f(CWDW_DLV_NO_ENTRY\fP.
+This is not an error, i.e. calling a function that needs a specific
+attribute is not an error for a die that does not contain that specific
+attribute.
+.P
+There are several methods that can be used to obtain the value of an
+attribute in a given die:
+.AL 1
+.LI
+Call \f(CWdwarf_hasattr()\fP to determine if the debugging information
+entry has the attribute of interest prior to issuing the query for
+information about the attribute.
+
+.LI
+Supply an \f(CWerror\fP argument, and check its value after the call to
+a query indicates an unsuccessful return, to determine the nature of the
+problem. The \f(CWerror\fP argument will indicate whether an error occurred,
+or the specific attribute needed was missing in that die.
+
+.LI
+Arrange to have an error handling function invoked upon detection of an
+error (see \f(CWdwarf_init()\fP).
+
+.LI
+Call \f(CWdwarf_attrlist()\fP and iterate through the returned list of
+attributes, dealing with each one as appropriate.
+.LE
+.P
+
+.H 3 "dwarf_get_die_infotypes_flag()"
+.DS
+\f(CWDwarf_Bool dwarf_get_die_infotypes_flag(Dwarf_Die die)\fP
+.DE
+.P
+The function \f(CWdwarf_tag()\fP returns the section flag
+indicating which section the DIE originates from.
+If the returned value is non-zero the DIE
+originates from the .debug_info section.
+If the returned value is zero the DIE
+originates from the .debug_types section.
+
+.H 3 "dwarf_tag()"
+.DS
+\f(CWint dwarf_tag(
+ Dwarf_Die die,
+ Dwarf_Half *tagval,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_tag()\fP returns the \f(CWtag\fP of \f(CWdie\fP
+through the pointer \f(CWtagval\fP if it succeeds.
+It returns \f(CWDW_DLV_OK\fP if it succeeds.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+
+.H 3 "dwarf_dieoffset()"
+.DS
+\f(CWint dwarf_dieoffset(
+ Dwarf_Die die,
+ Dwarf_Off * return_offset,
+ Dwarf_Error *error)\fP
+.DE
+When it succeeds,
+the function \f(CWdwarf_dieoffset()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_offset\fP
+to the position of \f(CWdie\fP
+in the section containing debugging information entries
+(the \f(CWreturn_offset\fP is a section-relative offset).
+In other words,
+it sets \f(CWreturn_offset\fP
+to the offset of the start of the debugging information entry
+described by \f(CWdie\fP in the section containing dies i.e .debug_info.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+
+.H 3 "dwarf_die_CU_offset()"
+.DS
+\f(CWint dwarf_die_CU_offset(
+ Dwarf_Die die,
+ Dwarf_Off *return_offset,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_die_CU_offset()\fP is similar to
+\f(CWdwarf_dieoffset()\fP, except that it puts the offset of the DIE
+represented by the \f(CWDwarf_Die\fP \f(CWdie\fP, from the
+start of the compilation-unit that it belongs to rather than the start
+of .debug_info (the \f(CWreturn_offset\fP is a CU-relative offset).
+
+.H 3 "dwarf_die_offsets()"
+.DS
+\f(CWint dwarf_die_offsets(
+ Dwarf_Die die,
+ Dwarf_Off *global_off,
+ Dwarf_Off *cu_off,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_die_offsets()\fP is a combination of
+\f(CWdwarf_dieoffset()\fP and \f(CWdwarf_die_cu_offset()\fP
+in that it returns both the global .debug_info offset and
+the CU-relative offset of the \f(CWdie\fP in a single call.
+
+
+.H 3 "dwarf_ptr_CU_offset()"
+.DS
+\f(CWint dwarf_ptr_CU_offset(
+ Dwarf_CU_Context cu_context,
+ Dwarf_Byte_ptr di_ptr ,
+ Dwarf_Off *cu_off)\fP
+.DE
+Given a valid CU context pointer and a pointer into that CU
+context,
+the function \f(CWdwarf_ptr_CU_offset()\fP returns DW_DLV_OK
+and sets \f(CW*cu_off\fP to the CU-relative (local) offset
+in that CU.
+
+
+.H 3 "dwarf_CU_dieoffset_given_die()"
+.DS
+\f(CWint dwarf_CU_dieoffset_given_die(
+ Dwarf_Die given_die,
+ Dwarf_Off *return_offset,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_CU_dieoffset_given_die()\fP is similar to
+\f(CWdwarf_die_CU_offset()\fP, except that it puts the
+global offset of the CU DIE owning \f(CWgiven_die\fP
+of .debug_info (the \f(CWreturn_offset\fP is a global section offset).
+.P
+This is useful when processing a DIE tree and encountering
+an error or other surprise in a DIE, as the \f(CWreturn_offset\fP
+can be passed to \f(CWdwarf_offdie_b()\fP to return a pointer
+to the CU die of the CU owning the \f(CWgiven_die\fP passed
+to \f(CWdwarf_CU_dieoffset_given_die()\fP. The consumer can
+extract information from the CU die and the \f(CWgiven_die\fP
+(in the normal way) and print it.
+
+An example (a snippet) of code using this function
+follows. It assumes that \f(CWin_die\fP is a DIE
+that, for some reason, you have decided needs CU context
+printed (assuming \f(CWprint_die_data\fP
+does some reasonable printing).
+
+.in +2
+.DS
+int res;
+Dwarf_Off cudieoff = 0;
+Dwarf_Die cudie = 0;
+
+print_die_data(dbg,in_die);
+res = dwarf_CU_dieoffset_given_die(in_die,&cudieoff,&error);
+if(res != DW_DLV_OK) {
+ printf("FAIL: dwarf_CU_dieoffset_given_die did not work\n");
+ exit(1);
+}
+res = dwarf_offdie_b(dbg,cudieoff,&cudie,&error);
+if(res != DW_DLV_OK) {
+ printf("FAIL: dwarf_offdie did not work\n");
+ exit(1);
+}
+print_die_data(dbg,cudie);
+dwarf_dealloc(dbg,cudie, DW_DLA_DIE);
+.DE
+.in -2
+
+
+
+.H 3 "dwarf_die_CU_offset_range()"
+.DS
+\f(CWint dwarf_die_CU_offset_range(
+ Dwarf_Die die,
+ Dwarf_Off *cu_global_offset,
+ Dwarf_Off *cu_length,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_die_CU_offset_range()\fP
+returns the offset of the beginning of the CU and the length of the CU.
+The offset and length are of the entire CU that this DIE is
+a part of. It is used by dwarfdump (for example) to check
+the validity of offsets.
+Most applications will have no reason to call this function.
+
+
+.H 3 "dwarf_diename()"
+.DS
+\f(CWint dwarf_diename(
+ Dwarf_Die die,
+ char ** return_name,
+ Dwarf_Error *error)\fP
+.DE
+When it succeeds,
+the function \f(CWdwarf_diename()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_name\fP
+to
+a pointer to a
+null-terminated string of characters that represents the name
+attribute of \f(CWdie\fP.
+It returns \f(CWDW_DLV_NO_ENTRY\fP if \f(CWdie\fP does not have a name attribute.
+It returns \f(CWDW_DLV_ERROR\fP if
+an error occurred.
+The storage pointed to by a successful return of
+\f(CWdwarf_diename()\fP should be freed using the allocation type
+\f(CWDW_DLA_STRING\fP when no longer of interest (see
+\f(CWdwarf_dealloc()\fP).
+
+.H 3 "dwarf_die_abbrev_code()"
+.DS
+\f(CWint dwarf_die_abbrev_code( Dwarf_Die die)\fP
+.DE
+The function returns
+the abbreviation code of the DIE.
+That is, it returns the abbreviation "index"
+into the abbreviation table for the compilation unit
+of which the DIE is a part.
+It cannot fail. No errors are possible.
+The pointer \f(CWdie()\fP must not be NULL.
+
+.H 3 "dwarf_die_abbrev_children_flag()"
+.DS
+\f(CWint dwarf_die_abbrev_children_flag( Dwarf_Die die,
+ Dwarf_Half *has_child)\fP
+.DE
+The function returns the has-children flag of the \f(CWdie\fP
+passed in through the \f(CW*has_child\fP passed in and returns
+\f(CWDW_DLV_OK\fP on success.
+A non-zero value of \f(CW*has_child\fP means the \f(CWdie\fP
+has children.
+
+On failure it returns \f(CWDW_DLV_ERROR\fP.
+
+The function was developed to let
+consumer code do better error reporting
+in some circumstances, it is not generally needed.
+
+
+.H 3 "dwarf_get_version_of_die()"
+.DS
+\f(CWint dwarf_get_version_of_die(Dwarf_Die die,
+ Dwarf_Half *version,
+ Dwarf_Half *offset_size)\fP
+.DE
+The function returns the CU context version through \f(CW*version\fP
+and the CU context offset-size through \f(CW*offset_size\fP and
+returns \f(CWDW_DLV_OK\fP on success.
+
+In case of error, the only errors possible involve
+an inappropriate NULL \f(CWdie\fP pointer so no Dwarf_Debug
+pointer is available. Therefore setting a Dwarf_Error would not
+be very meaningful (there is no Dwarf_Debug to
+attach it to). The function returns DW_DLV_ERROR on error.
+
+The values returned through the pointers are the values
+two arguments to dwarf_get_form_class() requires.
+
+.H 3 "dwarf_attrlist()"
+.DS
+\f(CWint dwarf_attrlist(
+ Dwarf_Die die,
+ Dwarf_Attribute** attrbuf,
+ Dwarf_Signed *attrcount,
+ Dwarf_Error *error)\fP
+.DE
+When it returns \f(CWDW_DLV_OK\fP,
+the function \f(CWdwarf_attrlist()\fP sets \f(CWattrbuf\fP to point
+to an array of \f(CWDwarf_Attribute\fP descriptors corresponding to
+each of the attributes in die, and returns the number of elements in
+the array through \f(CWattrcount\fP.
+\f(CWDW_DLV_NO_ENTRY\fP is returned if the count is zero (no
+\f(CWattrbuf\fP is allocated in this case).
+\f(CWDW_DLV_ERROR\fP is returned on error.
+On a successful return from \f(CWdwarf_attrlist()\fP, each of the
+\f(CWDwarf_Attribute\fP descriptors should be individually freed using
+\f(CWdwarf_dealloc()\fP with the allocation type \f(CWDW_DLA_ATTR\fP,
+followed by free-ing the list pointed to by \f(CW*attrbuf\fP using
+\f(CWdwarf_dealloc()\fP with the allocation type \f(CWDW_DLA_LIST\fP,
+when no longer of interest (see \f(CWdwarf_dealloc()\fP).
+
+Freeing the attrlist:
+.in +2
+.DS
+\f(CWDwarf_Unsigned atcnt;
+Dwarf_Attribute *atlist;
+int errv;
+
+errv = dwarf_attrlist(somedie, &atlist,&atcnt, &error);
+if (errv == DW_DLV_OK) {
+
+ for (i = 0; i < atcnt; ++i) {
+ /* use atlist[i] */
+ dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);
+ }
+ dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
+}\fP
+.DE
+.in -2
+.P
+.H 3 "dwarf_hasattr()"
+.DS
+\f(CWint dwarf_hasattr(
+ Dwarf_Die die,
+ Dwarf_Half attr,
+ Dwarf_Bool *return_bool,
+ Dwarf_Error *error)\fP
+.DE
+When it succeeds, the
+function \f(CWdwarf_hasattr()\fP returns \f(CWDW_DLV_OK\fP
+and sets \f(CW*return_bool\fP to \fInon-zero\fP if
+\f(CWdie\fP has the attribute \f(CWattr\fP and \fIzero\fP otherwise.
+If it fails, it returns \f(CWDW_DLV_ERROR\fP.
+
+.H 3 "dwarf_attr()"
+.DS
+\f(CWint dwarf_attr(
+ Dwarf_Die die,
+ Dwarf_Half attr,
+ Dwarf_Attribute *return_attr,
+ Dwarf_Error *error)\fP
+.DE
+.P
+When it returns \f(CWDW_DLV_OK\fP,
+the function \f(CWdwarf_attr()\fP
+sets
+\f(CW*return_attr\fP to the \f(CWDwarf_Attribute\fP
+descriptor of \f(CWdie\fP having the attribute \f(CWattr\fP.
+It returns \f(CWDW_DLV_NO_ENTRY\fP if \f(CWattr\fP is not contained
+in \f(CWdie\fP.
+It returns \f(CWDW_DLV_ERROR\fP if an error occurred.
+
+
+.H 3 "dwarf_lowpc()"
+.DS
+\f(CWint dwarf_lowpc(
+ Dwarf_Die die,
+ Dwarf_Addr * return_lowpc,
+ Dwarf_Error * error)\fP
+.DE
+The function \f(CWdwarf_lowpc()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_lowpc\fP
+to the low program counter
+value associated with the \f(CWdie\fP descriptor if \f(CWdie\fP
+represents a debugging information entry with this attribute.
+It returns \f(CWDW_DLV_NO_ENTRY\fP if \f(CWdie\fP does not have this
+attribute.
+It returns \f(CWDW_DLV_ERROR\fP if an error occurred.
+
+.H 3 "dwarf_highpc()"
+.DS
+\f(CWint dwarf_highpc(
+ Dwarf_Die die,
+ Dwarf_Addr * return_highpc,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_highpc()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_highpc\fP
+the high program counter
+value associated with the \f(CWdie\fP descriptor if \f(CWdie\fP
+represents a debugging information entry with this attribute.
+It returns \f(CWDW_DLV_NO_ENTRY\fP if \f(CWdie\fP does not have this
+attribute.
+It returns \f(CWDW_DLV_ERROR\fP if an error occurred.
+
+.H 3 "dwarf_bytesize()"
+.DS
+\f(CWDwarf_Signed dwarf_bytesize(
+ Dwarf_Die die,
+ Dwarf_Unsigned *return_size,
+ Dwarf_Error *error)\fP
+.DE
+When it succeeds,
+\f(CWdwarf_bytesize()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_size\fP
+to the number of bytes
+needed to contain an instance of the aggregate debugging information
+entry represented by \f(CWdie\fP.
+It returns \f(CWDW_DLV_NO_ENTRY\fP if
+\f(CWdie\fP does not contain the byte size attribute \f(CWDW_AT_byte_size\fP.
+It returns \f(CWDW_DLV_ERROR\fP if
+an error occurred.
+
+.\"#if 0
+.\".DS
+.\"\f(CWDwarf_Bool dwarf_isbitfield(
+.\" Dwarf_Die die,
+.\" Dwarf_Error *error)\fP
+.\".DE
+.\"The function \f(CWdwarf_isbitfield()\fP returns \fInon-zero\fP if
+.\"\f(CWdie\fP is a descriptor for a debugging information entry that
+.\"represents a bit field member. It returns \fIzero\fP if \f(CWdie\fP
+.\"is not associated with a bit field member. This function is currently
+.\"unimplemented.
+.\"#endif
+
+.H 3 "dwarf_bitsize()"
+.DS
+\f(CWint dwarf_bitsize(
+ Dwarf_Die die,
+ Dwarf_Unsigned *return_size,
+ Dwarf_Error *error)\fP
+.DE
+When it succeeds,
+\f(CWdwarf_bitsize()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_size\fP
+to the number of
+bits
+occupied by the bit field value that is an attribute of the given
+die.
+It returns \f(CWDW_DLV_NO_ENTRY\fP if \f(CWdie\fP does not
+contain the bit size attribute \f(CWDW_AT_bit_size\fP.
+It returns \f(CWDW_DLV_ERROR\fP if
+an error occurred.
+
+.H 3 "dwarf_bitoffset()"
+.DS
+\f(CWint dwarf_bitoffset(
+ Dwarf_Die die,
+ Dwarf_Unsigned *return_size,
+ Dwarf_Error *error)\fP
+.DE
+When it succeeds,
+\f(CWdwarf_bitoffset()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_size\fP
+to the number of bits
+to the left of the most significant bit of the bit field value.
+This bit offset is not necessarily the net bit offset within the
+structure or class , since \f(CWDW_AT_data_member_location\fP
+may give a byte offset to this \f(CWDIE\fP and the bit offset
+returned through the pointer
+does not include the bits in the byte offset.
+It returns \f(CWDW_DLV_NO_ENTRY\fP if \f(CWdie\fP does not contain the
+bit offset attribute \f(CWDW_AT_bit_offset\fP.
+It returns \f(CWDW_DLV_ERROR\fP if
+an error occurred.
+
+.H 3 "dwarf_srclang()"
+.DS
+\f(CWint dwarf_srclang(
+ Dwarf_Die die,
+ Dwarf_Unsigned *return_lang,
+ Dwarf_Error *error)\fP
+.DE
+When it succeeds,
+\f(CWdwarf_srclang()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_lang\fP
+to
+a code indicating the
+source language of the compilation unit represented by the descriptor
+\f(CWdie\fP.
+It returns \f(CWDW_DLV_NO_ENTRY\fP if \f(CWdie\fP does not
+represent a source file debugging information entry (i.e. contain the
+attribute \f(CWDW_AT_language\fP).
+It returns \f(CWDW_DLV_ERROR\fP if
+an error occurred.
+
+.H 3 "dwarf_arrayorder()"
+.DS
+\f(CWint dwarf_arrayorder(
+ Dwarf_Die die,
+ Dwarf_Unsigned *return_order,
+ Dwarf_Error *error)\fP
+.DE
+When it succeeds,
+\f(CWdwarf_arrayorder()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_order\fP
+a code indicating
+the ordering of the array represented by the descriptor \f(CWdie\fP.
+It returns \f(CWDW_DLV_NO_ENTRY\fP if \f(CWdie\fP does not contain the
+array order attribute \f(CWDW_AT_ordering\fP.
+It returns \f(CWDW_DLV_ERROR\fP if
+an error occurred.
+
+.H 2 "Attribute Queries"
+Based on the attributes form, these operations are concerned with
+returning uninterpreted attribute data. Since it is not always
+obvious from the return value of these functions if an error occurred,
+one should always supply an \f(CWerror\fP parameter or have arranged
+to have an error handling function invoked (see \f(CWdwarf_init()\fP)
+to determine the validity of the returned value and the nature of any
+errors that may have occurred.
+
+A \f(CWDwarf_Attribute\fP descriptor describes an attribute of a
+specific die. Thus, each \f(CWDwarf_Attribute\fP descriptor is
+implicitly associated with a specific die.
+
+.H 3 "dwarf_hasform()"
+.DS
+\f(CWint dwarf_hasform(
+ Dwarf_Attribute attr,
+ Dwarf_Half form,
+ Dwarf_Bool *return_hasform,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_hasform()\fP returns
+\f(CWDW_DLV_OK\fP and and puts a
+\fInon-zero\fP
+ value in the
+\f(CW*return_hasform\fP boolean if the
+attribute represented by the \f(CWDwarf_Attribute\fP descriptor
+\f(CWattr\fP has the attribute form \f(CWform\fP.
+If the attribute does not have that form \fIzero\fP
+is put into \f(CW*return_hasform\fP.
+\f(CWDW_DLV_ERROR\fP is returned on error.
+
+.H 3 "dwarf_whatform()"
+.DS
+\f(CWint dwarf_whatform(
+ Dwarf_Attribute attr,
+ Dwarf_Half *return_form,
+ Dwarf_Error *error)\fP
+.DE
+When it succeeds,
+\f(CWdwarf_whatform()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_form\fP
+to the attribute form code of
+the attribute represented by the \f(CWDwarf_Attribute\fP descriptor
+\f(CWattr\fP.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+An attribute using DW_FORM_indirect effectively has two forms.
+This function returns the 'final' form for \f(CWDW_FORM_indirect\fP,
+not the \f(CWDW_FORM_indirect\fP itself. This function is
+what most applications will want to call.
+
+.H 3 "dwarf_whatform_direct()"
+.DS
+\f(CWint dwarf_whatform_direct(
+ Dwarf_Attribute attr,
+ Dwarf_Half *return_form,
+ Dwarf_Error *error)\fP
+.DE
+When it succeeds,
+\f(CWdwarf_whatform_direct()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_form\fP
+to the attribute form code of
+the attribute represented by the \f(CWDwarf_Attribute\fP descriptor
+\f(CWattr\fP.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+An attribute using \f(CWDW_FORM_indirect\fP effectively has two forms.
+This returns the form 'directly' in the initial form field.
+So when the form field is \f(CWDW_FORM_indirect\fP
+this call returns the \f(CWDW_FORM_indirect\fP form,
+which is sometimes useful for dump utilities.
+
+.H 3 "dwarf_whatattr()"
+.DS
+\f(CWint dwarf_whatattr(
+ Dwarf_Attribute attr,
+ Dwarf_Half *return_attr,
+ Dwarf_Error *error)\fP
+.DE
+When it succeeds,
+\f(CWdwarf_whatattr()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_attr\fP
+to the attribute code
+represented by the \f(CWDwarf_Attribute\fP descriptor \f(CWattr\fP.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+
+.H 3 "dwarf_formref()"
+.DS
+\f(CWint dwarf_formref(
+ Dwarf_Attribute attr,
+ Dwarf_Off *return_offset,
+ Dwarf_Error *error)\fP
+.DE
+When it succeeds,
+\f(CWdwarf_formref()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_offset\fP
+to the CU-relative offset
+represented by the descriptor \f(CWattr\fP if the form of the attribute
+belongs to the \f(CWREFERENCE\fP class.
+\f(CWattr\fP must be a CU-local reference,
+not form \f(CWDW_FORM_ref_addr\fP and not \f(CWDW_FORM_sec_offset\fP .
+It is an error for the form to
+not belong to the \f(CWREFERENCE\fP class.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+
+Beginning November 2010:
+All \f(CWDW_DLV_ERROR\fP returns set \f(CW*return_offset\fP. Most
+errors set \f(CW*return_offset\fP to zero, but
+for error \f(CWDW_DLE_ATTR_FORM_OFFSET_BAD\fP
+the function sets \f(CW*return_offset\fP to the invalid
+offset (which allows the caller to print a more
+detailed error message).
+
+See also \f(CWdwarf_global_formref\fP below.
+
+
+.H 3 "dwarf_global_formref()"
+.DS
+\f(CWint dwarf_global_formref(
+ Dwarf_Attribute attr,
+ Dwarf_Off *return_offset,
+ Dwarf_Error *error)\fP
+.DE
+When it succeeds,
+\f(CWdwarf_global_formref()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_offset\fP
+to the section-relative offset
+represented by the descriptor \f(CWattr\fP if the form of the attribute
+belongs to the \f(CWREFERENCE\fP or other section-references classes.
+.P
+\f(CWattr\fP can be any legal
+\f(CWREFERENCE\fP class form plus \f(CWDW_FORM_ref_addr\fP or
+\f(CWDW_FORM_sec_offset\fP.
+It is an error for the form to
+not belong to one of the reference classes.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+See also \f(CWdwarf_formref\fP above.
+.P
+The caller must determine which section the offset returned applies to.
+The function \f(CWdwarf_get_form_class()\fP is useful to determine
+the applicable section.
+.P
+The function converts CU relative offsets from forms
+such as DW_FORM_ref4 into
+global section offsets.
+
+.H 3 "dwarf_convert_to_global_offset()"
+.DS
+\f(CWint dwarf_convert_to_global_offset(
+ Dwarf_Attribute attr,
+ Dwarf_Off offset,
+ Dwarf_Off *return_offset,
+ Dwarf_Error *error)\fP
+.DE
+When it succeeds,
+\f(CWdwarf_convert_to_global_offset()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_offset\fP
+to the section-relative offset
+represented by the cu-relative offset \f(CWoffset\fP
+if the form of the attribute
+belongs to the \f(CWREFERENCE\fP class.
+\f(CWattr\fP must be a CU-local reference (DWARF class REFERENCE)
+or form \f(CWDW_FORM_ref_addr\fP and the \f(CWattr\fP
+must be directly relevant for the calculated \f(CW*return_offset\fP
+to mean anything.
+
+The function returns \f(CWDW_DLV_ERROR\fP on error.
+
+The function is not strictly necessary but may be a
+convenience for attribute printing in case of error.
+
+
+.H 3 "dwarf_formaddr()"
+.DS
+\f(CWint dwarf_formaddr(
+ Dwarf_Attribute attr,
+ Dwarf_Addr * return_addr,
+ Dwarf_Error *error)\fP
+.DE
+When it succeeds,
+\f(CWdwarf_formaddr()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_addr\fP
+to
+the address
+represented by the descriptor \f(CWattr\fP if the form of the attribute
+belongs to the \f(CWADDRESS\fP class.
+It is an error for the form to
+not belong to this class.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+
+.H 3 "dwarf_formflag()"
+.DS
+\f(CWint dwarf_formflag(
+ Dwarf_Attribute attr,
+ Dwarf_Bool * return_bool,
+ Dwarf_Error *error)\fP
+.DE
+When it succeeds,
+\f(CWdwarf_formflag()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_bool\fP
+\f(CW1\fP (i.e. true) (if the attribute has a non-zero value)
+or \f(CW0\fP (i.e. false) (if the attribute has a zero value).
+It returns \f(CWDW_DLV_ERROR\fP on error or if the \f(CWattr\fP
+does not have form flag.
+
+.H 3 "dwarf_formudata()"
+.DS
+\f(CWint dwarf_formudata(
+ Dwarf_Attribute attr,
+ Dwarf_Unsigned * return_uvalue,
+ Dwarf_Error * error)\fP
+.DE
+The function
+\f(CWdwarf_formudata()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_uvalue\fP
+to
+the \f(CWDwarf_Unsigned\fP
+value of the attribute represented by the descriptor \f(CWattr\fP if the
+form of the attribute belongs to the \f(CWCONSTANT\fP class.
+It is an
+error for the form to not belong to this class.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+
+Never returns \f(CWDW_DLV_NO_ENTRY\fP.
+
+For DWARF2 and DWARF3, \f(CWDW_FORM_data4\fP and \f(CWDW_FORM_data8\fP
+are possibly class \f(CWCONSTANT\fP,
+and for DWARF4 and later they
+are definitely class \f(CWCONSTANT\fP.
+
+.H 3 "dwarf_formsdata()"
+.DS
+\f(CWint dwarf_formsdata(
+ Dwarf_Attribute attr,
+ Dwarf_Signed * return_svalue,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_formsdata()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_svalue\fP
+to
+the \f(CWDwarf_Signed\fP
+value of the attribute represented by the descriptor \f(CWattr\fP if the
+form of the attribute belongs to the \f(CWCONSTANT\fP class.
+It is an
+error for the form to not belong to this class.
+If the size of the data
+attribute referenced is smaller than the size of the \f(CWDwarf_Signed\fP
+type, its value is sign extended.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+
+Never returns \f(CWDW_DLV_NO_ENTRY\fP.
+
+For DWARF2 and DWARF3, \f(CWDW_FORM_data4\fP and \f(CWDW_FORM_data8\fP
+are possibly class \f(CWCONSTANT\fP,
+and for DWARF4 and later they
+are definitely class \f(CWCONSTANT\fP.
+
+.H 3 "dwarf_formblock()"
+.DS
+\f(CWint dwarf_formblock(
+ Dwarf_Attribute attr,
+ Dwarf_Block ** return_block,
+ Dwarf_Error * error)\fP
+.DE
+The function \f(CWdwarf_formblock()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_block\fP
+to
+a pointer to a
+\f(CWDwarf_Block\fP structure containing the value of the attribute
+represented by the descriptor \f(CWattr\fP if the form of the
+attribute belongs to the \f(CWBLOCK\fP class.
+It is an error
+for the form to not belong to this class.
+The storage pointed
+to by a successful return of \f(CWdwarf_formblock()\fP should
+be freed using the allocation type \f(CWDW_DLA_BLOCK\fP, when
+no longer of interest (see \f(CWdwarf_dealloc()\fP).
+It returns
+\f(CWDW_DLV_ERROR\fP on error.
+
+
+.H 3 "dwarf_formstring()"
+
+.DS
+\f(CWint dwarf_formstring(
+ Dwarf_Attribute attr,
+ char ** return_string,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_formstring()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_string\fP
+to
+a pointer to a
+null-terminated string containing the value of the attribute
+represented by the descriptor \f(CWattr\fP if the form of the
+attribute belongs to the \f(CWSTRING\fP class.
+It is an error
+for the form to not belong to this class.
+The storage pointed
+to by a successful return of \f(CWdwarf_formstring()\fP
+should not be freed. The pointer points into
+existing DWARF memory and the pointer becomes stale/invalid
+after a call to \f(CWdwarf_finish\fP.
+\f(CWdwarf_formstring()\fP returns \f(CWDW_DLV_ERROR\fP on error.
+
+.H 3 "dwarf_formsig8()"
+.DS
+\f(CWint dwarf_formsig8(
+ Dwarf_Attribute attr,
+ Dwarf_Sig8 * return_sig8,
+ Dwarf_Error * error)\fP
+.DE
+The function \f(CWdwarf_formsig8()\fP returns
+\f(CWDW_DLV_OK\fP and copies the 8 byte signature
+to a \f(CWDwarf_Sig8\fP structure provided by the caller
+if the form of the
+attribute is of form \f(CWDW_FORM_ref_sig8\fP
+( a member of the \f(CWREFERENCE\fP class).
+It is an error
+for the form to be anything but \f(CWDW_FORM_ref_sig8\fP.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+.P
+This form is used to refer to a type unit.
+
+.H 3 "dwarf_formsig8()"
+.DS
+\f(CWint dwarf_formexprloc(
+ Dwarf_Attribute attr,
+ Dwarf_Unsigned * return_exprlen,
+ Dwarf_Ptr * block_ptr,
+ Dwarf_Error * error)\fP
+.DE
+The function \f(CWdwarf_formexprloc()\fP returns
+\f(CWDW_DLV_OK\fP and sets the two values thru the pointers
+to the length and bytes of the DW_FORM_exprloc entry
+if the form of the
+attribute is of form \f(CWDW_FORM_experloc\fP.
+It is an error
+for the form to be anything but \f(CWDW_FORM_exprloc\fP.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+.P
+On success the value set through the
+\f(CWreturn_exprlen\fP pointer is the length
+of the location expression.
+On success the value set through the
+\f(CWblock_ptr\fP pointer is a pointer to
+the bytes of the location expression itself.
+
+.H 3 "dwarf_get_form_class()"
+.DS
+\f(CWenum Dwarf_Form_Class dwarf_get_form_class(
+ Dwarf_Half dwversion,
+ Dwarf_Half attrnum,
+ Dwarf_Half offset_size,
+ Dwarf_Half form)\fP
+.DE
+.P
+The function is just for the convenience
+of libdwarf clients that might wish to categorize
+the FORM of a particular attribute.
+The DWARF specification divides FORMs into classes
+in Chapter 7 and this function figures out the correct
+class for a form.
+.P
+The \f(CWdwversion\fP passed in shall be the dwarf version
+of the compilation unit involved (2 for DWARF2, 3 for
+DWARF3, 4 for DWARF 4).
+The \f(CWattrnum\fP passed in shall be the attribute
+number of the attribute involved (for example, \f(CWDW_AT_name\fP ).
+The \f(CWoffset_size\fP passed in shall be the
+length of an offset in the current compilation unit
+(4 for 32bit dwarf or 8 for 64bit dwarf).
+The \f(CWform\fP passed in shall be the attribute form number.
+If \f(CWform\fP \f(CWDW_FORM_indirect\fP
+is passed in \f(CWDW_FORM_CLASS_UNKNOWN\fP will be returned
+as this form has no defined 'class'.
+.P
+When it returns \f(CWDW_FORM_CLASS_UNKNOWN\fP the
+function is simply saying it could not determine the
+correct class given the arguments
+presented. Some user-defined
+attributes might have this problem.
+
+The function \f(CWdwarf_get_version_of_die()\fP may be helpful
+in filling out arguments for a call to \f(CWdwarf_get_form_class()\fP.
+
+.H 3 "dwarf_loclist_n()"
+.DS
+\f(CWint dwarf_loclist_n(
+ Dwarf_Attribute attr,
+ Dwarf_Locdesc ***llbuf,
+ Dwarf_Signed *listlen,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_loclist_n()\fP sets \f(CW*llbuf\fP to point to
+an array of \f(CWDwarf_Locdesc\fP pointers corresponding to each of
+the location expressions in a location list, and sets
+\f(CW*listlen\fP to the number
+of elements in the array and
+returns \f(CWDW_DLV_OK\fP if the attribute is
+appropriate.
+.P
+This is the preferred function for Dwarf_Locdesc as
+it is the interface allowing access to an entire
+loclist. (use of \f(CWdwarf_loclist_n()\fP is
+suggested as the better interface, though
+\f(CWdwarf_loclist()\fP is still
+supported.)
+.P
+If the attribute is a reference to a location list
+(DW_FORM_data4 or DW_FORM_data8)
+the location list entries are used to fill
+in all the fields of the \f(CWDwarf_Locdesc\fP(s) returned.
+.P
+If the attribute is a location description
+(DW_FORM_block2 or DW_FORM_block4)
+then some of the \f(CWDwarf_Locdesc\fP values of the single
+\f(CWDwarf_Locdesc\fP record are set to 'sensible'
+but arbitrary values. Specifically, ld_lopc is set to 0 and
+ld_hipc is set to all-bits-on. And \f(CW*listlen\fP is set to 1.
+.P
+It returns \f(CWDW_DLV_ERROR\fP on error.
+.P
+\f(CWdwarf_loclist_n()\fP works on \f(CWDW_AT_location\fP,
+\f(CWDW_AT_data_member_location\fP, \f(CWDW_AT_vtable_elem_location\fP,
+\f(CWDW_AT_string_length\fP, \f(CWDW_AT_use_location\fP, and
+\f(CWDW_AT_return_addr\fP attributes.
+.P
+If the attribute is \f(CWDW_AT_data_member_location\fP the value
+may be of class CONSTANT. \f(CWdwarf_loclist_n()\fP is unable
+to read class CONSTANT, so you need to first determine the
+class using \f(CWdwarf_get_form_class()\fP and if it is
+class CONSTANT call
+\f(CWdwarf_formsdata()\fP or \f(CWdwarf_formudata()\fP
+to get the constant value (you may need to call both as
+DWARF4 does not define the signedness of the constant value).
+.P
+Storage allocated by a successful call of \f(CWdwarf_loclist_n()\fP should
+be deallocated when no longer of interest (see \f(CWdwarf_dealloc()\fP).
+The block of \f(CWDwarf_Loc\fP structs pointed to by the \f(CWld_s\fP
+field of each \f(CWDwarf_Locdesc\fP structure
+should be deallocated with the allocation type
+\f(CWDW_DLA_LOC_BLOCK\fP.
+and the \f(CWllbuf[]\fP space pointed to should be deallocated with
+allocation type \f(CWDW_DLA_LOCDESC\fP.
+This should be followed by deallocation of the \f(CWllbuf\fP
+using the allocation type \f(CWDW_DLA_LIST\fP.
+.in +2
+.DS
+\f(CWDwarf_Signed lcnt;
+Dwarf_Locdesc **llbuf;
+int lres;
+
+lres = dwarf_loclist_n(someattr, &llbuf,&lcnt &error);
+if (lres == DW_DLV_OK) {
+ for (i = 0; i < lcnt; ++i) {
+ /* use llbuf[i] */
+
+ dwarf_dealloc(dbg, llbuf[i]->ld_s, DW_DLA_LOC_BLOCK);
+ dwarf_dealloc(dbg,llbuf[i], DW_DLA_LOCDESC);
+ }
+ dwarf_dealloc(dbg, llbuf, DW_DLA_LIST);
+}\fP
+.DE
+.in -2
+.P
+
+.H 3 "dwarf_loclist()"
+.DS
+\f(CWint dwarf_loclist(
+ Dwarf_Attribute attr,
+ Dwarf_Locdesc **llbuf,
+ Dwarf_Signed *listlen,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_loclist()\fP sets \f(CW*llbuf\fP to point to
+a \f(CWDwarf_Locdesc\fP pointer for the single location expression
+it can return.
+It sets
+\f(CW*listlen\fP to 1.
+and returns \f(CWDW_DLV_OK\fP
+if the attribute is
+appropriate.
+.P
+It is less flexible than \f(CWdwarf_loclist_n()\fP in that
+\f(CWdwarf_loclist()\fP can handle a maximum of one
+location expression, not a full location list.
+If a location-list is present it returns only
+the first location-list entry location description.
+Use \f(CWdwarf_loclist_n()\fP instead.
+.P
+It returns \f(CWDW_DLV_ERROR\fP on error.
+\f(CWdwarf_loclist()\fP works on \f(CWDW_AT_location\fP,
+\f(CWDW_AT_data_member_location\fP, \f(CWDW_AT_vtable_elem_location\fP,
+\f(CWDW_AT_string_length\fP, \f(CWDW_AT_use_location\fP, and
+\f(CWDW_AT_return_addr\fP attributes.
+.P
+Storage allocated by a successful call of \f(CWdwarf_loclist()\fP should
+be deallocated when no longer of interest (see \f(CWdwarf_dealloc()\fP).
+The block of \f(CWDwarf_Loc\fP structs pointed to by the \f(CWld_s\fP
+field of each \f(CWDwarf_Locdesc\fP structure
+should be deallocated with the allocation type \f(CWDW_DLA_LOC_BLOCK\fP.
+This should be followed by deallocation of the \f(CWllbuf\fP
+using the allocation type \f(CWDW_DLA_LOCDESC\fP.
+.in +2
+.DS
+\f(CWDwarf_Signed lcnt;
+Dwarf_Locdesc *llbuf;
+int lres;
+
+lres = dwarf_loclist(someattr, &llbuf,&lcnt,&error);
+if (lres == DW_DLV_OK) {
+ /* lcnt is always 1, (and has always been 1) */ */
+
+ /* Use llbuf here. */
+
+
+ dwarf_dealloc(dbg, llbuf->ld_s, DW_DLA_LOC_BLOCK);
+ dwarf_dealloc(dbg, llbuf, DW_DLA_LOCDESC);
+/* Earlier version.
+* for (i = 0; i < lcnt; ++i) {
+* /* use llbuf[i] */
+*
+* /* Deallocate Dwarf_Loc block of llbuf[i] */
+* dwarf_dealloc(dbg, llbuf[i].ld_s, DW_DLA_LOC_BLOCK);
+* }
+* dwarf_dealloc(dbg, llbuf, DW_DLA_LOCDESC);
+*/
+
+}\fP
+.DE
+.in -2
+.P
+
+.H 3 "dwarf_loclist_from_expr()"
+.DS
+\f(CWint dwarf_loclist_from_expr(
+ Dwarf_Ptr bytes_in,
+ Dwarf_Unsigned bytes_len,
+ Dwarf_Locdesc **llbuf,
+ Dwarf_Signed *listlen,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_loclist_from_expr()\fP sets \f(CW*llbuf\fP to point to
+a \f(CWDwarf_Locdesc\fP pointer for the single location expression
+which is pointed to by \f(CW*bytes_in\fP (whose length is
+\f(CW*bytes_len\fP).
+It sets
+\f(CW*listlen\fP to 1.
+and returns \f(CWDW_DLV_OK\fP
+if decoding is successful.
+Some sources of bytes of expressions are dwarf expressions
+in frame operations like \f(CWDW_CFA_def_cfa_expression\fP,
+\f(CWDW_CFA_expression\fP, and \f(CWDW_CFA_val_expression\fP.
+.P
+Any address_size data in the location expression is assumed
+to be the same size as the default address_size for the object
+being read (normally 4 or 8).
+.P
+It returns \f(CWDW_DLV_ERROR\fP on error.
+.P
+Storage allocated by a successful call of \f(CWdwarf_loclist_from_expr()\fP should
+be deallocated when no longer of interest (see \f(CWdwarf_dealloc()\fP).
+The block of \f(CWDwarf_Loc\fP structs pointed to by the \f(CWld_s\fP
+field of each \f(CWDwarf_Locdesc\fP structure
+should be deallocated with the allocation type \f(CWDW_DLA_LOC_BLOCK\fP.
+This should be followed by deallocation of the \f(CWllbuf\fP
+using the allocation type \f(CWDW_DLA_LOCDESC\fP.
+.in +2
+.DS
+\f(CWDwarf_Signed lcnt;
+Dwarf_Locdesc *llbuf;
+int lres;
+/* Example with an empty buffer here. */
+Dwarf_Ptr data = "";
+Dwarf_Unsigned len = 0;
+
+lres = dwarf_loclist_from_expr(data,len, &llbuf,&lcnt, &error);
+if (lres == DW_DLV_OK) {
+ /* lcnt is always 1 */
+
+ /* Use llbuf here.*/
+
+ dwarf_dealloc(dbg, llbuf->ld_s, DW_DLA_LOC_BLOCK);
+ dwarf_dealloc(dbg, llbuf, DW_DLA_LOCDESC);
+
+}\fP
+.DE
+.in -2
+.P
+
+.H 3 "dwarf_loclist_from_expr_a()"
+.DS
+\f(CWint dwarf_loclist_from_expr_a(
+ Dwarf_Ptr bytes_in,
+ Dwarf_Unsigned bytes_len,
+ Dwarf_Half addr_size,
+ Dwarf_Locdesc **llbuf,
+ Dwarf_Signed *listlen,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_loclist_from_expr_a()\fP
+is identical to \f(CWdwarf_loclist_from_expr()\fP
+in every way except that the caller passes the additional argument
+\f(CWaddr_size\fP containing the address size (normally 4 or 8)
+applying this location expression.
+.P
+The \f(CWaddr_size\fP argument (added 27April2009) is needed
+to correctly interpret frame information as different compilation
+units can have different address sizes.
+DWARF4 adds address_size to the CIE header.
+
+.P
+.H 2 "Line Number Operations"
+These functions are concerned with accessing line number entries,
+mapping debugging information entry objects to their corresponding
+source lines, and providing a mechanism for obtaining information
+about line number entries. Although, the interface talks of "lines"
+what is really meant is "statements". In case there is more than
+one statement on the same line, there will be at least one descriptor
+per statement, all with the same line number. If column number is
+also being represented they will have the column numbers of the start
+of the statements also represented.
+.P
+There can also be more than one Dwarf_Line per statement.
+For example, if a file is preprocessed by a language translator,
+this could result in translator output showing 2 or more sets of line
+numbers per translated line of output.
+
+.H 3 "Get A Set of Lines"
+The function returns information about every source line for a
+particular compilation-unit.
+The compilation-unit is specified
+by the corresponding die.
+.H 4 "dwarf_srclines()"
+.DS
+\f(CWint dwarf_srclines(
+ Dwarf_Die die,
+ Dwarf_Line **linebuf,
+ Dwarf_Signed *linecount,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_srclines()\fP places all line number descriptors
+for a single compilation unit into a single block, sets \f(CW*linebuf\fP
+to point to that block,
+sets \f(CW*linecount\fP to the number of descriptors in this block
+and returns \f(CWDW_DLV_OK\fP.
+The compilation-unit is indicated by the given \f(CWdie\fP which must be
+a compilation-unit die.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+On
+successful return, line number information
+should be freed using \f(CWdwarf_srclines_dealloc()\fP
+when no longer of interest.
+.P
+.in +2
+.DS
+\f(CWDwarf_Signed cnt;
+Dwarf_Line *linebuf;
+int sres;
+
+sres = dwarf_srclines(somedie, &linebuf,&cnt, &error);
+if (sres == DW_DLV_OK) {
+ for (i = 0; i < cnt; ++i) {
+ /* use linebuf[i] */
+ }
+ dwarf_srclines_dealloc(dbg, linebuf, cnt);
+}\fP
+.DE
+
+.in -2
+.P
+The following dealloc code (the only documented method before July 2005)
+still works, but does not completely free all data allocated.
+The \f(CWdwarf_srclines_dealloc()\fP routine was created
+to fix the problem of incomplete deallocation.
+.P
+.in +2
+.DS
+\f(CWDwarf_Signed cnt;
+Dwarf_Line *linebuf;
+int sres;
+
+sres = dwarf_srclines(somedie, &linebuf,&cnt, &error);
+if (sres == DW_DLV_OK) {
+ for (i = 0; i < cnt; ++i) {
+ /* use linebuf[i] */
+ dwarf_dealloc(dbg, linebuf[i], DW_DLA_LINE);
+ }
+ dwarf_dealloc(dbg, linebuf, DW_DLA_LIST);
+}\fP
+.DE
+.in -2
+
+.H 3 "Get the set of Source File Names"
+
+The function returns the names of the source files that have contributed
+to the compilation-unit represented by the given DIE. Only the source
+files named in the statement program prologue are returned.
+
+
+.DS
+\f(CWint dwarf_srcfiles(
+ Dwarf_Die die,
+ char ***srcfiles,
+ Dwarf_Signed *srccount,
+ Dwarf_Error *error)\fP
+.DE
+When it succeeds
+\f(CWdwarf_srcfiles()\fP returns
+\f(CWDW_DLV_OK\fP
+and
+puts
+the number of source
+files named in the statement program prologue indicated by the given
+\f(CWdie\fP
+into \f(CW*srccount\fP.
+Source files defined in the statement program are ignored.
+The given \f(CWdie\fP should have the tag
+\f(CWDW_TAG_compile_unit\fP,
+\f(CWDW_TAG_partial_unit\fP,
+or \f(CWDW_TAG_type_unit\fP
+.
+The location pointed to by \f(CWsrcfiles\fP is set to point to a list
+of pointers to null-terminated strings that name the source
+files.
+On a successful return from this function, each of the
+strings returned should be individually freed using \f(CWdwarf_dealloc()\fP
+with the allocation type \f(CWDW_DLA_STRING\fP when no longer of
+interest.
+This should be followed by free-ing the list using
+\f(CWdwarf_dealloc()\fP with the allocation type \f(CWDW_DLA_LIST\fP.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It returns \f(CWDW_DLV_NO_ENTRY\fP
+if there is no
+corresponding statement program (i.e., if there is no line information).
+.in +2
+.DS
+\f(CWDwarf_Signed cnt;
+char **srcfiles;
+int res;
+
+res = dwarf_srcfiles(somedie, &srcfiles,&cnt &error);
+if (res == DW_DLV_OK) {
+
+ for (i = 0; i < cnt; ++i) {
+ /* use srcfiles[i] */
+ dwarf_dealloc(dbg, srcfiles[i], DW_DLA_STRING);
+ }
+ dwarf_dealloc(dbg, srcfiles, DW_DLA_LIST);
+}\fP
+.DE
+.in -2
+.H 3 "Get information about a Single Table Line"
+The following functions can be used on the \f(CWDwarf_Line\fP descriptors
+returned by \f(CWdwarf_srclines()\fP to obtain information about the
+source lines.
+
+.H 4 "dwarf_linebeginstatement()"
+.DS
+\f(CWint dwarf_linebeginstatement(
+ Dwarf_Line line,
+ Dwarf_Bool *return_bool,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_linebeginstatement()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_bool\fP
+to
+\fInon-zero\fP
+(if \f(CWline\fP represents a line number entry that is marked as
+beginning a statement).
+or
+\fIzero\fP ((if \f(CWline\fP represents a line number entry
+that is not marked as beginning a statement).
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+
+.P
+.H 4 "dwarf_lineendsequence()"
+.DS
+\f(CWint dwarf_lineendsequence(
+ Dwarf_Line line,
+ Dwarf_Bool *return_bool,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_lineendsequence()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_bool\fP
+\fInon-zero\fP
+(in which case
+\f(CWline\fP represents a line number entry that is marked as
+ending a text sequence)
+or
+\fIzero\fP (in which case
+\f(CWline\fP represents a line number entry
+that is not marked as ending a text sequence).
+A line number entry that is marked as
+ending a text sequence is an entry with an address
+one beyond the highest address used by the current
+sequence of line table entries (that is, the table entry is
+a DW_LNE_end_sequence entry (see the DWARF specification)).
+.P
+The function \f(CWdwarf_lineendsequence()\fP
+returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+
+.P
+.H 4 "dwarf_lineno()"
+.DS
+\f(CWint dwarf_lineno(
+ Dwarf_Line line,
+ Dwarf_Unsigned * returned_lineno,
+ Dwarf_Error * error)\fP
+.DE
+The function \f(CWdwarf_lineno()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_lineno\fP to
+the source statement line
+number corresponding to the descriptor \f(CWline\fP.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+
+.P
+.H 4 "dwarf_line_srcfileno()"
+.DS
+\f(CWint dwarf_line_srcfileno(
+ Dwarf_Line line,
+ Dwarf_Unsigned * returned_fileno,
+ Dwarf_Error * error)\fP
+.DE
+The function \f(CWdwarf_line_srcfileno()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*returned_fileno\fP to
+the source statement line
+number corresponding to the descriptor \f(CWfile number\fP.
+When the number returned through \f(CW*returned_fileno\fP is zero it means
+the file name is unknown (see the DWARF2/3 line table specification).
+When the number returned through \f(CW*returned_fileno\fP is non-zero
+it is a file number:
+subtract 1 from this file number
+to get an
+index into the array of strings returned by \f(CWdwarf_srcfiles()\fP
+(verify the resulting index is in range for the array of strings
+before indexing into the array of strings).
+The file number may exceed the size of
+the array of strings returned by \f(CWdwarf_srcfiles()\fP
+because \f(CWdwarf_srcfiles()\fP does not return files names defined with
+the \f(CWDW_DLE_define_file\fP operator.
+The function \f(CWdwarf_line_srcfileno()\fP returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+
+.P
+.H 4 "dwarf_lineaddr()"
+.DS
+\f(CWint dwarf_lineaddr(
+ Dwarf_Line line,
+ Dwarf_Addr *return_lineaddr,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_lineaddr()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_lineaddr\fP to
+the address associated
+with the descriptor \f(CWline\fP.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+
+.P
+.H 4 "dwarf_lineoff()"
+.DS
+\f(CWint dwarf_lineoff(
+ Dwarf_Line line,
+ Dwarf_Signed * return_lineoff,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_lineoff()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_lineoff\fP to
+the column number at which
+the statement represented by \f(CWline\fP begins.
+.P
+It sets \f(CWreturn_lineoff\fP to zero
+if the column number of the statement is not represented
+(meaning the producer library call was given zero
+as the column number). Zero is the correct value meaning "left edge"
+as defined in the DWARF2/3/4 specication (section 6.2.2).
+.P
+Before December 2011 zero was not returned through
+the \f(CWreturn_lineoff\fP pointer, -1 was returned through the pointer.
+The reason for this oddity is unclear, lost in history.
+But there is no good reason for -1.
+.P
+The type of \f(CWreturn_lineoff\fP is a pointer-to-signed, but there
+is no good reason for the value to be signed, the DWARF specification
+does not deal with negative column numbers. However, changing the
+declaration would cause compilation errors for little benefit, so
+the pointer-to-signed is left unchanged.
+.P
+On error it returns \f(CWDW_DLV_ERROR\fP.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+
+.H 4 "dwarf_linesrc()"
+.DS
+\f(CWint dwarf_linesrc(
+ Dwarf_Line line,
+ char ** return_linesrc,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_linesrc()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_linesrc\fP to
+a pointer to a
+null-terminated string of characters that represents the name of the
+source-file where \f(CWline\fP occurs.
+It returns \f(CWDW_DLV_ERROR\fP on
+error.
+.P
+If the applicable file name in the line table Statement Program Prolog
+does not start with a '/' character
+the string in \f(CWDW_AT_comp_dir\fP (if applicable and present)
+or the applicable
+directory name from the line Statement Program Prolog
+is prepended to the
+file name in the line table Statement Program Prolog
+to make a full path.
+.P
+The storage pointed to by a successful return of
+\f(CWdwarf_linesrc()\fP should be freed using \f(CWdwarf_dealloc()\fP with
+the allocation type \f(CWDW_DLA_STRING\fP when no longer of interest.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+
+.H 4 "dwarf_lineblock()"
+.DS
+\f(CWint dwarf_lineblock(
+ Dwarf_Line line,
+ Dwarf_Bool *return_bool,
+ Dwarf_Error *error)\fP
+.DE
+The function
+\f(CWdwarf_lineblock()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_linesrc\fP to
+non-zero (i.e. true)(if the line is marked as
+beginning a basic block)
+or zero (i.e. false) (if the line is marked as not
+beginning a basic block).
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+
+.H 4 "dwarf_is_addr_set()"
+.DS
+\f(CWint dwarf_line_is_addr_set(
+ Dwarf_Line line,
+ Dwarf_Bool *return_bool,
+ Dwarf_Error *error)\fP
+.DE
+The function
+\f(CWdwarf_line_is_addr_set()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_bool\fP to
+non-zero (i.e. true)(if the line is marked as
+being a DW_LNE_set_address operation)
+or zero (i.e. false) (if the line is marked as not
+being a DW_LNE_set_address operation).
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+
+This is intended to allow consumers to do a more useful job
+printing and analyzing DWARF data, it is not strictly
+necessary.
+
+.H 4 "dwarf_prologue_end_etc()"
+.DS
+\f(CWint dwarf_prologue_end_etc(Dwarf_Line line,
+ Dwarf_Bool * prologue_end,
+ Dwarf_Bool * epilogue_begin,
+ Dwarf_Unsigned * isa,
+ Dwarf_Unsigned * discriminator,
+ Dwarf_Error * error)\fP
+.DE
+The function
+\f(CWdwarf_prologue_end_etc()\fP returns
+\f(CWDW_DLV_OK\fP and sets the returned fields to
+values currently set.
+While it is pretty safe to assume that the
+\f(CWisa\fP
+and
+\f(CWdiscriminator\fP
+values returned are very small integers, there is
+no restriction in the standard.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+
+This function is new in December 2011.
+
+
+.H 2 "Global Name Space Operations"
+These operations operate on the .debug_pubnames section of the debugging
+information.
+
+
+.H 2 "Global Name Space Operations"
+These operations operate on the .debug_pubnames section of the debugging
+information.
+
+.H 3 "Debugger Interface Operations"
+
+.H 4 "dwarf_get_globals()"
+.DS
+\f(CWint dwarf_get_globals(
+ Dwarf_Debug dbg,
+ Dwarf_Global **globals,
+ Dwarf_Signed * return_count,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_get_globals()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_count\fP to
+the count of pubnames
+represented in the section containing pubnames i.e. .debug_pubnames.
+It also stores at \f(CW*globals\fP, a pointer
+to a list of \f(CWDwarf_Global\fP descriptors, one for each of the
+pubnames in the .debug_pubnames section.
+The returned results are for the entire section.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It returns \f(CWDW_DLV_NO_ENTRY\fP if the .debug_pubnames
+section does not exist.
+
+.P
+On a successful return from
+\f(CWdwarf_get_globals()\fP, the \f(CWDwarf_Global\fP
+descriptors should be
+freed using \f(CWdwarf_globals_dealloc()\fP.
+\f(CWdwarf_globals_dealloc()\fP is new as of July 15, 2005
+and is the preferred approach to freeing this memory..
+
+.in +2
+.DS
+\f(CWDwarf_Signed cnt;
+Dwarf_Global *globs;
+int res;
+
+res = dwarf_get_globals(dbg, &globs,&cnt, &error);
+if (res == DW_DLV_OK) {
+
+ for (i = 0; i < cnt; ++i) {
+ /* use globs[i] */
+ }
+ dwarf_globals_dealloc(dbg, globs, cnt);
+}\fP
+.DE
+.in -2
+
+
+.P
+The following code is deprecated as of July 15, 2005 as it does not
+free all relevant memory.
+This approach still works as well as it ever did.
+On a successful return from
+\f(CWdwarf_get_globals()\fP, the \f(CWDwarf_Global\fP
+descriptors should be individually
+freed using \f(CWdwarf_dealloc()\fP with the allocation type
+\f(CWDW_DLA_GLOBAL_CONTEXT\fP,
+(or
+\f(CWDW_DLA_GLOBAL\fP, an older name, supported for compatibility)
+followed by the deallocation of the list itself
+with the allocation type \f(CWDW_DLA_LIST\fP when the descriptors are
+no longer of interest.
+
+.in +2
+.DS
+\f(CWDwarf_Signed cnt;
+Dwarf_Global *globs;
+int res;
+
+res = dwarf_get_globals(dbg, &globs,&cnt, &error);
+if (res == DW_DLV_OK) {
+
+ for (i = 0; i < cnt; ++i) {
+ /* use globs[i] */
+ dwarf_dealloc(dbg, globs[i], DW_DLA_GLOBAL_CONTEXT);
+ }
+ dwarf_dealloc(dbg, globs, DW_DLA_LIST);
+}\fP
+.DE
+.in -2
+
+.H 4 "dwarf_globname()"
+.DS
+\f(CWint dwarf_globname(
+ Dwarf_Global global,
+ char ** return_name,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_globname()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_name\fP to
+a pointer to a
+null-terminated string that names the pubname represented by the
+\f(CWDwarf_Global\fP descriptor, \f(CWglobal\fP.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+On a successful return from this function, the string should
+be freed using \f(CWdwarf_dealloc()\fP, with the allocation type
+\f(CWDW_DLA_STRING\fP when no longer of interest.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+
+.H 4 "dwarf_global_die_offset()"
+.DS
+\f(CWint dwarf_global_die_offset(
+ Dwarf_Global global,
+ Dwarf_Off *return_offset,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_global_die_offset()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_offset\fP to
+the offset in
+the section containing DIEs, i.e. .debug_info, of the DIE representing
+the pubname that is described by the \f(CWDwarf_Global\fP descriptor,
+\f(CWglob\fP.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+
+.H 4 "dwarf_global_cu_offset()"
+.DS
+\f(CWint dwarf_global_cu_offset(
+ Dwarf_Global global,
+ Dwarf_Off *return_offset,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_global_cu_offset()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_offset\fP to
+the offset in
+the section containing DIEs, i.e. .debug_info, of the compilation-unit
+header of the compilation-unit that contains the pubname described
+by the \f(CWDwarf_Global\fP descriptor, \f(CWglobal\fP.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+
+.H 4 "dwarf_get_cu_die_offset_given_cu_header_offset()"
+.DS
+\f(CWint dwarf_get_cu_die_offset_given_cu_header_offset_b(
+ Dwarf_Debug dbg,
+ Dwarf_Off in_cu_header_offset,
+ Dwarf_Bool is_info,
+ Dwarf_Off * out_cu_die_offset,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_get_cu_die_offset_given_cu_header_offset()\fP
+returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*out_cu_die_offset\fP to
+the offset of the compilation-unit DIE given the
+offset \f(CWin_cu_header_offset\fP of a compilation-unit header.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+.P
+If \f(CWis_info\fP is non-zero the \f(CWin_cu_header_offset\fP must refer
+to a .debug_info section offset.
+If \f(CWis_info\fP zero the \f(CWin_cu_header_offset\fP must refer
+to a .debug_types section offset.
+Chaos may result if the \f(CWis_info\fP flag is incorrect.
+
+This effectively turns a compilation-unit-header offset
+into a compilation-unit DIE offset (by adding the
+size of the applicable CU header).
+This function is also sometimes useful with the
+\f(CWdwarf_weak_cu_offset()\fP,
+\f(CWdwarf_func_cu_offset()\fP,
+\f(CWdwarf_type_cu_offset()\fP,
+and
+\f(CWint dwarf_var_cu_offset()\fP
+functions, though for those functions the data is
+only in .debug_info by definition.
+
+.H 4 "dwarf_get_cu_die_offset_given_cu_header_offset()"
+.DS
+\f(CWint dwarf_get_cu_die_offset_given_cu_header_offset(
+ Dwarf_Debug dbg,
+ Dwarf_Off in_cu_header_offset,
+ Dwarf_Off * out_cu_die_offset,
+ Dwarf_Error *error)\fP
+.DE
+This function is superseded by
+\f(CWdwarf_get_cu_die_offset_given_cu_header_offset_b()\fP,
+a function which is still supported thought it refers only
+to the .debug_info section.
+
+
+\f(CWdwarf_get_cu_die_offset_given_cu_header_offset()\fP
+added Rev 1.45, June, 2001.
+
+This function is declared as 'optional' in libdwarf.h
+on IRIX systems so the _MIPS_SYMBOL_PRESENT
+predicate may be used at run time to determine if the version of
+libdwarf linked into an application has this function.
+
+.H 4 "dwarf_global_name_offsets()"
+.DS
+\f(CWint dwarf_global_name_offsets(
+ Dwarf_Global global,
+ char **return_name,
+ Dwarf_Off *die_offset,
+ Dwarf_Off *cu_offset,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_global_name_offsets()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_name\fP to
+a pointer to
+a null-terminated string that gives the name of the pubname
+described by the \f(CWDwarf_Global\fP descriptor \f(CWglobal\fP.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+It also returns in the locations
+pointed to by \f(CWdie_offset\fP, and \f(CWcu_offset\fP, the offsets
+of the DIE representing the
+pubname, and the DIE
+representing the compilation-unit containing the
+pubname, respectively.
+On a
+successful return from \f(CWdwarf_global_name_offsets()\fP the storage
+pointed to by \f(CWreturn_name\fP
+should be freed using \f(CWdwarf_dealloc()\fP,
+with the allocation type \f(CWDW_DLA_STRING\fP when no longer of interest.
+
+
+.H 2 "DWARF3 Type Names Operations"
+Section ".debug_pubtypes" is new in DWARF3.
+.P
+These functions operate on the .debug_pubtypes section of the debugging
+information. The .debug_pubtypes section contains the names of file-scope
+user-defined types, the offsets of the \f(CWDIE\fPs that represent the
+definitions of those types, and the offsets of the compilation-units
+that contain the definitions of those types.
+
+.H 3 "Debugger Interface Operations"
+
+.H 4 "dwarf_get_pubtypes()"
+.DS
+\f(CWint dwarf_get_pubtypes(
+ Dwarf_Debug dbg,
+ Dwarf_Type **types,
+ Dwarf_Signed *typecount,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_get_pubtypes()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*typecount\fP to
+the count of user-defined
+type names represented in the section containing user-defined type names,
+i.e. .debug_pubtypes.
+It also stores at \f(CW*types\fP,
+a pointer to a list of \f(CWDwarf_Pubtype\fP descriptors, one for each of the
+user-defined type names in the .debug_pubtypes section.
+The returned results are for the entire section.
+It returns \f(CWDW_DLV_NOCOUNT\fP on error.
+It returns \f(CWDW_DLV_NO_ENTRY\fP if
+the .debug_pubtypes section does not exist.
+
+.P
+On a successful
+return from \f(CWdwarf_get_pubtypes()\fP,
+the \f(CWDwarf_Type\fP descriptors should be
+freed using \f(CWdwarf_types_dealloc()\fP.
+\f(CWdwarf_types_dealloc()\fP is used for both
+\f(CWdwarf_get_pubtypes()\fP and \f(CWdwarf_get_types()\fP
+as the data types are the same.
+
+.in +2
+.DS
+\f(CWDwarf_Signed cnt;
+Dwarf_Pubtype *types;
+int res;
+
+res = dwarf_get_pubtypes(dbg, &types,&cnt, &error);
+if (res == DW_DLV_OK) {
+
+ for (i = 0; i < cnt; ++i) {
+ /* use types[i] */
+ }
+ dwarf_types_dealloc(dbg, types, cnt);
+}\fP
+.DE
+.in -2
+
+.H 4 "dwarf_pubtypename()"
+.DS
+\f(CWint dwarf_pubtypename(
+ Dwarf_Pubtype type,
+ char **return_name,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_pubtypename()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_name\fP to
+a pointer to a
+null-terminated string that names the user-defined type represented by the
+\f(CWDwarf_Pubtype\fP descriptor, \f(CWtype\fP.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+On a successful return from this function, the string should
+be freed using \f(CWdwarf_dealloc()\fP, with the allocation type
+\f(CWDW_DLA_STRING\fP when no longer of interest.
+
+.H 4 "dwarf_pubtype_die_offset()"
+.DS
+\f(CWint dwarf_pubtype_die_offset(
+ Dwarf_Pubtype type,
+ Dwarf_Off *return_offset,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_pubtype_die_offset()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_offset\fP to
+the offset in
+the section containing DIEs, i.e. .debug_info, of the DIE representing
+the user-defined type that is described by the \f(CWDwarf_Pubtype\fP
+descriptor, \f(CWtype\fP.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+
+.H 4 "dwarf_pubtype_cu_offset()"
+.DS
+\f(CWint dwarf_pubtype_cu_offset(
+ Dwarf_Pubtype type,
+ Dwarf_Off *return_offset,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_pubtype_cu_offset()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_offset\fP to
+the offset in
+the section containing DIEs, i.e. .debug_info, of the compilation-unit
+header of the compilation-unit that contains the user-defined type
+described by the \f(CWDwarf_Pubtype\fP descriptor, \f(CWtype\fP.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+
+.H 4 "dwarf_pubtype_name_offsets()"
+.DS
+\f(CWint dwarf_pubtype_name_offsets(
+ Dwarf_Pubtype type,
+ char ** returned_name,
+ Dwarf_Off * die_offset,
+ Dwarf_Off * cu_offset,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_pubtype_name_offsets()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*returned_name\fP to
+a pointer to
+a null-terminated string that gives the name of the user-defined
+type described by the \f(CWDwarf_Pubtype\fP descriptor \f(CWtype\fP.
+It also returns in the locations
+pointed to by \f(CWdie_offset\fP, and \f(CWcu_offset\fP, the offsets
+of the DIE representing the
+user-defined type, and the DIE
+representing the compilation-unit containing the
+user-defined type, respectively.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+On a successful return from \f(CWdwarf_pubtype_name_offsets()\fP
+the storage pointed to by \f(CWreturned_name\fP should
+be freed using
+\f(CWdwarf_dealloc()\fP, with the allocation type \f(CWDW_DLA_STRING\fP
+when no longer of interest.
+
+
+.H 2 "User Defined Static Variable Names Operations"
+This section is SGI specific and is not part of standard DWARF version 2.
+.P
+These functions operate on the .debug_varnames section of the debugging
+information. The .debug_varnames section contains the names of file-scope
+static variables, the offsets of the \f(CWDIE\fPs that represent the
+definitions of those variables, and the offsets of the compilation-units
+that contain the definitions of those variables.
+.P
+
+
+.H 2 "Weak Name Space Operations"
+These operations operate on the .debug_weaknames section of the debugging
+information.
+.P
+These operations are SGI specific, not part of standard DWARF.
+.P
+
+.H 3 "Debugger Interface Operations"
+
+.H 4 "dwarf_get_weaks()"
+.DS
+\f(CWint dwarf_get_weaks(
+ Dwarf_Debug dbg,
+ Dwarf_Weak **weaks,
+ Dwarf_Signed *weak_count,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_get_weaks()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*weak_count\fP to
+the count of weak names
+represented in the section containing weak names i.e. .debug_weaknames.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It returns \f(CWDW_DLV_NO_ENTRY\fP if the section does not exist.
+It also stores in \f(CW*weaks\fP, a pointer to
+a list of \f(CWDwarf_Weak\fP descriptors, one for each of the weak names
+in the .debug_weaknames section.
+The returned results are for the entire section.
+
+.P
+On a successful return from this function,
+the \f(CWDwarf_Weak\fP descriptors should be freed using
+\f(CWdwarf_weaks_dealloc()\fP when the data is no longer of
+interest. \f(CWdwarf_weaks_dealloc()\fPis new as of July 15, 2005.
+
+.in +2
+.DS
+\f(CWDwarf_Signed cnt;
+Dwarf_Weak *weaks;
+int res;
+
+res = dwarf_get_weaks(dbg, &weaks, &cnt, &error);
+if (res == DW_DLV_OK) {
+
+ for (i = 0; i < cnt; ++i) {
+ /* use weaks[i] */
+ }
+ dwarf_weaks_dealloc(dbg, weaks, cnt);
+}\fP
+.DE
+.in -2
+
+
+
+.P
+The following code is deprecated as of July 15, 2005 as it does not
+free all relevant memory.
+This approach still works as well as it ever did.
+On a successful return from \f(CWdwarf_get_weaks()\fP
+the \f(CWDwarf_Weak\fP descriptors should be individually freed using
+\f(CWdwarf_dealloc()\fP with the allocation type
+\f(CWDW_DLA_WEAK_CONTEXT\fP,
+(or
+\f(CWDW_DLA_WEAK\fP, an older name, supported for compatibility)
+followed by the deallocation of the list itself with the allocation type
+\f(CWDW_DLA_LIST\fP when the descriptors are no longer of interest.
+
+.in +2
+.DS
+\f(CWDwarf_Signed cnt;
+Dwarf_Weak *weaks;
+int res;
+
+res = dwarf_get_weaks(dbg, &weaks, &cnt, &error);
+if (res == DW_DLV_OK) {
+
+ for (i = 0; i < cnt; ++i) {
+ /* use weaks[i] */
+ dwarf_dealloc(dbg, weaks[i], DW_DLA_WEAK_CONTEXT);
+ }
+ dwarf_dealloc(dbg, weaks, DW_DLA_LIST);
+}\fP
+.DE
+.in -2
+
+.H 4 "dwarf_weakname()"
+.DS
+\f(CWint dwarf_weakname(
+ Dwarf_Weak weak,
+ char ** return_name,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_weakname()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_name\fP to
+a pointer to a null-terminated
+string that names the weak name represented by the
+\f(CWDwarf_Weak\fP descriptor, \f(CWweak\fP.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+On a successful return from this function, the string should
+be freed using \f(CWdwarf_dealloc()\fP, with the allocation type
+\f(CWDW_DLA_STRING\fP when no longer of interest.
+
+.DS
+\f(CWint dwarf_weak_die_offset(
+ Dwarf_Weak weak,
+ Dwarf_Off *return_offset,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_weak_die_offset()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_offset\fP to the offset in
+the section containing DIEs, i.e. .debug_info, of the DIE representing
+the weak name that is described by the \f(CWDwarf_Weak\fP descriptor,
+\f(CWweak\fP.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+
+.H 4 "dwarf_weak_cu_offset()"
+.DS
+\f(CWint dwarf_weak_cu_offset(
+ Dwarf_Weak weak,
+ Dwarf_Off *return_offset,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_weak_cu_offset()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_offset\fP to the offset in
+the section containing DIEs, i.e. .debug_info, of the compilation-unit
+header of the compilation-unit that contains the weak name described
+by the \f(CWDwarf_Weak\fP descriptor, \f(CWweak\fP.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+
+.H 4 "dwarf_weak_name_offsets()"
+.DS
+\f(CWint dwarf_weak_name_offsets(
+ Dwarf_Weak weak,
+ char ** weak_name,
+ Dwarf_Off *die_offset,
+ Dwarf_Off *cu_offset,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_weak_name_offsets()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*weak_name\fP to
+a pointer to
+a null-terminated string that gives the name of the weak name
+described by the \f(CWDwarf_Weak\fP descriptor \f(CWweak\fP.
+It also returns in the locations
+pointed to by \f(CWdie_offset\fP, and \f(CWcu_offset\fP, the offsets
+of the DIE representing the
+weakname, and the DIE
+representing the compilation-unit containing the
+weakname, respectively.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+On a
+successful return from \f(CWdwarf_weak_name_offsets()\fP the storage
+pointed to by \f(CWweak_name\fP
+should be freed using \f(CWdwarf_dealloc()\fP,
+with the allocation type \f(CWDW_DLA_STRING\fP when no longer of interest.
+
+.H 2 "Static Function Names Operations"
+This section is SGI specific and is not part of standard DWARF version 2.
+.P
+These function operate on the .debug_funcnames section of the debugging
+information. The .debug_funcnames section contains the names of static
+functions defined in the object, the offsets of the \f(CWDIE\fPs that
+represent the definitions of the corresponding functions, and the offsets
+of the start of the compilation-units that contain the definitions of
+those functions.
+
+.H 3 "Debugger Interface Operations"
+
+.H 4 "dwarf_get_funcs()"
+.DS
+\f(CWint dwarf_get_funcs(
+ Dwarf_Debug dbg,
+ Dwarf_Func **funcs,
+ Dwarf_Signed *func_count,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_get_funcs()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*func_count\fP to
+the count of static
+function names represented in the section containing static function
+names, i.e. .debug_funcnames.
+It also
+stores, at \f(CW*funcs\fP, a pointer to a list of \f(CWDwarf_Func\fP
+descriptors, one for each of the static functions in the .debug_funcnames
+section.
+The returned results are for the entire section.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It returns \f(CWDW_DLV_NO_ENTRY\fP
+if the .debug_funcnames section does not exist.
+.P
+On a successful return from \f(CWdwarf_get_funcs()\fP,
+the \f(CWDwarf_Func\fP
+descriptors should be freed using \f(CWdwarf_funcs_dealloc()\fP.
+\f(CWdwarf_funcs_dealloc()\fP is new as of July 15, 2005.
+
+.in +2
+.DS
+\f(CWDwarf_Signed cnt;
+Dwarf_Func *funcs;
+int fres;
+
+fres = dwarf_get_funcs(dbg, &funcs, &cnt, &error);
+if (fres == DW_DLV_OK) {
+
+ for (i = 0; i < cnt; ++i) {
+ /* use funcs[i] */
+ }
+ dwarf_funcs_dealloc(dbg, funcs, cnt);
+}\fP
+.DE
+.in -2
+
+
+.P
+The following code is deprecated as of July 15, 2005 as it does not
+free all relevant memory.
+This approach still works as well as it ever did.
+On a successful return from \f(CWdwarf_get_funcs()\fP,
+the \f(CWDwarf_Func\fP
+descriptors should be individually freed using \f(CWdwarf_dealloc()\fP
+with the allocation type
+\f(CWDW_DLA_FUNC_CONTEXT\fP,
+(or
+\f(CWDW_DLA_FUNC\fP, an older name, supported for compatibility)
+followed by the deallocation
+of the list itself with the allocation type \f(CWDW_DLA_LIST\fP when
+the descriptors are no longer of interest.
+
+.in +2
+.DS
+\f(CWDwarf_Signed cnt;
+Dwarf_Func *funcs;
+int fres;
+
+fres = dwarf_get_funcs(dbg, &funcs, &error);
+if (fres == DW_DLV_OK) {
+
+ for (i = 0; i < cnt; ++i) {
+ /* use funcs[i] */
+ dwarf_dealloc(dbg, funcs[i], DW_DLA_FUNC_CONTEXT);
+ }
+ dwarf_dealloc(dbg, funcs, DW_DLA_LIST);
+}\fP
+.DE
+.in -2
+
+.H 4 "dwarf_funcname()"
+.DS
+\f(CWint dwarf_funcname(
+ Dwarf_Func func,
+ char ** return_name,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_funcname()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_name\fP to
+a pointer to a
+null-terminated string that names the static function represented by the
+\f(CWDwarf_Func\fP descriptor, \f(CWfunc\fP.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+On a successful return from this function, the string should
+be freed using \f(CWdwarf_dealloc()\fP, with the allocation type
+\f(CWDW_DLA_STRING\fP when no longer of interest.
+
+.H 4 "dwarf_func_die_offset()"
+.DS
+\f(CWint dwarf_func_die_offset(
+ Dwarf_Func func,
+ Dwarf_Off *return_offset,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_func_die_offset()\fP, returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_offset\fP to
+the offset in
+the section containing DIEs, i.e. .debug_info, of the DIE representing
+the static function that is described by the \f(CWDwarf_Func\fP
+descriptor, \f(CWfunc\fP.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+
+.H 4 "dwarf_func_cu_offset()"
+.DS
+\f(CWint dwarf_func_cu_offset(
+ Dwarf_Func func,
+ Dwarf_Off *return_offset,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_func_cu_offset()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_offset\fP to
+the offset in
+the section containing DIEs, i.e. .debug_info, of the compilation-unit
+header of the
+compilation-unit that contains the static function
+described by the \f(CWDwarf_Func\fP descriptor, \f(CWfunc\fP.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+
+.H 4 "dwarf_func_name_offsets()"
+.DS
+\f(CWint dwarf_func_name_offsets(
+ Dwarf_Func func,
+ char **func_name,
+ Dwarf_Off *die_offset,
+ Dwarf_Off *cu_offset,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_func_name_offsets()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*func_name\fP to
+a pointer to
+a null-terminated string that gives the name of the static
+function described by the \f(CWDwarf_Func\fP descriptor \f(CWfunc\fP.
+It also returns in the locations
+pointed to by \f(CWdie_offset\fP, and \f(CWcu_offset\fP, the offsets
+of the DIE representing the
+static function, and the DIE
+representing the compilation-unit containing the
+static function, respectively.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+On a successful return from \f(CWdwarf_func_name_offsets()\fP
+the storage pointed to by \f(CWfunc_name\fP should be freed using
+\f(CWdwarf_dealloc()\fP, with the allocation type \f(CWDW_DLA_STRING\fP
+when no longer of interest.
+
+.H 2 "User Defined Type Names Operations"
+Section "debug_typenames" is SGI specific
+and is not part of standard DWARF version 2.
+(However, an identical section is part of DWARF version 3
+named ".debug_pubtypes", see \f(CWdwarf_get_pubtypes()\fP above.)
+.P
+These functions operate on the .debug_typenames section of the debugging
+information. The .debug_typenames section contains the names of file-scope
+user-defined types, the offsets of the \f(CWDIE\fPs that represent the
+definitions of those types, and the offsets of the compilation-units
+that contain the definitions of those types.
+
+.H 3 "Debugger Interface Operations"
+
+.H 4 "dwarf_get_types()"
+.DS
+\f(CWint dwarf_get_types(
+ Dwarf_Debug dbg,
+ Dwarf_Type **types,
+ Dwarf_Signed *typecount,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_get_types()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*typecount\fP to
+the count of user-defined
+type names represented in the section containing user-defined type names,
+i.e. .debug_typenames.
+It also stores at \f(CW*types\fP,
+a pointer to a list of \f(CWDwarf_Type\fP descriptors, one for each of the
+user-defined type names in the .debug_typenames section.
+The returned results are for the entire section.
+It returns \f(CWDW_DLV_NOCOUNT\fP on error.
+It returns \f(CWDW_DLV_NO_ENTRY\fP if
+the .debug_typenames section does not exist.
+
+.P
+
+On a successful
+return from \f(CWdwarf_get_types()\fP,
+the \f(CWDwarf_Type\fP descriptors should be
+freed using \f(CWdwarf_types_dealloc()\fP.
+\f(CWdwarf_types_dealloc()\fP is new as of July 15, 2005
+and frees all memory allocated by \f(CWdwarf_get_types()\fP.
+
+.in +2
+.DS
+\f(CWDwarf_Signed cnt;
+Dwarf_Type *types;
+int res;
+
+res = dwarf_get_types(dbg, &types,&cnt, &error);
+if (res == DW_DLV_OK) {
+
+ for (i = 0; i < cnt; ++i) {
+ /* use types[i] */
+ }
+ dwarf_types_dealloc(dbg, types, cnt);
+}\fP
+.DE
+.in -2
+
+
+
+.P
+The following code is deprecated as of July 15, 2005 as it does not
+free all relevant memory.
+This approach still works as well as it ever did.
+On a successful
+return from \f(CWdwarf_get_types()\fP,
+the \f(CWDwarf_Type\fP descriptors should be
+individually freed using \f(CWdwarf_dealloc()\fP with the allocation type
+\f(CWDW_DLA_TYPENAME_CONTEXT\fP,
+(or
+\f(CWDW_DLA_TYPENAME\fP, an older name, supported for compatibility)
+followed by the deallocation of the list itself
+with the allocation type \f(CWDW_DLA_LIST\fP when the descriptors are no
+longer of interest.
+
+.in +2
+.DS
+\f(CWDwarf_Signed cnt;
+Dwarf_Type *types;
+int res;
+
+res = dwarf_get_types(dbg, &types,&cnt, &error);
+if (res == DW_DLV_OK) {
+
+ for (i = 0; i < cnt; ++i) {
+ /* use types[i] */
+ dwarf_dealloc(dbg, types[i], DW_DLA_TYPENAME_CONTEXT);
+ }
+ dwarf_dealloc(dbg, types, DW_DLA_LIST);
+}\fP
+.DE
+.in -2
+
+.H 4 "dwarf_typename()"
+.DS
+\f(CWint dwarf_typename(
+ Dwarf_Type type,
+ char **return_name,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_typename()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_name\fP to
+a pointer to a
+null-terminated string that names the user-defined type represented by the
+\f(CWDwarf_Type\fP descriptor, \f(CWtype\fP.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+On a successful return from this function, the string should
+be freed using \f(CWdwarf_dealloc()\fP, with the allocation type
+\f(CWDW_DLA_STRING\fP when no longer of interest.
+
+.H 4 "dwarf_type_die_offset()"
+.DS
+\f(CWint dwarf_type_die_offset(
+ Dwarf_Type type,
+ Dwarf_Off *return_offset,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_type_die_offset()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_offset\fP to
+the offset in
+the section containing DIEs, i.e. .debug_info, of the DIE representing
+the user-defined type that is described by the \f(CWDwarf_Type\fP
+descriptor, \f(CWtype\fP.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+
+.H 4 "dwarf_type_cu_offset()"
+.DS
+\f(CWint dwarf_type_cu_offset(
+ Dwarf_Type type,
+ Dwarf_Off *return_offset,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_type_cu_offset()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_offset\fP to
+the offset in
+the section containing DIEs, i.e. .debug_info, of the compilation-unit
+header of the compilation-unit that contains the user-defined type
+described by the \f(CWDwarf_Type\fP descriptor, \f(CWtype\fP.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+
+.H 4 "dwarf_type_name_offsets()"
+.DS
+\f(CWint dwarf_type_name_offsets(
+ Dwarf_Type type,
+ char ** returned_name,
+ Dwarf_Off * die_offset,
+ Dwarf_Off * cu_offset,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_type_name_offsets()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*returned_name\fP to
+a pointer to
+a null-terminated string that gives the name of the user-defined
+type described by the \f(CWDwarf_Type\fP descriptor \f(CWtype\fP.
+It also returns in the locations
+pointed to by \f(CWdie_offset\fP, and \f(CWcu_offset\fP, the offsets
+of the DIE representing the
+user-defined type, and the DIE
+representing the compilation-unit containing the
+user-defined type, respectively.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+On a successful return from \f(CWdwarf_type_name_offsets()\fP
+the storage pointed to by \f(CWreturned_name\fP should
+be freed using
+\f(CWdwarf_dealloc()\fP, with the allocation type \f(CWDW_DLA_STRING\fP
+when no longer of interest.
+
+
+.H 2 "User Defined Static Variable Names Operations"
+This section is SGI specific and is not part of standard DWARF version 2.
+.P
+These functions operate on the .debug_varnames section of the debugging
+information. The .debug_varnames section contains the names of file-scope
+static variables, the offsets of the \f(CWDIE\fPs that represent the
+definitions of those variables, and the offsets of the compilation-units
+that contain the definitions of those variables.
+.P
+
+.H 3 "Debugger Interface Operations"
+
+.H 4 "dwarf_get_vars()"
+
+.DS
+\f(CWint dwarf_get_vars(
+ Dwarf_Debug dbg,
+ Dwarf_Var **vars,
+ Dwarf_Signed *var_count,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_get_vars()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*var_count\fP to
+the count of file-scope
+static variable names represented in the section containing file-scope
+static variable names, i.e. .debug_varnames.
+It also stores, at \f(CW*vars\fP, a pointer to a list of
+\f(CWDwarf_Var\fP descriptors, one for each of the file-scope static
+variable names in the .debug_varnames section.
+The returned results are for the entire section.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It returns \f(CWDW_DLV_NO_ENTRY\fP if the .debug_varnames section does
+not exist.
+
+.P
+The following is new as of July 15, 2005.
+On a successful return
+from \f(CWdwarf_get_vars()\fP, the \f(CWDwarf_Var\fP descriptors should be
+freed using \f(CWdwarf_vars_dealloc()\fP.
+
+.in +2
+.DS
+\f(CWDwarf_Signed cnt;
+Dwarf_Var *vars;
+int res;
+
+res = dwarf_get_vars(dbg, &vars,&cnt &error);
+if (res == DW_DLV_OK) {
+
+ for (i = 0; i < cnt; ++i) {
+ /* use vars[i] */
+ }
+ dwarf_vars_dealloc(dbg, vars, cnt);
+}\fP
+.DE
+.in -2
+
+.P
+The following code is deprecated as of July 15, 2005 as it does not
+free all relevant memory.
+This approach still works as well as it ever did.
+On a successful return
+from \f(CWdwarf_get_vars()\fP, the \f(CWDwarf_Var\fP descriptors should be individually
+freed using \f(CWdwarf_dealloc()\fP with the allocation type
+\f(CWDW_DLA_VAR_CONTEXT\fP,
+(or
+\f(CWDW_DLA_VAR\fP, an older name, supported for compatibility)
+followed by the deallocation of the list itself with
+the allocation type \f(CWDW_DLA_LIST\fP when the descriptors are no
+longer of interest.
+
+.in +2
+.DS
+\f(CWDwarf_Signed cnt;
+Dwarf_Var *vars;
+int res;
+
+res = dwarf_get_vars(dbg, &vars,&cnt &error);
+if (res == DW_DLV_OK) {
+
+ for (i = 0; i < cnt; ++i) {
+ /* use vars[i] */
+ dwarf_dealloc(dbg, vars[i], DW_DLA_VAR_CONTEXT);
+ }
+ dwarf_dealloc(dbg, vars, DW_DLA_LIST);
+}\fP
+.DE
+.in -2
+
+.H 4 "dwarf_varname()"
+.DS
+\f(CWint dwarf_varname(
+ Dwarf_Var var,
+ char ** returned_name,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_varname()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*returned_name\fP to
+a pointer to a
+null-terminated string that names the file-scope static variable represented
+by the \f(CWDwarf_Var\fP descriptor, \f(CWvar\fP.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+On a successful return from this function, the string should
+be freed using \f(CWdwarf_dealloc()\fP, with the allocation type
+\f(CWDW_DLA_STRING\fP when no longer of interest.
+
+.H 4 "dwarf_var_die_offset()"
+.DS
+\f(CWint dwarf_var_die_offset(
+ Dwarf_Var var,
+ Dwarf_Off *returned_offset,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_var_die_offset()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*returned_offset\fP to
+the offset in
+the section containing DIEs, i.e. .debug_info, of the DIE representing
+the file-scope static variable that is described by the \f(CWDwarf_Var\fP
+descriptor, \f(CWvar\fP.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+
+.H 4 "dwarf_var_cu_offset()"
+.DS
+\f(CWint dwarf_var_cu_offset(
+ Dwarf_Var var,
+ Dwarf_Off *returned_offset,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_var_cu_offset()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*returned_offset\fP to
+the offset in
+the section containing DIEs, i.e. .debug_info, of the compilation-unit
+header of the compilation-unit that contains the file-scope static
+variable described by the \f(CWDwarf_Var\fP descriptor, \f(CWvar\fP.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+
+.H 4 "dwarf_var_name_offsets()"
+.DS
+\f(CWint dwarf_var_name_offsets(
+ Dwarf_Var var,
+ char **returned_name,
+ Dwarf_Off *die_offset,
+ Dwarf_Off *cu_offset,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_var_name_offsets()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*returned_name\fP to
+a pointer to
+a null-terminated string that gives the name of the file-scope
+static variable described by the \f(CWDwarf_Var\fP descriptor \f(CWvar\fP.
+It also returns in the locations
+pointed to by \f(CWdie_offset\fP, and \f(CWcu_offset\fP, the offsets
+of the DIE representing the
+file-scope static variable, and the DIE
+representing the compilation-unit containing the
+file-scope static variable, respectively.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+On a successful return from
+\f(CWdwarf_var_name_offsets()\fP the storage pointed to by
+\f(CWreturned_name\fP
+should be freed using \f(CWdwarf_dealloc()\fP, with the allocation
+type \f(CWDW_DLA_STRING\fP when no longer of interest.
+
+.H 2 "Macro Information Operations"
+.H 3 "General Macro Operations"
+.H 4 "dwarf_find_macro_value_start()"
+.DS
+\f(CWchar *dwarf_find_macro_value_start(char * macro_string);\fP
+.DE
+Given a macro string in the standard form defined in the DWARF
+document ("name <space> value" or "name(args)<space>value")
+this returns a pointer to the first byte of the macro value.
+It does not alter the string pointed to by macro_string or copy
+the string: it returns a pointer into the string whose
+address was passed in.
+.H 3 "Debugger Interface Macro Operations"
+Macro information is accessed from the .debug_info section via the
+DW_AT_macro_info attribute (whose value is an offset into .debug_macinfo).
+.P
+No Functions yet defined.
+.H 3 "Low Level Macro Information Operations"
+.H 4 "dwarf_get_macro_details()"
+.DS
+\f(CWint dwarf_get_macro_details(Dwarf_Debug /*dbg*/,
+ Dwarf_Off macro_offset,
+ Dwarf_Unsigned maximum_count,
+ Dwarf_Signed * entry_count,
+ Dwarf_Macro_Details ** details,
+ Dwarf_Error * err);\fP
+.DE
+\f(CWdwarf_get_macro_details()\fP
+returns
+\f(CWDW_DLV_OK\fP and sets
+\f(CWentry_count\fP to the number of \f(CWdetails\fP records
+returned through the \f(CWdetails\fP pointer.
+The data returned through \f(CWdetails\fP should be freed
+by a call to \f(CWdwarf_dealloc()\fP with the allocation type
+\f(CWDW_DLA_STRING\fP.
+If \f(CWDW_DLV_OK\fP is returned, the \f(CWentry_count\fP will
+be at least 1, since
+a compilation unit with macro information but no macros will
+have at least one macro data byte of 0.
+.P
+\f(CWdwarf_get_macro_details()\fP
+begins at the \f(CWmacro_offset\fP offset you supply
+and ends at the end of a compilation unit or at \f(CWmaximum_count\fP
+detail records (whichever comes first).
+If \f(CWmaximum_count\fP is 0, it is treated as if it were the maximum
+possible unsigned integer.
+.P
+\f(CWdwarf_get_macro_details()\fP
+attempts to set \f(CWdmd_fileindex\fP to the correct file in every
+\f(CWdetails\fP record. If it is unable to do so (or whenever
+the current file index is unknown, it sets \f(CWdmd_fileindex\fP
+to -1.
+.P
+\f(CWdwarf_get_macro_details()\fP returns \f(CWDW_DLV_ERROR\fP on error.
+It returns \f(CWDW_DLV_NO_ENTRY\fP if there is no more
+macro information at that \f(CWmacro_offset\fP. If \f(CWmacro_offset\fP
+is passed in as 0, a \f(CWDW_DLV_NO_ENTRY\fP return means there is
+no macro information.
+.P
+.in +2
+.DS
+\f(CWDwarf_Unsigned max = 0;
+Dwarf_Off cur_off = 0;
+Dwarf_Signed count = 0;
+Dwarf_Macro_Details *maclist;
+int errv;
+
+/* Loop through all the compilation units macro info.
+ This is not guaranteed to work because DWARF does not
+ guarantee every byte in the section is meaningful:
+ there can be garbage between the macro info
+ for CUs. But this loop will usually work.
+*/
+while((errv = dwarf_get_macro_details(dbg, cur_off,max,
+ &count,&maclist,&error))== DW_DLV_OK) {
+ for (i = 0; i < count; ++i) {
+ /* use maclist[i] */
+ }
+ cur_off = maclist[count-1].dmd_offset + 1;
+ dwarf_dealloc(dbg, maclist, DW_DLA_STRING);
+}\fP
+.DE
+
+
+.H 2 "Low Level Frame Operations"
+These functions provide information about stack frames to be
+used to perform stack traces. The information is an abstraction
+of a table with a row per instruction and a column per register
+and a column for the canonical frame address (CFA, which corresponds
+to the notion of a frame pointer),
+as well as a column for the return address.
+.P
+From 1993-2006 the interface we'll here refer to as DWARF2
+made the CFA be a column in the matrix, but left
+DW_FRAME_UNDEFINED_VAL, and DW_FRAME_SAME_VAL out of the matrix
+(giving them high numbers). As of the DWARF3 interfaces
+introduced in this document in April 2006, there are *two*
+interfaces (the original set and a new set).
+Several frame functions work transparently for either set, we
+will focus on the ones that are not equally suitable
+now.
+.P
+The original DWARF2 interface set still exists (dwarf_get_fde_info_for_reg(),
+dwarf_get_fde_info_for_cfa_reg(), and dwarf_get_fde_info_for_all_regs())
+and works adequately for MIPS/IRIX DWARF2 and ABI/ISA sets
+that are sufficiently similar to MIPS.
+These functions not a good choice for non-MIPS architectures nor
+were they a good design for MIPS either.
+It's better to switch entirely to the new functions mentioned
+in the next paragraph.
+This DWARF2 interface set assumes and uses DW_FRAME_CFA_COL
+and that is assumed when libdwarf is configured with --enable-oldframecol .
+.P
+A new DWARF3 interface set of dwarf_get_fde_info_for_reg3(),
+dwarf_get_fde_info_for_cfa_reg3(), dwarf_get_fde_info_for_all_regs3(),
+dwarf_set_frame_rule_table_size()
+dwarf_set_frame_cfa_value(),
+dwarf_set_frame_same_value(),
+dwarf_set_frame_undefined_value(), and
+dwarf_set_frame_rule_initial_value()
+is more flexible
+and will work for many more architectures.
+It is also entirely suitable for use with DWARF2 and DWARF4.
+The setting of the 'frame cfa column number'
+defaults to DW_FRAME_CFA_COL3
+and it can be set at runtime with dwarf_set_frame_cfa_value().
+.P
+Mixing use of the DWARF2 interface set with use
+of the new DWARF3 interface set
+on a single open Dwarf_Debug instance is a mistake.
+Do not do it.
+.P
+We will pretend, from here on unless otherwise
+specified, that
+DW_FRAME_CFA_COL3, DW_FRAME_UNDEFINED_VAL,
+and DW_FRAME_SAME_VAL are the synthetic column numbers.
+These columns may be user-chosen by calls of
+dwarf_set_frame_cfa_value()
+dwarf_set_frame_undefined_value(), and
+dwarf_set_frame_same_value() respectively.
+
+.P
+Each cell in the table contains one of the following:
+
+.AL
+.LI
+A register + offset(a)(b)
+
+.LI
+A register(c)(d)
+
+
+.LI
+A marker (DW_FRAME_UNDEFINED_VAL) meaning \fIregister value undefined\fP
+
+.LI
+A marker (DW_FRAME_SAME_VAL) meaning
+\fIregister value same as in caller\fP
+.LE
+.P
+(a old DWARF2 interface) When the column is DW_FRAME_CFA_COL:
+the register
+number is a real hardware register, not a reference
+to DW_FRAME_CFA_COL, not DW_FRAME_UNDEFINED_VAL,
+and not DW_FRAME_SAME_VAL.
+The CFA rule value should be the stack pointer
+plus offset 0 when no other value makes sense.
+A value of DW_FRAME_SAME_VAL would
+be semi-logical, but since the CFA is not a real register,
+not really correct.
+A value of DW_FRAME_UNDEFINED_VAL would imply
+the CFA is undefined --
+this seems to be a useless notion, as
+the CFA is a means to finding real registers,
+so those real registers should be marked DW_FRAME_UNDEFINED_VAL,
+and the CFA column content (whatever register it
+specifies) becomes unreferenced by anything.
+.P
+(a new April 2006 DWARF2/3 interface): The CFA is
+separately accessible and not part of the table.
+The 'rule number' for the CFA is a number outside the table.
+So the CFA is a marker, not a register number.
+See DW_FRAME_CFA_COL3 in libdwarf.h and
+dwarf_get_fde_info_for_cfa_reg3() and
+dwarf_set_frame_rule_cfa_value().
+.P
+(b) When the column is not DW_FRAME_CFA_COL3, the 'register'
+will and must be DW_FRAME_CFA_COL3(COL), implying that
+to get the final location for the column one must add
+the offset here plus the DW_FRAME_CFA_COL3 rule value.
+.P
+(c) When the column is DW_FRAME_CFA_COL3, then the 'register'
+number is (must be) a real hardware register .
+(This paragraph does not apply to the April 2006 new interface).
+If it were DW_FRAME_UNDEFINED_VAL or DW_FRAME_SAME_VAL
+it would be a marker, not a register number.
+.P
+(d) When the column is not DW_FRAME_CFA_COL3, the register
+may be a hardware register.
+It will not be DW_FRAME_CFA_COL3.
+.P
+There is no 'column' for DW_FRAME_UNDEFINED_VAL or DW_FRAME_SAME_VAL.
+Nor for DW_FRAME_CFA_COL3.
+
+Figure \n(aX
+is machine dependent and represents MIPS CPU register
+assignments. The DW_FRAME_CFA_COL define in dwarf.h
+is historical and really belongs
+in libdwarf.h, not dwarf.h.
+.DS
+.TS
+center box, tab(:);
+lfB lfB lfB
+l c l.
+NAME:value:PURPOSE
+_
+DW_FRAME_CFA_COL:0:column used for CFA
+DW_FRAME_REG1:1:integer register 1
+DW_FRAME_REG2:2:integer register 2
+---::obvious names and values here
+DW_FRAME_REG30:30:integer register 30
+DW_FRAME_REG31:31:integer register 31
+DW_FRAME_FREG0:32:floating point register 0
+DW_FRAME_FREG1:33:floating point register 1
+---::obvious names and values here
+DW_FRAME_FREG30:62:floating point register 30
+DW_FRAME_FREG31:63:floating point register 31
+DW_FRAME_RA_COL:64:column recording ra
+DW_FRAME_UNDEFINED_VAL:1034:register val undefined
+DW_FRAME_SAME_VAL:1035:register same as in caller
+.TE
+
+.FG "Frame Information Rule Assignments MIPS"
+.DE
+.P
+The following table shows SGI/MIPS specific
+special cell values: these values mean
+that the cell has the value \fIundefined\fP or \fIsame value\fP
+respectively, rather than containing a \fIregister\fP or
+\fIregister+offset\fP.
+It assumes DW_FRAME_CFA_COL is a table rule, which
+is not readily accomplished or even sensible for some architectures.
+.P
+.DS
+.TS
+center box, tab(:);
+lfB lfB lfB
+l c l.
+NAME:value:PURPOSE
+_
+DW_FRAME_UNDEFINED_VAL:1034:means undefined value.
+::Not a column or register value
+DW_FRAME_SAME_VAL:1035:means 'same value' as
+::caller had. Not a column or
+::register value
+DW_FRAME_CFA_COL:0:means register zero is
+::usurped by the CFA column.
+::
+.TE
+.FG "Frame Information Special Values any architecture"
+.DE
+
+.P
+The following table shows more general special cell values.
+These values mean
+that the cell register-number refers to the \fIcfa-register\fP or
+\fIundefined-value\fP or \fIsame-value\fP
+respectively, rather than referring to a \fIregister in the table\fP.
+The generality arises from making DW_FRAME_CFA_COL3 be
+outside the set of registers and making the cfa rule accessible
+from outside the rule-table.
+.P
+.DS
+.TS
+center box, tab(:);
+lfB lfB lfB
+l c l.
+NAME:value:PURPOSE
+_
+DW_FRAME_UNDEFINED_VAL:1034:means undefined value.
+::Not a column or register value
+DW_FRAME_SAME_VAL:1035:means 'same value' as
+::caller had. Not a column or
+::register value
+DW_FRAME_CFA_COL3:1436:means 'cfa register' is referred to,
+::not a real register, not a column, but the cfa (the cfa
+::does have a value, but in the DWARF3 libdwarf interface
+::it does not have a 'real register number').
+.TE
+.DE
+
+.P
+.H 4 "dwarf_get_fde_list()"
+.DS
+\f(CWint dwarf_get_fde_list(
+ Dwarf_Debug dbg,
+ Dwarf_Cie **cie_data,
+ Dwarf_Signed *cie_element_count,
+ Dwarf_Fde **fde_data,
+ Dwarf_Signed *fde_element_count,
+ Dwarf_Error *error);\fP
+.DE
+\f(CWdwarf_get_fde_list()\fP stores a pointer to a list of
+\f(CWDwarf_Cie\fP descriptors in \f(CW*cie_data\fP, and the
+count of the number of descriptors in \f(CW*cie_element_count\fP.
+There is a descriptor for each CIE in the .debug_frame section.
+Similarly, it stores a pointer to a list of \f(CWDwarf_Fde\fP
+descriptors in \f(CW*fde_data\fP, and the count of the number
+of descriptors in \f(CW*fde_element_count\fP. There is one
+descriptor per FDE in the .debug_frame section.
+\f(CWdwarf_get_fde_list()\fP returns \f(CWDW_DLV_ERROR\fP on error.
+It returns \f(CWDW_DLV_NO_ENTRY\fP if it cannot find frame entries.
+It returns \f(CWDW_DLV_OK\fP on a successful return.
+.P
+On successful return, structures pointed to by a
+descriptor should be freed using \f(CWdwarf_fde_cie_list_dealloc()\fP.
+This dealloc approach is new as of July 15, 2005.
+
+.in +2
+.DS
+\f(CWDwarf_Signed cnt;
+Dwarf_Cie *cie_data;
+Dwarf_Signed cie_count;
+Dwarf_Fde *fde_data;
+Dwarf_Signed fde_count;
+int fres;
+
+fres = dwarf_get_fde_list(dbg,&cie_data,&cie_count,
+ &fde_data,&fde_count,&error);
+if (fres == DW_DLV_OK) {
+ dwarf_fde_cie_list_dealloc(dbg, cie_data, cie_count,
+ fde_data,fde_count);
+}\fP
+.DE
+.in -2
+
+
+
+.P
+The following code is deprecated as of July 15, 2005 as it does not
+free all relevant memory.
+This approach still works as well as it ever did.
+.in +2
+.DS
+\f(CWDwarf_Signed cnt;
+Dwarf_Cie *cie_data;
+Dwarf_Signed cie_count;
+Dwarf_Fde *fde_data;
+Dwarf_Signed fde_count;
+int fres;
+
+fres = dwarf_get_fde_list(dbg,&cie_data,&cie_count,
+ &fde_data,&fde_count,&error);
+if (fres == DW_DLV_OK) {
+
+ for (i = 0; i < cie_count; ++i) {
+ /* use cie[i] */
+ dwarf_dealloc(dbg, cie_data[i], DW_DLA_CIE);
+ }
+ for (i = 0; i < fde_count; ++i) {
+ /* use fde[i] */
+ dwarf_dealloc(dbg, fde_data[i], DW_DLA_FDE);
+ }
+ dwarf_dealloc(dbg, cie_data, DW_DLA_LIST);
+ dwarf_dealloc(dbg, fde_data, DW_DLA_LIST);
+}\fP
+.DE
+.in -2
+
+.P
+.H 4 "dwarf_get_fde_list_eh()"
+.DS
+\f(CWint dwarf_get_fde_list_eh(
+ Dwarf_Debug dbg,
+ Dwarf_Cie **cie_data,
+ Dwarf_Signed *cie_element_count,
+ Dwarf_Fde **fde_data,
+ Dwarf_Signed *fde_element_count,
+ Dwarf_Error *error);\fP
+.DE
+\f(CWdwarf_get_fde_list_eh()\fP is identical to
+\f(CWdwarf_get_fde_list()\fP except that
+\f(CWdwarf_get_fde_list_eh()\fP reads the GNU gcc
+section named .eh_frame (C++ exception handling information).
+
+\f(CWdwarf_get_fde_list_eh()\fP stores a pointer to a list of
+\f(CWDwarf_Cie\fP descriptors in \f(CW*cie_data\fP, and the
+count of the number of descriptors in \f(CW*cie_element_count\fP.
+There is a descriptor for each CIE in the .debug_frame section.
+Similarly, it stores a pointer to a list of \f(CWDwarf_Fde\fP
+descriptors in \f(CW*fde_data\fP, and the count of the number
+of descriptors in \f(CW*fde_element_count\fP. There is one
+descriptor per FDE in the .debug_frame section.
+\f(CWdwarf_get_fde_list()\fP returns \f(CWDW_DLV_ERROR\fP on error.
+It returns \f(CWDW_DLV_NO_ENTRY\fP if it cannot find
+exception handling entries.
+It returns \f(CWDW_DLV_OK\fP on a successful return.
+
+.P
+On successful return, structures pointed to by a
+descriptor should be freed using \f(CWdwarf_fde_cie_list_dealloc()\fP.
+This dealloc approach is new as of July 15, 2005.
+
+.in +2
+.DS
+\f(CWDwarf_Signed cnt;
+Dwarf_Cie *cie_data;
+Dwarf_Signed cie_count;
+Dwarf_Fde *fde_data;
+Dwarf_Signed fde_count;
+int fres;
+
+fres = dwarf_get_fde_list(dbg,&cie_data,&cie_count,
+ &fde_data,&fde_count,&error);
+if (fres == DW_DLV_OK) {
+ dwarf_fde_cie_list_dealloc(dbg, cie_data, cie_count,
+ fde_data,fde_count);
+}\fP
+.DE
+.in -2
+
+
+.P
+.H 4 "dwarf_get_cie_of_fde()"
+.DS
+\f(CWint dwarf_get_cie_of_fde(Dwarf_Fde fde,
+ Dwarf_Cie *cie_returned,
+ Dwarf_Error *error);\fP
+.DE
+\f(CWdwarf_get_cie_of_fde()\fP stores a \f(CWDwarf_Cie\fP
+into the \f(CWDwarf_Cie\fP that \f(CWcie_returned\fP points at.
+
+If one has called dwarf_get_fde_list and does not wish
+to dwarf_dealloc() all the individual FDEs immediately, one
+must also avoid dwarf_dealloc-ing the CIEs for those FDEs
+not immediately dealloc'd.
+Failing to observe this restriction will cause the FDE(s) not
+dealloc'd to become invalid: an FDE contains (hidden in it)
+a CIE pointer which will be be invalid (stale, pointing to freed memory)
+if the CIE is dealloc'd.
+The invalid CIE pointer internal to the FDE cannot be detected
+as invalid by libdwarf.
+If one later passes an FDE with a stale internal CIE pointer
+to one of the routines taking an FDE as input the result will
+be failure of the call (returning DW_DLV_ERROR) at best and
+it is possible a coredump or worse will happen (eventually).
+
+
+\f(CWdwarf_get_cie_of_fde()\fP returns
+\f(CWDW_DLV_OK\fP if it is successful (it will be
+unless fde is the NULL pointer).
+It returns \f(CWDW_DLV_ERROR\fP if the fde is invalid (NULL).
+
+.P
+Each \f(CWDwarf_Fde\fP descriptor describes information about the
+frame for a particular subroutine or function.
+
+\f(CWint dwarf_get_fde_for_die\fP is SGI/MIPS specific.
+
+.H 4 "dwarf_get_fde_for_die()"
+.DS
+\f(CWint dwarf_get_fde_for_die(
+ Dwarf_Debug dbg,
+ Dwarf_Die die,
+ Dwarf_Fde * return_fde,
+ Dwarf_Error *error)\fP
+.DE
+When it succeeds,
+\f(CWdwarf_get_fde_for_die()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_fde\fP
+to
+a \f(CWDwarf_Fde\fP
+descriptor representing frame information for the given \f(CWdie\fP. It
+looks for the \f(CWDW_AT_MIPS_fde\fP attribute in the given \f(CWdie\fP.
+If it finds it, is uses the value of the attribute as the offset in
+the .debug_frame section where the FDE begins.
+If there is no \f(CWDW_AT_MIPS_fde\fP it returns \f(CWDW_DLV_NO_ENTRY\fP.
+If there is an error it returns \f(CWDW_DLV_ERROR\fP.
+
+.H 4 "dwarf_get_fde_range()"
+.DS
+\f(CWint dwarf_get_fde_range(
+ Dwarf_Fde fde,
+ Dwarf_Addr *low_pc,
+ Dwarf_Unsigned *func_length,
+ Dwarf_Ptr *fde_bytes,
+ Dwarf_Unsigned *fde_byte_length,
+ Dwarf_Off *cie_offset,
+ Dwarf_Signed *cie_index,
+ Dwarf_Off *fde_offset,
+ Dwarf_Error *error);\fP
+.DE
+On success,
+\f(CWdwarf_get_fde_range()\fP returns
+\f(CWDW_DLV_OK\fP.
+
+The location pointed to by \f(CWlow_pc\fP is set to the low pc value for
+this function.
+
+The location pointed to by \f(CWfunc_length\fP is
+set to the length of the function in bytes.
+This is essentially the
+length of the text section for the function.
+
+The location pointed
+to by \f(CWfde_bytes\fP is set to the address where the FDE begins
+in the .debug_frame section.
+
+The location pointed to by
+\f(CWfde_byte_length\fP is set to the length in bytes of the portion
+of .debug_frame for this FDE.
+This is the same as the value returned
+by \f(CWdwarf_get_fde_range\fP.
+
+The location pointed to by
+\f(CWcie_offset\fP is set to the offset in the .debug_frame section
+of the CIE used by this FDE.
+
+The location pointed to by \f(CWcie_index\fP
+is set to the index of the CIE used by this FDE.
+The index is the
+index of the CIE in the list pointed to by \f(CWcie_data\fP as set
+by the function \f(CWdwarf_get_fde_list()\fP.
+However, if the function
+\f(CWdwarf_get_fde_for_die()\fP was used to obtain the given \f(CWfde\fP,
+this index may not be correct.
+
+The location pointed to by
+\f(CWfde_offset\fP is set to the offset of the start of this FDE in
+the .debug_frame section.
+
+\f(CWdwarf_get_fde_range()\fP returns \f(CWDW_DLV_ERROR\fP on error.
+
+.H 4 "dwarf_get_cie_info()"
+.DS
+\f(CWint dwarf_get_cie_info(
+ Dwarf_Cie cie,
+ Dwarf_Unsigned *bytes_in_cie,
+ Dwarf_Small *version,
+ char **augmenter,
+ Dwarf_Unsigned *code_alignment_factor,
+ Dwarf_Signed *data_alignment_factor,
+ Dwarf_Half *return_address_register_rule,
+ Dwarf_Ptr *initial_instructions,
+ Dwarf_Unsigned *initial_instructions_length,
+ Dwarf_Error *error);\fP
+.DE
+\f(CWdwarf_get_cie_info()\fP is primarily for Internal-level Interface
+consumers.
+If successful,
+it returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*bytes_in_cie\fP to
+the number of bytes in the portion of the
+frames section for the CIE represented by the given \f(CWDwarf_Cie\fP
+descriptor, \f(CWcie\fP.
+The other fields are directly taken from
+the cie and returned, via the pointers to the caller.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+
+.H 4 "dwarf_get_cie_index()"
+.DS
+\f(CWint dwarf_get_cie_index(
+ Dwarf_Cie cie,
+ Dwarf_Signed *cie_index,
+ Dwarf_Error *error);\fP
+.DE
+On success,
+\f(CWdwarf_get_cie_index()\fP returns
+\f(CWDW_DLV_OK\fP.
+On error this function returns \f(CWDW_DLV_ERROR\fP.
+
+The location pointed to by \f(CWcie_index\fP
+is set to the index of the CIE of this FDE.
+The index is the
+index of the CIE in the list pointed to by \f(CWcie_data\fP as set
+by the function \f(CWdwarf_get_fde_list()\fP.
+
+So one must have used \f(CWdwarf_get_fde_list()\fP or
+\f(CWdwarf_get_fde_list_eh()\fP to get
+a cie list before this is meaningful.
+
+This function is occasionally useful, but is
+little used.
+
+.H 4 "dwarf_get_fde_instr_bytes()"
+.DS
+\f(CWint dwarf_get_fde_instr_bytes(
+ Dwarf_Fde fde,
+ Dwarf_Ptr *outinstrs,
+ Dwarf_Unsigned *outlen,
+ Dwarf_Error *error);\fP
+.DE
+\f(CWdwarf_get_fde_instr_bytes()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*outinstrs\fP to
+a pointer to a set of bytes which are the
+actual frame instructions for this fde.
+It also sets \f(CW*outlen\fP to the length, in
+bytes, of the frame instructions.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+The intent is to allow low-level consumers like a dwarf-dumper
+to print the bytes in some fashion.
+The memory pointed to by \f(CWoutinstrs\fP
+must not be changed and there
+is nothing to free.
+
+.H 4 "dwarf_get_fde_info_for_reg()"
+This interface is suitable for DWARF2 but is not
+sufficient for DWARF3. See \f(CWint dwarf_get_fde_info_for_reg3\fP.
+.DS
+\f(CWint dwarf_get_fde_info_for_reg(
+ Dwarf_Fde fde,
+ Dwarf_Half table_column,
+ Dwarf_Addr pc_requested,
+ Dwarf_Signed *offset_relevant,
+ Dwarf_Signed *register_num,
+ Dwarf_Signed *offset,
+ Dwarf_Addr *row_pc,
+ Dwarf_Error *error);\fP
+.DE
+\f(CWdwarf_get_fde_info_for_reg()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*offset_relevant\fP to
+non-zero if the offset is relevant for the
+row specified by \f(CWpc_requested\fP and column specified by
+\f(CWtable_column\fP, for the FDE specified by \f(CWfde\fP.
+The
+intent is to return the rule for the given pc value and register.
+The location pointed to by \f(CWregister_num\fP is set to the register
+value for the rule.
+The location pointed to by \f(CWoffset\fP
+is set to the offset value for the rule.
+If offset is not relevant for this rule, \f(CW*offset_relevant\fP is
+set to zero.
+Since more than one pc
+value will have rows with identical entries, the user may want to
+know the earliest pc value after which the rules for all the columns
+remained unchanged.
+Recall that in the virtual table that the frame information
+represents there may be one or more table rows with identical data
+(each such table row at a different pc value).
+Given a \f(CWpc_requested\fP which refers to a pc in such a group
+of identical rows,
+the location pointed to by \f(CWrow_pc\fP is set
+to the lowest pc value
+within the group of identical rows.
+The value put in \f(CW*register_num\fP any of the
+\f(CWDW_FRAME_*\fP table columns values specified in \f(CWlibdwarf.h\fP
+or \f(CWdwarf.h\fP.
+
+\f(CWdwarf_get_fde_info_for_reg\fP returns \f(CWDW_DLV_ERROR\fP if there is an error.
+
+It is usable with either
+\f(CWdwarf_get_fde_n()\fP or \f(CWdwarf_get_fde_at_pc()\fP.
+
+\f(CWdwarf_get_fde_info_for_reg()\fP is tailored to MIPS, please use
+\f(CWdwarf_get_fde_info_for_reg3()\fP instead for all architectures.
+
+
+.H 4 "dwarf_get_fde_info_for_all_regs()"
+.DS
+\f(CWint dwarf_get_fde_info_for_all_regs(
+ Dwarf_Fde fde,
+ Dwarf_Addr pc_requested,
+ Dwarf_Regtable *reg_table,
+ Dwarf_Addr *row_pc,
+ Dwarf_Error *error);\fP
+.DE
+\f(CWdwarf_get_fde_info_for_all_regs()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*reg_table\fP for the row specified by
+\f(CWpc_requested\fP for the FDE specified by \f(CWfde\fP.
+.P
+The intent is
+to return the rules for decoding all the registers, given a pc value.
+\f(CWreg_table\fP is an array of rules, one for each register specified in
+\f(CWdwarf.h\fP. The rule for each register contains three items -
+\f(CWdw_regnum\fP which denotes the register value for that rule,
+\f(CWdw_offset\fP which denotes the offset value for that rule and
+\f(CWdw_offset_relevant\fP which is set to zero if offset is not relevant
+for that rule. See \f(CWdwarf_get_fde_info_for_reg()\fP for a description
+of \f(CWrow_pc\fP.
+.P
+\f(CWdwarf_get_fde_info_for_all_regs\fP returns \f(CWDW_DLV_ERROR\fP if there is an error.
+.P
+\f(CWint dwarf_get_fde_info_for_all_regs\fP is tailored to SGI/MIPS,
+please use dwarf_get_fde_info_for_all_regs3() instead for all architectures.
+
+
+.H 4 "dwarf_set_frame_rule_table_size()"
+.P
+This allows consumers to set the size of the (internal to libdwarf)
+rule table when using the 'reg3' interfaces (these interfaces
+are strongly preferred over the older 'reg' interfaces).
+It should be at least as large as the
+number of real registers in the ABI which is to be read in
+for the dwarf_get_fde_info_for_reg3() or dwarf_get_fde_info_for_all_regs3()
+functions to work properly.
+
+The frame rule table size must be less than the marker values
+DW_FRAME_UNDEFINED_VAL, DW_FRAME_SAME_VAL, DW_FRAME_CFA_COL3
+(dwarf_set_frame_rule_undefined_value()
+dwarf_set_frame_same_value()
+dwarf_set_frame_cfa_value()
+effectively set these markers so
+the frame rule table size can actually be any value regardless
+of the macro values in libdwarf.h as long as the table size
+does not overlap these markers).
+.P
+.DS
+\f(CWDwarf_Half
+dwarf_set_frame_rule_table_size(Dwarf_Debug dbg,
+ Dwarf_Half value);\fP
+
+.DE
+\f(CWdwarf_set_frame_rule_table_size()\fP sets the
+value \f(CWvalue\fP as the size of libdwarf-internal
+rules tables of \f(CWdbg\fP.
+.P
+The function returns
+the previous value of the rules table size setting (taken from the
+\f(CWdbg\fP structure).
+
+.H 4 "dwarf_set_frame_rule_initial_value()"
+This allows consumers to set the initial value
+for rows in the frame tables. By default it
+is taken from libdwarf.h and is DW_FRAME_REG_INITIAL_VALUE
+(which itself is either DW_FRAME_SAME_VAL or DW_FRAME_UNDEFINED_VAL).
+The MIPS/IRIX default is DW_FRAME_SAME_VAL.
+Consumer code should set this appropriately and for
+many architectures (but probably not MIPS) DW_FRAME_UNDEFINED_VAL is an
+appropriate setting.
+Note: an earlier spelling of dwarf_set_frame_rule_inital_value()
+is still supported as an interface, but please change to use
+the new correctly spelled name.
+.DS
+\f(CWDwarf_Half
+dwarf_set_frame_rule_initial_value(Dwarf_Debug dbg,
+ Dwarf_Half value);\fP
+
+.DE
+\f(CWdwarf_set_frame_rule_initial_value()\fP sets the
+value \f(CWvalue\fP as the initial value for this \f(CWdbg\fP
+when initializing rules tables.
+.P
+The function returns
+the previous value of initial value (taken from the
+\f(CWdbg\fP structure).
+
+.H 4 "dwarf_set_frame_cfa_value()"
+This allows consumers to set the number of the CFA register
+for rows in the frame tables. By default it
+is taken from libdwarf.h and is \f(CWDW_FRAME_CFA_COL\fP.
+Consumer code should set this appropriately and for
+nearly all architectures \f(CWDW_FRAME_CFA_COL3\fP is an
+appropriate setting.
+.DS
+\f(CWDwarf_Half
+dwarf_set_frame_rule_cfa_value(Dwarf_Debug dbg,
+ Dwarf_Half value);\fP
+
+.DE
+\f(CWdwarf_set_frame_rule_cfa_value()\fP sets the
+value \f(CWvalue\fP as the number of the cfa 'register rule'
+for this \f(CWdbg\fP
+when initializing rules tables.
+.P
+The function returns
+the previous value of the pseudo-register (taken from the
+\f(CWdbg\fP structure).
+
+.H 4 "dwarf_set_frame_same_value()"
+This allows consumers to set the number of the pseudo-register
+when DW_CFA_same_value is the operation. By default it
+is taken from libdwarf.h and is \f(CWDW_FRAME_SAME_VAL\fP.
+Consumer code should set this appropriately, though for
+many architectures \f(CWDW_FRAME_SAME_VAL\fP is an
+appropriate setting.
+.DS
+\f(CWDwarf_Half
+dwarf_set_frame_rule_same_value(Dwarf_Debug dbg,
+ Dwarf_Half value);\fP
+
+.DE
+\f(CWdwarf_set_frame_rule_same_value()\fP sets the
+value \f(CWvalue\fP as the number of the register
+that is the pseudo-register set by the DW_CFA_same_value
+frame operation.
+.P
+The function returns
+the previous value of the pseudo-register (taken from the
+\f(CWdbg\fP structure).
+
+
+.H 4 "dwarf_set_frame_undefined_value()"
+This allows consumers to set the number of the pseudo-register
+ when DW_CFA_undefined_value is the operation. By default it
+is taken from libdwarf.h and is \f(CWDW_FRAME_UNDEFINED_VAL\fP.
+Consumer code should set this appropriately, though for
+many architectures \f(CWDW_FRAME_UNDEFINED_VAL\fP is an
+appropriate setting.
+.DS
+\f(CWDwarf_Half
+dwarf_set_frame_rule_undefined_value(Dwarf_Debug dbg,
+ Dwarf_Half value);\fP
+
+.DE
+\f(CWdwarf_set_frame_rule_undefined_value()\fP sets the
+value \f(CWvalue\fP as the number of the register
+that is the pseudo-register set by the DW_CFA_undefined_value
+frame operation.
+.P
+The function returns
+the previous value of the pseudo-register (taken from the
+\f(CWdbg\fP structure).
+
+.H 4 "dwarf_set_default_address_size()"
+This allows consumers to set a default address size.
+When one has an object where the
+default address_size does not match the frame address
+size where there is no debug_info available to get a
+frame-specific address-size, this function is useful.
+For example, if an Elf64 object has a .debug_frame whose
+real address_size is 4 (32 bits). This a very rare
+situation.
+.DS
+\f(CWDwarf_Small
+dwarf_set_default_address_size(Dwarf_Debug dbg,
+ Dwarf_Small value);\fP
+
+.DE
+\f(CWdwarf_set_default_address_size()\fP sets the
+value \f(CWvalue\fP as the default address size for
+this activation of the reader, but only if \f(CWvalue\fP
+is greater than zero (otherwise the default address size
+is not changed).
+.P
+The function returns
+the previous value of the default address size (taken from the
+\f(CWdbg\fP structure).
+
+
+
+.H 4 "dwarf_get_fde_info_for_reg3()"
+This interface is suitable for DWARF3 and DWARF2.
+It returns the values for a particular real register
+(Not for the CFA register, see dwarf_get_fde_info_for_cfa_reg3()
+below).
+If the application is going to retrieve the value for more
+than a few \f(CWtable_column\fP values at this \f(CWpc_requested\fP
+(by calling this function multiple times)
+it is much more efficient to
+call dwarf_get_fde_info_for_all_regs3() (in spite
+of the additional setup that requires of the caller).
+
+.DS
+\f(CWint dwarf_get_fde_info_for_reg3(
+ Dwarf_Fde fde,
+ Dwarf_Half table_column,
+ Dwarf_Addr pc_requested,
+ Dwarf_Small *value_type,
+ Dwarf_Signed *offset_relevant,
+ Dwarf_Signed *register_num,
+ Dwarf_Signed *offset_or_block_len,
+ Dwarf_Ptr *block_ptr,
+ Dwarf_Addr *row_pc,
+ Dwarf_Error *error);\fP
+.DE
+\f(CWdwarf_get_fde_info_for_reg3()\fP returns
+\f(CWDW_DLV_OK\fP on success.
+It sets \f(CW*value_type\fP
+to one of DW_EXPR_OFFSET (0),
+DW_EXPR_VAL_OFFSET(1), DW_EXPR_EXPRESSION(2) or
+DW_EXPR_VAL_EXPRESSION(3).
+On call, \f(CWtable_column\fP must be set to the
+register number of a real register. Not
+the cfa 'register' or DW_FRAME_SAME_VALUE or
+DW_FRAME_UNDEFINED_VALUE.
+
+
+if \f(CW*value_type\fP has the value DW_EXPR_OFFSET (0) then:
+.in +4
+.P
+It sets \f(CW*offset_relevant\fP to
+non-zero if the offset is relevant for the
+row specified by \f(CWpc_requested\fP and column specified by
+\f(CWtable_column\fP or, for the FDE specified by \f(CWfde\fP.
+In this case the \f(CW*register_num\fP will be set
+to DW_FRAME_CFA_COL3 (. This is an offset(N) rule
+as specified in the DWARF3/2 documents.
+Adding the value of \f(CW*offset_or_block_len\fP
+to the value of the CFA register gives the address
+of a location holding the previous value of
+register \f(CWtable_column\fP.
+
+.P
+If offset is not relevant for this rule, \f(CW*offset_relevant\fP is
+set to zero. \f(CW*register_num\fP will be set
+to the number of the real register holding the value of
+the \f(CWtable_column\fP register.
+This is the register(R) rule as specified in DWARF3/2 documents.
+.P
+The
+intent is to return the rule for the given pc value and register.
+The location pointed to by \f(CWregister_num\fP is set to the register
+value for the rule.
+The location pointed to by \f(CWoffset\fP
+is set to the offset value for the rule.
+Since more than one pc
+value will have rows with identical entries, the user may want to
+know the earliest pc value after which the rules for all the columns
+remained unchanged.
+Recall that in the virtual table that the frame information
+represents there may be one or more table rows with identical data
+(each such table row at a different pc value).
+Given a \f(CWpc_requested\fP which refers to a pc in such a group
+of identical rows,
+the location pointed to by \f(CWrow_pc\fP is set
+to the lowest pc value
+within the group of identical rows.
+
+.in -4
+
+.P
+If \f(CW*value_type\fP has the value DW_EXPR_VAL_OFFSET (1) then:
+.in +4
+This will be a val_offset(N) rule as specified in the
+DWARF3/2 documents so \f(CW*offset_relevant\fP will
+be non zero.
+The calculation is identical to the DW_EXPR_OFFSET (0)
+calculation with \f(CW*offset_relevant\fP non-zero,
+but the value resulting is the actual \f(CWtable_column\fP
+value (rather than the address where the value may be found).
+.in -4
+.P
+If \f(CW*value_type\fP has the value DW_EXPR_EXPRESSION (1) then:
+.in +4
+ \f(CW*offset_or_block_len\fP
+is set to the length in bytes of a block of memory
+with a DWARF expression in the block.
+\f(CW*block_ptr\fP is set to point at the block of memory.
+The consumer code should evaluate the block as
+a DWARF-expression. The result is the address where
+the previous value of the register may be found.
+This is a DWARF3/2 expression(E) rule.
+.in -4
+.P
+If \f(CW*value_type\fP has the value DW_EXPR_VAL_EXPRESSION (1) then:
+.in +4
+The calculation is exactly as for DW_EXPR_EXPRESSION (1)
+but the result of the DWARF-expression evaluation is
+the value of the \f(CWtable_column\fP (not
+the address of the value).
+This is a DWARF3/2 val_expression(E) rule.
+.in -4
+
+\f(CWdwarf_get_fde_info_for_reg\fP
+returns \f(CWDW_DLV_ERROR\fP if there is an error and
+if there is an error only the \f(CWerror\fP pointer is set, none
+of the other output arguments are touched.
+
+It is usable with either
+\f(CWdwarf_get_fde_n()\fP or \f(CWdwarf_get_fde_at_pc()\fP.
+
+
+.H 4 "dwarf_get_fde_info_for_cfa_reg3()"
+.DS
+ \f(CWint dwarf_get_fde_info_for_cfa_reg3(Dwarf_Fde fde,
+ Dwarf_Addr pc_requested,
+ Dwarf_Small * value_type,
+ Dwarf_Signed* offset_relevant,
+ Dwarf_Signed* register_num,
+ Dwarf_Signed* offset_or_block_len,
+ Dwarf_Ptr * block_ptr ,
+ Dwarf_Addr * row_pc_out,
+ Dwarf_Error * error)\fP
+.DE
+.P
+This is identical to \f(CWdwarf_get_fde_info_for_reg3()\fP
+except the returned values are for the CFA rule.
+So register number \f(CW*register_num\fP will be set
+to a real register, not one of the pseudo registers
+(which are usually
+DW_FRAME_CFA_COL3, DW_FRAME_SAME_VALUE, or
+DW_FRAME_UNDEFINED_VALUE).
+
+
+
+.H 4 "dwarf_get_fde_info_for_all_regs3()"
+.DS
+\f(CWint dwarf_get_fde_info_for_all_regs3(
+ Dwarf_Fde fde,
+ Dwarf_Addr pc_requested,
+ Dwarf_Regtable3 *reg_table,
+ Dwarf_Addr *row_pc,
+ Dwarf_Error *error)\fP
+.DE
+\f(CWdwarf_get_fde_info_for_all_regs3()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*reg_table\fP
+for the row specified by
+\f(CWpc_requested\fP for the FDE specified by \f(CWfde\fP.
+The intent is
+to return the rules for decoding all the registers, given a pc
+value.
+\f(CWreg_table\fP is an array of rules, the
+array size specified by the caller.
+plus a rule for the CFA.
+The rule for the cfa returned in \f(CW*reg_table\fP
+defines the CFA value at \f(CWpc_requested\fP
+The rule for each
+register contains several values that enable
+the consumer to determine the previous value
+of the register (see the earlier documentation of Dwarf_Regtable3).
+\f(CWdwarf_get_fde_info_for_reg3()\fP and
+the Dwarf_Regtable3 documentation above for a description of
+the values for each row.
+
+\f(CWdwarf_get_fde_info_for_all_regs3\fP returns \f(CWDW_DLV_ERROR\fP if there is an error.
+
+It is up to the caller to allocate space for
+\f(CW*reg_table\fP and initialize it properly.
+
+
+
+.H 4 "dwarf_get_fde_n()"
+.DS
+\f(CWint dwarf_get_fde_n(
+ Dwarf_Fde *fde_data,
+ Dwarf_Unsigned fde_index,
+ Dwarf_Fde *returned_fde
+ Dwarf_Error *error)\fP
+.DE
+\f(CWdwarf_get_fde_n()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CWreturned_fde\fP to
+the \f(CWDwarf_Fde\fP descriptor whose
+index is \f(CWfde_index\fP in the table of \f(CWDwarf_Fde\fP descriptors
+pointed to by \fPfde_data\fP.
+The index starts with 0.
+The table pointed to by fde_data is required to contain
+at least one entry. If the table has no entries at all
+the error checks may refer to uninitialized memory.
+Returns \f(CWDW_DLV_NO_ENTRY\fP if the index does not
+exist in the table of \f(CWDwarf_Fde\fP
+descriptors.
+Returns \f(CWDW_DLV_ERROR\fP if there is an error.
+This function cannot be used unless
+the block of \f(CWDwarf_Fde\fP descriptors has been created by a call to
+\f(CWdwarf_get_fde_list()\fP.
+
+.H 4 "dwarf_get_fde_at_pc()"
+.DS
+\f(CWint dwarf_get_fde_at_pc(
+ Dwarf_Fde *fde_data,
+ Dwarf_Addr pc_of_interest,
+ Dwarf_Fde *returned_fde,
+ Dwarf_Addr *lopc,
+ Dwarf_Addr *hipc,
+ Dwarf_Error *error)\fP
+.DE
+\f(CWdwarf_get_fde_at_pc()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CWreturned_fde\fP to
+a \f(CWDwarf_Fde\fP descriptor
+for a function which contains the pc value specified by \f(CWpc_of_interest\fP.
+In addition, it sets the locations pointed to
+by \f(CWlopc\fP and \f(CWhipc\fP to the low address and the high address
+covered by this FDE, respectively.
+The table pointed to by fde_data is required to contain
+at least one entry. If the table has no entries at all
+the error checks may refer to uninitialized memory.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It returns \f(CWDW_DLV_NO_ENTRY\fP
+if \f(CWpc_of_interest\fP is not in any of the
+FDEs represented by the block of \f(CWDwarf_Fde\fP descriptors pointed
+to by \f(CWfde_data\fP.
+This function cannot be used unless
+the block of \f(CWDwarf_Fde\fP descriptors has been created by a call to
+\f(CWdwarf_get_fde_list()\fP.
+
+.H 4 "dwarf_expand_frame_instructions()"
+.DS
+\f(CWint dwarf_expand_frame_instructions(
+ Dwarf_Cie cie,
+ Dwarf_Ptr instruction,
+ Dwarf_Unsigned i_length,
+ Dwarf_Frame_Op **returned_op_list,
+ Dwarf_Signed * returned_op_count,
+ Dwarf_Error *error);\fP
+.DE
+\f(CWdwarf_expand_frame_instructions()\fP is a High-level interface
+function which expands a frame instruction byte stream into an
+array of \f(CWDwarf_Frame_Op\fP structures.
+To indicate success, it returns \f(CWDW_DLV_OK\fP.
+The address where
+the byte stream begins is specified by \f(CWinstruction\fP, and
+the length of the byte stream is specified by \f(CWi_length\fP.
+The location pointed to by \f(CWreturned_op_list\fP is set to
+point to a table of
+\f(CWreturned_op_count\fP
+pointers to \f(CWDwarf_Frame_Op\fP which
+contain the frame instructions in the byte stream.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+After a successful return, the
+array of structures should be freed using
+\f(CWdwarf_dealloc()\fP with the allocation type \f(CWDW_DLA_FRAME_BLOCK\fP
+(when they are no longer of interest).
+.P
+Not all CIEs have the same address-size, so it is crucial
+that a CIE pointer to the frame's CIE be passed in.
+
+.in +2
+.DS
+\f(CWDwarf_Signed cnt;
+Dwarf_Frame_Op *frameops;
+Dwarf_Ptr instruction;
+Dwarf_Unsigned len;
+int res;
+
+res = expand_frame_instructions(dbg,instruction,len, &frameops,&cnt, &error);
+if (res == DW_DLV_OK) {
+ for (i = 0; i < cnt; ++i) {
+ /* use frameops[i] */
+ }
+ dwarf_dealloc(dbg, frameops, DW_DLA_FRAME_BLOCK);
+}\fP
+.DE
+.in -2
+.H 4 "dwarf_get_fde_exception_info()"
+.DS
+\f(CWint dwarf_get_fde_exception_info(
+ Dwarf_Fde fde,
+ Dwarf_Signed * offset_into_exception_tables,
+ Dwarf_Error * error);
+.DE
+\f(CWdwarf_get_fde_exception_info()\fP is an IRIX specific
+function which returns an exception table signed offset
+through \f(CWoffset_into_exception_tables\fP.
+The function never returns \f(CWDW_DLV_NO_ENTRY\fP.
+If \f(CWDW_DLV_NO_ENTRY\fP is NULL the function returns
+\f(CWDW_DLV_ERROR\fP.
+For non-IRIX objects the offset returned will always be zero.
+For non-C++ objects the offset returned will always be zero.
+The meaning of the offset and the content of the tables
+is not defined in this document.
+The applicable CIE augmentation string (see above)
+determines whether the value returned has meaning.
+
+.H 2 "Location Expression Evaluation"
+
+An "interpreter" which evaluates a location expression
+is required in any debugger. There is no interface defined
+here at this time.
+
+.P
+One problem with defining an interface is that operations are
+machine dependent: they depend on the interpretation of
+register numbers and the methods of getting values from the
+environment the expression is applied to.
+
+.P
+It would be desirable to specify an interface.
+
+.H 3 "Location List Internal-level Interface"
+
+.H 4 "dwarf_get_loclist_entry()"
+.DS
+\f(CWint dwarf_get_loclist_entry(
+ Dwarf_Debug dbg,
+ Dwarf_Unsigned offset,
+ Dwarf_Addr *hipc_offset,
+ Dwarf_Addr *lopc_offset,
+ Dwarf_Ptr *data,
+ Dwarf_Unsigned *entry_len,
+ Dwarf_Unsigned *next_entry,
+ Dwarf_Error *error)\fP
+.DE
+The function reads
+a location list entry starting at \f(CWoffset\fP and returns
+through pointers (when successful)
+the high pc \f(CWhipc_offset\fP, low pc
+\f(CWlopc_offset\fP, a pointer to the location description data
+\f(CWdata\fP, the length of the location description data
+\f(CWentry_len\fP, and the offset of the next location description
+entry \f(CWnext_entry\fP.
+.P
+This function will usually work correctly (meaning with most
+objects) but will not work correctly (and can crash
+an application calling it) if either
+some location list applies to a compilation unit with
+an address_size different from the overall address_size
+of the object file being read or if the .debug_loc section
+being read has random padding bytes between loclists.
+Neither of these characteristics necessarily represents
+a bug in the compiler/linker toolset that produced the
+object file being read. The DWARF standard
+allows both characteristics.
+.P
+\f(CWdwarf_dwarf_get_loclist_entry()\fP returns
+\f(CWDW_DLV_OK\fP if successful.
+\f(CWDW_DLV_NO_ENTRY\fP is returned when the offset passed
+in is beyond the end of the .debug_loc section (expected if
+you start at offset zero and proceed through all the entries).
+\f(CWDW_DLV_ERROR\fP is returned on error.
+.P
+The \f(CWhipc_offset\fP,
+low pc \f(CWlopc_offset\fP are offsets from the beginning of the
+current procedure, not genuine pc values.
+.in +2
+.DS
+\f(CW
+/* Looping through the dwarf_loc section finding loclists:
+ an example. */
+int res;
+Dwarf_Unsigned next_entry;
+Dwarf_unsigned offset=0;
+Dwarf_Addr hipc_off;
+Dwarf_Addr lopc_off;
+Dwarf_Ptr data;
+Dwarf_Unsigned entry_len;
+Dwarf_Unsigned next_entry;
+Dwarf_Error err;
+
+ for(;;) {
+ res = dwarf_get_loclist_entry(dbg,newoffset,&hipc_off,
+ &lowpc_off, &data, &entry_len,&next_entry,&err);
+ if (res == DW_DLV_OK) {
+ /* A valid entry. */
+ newoffset = next_entry;
+ continue;
+ } else if (res ==DW_DLV_NO_ENTRY) {
+ /* Done! */
+ break;
+ } else {
+ /* Error! */
+ break;
+ }
+
+
+ }
+}\fP
+.DE
+.in -2
+
+
+.H 2 "Abbreviations access"
+These are Internal-level Interface functions.
+Debuggers can ignore this.
+
+.H 3 "dwarf_get_abbrev()"
+.DS
+\f(CWint dwarf_get_abbrev(
+ Dwarf_Debug dbg,
+ Dwarf_Unsigned offset,
+ Dwarf_Abbrev *returned_abbrev,
+ Dwarf_Unsigned *length,
+ Dwarf_Unsigned *attr_count,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_get_abbrev()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*returned_abbrev\fP to
+\f(CWDwarf_Abbrev\fP
+descriptor for an abbreviation at offset \f(CW*offset\fP in the abbreviations
+section (i.e .debug_abbrev) on success.
+The user is responsible for making sure that
+a valid abbreviation begins at \f(CWoffset\fP in the abbreviations section.
+The location pointed to by \f(CWlength\fP
+is set to the length in bytes of the abbreviation in the abbreviations
+section.
+The location pointed to by \f(CWattr_count\fP is set to the
+number of attributes in the abbreviation.
+An abbreviation entry with a
+length of 1 is the 0 byte of the last abbreviation entry of a compilation
+unit.
+\f(CWdwarf_get_abbrev()\fP returns \f(CWDW_DLV_ERROR\fP on error.
+If the call succeeds, the storage pointed to
+by \f(CW*returned_abbrev\fP
+should be freed, using \f(CWdwarf_dealloc()\fP with the
+allocation type \f(CWDW_DLA_ABBREV\fP when no longer needed.
+
+
+.H 3 "dwarf_get_abbrev_tag()"
+.DS
+\f(CWint dwarf_get_abbrev_tag(
+ Dwarf_abbrev abbrev,
+ Dwarf_Half *return_tag,
+ Dwarf_Error *error);\fP
+.DE
+If successful,
+\f(CWdwarf_get_abbrev_tag()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_tag\fP to
+the \fItag\fP of
+the given abbreviation.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+
+.H 3 "dwarf_get_abbrev_code()"
+.DS
+\f(CWint dwarf_get_abbrev_code(
+ Dwarf_abbrev abbrev,
+ Dwarf_Unsigned *return_code,
+ Dwarf_Error *error);\fP
+.DE
+If successful,
+\f(CWdwarf_get_abbrev_code()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*return_code\fP to
+the abbreviation code of
+the given abbreviation.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It never returns \f(CWDW_DLV_NO_ENTRY\fP.
+
+.H 3 "dwarf_get_abbrev_children_flag()"
+.DS
+\f(CWint dwarf_get_abbrev_children_flag(
+ Dwarf_Abbrev abbrev,
+ Dwarf_Signed *returned_flag,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_get_abbrev_children_flag()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CWreturned_flag\fP to
+\f(CWDW_children_no\fP (if the given abbreviation indicates that
+a die with that abbreviation has no children) or
+\f(CWDW_children_yes\fP (if the given abbreviation indicates that
+a die with that abbreviation has a child).
+It returns \f(CWDW_DLV_ERROR\fP on error.
+
+.H 3 "dwarf_get_abbrev_entry()"
+.DS
+\f(CWint dwarf_get_abbrev_entry(
+ Dwarf_Abbrev abbrev,
+ Dwarf_Signed index,
+ Dwarf_Half *attr_num,
+ Dwarf_Signed *form,
+ Dwarf_Off *offset,
+ Dwarf_Error *error)\fP
+
+.DE
+If successful,
+\f(CWdwarf_get_abbrev_entry()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*attr_num\fP to the attribute code of
+the attribute
+whose index is specified by \f(CWindex\fP in the given abbreviation.
+The index starts at 0.
+The location pointed to by \f(CWform\fP is set
+to the form of the attribute.
+The location pointed to by \f(CWoffset\fP
+is set to the byte offset of the attribute in the abbreviations section.
+It returns \f(CWDW_DLV_NO_ENTRY\fP if the index specified is outside
+the range of attributes in this abbreviation.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+
+.H 2 "String Section Operations"
+The .debug_str section contains only strings. Debuggers need
+never use this interface: it is only for debugging problems with
+the string section itself.
+
+.H 3 "dwarf_get_str()"
+.DS
+\f(CWint dwarf_get_str(
+ Dwarf_Debug dbg,
+ Dwarf_Off offset,
+ char **string,
+ Dwarf_Signed *returned_str_len,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_get_str()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*returned_str_len\fP to
+the length of
+the string, not counting the null terminator, that begins at the offset
+specified by \f(CWoffset\fP in the .debug_str section.
+The location
+pointed to by \f(CWstring\fP is set to a pointer to this string.
+The next string in the .debug_str
+section begins at the previous \f(CWoffset\fP + 1 + \f(CW*returned_str_len\fP.
+A zero-length string is NOT the end of the section.
+If there is no .debug_str section, \f(CWDW_DLV_NO_ENTRY\fP is returned.
+If there is an error, \f(CWDW_DLV_ERROR\fP is returned.
+If we are at the end of the section (that is, \f(CWoffset\fP
+is one past the end of the section) \f(CWDW_DLV_NO_ENTRY\fP is returned.
+If the \f(CWoffset\fP is some other too-large value then
+\f(CWDW_DLV_ERROR\fP is returned.
+
+.H 2 "Address Range Operations"
+These functions provide information about address ranges. Address
+ranges map ranges of pc values to the corresponding compilation-unit
+die that covers the address range.
+
+.H 3 "dwarf_get_aranges()"
+.DS
+\f(CWint dwarf_get_aranges(
+ Dwarf_Debug dbg,
+ Dwarf_Arange **aranges,
+ Dwarf_Signed * returned_arange_count,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_get_aranges()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*returned_arange_count\fP to
+the count of the
+number of address ranges in the .debug_aranges section
+(for all compilation units).
+It sets
+\f(CW*aranges\fP to point to a block of \f(CWDwarf_Arange\fP
+descriptors, one for each address range.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It returns \f(CWDW_DLV_NO_ENTRY\fP if there is no .debug_aranges
+section.
+
+.in +2
+.DS
+\f(CWDwarf_Signed cnt;
+Dwarf_Arange *arang;
+int res;
+
+res = dwarf_get_aranges(dbg, &arang,&cnt, &error);
+if (res == DW_DLV_OK) {
+
+ for (i = 0; i < cnt; ++i) {
+ /* use arang[i] */
+ dwarf_dealloc(dbg, arang[i], DW_DLA_ARANGE);
+ }
+ dwarf_dealloc(dbg, arang, DW_DLA_LIST);
+}\fP
+.DE
+.in -2
+
+.H 3 "dwarf_get_arange()"
+.DS
+\f(CWint dwarf_get_arange(
+ Dwarf_Arange *aranges,
+ Dwarf_Unsigned arange_count,
+ Dwarf_Addr address,
+ Dwarf_Arange *returned_arange,
+ Dwarf_Error *error);\fP
+.DE
+The function \f(CWdwarf_get_arange()\fP takes as input a pointer
+to a block of \f(CWDwarf_Arange\fP pointers, and a count of the
+number of descriptors in the block.
+It then searches for the
+descriptor that covers the given \f(CWaddress\fP.
+If it finds
+one, it returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*returned_arange\fP to
+the descriptor.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It returns \f(CWDW_DLV_NO_ENTRY\fP if there is no .debug_aranges
+entry covering that address.
+
+
+
+
+
+.H 3 "dwarf_get_cu_die_offset()"
+.DS
+\f(CWint dwarf_get_cu_die_offset(
+ Dwarf_Arange arange,
+ Dwarf_Off *returned_cu_die_offset,
+ Dwarf_Error *error);\fP
+.DE
+The function \f(CWdwarf_get_cu_die_offset()\fP takes a
+\f(CWDwarf_Arange\fP descriptor as input, and
+if successful returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*returned_cu_die_offset\fP to
+the offset
+in the .debug_info section of the compilation-unit DIE for the
+compilation-unit represented by the given address range.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+
+.H 3 "dwarf_get_arange_cu_header_offset()"
+.DS
+\f(CWint dwarf_get_arange_cu_header_offset(
+ Dwarf_Arange arange,
+ Dwarf_Off *returned_cu_header_offset,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_get_arange_cu_header_offset()\fP takes a
+\f(CWDwarf_Arange\fP descriptor as input, and
+if successful returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*returned_cu_header_offset\fP to
+the offset
+in the .debug_info section of the compilation-unit header for the
+compilation-unit represented by the given address range.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+
+This function added Rev 1.45, June, 2001.
+
+This function is declared as 'optional' in libdwarf.h
+on IRIX systems so the _MIPS_SYMBOL_PRESENT
+predicate may be used at run time to determine if the version of
+libdwarf linked into an application has this function.
+
+
+
+.H 3 "dwarf_get_arange_info()"
+.DS
+\f(CWint dwarf_get_arange_info(
+ Dwarf_Arange arange,
+ Dwarf_Addr *start,
+ Dwarf_Unsigned *length,
+ Dwarf_Off *cu_die_offset,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_get_arange_info()\fP returns
+\f(CWDW_DLV_OK\fP
+and
+stores the starting value of the address range in the location pointed
+to by \f(CWstart\fP, the length of the address range in the location
+pointed to by \f(CWlength\fP, and the offset in the .debug_info section
+of the compilation-unit DIE for the compilation-unit represented by the
+address range.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+
+.H 2 "General Low Level Operations"
+This function is low-level and intended for use only
+by programs such as dwarf-dumpers.
+
+.H 3 "dwarf_get_address_size()"
+.DS
+\f(CWint dwarf_get_address_size(Dwarf_Debug dbg,
+ Dwarf_Half *addr_size,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_get_address_size()\fP
+returns \f(CWDW_DLV_OK\fP on success and sets
+the \f(CW*addr_size\fP
+to the size in bytes of an address.
+In case of error, it returns \f(CWDW_DLV_ERROR\fP
+and does not set \f(CW*addr_size\fP.
+
+The address size returned is the overall address size,
+which can be misleading if different compilation
+units have different address sizes.
+Many ABIs have only a single address size per
+executable, but differing address sizes are
+becoming more common.
+
+Use \f(CWdwarf_get_die_address_size()\fP
+instead whenever possible.
+
+.H 3 "dwarf_get_die_address_size()"
+.DS
+\f(CWint dwarf_get_die_address_size(Dwarf_Die die,
+ Dwarf_Half *addr_size,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_get_die_address_size()\fP
+returns \f(CWDW_DLV_OK\fP on success and sets
+the \f(CW*addr_size\fP
+to the size in bytes of an address.
+In case of error, it returns \f(CWDW_DLV_ERROR\fP
+and does not set \f(CW*addr_size\fP.
+
+The address size returned is the address size
+of the compilation unit owning the \f(CWdie\fP
+
+This is the preferred way to get address size when the
+\f(CWDwarf_Die\fP is known.
+
+
+.H 2 "Ranges Operations (.debug_ranges)"
+
+
+.H 2 "Ranges Operations (.debug_ranges)"
+These functions provide information about the address ranges
+indicated by a \f(CWDW_AT_ranges\fP attribute (the ranges are recorded
+in the \f(CW.debug_ranges\fP section) of a DIE.
+Each call of \f(CWdwarf_get_ranges_a()\fP
+or \f(CWdwarf_get_ranges()\fP
+returns a an array
+of Dwarf_Ranges structs, each of which represents a single ranges
+entry. The struct is defined in \f(CWlibdwarf.h\fP.
+
+
+.H 3 "dwarf_get_ranges()"
+This is the original call and it will work fine when
+all compilation units have the same address_size.
+There is no \f(CWdie\fP argument to this original
+version of the function.
+Other arguments (and deallocation) match the use
+of \f(CWdwarf_get_ranges_a()\fP ( described next).
+
+.H 3 "dwarf_get_ranges_a()"
+.DS
+\f(CWint dwarf_get_ranges_a(
+ Dwarf_Debug dbg,
+ Dwarf_Off offset,
+ Dwarf_Die die,
+ Dwarf_Ranges **ranges,
+ Dwarf_Signed * returned_ranges_count,
+ Dwarf_Unsigned * returned_byte_count,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_get_ranges_a()\fP returns
+\f(CWDW_DLV_OK\fP and sets \f(CW*returned_ranges_count\fP to
+the count of the
+number of address ranges in the group of ranges
+in the .debug_ranges section at offset \f(CWoffset\fP
+(which ends with a pair of zeros of pointer-size).
+This function is new as of 27 April 2009.
+
+The
+\f(CWoffset\fP argument should be the value of
+a \f(CWDW_AT_ranges\fP attribute of a Debugging Information Entry.
+
+The
+\f(CWdie\fP argument should be the value of
+a \f(CWDwarf_Die\fP pointer of a \f(CWDwarf_Die\fP with
+the attribute containing
+this range set offset. Because each compilation unit
+has its own address_size field this argument is necessary to
+to correctly read ranges. (Most executables have the
+same address_size in every compilation unit, but
+some ABIs allow multiple address sized in an executable).
+If a NULL pointer is passed in libdwarf assumes
+a single address_size is appropriate for all ranges records.
+
+The call sets
+\f(CW*ranges\fP to point to a block of \f(CWDwarf_Ranges\fP
+structs, one for each address range.
+It returns \f(CWDW_DLV_ERROR\fP on error.
+It returns \f(CWDW_DLV_NO_ENTRY\fP if there is no \f(CW.debug_ranges\fP
+section or if \f(CWoffset\fP is past the end of the
+\f(CW.debug_ranges\fP section.
+
+If the \f(CW*returned_byte_count\fP pointer is passed as non-NULL
+the number of bytes that the returned ranges
+were taken from is returned through the pointer
+(for example if the returned_ranges_count is 2 and the pointer-size
+is 4, then returned_byte_count will be 8).
+If the \f(CW*returned_byte_count\fP pointer is passed as NULL
+the parameter is ignored.
+The \f(CW*returned_byte_count\fP is only of use to certain
+dumper applications, most applications will not use it.
+
+
+.in +2
+.DS
+\f(CWDwarf_Signed cnt;
+Dwarf_Ranges *ranges;
+Dwarf_Unsigned bytes;
+int res;
+res = dwarf_get_ranges_a(dbg,off,dieptr, &ranges,&cnt,&bytes,&error);
+if (res == DW_DLV_OK) {
+ Dwarf_Signed i;
+ for( i = 0; i < cnt; ++i ) {
+ Dwarf_Ranges *cur = ranges+i;
+ /* Use cur. */
+ }
+ dwarf_ranges_dealloc(dbg,ranges,cnt);
+}\fP
+.DE
+.in -2
+
+.H 3 "dwarf_ranges_dealloc()"
+.DS
+\f(CWint dwarf_ranges_dealloc(
+ Dwarf_Debug dbg,
+ Dwarf_Ranges *ranges,
+ Dwarf_Signed range_count,
+ );\fP
+.DE
+The function \f(CWdwarf_ranges_dealloc()\fP takes as input a pointer
+to a block of \f(CWDwarf_Ranges\fP array and the
+number of structures in the block.
+It frees all the data in the array of structures.
+
+.H 2 "TAG ATTR etc names as strings"
+These functions turn a value into a string.
+So applications wanting the string "DW_TAG_compile_unit"
+given the value 0x11 (the value defined for this TAG) can do so easily.
+
+The general form is
+.in +2
+.DS
+\f(CWint dwarf_get_<something>_name(
+ unsigned value,
+ char **s_out,
+ );\fP
+.DE
+.in -2
+
+If the \f(CWvalue\fP passed in is known, the function
+returns \f(CWDW_DLV_OK\fP and places a pointer to the appropriate string
+into \f(CW*s_out\fP. The string is in static storage
+and applications must never free the string.
+If the \f(CWvalue\fP is not known, \f(CWDW_DLV_NO_ENTRY\fP is returned
+and \f(CW*s_out\fP is not set. \f(CWDW_DLV_ERROR\fP is never returned.
+
+\f(CWLibdwarf\fP generates these functions at libdwarf build time
+by reading dwarf.h.
+
+All these follow this pattern rigidly, so the details of each
+are not repeated for each function.
+
+The choice of 'unsigned' for the value type argument (the code value)
+argument is somewhat arbitrary, 'int' could have been used.
+
+The library simply assumes the value passed in is applicable.
+So, for example,
+passing a TAG value code to \f(CWdwarf_get_ACCESS_name()\fP
+is a coding error which libdwarf will process as if it was
+an accessibility code value.
+Examples of bad and good usage are:
+
+.in +2
+.DS
+\f(CW
+ const char * out;
+ int res;
+ /* The following is wrong, do not do it! */
+ res = dwarf_get_ACCESS_name(DW_TAG_entry_point,&out);
+ /* Nothing one does here with 'res' or 'out'
+ is meaningful. */
+
+ /* The following is meaningful.*/
+ res = dwarf_get_TAG_name(DW_TAG_entry_point,&out);
+ if( res == DW_DLV_OK) {
+ /* Here 'out' is a pointer one can use which
+ points to the string "DW_TAG_entry_point". */
+ } else {
+ /* Here 'out' has not been touched, it is
+ uninitialized. Do not use it. */
+ }
+\fP
+.DE
+.in -2
+
+
+
+
+.H 2 "dwarf_get_ACCESS_name()"
+Returns an accessibility code name through the \f(CWs_out\fP pointer.
+.H 2 "dwarf_get_AT_name()"
+Returns an attribute code name through the \f(CWs_out\fP pointer.
+.H 2 "dwarf_get_ATE_name()"
+Returns a base type encoding name through the \f(CWs_out\fP pointer.
+.H 2 "dwarf_get_ADDR_name()"
+Returns an address type encoding name through the \f(CWs_out\fP pointer.
+As of this writing only \f(CWDW_ADDR_none\fP is defined in \f(CWdwarf.h\fP.
+.H 2 "dwarf_get_ATCF_name()"
+Returns a SUN code flag encoding name through the \f(CWs_out\fP pointer.
+This code flag is entirely a DWARF extension.
+.H 2 "dwarf_get_CHILDREN_name()"
+Returns a child determination name (which
+is seen in the abbreviations section data) through the \f(CWs_out\fP pointer.
+The only value this recognizes for a 'yes' value is 1.
+As a flag value this is not quite correct (any non-zero value means
+yes) but dealing with this is left up to client code (normally
+compilers really do emit a value of 1 for a flag).
+.H 2 "dwarf_get_children_name()"
+Returns a child determination name through the \f(CWs_out\fP pointer,
+though this version is really a libdwarf artifact.
+The standard function is \f(CWdwarf_get_CHILDREN_name()\fP
+which appears just above.
+As a flag value this is not quite correct (any non-zero value means
+yes) but dealing with this is left up to client code (normally
+compilers really do emit a value of 1 for a flag).
+.H 2 "dwarf_get_CC_name()"
+Returns a calling convention case code name through the \f(CWs_out\fP pointer.
+.H 2 "dwarf_get_CFA_name()"
+Returns a call frame information instruction
+name through the \f(CWs_out\fP pointer.
+.H 2 "dwarf_get_DS_name()"
+Returns a decimal sign code name through the \f(CWs_out\fP pointer.
+.H 2 "dwarf_get_DSC_name()"
+Returns a discriminant descriptor code name through the \f(CWs_out\fP pointer.
+.H 2 "dwarf_get_EH_name()"
+Returns a GNU exception header
+code name through the \f(CWs_out\fP pointer.
+.H 2 "dwarf_get_END_name()"
+Returns an endian code name through the \f(CWs_out\fP pointer.
+.H 2 "dwarf_get_FORM_name()"
+Returns an form code name through the \f(CWs_out\fP pointer.
+.H 2 "dwarf_get_FRAME_name()"
+Returns a frame code name through the \f(CWs_out\fP pointer.
+These are dependent on the particular ABI, so unless the
+\f(CWdwarf.h\fP used to generate libdwarf matches your ABI
+these names are unlikely to be very useful and certainly
+won't be entirely appropriate.
+.H 2 "dwarf_get_ID_name()"
+Returns an identifier case code name through the \f(CWs_out\fP pointer.
+.H 2 "dwarf_get_INL_name()"
+Returns an inline code name through the \f(CWs_out\fP pointer.
+.H 2 "dwarf_get_LANG_name()"
+Returns a language code name through the \f(CWs_out\fP pointer.
+.H 2 "dwarf_get_LNE_name()"
+Returns a line table extended
+opcode code name through the \f(CWs_out\fP pointer.
+.H 2 "dwarf_get_LNS_name()"
+Returns a line table standard
+opcode code name through the \f(CWs_out\fP pointer.
+.H 2 "dwarf_get_MACINFO_name()"
+Returns a macro information macinfo
+code name through the \f(CWs_out\fP pointer.
+.H 2 "dwarf_get_OP_name()"
+Returns a DWARF expression operation
+code name through the \f(CWs_out\fP pointer.
+.H 2 "dwarf_get_ORD_name()"
+Returns an array ordering code name through the \f(CWs_out\fP pointer.
+.H 2 "dwarf_get_TAG_name()"
+Returns a TAG name through the \f(CWs_out\fP pointer.
+.H 2 "dwarf_get_VIRTUALITY_name()"
+Returns a virtuality code name through the \f(CWs_out\fP pointer.
+.H 2 "dwarf_get_VIS_name()"
+Returns a visibility code name through the \f(CWs_out\fP pointer.
+
+
+.H 2 "Section Operations"
+In checking DWARF in linkonce sections for correctness
+it has been found useful to have certain section-oriented
+operations when processing object files.
+Normally these operations are not needed or useful
+in a fully-linked executable or shared library.
+
+While the code is written with Elf sections in mind,
+it is quite possible to process non-Elf objects
+with code that implements certain function pointers
+(see \f(CWstruct Dwarf_Obj_Access_interface_s\fP).
+
+So far no one with such non-elf code has come forward
+to open-source it.
+
+.H 3 "dwarf_get_section_count()"
+.DS
+\f(CWint dwarf_get_section_count(
+ Dwarf_Debug dbg) \fP
+.DE
+
+Returns a count of the number of object sections found.
+
+
+
+.H 3 "dwarf_get_section_info_by_name()"
+.DS
+\f(CWint dwarf_get_section_info_by_name(
+ const char *section_name,
+ Dwarf_Addr *section_addr,
+ Dwarf_Unsigned *section_size,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_get_section_info_by_name()\fP
+returns \f(CWDW_DLV_OK\fP if the section given by \f(CWsection_name\fP
+was seen by libdwarf.
+On success it sets \f(CW*section_addr\fP to the virtual address
+assigned to the section by the linker or compiler and \f(CW*section_size\fP
+to the size of the object section.
+
+It returns DW_DLV_ERROR on error.
+.H 3 "dwarf_get_section_info_by_index()"
+.DS
+\f(CWint dwarf_get_section_info_by_index(
+ int section_index,
+ const char **section_name,
+ Dwarf_Addr *section_addr,
+ Dwarf_Unsigned *section_size,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_get_section_info_by_index()\fP
+returns \f(CWDW_DLV_OK\fP if the section given by \f(CWsection_index\fP
+was seen by libdwarf.
+\f(CW*section_addr\fP to the virtual address
+assigned to the section by the linker or compiler
+and \f(CW*section_size\fP
+to the size of the object section.
+
+No free or deallocate of information returned should be done by
+callers.
+
+
+.H 2 "Utility Operations"
+These functions aid in the management of errors encountered when using
+functions in the \fIlibdwarf\fP library and releasing memory allocated
+as a result of a \fIlibdwarf\fP operation.
+
+.H 3 "dwarf_errno()"
+.DS
+\f(CWDwarf_Unsigned dwarf_errno(
+ Dwarf_Error error)\fP
+.DE
+The function \f(CWdwarf_errno()\fP returns the error number corresponding
+to the error specified by \f(CWerror\fP.
+
+.H 3 "dwarf_errmsg()"
+.DS
+\f(CWconst char* dwarf_errmsg(
+ Dwarf_Error error)\fP
+.DE
+The function \f(CWdwarf_errmsg()\fP returns a pointer to a
+null-terminated error message string corresponding to the error specified by
+\f(CWerror\fP.
+The string returned by \f(CWdwarf_errmsg()\fP
+should not be deallocated using \f(CWdwarf_dealloc()\fP.
+
+.H 3 "dwarf_get_harmless_error_list()"
+.DS
+\f(CWint dwarf_get_harmless_error_list(Dwarf_Debug dbg,
+ unsigned count,
+ const char ** errmsg_ptrs_array,
+ unsigned * newerr_count);\fP
+.DE
+The harmless errors are not denoted by error returns from
+the other libdwarf functions. Instead, this function
+returns strings of any harmless errors that have been
+seen in the current object. Clients never need call this, but
+if a client wishes to report any such errors it may call.
+
+Only a fixed number of harmless errors are recorded. It
+is a circular list, so if more than the current maximum
+is encountered older harmless error messages are lost.
+
+The caller passes in a pointer to an array of pointer-to-char
+as the argument \f(CWerrmsg_ptrs_array\fP. The caller
+must provide this array, libdwarf does not provide it.
+The caller need not initialize the array elements.
+
+The caller passes in the number of elements of the array of
+pointer-to-char thru \f(CWcount\fP. Since the
+
+If there are no unreported harmless errors the function
+returns \f(CWDW_DLV_NO_ENTRY\fP and the function arguments
+are ignored.
+Otherwise the function returns \f(CWDW_DLV_OK\fP
+and uses the arguments.
+
+\f(CWlibdwarf\fP assigns error strings to the errmsg_ptrs_array.
+The MININUM(count-1, number of messages recorded) pointers are assigned
+to the array. The array is terminated with a NULL pointer.
+(That is, one array entry is reserved for a NULL pointer).
+So if \f(CWcount\fP is 5 up to 4 strings may be returned through
+the array, and one array entry is set to NULL.
+
+Because the list is circular and messages may have been dropped
+the function also returns the actual error count of harmless
+errors encountered through \f(CWnewerr_count\fP
+(unless the argument is NULL, in which case it is ignored).
+
+Each call to this function resets the circular error buffer and
+the error count.
+So think of this call as reporting harmless errors since the
+last call to it.
+
+The pointers returned through \f(CWerrmsg_ptrs_array\fP
+are only valid till the next call to libdwarf.
+Do not save the pointers, they become invalid. Copy the strings
+if you wish to save them.
+
+Calling this function neither allocates any space in memory nor
+frees any space in memory.
+
+
+.H 3 "dwarf_insert_harmless_error()"
+.DS
+void dwarf_insert_harmless_error(Dwarf_Debug dbg,
+ char * newerror);
+.DE
+This function is used to test
+\f(CWdwarf_get_harmless_error_list\fP. It simply adds
+a harmless error string.
+There is little reason client code should use this function.
+It exists so that the harmless error functions can be
+easily tested for correctness and leaks.
+
+.H 3 "dwarf_set_harmless_error_list_size()"
+.DS
+\f(CWunsigned dwarf_set_harmless_error_list_size(Dwarf_Debug dbg,
+ unsigned maxcount)\fP
+.DE
+\f(CWdwarf_set_harmless_error_list_size\fP returns the
+number of harmless error strings the library is currently
+set to hold.
+If \f(CWmaxcount\fP is non-zero the library changes the
+maximum it will record to be \f(CWmaxcount\fP.
+
+It is extremely unwise to make \f(CWmaxcount\fP large because
+\f(CWlibdwarf\fP allocates space for \f(CWmaxcount\fP
+strings immediately.
+
+.P
+The set of errors
+enumerated in Figure \n(aX below were defined in Dwarf 1.
+These errors are not used by the \f(CWlibdwarf\fP implementation
+for Dwarf 2 or later.
+.DS
+.TS
+center box, tab(:);
+lfB lfB
+l l.
+SYMBOLIC NAME:DESCRIPTION
+_
+DW_DLE_NE:No error (0)
+DW_DLE_VMM:Version of DWARF information newer than libdwarf
+DW_DLE_MAP:Memory map failure
+DW_DLE_LEE:Propagation of libelf error
+DW_DLE_NDS:No debug section
+DW_DLE_NLS:No line section
+DW_DLE_ID:Requested information not associated with descriptor
+DW_DLE_IOF:I/O failure
+DW_DLE_MAF:Memory allocation failure
+DW_DLE_IA:Invalid argument
+DW_DLE_MDE:Mangled debugging entry
+DW_DLE_MLE:Mangled line number entry
+DW_DLE_FNO:File descriptor does not refer to an open file
+DW_DLE_FNR:File is not a regular file
+DW_DLE_FWA:File is opened with wrong access
+DW_DLE_NOB:File is not an object file
+DW_DLE_MOF:Mangled object file header
+DW_DLE_EOLL:End of location list entries
+DW_DLE_NOLL:No location list section
+DW_DLE_BADOFF:Invalid offset
+DW_DLE_EOS:End of section
+DW_DLE_ATRUNC:Abbreviations section appears truncated
+DW_DLE_BADBITC:Address size passed to dwarf bad
+.TE
+.FG "List of Dwarf Error Codes"
+.DE
+
+The set of errors returned by \f(CWLibdwarf\fP functions
+is listed below.
+Some of the errors are SGI specific.
+
+.DS
+.TS
+center box, tab(:);
+lfB lfB
+l l.
+SYMBOLIC NAME:DESCRIPTION
+_
+DW_DLE_DBG_ALLOC:Could not allocate Dwarf_Debug struct
+DW_DLE_FSTAT_ERROR:Error in fstat()-ing object
+DW_DLE_FSTAT_MODE_ERROR:Error in mode of object file
+DW_DLE_INIT_ACCESS_WRONG:Incorrect access to dwarf_init()
+DW_DLE_ELF_BEGIN_ERROR:Error in elf_begin() on object
+DW_DLE_ELF_GETEHDR_ERROR:Error in elf_getehdr() on object
+DW_DLE_ELF_GETSHDR_ERROR:Error in elf_getshdr() on object
+DW_DLE_ELF_STRPTR_ERROR:Error in elf_strptr() on object
+DW_DLE_DEBUG_INFO_DUPLICATE:Multiple .debug_info sections
+DW_DLE_DEBUG_INFO_NULL:No data in .debug_info section
+DW_DLE_DEBUG_ABBREV_DUPLICATE:Multiple .debug_abbrev sections
+DW_DLE_DEBUG_ABBREV_NULL:No data in .debug_abbrev section
+DW_DLE_DEBUG_ARANGES_DUPLICATE:Multiple .debug_arange sections
+DW_DLE_DEBUG_ARANGES_NULL:No data in .debug_arange section
+DW_DLE_DEBUG_LINE_DUPLICATE:Multiple .debug_line sections
+DW_DLE_DEBUG_LINE_NULL:No data in .debug_line section
+DW_DLE_DEBUG_LOC_DUPLICATE:Multiple .debug_loc sections
+DW_DLE_DEBUG_LOC_NULL:No data in .debug_loc section
+DW_DLE_DEBUG_MACINFO_DUPLICATE:Multiple .debug_macinfo sections
+DW_DLE_DEBUG_MACINFO_NULL:No data in .debug_macinfo section
+DW_DLE_DEBUG_PUBNAMES_DUPLICATE:Multiple .debug_pubnames sections
+DW_DLE_DEBUG_PUBNAMES_NULL:No data in .debug_pubnames section
+DW_DLE_DEBUG_STR_DUPLICATE:Multiple .debug_str sections
+DW_DLE_DEBUG_STR_NULL:No data in .debug_str section
+DW_DLE_CU_LENGTH_ERROR:Length of compilation-unit bad
+DW_DLE_VERSION_STAMP_ERROR:Incorrect Version Stamp
+DW_DLE_ABBREV_OFFSET_ERROR:Offset in .debug_abbrev bad
+DW_DLE_ADDRESS_SIZE_ERROR:Size of addresses in target bad
+DW_DLE_DEBUG_INFO_PTR_NULL:Pointer into .debug_info in DIE null
+DW_DLE_DIE_NULL:Null Dwarf_Die
+DW_DLE_STRING_OFFSET_BAD:Offset in .debug_str bad
+DW_DLE_DEBUG_LINE_LENGTH_BAD:Length of .debug_line segment bad
+DW_DLE_LINE_PROLOG_LENGTH_BAD:Length of .debug_line prolog bad
+DW_DLE_LINE_NUM_OPERANDS_BAD:Number of operands to line instr bad
+DW_DLE_LINE_SET_ADDR_ERROR:Error in DW_LNE_set_address instruction
+DW_DLE_LINE_EXT_OPCODE_BAD:Error in DW_EXTENDED_OPCODE instruction
+DW_DLE_DWARF_LINE_NULL:Null Dwarf_line argument
+DW_DLE_INCL_DIR_NUM_BAD:Error in included directory for given line
+DW_DLE_LINE_FILE_NUM_BAD:File number in .debug_line bad
+DW_DLE_ALLOC_FAIL:Failed to allocate required structs
+DW_DLE_DBG_NULL:Null Dwarf_Debug argument
+DW_DLE_DEBUG_FRAME_LENGTH_BAD:Error in length of frame
+DW_DLE_FRAME_VERSION_BAD:Bad version stamp for frame
+DW_DLE_CIE_RET_ADDR_REG_ERROR:Bad register specified for return address
+DW_DLE_FDE_NULL:Null Dwarf_Fde argument
+DW_DLE_FDE_DBG_NULL:No Dwarf_Debug associated with FDE
+DW_DLE_CIE_NULL:Null Dwarf_Cie argument
+DW_DLE_CIE_DBG_NULL:No Dwarf_Debug associated with CIE
+DW_DLE_FRAME_TABLE_COL_BAD:Bad column in frame table specified
+.TE
+.FG "List of Dwarf 2 Error Codes (continued)"
+.DE
+
+.DS
+.TS
+center box, tab(:);
+lfB lfB
+l l.
+SYMBOLIC NAME:DESCRIPTION
+_
+DW_DLE_PC_NOT_IN_FDE_RANGE:PC requested not in address range of FDE
+DW_DLE_CIE_INSTR_EXEC_ERROR:Error in executing instructions in CIE
+DW_DLE_FRAME_INSTR_EXEC_ERROR:Error in executing instructions in FDE
+DW_DLE_FDE_PTR_NULL:Null Pointer to Dwarf_Fde specified
+DW_DLE_RET_OP_LIST_NULL:No location to store pointer to Dwarf_Frame_Op
+DW_DLE_LINE_CONTEXT_NULL:Dwarf_Line has no context
+DW_DLE_DBG_NO_CU_CONTEXT:dbg has no CU context for dwarf_siblingof()
+DW_DLE_DIE_NO_CU_CONTEXT:Dwarf_Die has no CU context
+DW_DLE_FIRST_DIE_NOT_CU:First DIE in CU not DW_TAG_compilation_unit
+DW_DLE_NEXT_DIE_PTR_NULL:Error in moving to next DIE in .debug_info
+DW_DLE_DEBUG_FRAME_DUPLICATE:Multiple .debug_frame sections
+DW_DLE_DEBUG_FRAME_NULL:No data in .debug_frame section
+DW_DLE_ABBREV_DECODE_ERROR:Error in decoding abbreviation
+DW_DLE_DWARF_ABBREV_NULL:Null Dwarf_Abbrev specified
+DW_DLE_ATTR_NULL:Null Dwarf_Attribute specified
+DW_DLE_DIE_BAD:DIE bad
+DW_DLE_DIE_ABBREV_BAD:No abbreviation found for code in DIE
+DW_DLE_ATTR_FORM_BAD:Inappropriate attribute form for attribute
+DW_DLE_ATTR_NO_CU_CONTEXT:No CU context for Dwarf_Attribute struct
+DW_DLE_ATTR_FORM_SIZE_BAD:Size of block in attribute value bad
+DW_DLE_ATTR_DBG_NULL:No Dwarf_Debug for Dwarf_Attribute struct
+DW_DLE_BAD_REF_FORM:Inappropriate form for reference attribute
+DW_DLE_ATTR_FORM_OFFSET_BAD:Offset reference attribute outside current CU
+DW_DLE_LINE_OFFSET_BAD:Offset of lines for current CU outside .debug_line
+DW_DLE_DEBUG_STR_OFFSET_BAD:Offset into .debug_str past its end
+DW_DLE_STRING_PTR_NULL:Pointer to pointer into .debug_str NULL
+DW_DLE_PUBNAMES_VERSION_ERROR:Version stamp of pubnames incorrect
+DW_DLE_PUBNAMES_LENGTH_BAD:Read pubnames past end of .debug_pubnames
+DW_DLE_GLOBAL_NULL:Null Dwarf_Global specified
+DW_DLE_GLOBAL_CONTEXT_NULL:No context for Dwarf_Global given
+DW_DLE_DIR_INDEX_BAD:Error in directory index read
+DW_DLE_LOC_EXPR_BAD:Bad operator read for location expression
+DW_DLE_DIE_LOC_EXPR_BAD:Expected block value for attribute not found
+DW_DLE_OFFSET_BAD:Offset for next compilation-unit in .debug_info bad
+DW_DLE_MAKE_CU_CONTEXT_FAIL:Could not make CU context
+DW_DLE_ARANGE_OFFSET_BAD:Offset into .debug_info in .debug_aranges bad
+DW_DLE_SEGMENT_SIZE_BAD:Segment size will be 0 for MIPS processors and should always be < 8.
+DW_DLE_ARANGE_LENGTH_BAD:Length of arange section in .debug_arange bad
+DW_DLE_ARANGE_DECODE_ERROR:Aranges do not end at end of .debug_aranges
+DW_DLE_ARANGES_NULL:NULL pointer to Dwarf_Arange specified
+DW_DLE_ARANGE_NULL:NULL Dwarf_Arange specified
+DW_DLE_NO_FILE_NAME:No file name for Dwarf_Line struct
+DW_DLE_NO_COMP_DIR:No Compilation directory for compilation-unit
+DW_DLE_CU_ADDRESS_SIZE_BAD:CU header address size not match Elf class
+DW_DLE_ELF_GETIDENT_ERROR:Error in elf_getident() on object
+DW_DLE_NO_AT_MIPS_FDE:DIE does not have DW_AT_MIPS_fde attribute
+DW_DLE_NO_CIE_FOR_FDE:No CIE specified for FDE
+DW_DLE_DIE_ABBREV_LIST_NULL:No abbreviation for the code in DIE found
+DW_DLE_DEBUG_FUNCNAMES_DUPLICATE:Multiple .debug_funcnames sections
+DW_DLE_DEBUG_FUNCNAMES_NULL:No data in .debug_funcnames section
+.TE
+.FG "List of Dwarf 2 Error Codes (continued)"
+.DE
+
+.DS
+.TS
+center box, tab(:);
+lfB lfB
+l l.
+SYMBOLIC NAME:DESCRIPTION
+_
+DW_DLE_DEBUG_FUNCNAMES_VERSION_ERROR:Version stamp in .debug_funcnames bad
+DW_DLE_DEBUG_FUNCNAMES_LENGTH_BAD:Length error in reading .debug_funcnames
+DW_DLE_FUNC_NULL:NULL Dwarf_Func specified
+DW_DLE_FUNC_CONTEXT_NULL:No context for Dwarf_Func struct
+DW_DLE_DEBUG_TYPENAMES_DUPLICATE:Multiple .debug_typenames sections
+DW_DLE_DEBUG_TYPENAMES_NULL:No data in .debug_typenames section
+DW_DLE_DEBUG_TYPENAMES_VERSION_ERROR:Version stamp in .debug_typenames bad
+DW_DLE_DEBUG_TYPENAMES_LENGTH_BAD:Length error in reading .debug_typenames
+DW_DLE_TYPE_NULL:NULL Dwarf_Type specified
+DW_DLE_TYPE_CONTEXT_NULL:No context for Dwarf_Type given
+DW_DLE_DEBUG_VARNAMES_DUPLICATE:Multiple .debug_varnames sections
+DW_DLE_DEBUG_VARNAMES_NULL:No data in .debug_varnames section
+DW_DLE_DEBUG_VARNAMES_VERSION_ERROR:Version stamp in .debug_varnames bad
+DW_DLE_DEBUG_VARNAMES_LENGTH_BAD:Length error in reading .debug_varnames
+DW_DLE_VAR_NULL:NULL Dwarf_Var specified
+DW_DLE_VAR_CONTEXT_NULL:No context for Dwarf_Var given
+DW_DLE_DEBUG_WEAKNAMES_DUPLICATE:Multiple .debug_weaknames section
+DW_DLE_DEBUG_WEAKNAMES_NULL:No data in .debug_varnames section
+DW_DLE_DEBUG_WEAKNAMES_VERSION_ERROR:Version stamp in .debug_varnames bad
+DW_DLE_DEBUG_WEAKNAMES_LENGTH_BAD:Length error in reading .debug_weaknames
+DW_DLE_WEAK_NULL:NULL Dwarf_Weak specified
+DW_DLE_WEAK_CONTEXT_NULL:No context for Dwarf_Weak given
+.TE
+.FG "List of Dwarf 2 Error Codes"
+.DE
+
+This list of errors is not complete;
+additional errors have been added.
+Some of the above errors may be unused.
+Errors may not have the same meaning in different releases.
+Since most error codes are returned from only one place
+(or a very small number of places) in the source
+it is normally very useful to simply search the
+\f(CWlibdwarf\fP source to find
+out where a particular error code is generated.
+
+.H 3 "dwarf_seterrhand()"
+.DS
+\f(CWDwarf_Handler dwarf_seterrhand(
+ Dwarf_Debug dbg,
+ Dwarf_Handler errhand)\fP
+.DE
+The function \f(CWdwarf_seterrhand()\fP replaces the error handler
+(see \f(CWdwarf_init()\fP) with \f(CWerrhand\fP. The old error handler
+is returned. This function is currently unimplemented.
+
+.H 3 "dwarf_seterrarg()"
+.DS
+\f(CWDwarf_Ptr dwarf_seterrarg(
+ Dwarf_Debug dbg,
+ Dwarf_Ptr errarg)\fP
+.DE
+The function \f(CWdwarf_seterrarg()\fP replaces the pointer to the
+error handler communication area (see \f(CWdwarf_init()\fP) with
+\f(CWerrarg\fP. A pointer to the old area is returned. This
+function is currently unimplemented.
+
+.H 3 "dwarf_dealloc()"
+.DS
+\f(CWvoid dwarf_dealloc(
+ Dwarf_Debug dbg,
+ void* space,
+ Dwarf_Unsigned type)\fP
+.DE
+The function \f(CWdwarf_dealloc\fP frees the dynamic storage pointed
+to by \f(CWspace\fP, and allocated to the given \f(CWDwarf_Debug\fP.
+The argument \f(CWtype\fP is an integer code that specifies the allocation
+type of the region pointed to by the \f(CWspace\fP. Refer to section
+4 for details on \fIlibdwarf\fP memory management.
+
+.SK
+.S
+.TC 1 1 4
+.CS
diff --git a/libdwarf/libdwarf2.1.pdf b/libdwarf/libdwarf2.1.pdf
new file mode 100644
index 0000000..a88752b
--- /dev/null
+++ b/libdwarf/libdwarf2.1.pdf
Binary files differ
diff --git a/libdwarf/libdwarf2p.1.mm b/libdwarf/libdwarf2p.1.mm
new file mode 100644
index 0000000..037b813
--- /dev/null
+++ b/libdwarf/libdwarf2p.1.mm
@@ -0,0 +1,2748 @@
+\." $Revision: 1.12 $
+\." $Date: 2002/01/14 23:40:11 $
+\."
+\."
+\." the following line may be removed if the ff ligature works on your machine
+.lg 0
+\." set up heading formats
+.ds HF 3 3 3 3 3 2 2
+.ds HP +2 +2 +1 +0 +0
+.nr Hs 5
+.nr Hb 5
+\." ==============================================
+\." Put current date in the following at each rev
+.ds vE rev 1.32, 13 December 2011
+\." ==============================================
+\." ==============================================
+.ds | |
+.ds ~ ~
+.ds ' '
+.if t .ds Cw \&\f(CW
+.if n .ds Cw \fB
+.de Cf \" Place every other arg in Cw font, beginning with first
+.if \\n(.$=1 \&\*(Cw\\$1\fP
+.if \\n(.$=2 \&\*(Cw\\$1\fP\\$2
+.if \\n(.$=3 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP
+.if \\n(.$=4 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP\\$4
+.if \\n(.$=5 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP\\$4\*(Cw\\$5\fP
+.if \\n(.$=6 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP\\$4\*(Cw\\$5\fP\\$6
+.if \\n(.$=7 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP\\$4\*(Cw\\$5\fP\\$6\*(Cw\\$7\fP
+.if \\n(.$=8 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP\\$4\*(Cw\\$5\fP\\$6\*(Cw\\$7\fP\\$8
+.if \\n(.$=9 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP\\$4\*(Cw\\$5\fP\\$6\*(Cw\\$7\fP\\$8\
+*(Cw
+..
+.nr Cl 3
+.SA 1
+.TL
+A Producer Library Interface to DWARF
+.AF ""
+.AU "David Anderson"
+.PF "'\*(vE '- \\\\nP -''"
+.AS 1
+This document describes an interface to a library of functions
+to create DWARF debugging information entries and DWARF line number
+information. It does not make recommendations as to how the functions
+described in this document should be implemented nor does it
+suggest possible optimizations.
+.P
+The document is oriented to creating DWARF version 2.
+Support for creating DWARF3 is intended but such support
+is not yet fully present.
+DWARF4 support is also intended.
+.P
+\*(vE
+.AE
+.MT 4
+.H 1 "INTRODUCTION"
+This document describes an interface to \f(CWlibdwarf\fP, a
+library of functions to provide creation of DWARF debugging information
+records, DWARF line number information, DWARF address range and
+pubnames information, weak names information, and DWARF frame description
+information.
+
+
+.H 2 "Copyright"
+Copyright 1993-2006 Silicon Graphics, Inc.
+
+Copyright 2007-2010 David Anderson.
+
+Permission is hereby granted to
+copy or republish or use any or all of this document without
+restriction except that when publishing more than a small amount
+of the document
+please acknowledge Silicon Graphics, Inc and David Anderson.
+
+This document is distributed in the hope that it would be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+.H 2 "Purpose and Scope"
+The purpose of this document is to propose a library of functions to
+create DWARF debugging information. Reading (consuming) of such records
+is discussed in a separate document.
+
+The functions in this document have mostly been implemented at
+Silicon Graphics
+and are being used by the code generator to provide debugging information.
+Some functions (and support for some extensions) were provided
+by Sun Microsystems.
+
+Example code showing one use of the functionality
+may be found in the dwarfgen \f(CWdwarfgen\fP application
+(provided in the source distribution along with libdwarf).
+
+.P
+The focus of this document is the functional interface,
+and as such, implementation and optimization issues are
+intentionally ignored.
+
+.P
+Error handling, error codes, and certain \f(CWLibdwarf\fP codes are discussed
+in the "\fIA Consumer Library Interface to DWARF\fP", which should
+be read (or at least skimmed) before reading this document.
+.P
+However the general style of functions here
+in the producer library is rather C-traditional
+with various types as return values (quite different
+from the consumer library interfaces). The style
+generally follows the style of the original DWARF1 reader
+proposed as an interface to DWARF.
+When the style of the reader interfaces was changed (1994) in the
+dwarf reader ( See the "Document History"
+section of "A Consumer Library Interface to DWARF")
+the interfaces here were not changed as it seemed like
+too much of a change for the two applications then using
+the interface! So this interface remains in the traditional C style
+of returning various data types with various (somewhat inconsistent)
+means of indicating failure.
+.P
+The error handling code in the library may either
+return a value or abort.
+The library user can provide a function that the producer code
+will call on errors (which would allow callers avoid testing
+for error returns if the user function exits or aborts).
+See the \f(CWdwarf_producer_init_c()\fP
+description below for more details
+(possibly the older forms \f(CWdwarf_producer_init_b()\fP
+and \f(CWdwarf_producer_init()\fP may be of interest).
+
+
+.H 2 "Document History"
+This document originally prominently referenced
+"UNIX International Programming Languages Special Interest Group "
+(PLSIG).
+Both UNIX International and the
+affiliated Programming Languages Special Interest Group
+are defunct
+(UNIX is a registered trademark of UNIX System Laboratories, Inc.
+in the United States and other countries).
+Nothing except the general interface style is actually
+related to anything shown to the PLSIG
+(this document was open sourced with libdwarf in the mid 1990's).
+.P
+See "http://www.dwarfstd.org" for information on current
+DWARF standards and committee activities.
+
+.H 2 "Definitions"
+DWARF debugging information entries (DIEs) are the segments of information
+placed in the \f(CW.debug_info\fP and related
+sections by compilers, assemblers, and linkage
+editors that, in conjunction with line number entries, are necessary for
+symbolic source-level debugging.
+Refer to the document
+"\fIDWARF Debugging Information Format\fP" from UI PLSIG for a more complete
+description of these entries.
+
+.P
+This document adopts all the terms and definitions in
+"\fIDWARF Debugging Information Format\fP" version 2.
+and the "\fIA Consumer Library Interface to DWARF\fP".
+
+.P
+In addition, this document refers to Elf, the ATT/USL System V
+Release 4 object format.
+This is because the library was first developed for that object
+format.
+Hopefully the functions defined here can easily be
+applied to other object formats.
+
+.H 2 "Overview"
+The remaining sections of this document describe a proposed producer
+(compiler or assembler) interface to \fILibdwarf\fP, first by describing
+the purpose of additional types defined by the interface, followed by
+descriptions of the available operations.
+This document assumes you
+are thoroughly familiar with the information contained in the
+\fIDWARF
+Debugging Information Format\fP document, and
+"\fIA Consumer Library Interface to DWARF\fP".
+
+.P
+The interface necessarily knows a little bit about the object format
+(which is assumed to be Elf). We make an attempt to make this knowledge
+as limited as possible. For example, \fILibdwarf\fP does not do the
+writing of object data to the disk. The producer program does that.
+
+.H 2 "Revision History"
+.VL 15
+.LI "March 1993"
+Work on dwarf2 sgi producer draft begins
+.LI "March 1999"
+Adding a function to allow any number of trips
+through the dwarf_get_section_bytes() call.
+.LI "April 10 1999"
+Added support for assembler text output of dwarf
+(as when the output must pass through an assembler).
+Revamped internals for better performance and
+simpler provision for differences in ABI.
+.LI "Sep 1, 1999"
+Added support for little- and cross- endian
+debug info creation.
+.LI "May 7 2007"
+This library interface now cleans up, deallocating
+all memory it uses (the application simply calls
+dwarf_producer_finish(dbg)).
+.LI "September 20 2010"
+Now documents the marker feature of DIE creation.
+.LE
+
+.H 1 "Type Definitions"
+
+.H 2 "General Description"
+The \fIlibdwarf.h\fP
+header file contains typedefs and preprocessor
+definitions of types and symbolic names
+used to reference objects of \fI Libdwarf \fP .
+The types defined by typedefs contained in \fI libdwarf.h\fP
+all use the convention of adding \fI Dwarf_ \fP
+as a prefix to
+indicate that they refer to objects used by Libdwarf.
+The prefix \fI Dwarf_P_\fP is used for objects
+referenced by the \fI Libdwarf\fP
+Producer when there are similar but distinct
+objects used by the Consumer.
+
+.H 2 "Namespace issues"
+Application programs should avoid creating names
+beginning with
+\f(CWDwarf_\fP
+\f(CWdwarf_\fP
+or
+\f(CWDW_\fP
+as these are reserved to dwarf and libdwarf.
+
+.H 1 "libdwarf and Elf and relocations"
+Much of the description below presumes that Elf is the object
+format in use.
+The library is probably usable with other object formats
+that allow arbitrary sections to be created.
+
+.H 2 "binary or assembler output"
+With
+\f(CWDW_DLC_STREAM_RELOCATIONS\fP
+(see below)
+it is assumed that the calling app will simply
+write the streams and relocations directly into
+an Elf file, without going through an assembler.
+
+With
+\f(CWDW_DLC_SYMBOLIC_RELOCATIONS\fP
+the calling app must either
+A) generate binary relocation streams and write
+the generated debug information streams and
+the relocation streams direct to an elf file
+or
+B) generate assembler output text for an assembler
+to read and produce an object file.
+
+With case B) the libdwarf-calling application must
+use the relocation information to change
+points of each binary stream into references to
+symbolic names.
+It is necessary for the assembler to be
+willing to accept and generate relocations
+for references from arbitrary byte boundaries.
+For example:
+.sp
+.nf
+.in +4
+ .data 0a0bcc #producing 3 bytes of data.
+ .word mylabel #producing a reference
+ .word endlabel - startlable #producing absolute length
+.in -4
+.fi
+.sp
+
+
+
+
+.H 2 "libdwarf relationship to Elf"
+When the documentation below refers to 'an elf section number'
+it is really only dependent on getting (via the callback
+function passed by the caller of
+\f(CWdwarf_producer_init_c()\fP and
+the older forms, \f(CWdwarf_producer_init_b()\fP or
+\f(CWdwarf_producer_init()\fP)
+a sequence of integers back (with 1 as the lowest).
+
+When the documentation below refers to 'an Elf symbol index'
+it is really dependent on
+Elf symbol numbers
+only if
+\f(CWDW_DLC_STREAM_RELOCATIONS\fP
+are being generated (see below).
+With
+\f(CWDW_DLC_STREAM_RELOCATIONS\fP
+the library is generating Elf relocations
+and the section numbers in binary form so
+the section numbers and symbol indices must really
+be Elf (or elf-like) numbers.
+
+
+With
+\f(CWDW_DLC_SYMBOLIC_RELOCATIONS\fP
+the values passed as symbol indexes can be any
+integer set or even pointer set.
+All that libdwarf assumes is that where values
+are unique they get unique values.
+Libdwarf does not generate any kind of symbol table
+from the numbers and does not check their
+uniqueness or lack thereof.
+
+.H 2 "libdwarf and relocations"
+With
+\f(CWDW_DLC_SYMBOLIC_RELOCATIONS\fP
+libdwarf creates binary streams of debug information
+and arrays of relocation information describing
+the necessary relocation.
+The Elf section numbers and symbol numbers appear
+nowhere in the binary streams. Such appear
+only in the relocation information and the passed-back
+information from calls requesting the relocation information.
+As a consequence, the 'symbol indices' can be
+any pointer or integer value as the caller must
+arrange that the output deal with relocations.
+
+With
+\f(CWDW_DLC_STREAM_RELOCATIONS\fP
+all the relocations are directly created by libdwarf
+as binary streams (libdwarf only creates the streams
+in memory,
+it does not write them to disk).
+
+.H 2 "symbols, addresses, and offsets"
+The following applies to calls that
+pass in symbol indices, addresses, and offsets, such
+as
+\f(CWdwarf_add_AT_targ_address() \fP
+\f(CWdwarf_add_arange_b()\fP
+and
+\f(CWdwarf_add_frame_fde_b()\fP.
+
+With
+\f(CWDW_DLC_STREAM_RELOCATIONS\fP
+a passed in address is one of:
+a) a section offset and the (non-global) symbol index of
+a section symbol.
+b) A symbol index (global symbol) and a zero offset.
+
+With \f(CWDW_DLC_SYMBOLIC_RELOCATIONS\fP
+the same approach can be used, or, instead,
+a passed in address may be
+c) a symbol handle and an offset.
+In this case, since it is up to the calling app to
+generate binary relocations (if appropriate)
+or to turn the binary stream into
+a text stream (for input to an assembler, if appropriate)
+the application has complete control of the interpretation
+of the symbol handles.
+
+
+
+.H 1 "Memory Management"
+
+Several of the functions that comprise the \fILibdwarf\fP
+producer interface dynamically allocate values and some
+return pointers to those spaces.
+The dynamically allocated spaces
+can not be reclaimed (and must
+not be freed) except by \f(CWdwarf_producer_finish(dbg)\fP.
+
+All data for a particular \f(CWDwarf_P_Debug\fP descriptor
+is separate from the data for any other
+\f(CWDwarf_P_Debug\fP descriptor in use in the library-calling
+application.
+
+.H 2 "Read-only Properties"
+All pointers returned by or as a result of a \fILibdwarf\fP call should
+be assumed to point to read-only memory.
+Except as defined by this document, the results are undefined for
+\fILibdwarf\fP clients that attempt to write to a region pointed to by a
+return value from a \fILibdwarf\fP call.
+
+.H 2 "Storage Deallocation"
+Calling \f(CWdwarf_producer_finish(dbg)\fP frees all the space, and
+invalidates all pointers returned from \f(CWLibdwarf\fP functions on
+or descended from \f(CWdbg\fP).
+
+.H 1 "Functional Interface"
+This section describes the functions available in the \fILibdwarf\fP
+library. Each function description includes its definition, followed
+by a paragraph describing the function's operation.
+
+.P
+The functions may be categorized into groups:
+\fIinitialization and termination operations\fP,
+\fIdebugging information entry creation\fP,
+\fIElf section callback function\fP,
+\fIattribute creation\fP,
+\fIexpression creation\fP,
+\fIline number creation\fP,
+\fIfast-access (aranges) creation\fP,
+\fIfast-access (pubnames) creation\fP,
+\fIfast-access (weak names) creation\fP,
+\fImacro information creation\fP,
+\fIlow level (.debug_frame) creation\fP,
+and
+\fIlocation list (.debug_loc) creation\fP.
+
+.P
+The following sections describe these functions.
+
+.H 2 "Initialization and Termination Operations"
+These functions setup \f(CWLibdwarf\fP to accumulate debugging information
+for an object, usually a compilation-unit, provided by the producer.
+The actual addition of information is done by functions in the other
+sections of this document. Once all the information has been added,
+functions from this section are used to transform the information to
+appropriate byte streams, and help to write out the byte streams to
+disk.
+
+Typically then, a producer application
+would create a \f(CWDwarf_P_Debug\fP
+descriptor to gather debugging information for a particular
+compilation-unit using \f(CWdwarf_producer_init_c()\fP.
+(Older code may use \f(CWdwarf_producer_init_b()\fP or
+\f(CWdwarf_producer_init()\fP).
+The producer application would
+use this \f(CWDwarf_P_Debug\fP descriptor to accumulate debugging
+information for this object using functions from other sections of
+this document.
+Once all the information had been added, it would
+call \f(CWdwarf_transform_to_disk_form()\fP to convert the accumulated
+information into byte streams in accordance with the \f(CWDWARF\fP
+standard.
+The application would then repeatedly call
+\f(CWdwarf_get_section_bytes()\fP
+for each of the \f(CW.debug_*\fP created.
+This gives the producer
+information about the data bytes to be written to disk.
+At this point,
+the producer would release all resource used by \f(CWLibdwarf\fP for
+this object by calling \f(CWdwarf_producer_finish()\fP.
+
+It is also possible to create assembler-input character streams
+from the byte streams created by this library.
+This feature requires slightly different interfaces than
+direct binary output.
+The details are mentioned in the text.
+
+.H 3 "dwarf_producer_init()"
+
+.DS
+\f(CWDwarf_P_Debug dwarf_producer_init(
+ Dwarf_Unsigned flags,
+ Dwarf_Callback_Func func,
+ Dwarf_Handler errhand,
+ Dwarf_Ptr errarg,
+ Dwarf_Error *error) \fP
+.DE
+This is the oldest form and code should migrate to the newest form,
+\f(CWdwarf_producer_init_c()\fP.
+.P
+The function \f(CWdwarf_producer_init() \fP returns a new
+\f(CWDwarf_P_Debug\fP descriptor that can be used to add \f(CWDwarf\fP
+information to the object.
+On error it returns \f(CWDW_DLV_BADADDR\fP.
+\f(CWflags\fP determine whether the target object is 64-bit or 32-bit.
+\f(CWfunc\fP is a pointer to a function called-back from \f(CWLibdwarf\fP
+whenever \f(CWLibdwarf\fP needs to create a new object section (as it will
+for each .debug_* section and related relocation section).
+.P
+\f(CWerrhand\fP
+is a pointer to a function that will be used as
+a default fall-back function for handling errors detected
+by \f(CWLibdwarf\fP.
+.P
+\f(CWerrarg\fP is the default error argument used
+by the function pointed to by \f(CWerrhand\fP.
+.P
+For historical reasons the error handling is complicated
+and the following three paragraphs describe the three
+possible scenarios when a producer function detects an error.
+In all cases a short error message is printed on
+stdout if the error number
+is negative (as all such should be, see libdwarf.h).
+Then further action is taken as follows.
+.P
+First,
+if the Dwarf_Error argument to any specific producer function
+(see the functions documented below) is non-null
+the \f(CWerrhand\fP argument here is ignored in that call and
+the specific producer function sets the Dwarf_Error and returns
+some specific value (for dwarf_producer_init it is DW_DLV_BADADDR
+as mentioned just above) indicating there is an error.
+.P
+Second,
+if the Dwarf_Error argument to any specific producer function
+(see the functions documented below) is NULL and the
+\f(CWerrarg\fP to \f(CWdwarf_producer_init() \fP is non-NULL
+then on an error in the producer code the Dwarf_Handler function is called
+and if that called function returns the producer code returns
+a specific value (for dwarf_producer_init it is DW_DLV_BADADDR
+as mentioned just above) indicating there is an error.
+.P
+Third,
+if the Dwarf_Error argument to any specific producer function
+(see the functions documented below) is NULL and the
+\f(CWerrarg\fP to \f(CWdwarf_producer_init() \fP is NULL
+then on an error \f(CWabort()\fP is called.
+.P
+The \f(CWflags\fP
+values are as follows:
+.in +4
+\f(CWDW_DLC_WRITE\fP
+is required.
+The values
+\f(CWDW_DLC_READ\fP
+\f(CWDW_DLC_RDWR\fP
+are not supported by the producer and must not be passed.
+
+If
+\f(CWDW_DLC_SIZE_64\fP
+is not ORed into \f(CWflags\fP
+then
+\f(CWDW_DLC_SIZE_32\fP
+is assumed.
+Oring in both is an error.
+
+If
+\f(CWDW_DLC_OFFSET_SIZE_64\fP
+is not ORed into \f(CWflags\fP
+then 64 bit offsets (as defined in the 1999 DWARF3)
+may be used (see next paragraph) to generate DWARF (if and only if
+DW_DLC_SIZE_64 is also ORed into \f(CWflags\fP).
+
+If \f(CWHAVE_STRICT_32BIT_OFFSET\fP is set at configure time
+only 32bit DWARF offsets are generated
+(use configure option --enable-dwarf-format-strict-32bit)
+and \f(CWDW_DLC_OFFSET_SIZE_64\fP is ignored.
+If \f(CWHAVE_SGI_IRIX_OFFSETS\fP is set at configure time
+SGI IRIX offsets (standard 32bit, a special 64bit offset
+for 64bit address objects) are generated
+(use configure option --enable-dwarf-format-sgi-irix)
+and \f(CWDW_DLC_OFFSET_SIZE_64\fP is ignored.
+If neither \f(CWHAVE_STRICT_32BIT_OFFSET\fP nor \f(CWHAVE_SGI_IRIX_OFFSETS\fP
+is set at configure time then standard
+offset sizes are used ( and \f(CWHAVE_DWARF2_99_EXTENSION\fP is
+set) and \f(CWDW_DLC_OFFSET_SIZE_64\fP is honored.
+
+If
+\f(CWDW_DLC_ISA_IA64\fP
+is not ORed into \f(CWflags\fP
+then
+\f(CWDW_DLC_ISA_MIPS\fP
+is assumed.
+Oring in both is an error.
+
+If
+\f(CWDW_DLC_TARGET_BIGENDIAN\fP
+is not ORed into \f(CWflags\fP
+then
+endianness the same as the host is assumed.
+
+If
+\f(CWDW_DLC_TARGET_LITTLEENDIAN\fP
+is not ORed into \f(CWflags\fP
+then
+endianness the same as the host is assumed.
+
+If both
+\f(CWDW_DLC_TARGET_LITTLEENDIAN\fP
+and
+\f(CWDW_DLC_TARGET_BIGENDIAN\fP
+are or-d in it is an error.
+
+
+
+Either one of two output forms is specifiable:
+\f(CWDW_DLC_STREAM_RELOCATIONS\fP
+or
+\f(CWDW_DLC_SYMBOLIC_RELOCATIONS\fP .
+
+The default is
+\f(CWDW_DLC_STREAM_RELOCATIONS\fP .
+The
+\f(CWDW_DLC_STREAM_RELOCATIONS\fP
+are relocations in a binary stream (as used
+in a MIPS Elf object).
+
+The
+\f(CWDW_DLC_SYMBOLIC_RELOCATIONS\fP
+are the same relocations but expressed in an
+array of structures defined by libdwarf,
+which the caller of the relevant function
+(see below) must deal with appropriately.
+This method of expressing relocations allows
+the producer-application to easily produce
+assembler text output of debugging information.
+
+
+If
+\f(CWDW_DLC_SYMBOLIC_RELOCATIONS\fP
+is ORed into \f(CWflags\fP
+then relocations are returned not as streams
+but through an array of structures.
+
+.in -4
+.P
+The function \f(CWfunc\fP
+must be provided by the user of this library.
+Its prototype is:
+.DS
+\f(CWtypedef int (*Dwarf_Callback_Func)(
+ char* name,
+ int size,
+ Dwarf_Unsigned type,
+ Dwarf_Unsigned flags,
+ Dwarf_Unsigned link,
+ Dwarf_Unsigned info,
+ int* sect_name_index,
+ int* error) \fP
+.DE
+For each section in the object file that \f(CWlibdwarf\fP
+needs to create, it calls this function once (calling it
+from \f(CWdwarf_transform_to_disk_form()\fP), passing in
+the section \f(CWname\fP, the section \f(CWtype\fP,
+the section \f(CWflags\fP, the \f(CWlink\fP field, and
+the \f(CWinfo\fP field.
+For an Elf object file these values
+should be appropriate Elf section header values.
+For example, for relocation callbacks, the \f(CWlink\fP
+field is supposed to be set (by the app) to the index
+of the symtab section (the link field passed through the
+callback must be ignored by the app).
+And, for relocation callbacks, the \f(CWinfo\fP field
+is passed as the elf section number of the section
+the relocations apply to.
+.P
+On success
+the user function should return the Elf section number of the
+newly created Elf section.
+.P
+On success, the function should also set the integer
+pointed to by \f(CWsect_name_index\fP to the
+Elf symbol number assigned in the Elf symbol table of the
+new Elf section.
+This symbol number is needed with relocations
+dependent on the relocation of this new section.
+Because "int *" is not guaranteed to work with elf 'symbols'
+that are really pointers,
+It is better to use the
+\f(CWdwarf_producer_init_c()\fP
+interface.
+.P
+For example, the \f(CW.debug_line\fP section's third
+data element (in a compilation unit) is the offset from the
+beginning of the \f(CW.debug_info\fP section of the compilation
+unit entry for this \f(CW.debug_line\fP set.
+The relocation entry in \f(CW.rel.debug_line\fP
+for this offset
+must have the relocation symbol index of the
+symbol \f(CW.debug_info\fP returned
+by the callback of that section-creation through
+the pointer \f(CWsect_name_index\fP.
+.P
+On failure, the function should return -1 and set the \f(CWerror\fP
+integer to an error code.
+.P
+Nothing in libdwarf actually depends on the section index
+returned being a real Elf section.
+The Elf section is simply useful for generating relocation
+records.
+Similarly, the Elf symbol table index returned through
+the \f(CWsect_name_index\fP must simply be an index
+that can be used in relocations against this section.
+The application will probably want to note the
+values passed to this function in some form, even if
+no Elf file is being produced.
+
+.H 3 "dwarf_producer_init_c()"
+.DS
+ \f(CWDwarf_P_Debug dwarf_producer_init_c(
+ Dwarf_Unsigned flags,
+ Dwarf_Callback_Func_c func,
+ Dwarf_Handler errhand,
+ Dwarf_Ptr errarg,
+ void * user_data,
+ Dwarf_Error *error) \fP
+ .DE
+
+The function \f(CWdwarf_producer_init_c() \fP
+is the same as \f(CWdwarf_producer_init() \fP
+except that a) the callback function uses
+Dwarf_Unsigned rather than int as the
+type of the symbol-index returned to libdwarf
+through the pointer argument (see below), and
+b) the \f(CWuser_data\fP argument passed in
+is passed through (unchanged) to the callback functions.
+.P
+The \f(CWuser_data\fP argument is not examined by libdwarf and
+may be used by consumer code for the consumer's own purposes.
+.P
+The \f(CWflags\fP
+values are as follows:
+.in +4
+\f(CWDW_DLC_WRITE\fP
+is required.
+The values
+\f(CWDW_DLC_READ\fP
+\f(CWDW_DLC_RDWR\fP
+are not supported by the producer and must not be passed.
+
+If
+\f(CWDW_DLC_SIZE_64\fP
+is not ORed into \f(CWflags\fP
+then
+\f(CWDW_DLC_SIZE_32\fP
+is assumed.
+Oring in both is an error.
+
+If
+\f(CWDW_DLC_ISA_IA64\fP
+is not ORed into \f(CWflags\fP
+then
+\f(CWDW_DLC_ISA_MIPS\fP
+is assumed.
+Oring in both is an error.
+
+Either one of two output forms are specifiable:
+\f(CWDW_DLC_STREAM_RELOCATIONS\fP
+or
+\f(CWDW_DLC_SYMBOLIC_RELOCATIONS\fP .
+\f(CWdwarf_producer_init_c() \fP
+is usable with
+either output form.
+
+Either one of two output forms is specifiable:
+\f(CWDW_DLC_STREAM_RELOCATIONS\fP
+or
+\f(CWDW_DLC_SYMBOLIC_RELOCATIONS\fP .
+
+The default is
+\f(CWDW_DLC_STREAM_RELOCATIONS\fP .
+The
+\f(CWDW_DLC_STREAM_RELOCATIONS\fP
+are relocations in a binary stream (as used
+in a MIPS Elf object).
+
+\f(CWDW_DLC_SYMBOLIC_RELOCATIONS\fP
+are ORed into flags
+to cause
+the same relocations to be expressed in an
+array of structures defined by libdwarf,
+which the caller of the relevant function
+(see below) must deal with appropriately.
+This method of expressing relocations allows
+the producer-application to easily produce
+assembler text output of debugging information.
+
+.in -4
+.P
+The function \f(CWfunc\fP
+must be provided by the user of this library.
+Its prototype is:
+.DS
+\f(CWtypedef int (*Dwarf_Callback_Func_c)(
+ char* name,
+ int size,
+ Dwarf_Unsigned type,
+ Dwarf_Unsigned flags,
+ Dwarf_Unsigned link,
+ Dwarf_Unsigned info,
+ Dwarf_Unsigned* sect_name_index,
+ void * user_data,
+ int* error) \fP
+.DE
+For each section in the object file that \f(CWlibdwarf\fP
+needs to create, it calls this function once, passing in
+the section \f(CWname\fP, the section \f(CWtype\fP,
+the section \f(CWflags\fP, the \f(CWlink\fP field, and
+the \f(CWinfo\fP field. For an Elf object file these values
+should be appropriate Elf section header values.
+For example, for relocation callbacks, the \f(CWlink\fP
+field is supposed to be set (by the app) to the index
+of the symtab section (the link field passed through the
+callback must be ignored by the app).
+And, for relocation callbacks, the \f(CWinfo\fP field
+is passed as the elf section number of the section
+the relocations apply to.
+
+On success
+the user function should return the Elf section number of the
+newly created Elf section.
+.P
+On success, the function should also set the integer
+pointed to by \f(CWsect_name_index\fP to the
+Elf symbol number assigned in the Elf symbol table of the
+new Elf section.
+This symbol number is needed with relocations
+dependent on the relocation of this new section.
+.P
+For example, the \f(CW.debug_line\fP section's third
+data element (in a compilation unit) is the offset from the
+beginning of the \f(CW.debug_info\fP section of the compilation
+unit entry for this \f(CW.debug_line\fP set.
+The relocation entry in \f(CW.rel.debug_line\fP
+for this offset
+must have the relocation symbol index of the
+symbol \f(CW.debug_info\fP returned
+by the callback of that section-creation through
+the pointer \f(CWsect_name_index\fP.
+.P
+On failure, the function should return -1 and set the \f(CWerror\fP
+integer to an error code.
+.P
+Nothing in libdwarf actually depends on the section index
+returned being a real Elf section.
+The Elf section is simply useful for generating relocation
+records.
+Similarly, the Elf symbol table index returned through
+the \f(CWsect_name_index\fP must simply be an index
+that can be used in relocations against this section.
+The application will probably want to note the
+values passed to this function in some form, even if
+no Elf file is being produced.
+
+Note that the \f(CWDwarf_Callback_Func_c() \fP form
+passes back the sect_name_index as a Dwarf_Unsigned.
+This is guaranteed large enough to hold a pointer.
+(the other functional interfaces have versions with
+the 'symbol index' as a Dwarf_Unsigned too. See below).
+
+If \f(CWDW_DLC_SYMBOLIC_RELOCATIONS\fP
+is in use, then the symbol index is simply an arbitrary
+value (from the point of view of libdwarf) so the
+caller can put anything in it:
+a normal elf symbol index,
+a pointer to a struct (with arbitrary contents)
+(the caller must cast to/from Dwarf_Unsigned
+as appropriate),
+or some other kind of pointer or value.
+The values show up in the
+output of \f(CWdwarf_get_relocation_info()\fP
+(described below) and are not emitted anywhere else.
+
+.H 3 "dwarf_producer_init_b()"
+
+.DS
+\f(CWDwarf_P_Debug dwarf_producer_init_b(
+ Dwarf_Unsigned flags,
+ Dwarf_Callback_Func_b func,
+ Dwarf_Handler errhand,
+ Dwarf_Ptr errarg,
+ Dwarf_Error *error) \fP
+.DE
+This is identical to \f(CWdwarf_producer_init_c()\fP except that
+the user_data argument in \f(CWdwarf_producer_init_c()\fP and
+in \f(CWDwarf_Callback_Func_c\fP are absent in the _b form.
+
+
+.H 3 "dwarf_transform_to_disk_form()"
+
+.DS
+\f(CWDwarf_Signed dwarf_transform_to_disk_form(
+ Dwarf_P_Debug dbg,
+ Dwarf_Error* error) \fP
+.DE
+The function \f(CWdwarf_transform_to_disk_form() \fP does the actual
+conversion of the \f(CWDwarf\fP information provided so far, to the
+form that is
+normally written out as \f(CWElf\fP sections.
+In other words,
+once all DWARF information has been passed to \f(CWLibdwarf\fP, call
+\f(CWdwarf_transform_to_disk_form() \fP to transform all the accumulated
+data into byte streams.
+This includes turning relocation information
+into byte streams (and possibly relocation arrays).
+This function does not write anything to disk. If
+successful, it returns a count of the number of \f(CWElf\fP sections
+ready to be retrieved (and, normally, written to disk).
+In case of error, it returns
+\f(CWDW_DLV_NOCOUNT\fP.
+
+
+.H 3 "dwarf_get_section_bytes()"
+
+.DS
+\f(CWDwarf_Ptr dwarf_get_section_bytes(
+ Dwarf_P_Debug dbg,
+ Dwarf_Signed dwarf_section,
+ Dwarf_Signed *elf_section_index,
+ Dwarf_Unsigned *length,
+ Dwarf_Error* error)\fP
+.DE
+The function \f(CWdwarf_get_section_bytes() \fP must be called repetitively,
+with the index \f(CWdwarf_section\fP starting at 0 and continuing for the
+number of sections
+returned by \f(CWdwarf_transform_to_disk_form() \fP.
+It returns \f(CWNULL\fP to indicate that there are no more sections of
+\f(CWDwarf\fP information.
+For each non-NULL return, the return value
+points to \f(CW*length\fP bytes of data that are normally
+added to the output
+object in \f(CWElf\fP section \f(CW*elf_section\fP by the producer application.
+It is illegal to call these in any order other than 0 through N-1 where
+N is the number of dwarf sections
+returned by \f(CWdwarf_transform_to_disk_form() \fP.
+The \f(CWdwarf_section\fP
+number is actually ignored: the data is returned as if the
+caller passed in the correct dwarf_section numbers in the
+required sequence.
+The \f(CWerror\fP argument is not used.
+.P
+There is no requirement that the section bytes actually
+be written to an elf file.
+For example, consider the .debug_info section and its
+relocation section (the call back function would resulted in
+assigning 'section' numbers and the link field to tie these
+together (.rel.debug_info would have a link to .debug_info).
+One could examine the relocations, split the .debug_info
+data at relocation boundaries, emit byte streams (in hex)
+as assembler output, and at each relocation point,
+emit an assembler directive with a symbol name for the assembler.
+Examining the relocations is awkward though.
+It is much better to use \f(CWdwarf_get_section_relocation_info() \fP
+.P
+
+The memory space of the section byte stream is freed
+by the \f(CWdwarf_producer_finish() \fP call
+(or would be if the \f(CWdwarf_producer_finish() \fP
+was actually correct), along
+with all the other space in use with that Dwarf_P_Debug.
+
+.H 3 "dwarf_get_relocation_info_count()"
+.DS
+\f(CWint dwarf_get_relocation_info_count(
+ Dwarf_P_Debug dbg,
+ Dwarf_Unsigned *count_of_relocation_sections ,
+ int *drd_buffer_version,
+ Dwarf_Error* error)\fP
+.DE
+The function \f(CWdwarf_get_relocation_info() \fP
+returns, through the pointer \f(CWcount_of_relocation_sections\fP, the
+number of times that \f(CWdwarf_get_relocation_info() \fP
+should be called.
+
+The function \f(CWdwarf_get_relocation_info() \fP
+returns DW_DLV_OK if the call was successful (the
+\f(CWcount_of_relocation_sections\fP is therefore meaningful,
+though \f(CWcount_of_relocation_sections\fP
+could be zero).
+
+\f(CW*drd_buffer_version\fP
+is the value 2.
+If the structure pointed to by
+the \f(CW*reldata_buffer\fP
+changes this number will change.
+The application should verify that the number is
+the version it understands (that it matches
+the value of DWARF_DRD_BUFFER_VERSION (from libdwarf.h)).
+The value 1 version was never used in production
+MIPS libdwarf (version 1 did exist in source).
+
+It returns DW_DLV_NO_ENTRY if
+\f(CWcount_of_relocation_sections\fP is not meaningful
+because \f(CWDW_DLC_SYMBOLIC_RELOCATIONS\fP was not
+passed to the
+\f(CWdwarf_producer_init_c()\fP
+\f(CWdwarf_producer_init_b()\fP or
+\f(CWdwarf_producer_init()\fP call
+(whichever one was used).
+
+It returns DW_DLV_ERROR if there was an error,
+in which case
+\f(CWcount_of_relocation_sections\fP is not meaningful.
+
+.H 3 "dwarf_get_relocation_info()"
+.DS
+\f(CWint dwarf_get_relocation_info(
+ Dwarf_P_Debug dbg,
+ Dwarf_Signed *elf_section_index,
+ Dwarf_Signed *elf_section_index_link,
+ Dwarf_Unsigned *relocation_buffer_count,
+ Dwarf_Relocation_Data *reldata_buffer,
+ Dwarf_Error* error)\fP
+.DE
+
+The function \f(CWdwarf_get_relocation_info() \fP
+should normally be called repetitively,
+for the number of relocation sections that
+\f(CWdwarf_get_relocation_info_count() \fP
+indicated exist.
+
+It returns \f(CWDW_DLV_OK\fP to indicate that
+valid values are returned through the pointer arguments.
+The \f(CWerror\fP argument is not set.
+
+It returns DW_DLV_NO_ENTRY if there are no entries
+(the count of relocation arrays is zero.).
+The \f(CWerror\fP argument is not set.
+
+It returns \f(CWDW_DLV_ERROR\fP if there is an error.
+Calling \f(CWdwarf_get_relocation_info() \fP
+more than the number of times indicated by
+\f(CWdwarf_get_relocation_info_count() \fP
+(without an intervening call to
+\f(CWdwarf_reset_section_bytes() \fP )
+results in a return of \f(CWDW_DLV_ERROR\fP once past
+the valid count.
+The \f(CWerror\fP argument is set to indicate the error.
+
+Now consider the returned-through-pointer values for
+\f(CWDW_DLV_OK\fP .
+
+\f(CW*elf_section_index\fP
+is the 'elf section index' of the section implied by
+this group of relocations.
+
+
+\f(CW*elf_section_index_link\fP
+is the section index of the section that these
+relocations apply to.
+
+\f(CW*relocation_buffer_count\fP
+is the number of array entries of relocation information
+in the array pointed to by
+\f(CW*reldata_buffer\fP .
+
+
+\f(CW*reldata_buffer\fP
+points to an array of 'struct Dwarf_Relocation_Data_s'
+structures.
+
+The version 2 array information is as follows:
+
+.nf
+enum Dwarf_Rel_Type {dwarf_drt_none,
+ dwarf_drt_data_reloc,
+ dwarf_drt_segment_rel,
+ dwarf_drt_first_of_length_pair,
+ dwarf_drt_second_of_length_pair
+};
+typedef struct Dwarf_Relocation_Data_s * Dwarf_Relocation_Data;
+struct Dwarf_Relocation_Data_s {
+ unsigned char drd_type; /* contains Dwarf_Rel_Type */
+ unsigned char drd_length; /* typically 4 or 8 */
+ Dwarf_Unsigned drd_offset; /* where the data to reloc is */
+ Dwarf_Unsigned drd_symbol_index;
+};
+
+.fi
+
+The \f(CWDwarf_Rel_Type\fP enum is encoded (via casts if necessary)
+into the single unsigned char \f(CWdrd_type\fP field to control
+the space used for this information (keep the space to 1 byte).
+
+The unsigned char \f(CWdrd_length\fP field
+holds the size in bytes of the field to be relocated.
+So for elf32 object formats with 32 bit apps, \f(CWdrd_length\fP
+will be 4. For objects with MIPS -64 contents,
+\f(CWdrd_length\fP will be 8.
+For some dwarf 64 bit environments, such as ia64, \f(CWdrd_length\fP
+is 4 for some relocations (file offsets, for example)
+and 8 for others (run time
+addresses, for example).
+
+If \f(CWdrd_type\fP is \f(CWdwarf_drt_none\fP, this is an unused slot
+and it should be ignored.
+
+If \f(CWdrd_type\fP is \f(CWdwarf_drt_data_reloc\fP
+this is an ordinary relocation.
+The relocation type means either
+(R_MIPS_64) or (R_MIPS_32) (or the like for
+the particular ABI.
+\f(CWdrd_length\fP gives the length of the field to be relocated.
+\f(CWdrd_offset\fP is an offset (of the
+value to be relocated) in
+the section this relocation stuff is linked to.
+\f(CWdrd_symbol_index\fP is the symbol index (if elf symbol
+indices were provided) or the handle to arbitrary
+information (if that is what the caller passed in
+to the relocation-creating dwarf calls) of the symbol
+that the relocation is relative to.
+
+
+When \f(CWdrd_type\fP is \f(CWdwarf_drt_first_of_length_pair\fP
+the next data record will be \f(CWdrt_second_of_length_pair\fP
+and the \f(CWdrd_offset\fP of the two data records will match.
+The relevant 'offset' in the section this reloc applies to
+should contain a symbolic pair like
+.nf
+.in +4
+ .word second_symbol - first_symbol
+.in -4
+.fi
+to generate a length.
+\f(CWdrd_length\fP gives the length of the field to be relocated.
+
+\f(CWdrt_segment_rel\fP means (R_MIPS_SCN_DISP)
+is the real relocation (R_MIPS_SCN_DISP applies to
+exception tables and this part may need further work).
+\f(CWdrd_length\fP gives the length of the field to be relocated.
+
+.P
+The memory space of the section byte stream is freed
+by the \f(CWdwarf_producer_finish() \fP call
+(or would be if the \f(CWdwarf_producer_finish() \fP
+was actually correct), along
+with all the other space in use with that Dwarf_P_Debug.
+
+.H 3 "dwarf_reset_section_bytes()"
+
+.DS
+\f(CWvoid dwarf_reset_section_bytes(
+ Dwarf_P_Debug dbg
+ ) \fP
+.DE
+The function \f(CWdwarf_reset_section_bytes() \fP
+is used to reset the internal information so that
+\f(CWdwarf_get_section_bytes() \fP will begin (on the next
+call) at the initial dwarf section again.
+It also resets so that calls to
+\f(CWdwarf_get_relocation_info() \fP
+will begin again at the initial array of relocation information.
+
+Some dwarf producers need to be able to run through
+the \f(CWdwarf_get_section_bytes()\fP
+and/or
+the \f(CWdwarf_get_relocation_info()\fP
+calls more than once and this call makes additional
+passes possible.
+The set of Dwarf_Ptr values returned is identical to the
+set returned by the first pass.
+It is acceptable to call this before finishing a pass
+of \f(CWdwarf_get_section_bytes()\fP
+or
+\f(CWdwarf_get_relocation_info()\fP
+calls.
+No errors are possible as this just resets some
+internal pointers.
+It is unwise to call this before
+\f(CWdwarf_transform_to_disk_form() \fP has been called.
+.P
+
+.H 3 "dwarf_producer_finish()"
+.DS
+\f(CWDwarf_Unsigned dwarf_producer_finish(
+ Dwarf_P_Debug dbg,
+ Dwarf_Error* error) \fP
+.DE
+The function \f(CWdwarf_producer_finish() \fP should be called after all
+the bytes of data have been copied somewhere
+(normally the bytes are written to disk).
+It frees all dynamic space
+allocated for \f(CWdbg\fP, include space for the structure pointed to by
+\f(CWdbg\fP.
+This should not be called till the data have been
+copied or written
+to disk or are no longer of interest.
+It returns non-zero if successful, and \f(CWDW_DLV_NOCOUNT\fP
+if there is an error.
+
+.H 2 "Debugging Information Entry Creation"
+The functions in this section add new \f(CWDIE\fPs to the object,
+and also the relationships among the \f(CWDIE\fP to be specified
+by linking them up as parents, children, left or right siblings
+of each other.
+In addition, there is a function that marks the
+root of the graph thus created.
+
+.H 3 "dwarf_add_die_to_debug()"
+.DS
+\f(CWDwarf_Unsigned dwarf_add_die_to_debug(
+ Dwarf_P_Debug dbg,
+ Dwarf_P_Die first_die,
+ Dwarf_Error *error) \fP
+.DE
+The function \f(CWdwarf_add_die_to_debug() \fP indicates to \f(CWLibdwarf\fP
+the root \f(CWDIE\fP of the \f(CWDIE\fP graph that has been built so
+far.
+It is intended to mark the compilation-unit \f(CWDIE\fP for the
+object represented by \f(CWdbg\fP.
+The root \f(CWDIE\fP is specified
+by \f(CWfirst_die\fP.
+
+It returns \f(CW0\fP on success, and \f(CWDW_DLV_NOCOUNT\fP on error.
+
+.H 3 "dwarf_new_die()"
+.DS
+\f(CWDwarf_P_Die dwarf_new_die(
+ Dwarf_P_Debug dbg,
+ Dwarf_Tag new_tag,
+ Dwarf_P_Die parent,
+ Dwarf_P_Die child,
+ Dwarf_P_Die left_sibling,
+ Dwarf_P_Die right_sibling,
+ Dwarf_Error *error) \fP
+.DE
+The function \f(CWdwarf_new_die() \fP creates a new \f(CWDIE\fP with
+its parent, child, left sibling, and right sibling \f(CWDIE\fPs
+specified by \f(CWparent\fP, \f(CWchild\fP, \f(CWleft_sibling\fP,
+and \f(CWright_sibling\fP, respectively.
+There is no requirement
+that all of these \f(CWDIE\fPs be specified, i.e. any of these
+descriptors may be \f(CWNULL\fP.
+If none is specified, this will
+be an isolated \f(CWDIE\fP.
+A \f(CWDIE\fP is
+transformed to disk form by \f(CWdwarf_transform_to_disk_form() \fP
+only if there is a path from
+the \f(CWDIE\fP specified by \f(CWdwarf_add_die_to_debug\fP to it.
+This function returns \f(CWDW_DLV_BADADDR\fP on error.
+
+\f(CWnew_tag\fP is the tag which is given to the new \f(CWDIE\fP.
+\f(CWparent\fP, \f(CWchild\fP, \f(CWleft_sibling\fP, and
+\f(CWright_sibling\fP are pointers to establish links to existing
+\f(CWDIE\fPs. Only one of \f(CWparent\fP, \f(CWchild\fP,
+\f(CWleft_sibling\fP, and \f(CWright_sibling\fP may be non-NULL.
+If \f(CWparent\fP (\f(CWchild\fP) is given, the \f(CWDIE\fP is
+linked into the list after (before) the \f(CWDIE\fP pointed to.
+If \f(CWleft_sibling\fP (\f(CWright_sibling\fP) is given, the
+\f(CWDIE\fP is linked into the list after (before) the \f(CWDIE\fP
+pointed to.
+
+To add attributes to the new \f(CWDIE\fP, use the \f(CWAttribute Creation\fP
+functions defined in the next section.
+
+.H 3 "dwarf_die_link()"
+.DS
+\f(CWDwarf_P_Die dwarf_die_link(
+ Dwarf_P_Die die,
+ Dwarf_P_Die parent,
+ Dwarf_P_Die child,
+ Dwarf_P_Die left-sibling,
+ Dwarf_P_Die right_sibling,
+ Dwarf_Error *error) \fP
+.DE
+The function \f(CWdwarf_die_link() \fP links an existing \f(CWDIE\fP
+described by the given \f(CWdie\fP to other existing \f(CWDIE\fPs.
+The given \f(CWdie\fP can be linked to a parent \f(CWDIE\fP, a child
+\f(CWDIE\fP, a left sibling \f(CWDIE\fP, or a right sibling \f(CWDIE\fP
+by specifying non-NULL \f(CWparent\fP, \f(CWchild\fP, \f(CWleft_sibling\fP,
+and \f(CWright_sibling\fP \f(CWDwarf_P_Die\fP descriptors.
+It returns
+the given \f(CWDwarf_P_Die\fP descriptor, \f(CWdie\fP, on success,
+and \f(CWDW_DLV_BADADDR\fP on error.
+
+Only one of \f(CWparent\fP, \f(CWchild\fP, \f(CWleft_sibling\fP,
+and \f(CWright_sibling\fP may be non-NULL.
+If \f(CWparent\fP
+(\f(CWchild\fP) is given, the \f(CWDIE\fP is linked into the list
+after (before) the \f(CWDIE\fP pointed to.
+If \f(CWleft_sibling\fP
+(\f(CWright_sibling\fP) is given, the \f(CWDIE\fP is linked into
+the list after (before) the \f(CWDIE\fP pointed to.
+Non-NULL links
+overwrite the corresponding links the given \f(CWdie\fP may have
+had before the call to \f(CWdwarf_die_link() \fP.
+
+.H 2 "DIE Markers"
+DIE markers provide a way for a producer to extract DIE offsets
+from DIE generation. The markers do not influence the
+generation of DWARF, they simply allow a producer to
+extract .debug_info offsets for whatever purpose the
+producer finds useful (for example, a producer might
+want some unique other section unknown
+to libdwarf to know a particular DIE offset).
+
+One marks one or more DIEs as desired any time before
+calling \f(CWdwarf_transform_to_disk_form()\fP.
+
+After calling \f(CWdwarf_transform_to_disk_form()\fP
+call
+\f(CWdwarf_get_die_markers()\fP
+which has the offsets where the marked DIEs were written
+in the generated .debug_info data.
+
+
+.H 3 "dwarf_add_die_marker()"
+.DS
+\f(CWDwarf_Unsigned dwarf_add_die_marker(
+ Dwarf_P_Debug dbg,
+ Dwarf_P_Die die,
+ Dwarf_Unsigned marker,
+ Dwarf_Error *error) \fP
+.DE
+The function \f(CWdwarf_add_die_marker() \fP writes the
+value \f(CWmarker\fP to the \f(CWDIE\fP descriptor given by
+\f(CWdie\fP.
+Passing in a marker of 0 means 'there is no marker'
+(zero is the default in DIEs).
+
+It returns \f(CW0\fP, on success.
+On error it returns \f(CWDW_DLV_NOCOUNT\fP.
+
+.H 3 "dwarf_get_die_marker()"
+.DS
+\f(CWDwarf_Unsigned dwarf_get_die_marker(
+ Dwarf_P_Debug dbg,
+ Dwarf_P_Die die,
+ Dwarf_Unsigned *marker,
+ Dwarf_Error *error) \fP
+.DE
+The function \f(CWdwarf_get_die_marker() \fP returns the
+current marker value for this DIE
+through the pointer \f(CWmarker\fP.
+A marker value of 0 means 'no marker was set'.
+
+It returns \f(CW0\fP, on success.
+On error it returns \f(CWDW_DLV_NOCOUNT\fP.
+
+.H 3 "dwarf_get_die_markers()"
+.DS
+\f(CWDwarf_Unsigned dwarf_get_die_markers(
+ Dwarf_P_Debug dbg,
+ Dwarf_P_Marker * marker_list,
+ Dwarf_Unsigned *marker_count,
+ Dwarf_Error *error) \fP
+.DE
+The function \f(CWdwarf_get_die_marker() \fP returns
+a pointer to an array of \f(CWDwarf_P_Marker\fP pointers to
+\f(CWstruct Dwarf_P_Marker_s\fP structures through
+the pointer \f(CWmarker_list\fP.
+The array length is returned through the
+pointer \f(CWmarker_count\fP.
+
+The call is only meaningful after
+a call to \f(CWdwarf_transform_to_disk_form()\fP as the
+transform call creates the \f(CWstruct Dwarf_P_Marker_s\fP
+structures, one for each DIE generated for .debug_info
+(but only for DIEs that had a non-zero marker value).
+The field \f(CWma_offset\fP in the structure is set
+during generation of the .debug_info byte stream.
+The field \f(CWma_marker\fP in the structure is a copy
+of the DIE marker of the DIE given that offset.
+
+It returns \f(CW0\fP, on success.
+On error it returns \f(CWDW_DLV_BADADDR\fP (if there are no
+markers it returns \f(CWDW_DLV_BADADDR\fP).
+
+.H 2 "Attribute Creation"
+The functions in this section add attributes to a \f(CWDIE\fP.
+These functions return a \f(CWDwarf_P_Attribute\fP descriptor
+that represents the attribute added to the given \f(CWDIE\fP.
+In most cases the return value is only useful to determine if
+an error occurred.
+
+Some of the attributes have values that are relocatable.
+They
+need a symbol with respect to which the linker will perform
+relocation.
+This symbol is specified by means of an index into
+the Elf symbol table for the object
+(of course, the symbol index can be more general than an index).
+
+.H 3 "dwarf_add_AT_location_expr()"
+.DS
+\f(CWDwarf_P_Attribute dwarf_add_AT_location_expr(
+ Dwarf_P_Debug dbg,
+ Dwarf_P_Die ownerdie,
+ Dwarf_Half attr,
+ Dwarf_P_Expr loc_expr,
+ Dwarf_Error *error) \fP
+.DE
+The function \f(CWdwarf_add_AT_location_expr() \fP adds the attribute
+specified by \f(CWattr\fP to the \f(CWDIE\fP descriptor given by
+\f(CWownerdie\fP. The attribute should be one that has a location
+expression as its value. The location expression that is the value
+is represented by the \f(CWDwarf_P_Expr\fP descriptor \f(CWloc_expr\fP.
+It returns the \f(CWDwarf_P_Attribute\fP descriptor for the attribute
+given, on success. On error it returns \f(CWDW_DLV_BADADDR\fP.
+
+.H 3 "dwarf_add_AT_name()"
+.DS
+\f(CWDwarf_P_Attribute dwarf_add_AT_name(
+ Dwarf_P_Die ownerdie,
+ char *name,
+ Dwarf_Error *error) \fP
+.DE
+The function \f(CWdwarf_add_AT_name() \fP adds the string specified
+by \f(CWname\fP as the value of the \f(CWDW_AT_name\fP attribute
+for the given \f(CWDIE\fP, \f(CWownerdie\fP. It returns the
+\f(CWDwarf_P_attribute\fP descriptor for the \f(CWDW_AT_name\fP
+attribute on success. On error, it returns \f(CWDW_DLV_BADADDR\fP.
+
+.H 3 "dwarf_add_AT_comp_dir()"
+.DS
+\f(CWDwarf_P_Attribute dwarf_add_AT_comp_dir(
+ Dwarf_P_Die ownerdie,
+ char *current_working_directory,
+ Dwarf_Error *error) \fP
+.DE
+The function \f(CWdwarf_add_AT_comp_dir() \fP adds the string given by
+\f(CWcurrent_working_directory\fP as the value of the \f(CWDW_AT_comp_dir\fP
+attribute for the \f(CWDIE\fP described by the given \f(CWownerdie\fP.
+It returns the \f(CWDwarf_P_Attribute\fP for this attribute on success.
+On error, it returns \f(CWDW_DLV_BADADDR\fP.
+
+.H 3 "dwarf_add_AT_producer()"
+.DS
+\f(CWDwarf_P_Attribute dwarf_add_AT_producer(
+ Dwarf_P_Die ownerdie,
+ char *producer_string,
+ Dwarf_Error *error) \fP
+.DE
+The function \f(CWdwarf_add_AT_producer() \fP adds the string given by
+\f(CWproducer_string\fP as the value of the \f(CWDW_AT_producer\fP
+attribute for the \f(CWDIE\fP given by \f(CWownerdie\fP. It returns
+the \f(CWDwarf_P_Attribute\fP descriptor representing this attribute
+on success. On error, it returns \f(CWDW_DLV_BADADDR\fP.
+
+.H 3 "dwarf_add_AT_const_value_signedint()"
+.DS
+\f(CWDwarf_P_Attribute dwarf_add_AT_const_value_signedint(
+ Dwarf_P_Die ownerdie,
+ Dwarf_Signed signed_value,
+ Dwarf_Error *error) \fP
+.DE
+The function \f(CWdwarf_add_AT_const_value_signedint() \fP adds the
+given \f(CWDwarf_Signed\fP value \f(CWsigned_value\fP as the value
+of the \f(CWDW_AT_const_value\fP attribute for the \f(CWDIE\fP
+described by the given \f(CWownerdie\fP. It returns the
+\f(CWDwarf_P_Attribute\fP descriptor for this attribute on success.
+On error, it returns \f(CWDW_DLV_BADADDR\fP.
+
+.H 3 "dwarf_add_AT_const_value_unsignedint()"
+.DS
+\f(CWDwarf_P_Attribute dwarf_add_AT_const_value_unsignedint(
+ Dwarf_P_Die ownerdie,
+ Dwarf_Unsigned unsigned_value,
+ Dwarf_Error *error) \fP
+.DE
+The function \f(CWdwarf_add_AT_const_value_unsignedint() \fP adds the
+given \f(CWDwarf_Unsigned\fP value \f(CWunsigned_value\fP as the value
+of the \f(CWDW_AT_const_value\fP attribute for the \f(CWDIE\fP described
+by the given \f(CWownerdie\fP. It returns the \f(CWDwarf_P_Attribute\fP
+descriptor for this attribute on success. On error, it returns
+\f(CWDW_DLV_BADADDR\fP.
+
+.H 3 "dwarf_add_AT_const_value_string()"
+.DS
+\f(CWDwarf_P_Attribute dwarf_add_AT_const_value_string(
+ Dwarf_P_Die ownerdie,
+ char *string_value,
+ Dwarf_Error *error) \fP
+.DE
+The function \f(CWdwarf_add_AT_const_value_string() \fP adds the
+string value given by \f(CWstring_value\fP as the value of the
+\f(CWDW_AT_const_value\fP attribute for the \f(CWDIE\fP described
+by the given \f(CWownerdie\fP. It returns the \f(CWDwarf_P_Attribute\fP
+descriptor for this attribute on success. On error, it returns
+\f(CWDW_DLV_BADADDR\fP.
+
+.H 3 "dwarf_add_AT_targ_address()"
+.DS
+\f(CWDwarf_P_Attribute dwarf_add_AT_targ_address(
+ Dwarf_P_Debug dbg,
+ Dwarf_P_Die ownerdie,
+ Dwarf_Half attr,
+ Dwarf_Unsigned pc_value,
+ Dwarf_Signed sym_index,
+ Dwarf_Error *error) \fP
+.DE
+The function \f(CWdwarf_add_AT_targ_address() \fP adds an attribute that
+belongs to the "address" class to the die specified by \f(CWownerdie\fP.
+The attribute is specified by \f(CWattr\fP, and the object that the
+\f(CWDIE\fP belongs to is specified by \f(CWdbg\fP. The relocatable
+address that is the value of the attribute is specified by \f(CWpc_value\fP.
+The symbol to be used for relocation is specified by the \f(CWsym_index\fP,
+which is the index of the symbol in the Elf symbol table.
+
+It returns the \f(CWDwarf_P_Attribute\fP descriptor for the attribute
+on success, and \f(CWDW_DLV_BADADDR\fP on error.
+
+
+.H 3 "dwarf_add_AT_targ_address_b()"
+.DS
+\f(CWDwarf_P_Attribute dwarf_add_AT_targ_address_b(
+ Dwarf_P_Debug dbg,
+ Dwarf_P_Die ownerdie,
+ Dwarf_Half attr,
+ Dwarf_Unsigned pc_value,
+ Dwarf_Unsigned sym_index,
+ Dwarf_Error *error) \fP
+.DE
+The function \f(CWdwarf_add_AT_targ_address_b() \fP
+is identical to \f(CWdwarf_add_AT_targ_address_b() \fP
+except that \f(CWsym_index() \fP is guaranteed to
+be large enough that it can contain a pointer to
+arbitrary data (so the caller can pass in a real elf
+symbol index, an arbitrary number, or a pointer
+to arbitrary data).
+The ability to pass in a pointer through \f(CWsym_index() \fP
+is only usable with
+\f(CWDW_DLC_SYMBOLIC_RELOCATIONS\fP.
+
+The \f(CWpc_value\fP
+is put into the section stream output and
+the \f(CWsym_index\fP is applied to the relocation
+information.
+
+Do not use this function for attr \f(CWDW_AT_high_pc\fP
+if the value to be recorded is an offset (not a pc)
+[ use \f(CWdwarf_add_AT_unsigned_const()\fP (for example)
+instead].
+
+.H 3 "dwarf_add_AT_dataref()"
+.DS
+\f(CWDwarf_P_Attribute dwarf_add_AT_dataref(
+ Dwarf_P_Debug dbg,
+ Dwarf_P_Die ownerdie,
+ Dwarf_Half attr,
+ Dwarf_Unsigned pc_value,
+ Dwarf_Unsigned sym_index,
+ Dwarf_Error *error) \fP
+.DE
+This is very similar to \f(CWdwarf_add_AT_targ_address_b() \fP
+but results in a different FORM (results in DW_FORM_data4
+or DW_FORM_data8).
+
+Useful for adding relocatable addresses in location lists.
+
+\f(CWsym_index() \fP is guaranteed to
+be large enough that it can contain a pointer to
+arbitrary data (so the caller can pass in a real elf
+symbol index, an arbitrary number, or a pointer
+to arbitrary data).
+The ability to pass in a pointer through \f(CWsym_index() \fP
+is only usable with
+\f(CWDW_DLC_SYMBOLIC_RELOCATIONS\fP.
+
+The \f(CWpc_value\fP
+is put into the section stream output and
+the \f(CWsym_index\fP is applied to the relocation
+information.
+
+Do not use this function for \f(CWDW_AT_high_pc\fP, use
+\f(CWdwarf_add_AT_unsigned_const()\fP [ (for example)
+if the value to be recorded is
+an offset of \f(CWDW_AT_low_pc\fP]
+or \f(CWdwarf_add_AT_targ_address_b()\fP [ if the value
+to be recorded is an address].
+
+.H 3 "dwarf_add_AT_ref_address()"
+.DS
+\f(CWDwarf_P_Attribute dwarf_add_AT_ref_address(
+ Dwarf_P_Debug dbg,
+ Dwarf_P_Die ownerdie,
+ Dwarf_Half attr,
+ Dwarf_Unsigned pc_value,
+ Dwarf_Unsigned sym_index,
+ Dwarf_Error *error) \fP
+.DE
+
+This is very similar to \f(CWdwarf_add_AT_targ_address_b() \fP
+but results in a different FORM (results in \f(CWDW_FORM_ref_addr\fP
+being generated).
+
+Useful for \f(CWDW_AT_type\fP and \f(CWDW_AT_import\fP attributes.
+
+\f(CWsym_index() \fP is guaranteed to
+be large enough that it can contain a pointer to
+arbitrary data (so the caller can pass in a real elf
+symbol index, an arbitrary number, or a pointer
+to arbitrary data).
+The ability to pass in a pointer through \f(CWsym_index() \fP
+is only usable with
+\f(CWDW_DLC_SYMBOLIC_RELOCATIONS\fP.
+
+The \f(CWpc_value\fP
+is put into the section stream output and
+the \f(CWsym_index\fP is applied to the relocation
+information.
+
+Do not use this function for \f(CWDW_AT_high_pc\fP.
+
+
+.H 3 "dwarf_add_AT_unsigned_const()"
+.DS
+\f(CWDwarf_P_Attribute dwarf_add_AT_unsigned_const(
+ Dwarf_P_Debug dbg,
+ Dwarf_P_Die ownerdie,
+ Dwarf_Half attr,
+ Dwarf_Unsigned value,
+ Dwarf_Error *error) \fP
+.DE
+The function \f(CWdwarf_add_AT_unsigned_const() \fP adds an attribute
+with a \f(CWDwarf_Unsigned\fP value belonging to the "constant" class,
+to the \f(CWDIE\fP specified by \f(CWownerdie\fP. The object that
+the \f(CWDIE\fP belongs to is specified by \f(CWdbg\fP. The attribute
+is specified by \f(CWattr\fP, and its value is specified by \f(CWvalue\fP.
+
+It returns the \f(CWDwarf_P_Attribute\fP descriptor for the attribute
+on success, and \f(CWDW_DLV_BADADDR\fP on error.
+
+.H 3 "dwarf_add_AT_signed_const()"
+.DS
+\f(CWDwarf_P_Attribute dwarf_add_AT_signed_const(
+ Dwarf_P_Debug dbg,
+ Dwarf_P_Die ownerdie,
+ Dwarf_Half attr,
+ Dwarf_Signed value,
+ Dwarf_Error *error) \fP
+.DE
+The function \f(CWdwarf_add_AT_signed_const() \fP adds an attribute
+with a \f(CWDwarf_Signed\fP value belonging to the "constant" class,
+to the \f(CWDIE\fP specified by \f(CWownerdie\fP. The object that
+the \f(CWDIE\fP belongs to is specified by \f(CWdbg\fP. The attribute
+is specified by \f(CWattr\fP, and its value is specified by \f(CWvalue\fP.
+
+It returns the \f(CWDwarf_P_Attribute\fP descriptor for the attribute
+on success, and \f(CWDW_DLV_BADADDR\fP on error.
+
+.H 3 "dwarf_add_AT_reference()"
+.DS
+\f(CWDwarf_P_Attribute dwarf_add_AT_reference(
+ Dwarf_P_Debug dbg,
+ Dwarf_P_Die ownerdie,
+ Dwarf_Half attr,
+ Dwarf_P_Die otherdie,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_add_AT_reference()\fP adds an attribute
+with a value that is a reference to another \f(CWDIE\fP in the
+same compilation-unit to the \f(CWDIE\fP specified by \f(CWownerdie\fP.
+The object that the \f(CWDIE\fP belongs to is specified by \f(CWdbg\fP.
+The attribute is specified by \f(CWattr\fP, and the other \f(CWDIE\fP
+being referred to is specified by \f(CWotherdie\fP.
+
+This cannot generate DW_FORM_ref_addr references to
+\f(CWDIE\fPs in other compilation units.
+
+It returns the \f(CWDwarf_P_Attribute\fP descriptor for the attribute
+on success, and \f(CWDW_DLV_BADADDR\fP on error.
+
+.H 3 "dwarf_add_AT_flag()"
+.DS
+\f(CWDwarf_P_Attribute dwarf_add_AT_flag(
+ Dwarf_P_Debug dbg,
+ Dwarf_P_Die ownerdie,
+ Dwarf_Half attr,
+ Dwarf_Small flag,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_add_AT_flag()\fP adds an attribute with
+a \f(CWDwarf_Small\fP value belonging to the "flag" class, to the
+\f(CWDIE\fP specified by \f(CWownerdie\fP. The object that the
+\f(CWDIE\fP belongs to is specified by \f(CWdbg\fP. The attribute
+is specified by \f(CWattr\fP, and its value is specified by \f(CWflag\fP.
+
+It returns the \f(CWDwarf_P_Attribute\fP descriptor for the attribute
+on success, and \f(CWDW_DLV_BADADDR\fP on error.
+
+.H 3 "dwarf_add_AT_string()"
+.DS
+\f(CWDwarf_P_Attribute dwarf_add_AT_string(
+ Dwarf_P_Debug dbg,
+ Dwarf_P_Die ownerdie,
+ Dwarf_Half attr,
+ char *string,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_add_AT_string()\fP adds an attribute with a
+value that is a character string to the \f(CWDIE\fP specified by
+\f(CWownerdie\fP. The object that the \f(CWDIE\fP belongs to is
+specified by \f(CWdbg\fP. The attribute is specified by \f(CWattr\fP,
+and its value is pointed to by \f(CWstring\fP.
+
+It returns the \f(CWDwarf_P_Attribute\fP descriptor for the attribute
+on success, and \f(CWDW_DLV_BADADDR\fP on error.
+
+.H 2 "Expression Creation"
+The following functions are used to convert location expressions into
+blocks so that attributes with values that are location expressions
+can store their values as a \f(CWDW_FORM_blockn\fP value. This is for
+both .debug_info and .debug_loc expression blocks.
+
+To create an expression, first call \f(CWdwarf_new_expr()\fP to get
+a \f(CWDwarf_P_Expr\fP descriptor that can be used to build up the
+block containing the location expression. Then insert the parts of
+the expression in prefix order (exactly the order they would be
+interpreted in in an expression interpreter). The bytes of the
+expression are then built-up as specified by the user.
+
+.H 3 "dwarf_new_expr()"
+.DS
+\f(CWDwarf_Expr dwarf_new_expr(
+ Dwarf_P_Debug dbg,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_new_expr()\fP creates a new expression area
+in which a location expression stream can be created. It returns
+a \f(CWDwarf_P_Expr\fP descriptor that can be used to add operators
+to build up a location expression. It returns \f(CWNULL\fP on error.
+
+.H 3 "dwarf_add_expr_gen()"
+.DS
+\f(CWDwarf_Unsigned dwarf_add_expr_gen(
+ Dwarf_P_Expr expr,
+ Dwarf_Small opcode,
+ Dwarf_Unsigned val1,
+ Dwarf_Unsigned val2,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_add_expr_gen()\fP takes an operator specified
+by \f(CWopcode\fP, along with up to 2 operands specified by \f(CWval1\fP,
+and \f(CWval2\fP, converts it into the \f(CWDwarf\fP representation and
+appends the bytes to the byte stream being assembled for the location
+expression represented by \f(CWexpr\fP. The first operand, if present,
+to \f(CWopcode\fP is in \f(CWval1\fP, and the second operand, if present,
+is in \f(CWval2\fP. Both the operands may actually be signed or unsigned
+depending on \f(CWopcode\fP. It returns the number of bytes in the byte
+stream for \f(CWexpr\fP currently generated, i.e. after the addition of
+\f(CWopcode\fP. It returns \f(CWDW_DLV_NOCOUNT\fP on error.
+
+The function \f(CWdwarf_add_expr_gen()\fP works for all opcodes except
+those that have a target address as an operand. This is because it does
+not set up a relocation record that is needed when target addresses are
+involved.
+
+.H 3 "dwarf_add_expr_addr()"
+.DS
+\f(CWDwarf_Unsigned dwarf_add_expr_addr(
+ Dwarf_P_Expr expr,
+ Dwarf_Unsigned address,
+ Dwarf_Signed sym_index,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_add_expr_addr()\fP is used to add the
+\f(CWDW_OP_addr\fP opcode to the location expression represented
+by the given \f(CWDwarf_P_Expr\fP descriptor, \f(CWexpr\fP. The
+value of the relocatable address is given by \f(CWaddress\fP.
+The symbol to be used for relocation is given by \f(CWsym_index\fP,
+which is the index of the symbol in the Elf symbol table. It returns
+the number of bytes in the byte stream for \f(CWexpr\fP currently
+generated, i.e. after the addition of the \f(CWDW_OP_addr\fP operator.
+It returns \f(CWDW_DLV_NOCOUNT\fP on error.
+
+.H 3 "dwarf_add_expr_addr_b()"
+.DS
+\f(CWDwarf_Unsigned dwarf_add_expr_addr_b(
+ Dwarf_P_Expr expr,
+ Dwarf_Unsigned address,
+ Dwarf_Unsigned sym_index,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_add_expr_addr_f()\fP is
+identical to \f(CWdwarf_add_expr_addr()\fP
+except that \f(CWsym_index() \fP is guaranteed to
+be large enough that it can contain a pointer to
+arbitrary data (so the caller can pass in a real elf
+symbol index, an arbitrary number, or a pointer
+to arbitrary data).
+The ability to pass in a pointer through \f(CWsym_index() \fP
+is only usable with
+\f(CWDW_DLC_SYMBOLIC_RELOCATIONS\fP.
+
+
+
+.H 3 "dwarf_expr_current_offset()"
+.DS
+\f(CWDwarf_Unsigned dwarf_expr_current_offset(
+ Dwarf_P_Expr expr,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_expr_current_offset()\fP returns the number
+of bytes currently in the byte stream for the location expression
+represented by the given \fCW(Dwarf_P_Expr\fP descriptor, \f(CWexpr\fP.
+It returns \f(CWDW_DLV_NOCOUNT\fP on error.
+
+.H 3 "dwarf_expr_into_block()"
+.DS
+\f(CWDwarf_Addr dwarf_expr_into_block(
+ Dwarf_P_Expr expr,
+ Dwarf_Unsigned *length,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_expr_into_block()\fP returns the address
+of the start of the byte stream generated for the location expression
+represented by the given \f(CWDwarf_P_Expr\fP descriptor, \f(CWexpr\fP.
+The length of the byte stream is returned in the location pointed to
+by \f(CWlength\fP. It returns \f(CWDW_DLV_BADADDR\fP on error.
+
+.H 2 "Line Number Operations"
+These are operations on the .debug_line section.
+They provide
+information about instructions in the program and the source
+lines the instruction come from.
+Typically, code is generated
+in contiguous blocks, which may then be relocated as contiguous
+blocks.
+To make the provision of relocation information more
+efficient, the information is recorded in such a manner that only
+the address of the start of the block needs to be relocated.
+This is done by providing the address of the first instruction
+in a block using the function \f(CWdwarf_lne_set_address()\fP.
+Information about the instructions in the block are then added
+using the function \f(CWdwarf_add_line_entry()\fP, which specifies
+offsets from the address of the first instruction.
+The end of
+a contiguous block is indicated by calling the function
+\f(CWdwarf_lne_end_sequence()\fP.
+.P
+Line number operations do not support
+\f(CWDW_DLC_SYMBOLIC_RELOCATIONS\fP.
+
+.H 3 "dwarf_add_line_entry_b()"
+.DS
+\f(CWDwarf_Unsigned dwarf_add_line_entry_b(
+ Dwarf_P_Debug dbg,
+ Dwarf_Unsigned file_index,
+ Dwarf_Addr code_offset,
+ Dwarf_Unsigned lineno,
+ Dwarf_Signed column_number,
+ Dwarf_Bool is_source_stmt_begin,
+ Dwarf_Bool is_basic_block_begin,
+ Dwarf_Bool is_epilogue_begin,
+ Dwarf_Bool is_prologue_end,
+ Dwarf_Unsigned isa,
+ Dwarf_Unsigned discriminator,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_add_line_entry()\fP adds an entry to the
+section containing information about source lines.
+It specifies
+in \f(CWcode_offset\fP, the address of this line.
+The function subtracts \f(CWcode_offset\fP from the value given
+as the address of a previous line call to compute an offset,
+and the offset is what is recorded in the line instructions
+so no relocation will be needed on the line instruction generated.
+.P
+The source file that gave rise
+to the instruction is specified by \f(CWfile_index\fP, the source
+line number is specified by \f(CWlineno\fP, and the source column
+number is specified by \f(CWcolumn_number\fP
+(column numbers begin at 1)
+(if the source column is unknown, specify 0).
+\f(CWfile_index\fP
+is the index of the source file in a list of source files which is
+built up using the function \f(CWdwarf_add_file_decl()\fP.
+
+\f(CWis_source_stmt_begin\fP is a boolean flag that is true only if
+the instruction at \f(CWcode_address\fP is the first instruction in
+the sequence generated for the source line at \f(CWlineno\fP. Similarly,
+\f(CWis_basic_block_begin\fP is a boolean flag that is true only if
+the instruction at \f(CWcode_address\fP is the first instruction of
+a basic block.
+
+\f(CWis_epilogue_begin\fP is a boolean flag that is true only if
+the instruction at \f(CWcode_address\fP is the first instruction in
+the sequence generated for the function epilogue code.
+
+Similarly, \f(CWis_prolgue_end\fP is a boolean flag that is true only if
+the instruction at \f(CWcode_address\fP is the last instruction of
+the seqence generated for the function prologue.
+
+\f(CWisa\fP should be zero unless the code
+at \f(CWcode_address\fP is generated in a non-standard isa.
+The values assigned to non-standard isas are defined by the compiler
+implementation.
+
+\f(CWdiscriminator\fP should be zero unless the line table
+needs to distinguish among multiple blocks
+associated with the same source file, line, and column.
+The values assigned to \f(CWdiscriminator\fP are defined by the compiler
+implementation.
+
+It returns \f(CW0\fP on success, and \f(CWDW_DLV_NOCOUNT\fP on error.
+
+This function is defined as of December 2011.
+
+.H 3 "dwarf_add_line_entry()"
+.DS
+\f(CWDwarf_Unsigned dwarf_add_line_entry(
+ Dwarf_P_Debug dbg,
+ Dwarf_Unsigned file_index,
+ Dwarf_Addr code_offset,
+ Dwarf_Unsigned lineno,
+ Dwarf_Signed column_number,
+ Dwarf_Bool is_source_stmt_begin,
+ Dwarf_Bool is_basic_block_begin,
+ Dwarf_Error *error)\fP
+.DE
+This function is the same as \f(CWdwarf_add_line_entry_b()\fP
+except this older version is missing the new
+DWARF3/4 line table fields.
+
+.H 3 "dwarf_lne_set_address()"
+.DS
+\f(CWDwarf_Unsigned dwarf_lne_set_address(
+ Dwarf_P_Debug dbg,
+ Dwarf_Addr offs,
+ Dwarf_Unsigned symidx,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_lne_set_address()\fP sets the target address
+at which a contiguous block of instructions begin. Information about
+the instructions in the block is added to .debug_line using calls to
+\f(CWdwarfdwarf_add_line_entry()\fP which specifies the offset of each
+instruction in the block relative to the start of the block. This is
+done so that a single relocation record can be used to obtain the final
+target address of every instruction in the block.
+
+The relocatable address of the start of the block of instructions is
+specified by \f(CWoffs\fP. The symbol used to relocate the address
+is given by \f(CWsymidx\fP, which is normally the index of the symbol in the
+Elf symbol table.
+
+It returns \f(CW0\fP on success, and \f(CWDW_DLV_NOCOUNT\fP on error.
+
+.H 3 "dwarf_lne_end_sequence()"
+.DS
+\f(CWDwarf_Unsigned dwarf_lne_end_sequence(
+ Dwarf_P_Debug dbg,
+ Dwarf_Addr address;
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_lne_end_sequence()\fP indicates the end of a
+contiguous block of instructions.
+\f(CWaddress()\fP
+should be just higher than the end of the last address in the
+sequence of instructions.
+Before the next
+block of instructions (if any) a call to \f(CWdwarf_lne_set_address()\fP will
+have to be made to set the address of the start of the target address
+of the block, followed by calls to \f(CWdwarf_add_line_entry()\fP for
+each of the instructions in the block.
+
+It returns \f(CW0\fP on success, and \f(CWDW_DLV_NOCOUNT\fP on error.
+
+.H 3 "dwarf_add_directory_decl()"
+.DS
+\f(CWDwarf_Unsigned dwarf_add_directory_decl(
+ Dwarf_P_Debug dbg,
+ char *name,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_add_directory_decl()\fP adds the string
+specified by \f(CWname\fP to the list of include directories in
+the statement program prologue of the .debug_line section.
+The
+string should therefore name a directory from which source files
+have been used to create the present object.
+
+It returns the index of the string just added, in the list of include
+directories for the object.
+This index is then used to refer to this
+string. The first successful call of this function
+returns one, not zero, to be consistent with the directory indices
+that \f(CWdwarf_add_file_decl()\fP (below) expects..
+
+\f(CWdwarf_add_directory_decl()\fP
+returns \f(CWDW_DLV_NOCOUNT\fP on error.
+
+.H 3 "dwarf_add_file_decl()"
+.DS
+\f(CWDwarf_Unsigned dwarf_add_file_decl(
+ Dwarf_P_Debug dbg,
+ char *name,
+ Dwarf_Unsigned dir_idx,
+ Dwarf_Unsigned time_mod,
+ Dwarf_Unsigned length,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_add_file_decl()\fP adds the name of a source
+file that contributed to the present object.
+The name of the file is
+specified by \f(CWname\fP (which must not be the empty string
+or a null pointer, it must point to
+a string with length greater than 0).
+
+In case the name is not a fully-qualified
+pathname, it is
+considered prefixed with the name of the directory specified by
+\f(CWdir_idx\fP (which does not mean the \f(CWname\fP
+is changed or physically prefixed by
+this producer function, we simply describe the meaning here).
+\f(CWdir_idx\fP is the index of the directory to be
+prefixed in the list builtup using \f(CWdwarf_add_directory_decl()\fP.
+As specified by the DWARF spec, a \f(CWdir_idx\fP of zero will be
+interpreted as meaning the directory of the compilation and
+another index must refer to a valid directory as
+FIXME
+
+
+\f(CWtime_mod\fP gives the time at which the file was last modified,
+and \f(CWlength\fP gives the length of the file in bytes.
+
+It returns the index of the source file in the list built up so far
+using this function, on success. This index can then be used to
+refer to this source file in calls to \f(CWdwarf_add_line_entry()\fP.
+On error, it returns \f(CWDW_DLV_NOCOUNT\fP.
+
+.H 2 "Fast Access (aranges) Operations"
+These functions operate on the .debug_aranges section.
+
+.H 3 "dwarf_add_arange()"
+.DS
+\f(CWDwarf_Unsigned dwarf_add_arange(
+ Dwarf_P_Debug dbg,
+ Dwarf_Addr begin_address,
+ Dwarf_Unsigned length,
+ Dwarf_Signed symbol_index,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_add_arange()\fP adds another address range
+to be added to the section
+containing address range information, .debug_aranges.
+The relocatable start address of the range is
+specified by \f(CWbegin_address\fP, and the length of the address
+range is specified by \f(CWlength\fP.
+The relocatable symbol to be
+used to relocate the start of the address range is specified by
+\f(CWsymbol_index\fP, which is normally
+the index of the symbol in the Elf
+symbol table.
+
+It returns a non-zero value on success, and \f(CW0\fP on error.
+
+.H 3 "dwarf_add_arange_b()"
+.DS
+\f(CWDwarf_Unsigned dwarf_add_arange_b(
+ Dwarf_P_Debug dbg,
+ Dwarf_Addr begin_address,
+ Dwarf_Unsigned length,
+ Dwarf_Unsigned symbol_index,
+ Dwarf_Unsigned end_symbol_index,
+ Dwarf_Addr offset_from_end_symbol,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_add_arange_b()\fP adds another address range
+to be added to the section containing
+address range information, .debug_aranges.
+
+If
+\f(CWend_symbol_index is not zero\fP
+we are using two symbols to create a length
+(must be \f(CWDW_DLC_SYMBOLIC_RELOCATIONS\fP to be useful)
+.sp
+.in +2
+\f(CWbegin_address\fP
+is the offset from the symbol specified by
+\f(CWsymbol_index\fP .
+\f(CWoffset_from_end_symbol\fP
+is the offset from the symbol specified by
+\f(CWend_symbol_index\fP.
+\f(CWlength\fP is ignored.
+This begin-end pair will be show up in the
+relocation array returned by
+\f(CWdwarf_get_relocation_info() \fP
+as a
+\f(CWdwarf_drt_first_of_length_pair\fP
+and
+\f(CWdwarf_drt_second_of_length_pair\fP
+pair of relocation records.
+The consuming application will turn that pair into
+something conceptually identical to
+.sp
+.nf
+.in +4
+ .word end_symbol + offset_from_end - \\
+ ( start_symbol + begin_address)
+.in -4
+.fi
+.sp
+The reason offsets are allowed on the begin and end symbols
+is to allow the caller to re-use existing labels
+when the labels are available
+and the corresponding offset is known
+(economizing on the number of labels in use).
+The 'offset_from_end - begin_address'
+will actually be in the binary stream, not the relocation
+record, so the app processing the relocation array
+must read that stream value into (for example)
+net_offset and actually emit something like
+.sp
+.nf
+.in +4
+ .word end_symbol - start_symbol + net_offset
+.in -4
+.fi
+.sp
+.in -2
+
+If
+\f(CWend_symbol_index\fP is zero
+we must be given a length
+(either
+\f(CWDW_DLC_STREAM_RELOCATIONS\fP
+or
+\f(CWDW_DLC_SYMBOLIC_RELOCATIONS\fP
+):
+.sp
+.in +2
+The relocatable start address of the range is
+specified by \f(CWbegin_address\fP, and the length of the address
+range is specified by \f(CWlength\fP.
+The relocatable symbol to be
+used to relocate the start of the address range is specified by
+\f(CWsymbol_index\fP, which is normally
+the index of the symbol in the Elf
+symbol table.
+The
+\f(CWoffset_from_end_symbol\fP
+is ignored.
+.in -2
+
+
+It returns a non-zero value on success, and \f(CW0\fP on error.
+
+
+.H 2 "Fast Access (pubnames) Operations"
+These functions operate on the .debug_pubnames section.
+.sp
+.H 3 "dwarf_add_pubname()"
+.DS
+\f(CWDwarf_Unsigned dwarf_add_pubname(
+ Dwarf_P_Debug dbg,
+ Dwarf_P_Die die,
+ char *pubname_name,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_add_pubname()\fP adds the pubname specified
+by \f(CWpubname_name\fP to the section containing pubnames, i.e.
+ .debug_pubnames. The \f(CWDIE\fP that represents the function
+being named is specified by \f(CWdie\fP.
+
+It returns a non-zero value on success, and \f(CW0\fP on error.
+
+.H 2 "Fast Access (weak names) Operations"
+These functions operate on the .debug_weaknames section.
+
+.H 3 "dwarf_add_weakname()"
+.DS
+\f(CWDwarf_Unsigned dwarf_add_weakname(
+ Dwarf_P_Debug dbg,
+ Dwarf_P_Die die,
+ char *weak_name,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_add_weakname()\fP adds the weak name specified
+by \f(CWweak_name\fP to the section containing weak names, i.e.
+ .debug_weaknames. The \f(CWDIE\fP that represents the function
+being named is specified by \f(CWdie\fP.
+
+It returns a non-zero value on success, and \f(CW0\fP on error.
+
+.H 2 "Static Function Names Operations"
+The .debug_funcnames section contains the names of static function
+names defined in the object, and also the offsets of the \f(CWDIE\fPs
+that represent the definitions of the functions in the .debug_info
+section.
+
+.H 3 "dwarf_add_funcname()"
+.DS
+\f(CWDwarf_Unsigned dwarf_add_funcname(
+ Dwarf_P_Debug dbg,
+ Dwarf_P_Die die,
+ char *func_name,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_add_funcname()\fP adds the name of a static
+function specified by \f(CWfunc_name\fP to the section containing the
+names of static functions defined in the object represented by \f(CWdbg\fP.
+The \f(CWDIE\fP that represents the definition of the function is
+specified by \f(CWdie\fP.
+
+It returns a non-zero value on success, and \f(CW0\fP on error.
+
+.H 2 "File-scope User-defined Type Names Operations"
+The .debug_typenames section contains the names of file-scope
+user-defined types in the given object, and also the offsets
+of the \f(CWDIE\fPs that represent the definitions of the types
+in the .debug_info section.
+
+.H 3 "dwarf_add_typename()"
+.DS
+\f(CWDwarf_Unsigned dwarf_add_typename(
+ Dwarf_P_Debug dbg,
+ Dwarf_P_Die die,
+ char *type_name,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_add_typename()\fP adds the name of a file-scope
+user-defined type specified by \f(CWtype_name\fP to the section that
+contains the names of file-scope user-defined type. The object that
+this section belongs to is specified by \f(CWdbg\fP. The \f(CWDIE\fP
+that represents the definition of the type is specified by \f(CWdie\fP.
+
+It returns a non-zero value on success, and \f(CW0\fP on error.
+
+.H 2 "File-scope Static Variable Names Operations"
+The .debug_varnames section contains the names of file-scope static
+variables in the given object, and also the offsets of the \f(CWDIE\fPs
+that represent the definition of the variables in the .debug_info
+section.
+
+.H 3 "dwarf_add_varname()"
+.DS
+\f(CWDwarf_Unsigned dwarf_add_varname(
+ Dwarf_P_Debug dbg,
+ Dwarf_P_Die die,
+ char *var_name,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_add_varname()\fP adds the name of a file-scope
+static variable specified by \f(CWvar_name\fP to the section that
+contains the names of file-scope static variables defined by the
+object represented by \f(CWdbg\fP. The \f(CWDIE\fP that represents
+the definition of the static variable is specified by \f(CWdie\fP.
+
+It returns a non-zero value on success, and \f(CW0\fP on error.
+
+.H 2 "Macro Information Creation"
+All strings passed in by the caller are copied by these
+functions, so the space in which the caller provides the strings
+may be ephemeral (on the stack, or immediately reused or whatever)
+without this causing any difficulty.
+
+.H 3 "dwarf_def_macro()"
+.DS
+\f(CWint dwarf_def_macro(Dwarf_P_Debug dbg,
+ Dwarf_Unsigned lineno,
+ char *name
+ char *value,
+ Dwarf_Error *error);\fP
+.DE
+Adds a macro definition.
+The \f(CWname\fP argument should include the parentheses
+and parameter names if this is a function-like macro.
+Neither string should contain extraneous whitespace.
+\f(CWdwarf_def_macro()\fP adds the mandated space after the
+name and before the value in the
+output DWARF section(but does not change the
+strings pointed to by the arguments).
+If this is a definition before any files are read,
+\f(CWlineno\fP should be 0.
+Returns \f(CWDW_DLV_ERROR\fP
+and sets \f(CWerror\fP
+if there is an error.
+Returns \f(CWDW_DLV_OK\fP if the call was successful.
+
+
+.H 3 "dwarf_undef_macro()"
+.DS
+\f(CWint dwarf_undef_macro(Dwarf_P_Debug dbg,
+ Dwarf_Unsigned lineno,
+ char *name,
+ Dwarf_Error *error);\fP
+.DE
+Adds a macro un-definition note.
+If this is a definition before any files are read,
+\f(CWlineno\fP should be 0.
+Returns \f(CWDW_DLV_ERROR\fP
+and sets \f(CWerror\fP
+if there is an error.
+Returns \f(CWDW_DLV_OK\fP if the call was successful.
+
+
+.H 3 "dwarf_start_macro_file()"
+.DS
+\f(CWint dwarf_start_macro_file(Dwarf_P_Debug dbg,
+ Dwarf_Unsigned lineno,
+ Dwarf_Unsigned fileindex,
+ Dwarf_Error *error);\fP
+.DE
+\f(CWfileindex\fP is an index in the .debug_line header:
+the index of
+the file name.
+See the function \f(CWdwarf_add_file_decl()\fP.
+The \f(CWlineno\fP should be 0 if this file is
+the file of the compilation unit source itself
+(which, of course, is not a #include in any
+file).
+Returns \f(CWDW_DLV_ERROR\fP
+and sets \f(CWerror\fP
+if there is an error.
+Returns \f(CWDW_DLV_OK\fP if the call was successful.
+
+
+.H 3 "dwarf_end_macro_file()"
+.DS
+\f(CWint dwarf_end_macro_file(Dwarf_P_Debug dbg,
+ Dwarf_Error *error);\fP
+.DE
+Returns \f(CWDW_DLV_ERROR\fP
+and sets \f(CWerror\fP
+if there is an error.
+Returns \f(CWDW_DLV_OK\fP if the call was successful.
+
+.H 3 "dwarf_vendor_ext()"
+.DS
+\f(CWint dwarf_vendor_ext(Dwarf_P_Debug dbg,
+ Dwarf_Unsigned constant,
+ char * string,
+ Dwarf_Error* error); \fP
+.DE
+The meaning of the \f(CWconstant\fP and the\f(CWstring\fP
+in the macro info section
+are undefined by DWARF itself, but the string must be
+an ordinary null terminated string.
+This call is not an extension to DWARF.
+It simply enables storing
+macro information as specified in the DWARF document.
+Returns \f(CWDW_DLV_ERROR\fP
+and sets \f(CWerror\fP
+if there is an error.
+Returns \f(CWDW_DLV_OK\fP if the call was successful.
+
+
+.H 2 "Low Level (.debug_frame) operations"
+These functions operate on the .debug_frame section. Refer to
+\f(CWlibdwarf.h\fP for the register names and register assignment
+mapping. Both of these are necessarily machine dependent.
+
+.H 3 "dwarf_new_fde()"
+.DS
+\f(CWDwarf_P_Fde dwarf_new_fde(
+ Dwarf_P_Debug dbg,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_new_fde()\fP returns a new \f(CWDwarf_P_Fde\fP
+descriptor that should be used to build a complete \f(CWFDE\fP.
+Subsequent calls to routines that build up the \f(CWFDE\fP should use
+the same \f(CWDwarf_P_Fde\fP descriptor.
+
+It returns a valid \f(CWDwarf_P_Fde\fP descriptor on success, and
+\f(CWDW_DLV_BADADDR\fP on error.
+
+.H 3 "dwarf_add_frame_cie()"
+.DS
+\f(CWDwarf_Unsigned dwarf_add_frame_cie(
+ Dwarf_P_Debug dbg,
+ char *augmenter,
+ Dwarf_Small code_align,
+ Dwarf_Small data_align,
+ Dwarf_Small ret_addr_reg,
+ Dwarf_Ptr init_bytes,
+ Dwarf_Unsigned init_bytes_len,
+ Dwarf_Error *error);\fP
+.DE
+The function
+\f(CWdwarf_add_frame_cie()\fP
+creates a \f(CWCIE\fP,
+and returns an index to it, that should be used to refer to this
+\f(CWCIE\fP.
+\f(CWCIE\fPs are used by \f(CWFDE\fPs to setup
+initial values for frames.
+The augmentation string for the \f(CWCIE\fP
+is specified by \f(CWaugmenter\fP.
+The code alignment factor,
+data alignment factor, and the return address register for the
+\f(CWCIE\fP are specified by \f(CWcode_align\fP, \f(CWdata_align\fP,
+and \f(CWret_addr_reg\fP respectively.
+\f(CWinit_bytes\fP points
+to the bytes that represent the instructions for the \f(CWCIE\fP
+being created, and \f(CWinit_bytes_len\fP specifies the number
+of bytes of instructions.
+
+There is no convenient way to generate the \f(CWinit_bytes\fP
+stream.
+One just
+has to calculate it by hand or separately
+generate something with the
+correct sequence and use dwarfdump -v and readelf (or objdump)
+and some
+kind of hex dumper to see the bytes.
+This is a serious inconvenience!
+
+It returns an index to the \f(CWCIE\fP just created on success.
+On error it returns \f(CWDW_DLV_NOCOUNT\fP.
+
+.H 3 "dwarf_add_frame_fde()"
+.DS
+\f(CWDwarf_Unsigned dwarf_add_frame_fde(
+ Dwarf_P_Debug dbg,
+ Dwarf_P_Fde fde,
+ Dwarf_P_Die die,
+ Dwarf_Unsigned cie,
+ Dwarf_Addr virt_addr,
+ Dwarf_Unsigned code_len,
+ Dwarf_Unsigned sym_idx,
+ Dwarf_Error* error)\fP
+.DE
+The function \f(CWdwarf_add_frame_fde()\fP adds the \f(CWFDE\fP
+specified by \f(CWfde\fP to the list of \f(CWFDE\fPs for the
+object represented by the given \f(CWdbg\fP.
+\f(CWdie\fP specifies
+the \f(CWDIE\fP that represents the function whose frame information
+is specified by the given \f(CWfde\fP.
+\f(CWcie\fP specifies the
+index of the \f(CWCIE\fP that should be used to setup the initial
+conditions for the given frame.
+
+If the MIPS/IRIX specific DW_AT_MIPS_fde attribute is not
+needed in .debug_info pass in 0 as the \f(CWdie\fP argument.
+
+It returns an index to the given \f(CWfde\fP.
+
+
+.H 3 "dwarf_add_frame_fde_b()"
+.DS
+\f(CWDwarf_Unsigned dwarf_add_frame_fde_b(
+ Dwarf_P_Debug dbg,
+ Dwarf_P_Fde fde,
+ Dwarf_P_Die die,
+ Dwarf_Unsigned cie,
+ Dwarf_Addr virt_addr,
+ Dwarf_Unsigned code_len,
+ Dwarf_Unsigned sym_idx,
+ Dwarf_Unsigned sym_idx_of_end,
+ Dwarf_Addr offset_from_end_sym,
+ Dwarf_Error* error)\fP
+.DE
+This function is like
+\f(CWdwarf_add_frame_fde()\fP
+except that
+\f(CWdwarf_add_frame_fde_b()\fP
+has new arguments to allow use
+with
+\f(CWDW_DLC_SYMBOLIC_RELOCATIONS\fP.
+
+The function \f(CWdwarf_add_frame_fde_b()\fP
+adds the
+\f(CWFDE\fP
+specified by \f(CWfde\fP to the list of \f(CWFDE\fPs for the
+object represented by the given \f(CWdbg\fP.
+
+\f(CWdie\fP specifies
+the \f(CWDIE\fP that represents the function whose frame information
+is specified by the given \f(CWfde\fP.
+If the MIPS/IRIX specific DW_AT_MIPS_fde attribute is not
+needed in .debug_info pass in 0 as the \f(CWdie\fP argument.
+
+\f(CWcie\fP specifies the
+index of the \f(CWCIE\fP that should be used to setup the initial
+conditions for the given frame.
+\f(CWvirt_addr\fP represents the
+relocatable address at which the code for the given function begins,
+and \f(CWsym_idx\fP gives the index of the relocatable symbol to
+be used to relocate this address (\f(CWvirt_addr\fP that is).
+\f(CWcode_len\fP specifies the size in bytes of the machine instructions
+for the given function.
+
+If \f(CWsym_idx_of_end\fP is zero
+(may be
+\f(CWDW_DLC_STREAM_RELOCATIONS\fP
+or
+\f(CWDW_DLC_SYMBOLIC_RELOCATIONS\fP
+):
+.sp
+.in +2
+\f(CWvirt_addr\fP represents the
+relocatable address at which the code for the given function begins,
+and \f(CWsym_idx\fP gives the index of the relocatable symbol to
+be used to relocate this address (\f(CWvirt_addr\fP that is).
+\f(CWcode_len\fP
+specifies the size in bytes of the machine instructions
+for the given function.
+\f(CWsym_idx_of_end\fP
+and
+\f(CWoffset_from_end_sym\fP
+are unused.
+.in -2
+.sp
+
+
+If \f(CWsym_idx_of_end\fP is non-zero
+(must be \f(CWDW_DLC_SYMBOLIC_RELOCATIONS\fP to be useful):
+.sp
+.in +2
+\f(CWvirt_addr\fP
+is the offset from the symbol specified by
+\f(CWsym_idx\fP .
+\f(CWoffset_from_end_sym\fP
+is the offset from the symbol specified by
+\f(CWsym_idx_of_end\fP.
+\f(CWcode_len\fP is ignored.
+This begin-end pair will be show up in the
+relocation array returned by
+\f(CWdwarf_get_relocation_info() \fP
+as a
+\f(CWdwarf_drt_first_of_length_pair\fP
+and
+\f(CWdwarf_drt_second_of_length_pair\fP
+pair of relocation records.
+The consuming application will turn that pair into
+something conceptually identical to
+.sp
+.nf
+.in +4
+ .word end_symbol + begin - \\
+ ( start_symbol + offset_from_end)
+.in -4
+.fi
+.sp
+The reason offsets are allowed on the begin and end symbols
+is to allow the caller to re-use existing labels
+when the labels are available
+and the corresponding offset is known
+(economizing on the number of labels in use).
+The 'offset_from_end - begin_address'
+will actually be in the binary stream, not the relocation
+record, so the app processing the relocation array
+must read that stream value into (for example)
+net_offset and actually emit something like
+.sp
+.nf
+.in +4
+ .word end_symbol - start_symbol + net_offset
+.in -4
+.fi
+.sp
+.in -2
+
+It returns an index to the given \f(CWfde\fP.
+
+On error, it returns \f(CWDW_DLV_NOCOUNT\fP.
+
+.H 3 "dwarf_add_frame_info_b()"
+.DS
+\f(CWDwarf_Unsigned dwarf_add_frame_info_b(
+ Dwarf_P_Debug dbg,
+ Dwarf_P_Fde fde,
+ Dwarf_P_Die die,
+ Dwarf_Unsigned cie,
+ Dwarf_Addr virt_addr,
+ Dwarf_Unsigned code_len,
+ Dwarf_Unsigned sym_idx,
+ Dwarf_Unsigned end_symbol_index,
+ Dwarf_Addr offset_from_end_symbol,
+ Dwarf_Signed offset_into_exception_tables,
+ Dwarf_Unsigned exception_table_symbol,
+ Dwarf_Error* error)\fP
+.DE
+The function \f(CWdwarf_add_frame_fde()\fP adds the \f(CWFDE\fP
+specified by \f(CWfde\fP to the list of \f(CWFDE\fPs for the
+object represented by the given \f(CWdbg\fP.
+
+This function refers to MIPS/IRIX specific exception tables
+and is not a function other targets need.
+
+\f(CWdie\fP specifies
+the \f(CWDIE\fP that represents the function whose frame information
+is specified by the given \f(CWfde\fP.
+If the MIPS/IRIX specific DW_AT_MIPS_fde attribute is not
+needed in .debug_info pass in 0 as the \f(CWdie\fP argument.
+
+\f(CWcie\fP specifies the
+index of the \f(CWCIE\fP that should be used to setup the initial
+conditions for the given frame.
+
+\f(CWoffset_into_exception_tables\fP specifies the
+MIPS/IRIX specific
+offset into \f(CW.MIPS.eh_region\fP elf section where the exception tables
+for this function begins.
+\f(CWexception_table_symbol\fP is also MIPS/IRIX
+specific and it specifies the index of
+the relocatable symbol to be used to relocate this offset.
+
+
+If
+\f(CWend_symbol_index is not zero\fP
+we are using two symbols to create a length
+(must be \f(CWDW_DLC_SYMBOLIC_RELOCATIONS\fP to be useful)
+.sp
+.in +2
+\f(CWvirt_addr\fP
+is the offset from the symbol specified by
+\f(CWsym_idx\fP .
+\f(CWoffset_from_end_symbol\fP
+is the offset from the symbol specified by
+\f(CWend_symbol_index\fP.
+\f(CWcode_len\fP is ignored.
+This begin-end pair will be show up in the
+relocation array returned by
+\f(CWdwarf_get_relocation_info() \fP
+as a
+\f(CWdwarf_drt_first_of_length_pair\fP
+and
+\f(CWdwarf_drt_second_of_length_pair\fP
+pair of relocation records.
+The consuming application will turn that pair into
+something conceptually identical to
+.sp
+.nf
+.in +4
+ .word end_symbol + offset_from_end_symbol - \\
+ ( start_symbol + virt_addr)
+.in -4
+.fi
+.sp
+The reason offsets are allowed on the begin and end symbols
+is to allow the caller to re-use existing labels
+when the labels are available
+and the corresponding offset is known
+(economizing on the number of labels in use).
+The 'offset_from_end - begin_address'
+will actually be in the binary stream, not the relocation
+record, so the app processing the relocation array
+must read that stream value into (for example)
+net_offset and actually emit something like
+.sp
+.nf
+.in +4
+ .word end_symbol - start_symbol + net_offset
+.in -4
+.fi
+.sp
+.in -2
+
+If
+\f(CWend_symbol_index\fP is zero
+we must be given a code_len value
+(either
+\f(CWDW_DLC_STREAM_RELOCATIONS\fP
+or
+\f(CWDW_DLC_SYMBOLIC_RELOCATIONS\fP
+):
+.sp
+.in +2
+The relocatable start address of the range is
+specified by \f(CWvirt_addr\fP, and the length of the address
+range is specified by \f(CWcode_len\fP.
+The relocatable symbol to be
+used to relocate the start of the address range is specified by
+\f(CWsymbol_index\fP, which is normally
+the index of the symbol in the Elf
+symbol table.
+The
+\f(CWoffset_from_end_symbol\fP
+is ignored.
+.in -2
+
+
+It returns an index to the given \f(CWfde\fP.
+
+On error, it returns \f(CWDW_DLV_NOCOUNT\fP.
+
+
+.H 3 "dwarf_add_frame_info()"
+
+.DS
+\f(CWDwarf_Unsigned dwarf_add_frame_info(
+ Dwarf_P_Debug dbg,
+ Dwarf_P_Fde fde,
+ Dwarf_P_Die die,
+ Dwarf_Unsigned cie,
+ Dwarf_Addr virt_addr,
+ Dwarf_Unsigned code_len,
+ Dwarf_Unsigned sym_idx,
+ Dwarf_Signed offset_into_exception_tables,
+ Dwarf_Unsigned exception_table_symbol,
+ Dwarf_Error* error)\fP
+.DE
+The function \f(CWdwarf_add_frame_fde()\fP adds the \f(CWFDE\fP
+specified by \f(CWfde\fP to the list of \f(CWFDE\fPs for the
+object represented by the given \f(CWdbg\fP.
+
+\f(CWdie\fP specifies
+the \f(CWDIE\fP that represents the function whose frame information
+is specified by the given \f(CWfde\fP.
+If the MIPS/IRIX specific DW_AT_MIPS_fde attribute is not
+needed in .debug_info pass in 0 as the \f(CWdie\fP argument.
+
+\f(CWcie\fP specifies the
+index of the \f(CWCIE\fP that should be used to setup the initial
+conditions for the given frame. \f(CWvirt_addr\fP represents the
+relocatable address at which the code for the given function begins,
+and \f(CWsym_idx\fP gives the index of the relocatable symbol to
+be used to relocate this address (\f(CWvirt_addr\fP that is).
+\f(CWcode_len\fP specifies the size in bytes of the machine instructions
+for the given function.
+
+\f(CWoffset_into_exception_tables\fP specifies the
+offset into \f(CW.MIPS.eh_region\fP elf section where the exception tables
+for this function begins.
+\f(CWexception_table_symbol\fP gives the index of
+the relocatable symbol to be used to relocate this offset.
+These arguments are MIPS/IRIX specific, pass in 0 for
+other targets.
+
+It returns an index to the given \f(CWfde\fP.
+
+.H 3 "dwarf_fde_cfa_offset()"
+.DS
+\f(CWDwarf_P_Fde dwarf_fde_cfa_offset(
+ Dwarf_P_Fde fde,
+ Dwarf_Unsigned reg,
+ Dwarf_Signed offset,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_fde_cfa_offset()\fP appends a \f(CWDW_CFA_offset\fP
+operation to the \f(CWFDE\fP, specified by \f(CWfde\fP, being constructed.
+The first operand of the \f(CWDW_CFA_offset\fP operation is specified by
+\f(CWreg\P. The register specified should not exceed 6 bits. The second
+operand of the \f(CWDW_CFA_offset\fP operation is specified by \f(CWoffset\fP.
+
+It returns the given \f(CWfde\fP on success.
+
+It returns \f(CWDW_DLV_BADADDR\fP on error.
+
+.H 3 "dwarf_add_fde_inst()"
+.DS
+\f(CWDwarf_P_Fde dwarf_add_fde_inst(
+ Dwarf_P_Fde fde,
+ Dwarf_Small op,
+ Dwarf_Unsigned val1,
+ Dwarf_Unsigned val2,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_add_fde_inst()\fP adds the operation specified
+by \f(CWop\fP to the \f(CWFDE\fP specified by \f(CWfde\fP. Up to two
+operands can be specified in \f(CWval1\fP, and \f(CWval2\fP. Based on
+the operand specified \f(CWLibdwarf\fP decides how many operands are
+meaningful for the operand. It also converts the operands to the
+appropriate datatypes (they are passed to \f(CWdwarf_add_fde_inst\fP
+as \f(CWDwarf_Unsigned\fP).
+
+It returns the given \f(CWfde\fP on success, and \f(CWDW_DLV_BADADDR\fP
+on error.
+
+.H 3 "dwarf_insert_fde_inst_bytes()"
+.DS
+\f(CWint dwarf_insert_fde_inst_bytes(
+ Dwarf_P_Debug dbg,
+ Dwarf_P_Fde fde,
+ Dwarf_Unsigned len,
+ Dwarf_Ptr ibytes,
+ Dwarf_Error *error)\fP
+.DE
+The function \f(CWdwarf_insert_fde_inst_bytes()\fP inserts
+the byte array (pointed at by \f(CWibytes\fP and of length \f(CWlen\fP)
+of frame instructions into the fde \f(CWfde\fP.
+It is incompatible with \f(CWdwarf_add_fde_inst()\fP, do not use
+both functions on any given Dwarf_P_Debug.
+At present it may only be called once on a given \f(CWfde\fP.
+The \f(CWlen\fP bytes \f(CWibytes\fP may be constructed in any way, but
+the assumption is they were copied from an object file
+such as is returned by the libdwarf consumer function
+\f(CWdwarf_get_fde_instr_bytes()\fP.
+
+It returns \f(CWDW_DLV_OK\fP on success, and \f(CWDW_DLV_ERROR\fP
+on error.
+
+
+.S
+.TC 1 1 4
+.CS
diff --git a/libdwarf/libdwarf2p.1.pdf b/libdwarf/libdwarf2p.1.pdf
new file mode 100644
index 0000000..c353ff8
--- /dev/null
+++ b/libdwarf/libdwarf2p.1.pdf
Binary files differ
diff --git a/libdwarf/libdwarfdefs.h b/libdwarf/libdwarfdefs.h
new file mode 100644
index 0000000..83c8a42
--- /dev/null
+++ b/libdwarf/libdwarfdefs.h
@@ -0,0 +1,91 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+/* libdwarfdefs.h
+*/
+
+#ifndef LIBDWARFDEFS_H
+#define LIBDWARFDEFS_H
+
+/* We want __uint32_t and __uint64_t and __int32_t __int64_t
+ properly defined but not duplicated, since duplicate typedefs
+ are not legal C.
+*/
+/*
+ HAVE___UINT32_T
+ HAVE___UINT64_T will be set by configure if
+ our 4 types are predefined in compiler
+*/
+
+
+#if (!defined(HAVE___UINT32_T)) && defined(HAVE___UINT32_T_IN_SGIDEFS_H)
+#include <sgidefs.h> /* sgidefs.h defines them */
+#define HAVE___UINT32_T 1
+#endif
+
+#if (!defined(HAVE___UINT64_T)) && defined(HAVE___UINT64_T_IN_SGIDEFS_H)
+#include <sgidefs.h> /* sgidefs.h defines them */
+#define HAVE___UINT64_T 1
+#endif
+
+
+#if (!defined(HAVE___UINT32_T)) && \
+ defined(HAVE_SYS_TYPES_H) && \
+ defined(HAVE___UINT32_T_IN_SYS_TYPES_H)
+# include <sys/types.h>
+#define HAVE___UINT32_T 1
+#endif
+
+#if (!defined(HAVE___UINT64_T)) && \
+ defined(HAVE_SYS_TYPES_H) && \
+ defined(HAVE___UINT64_T_IN_SYS_TYPES_H)
+# include <sys/types.h>
+#define HAVE___UINT64_T 1
+#endif
+
+#ifndef HAVE___UINT32_T
+typedef int __int32_t;
+typedef unsigned __uint32_t;
+#define HAVE___UINT32_T 1
+#endif
+
+#ifndef HAVE___UINT64_T
+typedef long long __int64_t;
+typedef unsigned long long __uint64_t;
+#define HAVE___UINT64_T 1
+#endif
+
+#endif /* LIBDWARFDEFS_H */
diff --git a/libdwarf/malloc_check.c b/libdwarf/malloc_check.c
new file mode 100644
index 0000000..35a1483
--- /dev/null
+++ b/libdwarf/malloc_check.c
@@ -0,0 +1,339 @@
+/*
+
+ Copyright (C) 2005 Silicon Graphics, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+/* malloc_check.c For checking dealloc completeness.
+
+ This code is as simple as possible and works ok for
+ reasonable size allocation counts.
+
+ It treats allocation as global, and so will not
+ work very well if an application opens more than one
+ Dwarf_Debug.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h> /* for exit() and various malloc
+ prototypes */
+#include "config.h"
+#include "dwarf_incl.h"
+#include "malloc_check.h"
+#ifdef WANT_LIBBDWARF_MALLOC_CHECK
+
+/* To turn off printing every entry, just change the define
+ to set PRINT_MALLOC_DETAILS 0.
+*/
+#define PRINT_MALLOC_DETAILS 0
+
+#define MC_TYPE_UNKNOWN 0
+#define MC_TYPE_ALLOC 1
+#define MC_TYPE_DEALLOC 2
+
+struct mc_data_s {
+ struct mc_data_s *mc_prev;
+ unsigned long mc_address; /* Assumes this is large enough to hold
+ a pointer! */
+
+ long mc_alloc_number; /* Assigned in order by when record
+ created. */
+ unsigned char mc_alloc_code; /* Allocation code, libdwarf. */
+ unsigned char mc_type;
+ unsigned char mc_dealloc_noted; /* Used on an ALLOC node. */
+ unsigned char mc_dealloc_noted_count; /* Used on an ALLOC
+ node. */
+};
+
+/*
+
+
+*/
+#define HASH_TABLE_SIZE 10501
+static struct mc_data_s *mc_data_hash[HASH_TABLE_SIZE];
+static long mc_data_list_size = 0;
+
+static char *alloc_type_name[MAX_DW_DLA + 1] = {
+ "",
+ "DW_DLA_STRING",
+ "DW_DLA_LOC",
+ "DW_DLA_LOCDESC",
+ "DW_DLA_ELLIST",
+ "DW_DLA_BOUNDS",
+ "DW_DLA_BLOCK",
+ "DW_DLA_DEBUG",
+ "DW_DLA_DIE",
+ "DW_DLA_LINE",
+ "DW_DLA_ATTR",
+ "DW_DLA_TYPE",
+ "DW_DLA_SUBSCR",
+ "DW_DLA_GLOBAL",
+ "DW_DLA_ERROR",
+ "DW_DLA_LIST",
+ "DW_DLA_LINEBUF",
+ "DW_DLA_ARANGE",
+ "DW_DLA_ABBREV",
+ "DW_DLA_FRAME_OP",
+ "DW_DLA_CIE",
+ "DW_DLA_FDE",
+ "DW_DLA_LOC_BLOCK",
+ "DW_DLA_FRAME_BLOCK",
+ "DW_DLA_FUNC",
+ "DW_DLA_TYPENAME",
+ "DW_DLA_VAR",
+ "DW_DLA_WEAK",
+ "DW_DLA_ADDR",
+ "DW_DLA_ABBREV_LIST",
+ "DW_DLA_CHAIN",
+ "DW_DLA_CU_CONTEXT",
+ "DW_DLA_FRAME",
+ "DW_DLA_GLOBAL_CONTEXT",
+ "DW_DLA_FILE_ENTRY",
+ "DW_DLA_LINE_CONTEXT",
+ "DW_DLA_LOC_CHAIN",
+ "DW_DLA_HASH_TABLE",
+ "DW_DLA_FUNC_CONTEXT",
+ "DW_DLA_TYPENAME_CONTEXT",
+ "DW_DLA_VAR_CONTEXT",
+ "DW_DLA_WEAK_CONTEXT",
+ "DW_DLA_PUBTYPES_CONTEXT"
+ /* Don't forget to expand this list if the list of codes
+ expands. */
+};
+
+static unsigned
+hash_address(unsigned long addr)
+{
+ unsigned long a = addr >> 2;
+
+ return a % HASH_TABLE_SIZE;
+}
+
+#if PRINT_MALLOC_DETAILS
+static void
+print_alloc_dealloc_detail(unsigned long addr,
+ int code, char *whichisit)
+{
+ fprintf(stderr,
+ "%s addr 0x%lx code %d (%s) entry %ld\n",
+ whichisit, addr, code, alloc_type_name[code],
+ mc_data_list_size);
+}
+#else
+#define print_alloc_dealloc_detail(a,b,c) /* nothing */
+#endif
+
+/* Create a zeroed struct or die. */
+static void *
+newone(void)
+{
+ struct mc_data_s *newd = malloc(sizeof(struct mc_data_s));
+
+ if (newd == 0) {
+ fprintf(stderr, "out of memory , # %ld\n", mc_data_list_size);
+ exit(1);
+ }
+ memset(newd, 0, sizeof(struct mc_data_s));
+ return newd;
+}
+
+/* Notify checker that get_alloc has allocated user data. */
+void
+dwarf_malloc_check_alloc_data(void *addr_in, unsigned char code)
+{
+ struct mc_data_s *newd = newone();
+ unsigned long addr = (unsigned long) addr_in;
+ struct mc_data_s **base = &mc_data_hash[hash_address(addr)];
+
+ print_alloc_dealloc_detail(addr, code, "alloc ");
+ newd->mc_address = addr;
+ newd->mc_alloc_code = code;
+ newd->mc_type = MC_TYPE_ALLOC;
+ newd->mc_alloc_number = mc_data_list_size;
+ newd->mc_prev = *base;
+ *base = newd;
+ newd->mc_alloc_number = mc_data_list_size;
+ mc_data_list_size += 1;
+}
+
+static void
+print_entry(char *msg, struct mc_data_s *data)
+{
+ fprintf(stderr,
+ "%s: 0x%08lx code %2d (%s) type %s dealloc noted %u ct %u\n",
+ msg,
+ (long) data->mc_address,
+ data->mc_alloc_code,
+ alloc_type_name[data->mc_alloc_code],
+ (data->mc_type == MC_TYPE_ALLOC) ? "alloc " :
+ (data->mc_type == MC_TYPE_DEALLOC) ? "dealloc" : "unknown",
+ (unsigned) data->mc_dealloc_noted,
+ (unsigned) data->mc_dealloc_noted_count);
+}
+
+/* newd is a 'dealloc'.
+*/
+static long
+balanced_by_alloc_p(struct mc_data_s *newd,
+ long *addr_match_num,
+ struct mc_data_s **addr_match,
+ struct mc_data_s *base)
+{
+ struct mc_data_s *cur = base;
+
+ for (; cur; cur = cur->mc_prev) {
+ if (cur->mc_address == newd->mc_address) {
+ if (cur->mc_type == MC_TYPE_ALLOC) {
+ if (cur->mc_alloc_code == newd->mc_alloc_code) {
+ *addr_match = cur;
+ *addr_match_num = cur->mc_alloc_number;
+ return cur->mc_alloc_number;
+ } else {
+ /* code mismatch */
+ *addr_match = cur;
+ *addr_match_num = cur->mc_alloc_number;
+ return -1;
+ }
+ } else {
+ /* Unbalanced new/del */
+ *addr_match = cur;
+ *addr_match_num = cur->mc_alloc_number;
+ return -1;
+ }
+ }
+ }
+ return -1;
+}
+
+/* A dealloc is to take place. Ensure it balances an alloc.
+*/
+void
+dwarf_malloc_check_dealloc_data(void *addr_in, unsigned char code)
+{
+ struct mc_data_s *newd = newone();
+ long prev;
+ long addr_match_num = -1;
+ struct mc_data_s *addr_match = 0;
+ unsigned long addr = (unsigned long) addr_in;
+ struct mc_data_s **base = &mc_data_hash[hash_address(addr)];
+
+
+ print_alloc_dealloc_detail(addr, code, "dealloc ");
+ newd->mc_address = (unsigned long) addr;
+ newd->mc_alloc_code = code;
+ newd->mc_type = MC_TYPE_DEALLOC;
+ newd->mc_prev = *base;
+ prev =
+ balanced_by_alloc_p(newd, &addr_match_num, &addr_match, *base);
+ if (prev < 0) {
+ fprintf(stderr,
+ "Unbalanced dealloc at index %ld\n", mc_data_list_size);
+ print_entry("new", newd);
+ fprintf(stderr, "addr-match_num? %ld\n", addr_match_num);
+ if (addr_match) {
+ print_entry("prev entry", addr_match);
+ if (addr_match->mc_dealloc_noted > 1) {
+ fprintf(stderr, "Above is Duplicate dealloc!\n");
+ }
+ }
+ abort();
+ exit(3);
+ }
+ addr_match->mc_dealloc_noted = 1;
+ addr_match->mc_dealloc_noted_count += 1;
+ if (addr_match->mc_dealloc_noted_count > 1) {
+ fprintf(stderr, "Double dealloc entry %ld\n", addr_match_num);
+ print_entry("new dealloc entry", newd);
+ print_entry("bad alloc entry", addr_match);
+ }
+ *base = newd;
+ mc_data_list_size += 1;
+}
+
+/* Final check for leaks.
+*/
+void
+dwarf_malloc_check_complete(char *msg)
+{
+ long i = 0;
+ long total = mc_data_list_size;
+ long hash_slots_used = 0;
+ long max_chain_length = 0;
+
+ fprintf(stderr, "Run complete, %s. %ld entries\n", msg, total);
+ for (; i < HASH_TABLE_SIZE; ++i) {
+ struct mc_data_s *cur = mc_data_hash[i];
+ long cur_chain_length = 0;
+
+ if (cur == 0)
+ continue;
+ ++hash_slots_used;
+ for (; cur; cur = cur->mc_prev) {
+ ++cur_chain_length;
+ if (cur->mc_type == MC_TYPE_ALLOC) {
+ if (cur->mc_dealloc_noted) {
+ if (cur->mc_dealloc_noted > 1) {
+ fprintf(stderr,
+ " Duplicate dealloc! entry %ld\n",
+ cur->mc_alloc_number);
+ print_entry("duplicate dealloc", cur);
+
+ }
+ continue;
+ } else {
+ fprintf(stderr, "malloc no dealloc, entry %ld\n",
+ cur->mc_alloc_number);
+ print_entry("dangle", cur);
+ }
+ } else {
+ /* mc_type is MC_TYPE_DEALLOC, already checked */
+
+ }
+ }
+ if (cur_chain_length > max_chain_length) {
+ max_chain_length = cur_chain_length;
+ }
+ }
+ fprintf(stderr, "mc hash table slots=%ld, "
+ "used=%ld, maxchain=%ld\n",
+ (long) HASH_TABLE_SIZE, hash_slots_used, max_chain_length);
+ return;
+}
+
+#else
+
+extern void *libdwarf_an_unused_function_so_not_empty_c_file();
+
+#endif /* WANT_LIBBDWARF_MALLOC_CHECK */
diff --git a/libdwarf/malloc_check.h b/libdwarf/malloc_check.h
new file mode 100644
index 0000000..ba1ad3d
--- /dev/null
+++ b/libdwarf/malloc_check.h
@@ -0,0 +1,62 @@
+/*
+
+ Copyright (C) 2005 Silicon Graphics, Inc. All Rights Reserved.
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+/* malloc_check.h */
+
+/* A simple libdwarf-aware malloc checker.
+ define WANT_LIBBDWARF_MALLOC_CHECK and rebuild libdwarf
+ do make a checking-for-alloc-mistakes libdwarf.
+ NOT recommended for production use.
+
+ When defined, also add malloc_check.c to the list of
+ files in Makefile.
+*/
+
+#undef WANT_LIBBDWARF_MALLOC_CHECK
+/*#define WANT_LIBBDWARF_MALLOC_CHECK 1 */
+
+#ifdef WANT_LIBBDWARF_MALLOC_CHECK
+
+void dwarf_malloc_check_alloc_data(void * addr,unsigned char code);
+void dwarf_malloc_check_dealloc_data(void * addr,unsigned char code);
+void dwarf_malloc_check_complete(char *wheremsg); /* called at exit of app */
+
+#else /* !WANT_LIBBDWARF_MALLOC_CHECK */
+
+#define dwarf_malloc_check_alloc_data(a,b) /* nothing */
+#define dwarf_malloc_check_dealloc_data(a,b) /* nothing */
+#define dwarf_malloc_check_complete(a) /* nothing */
+
+#endif /* WANT_LIBBDWARF_MALLOC_CHECK */
diff --git a/libdwarf/mips_extensions.mm b/libdwarf/mips_extensions.mm
new file mode 100644
index 0000000..7a312f0
--- /dev/null
+++ b/libdwarf/mips_extensions.mm
@@ -0,0 +1,1266 @@
+\."
+\." the following line may be removed if the ff ligature works on your machine
+.lg 0
+\." set up heading formats
+.ds HF 3 3 3 3 3 2 2
+.ds HP +2 +2 +1 +0 +0
+.nr Hs 5
+.nr Hb 5
+\." ==============================================
+\." Put current date in the following at each rev
+.ds vE rev 1.18, 31 March 2005
+\." ==============================================
+\." ==============================================
+.ds | |
+.ds ~ ~
+.ds ' '
+.if t .ds Cw \&\f(CW
+.if n .ds Cw \fB
+.de Cf \" Place every other arg in Cw font, beginning with first
+.if \\n(.$=1 \&\*(Cw\\$1\fP
+.if \\n(.$=2 \&\*(Cw\\$1\fP\\$2
+.if \\n(.$=3 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP
+.if \\n(.$=4 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP\\$4
+.if \\n(.$=5 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP\\$4\*(Cw\\$5\fP
+.if \\n(.$=6 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP\\$4\*(Cw\\$5\fP\\$6
+.if \\n(.$=7 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP\\$4\*(Cw\\$5\fP\\$6\*(Cw\\$7\fP
+.if \\n(.$=8 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP\\$4\*(Cw\\$5\fP\\$6\*(Cw\\$7\fP\\$8
+.if \\n(.$=9 \&\*(Cw\\$1\fP\\$2\*(Cw\\$3\fP\\$4\*(Cw\\$5\fP\\$6\*(Cw\\$7\fP\\$8\
+*(Cw
+..
+.nr Cl 4
+.SA 1
+.TL
+MIPS Extensions to DWARF Version 2.0
+.AF ""
+.AU "Silicon Graphics Computer Systems"
+.PF "'\*(vE'- \\\\nP -''"
+.AS 1
+This document describes the MIPS/Silicon Graphics extensions
+to the "DWARF Information Format" (version 2.0.0 dated July 27, 1993).
+DWARF3 draft 8 (or draft 9) is out as of 2005, and
+is mentioned below where applicable.
+MIPS/IRIX compilers emit DWARF2 (with extensions).
+.P
+Rather than alter the base documents to describe the extensions
+we provide this separate document.
+.P
+The extensions documented here are subject to change.
+.P
+It also describes known bugs resulting in incorrect dwarf usage.
+.P
+\*(vE
+
+.AE
+.MT 4
+
+.H 1 "INTRODUCTION"
+.P
+This
+document describes MIPS extensions
+to the DWARF debugging information format.
+The extensions documented here are subject to change at
+any time.
+.H 1 "64 BIT DWARF"
+.P
+The DWARF2 spec has no provision for 64 bit offsets.
+SGI-IRIX/MIPS Elf64 objects contain DWARF 2 with all offsets
+(and addresses) as 64bit values.
+This non-standard extension was adopted in 1992.
+Nothing in the dwarf itself identifies the dwarf as 64bit.
+This extension 64bit-offset dwarf cannot be mixed with 32bit-offset dwarf
+in a single object or executable, and SGI-IRIX/MIPS compilers
+and tools do not mix the sizes.
+.P
+In 2001 DWARF3 adopted a very different 64bit-offset
+format which can be mixed usefully with 32bit-offset DWARF2 or DWARF3.
+It is not very likely SGI-IRIX/MIPS compilers will switch to the
+now-standard
+DWARF3 64bit-offset scheme, but such a switch is theoretically
+possible and would be a good idea.
+.P
+SGI-IRIX/MIPS Elf32 objects
+contain DWARF2 with all offsets (and addresses) 32 bits.
+.H 1 "How much symbol information is emitted"
+The following standard DWARF V2 sections may be emitted:
+.AL
+.LI
+Section .debug_abbrev
+contains
+abbreviations supporting the .debug_info section.
+.LI
+Section .debug_info
+contains
+Debug Information Entries (DIEs).
+.LI
+Section .debug_frame
+contains
+stack frame descriptions.
+.LI
+Section .debug_line
+contains
+line number information.
+.LI
+Section .debug_aranges
+contains
+address range descriptions.
+.LI
+Section .debug_pubnames
+contains
+names of global functions and data.
+.P
+The following
+are MIPS extensions.
+Theses were created to allow debuggers to
+know names without having to look at
+the .debug_info section.
+.LI
+Section .debug_weaknames
+is a MIPS extension
+containing .debug_pubnames-like entries describing weak
+symbols.
+.LI
+Section .debug_funcnames
+is a MIPS extension
+containing .debug_pubnames-like entries describing file-static
+functions (C static functions).
+The gcc extension of nested subprograms (like Pascal)
+adds non-global non-static functions. These should be treated like
+static functions and gcc should add such to this section
+so that IRIX libexc(3C) will work correctly.
+Similarly, Ada functions which are non-global should be here too
+so that libexc(3C) can work.
+Putting it another way, every function (other than inline code)
+belongs either in .debug_pubnames or in .debug_funcnames
+or else libexc(3C) cannot find the function name.
+.LI
+Section .debug_varnames
+is a MIPS extension
+containing .debug_pubnames-like entries describing file-static
+data symbols (C static variables).
+.LI
+Section .debug_typenames
+is a MIPS extension
+containing .debug_pubnames-like entries describing file-level
+types.
+.P
+The following are not currently emitted.
+.LI
+Section .debug_macinfo
+Macro information is not currently emitted.
+.LI
+Section .debug_loc
+Location lists are not currently emitted.
+.LI
+Section .debug_str
+The string section is not currently emitted.
+.LE
+.H 2 "Overview of information emitted"
+We emit debug information in 3 flavors.
+We mention C here.
+The situation is essentially identical for f77, f90, and C++.
+.AL
+.LI
+"default C"
+We emit line information and DIEs for each subprogram.
+But no local symbols and no type information.
+Frame information is output.
+The DW_AT_producer string has the optimization level: for example
+"-O2".
+We put so much in the DW_AT_producer that the string
+is a significant user of space in .debug_info --
+this is perhaps a poor use of space.
+When optimizing the IRIX CC/cc option -DEBUG:optimize_space
+eliminates such wasted space.
+Debuggers only currently use the lack of -g
+of DW_AT_producer
+as a hint as to how a 'step' command should be interpreted, and
+the rest of the string is not used for anything (unless
+a human looks at it for some reason), so if space-on-disk
+is an issue, it is quite appropriate to use -DEBUG:optimize_space
+and save disk space.
+Every function definition (not inline instances though) is mentioned
+in either .debug_pubnames or .debug_funcnames.
+This is crucial to allow libexc(3C) stack-traceback to work and
+show function names (for all languages).
+.LI
+"C with full symbols"
+All possible info is emitted.
+DW_AT_producer string has all options that might be of interest,
+which includes -D's, -U's, and the -g option.
+These options look like they came from the command line.
+We put so much in the DW_AT_producer that the string
+is a significant user of space in .debug_info.
+this is perhaps a poor use of space.
+Debuggers only currently use the -g
+of DW_AT_producer
+as a hint as to how a 'step' command should be interpreted, and
+the rest of the string is not used for anything (unless
+a human looks at it for some reason).
+Every function definition (not inline instances though) is mentioned
+in either .debug_pubnames or .debug_funcnames.
+This is crucial to allow libexc(3C) stack-traceback to work and
+show function names (for all languages).
+.LI
+"Assembler (-g, non -g are the same)"
+Frame information is output.
+No type information is emitted, but DIEs are prepared
+for globals.
+.LE
+.H 2 "Detecting 'full symbols' (-g)"
+The debugger depends on the existence of
+the DW_AT_producer string to determine if the
+compilation unit has full symbols or not.
+It looks for -g or -g[123] and accepts these as
+full symbols but an absent -g or a present -g0
+is taken to mean that only basic symbols are defined and there
+are no local symbols and no type information.
+.P
+In various contexts the debugger will think the program is
+stripped or 'was not compiled with -g' unless the -g
+is in the DW_AT_producer string.
+.H 2 "DWARF and strip(1)"
+The DWARF section ".debug_frame" is marked SHF_MIPS_NOSTRIP
+and is not stripped by the strip(1) program.
+This is because the section is needed for doing
+stack back traces (essential for C++
+and Ada exception handling).
+.P
+All .debug_* sections are marked with elf type
+SHT_MIPS_DWARF.
+Applications needing to access the various DWARF sections
+must use the section name to discriminate between them.
+
+.H 2 "Evaluating location expressions"
+When the debugger evaluates location expressions, it does so
+in 2 stages. In stage one it simply looks for the trivial
+location expressions and treats those as special cases.
+.P
+If the location expression is not trivial, it enters stage two.
+In this case it uses a stack to evaluate the expression.
+.P
+If the application is a 32-bit application, it does the operations
+on 32-bit values (address size values). Even though registers
+can be 64 bits in a 32-bit program all evaluations are done in
+32-bit quantities, so an attempt to calculate a 32-bit quantity
+by taking the difference of 2 64-bit register values will not
+work. The notion is that the stack machine is, by the dwarf
+definition, working in address size units.
+.P
+These values are then expanded to 64-bit values (addresses or
+offsets). This extension does not involve sign-extension.
+.P
+If the application is a 64-bit application, then the stack
+values are all 64 bits and all operations are done on 64 bits.
+.H 3 "The fbreg location op"
+Compilers shipped with IRIX 6.0 and 6.1
+do not emit the fbreg location expression
+and never emit the DW_AT_frame_base attribute that it
+depends on.
+However, this changes
+with release 6.2 and these are now emitted routinely.
+
+.H 1 "Frame Information"
+.H 2 "Initial Instructions"
+The DWARF V2 spec
+provides for "initial instructions" in each CIE (page 61,
+section 6.4.1).
+However, it does not say whether there are default
+values for each column (register).
+.P
+Rather than force every CIE to have a long list
+of bytes to initialize all 32 integer registers,
+we define that the default values of all registers
+(as returned by libdwarf in the frame interface)
+are 'same value'.
+This is a good choice for many non-register-windows
+implementations.
+.H 2 "Augmentation string in debug_frame"
+The augmentation string we use in shipped compilers (up thru
+irix6.2) is the empty string.
+IRIX6.2 and later has an augmentation string
+the empty string ("")
+or "z" or "mti v1"
+where the "v1" is a version number (version 1).
+.P
+We do not believe that "mti v1" was emitted as the
+augmentation string in any shipped compiler.
+.P
+.H 3 "CIE processing based on augmentation string:"
+If the augmentation string begins with 'z', then it is followed
+immediately by a unsigned_leb_128 number giving the code alignment factor.
+Next is a signed_leb_128 number giving the data alignment factor.
+Next is a unsigned byte giving the number of the return address register.
+Next is an unsigned_leb_128 number giving the length of the 'augmentation'
+fields (the length of augmentation bytes, not
+including the unsigned_leb_128 length itself).
+As of release 6.2, the length of the CIE augmentation fields is 0.
+What this means is that it is possible to add new
+augmentations, z1, z2, etc and yet an old consumer to
+understand the entire CIE as it can bypass the
+augmentation it does not understand because the
+length of the augmentation fields is present.
+Presuming of course that all augmentation fields are
+simply additional information,
+not some 'changing of the meaning of
+an existing field'.
+Currently there is no CIE data in the augmentation for things
+beginning with 'z'.
+.P
+If the augmentation string is "mti v1" or "" then it is followed
+immediately by a unsigned_leb_128 number giving the code alignment factor.
+Next is a signed_leb_128 number giving the data alignment factor.
+Next is a unsigned byte giving the number of the return address register.
+.P
+If the augmentation string is something else, then the
+code alignment factor is assumed to be 4 and the data alignment
+factor is assumed to be -1 and the return
+address register is assumed to be 31. Arbitrarily.
+The library (libdwarf) assumes it does not understand the rest of the CIE.
+.P
+.H 3 "FDE processing based on augmentation"
+If the CIE augmentation string
+for an fde begins with 'z'
+then the next FDE field after the address_range field
+is an
+unsigned_leb_128 number giving the length of the 'augmentation'
+fields, and those fields follow immediately.
+
+.H 4 "FDE augmentation fields"
+.P
+If the CIE augmentation string is "mti v1" or ""
+then the FDE is exactly as described in the Dwarf Document section 6.4.1.
+.P
+Else, if the CIE augmentation string begins with "z"
+then the next field after the FDE augmentation length field
+is a Dwarf_Sword size offset into
+exception tables.
+If the CIE augmentation string does not begin with "z"
+(and is neither "mti v1" nor "")
+the FDE augmentation fields are skipped (not understood).
+Note that libdwarf actually (as of MIPSpro7.3 and earlier)
+only tests that the initial character of the augmentation
+string is 'z', and ignores the rest of the string, if any.
+So in reality the test is for a _prefix_ of 'z'.
+.P
+If the CIE augmentation string neither starts with 'z' nor is ""
+nor is "mti v1" then libdwarf (incorrectly) assumes that the
+table defining instructions start next.
+Processing (in libdwarf) will be incorrect.
+.H 2 "Stack Pointer recovery from debug_frame"
+There is no identifiable means in
+DWARF2 to say that the stack register is
+recovered by any particular operation.
+A 'register rule' works if the caller's
+stack pointer was copied to another
+register.
+An 'offset(N)' rule works if the caller's
+stack pointer was stored on the stack.
+However if the stack pointer is
+some register value plus/minus some offset,
+there is no means to say this in an FDE.
+For MIPS/IRIX, the recovered stack pointer
+of the next frame up the stack (towards main())
+is simply the CFA value of the current
+frame, and the CFA value is
+precisely a register (value of a register)
+or a register plus offset (value of a register
+plus offset). This is a software convention.
+.H 1 "egcs dwarf extensions (egcs-1.1.2 extensions)"
+This and following egcs sections describe
+the extensions currently shown in egcs dwarf2.
+Note that egcs has chosen to adopt tag and
+attribute naming as if their choices were
+standard dwarf, not as if they were extensions.
+However, they are properly numbered as extensions.
+
+.H 2 "DW_TAG_format_label 0x4101"
+For FORTRAN 77, Fortran 90.
+Details of use not defined in egcs source, so
+unclear if used.
+.H 2 "DW_TAG_function_template 0x4102"
+For C++.
+Details of use not defined in egcs source, so
+unclear if used.
+.H 2 "DW_TAG_class_template 0x4103"
+For C++.
+Details of use not defined in egcs source, so
+unclear if used.
+.H 2 "DW_AT_sf_names 0x2101"
+Apparently only output in DWARF1, not DWARF2.
+.H 2 "DW_AT_src_info 0x2102"
+Apparently only output in DWARF1, not DWARF2.
+.H 2 "DW_AT_mac_info 0x2103"
+Apparently only output in DWARF1, not DWARF2.
+.H 2 "DW_AT_src_coords 0x2104"
+Apparently only output in DWARF1, not DWARF2.
+.H 2 "DW_AT_body_begin 0x2105"
+Apparently only output in DWARF1, not DWARF2.
+.H 2 "DW_AT_body_end 0x2106"
+Apparently only output in DWARF1, not DWARF2.
+
+.H 1 "egcs .eh_frame (non-sgi) (egcs-1.1.2 extensions)"
+egcs-1.1.2 (and earlier egcs)
+emits by default a section named .eh_frame
+for ia32 (and possibly other platforms) which
+is nearly identical to .debug_frame in format and content.
+This section is used for helping handle C++ exceptions.
+.P
+Because after linking there are sometimes zero-ed out bytes
+at the end of the eh_frame section, the reader code in
+dwarf_frame.c considers a zero cie/fde length as an indication
+that it is the end of the section.
+.P
+.H 2 "CIE_id 0"
+The section is an ALLOCATED section in an executable, and
+is therefore mapped into memory at run time.
+The CIE_pointer (aka CIE_id, section 6.4.1
+of the DWARF2 document) is the field that
+distinguishes a CIE from an FDE.
+The designers of the egcs .eh_frame section
+decided to make the CIE_id
+be 0 as the CIE_pointer definition is
+.in +2
+the number of bytes from the CIE-pointer in the FDE back to the
+applicable CIE.
+.in -2
+In a dwarf .debug_frame section, the CIE_pointer is the
+offset in .debug_frame of the CIE for this fde, and
+since an offset can be zero of some CIE, the CIE_id
+cannot be 0, but must be all 1 bits .
+Note that the dwarf2.0 spec does specify the value of CIE_id
+as 0xffffffff
+(see section 7.23 of v2.0.0),
+though earlier versions of this extensions document
+incorrectly said it was not specified in the dwarf
+document.
+.H 2 "augmentation eh"
+The augmentation string in each CIE is "eh"
+which, with its following NUL character, aligns
+the following word to a 32bit boundary.
+Following the augmentation string is a 32bit
+word with the address of the __EXCEPTION_TABLE__,
+part of the exception handling data for egcs.
+.H 2 "DW_CFA_GNU_window_save 0x2d"
+This is effectively a flag for architectures with
+register windows, and tells the unwinder code that
+it must look to a previous frame for the
+correct register window set.
+As of this writing, egcs gcc/frame.c
+indicates this is for SPARC register windows.
+.H 2 "DW_CFA_GNU_args_size 0x2e"
+DW_CFA_GNU_args_size has a single uleb128 argument
+which is the size, in bytes, of the function's stack
+at that point in the function.
+.H 2 "__EXCEPTION_TABLE__"
+A series of 3 32bit word entries by default:
+0 word: low pc address
+1 word: high pc address
+2 word: pointer to exception handler code
+The end of the table is
+signaled by 2 words of -1 (not 3 words!).
+.H 1 "Interpretations of the DWARF V2 spec"
+.H 2 "template TAG spellings"
+The DWARF V2 spec spells two attributes in two ways.
+DW_TAG_template_type_param
+(listed in Figure 1, page 7)
+is spelled DW_TAG_template_type_parameter
+in the body of the document (section 3.3.7, page 28).
+We have adopted the spelling
+DW_TAG_template_type_param.
+.P
+DW_TAG_template_value_param
+(listed in Figure 1, page 7)
+is spelled DW_TAG_template_value_parameter
+in the body of the document (section 3.3.7, page 28).
+We have adopted the spelling
+DW_TAG_template_value_parameter.
+.P
+We recognize that the choices adopted are neither consistently
+the longer nor the shorter name.
+This inconsistency was an accident.
+.H 2 DW_FORM_ref_addr confusing
+Section 7.5.4, Attribute Encodings, describes
+DW_FORM_ref_addr.
+The description says the reference is the size of an address
+on the target architecture.
+This is surely a mistake, because on a 16bit-pointer-architecture
+it would mean that the reference could not exceed
+16 bits, which makes only
+a limited amount of sense as the reference is from one
+part of the dwarf to another, and could (in theory)
+be *on the disk* and not limited to what fits in memory.
+Since MIPS is 32 bit pointers (at the smallest)
+the restriction is not a problem for MIPS/SGI.
+The 32bit pointer ABIs are limited to 32 bit section sizes
+anyway (as a result of implementation details).
+And the 64bit pointer ABIs currently have the same limit
+as a result of how the compilers and tools are built
+(this has not proven to be a limit in practice, so far).
+.P
+This has been clarified in the DWARF3 spec and the IRIX use
+of DW_FORM_ref_addr being an offset is correct.
+.H 2 "Section .debug_macinfo in a debugger"
+It seems quite difficult, in general, to
+tie specific text(code) addresses to points in the
+stream of macro information for a particular compilation unit.
+So it's been difficult to see how to design a consumer
+interface to libdwarf for macro information.
+.P
+The best (simple to implement, easy for a debugger user to
+understand) candidate seems to be that
+the debugger asks for macros of a given name in a compilation
+unit, and the debugger responds with *all* the macros of that name.
+.H 3 "only a single choice exists"
+If there is exactly one, that is usable in expressions, if the
+debugger is able to evaluate such.
+.H 3 "multiple macros with same name".
+If there are multiple macros with the same name
+in a compilation unit,
+the debugger (and the debugger user and the application
+programmer) have
+a problem: confusion is quite possible.
+If the macros are simple the
+debugger user can simply substitute by hand in an expression.
+If the macros are complicated hand substitution will be
+impractical, and the debugger will have to identify the
+choices and let the debugger user choose an interpretation.
+.H 2 "Section 6.1.2 Lookup by address problem"
+Each entry is a beginning-address followed by a length.
+And the distinguished entry 0,0 is used to denote
+the end of a range of entries.
+.P
+This means that one must be careful not to emit a zero length,
+as in a .o (object file) the beginning address of
+a normal entry might be 0 (it is a section offset after all),
+and the resulting 0,0 would be taken as end-of-range, not
+as a valid entry.
+A dwarf dumper would have trouble with such data
+in an object file.
+.P
+In an a.out or shared object (dynamic shared object, DSO)
+no text will be at address zero so in such this problem does
+not arise.
+.H 2 "Section 5.10 Subrange Type Entries problem"
+It is specified that DW_AT_upper_bound (and lower bound)
+must be signed entries if there is no object type
+info to specify the bound type (Sec 5.10, end of section).
+One cannot tell (with some
+dwarf constant types) what the signedness is from the
+form itself (like DW_FORM_data1), so it is necessary
+to determine the object and type according to the rules
+in 5.10 and then if all that fails, the type is signed.
+It's a bit complicated and earlier versions of mips_extensions
+incorrectly said signedness was not defined.
+.H 2 "Section 5.5.6 Class Template Instantiations problem"
+Lots of room for implementor to canonicalize
+template declarations. Ie various folks won't agree.
+This is not serious since a given compiler
+will be consistent with itself and debuggers
+will have to cope!
+.H 2 "Section 2.4.3.4 # 11. operator spelling"
+DW_OP_add should be DW_OP_plus (page 14)
+(this mistake just one place on the page).
+.H 2 "No clear specification of C++ static funcs"
+There is no clear way to tell if a C++ member function
+is a static member or a non-static member function.
+(dwarf2read.c in gdb 4.18, for example, has this observation)
+.H 2 "Misspelling of DW_AT_const_value"
+Twice in appendix 1, DW_AT_const_value is misspelled
+as DW_AT_constant_value.
+.H 2 "Mistake in Atribute Encodings"
+Section 7.5.4, "Attribute Encodings"
+has a brief discussion of "constant"
+which says there are 6 forms of constants.
+It is incorrect in that it fails to mention (or count)
+the block forms, which are clearly allowed by
+section 4.1 "Data Object Entries" (see entry number 9 in
+the numbered list, on constants).
+.H 2 "DW_OP_bregx"
+The description of DW_OP_bregx in 2.4.3.2 (Register Based
+Addressing) is slightly misleading, in that it
+lists the offset first.
+As section 7.7.1 (Location Expression)
+makes clear, in the encoding the register number
+comes first.
+.H 1 "MIPS attributes"
+.H 2 "DW_AT_MIPS_fde"
+This extension to Dwarf appears only on subprogram TAGs and has as
+its value the offset, in the .debug_frame section, of the fde which
+describes the frame of this function. It is an optimization of
+sorts to have this present.
+
+.H 2 "DW_CFA_MIPS_advance_loc8 0x1d"
+This obvious extension to dwarf line tables enables encoding of 8 byte
+advance_loc values (for cases when such must be relocatable,
+and thus must be full length). Applicable only to 64-bit objects.
+
+.H 2 "DW_TAG_MIPS_loop 0x4081"
+For future use. Not currently emitted.
+Places to be emitted and attributes that this might own
+not finalized.
+
+.H 2 "DW_AT_MIPS_loop_begin 0x2002"
+For future use. Not currently emitted.
+Attribute form and content not finalized.
+
+.H 2 "DW_AT_MIPS_tail_loop_begin 0x2003"
+For future use. Not currently emitted.
+Attribute form and content not finalized.
+
+.H 2 "DW_AT_MIPS_epilog_begin 0x2004"
+For future use. Not currently emitted.
+Attribute form and content not finalized.
+
+.H 2 "DW_AT_MIPS_loop_unroll_factor 0x2005"
+For future use. Not currently emitted.
+Attribute form and content not finalized.
+
+.H 2 "DW_AT_MIPS_software_pipeline_depth 0x2006"
+For future use. Not currently emitted.
+Attribute form and content not finalized.
+.H 2 "DW_AT_MIPS_linkage_name 0x2007"
+The rules for mangling C++ names are not part of the
+C++ standard and are different for different versions
+of C++. With this extension, the compiler emits
+both the DW_AT_name for things with mangled names
+(recall that DW_AT_name is NOT the mangled form)
+and also emits DW_AT_MIPS_linkage_name whose value
+is the mangled name.
+.P
+This makes looking for the mangled name in other linker
+information straightforward.
+It also is passed (by the debugger) to the
+libmangle routines to generate names to present to the
+debugger user.
+.H 2 "DW_AT_MIPS_stride 0x2008"
+F90 allows assumed shape arguments and pointers to describe
+non-contiguous memory. A (runtime) descriptor contains address,
+bounds and stride information - rank and element size is known
+during compilation. The extent in each dimension is given by the
+bounds in a DW_TAG_subrange_type, but the stride cannot be
+represented in conventional dwarf. DW_AT_MIPS_stride was added as
+an attribute of a DW_TAG_subrange_type to describe the
+location of the stride.
+Used in the MIPSpro 7.2 (7.2.1 etc) compilers.
+.P
+If the stride is constant (ie: can be inferred from the type in the
+usual manner) DW_AT_MIPS_stride is absent.
+.P
+If DW_AT_MIPS_stride is present, the attribute contains a reference
+to a DIE which describes the location holding the stride, and the
+DW_AT_stride_size field of DW_TAG_array_type is ignored if
+present. The value of the stride is the number of
+4 byte words between
+elements along that axis.
+.P
+This applies to
+.nf
+a) Intrinsic types whose size is greater
+ or equal to 4bytes ie: real*4,integer*8
+ complex etc, but not character types.
+
+b) Derived types (ie: structs) of any size,
+ unless all components are of type character.
+.fi
+
+.H 2 "DW_AT_MIPS_abstract_name 0x2009"
+This attribute only appears in a DA_TAG_inlined_subroutine DIE.
+The value of this attribute is a string.
+When IPA inlines a routine and the abstract origin is
+in another compilation unit, there is a problem with putting
+in a reference, since the ordering and timing of the
+creation of references is unpredicatable with reference to
+the DIE and compilation unit the reference refers to.
+.P
+Since there may be NO ordering of the compilation units that
+allows a correct reference to be done without some kind of patching,
+and since even getting the information from one place to another
+is a problem, the compiler simply passes the problem on to the debugger.
+.P
+The debugger must match the DW_AT_MIPS_abstract_name
+in the concrete
+inlined instance DIE
+with the DW_AT_MIPS_abstract_name
+in the abstract inlined subroutine DIE.
+.P
+A dwarf-consumer-centric view of this and other inline
+issues could be expressed as follows:
+.nf
+If DW_TAG_subprogram
+ If has DW_AT_inline is abstract instance root
+ If has DW_AT_abstract_origin, is out-of-line instance
+ of function (need abstract origin for some data)
+ (abstract root in same CU (conceptually anywhere
+ a ref can reach, but reaching outside of CU is
+ a problem for ipa: see DW_AT_MIPS_abstract_name))
+ If has DW_AT_MIPS_abstract_name is abstract instance
+ root( must have DW_AT_inline) and this name is used to
+ match with the abstract root
+
+If DW_TAG_inline_subroutine
+ Is concrete inlined subprogram instance.
+ If has DW_AT_abstract_origin, it is a CU-local inline.
+ If it has DW_AT_MIPS_abstract_name it is an
+ inline whose abstract root is in another file (CU).
+.fi
+
+.H 2 "DW_AT_MIPS_clone_origin 0x200a"
+This attribute appears only in a cloned subroutine.
+The procedure is cloned from the same compilation unit.
+The value of this attribute is a reference to
+the original routine in this compilation unit.
+.P
+The 'original' routine means the routine which has all the
+original code. The cloned routines will always have
+been 'specialized' by IPA.
+A routine with DW_AT_MIPS_clone_origin
+will also have the DW_CC_nocall value of the DW_AT_calling_convention
+attribute.
+
+.H 2 "DW_AT_MIPS_has_inlines 0x200b"
+This attribute may appear in a DW_TAG_subprogram DIE.
+If present and it has the value True, then the subprogram
+has inlined functions somewhere in the body.
+.P
+By default, at startup, the debugger may not look for
+inlined functions in scopes inside the outer function.
+.P
+This is a hint to the debugger to look for the inlined functions
+so the debugger can set breakpoints on these in case the user
+requests 'stop in foo' and foo is inlined.
+.H 2 "DW_AT_MIPS_stride_byte 0x200c"
+Created for f90 pointer and assumed shape
+arrays.
+Used in the MIPSpro 7.2 (7.2.1 etc) compilers.
+A variant of DW_AT_MIPS_stride.
+This stride is interpreted as a byte count.
+Used for integer*1 and character arrays
+and arrays of derived type
+whose components are all character.
+.H 2 "DW_AT_MIPS_stride_elem 0x200d"
+Created for f90 pointer and assumed shape
+arrays.
+Used in the MIPSpro 7.2 (7.2.1 etc) compilers.
+A variant of DW_AT_MIPS_stride.
+This stride is interpreted as a byte-pair (2 byte) count.
+Used for integer*2 arrays.
+.H 2 "DW_AT_MIPS_ptr_dopetype 0x200e"
+See following.
+.H 2 "DW_AT_MIPS_allocatable_dopetype 0x200f"
+See following.
+.H 2 "DW_AT_MIPS_assumed_shape_dopetype 0x2010"
+DW_AT_MIPS_assumed_shape_dopetype, DW_AT_MIPS_allocatable_dopetype,
+and DW_AT_MIPS_ptr_dopetype have an attribute value
+which is a reference to a Fortran 90 Dope Vector.
+These attributes are introduced in MIPSpro7.3.
+They only apply to f90 arrays (where they are
+needed to describe arrays never properly described
+before in debug information).
+C, C++, f77, and most f90 arrays continue to be described
+in standard dwarf.
+.P
+The distinction between these three attributes is the f90 syntax
+distinction: keywords 'pointer' and 'allocatable' with the absence
+of these keywords on an assumed shape array being the third case.
+.P
+A "Dope Vector" is a struct (C struct) which describes
+a dynamically-allocatable array.
+In objects with full debugging the C struct will be
+in the dwarf information (of the f90 object, represented like C).
+A debugger will use the link to find the main struct DopeVector
+and will use that information to decode the dope vector.
+At the outer allocatable/assumed-shape/pointer
+the DW_AT_location points at the dope vector (so debugger
+calculations use that as a base).
+.H 2 "Overview of debugger use of dope vectors"
+Fundamentally, we build two distinct
+representations of the arrays and pointers.
+One, in dwarf, represents the statically-representable
+information (the types and
+variable/type-names, without type size information).
+The other, using dope vectors in memory, represents
+the run-time data of sizes.
+A debugger must process the two representations
+in parallel (and merge them) to deal with user expressions in
+a debugger.
+.H 2 "Example f90 code for use in explanation"
+[Note
+We want dwarf output with *exactly*
+this little (arbitrary) example.
+Not yet available.
+end Note]
+Consider the following code.
+.nf
+ type array_ptr
+ real :: myvar
+ real, dimension (:), pointer :: ap
+ end type array_ptr
+
+ type (array_ptr), allocatable, dimension (:) :: arrays
+
+ allocate (arrays(20))
+ do i = 1,20
+ allocate (arrays(i)%ap(i))
+ end do
+.fi
+arrays is an allocatable array (1 dimension) whose size is
+not known at compile time (it has
+a Dope Vector). At run time, the
+allocate statement creats 20 array_ptr dope vectors
+and marks the base arrays dopevector as allocated.
+The myvar variable is just there to add complexity to
+the example :-)
+.nf
+In the loop, arrays(1)%ap(1)
+ is allocated as a single element array of reals.
+In the loop, arrays(2)%ap(2)
+ is allocated as an array of two reals.
+...
+In the loop, arrays(20)%ap(20)
+ is allocated as an array of twenty reals.
+.fi
+.H 2 "the problem with standard dwarf and this example"
+.sp
+In dwarf, there is no way to find the array bounds of arrays(3)%ap,
+for example, (which are 1:3 in f90 syntax)
+since any location expression in an ap array lower bound
+attribute cannot involve the 3 (the 3 is known at debug time and
+does not appear in the running binary, so no way for the
+location expression to get to it).
+And of course the 3 must actually index across the array of
+dope vectors in 'arrays' in our implementation, but that is less of
+a problem than the problem with the '3'.
+.sp
+Plus dwarf has no way to find the 'allocated' flag in the
+dope vector (so the debugger can know when the allocate is done
+for a particular arrays(j)%ap).
+.sp
+Consequently, the calculation of array bounds and indices
+for these dynamically created f90 arrays
+is now pushed of into the debugger, which must know the
+field names and usages of the dope vector C structure and
+use the field offsets etc to find data arrays.
+C, C++, f77, and most f90 arrays continue to be described
+in standard dwarf.
+At the outer allocatable/assumed-shape/pointer
+the DW_AT_location points at the dope vector (so debugger
+calculations use that as a base).
+.P
+It would have been nice to design a dwarf extension
+to handle the above problems, but
+the methods considered to date were not
+any more consistent with standard dwarf than
+this dope vector centric approach: essentially just
+as much work in the debugger appeared necessary either way.
+A better (more dwarf-ish)
+design would be welcome information.
+
+.H 2 "A simplified sketch of the dwarf information"
+[Note:
+Needs to be written.
+end Note]
+
+.H 2 "A simplified sketch of the dope vector information"
+[Note:
+This one is simplified.
+Details left out that should be here. Amplify.
+end Note]
+This is an overly simplified version of a dope vector,
+presented as an initial hint.
+Full details presented later.
+.nf
+struct simplified{
+ void *base; // pointer to the data this describes
+ long el_len;
+ int assoc:1
+ int ptr_alloc:1
+ int num_dims:3;
+ struct dims_s {
+ long lb;
+ long ext;
+ long str_m;
+ } dims[7];
+};
+.fi
+Only 'num_dims' elements of dims[] are actually used.
+
+.H 2 "The dwarf information"
+
+Here is dwarf information from the compiler for
+the example above, as printed by dwarfdump(1)
+.nf
+[Note:
+The following may not be the test.
+Having field names with '.' in the name is
+not such a good idea, as it conflicts with the
+use of '.' in dbx extended naming.
+Something else, like _$, would be much easier
+to work with in dbx (customers won't care about this,
+for the most part,
+but folks working on dbx will, and in those
+rare circumstances when a customer cares,
+the '.' will be a real problem in dbx.).
+Note that to print something about .base., in dbx one
+would have to do
+ whatis `.base.`
+where that is the grave accent, or back-quote I am using.
+With extended naming one do
+ whatis `.dope.`.`.base.`
+which is hard to type and hard to read.
+end Note]
+
+<2>< 388> DW_TAG_array_type
+ DW_AT_name .base.
+ DW_AT_type <815>
+ DW_AT_declaration yes(1)
+<3>< 401> DW_TAG_subrange_type
+ DW_AT_lower_bound 0
+ DW_AT_upper_bound 0
+<2>< 405> DW_TAG_pointer_type
+ DW_AT_type <388>
+ DW_AT_byte_size 4
+ DW_AT_address_class 0
+<2>< 412> DW_TAG_structure_type
+ DW_AT_name .flds.
+ DW_AT_byte_size 28
+<3>< 421> DW_TAG_member
+ DW_AT_name el_len
+ DW_AT_type <815>
+ DW_AT_data_member_location DW_OP_consts 0
+<3>< 436> DW_TAG_member
+ DW_AT_name assoc
+ DW_AT_type <841>
+ DW_AT_byte_size 0
+ DW_AT_bit_offset 0
+ DW_AT_bit_size 1
+ DW_AT_data_member_location DW_OP_consts 4
+<3>< 453> DW_TAG_member
+ DW_AT_name ptr_alloc
+ DW_AT_type <841>
+ DW_AT_byte_size 0
+ DW_AT_bit_offset 1
+ DW_AT_bit_size 1
+ DW_AT_data_member_location DW_OP_consts 4
+<3>< 474> DW_TAG_member
+ DW_AT_name p_or_a
+ DW_AT_type <841>
+ DW_AT_byte_size 0
+ DW_AT_bit_offset 2
+ DW_AT_bit_size 2
+ DW_AT_data_member_location DW_OP_consts 4
+<3>< 492> DW_TAG_member
+ DW_AT_name a_contig
+ DW_AT_type <841>
+ DW_AT_byte_size 0
+ DW_AT_bit_offset 4
+ DW_AT_bit_size 1
+ DW_AT_data_member_location DW_OP_consts 4
+<3>< 532> DW_TAG_member
+ DW_AT_name num_dims
+ DW_AT_type <841>
+ DW_AT_byte_size 0
+ DW_AT_bit_offset 29
+ DW_AT_bit_size 3
+ DW_AT_data_member_location DW_OP_consts 8
+<3>< 572> DW_TAG_member
+ DW_AT_name type_code
+ DW_AT_type <841>
+ DW_AT_byte_size 0
+ DW_AT_bit_offset 0
+ DW_AT_bit_size 32
+ DW_AT_data_member_location DW_OP_consts 16
+<3>< 593> DW_TAG_member
+ DW_AT_name orig_base
+ DW_AT_type <841>
+ DW_AT_data_member_location DW_OP_consts 20
+<3>< 611> DW_TAG_member
+ DW_AT_name orig_size
+ DW_AT_type <815>
+ DW_AT_data_member_location DW_OP_consts 24
+<2>< 630> DW_TAG_structure_type
+ DW_AT_name .dope_bnd.
+ DW_AT_byte_size 12
+<3>< 643> DW_TAG_member
+ DW_AT_name lb
+ DW_AT_type <815>
+ DW_AT_data_member_location DW_OP_consts 0
+<3>< 654> DW_TAG_member
+ DW_AT_name ext
+ DW_AT_type <815>
+ DW_AT_data_member_location DW_OP_consts 4
+<3>< 666> DW_TAG_member
+ DW_AT_name str_m
+ DW_AT_type <815>
+ DW_AT_data_member_location DW_OP_consts 8
+<2>< 681> DW_TAG_array_type
+ DW_AT_name .dims.
+ DW_AT_type <630>
+ DW_AT_declaration yes(1)
+<3>< 694> DW_TAG_subrange_type
+ DW_AT_lower_bound 0
+ DW_AT_upper_bound 0
+<2>< 698> DW_TAG_structure_type
+ DW_AT_name .dope.
+ DW_AT_byte_size 44
+<3>< 707> DW_TAG_member
+ DW_AT_name base
+ DW_AT_type <405>
+ DW_AT_data_member_location DW_OP_consts 0
+<3>< 720> DW_TAG_member
+ DW_AT_name .flds
+ DW_AT_type <412>
+ DW_AT_data_member_location DW_OP_consts 4
+<3>< 734> DW_TAG_member
+ DW_AT_name .dims.
+ DW_AT_type <681>
+ DW_AT_data_member_location DW_OP_consts 32
+<2>< 750> DW_TAG_variable
+ DW_AT_type <815>
+ DW_AT_location DW_OP_fbreg -32
+ DW_AT_artificial yes(1)
+<2>< 759> DW_TAG_variable
+ DW_AT_type <815>
+ DW_AT_location DW_OP_fbreg -28
+ DW_AT_artificial yes(1)
+<2>< 768> DW_TAG_variable
+ DW_AT_type <815>
+ DW_AT_location DW_OP_fbreg -24
+ DW_AT_artificial yes(1)
+<2>< 777> DW_TAG_array_type
+ DW_AT_type <815>
+ DW_AT_declaration yes(1)
+<3>< 783> DW_TAG_subrange_type
+ DW_AT_lower_bound <750>
+ DW_AT_count <759>
+ DW_AT_MIPS_stride <768>
+<2>< 797> DW_TAG_variable
+ DW_AT_decl_file 1
+ DW_AT_decl_line 1
+ DW_AT_name ARRAY
+ DW_AT_type <698>
+ DW_AT_location DW_OP_fbreg -64 DW_OP_deref
+<1>< 815> DW_TAG_base_type
+ DW_AT_name INTEGER_4
+ DW_AT_encoding DW_ATE_signed
+ DW_AT_byte_size 4
+<1>< 828> DW_TAG_base_type
+ DW_AT_name INTEGER_8
+ DW_AT_encoding DW_ATE_signed
+ DW_AT_byte_size 8
+<1>< 841> DW_TAG_base_type
+ DW_AT_name INTEGER*4
+ DW_AT_encoding DW_ATE_unsigned
+ DW_AT_byte_size 4
+<1>< 854> DW_TAG_base_type
+ DW_AT_name INTEGER*8
+ DW_AT_encoding DW_ATE_unsigned
+ DW_AT_byte_size 8
+
+.fi
+.H 2 "The dope vector structure details"
+A dope vector is the following C struct, "dopevec.h".
+Not all the fields are of use to a debugger.
+It may be that not all fields will show up
+in the f90 dwarf (since not all are of interest to debuggers).
+.nf
+[Note:
+Need details on the use of each field.
+And need to know which are really 32 bits and which
+are 32 or 64.
+end Note]
+The following
+struct
+is a representation of all the dope vector fields.
+It suppresses irrelevant detail and may not
+exactly match the layout in memory (a debugger must
+examine the dwarf to find the fields, not
+compile this structure into the debugger!).
+.nf
+struct .dope. {
+ void *base; // pointer to data
+ struct .flds. {
+ long el_len; // length of element in bytes?
+ unsigned int assoc:1; //means?
+ unsigned int ptr_alloc:1; //means?
+ unsigned int p_or_a:2; //means?
+ unsigned int a_contig:1; // means?
+ unsigned int num_dims: 3; // 0 thru 7
+ unsigned int type_code:32; //values?
+ unsigned int orig_base; //void *? means?
+ long orig_size; // means?
+ } .flds;
+
+ struct .dope_bnd. {
+ long lb ; // lower bound
+ long ext ; // means?
+ long str_m; // means?
+ } .dims[7];
+}
+.fi
+
+.H 2 "DW_AT_MIPS_assumed_size 0x2011"
+This flag was invented to deal with f90 arrays.
+For example:
+
+.nf
+ pointer (rptr, axx(1))
+ pointer (iptr, ita(*))
+ rptr = malloc (100*8)
+ iptr = malloc (100*4)
+.fi
+
+This flag attribute has the value 'yes' (true, on) if and only if
+the size is unbounded, as iptr is.
+Both may show an explicit upper bound of 1 in the dwarf,
+but this flag notifies the debugger that there is explicitly
+no user-provided size.
+
+So if a user asks for a printout of the rptr allocated
+array, the default will be of a single entry (as
+there is a user slice bound in the source).
+In contrast, there is no explicit upper bound on the iptr
+(ita) array so the default slice will use the current bound
+(a value calculated from the malloc size, see the dope vector).
+
+Given explicit requests, more of rptr(axx) can me shown
+than the default.
+
+.H 1 "Line information and Source Position"
+DWARF does not define the meaning of the term 'source statement'.
+Nor does it define any way to find the first user-written
+executable code in a function.
+.P
+It does define that a source statement has a file name,
+a line number, and a column position (see Sec 6.2, Line Number
+Information of the Dwarf Version 2 document).
+We will call those 3 source coordinates a 'source position'
+in this document. We'll try not to accidentally call the
+source position a 'line number' since that is ambiguous
+as to what it means.
+
+.H 2 "Definition of Statement"
+.P
+A function prolog is a statement.
+.P
+A C, C++, Pascal, or Fortran statement is a statement.
+.P
+Each initialized local variable in C,C++ is a statement
+in that its initialization generates a source position.
+This means that
+ x =3, y=4;
+is two statements.
+.P
+For C, C++:
+The 3 parts a,b,c in for(a;b;c) {d;} are individual statements.
+The condition portion of a while() and do {} while() is
+a statement. (of course d; can be any number of statements)
+.P
+For Fortran, the controlling expression of a DO loop is a statement.
+Is a 'continue' statement in Fortran a DWARF statement?
+.P
+Each function return, whether user coded or generated by the
+compiler, is a statement. This is so one can step over (in
+a debugger) the final user-coded statement
+(exclusive of the return statement if any) in a function
+wile not leaving the function scope.
+.P
+
+.H 2 "Finding The First User Code in a Function"
+
+.nf
+Consider:
+int func(int a)
+{ /* source position 1 */
+ float b = a; /* source position 2 */
+ int x;
+ x = b + 2; /* source position 3 */
+} /* source position 4 */
+.fi
+.P
+The DIE for a function gives the address range of the function,
+including function prolog(s) and epilog(s)
+.P
+Since there is no scope block for the outer user scope of a
+function (and thus no beginning address range for the outer
+user scope: the DWARF committee explicitly rejected the idea
+of having a user scope block)
+it is necessary to use the source position information to find
+the first user-executable statement.
+.P
+This means that the user code for a function must be presumed
+to begin at the code location of the second source position in
+the function address range.
+.P
+If a function has exactly one source position, the function
+presumably consists solely of a return.
+.P
+If a function has exactly two source positions, the function
+may consist of a function prolog and a return or a single user
+statement and a return (there may be no prolog code needed in a
+leaf function). In this case, there is no way to be sure which
+is the first source position of user code, so the rule is to
+presume that the first address is user code.
+.P
+If a function consists of 3 or more source positions, one
+should assume that the first source position is function prolog and
+the second is the first user executable code.
+
+.H 2 "Using debug_frame Information to find first user statement"
+In addition to the line information, the debug_frame information
+can be
+useful in determining the first user source line.
+.P
+Given that a function has more than 1 source position,
+Find the code location of the second source position, then
+examine the debug_frame information to determine if the Canonical
+Frame Address (cfa) is updated before the second source position
+code location.
+If the cfa is updated, then one can be pretty sure that the
+code for the first source position is function prolog code.
+.P
+Similarly, if the cfa is restored in the code for
+a source position, the source position is likely to
+represent a function exit block.
+
+.H 2 "Debugger Use Of Source Position"
+Command line debuggers, such as dbx and gdb, will ordinarily
+want to consider multiple statements on one line to be a single
+statement: doing otherwise is distressing to users since it
+causes a 'step' command to appear to have no effect.
+.P
+An exception for command line debuggers is in determining the
+first user statement: as detailed above, there one wants to
+consider the full source position and will want to consider
+the function return a separate statement. It is difficult to
+make the function return a separate statement 'step' reliably
+however if a function is coded all on one line or if the last
+line of user code before the return is on the same line as the
+return.
+.P
+A graphical debugger has none of these problems if it simply
+highlights the portion of the line being executed. In that
+case, stepping will appear natural even stepping within a
+line.
+.H 1 "Known Bugs"
+Up through at least MIPSpro7.2.1
+the compiler has been emitting form DW_FORM_DATA1,2, or 4
+for DW_AT_const_value in DW_TAG_enumerator.
+And dwarfdump and debuggers have read this with dwarf_formudata()
+or form_sdata() and gotten some values incorrect.
+For example, a value of 128 was printed by debuggers as a negative value.
+Since dwarfdump and the compilers were not written to use the
+value the same way, their output differed.
+For negative enumerator values the compiler has been emitting 32bit values
+in a DW_FORM_DATA4.
+The compiler should probably be emitting a DW_FORM_sdata for
+enumerator values.
+And consumers of enumerator values should then call form_sdata().
+However, right now, debuggers should call form_udata() and only if
+it fails, call form_sdata().
+Anything else will break backward compatibility with
+the objects produced earlier.
+.SK
+.S
+.TC 1 1 4
+.CS
diff --git a/libdwarf/mips_extensions.pdf b/libdwarf/mips_extensions.pdf
new file mode 100644
index 0000000..4bab49e
--- /dev/null
+++ b/libdwarf/mips_extensions.pdf
Binary files differ
diff --git a/libdwarf/pro_alloc.c b/libdwarf/pro_alloc.c
new file mode 100644
index 0000000..840aad8
--- /dev/null
+++ b/libdwarf/pro_alloc.c
@@ -0,0 +1,188 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "pro_incl.h"
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif /* HAVE_STDLIB_H */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#include <malloc.h>
+
+/* When each block is allocated, there is a two-word structure
+ allocated at the beginning so the block can go on a list.
+ The address returned is the address *after* the two pointers
+ at the start. But this allows us to be given a pointer to
+ a generic block, and go backwards to find the list-node. Then
+ we can remove this block from it's list without the need to search
+ through a linked list in order to remove the node. It also allows
+ us to 'delete' a memory block without needing the dbg structure.
+ We still need the dbg structure on allocation so that we know which
+ linked list to add the block to.
+
+ Only the allocation of the dbg structure itself cannot use
+ _dwarf_p_get_alloc.
+ That structure should be set up by hand, and the two list pointers
+ should be initialized to point at the node itself. That initializes
+ the doubly linked list. */
+
+#define LIST_TO_BLOCK(lst) ((void*) (((char *)lst) + sizeof(memory_list_t)))
+#define BLOCK_TO_LIST(blk) ((memory_list_t*) (((char*)blk) - sizeof(memory_list_t)))
+
+
+/*
+ dbg should be NULL only when allocating dbg itself. In that
+ case we initialize it to an empty circular doubly-linked list.
+*/
+
+Dwarf_Ptr
+_dwarf_p_get_alloc(Dwarf_P_Debug dbg, Dwarf_Unsigned size)
+{
+ void *sp;
+ memory_list_t *lp = NULL;
+ memory_list_t *dbglp = NULL;
+ memory_list_t *nextblock = NULL;
+
+ /* alloc control struct and data block together for performance reasons */
+ lp = (memory_list_t *) malloc(size + sizeof(memory_list_t));
+ if (lp == NULL) {
+ /* should throw an error */
+ return NULL;
+ }
+
+ /* point to 'size' bytes just beyond lp struct */
+ sp = LIST_TO_BLOCK(lp);
+ memset(sp, 0, size);
+
+ if (dbg == NULL) {
+ lp->next = lp->prev = lp;
+ } else {
+ /* I always have to draw a picture to understand this part. */
+
+ dbglp = BLOCK_TO_LIST(dbg);
+ nextblock = dbglp->next;
+
+ /* Insert between dbglp and nextblock */
+ dbglp->next = lp;
+ lp->prev = dbglp;
+ lp->next = nextblock;
+ nextblock->prev = lp;
+ }
+
+ return sp;
+}
+
+/*
+ This routine is only here in case a caller of an older version of the
+ library is calling this for some reason.
+ We will clean up any stray blocks when the session is closed.
+ No need to remove this block. In theory the user might be
+ depending on the fact that we used to just 'free' this.
+ In theory they might also be
+ passing a block that they got from libdwarf. So we don't know if we
+ should try to remove this block from our global list. Safest just to
+ do nothing at this point.
+
+ !!!
+ This function is deprecated! Don't call it inside libdwarf or outside of it.
+ !!!
+*/
+
+void
+dwarf_p_dealloc(Dwarf_Small * ptr)
+{
+ return;
+}
+
+/*
+ The dbg structure is not needed here anymore.
+*/
+
+void
+_dwarf_p_dealloc(Dwarf_P_Debug dbg, Dwarf_Small * ptr) /* ARGSUSED */
+{
+ memory_list_t *lp;
+ lp = BLOCK_TO_LIST(ptr);
+
+ /*
+ Remove from a doubly linked, circular list.
+ Read carefully, use a white board if necessary.
+ If this is an empty list, the following statements are no-ops, and
+ will write to the same memory location they read from.
+ This should only happen when we deallocate the dbg structure itself.
+ */
+
+ lp->prev->next = lp->next;
+ lp->next->prev = lp->prev;
+
+ free((void*)lp);
+}
+
+
+/*
+ This routine deallocates all the nodes on the dbg list,
+ and then deallocates the dbg structure itself.
+*/
+
+void
+_dwarf_p_dealloc_all(Dwarf_P_Debug dbg)
+{
+ memory_list_t *dbglp;
+
+ if (dbg == NULL) {
+ /* should throw an error */
+ return;
+ }
+
+ dbglp = BLOCK_TO_LIST(dbg);
+ while (dbglp->next != dbglp) {
+ _dwarf_p_dealloc(dbg, LIST_TO_BLOCK(dbglp->next));
+ }
+ if (dbglp->next != dbglp ||
+ dbglp->prev != dbglp) {
+
+ /* should throw error */
+ /* For some reason we couldn't free all the blocks? */
+ return;
+ }
+ _dwarf_p_dealloc(NULL, (void*)dbg);
+}
+
diff --git a/libdwarf/pro_alloc.h b/libdwarf/pro_alloc.h
new file mode 100644
index 0000000..b4da653
--- /dev/null
+++ b/libdwarf/pro_alloc.h
@@ -0,0 +1,42 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+Dwarf_Ptr _dwarf_p_get_alloc(Dwarf_P_Debug, Dwarf_Unsigned);
+
+void _dwarf_p_dealloc(Dwarf_P_Debug dbg, Dwarf_Small * ptr);
+
+void _dwarf_p_dealloc_all(Dwarf_P_Debug dbg);
diff --git a/libdwarf/pro_arange.c b/libdwarf/pro_arange.c
new file mode 100644
index 0000000..3270b37
--- /dev/null
+++ b/libdwarf/pro_arange.c
@@ -0,0 +1,321 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_ELFACCESS_H
+#include <elfaccess.h>
+#endif
+#include "pro_incl.h"
+#include "pro_arange.h"
+#include "pro_section.h"
+#include "pro_reloc.h"
+
+
+
+/* This function adds another address range
+ to the list of address ranges for the
+ given Dwarf_P_Debug. It returns 0 on error,
+ and 1 otherwise. */
+Dwarf_Unsigned
+dwarf_add_arange(Dwarf_P_Debug dbg,
+ Dwarf_Addr begin_address,
+ Dwarf_Unsigned length,
+ Dwarf_Signed symbol_index, Dwarf_Error * error)
+{
+ return dwarf_add_arange_b(dbg, begin_address, length, symbol_index,
+ /* end_symbol_index */ 0,
+ /* offset_from_end_sym */ 0,
+ error);
+}
+
+/* This function adds another address range
+ to the list of address ranges for the
+ given Dwarf_P_Debug. It returns 0 on error,
+ and 1 otherwise. */
+Dwarf_Unsigned
+dwarf_add_arange_b(Dwarf_P_Debug dbg,
+ Dwarf_Addr begin_address,
+ Dwarf_Unsigned length,
+ Dwarf_Unsigned symbol_index,
+ Dwarf_Unsigned end_symbol_index,
+ Dwarf_Addr offset_from_end_sym, Dwarf_Error * error)
+{
+ Dwarf_P_Arange arange;
+
+ if (dbg == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
+ return (0);
+ }
+
+ arange = (Dwarf_P_Arange)
+ _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Arange_s));
+ if (arange == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (0);
+ }
+
+ arange->ag_begin_address = begin_address;
+ arange->ag_length = length;
+ arange->ag_symbol_index = symbol_index;
+ arange->ag_end_symbol_index = end_symbol_index;
+ arange->ag_end_symbol_offset = offset_from_end_sym;
+
+ if (dbg->de_arange == NULL)
+ dbg->de_arange = dbg->de_last_arange = arange;
+ else {
+ dbg->de_last_arange->ag_next = arange;
+ dbg->de_last_arange = arange;
+ }
+ dbg->de_arange_count++;
+
+ return (1);
+}
+
+
+int
+_dwarf_transform_arange_to_disk(Dwarf_P_Debug dbg, Dwarf_Error * error)
+{
+ /* Total num of bytes in .debug_aranges section. */
+ Dwarf_Unsigned arange_num_bytes = 0;
+
+ /* Adjustment to align the start of the actual address ranges on a
+ boundary aligned with twice the address size. */
+ Dwarf_Small remainder = 0;
+
+ /* Total number of bytes excluding the length field. */
+ Dwarf_Unsigned adjusted_length = 0;
+
+ /* Points to first byte of .debug_aranges buffer. */
+ Dwarf_Small *arange = 0;
+
+ /* Fills in the .debug_aranges buffer. */
+ Dwarf_Small *arange_ptr = 0;
+
+ /* Scans the list of address ranges provided by user. */
+ Dwarf_P_Arange given_arange = 0;
+
+ /* Used to fill in 0. */
+ const Dwarf_Signed big_zero = 0;
+
+ int extension_word_size = dbg->de_64bit_extension ? 4 : 0;
+ int uword_size = dbg->de_offset_size;
+ int upointer_size = dbg->de_pointer_size;
+ int res = 0;
+
+
+ /* ***** BEGIN CODE ***** */
+
+ /* Size of the .debug_aranges section header. */
+ arange_num_bytes = extension_word_size +
+ uword_size + /* Size of length field. */
+ sizeof(Dwarf_Half) + /* Size of version field. */
+ uword_size + /* Size of .debug_info offset. */
+ sizeof(Dwarf_Small) + /* Size of address size field. */
+ sizeof(Dwarf_Small); /* Size of segment size field. */
+
+ /* Adjust the size so that the set of aranges begins on a boundary
+ that aligned with twice the address size. This is a Libdwarf
+ requirement. */
+ remainder = arange_num_bytes % (2 * upointer_size);
+ if (remainder != 0)
+ arange_num_bytes += (2 * upointer_size) - remainder;
+
+
+ /* Add the bytes for the actual address ranges. */
+ arange_num_bytes += upointer_size * 2 * (dbg->de_arange_count + 1);
+
+ GET_CHUNK(dbg, dbg->de_elf_sects[DEBUG_ARANGES],
+ arange, (unsigned long) arange_num_bytes, error);
+ arange_ptr = arange;
+ if (arange == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (0);
+ }
+ if (extension_word_size) {
+ Dwarf_Word x = DISTINGUISHED_VALUE;
+
+ WRITE_UNALIGNED(dbg, (void *) arange_ptr,
+ (const void *) &x,
+ sizeof(x), extension_word_size);
+ arange_ptr += extension_word_size;
+ }
+
+ /* Write the total length of .debug_aranges section. */
+ adjusted_length = arange_num_bytes - uword_size
+ - extension_word_size;
+ {
+ Dwarf_Unsigned du = adjusted_length;
+
+ WRITE_UNALIGNED(dbg, (void *) arange_ptr,
+ (const void *) &du, sizeof(du), uword_size);
+ arange_ptr += uword_size;
+ }
+
+ /* Write the version as 2 bytes. */
+ {
+ Dwarf_Half verstamp = CURRENT_VERSION_STAMP;
+
+ WRITE_UNALIGNED(dbg, (void *) arange_ptr,
+ (const void *) &verstamp,
+ sizeof(verstamp), sizeof(Dwarf_Half));
+ arange_ptr += sizeof(Dwarf_Half);
+ }
+
+
+ /* Write the .debug_info offset. This is always 0. */
+ WRITE_UNALIGNED(dbg, (void *) arange_ptr,
+ (const void *) &big_zero,
+ sizeof(big_zero), uword_size);
+ arange_ptr += uword_size;
+
+ {
+ unsigned long count = dbg->de_arange_count + 1;
+ int res = 0;
+
+ if (dbg->de_reloc_pair) {
+ count = (3 * dbg->de_arange_count) + 1;
+ }
+ /* The following is a small optimization: not needed for
+ correctness */
+ res = _dwarf_pro_pre_alloc_n_reloc_slots(dbg,
+ DEBUG_ARANGES, count);
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (0);
+ }
+ }
+
+ /* reloc for .debug_info */
+ res = dbg->de_reloc_name(dbg,
+ DEBUG_ARANGES,
+ extension_word_size +
+ uword_size + sizeof(Dwarf_Half),
+ dbg->de_sect_name_idx[DEBUG_INFO],
+ dwarf_drt_data_reloc, uword_size);
+
+ /* Write the size of addresses. */
+ *arange_ptr = dbg->de_pointer_size;
+ arange_ptr++;
+
+ /* Write the size of segment addresses. This is zero for MIPS
+ architectures. */
+ *arange_ptr = 0;
+ arange_ptr++;
+
+ /* Skip over the padding to align the start of the actual address
+ ranges to twice the address size. */
+ if (remainder != 0)
+ arange_ptr += (2 * upointer_size) - remainder;
+
+
+
+
+
+ /* The arange address, length are pointer-size fields of the target
+ machine. */
+ for (given_arange = dbg->de_arange; given_arange != NULL;
+ given_arange = given_arange->ag_next) {
+
+ /* Write relocation record for beginning of address range. */
+ res = dbg->de_reloc_name(dbg, DEBUG_ARANGES,
+ arange_ptr - arange, /* r_offset */
+ (long) given_arange->ag_symbol_index,
+ dwarf_drt_data_reloc, upointer_size);
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (0);
+ }
+
+ /* Copy beginning address of range. */
+ WRITE_UNALIGNED(dbg, (void *) arange_ptr,
+ (const void *) &given_arange->ag_begin_address,
+ sizeof(given_arange->ag_begin_address),
+ upointer_size);
+ arange_ptr += upointer_size;
+
+ if (dbg->de_reloc_pair &&
+ given_arange->ag_end_symbol_index != 0 &&
+ given_arange->ag_length == 0) {
+ /* symbolic reloc, need reloc for length What if we really
+ know the length? If so, should use the other part of
+ 'if'. */
+ Dwarf_Unsigned val;
+
+ res = dbg->de_reloc_pair(dbg, DEBUG_ARANGES,
+ arange_ptr - arange, /* r_offset */
+ given_arange->ag_symbol_index,
+ given_arange->ag_end_symbol_index,
+ dwarf_drt_first_of_length_pair,
+ upointer_size);
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (0);
+ }
+
+ /* arange pre-calc so assem text can do .word end - begin
+ + val (gets val from stream) */
+ val = given_arange->ag_end_symbol_offset -
+ given_arange->ag_begin_address;
+ WRITE_UNALIGNED(dbg, (void *) arange_ptr,
+ (const void *) &val,
+ sizeof(val), upointer_size);
+ arange_ptr += upointer_size;
+
+ } else {
+ /* plain old length to copy, no relocation at all */
+ WRITE_UNALIGNED(dbg, (void *) arange_ptr,
+ (const void *) &given_arange->ag_length,
+ sizeof(given_arange->ag_length),
+ upointer_size);
+ arange_ptr += upointer_size;
+ }
+ }
+
+ WRITE_UNALIGNED(dbg, (void *) arange_ptr,
+ (const void *) &big_zero,
+ sizeof(big_zero), upointer_size);
+
+ arange_ptr += upointer_size;
+ WRITE_UNALIGNED(dbg, (void *) arange_ptr,
+ (const void *) &big_zero,
+ sizeof(big_zero), upointer_size);
+ return (int) dbg->de_n_debug_sect;
+}
diff --git a/libdwarf/pro_arange.h b/libdwarf/pro_arange.h
new file mode 100644
index 0000000..ff5db98
--- /dev/null
+++ b/libdwarf/pro_arange.h
@@ -0,0 +1,60 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+/*
+ If ag_end_symbol_index is zero,
+ ag_length must be known and non-zero.
+
+ Deals with length being known costant or fr
+ assembler output, not known.
+*/
+
+struct Dwarf_P_Arange_s {
+ Dwarf_Addr ag_begin_address; /* known address or for
+ symbolic assem output,
+ offset of symbol */
+ Dwarf_Addr ag_length; /* zero or address or offset */
+ Dwarf_Unsigned ag_symbol_index;
+
+ Dwarf_P_Arange ag_next;
+
+ Dwarf_Unsigned ag_end_symbol_index; /* zero or index/id of end
+symbol */
+ Dwarf_Addr ag_end_symbol_offset; /* known address or for
+ symbolic assem output,
+ offset of end symbol */
+
+};
diff --git a/libdwarf/pro_die.c b/libdwarf/pro_die.c
new file mode 100644
index 0000000..cc22050
--- /dev/null
+++ b/libdwarf/pro_die.c
@@ -0,0 +1,439 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#include "pro_incl.h"
+#include "pro_die.h"
+
+#ifndef R_MIPS_NONE
+#define R_MIPS_NONE 0
+#endif
+
+/* adds an attribute to a die */
+void _dwarf_pro_add_at_to_die(Dwarf_P_Die die, Dwarf_P_Attribute attr);
+
+/* This function creates a new die.
+ tag: tag of the new die to be created
+ parent,child,left,right: specify neighbors of the new die. Only
+ one of these may be non-null */
+Dwarf_P_Die
+dwarf_new_die(Dwarf_P_Debug dbg,
+ Dwarf_Tag tag,
+ Dwarf_P_Die parent,
+ Dwarf_P_Die child,
+ Dwarf_P_Die left, Dwarf_P_Die right, Dwarf_Error * error)
+{
+ Dwarf_P_Die ret_die = 0;
+
+ Dwarf_P_Die new_die = (Dwarf_P_Die)
+ _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Die_s));
+ if (new_die == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_ALLOC,
+ (Dwarf_P_Die) DW_DLV_BADADDR);
+ }
+ new_die->di_parent = NULL;
+ new_die->di_left = NULL;
+ new_die->di_right = NULL;
+ new_die->di_child = NULL;
+ new_die->di_last_child = NULL;
+ new_die->di_tag = tag;
+ new_die->di_dbg = dbg;
+ new_die->di_marker = 0;
+ ret_die =
+ dwarf_die_link(new_die, parent, child, left, right, error);
+ return ret_die;
+}
+
+/* This function links up a die to specified neighbors
+ parent,child,left,right: specify neighbors of the new die. Only
+ one of these may be non-null */
+Dwarf_P_Die
+dwarf_die_link(Dwarf_P_Die new_die,
+ Dwarf_P_Die parent,
+ Dwarf_P_Die child,
+ Dwarf_P_Die left, Dwarf_P_Die right, Dwarf_Error * error)
+{
+ /* Count the # of non null neighbors. */
+ int n_nulls = 0;
+
+ if (parent != NULL) {
+ n_nulls++;
+ if (new_die->di_parent != NULL) {
+ DWARF_P_DBG_ERROR(NULL, DW_DLE_LINK_LOOP,
+ (Dwarf_P_Die) DW_DLV_BADADDR);
+ }
+ new_die->di_parent = parent;
+ if (parent->di_child) {
+
+ /* di_last_child identifies the last sibling, the
+ die we want to attach new_die to. */
+ /* ASSERT: if di_child is set so is di_last_child. */
+ Dwarf_P_Die former_lastchild = parent->di_last_child;
+ parent->di_last_child = new_die;
+ /* Attach to the new die to end of the sibling list. */
+ former_lastchild->di_right = new_die;
+ new_die->di_left = former_lastchild;
+ } else {
+ parent->di_child = new_die;
+ parent->di_last_child = new_die;
+ }
+ }
+ if (child != NULL) {
+ n_nulls++;
+ new_die->di_child = child;
+ new_die->di_last_child = child;
+ if (child->di_parent) {
+ DWARF_P_DBG_ERROR(NULL, DW_DLE_PARENT_EXISTS,
+ (Dwarf_P_Die) DW_DLV_BADADDR);
+ } else {
+ child->di_parent = new_die;
+ }
+ }
+ if (left != NULL) {
+ n_nulls++;
+ new_die->di_left = left;
+ if (left->di_right) {
+ /* There's already a right sibling of left,
+ insert the new die in the list. */
+ new_die->di_right = left->di_right;
+ left->di_right->di_left = new_die;
+ }
+ left->di_right = new_die;
+ if (new_die->di_parent) {
+ DWARF_P_DBG_ERROR(NULL, DW_DLE_PARENT_EXISTS,
+ (Dwarf_P_Die) DW_DLV_BADADDR);
+ } else {
+ new_die->di_parent = left->di_parent;
+ }
+ }
+ if (right != NULL) {
+ n_nulls++;
+ new_die->di_right = right;
+ if (right->di_left) {
+ /* There is already a left sibling of the right die,
+ insert the new die in the list. */
+ new_die->di_left = right->di_left;
+ right->di_left->di_right = new_die;
+ }
+ right->di_left = new_die;
+ if (new_die->di_parent) {
+ DWARF_P_DBG_ERROR(NULL, DW_DLE_PARENT_EXISTS,
+ (Dwarf_P_Die) DW_DLV_BADADDR);
+ } else {
+ new_die->di_parent = right->di_parent;
+ }
+ }
+ if (n_nulls > 1) {
+ /* Multiple neighbors! error! */
+ DWARF_P_DBG_ERROR(NULL, DW_DLE_EXTRA_NEIGHBORS,
+ (Dwarf_P_Die) DW_DLV_BADADDR);
+ }
+ return new_die;
+
+}
+
+Dwarf_Unsigned
+dwarf_add_die_marker(Dwarf_P_Debug dbg,
+ Dwarf_P_Die die,
+ Dwarf_Unsigned marker,
+ Dwarf_Error * error)
+{
+ if (die == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL, DW_DLV_NOCOUNT);
+ }
+ die->di_marker = marker;
+ return 0;
+}
+
+
+Dwarf_Unsigned
+dwarf_get_die_marker(Dwarf_P_Debug dbg,
+ Dwarf_P_Die die,
+ Dwarf_Unsigned * marker,
+ Dwarf_Error * error)
+{
+ if (die == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL, DW_DLV_NOCOUNT);
+ }
+ *marker = die->di_marker;
+ return 0;
+}
+
+
+/*----------------------------------------------------------------------------
+ This function adds a die to dbg struct. It should be called using
+ the root of all the dies.
+-----------------------------------------------------------------------------*/
+Dwarf_Unsigned
+dwarf_add_die_to_debug(Dwarf_P_Debug dbg,
+ Dwarf_P_Die first_die, Dwarf_Error * error)
+{
+ if (first_die == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_DIE_NULL, DW_DLV_NOCOUNT);
+ }
+ if (first_die->di_tag != DW_TAG_compile_unit) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_WRONG_TAG, DW_DLV_NOCOUNT);
+ }
+ dbg->de_dies = first_die;
+ return 0;
+}
+
+int
+_dwarf_pro_add_AT_stmt_list(Dwarf_P_Debug dbg,
+ Dwarf_P_Die first_die, Dwarf_Error * error)
+{
+ Dwarf_P_Attribute new_attr;
+ int uwordb_size = dbg->de_offset_size;
+
+ /* Add AT_stmt_list attribute */
+ new_attr = (Dwarf_P_Attribute)
+ _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
+ if (new_attr == NULL) {
+ DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, DW_DLV_NOCOUNT);
+ }
+
+ new_attr->ar_attribute = DW_AT_stmt_list;
+ new_attr->ar_attribute_form = dbg->de_ar_data_attribute_form;
+ new_attr->ar_rel_type = dbg->de_offset_reloc;
+
+ new_attr->ar_nbytes = uwordb_size;
+ new_attr->ar_next = NULL;
+ new_attr->ar_reloc_len = uwordb_size;
+ new_attr->ar_data = (char *)
+ _dwarf_p_get_alloc(dbg, uwordb_size);
+ if (new_attr->ar_data == NULL) {
+ DWARF_P_DBG_ERROR(NULL, DW_DLE_ADDR_ALLOC, DW_DLV_NOCOUNT);
+ }
+ {
+ Dwarf_Unsigned du = 0;
+
+ WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data,
+ (const void *) &du, sizeof(du), uwordb_size);
+ }
+
+ _dwarf_pro_add_at_to_die(first_die, new_attr);
+ return 0;
+}
+
+/*-----------------------------------------------------------------------------
+ Add AT_name attribute to die
+------------------------------------------------------------------------------*/
+Dwarf_P_Attribute
+dwarf_add_AT_name(Dwarf_P_Die die, char *name, Dwarf_Error * error)
+{
+ Dwarf_P_Attribute new_attr;
+
+ if (die == NULL) {
+ DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL,
+ (Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+ new_attr = (Dwarf_P_Attribute)
+ _dwarf_p_get_alloc(die->di_dbg,sizeof(struct Dwarf_P_Attribute_s));
+ if (new_attr == NULL) {
+ DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC,
+ (Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ /* fill in the information */
+ new_attr->ar_attribute = DW_AT_name;
+ /* assume that form is string, no debug_str yet */
+ new_attr->ar_attribute_form = DW_FORM_string;
+ new_attr->ar_nbytes = strlen(name) + 1;
+ new_attr->ar_next = NULL;
+ new_attr->ar_reloc_len = 0;
+ new_attr->ar_data = (char *)
+ _dwarf_p_get_alloc(die->di_dbg, strlen(name)+1);
+ if (new_attr->ar_data == NULL) {
+ DWARF_P_DBG_ERROR(NULL, DW_DLE_STRING_ALLOC,
+ (Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+ strcpy(new_attr->ar_data, name);
+
+ new_attr->ar_rel_type = R_MIPS_NONE;
+
+ /* add attribute to the die */
+ _dwarf_pro_add_at_to_die(die, new_attr);
+ return new_attr;
+}
+
+
+/*-----------------------------------------------------------------------------
+ Add AT_comp_dir attribute to die
+------------------------------------------------------------------------------*/
+Dwarf_P_Attribute
+dwarf_add_AT_comp_dir(Dwarf_P_Die ownerdie,
+ char *current_working_directory,
+ Dwarf_Error * error)
+{
+ Dwarf_P_Attribute new_attr;
+
+ if (ownerdie == NULL) {
+ DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL,
+ (Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+ new_attr = (Dwarf_P_Attribute)
+ _dwarf_p_get_alloc(ownerdie->di_dbg,
+ sizeof(struct Dwarf_P_Attribute_s));
+ if (new_attr == NULL) {
+ DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC,
+ (Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ /* fill in the information */
+ new_attr->ar_attribute = DW_AT_comp_dir;
+ /* assume that form is string, no debug_str yet */
+ new_attr->ar_attribute_form = DW_FORM_string;
+ new_attr->ar_nbytes = strlen(current_working_directory) + 1;
+ new_attr->ar_next = NULL;
+ new_attr->ar_reloc_len = 0;
+ new_attr->ar_data = (char *)
+ _dwarf_p_get_alloc(ownerdie->di_dbg,
+ strlen(current_working_directory)+1);
+ if (new_attr->ar_data == NULL) {
+ DWARF_P_DBG_ERROR(NULL, DW_DLE_STRING_ALLOC,
+ (Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+ strcpy(new_attr->ar_data, current_working_directory);
+
+ new_attr->ar_rel_type = R_MIPS_NONE;
+
+ /* add attribute to the die */
+ _dwarf_pro_add_at_to_die(ownerdie, new_attr);
+ return new_attr;
+}
+
+int
+_dwarf_pro_add_AT_fde(Dwarf_P_Debug dbg,
+ Dwarf_P_Die die,
+ Dwarf_Unsigned offset, Dwarf_Error * error)
+{
+ Dwarf_P_Attribute new_attr;
+ int uwordb_size = dbg->de_offset_size;
+
+ if (die == NULL) {
+ DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, -1);
+ }
+ new_attr = (Dwarf_P_Attribute)
+ _dwarf_p_get_alloc(dbg,sizeof(struct Dwarf_P_Attribute_s));
+ if (new_attr == NULL) {
+ DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, -1);
+ }
+
+ /* fill in the information */
+ new_attr->ar_attribute = DW_AT_MIPS_fde;
+ new_attr->ar_attribute_form = dbg->de_ar_data_attribute_form;;
+ new_attr->ar_rel_type = dbg->de_offset_reloc;
+ new_attr->ar_nbytes = uwordb_size;
+ new_attr->ar_next = NULL;
+ new_attr->ar_reloc_len = uwordb_size;
+ new_attr->ar_data = (char *)
+ _dwarf_p_get_alloc(dbg, uwordb_size);
+ if (new_attr->ar_data == NULL) {
+ DWARF_P_DBG_ERROR(NULL, DW_DLE_ADDR_ALLOC, DW_DLV_NOCOUNT);
+ }
+ {
+ Dwarf_Unsigned du = offset;
+
+ WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data,
+ (const void *) &du, sizeof(du), uwordb_size);
+ }
+
+ _dwarf_pro_add_at_to_die(die, new_attr);
+
+ return 0;
+}
+
+int
+_dwarf_pro_add_AT_macro_info(Dwarf_P_Debug dbg,
+ Dwarf_P_Die die,
+ Dwarf_Unsigned offset, Dwarf_Error * error)
+{
+ Dwarf_P_Attribute new_attr;
+ int uwordb_size = dbg->de_offset_size;
+
+ if (die == NULL) {
+ DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, -1);
+ }
+ new_attr = (Dwarf_P_Attribute)
+ _dwarf_p_get_alloc(dbg,sizeof(struct Dwarf_P_Attribute_s));
+ if (new_attr == NULL) {
+ DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, -1);
+ }
+
+ /* fill in the information */
+ new_attr->ar_attribute = DW_AT_macro_info;
+ new_attr->ar_attribute_form = dbg->de_ar_data_attribute_form;
+ new_attr->ar_rel_type = dbg->de_offset_reloc;
+
+ new_attr->ar_nbytes = uwordb_size;
+ new_attr->ar_next = NULL;
+ new_attr->ar_reloc_len = uwordb_size;
+ new_attr->ar_data = (char *)
+ _dwarf_p_get_alloc(dbg, uwordb_size);
+ if (new_attr->ar_data == NULL) {
+ DWARF_P_DBG_ERROR(NULL, DW_DLE_ADDR_ALLOC, DW_DLV_NOCOUNT);
+ }
+ {
+ Dwarf_Unsigned du = offset;
+
+ WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data,
+ (const void *) &du, sizeof(du), uwordb_size);
+ }
+
+ _dwarf_pro_add_at_to_die(die, new_attr);
+
+ return 0;
+}
+
+
+void
+_dwarf_pro_add_at_to_die(Dwarf_P_Die die, Dwarf_P_Attribute attr)
+{
+ if (die->di_last_attr) {
+ die->di_last_attr->ar_next = attr;
+ die->di_last_attr = attr;
+ die->di_n_attr++;
+ } else {
+ die->di_n_attr = 1;
+ die->di_attrs = die->di_last_attr = attr;
+ }
+}
diff --git a/libdwarf/pro_die.h b/libdwarf/pro_die.h
new file mode 100644
index 0000000..01924a9
--- /dev/null
+++ b/libdwarf/pro_die.h
@@ -0,0 +1,68 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+
+/*
+ This struct holds the abbreviation table, before they are written
+ on disk. Holds a linked list of abbreviations, each consisting of
+ a bitmap for attributes and a bitmap for forms
+*/
+typedef struct Dwarf_P_Abbrev_s *Dwarf_P_Abbrev;
+
+struct Dwarf_P_Abbrev_s {
+ Dwarf_Unsigned abb_idx; /* index of abbreviation */
+ Dwarf_Tag abb_tag; /* tag of die */
+ Dwarf_Ubyte abb_children; /* if children are present */
+ Dwarf_ufixed *abb_attrs; /* holds names of attrs */
+ Dwarf_ufixed *abb_forms; /* forms of attributes */
+ int abb_n_attr; /* num of attrs = # of forms */
+ Dwarf_P_Abbrev abb_next;
+};
+
+/* used in pro_section.c */
+
+int _dwarf_pro_add_AT_fde(Dwarf_P_Debug dbg, Dwarf_P_Die die,
+ Dwarf_Unsigned offset, Dwarf_Error * error);
+
+int _dwarf_pro_add_AT_stmt_list(Dwarf_P_Debug dbg,
+ Dwarf_P_Die first_die,
+ Dwarf_Error * error);
+
+int _dwarf_pro_add_AT_macro_info(Dwarf_P_Debug dbg,
+ Dwarf_P_Die first_die,
+ Dwarf_Unsigned offset,
+ Dwarf_Error * error);
diff --git a/libdwarf/pro_encode_nm.c b/libdwarf/pro_encode_nm.c
new file mode 100644
index 0000000..1b89781
--- /dev/null
+++ b/libdwarf/pro_encode_nm.c
@@ -0,0 +1,119 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <string.h>
+#include "pro_incl.h"
+
+#define MORE_BYTES 0x80
+#define DATA_MASK 0x7f
+#define DIGIT_WIDTH 7
+#define SIGN_BIT 0x40
+
+
+/* Encode val as a leb128. This encodes it as an unsigned
+ number. */
+/* Return DW_DLV_ERROR or DW_DLV_OK.
+ space to write leb number is provided by caller, with caller
+ passing length.
+ number of bytes used returned thru nbytes arg */
+int
+_dwarf_pro_encode_leb128_nm(Dwarf_Unsigned val, int *nbytes,
+ char *space, int splen)
+{
+ char *a;
+ char *end = space + splen;
+
+ a = space;
+ do {
+ unsigned char uc;
+
+ if (a >= end) {
+ return DW_DLV_ERROR;
+ }
+ uc = val & DATA_MASK;
+ val >>= DIGIT_WIDTH;
+ if (val != 0) {
+ uc |= MORE_BYTES;
+ }
+ *a = uc;
+ a++;
+ } while (val);
+ *nbytes = a - space;
+ return DW_DLV_OK;
+}
+
+/* return DW_DLV_ERROR or DW_DLV_OK.
+** space to write leb number is provided by caller, with caller
+** passing length.
+** number of bytes used returned thru nbytes arg
+** encodes a signed number.
+*/
+int
+_dwarf_pro_encode_signed_leb128_nm(Dwarf_Signed value, int *nbytes,
+ char *space, int splen)
+{
+ char *str;
+ Dwarf_Signed sign = -(value < 0);
+ int more = 1;
+ char *end = space + splen;
+
+ str = space;
+
+ do {
+ unsigned char byte = value & DATA_MASK;
+
+ value >>= DIGIT_WIDTH;
+
+ if (str >= end) {
+ return DW_DLV_ERROR;
+ }
+ /* Remaining chunks would just contain the sign bit, and this chunk
+ has already captured at least one sign bit. */
+ if (value == sign && ((byte & SIGN_BIT) == (sign & SIGN_BIT))) {
+ more = 0;
+ } else {
+ byte |= MORE_BYTES;
+ }
+ *str = byte;
+ str++;
+ } while (more);
+ *nbytes = str - space;
+ return DW_DLV_OK;
+}
diff --git a/libdwarf/pro_encode_nm.h b/libdwarf/pro_encode_nm.h
new file mode 100644
index 0000000..6e42838
--- /dev/null
+++ b/libdwarf/pro_encode_nm.h
@@ -0,0 +1,48 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+/* Bytes needed to encode a number.
+ Not a tight bound, just a reasonable bound.
+*/
+#define ENCODE_SPACE_NEEDED (2*sizeof(Dwarf_Unsigned))
+
+
+int _dwarf_pro_encode_leb128_nm(Dwarf_Unsigned val, int *nbytes,
+ char *space, int splen);
+
+int _dwarf_pro_encode_signed_leb128_nm(Dwarf_Signed value, int *nbytes,
+ char *space, int splen);
diff --git a/libdwarf/pro_error.c b/libdwarf/pro_error.c
new file mode 100644
index 0000000..d9a599b
--- /dev/null
+++ b/libdwarf/pro_error.c
@@ -0,0 +1,107 @@
+/*
+
+ Copyright (C) 2000,2002,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#ifdef HAVE_ELF_H
+#include <elf.h>
+#endif
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include "pro_incl.h"
+
+extern char *_dwarf_errmsgs[];
+
+/*
+ This function performs error handling as described in the
+ libdwarf consumer document section 3. Dbg is the Dwarf_P_debug
+ structure being processed. Error is a pointer to the pointer
+ to the error descriptor that will be returned. Errval is an
+ error code listed in dwarf_error.h.
+
+ The error number may be retrieved from the Dwarf_Error
+ by calling dwarf_errno().
+ The error string implied by the error number may be retrieved
+ from the Dwarf_Error by calling dwarf_errmsg().
+*/
+void
+_dwarf_p_error(Dwarf_P_Debug dbg,
+ Dwarf_Error * error, Dwarf_Word errval)
+{
+ Dwarf_Error errptr;
+
+ if (errval > DW_DLE_LAST) {
+ /* We do not expect to ever see such an error number,
+ DW_DLE_LO_USER is not used. */
+ /* The 'standard' typedef for Dwarf_Word is "unsigned long". */
+ fprintf(stderr,"ERROR VALUE: %lu - %s\n",
+ (unsigned long) errval, "this error value is unknown to libdwarf.");
+ }
+ /* Allow NULL dbg on entry, since sometimes that can happen and we
+ want to report the upper-level error, not this one. */
+ if (error != NULL) {
+ errptr = (Dwarf_Error)
+ _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_Error_s));
+ if (errptr == NULL) {
+ fprintf(stderr,
+ "Could not allocate Dwarf_Error structure\n");
+ abort();
+ }
+ errptr->er_errval = (Dwarf_Sword) errval;
+ *error = errptr;
+ return;
+ }
+
+ if (dbg != NULL && dbg->de_errhand != NULL) {
+ errptr = (Dwarf_Error)
+ _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_Error_s));
+ if (errptr == NULL) {
+ fprintf(stderr,
+ "Could not allocate Dwarf_Error structure\n");
+ abort();
+ }
+ errptr->er_errval = (Dwarf_Sword) errval;
+ dbg->de_errhand(errptr, dbg->de_errarg);
+ return;
+ }
+
+ abort();
+}
diff --git a/libdwarf/pro_error.h b/libdwarf/pro_error.h
new file mode 100644
index 0000000..fb255f5
--- /dev/null
+++ b/libdwarf/pro_error.h
@@ -0,0 +1,52 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+
+/* Handle error passing in the name of the Dwarf_P_Debug
+ User must supply {} around the macro.
+ Putting the {} here leads to macro uses that don't look like C.
+ The error argument to dwarf_error is hard coded here as 'error'
+*/
+#define DWARF_P_DBG_ERROR(dbg,errval,retval) \
+ _dwarf_p_error(dbg,error,errval); return(retval);
+
+struct Dwarf_Error_s {
+ Dwarf_Sword er_errval;
+};
+
+void _dwarf_p_error(Dwarf_P_Debug dbg, Dwarf_Error * error,
+ Dwarf_Word errval);
diff --git a/libdwarf/pro_expr.c b/libdwarf/pro_expr.c
new file mode 100644
index 0000000..21526c5
--- /dev/null
+++ b/libdwarf/pro_expr.c
@@ -0,0 +1,585 @@
+/*
+ Copyright (C) 2000,2004,2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#include "pro_incl.h"
+#include "pro_expr.h"
+
+/*
+ This function creates a new expression
+ struct that can be used to build up a
+ location expression.
+*/
+Dwarf_P_Expr
+dwarf_new_expr(Dwarf_P_Debug dbg, Dwarf_Error * error)
+{
+ Dwarf_P_Expr ret_expr;
+
+ if (dbg == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
+ return (NULL);
+ }
+
+ ret_expr = (Dwarf_P_Expr)
+ _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Expr_s));
+ if (ret_expr == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (NULL);
+ }
+
+ ret_expr->ex_dbg = dbg;
+
+ return (ret_expr);
+}
+
+
+Dwarf_Unsigned
+dwarf_add_expr_gen(Dwarf_P_Expr expr,
+ Dwarf_Small opcode,
+ Dwarf_Unsigned val1,
+ Dwarf_Unsigned val2, Dwarf_Error * error)
+{
+ /* 2* since used to concatenate 2 leb's below */
+ char encode_buffer[2 * ENCODE_SPACE_NEEDED];
+
+ char encode_buffer2[ENCODE_SPACE_NEEDED];
+ int res = 0;
+ Dwarf_P_Debug dbg = expr->ex_dbg;
+
+ /* Give the buffer where the operands are first going to be
+ assembled the largest alignment. */
+ Dwarf_Unsigned operand_buffer[10];
+
+ /* Size of the byte stream buffer that needs to be memcpy-ed. */
+ int operand_size = 0;
+
+ /* Points to the byte stream for the first operand, and finally to
+ the buffer that is memcp-ed into the Dwarf_P_Expr_s struct. */
+ Dwarf_Small *operand = 0;
+
+ /* Size of the byte stream for second operand. */
+ int operand2_size = 0;
+
+ /* Points to next byte to be written in Dwarf_P_Expr_s struct. */
+ Dwarf_Small *next_byte_ptr = 0;
+
+ /* Offset past the last byte written into Dwarf_P_Expr_s. */
+ int next_byte_offset = 0;
+
+ /* ***** BEGIN CODE ***** */
+
+ if (expr == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL);
+ return (DW_DLV_NOCOUNT);
+ }
+
+ if (expr->ex_dbg == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_NOCOUNT);
+ }
+
+ operand = NULL;
+ operand_size = 0;
+
+ switch (opcode) {
+ case DW_OP_reg0:
+ case DW_OP_reg1:
+ case DW_OP_reg2:
+ case DW_OP_reg3:
+ case DW_OP_reg4:
+ case DW_OP_reg5:
+ case DW_OP_reg6:
+ case DW_OP_reg7:
+ case DW_OP_reg8:
+ case DW_OP_reg9:
+ case DW_OP_reg10:
+ case DW_OP_reg11:
+ case DW_OP_reg12:
+ case DW_OP_reg13:
+ case DW_OP_reg14:
+ case DW_OP_reg15:
+ case DW_OP_reg16:
+ case DW_OP_reg17:
+ case DW_OP_reg18:
+ case DW_OP_reg19:
+ case DW_OP_reg20:
+ case DW_OP_reg21:
+ case DW_OP_reg22:
+ case DW_OP_reg23:
+ case DW_OP_reg24:
+ case DW_OP_reg25:
+ case DW_OP_reg26:
+ case DW_OP_reg27:
+ case DW_OP_reg28:
+ case DW_OP_reg29:
+ case DW_OP_reg30:
+ case DW_OP_reg31:
+ break;
+
+ case DW_OP_breg0:
+ case DW_OP_breg1:
+ case DW_OP_breg2:
+ case DW_OP_breg3:
+ case DW_OP_breg4:
+ case DW_OP_breg5:
+ case DW_OP_breg6:
+ case DW_OP_breg7:
+ case DW_OP_breg8:
+ case DW_OP_breg9:
+ case DW_OP_breg10:
+ case DW_OP_breg11:
+ case DW_OP_breg12:
+ case DW_OP_breg13:
+ case DW_OP_breg14:
+ case DW_OP_breg15:
+ case DW_OP_breg16:
+ case DW_OP_breg17:
+ case DW_OP_breg18:
+ case DW_OP_breg19:
+ case DW_OP_breg20:
+ case DW_OP_breg21:
+ case DW_OP_breg22:
+ case DW_OP_breg23:
+ case DW_OP_breg24:
+ case DW_OP_breg25:
+ case DW_OP_breg26:
+ case DW_OP_breg27:
+ case DW_OP_breg28:
+ case DW_OP_breg29:
+ case DW_OP_breg30:
+ case DW_OP_breg31:
+ res = _dwarf_pro_encode_signed_leb128_nm(val1,
+ &operand_size, encode_buffer, sizeof(encode_buffer));
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
+ return (DW_DLV_NOCOUNT);
+ }
+ operand = (Dwarf_Small *) encode_buffer;
+ break;
+
+ case DW_OP_regx:
+ res = _dwarf_pro_encode_leb128_nm(val1, &operand_size,
+ encode_buffer, sizeof(encode_buffer));
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
+ return (DW_DLV_NOCOUNT);
+ }
+ operand = (Dwarf_Small *) encode_buffer;
+ break;
+
+ case DW_OP_lit0:
+ case DW_OP_lit1:
+ case DW_OP_lit2:
+ case DW_OP_lit3:
+ case DW_OP_lit4:
+ case DW_OP_lit5:
+ case DW_OP_lit6:
+ case DW_OP_lit7:
+ case DW_OP_lit8:
+ case DW_OP_lit9:
+ case DW_OP_lit10:
+ case DW_OP_lit11:
+ case DW_OP_lit12:
+ case DW_OP_lit13:
+ case DW_OP_lit14:
+ case DW_OP_lit15:
+ case DW_OP_lit16:
+ case DW_OP_lit17:
+ case DW_OP_lit18:
+ case DW_OP_lit19:
+ case DW_OP_lit20:
+ case DW_OP_lit21:
+ case DW_OP_lit22:
+ case DW_OP_lit23:
+ case DW_OP_lit24:
+ case DW_OP_lit25:
+ case DW_OP_lit26:
+ case DW_OP_lit27:
+ case DW_OP_lit28:
+ case DW_OP_lit29:
+ case DW_OP_lit30:
+ case DW_OP_lit31:
+ break;
+
+ case DW_OP_addr:
+ _dwarf_p_error(expr->ex_dbg, error, DW_DLE_BAD_EXPR_OPCODE);
+ return (DW_DLV_NOCOUNT);
+
+ case DW_OP_const1u:
+ case DW_OP_const1s:
+ operand = (Dwarf_Small *) & operand_buffer[0];
+ WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 1);
+ operand_size = 1;
+ break;
+
+ case DW_OP_const2u:
+ case DW_OP_const2s:
+ operand = (Dwarf_Small *) & operand_buffer[0];
+ WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 2);
+ operand_size = 2;
+ break;
+
+ case DW_OP_const4u:
+ case DW_OP_const4s:
+ operand = (Dwarf_Small *) & operand_buffer[0];
+ WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 4);
+ operand_size = 4;
+ break;
+
+ case DW_OP_const8u:
+ case DW_OP_const8s:
+ operand = (Dwarf_Small *) & operand_buffer[0];
+ WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 8);
+ operand_size = 8;
+ break;
+
+ case DW_OP_constu:
+ res = _dwarf_pro_encode_leb128_nm(val1,
+ &operand_size, encode_buffer, sizeof(encode_buffer));
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
+ return (DW_DLV_NOCOUNT);
+ }
+ operand = (Dwarf_Small *) encode_buffer;
+ break;
+
+ case DW_OP_consts:
+ res = _dwarf_pro_encode_signed_leb128_nm(val1,
+ &operand_size,
+ encode_buffer,
+ sizeof(encode_buffer));
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
+ return (DW_DLV_NOCOUNT);
+ }
+ operand = (Dwarf_Small *) encode_buffer;
+ break;
+
+ case DW_OP_fbreg:
+ res = _dwarf_pro_encode_signed_leb128_nm(val1,
+ &operand_size,
+ encode_buffer,
+ sizeof(encode_buffer));
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
+ return (DW_DLV_NOCOUNT);
+ }
+ operand = (Dwarf_Small *) encode_buffer;
+ break;
+
+ case DW_OP_bregx:
+ res = _dwarf_pro_encode_leb128_nm(val1, &operand_size,
+ encode_buffer,
+ sizeof(encode_buffer));
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
+ return (DW_DLV_NOCOUNT);
+ }
+ operand = (Dwarf_Small *) encode_buffer;
+ /* put this one directly into 'operand' at tail of prev value */
+ res = _dwarf_pro_encode_signed_leb128_nm(val2, &operand2_size,
+ ((char *) operand) +
+ operand_size,
+ sizeof(encode_buffer2));
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
+ return (DW_DLV_NOCOUNT);
+ }
+ operand_size += operand2_size;
+
+ case DW_OP_dup:
+ case DW_OP_drop:
+ break;
+
+ case DW_OP_pick:
+ operand = (Dwarf_Small *) & operand_buffer[0];
+ WRITE_UNALIGNED(dbg, operand, (const void *) &val1,
+ sizeof(val1), 1);
+ operand_size = 1;
+ break;
+
+ case DW_OP_over:
+ case DW_OP_swap:
+ case DW_OP_rot:
+ case DW_OP_deref:
+ case DW_OP_xderef:
+ break;
+
+ case DW_OP_deref_size:
+ case DW_OP_xderef_size:
+ operand = (Dwarf_Small *) & operand_buffer[0];
+ WRITE_UNALIGNED(dbg, operand, (const void *) &val1,
+ sizeof(val1), 1);
+ operand_size = 1;
+ break;
+
+ 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:
+ break;
+
+ case DW_OP_plus_uconst:
+ res = _dwarf_pro_encode_leb128_nm(val1, &operand_size,
+ encode_buffer,
+ sizeof(encode_buffer));
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
+ return (DW_DLV_NOCOUNT);
+ }
+ operand = (Dwarf_Small *) encode_buffer;
+ break;
+
+ case DW_OP_shl:
+ case DW_OP_shr:
+ case DW_OP_shra:
+ case DW_OP_xor:
+ break;
+
+ case DW_OP_le:
+ case DW_OP_ge:
+ case DW_OP_eq:
+ case DW_OP_lt:
+ case DW_OP_gt:
+ case DW_OP_ne:
+ break;
+
+ case DW_OP_skip:
+ case DW_OP_bra:
+ /* FIX: unhandled! OP_bra, OP_skip! */
+ _dwarf_p_error(expr->ex_dbg, error, DW_DLE_BAD_EXPR_OPCODE);
+ return (DW_DLV_NOCOUNT);
+
+ case DW_OP_piece:
+ res = _dwarf_pro_encode_leb128_nm(val1, &operand_size,
+ encode_buffer,
+ sizeof(encode_buffer));
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
+ return (DW_DLV_NOCOUNT);
+ }
+ operand = (Dwarf_Small *) encode_buffer;
+ break;
+
+ case DW_OP_nop:
+ break;
+ case DW_OP_push_object_address: /* DWARF3 */
+ break;
+ case DW_OP_call2: /* DWARF3 */
+ operand = (Dwarf_Small *) & operand_buffer[0];
+ WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 2);
+ operand_size = 2;
+ break;
+
+ case DW_OP_call4: /* DWARF3 */
+ operand = (Dwarf_Small *) & operand_buffer[0];
+ WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 4);
+ operand_size = 4;
+ break;
+
+ case DW_OP_call_ref: /* DWARF3 */
+ operand = (Dwarf_Small *) & operand_buffer[0];
+ WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1),
+ dbg->de_offset_size);
+ operand_size = dbg->de_offset_size;
+ break;
+ case DW_OP_form_tls_address: /* DWARF3f */
+ break;
+ case DW_OP_call_frame_cfa: /* DWARF3f */
+ break;
+ case DW_OP_bit_piece: /* DWARF3f */
+ res = _dwarf_pro_encode_leb128_nm(val1, &operand_size,
+ encode_buffer,
+ sizeof(encode_buffer));
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
+ return (DW_DLV_NOCOUNT);
+ }
+ operand = (Dwarf_Small *) encode_buffer;
+ /* put this one directly into 'operand' at tail of prev value */
+ res = _dwarf_pro_encode_leb128_nm(val2, &operand2_size,
+ ((char *) operand) +
+ operand_size,
+ sizeof(encode_buffer2));
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
+ return (DW_DLV_NOCOUNT);
+ }
+ operand_size += operand2_size;
+
+
+ default:
+ _dwarf_p_error(expr->ex_dbg, error, DW_DLE_BAD_EXPR_OPCODE);
+ return (DW_DLV_NOCOUNT);
+ }
+
+ next_byte_offset = expr->ex_next_byte_offset + operand_size + 1;
+
+ if (next_byte_offset > MAXIMUM_LOC_EXPR_LENGTH) {
+ _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
+ return (DW_DLV_NOCOUNT);
+ }
+
+ next_byte_ptr =
+ &(expr->ex_byte_stream[0]) + expr->ex_next_byte_offset;
+
+ *next_byte_ptr = opcode;
+ next_byte_ptr++;
+ memcpy(next_byte_ptr, operand, operand_size);
+
+ expr->ex_next_byte_offset = next_byte_offset;
+ return (next_byte_offset);
+}
+
+Dwarf_Unsigned
+dwarf_add_expr_addr_b(Dwarf_P_Expr expr,
+ Dwarf_Unsigned addr,
+ Dwarf_Unsigned sym_index, Dwarf_Error * error)
+{
+ Dwarf_P_Debug dbg;
+ Dwarf_Small *next_byte_ptr;
+ Dwarf_Unsigned next_byte_offset;
+ int upointer_size;
+
+ if (expr == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL);
+ return (DW_DLV_NOCOUNT);
+ }
+
+ dbg = expr->ex_dbg;
+ if (dbg == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_NOCOUNT);
+ }
+
+ upointer_size = dbg->de_pointer_size;
+ next_byte_offset = expr->ex_next_byte_offset + upointer_size + 1;
+ if (next_byte_offset > MAXIMUM_LOC_EXPR_LENGTH) {
+ _dwarf_p_error(dbg, error, DW_DLE_EXPR_LENGTH_BAD);
+ return (DW_DLV_NOCOUNT);
+ }
+
+ next_byte_ptr =
+ &(expr->ex_byte_stream[0]) + expr->ex_next_byte_offset;
+
+ *next_byte_ptr = DW_OP_addr;
+ next_byte_ptr++;
+ WRITE_UNALIGNED(dbg, next_byte_ptr, (const void *) &addr,
+ sizeof(addr), upointer_size);
+
+ if (expr->ex_reloc_offset != 0) {
+ _dwarf_p_error(dbg, error, DW_DLE_MULTIPLE_RELOC_IN_EXPR);
+ return (DW_DLV_NOCOUNT);
+ }
+
+ expr->ex_reloc_sym_index = sym_index;
+ expr->ex_reloc_offset = expr->ex_next_byte_offset + 1;
+
+ expr->ex_next_byte_offset = next_byte_offset;
+ return (next_byte_offset);
+}
+
+Dwarf_Unsigned
+dwarf_add_expr_addr(Dwarf_P_Expr expr,
+ Dwarf_Unsigned addr,
+ Dwarf_Signed sym_index, Dwarf_Error * error)
+{
+ return
+ dwarf_add_expr_addr_b(expr, addr, (Dwarf_Unsigned) sym_index,
+ error);
+}
+
+
+Dwarf_Unsigned
+dwarf_expr_current_offset(Dwarf_P_Expr expr, Dwarf_Error * error)
+{
+ if (expr == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL);
+ return (DW_DLV_NOCOUNT);
+ }
+
+ if (expr->ex_dbg == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_NOCOUNT);
+ }
+
+ return (expr->ex_next_byte_offset);
+}
+
+void
+dwarf_expr_reset(Dwarf_P_Expr expr, Dwarf_Error * error)
+{
+ if (expr == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL);
+ return;
+ }
+ expr->ex_next_byte_offset=0;
+}
+
+
+Dwarf_Addr
+dwarf_expr_into_block(Dwarf_P_Expr expr,
+ Dwarf_Unsigned * length, Dwarf_Error * error)
+{
+ if (expr == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL);
+ return (DW_DLV_BADADDR);
+ }
+
+ if (expr->ex_dbg == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_BADADDR);
+ }
+
+ if (length != NULL)
+ *length = expr->ex_next_byte_offset;
+ /* The following cast from pointer to integer is ok as long as
+ Dwarf_Addr is at least as large as a pointer. Which is a
+ requirement of libdwarf so must be satisfied (some compilers
+ emit a warning about the following line). */
+ return ((Dwarf_Addr) & (expr->ex_byte_stream[0]));
+}
diff --git a/libdwarf/pro_expr.h b/libdwarf/pro_expr.h
new file mode 100644
index 0000000..202f2d3
--- /dev/null
+++ b/libdwarf/pro_expr.h
@@ -0,0 +1,45 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+#define MAXIMUM_LOC_EXPR_LENGTH 20
+
+struct Dwarf_P_Expr_s {
+ Dwarf_Small ex_byte_stream[MAXIMUM_LOC_EXPR_LENGTH];
+ Dwarf_P_Debug ex_dbg;
+ Dwarf_Unsigned ex_next_byte_offset;
+ Dwarf_Unsigned ex_reloc_sym_index;
+ Dwarf_Unsigned ex_reloc_offset;
+};
diff --git a/libdwarf/pro_finish.c b/libdwarf/pro_finish.c
new file mode 100644
index 0000000..43b0f29
--- /dev/null
+++ b/libdwarf/pro_finish.c
@@ -0,0 +1,56 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2011 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include "pro_incl.h"
+
+/* This routine deallocates all memory, and does some
+ finishing up */
+/*ARGSUSED*/ Dwarf_Unsigned
+dwarf_producer_finish(Dwarf_P_Debug dbg, Dwarf_Error * error)
+{
+ if (dbg->de_version_magic_number != PRO_VERSION_MAGIC) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_IA, DW_DLV_NOCOUNT);
+ }
+
+ /* this frees all blocks, then frees dbg. */
+ _dwarf_p_dealloc_all(dbg);
+ return 0;
+}
diff --git a/libdwarf/pro_forms.c b/libdwarf/pro_forms.c
new file mode 100644
index 0000000..ee1b98f
--- /dev/null
+++ b/libdwarf/pro_forms.c
@@ -0,0 +1,1161 @@
+/*
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2007-2010 David Anderson. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include "pro_incl.h"
+#include "pro_expr.h"
+
+#ifndef R_MIPS_NONE
+#define R_MIPS_NONE 0
+#endif
+
+
+/* Indicates no relocation needed. */
+#define NO_ELF_SYM_INDEX 0
+
+
+/* Adds an attribute to a die */
+extern void _dwarf_pro_add_at_to_die(Dwarf_P_Die die,
+ Dwarf_P_Attribute attr);
+
+/* This function adds an attribute whose value is
+ a target address to the given die. The attribute
+ is given the name provided by attr. The address
+ is given in pc_value. */
+
+static Dwarf_P_Attribute
+local_add_AT_address(Dwarf_P_Debug dbg,
+ Dwarf_P_Die ownerdie,
+ Dwarf_Half attr,
+ Dwarf_Signed form,
+ Dwarf_Unsigned pc_value,
+ Dwarf_Unsigned sym_index,
+ Dwarf_Error * error);
+
+/* old interface */
+Dwarf_P_Attribute
+dwarf_add_AT_targ_address(Dwarf_P_Debug dbg,
+ Dwarf_P_Die ownerdie,
+ Dwarf_Half attr,
+ Dwarf_Unsigned pc_value,
+ Dwarf_Signed sym_index, Dwarf_Error * error)
+{
+ return
+ dwarf_add_AT_targ_address_b(dbg,
+ ownerdie,
+ attr,
+ pc_value,
+ (Dwarf_Unsigned) sym_index, error);
+}
+
+/* New interface, replacing dwarf_add_AT_targ_address.
+ Essentially just makes sym_index a Dwarf_Unsigned
+ so for symbolic relocations it can be a full address. */
+Dwarf_P_Attribute
+dwarf_add_AT_targ_address_b(Dwarf_P_Debug dbg,
+ Dwarf_P_Die ownerdie,
+ Dwarf_Half attr,
+ Dwarf_Unsigned pc_value,
+ Dwarf_Unsigned sym_index,
+ Dwarf_Error * error)
+{
+ switch (attr) {
+ case DW_AT_low_pc:
+ case DW_AT_high_pc:
+
+ /* added to support location lists */
+ /* no way to check that this is a loclist-style address though */
+ case DW_AT_location:
+ case DW_AT_string_length:
+ case DW_AT_return_addr:
+ case DW_AT_frame_base:
+ case DW_AT_segment:
+ case DW_AT_static_link:
+ case DW_AT_use_location:
+ case DW_AT_vtable_elem_location:
+ case DW_AT_const_value: /* Gcc can generate this as address. */
+ case DW_AT_entry_pc:
+ break;
+ default:
+ if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) {
+ _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+ break;
+ }
+
+ return local_add_AT_address(dbg, ownerdie, attr, DW_FORM_addr,
+ pc_value, sym_index, error);
+}
+
+Dwarf_P_Attribute
+dwarf_add_AT_ref_address(Dwarf_P_Debug dbg,
+ Dwarf_P_Die ownerdie,
+ Dwarf_Half attr,
+ Dwarf_Unsigned pc_value,
+ Dwarf_Unsigned sym_index,
+ Dwarf_Error * error)
+{
+ switch (attr) {
+ case DW_AT_type:
+ case DW_AT_import:
+ break;
+
+ default:
+ if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) {
+ _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+ break;
+ }
+
+ return local_add_AT_address(dbg, ownerdie, attr, DW_FORM_ref_addr,
+ pc_value, sym_index, error);
+}
+
+
+/* Make sure attribute types are checked before entering here. */
+static Dwarf_P_Attribute
+local_add_AT_address(Dwarf_P_Debug dbg,
+ Dwarf_P_Die ownerdie,
+ Dwarf_Half attr,
+ Dwarf_Signed form,
+ Dwarf_Unsigned pc_value,
+ Dwarf_Unsigned sym_index,
+ Dwarf_Error * error)
+{
+ Dwarf_P_Attribute new_attr;
+ int upointer_size = dbg->de_pointer_size;
+
+ if (dbg == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ if (ownerdie == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ /* attribute types have already been checked */
+ /* switch (attr) { ... } */
+
+ new_attr = (Dwarf_P_Attribute)
+ _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
+ if (new_attr == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ new_attr->ar_attribute = attr;
+ new_attr->ar_attribute_form = form;
+ new_attr->ar_nbytes = upointer_size;
+ new_attr->ar_rel_symidx = sym_index;
+ new_attr->ar_reloc_len = upointer_size;
+ new_attr->ar_next = 0;
+ if (sym_index != NO_ELF_SYM_INDEX)
+ new_attr->ar_rel_type = dbg->de_ptr_reloc;
+ else
+ new_attr->ar_rel_type = R_MIPS_NONE;
+
+ new_attr->ar_data = (char *)
+ _dwarf_p_get_alloc(dbg, upointer_size);
+ if (new_attr->ar_data == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+ WRITE_UNALIGNED(dbg, new_attr->ar_data,
+ (const void *) &pc_value,
+ sizeof(pc_value), upointer_size);
+
+ /* add attribute to the die */
+ _dwarf_pro_add_at_to_die(ownerdie, new_attr);
+ return new_attr;
+}
+
+/* Functions to compress and uncompress data from normal
+ arrays of integral types into arrays of LEB128 numbers.
+ Extend these functions as needed to handle wider input
+ variety. Return values should be freed with _dwarf_p_dealloc
+ after they aren't needed any more. */
+
+/* return value points to an array of LEB number */
+
+void *
+dwarf_compress_integer_block(
+ Dwarf_P_Debug dbg,
+ Dwarf_Bool unit_is_signed,
+ Dwarf_Small unit_length_in_bits,
+ void* input_block,
+ Dwarf_Unsigned input_length_in_units,
+ Dwarf_Unsigned* output_length_in_bytes_ptr,
+ Dwarf_Error* error
+)
+{
+ Dwarf_Unsigned output_length_in_bytes = 0;
+ char * output_block = 0;
+ char encode_buffer[ENCODE_SPACE_NEEDED];
+ int i = 0;
+ char * ptr = 0;
+ int remain = 0;
+ int result = 0;
+
+ if (dbg == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
+ return((void *)DW_DLV_BADADDR);
+ }
+
+ if (unit_is_signed == false ||
+ unit_length_in_bits != 32 ||
+ input_block == NULL ||
+ input_length_in_units == 0 ||
+ output_length_in_bytes_ptr == NULL) {
+
+ _dwarf_p_error(NULL, error, DW_DLE_BADBITC);
+ return ((void *) DW_DLV_BADADDR);
+ }
+
+ /* At this point we assume the format is: signed 32 bit */
+
+ /* First compress everything to find the total size. */
+
+ output_length_in_bytes = 0;
+ for (i=0; i<input_length_in_units; i++) {
+ int unit_encoded_size;
+ Dwarf_sfixed unit; /* this is fixed at signed-32-bits */
+
+ unit = ((Dwarf_sfixed*)input_block)[i];
+
+ result = _dwarf_pro_encode_signed_leb128_nm(unit, &unit_encoded_size,
+ encode_buffer,sizeof(encode_buffer));
+ if (result != DW_DLV_OK) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return((Dwarf_P_Attribute)DW_DLV_BADADDR);
+ }
+ output_length_in_bytes += unit_encoded_size;
+ }
+
+
+ /* Then alloc */
+
+ output_block = (void *)
+ _dwarf_p_get_alloc(dbg, output_length_in_bytes);
+ if (output_block == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return((void*)DW_DLV_BADADDR);
+ }
+
+ /* Then compress again and copy into new buffer */
+
+ ptr = output_block;
+ remain = output_length_in_bytes;
+ for (i=0; i<input_length_in_units; i++) {
+ int unit_encoded_size;
+ Dwarf_sfixed unit; /* this is fixed at signed-32-bits */
+
+ unit = ((Dwarf_sfixed*)input_block)[i];
+
+ result = _dwarf_pro_encode_signed_leb128_nm(unit, &unit_encoded_size,
+ ptr, remain);
+ if (result != DW_DLV_OK) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return((Dwarf_P_Attribute)DW_DLV_BADADDR);
+ }
+ remain -= unit_encoded_size;
+ ptr += unit_encoded_size;
+ }
+
+ if (remain != 0) {
+ _dwarf_p_dealloc(dbg, (unsigned char *)output_block);
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return((Dwarf_P_Attribute)DW_DLV_BADADDR);
+ }
+
+ *output_length_in_bytes_ptr = output_length_in_bytes;
+ return (void*) output_block;
+
+}
+
+void
+dwarf_dealloc_compressed_block(Dwarf_P_Debug dbg, void * space)
+{
+ _dwarf_p_dealloc(dbg, space);
+}
+
+/* This is very similar to targ_address but results in a different FORM */
+/* dbg->de_ar_data_attribute_form is data4 or data8
+ and dwarf4 changes the definition for such on DW_AT_high_pc.
+ DWARF 3: the FORM here has no defined meaning for dwarf3.
+ DWARF 4: the FORM here means that for DW_AT_high_pc the value
+ is not a high address but is instead an offset
+ from a (separate) DW_AT_low_pc.
+ The intent for DWARF4 is that this is not a relocated
+ address at all. Instead a simple offset.
+ But this should NOT be called for a simple non-relocated offset.
+ So do not call this with an attr of DW_AT_high_pc.
+ Use dwarf_add_AT_unsigned_const() (for example) instead of
+ dwarf_add_AT_dataref when the value is a simple offset . */
+Dwarf_P_Attribute
+dwarf_add_AT_dataref(
+ Dwarf_P_Debug dbg,
+ Dwarf_P_Die ownerdie,
+ Dwarf_Half attr,
+ Dwarf_Unsigned pc_value,
+ Dwarf_Unsigned sym_index,
+ Dwarf_Error * error)
+{
+ /* TODO: Add checking here */
+ return local_add_AT_address(dbg, ownerdie, attr,
+ dbg->de_ar_data_attribute_form,
+ pc_value,
+ sym_index,
+ error);
+}
+
+
+
+Dwarf_P_Attribute
+dwarf_add_AT_block(
+ Dwarf_P_Debug dbg,
+ Dwarf_P_Die ownerdie,
+ Dwarf_Half attr,
+ Dwarf_Small *block_data,
+ Dwarf_Unsigned block_size,
+ Dwarf_Error *error
+)
+{
+ Dwarf_P_Attribute new_attr = 0;
+ int result = 0;
+ char encode_buffer[ENCODE_SPACE_NEEDED];
+ int len_size = 0;
+ char * attrdata = 0;
+
+ if (dbg == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
+ return((Dwarf_P_Attribute)DW_DLV_BADADDR);
+ }
+
+ if (ownerdie == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
+ return((Dwarf_P_Attribute)DW_DLV_BADADDR);
+ }
+
+ /* I don't mess with block1, block2, block4, not worth the effort */
+
+ /* So, encode the length into LEB128 */
+ result = _dwarf_pro_encode_leb128_nm(block_size, &len_size,
+ encode_buffer,sizeof(encode_buffer));
+ if (result != DW_DLV_OK) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return((Dwarf_P_Attribute)DW_DLV_BADADDR);
+ }
+
+ /* Allocate the new attribute */
+ new_attr = (Dwarf_P_Attribute)
+ _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
+ if (new_attr == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return((Dwarf_P_Attribute)DW_DLV_BADADDR);
+ }
+
+ /* Fill in the attribute */
+ new_attr->ar_attribute = attr;
+ new_attr->ar_attribute_form = DW_FORM_block;
+ new_attr->ar_nbytes = len_size + block_size;
+ new_attr->ar_next = 0;
+
+ new_attr->ar_data = attrdata = (char *)
+ _dwarf_p_get_alloc(dbg, len_size + block_size);
+ if (new_attr->ar_data == NULL) {
+ /* free the block we got earlier */
+ _dwarf_p_dealloc(dbg, (unsigned char *) new_attr);
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return((Dwarf_P_Attribute)DW_DLV_BADADDR);
+ }
+
+ /* write length and data to attribute data buffer */
+ memcpy(attrdata, encode_buffer, len_size);
+ attrdata += len_size;
+ memcpy(attrdata, block_data, block_size);
+
+ /* add attribute to the die */
+ _dwarf_pro_add_at_to_die(ownerdie, new_attr);
+
+ return new_attr;
+}
+
+
+/*
+ This function adds attributes whose value
+ is an unsigned constant. It determines the
+ size of the value field from the value of
+ the constant.
+*/
+Dwarf_P_Attribute
+dwarf_add_AT_unsigned_const(Dwarf_P_Debug dbg,
+ Dwarf_P_Die ownerdie,
+ Dwarf_Half attr,
+ Dwarf_Unsigned value, Dwarf_Error * error)
+{
+ Dwarf_P_Attribute new_attr = 0;
+ Dwarf_Half attr_form = 0;
+ Dwarf_Small size = 0;
+
+ if (dbg == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ if (ownerdie == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ switch (attr) {
+ case DW_AT_ordering:
+ case DW_AT_byte_size:
+ case DW_AT_bit_offset:
+ case DW_AT_bit_size:
+ case DW_AT_inline:
+ case DW_AT_language:
+ case DW_AT_visibility:
+ case DW_AT_virtuality:
+ case DW_AT_accessibility:
+ case DW_AT_address_class:
+ case DW_AT_calling_convention:
+ case DW_AT_encoding:
+ case DW_AT_identifier_case:
+ case DW_AT_MIPS_loop_unroll_factor:
+ case DW_AT_MIPS_software_pipeline_depth:
+ break;
+
+ case DW_AT_decl_column:
+ case DW_AT_decl_file:
+ case DW_AT_decl_line:
+ case DW_AT_const_value:
+ case DW_AT_start_scope:
+ case DW_AT_stride_size:
+ case DW_AT_count:
+ case DW_AT_associated:
+ case DW_AT_allocated:
+ case DW_AT_upper_bound:
+ case DW_AT_lower_bound:
+ case DW_AT_call_file:
+ case DW_AT_call_line:
+ break;
+
+ default:
+ if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) {
+ _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+ break;
+ }
+
+ /* Compute the number of bytes needed to hold constant. */
+ if (value <= UCHAR_MAX) {
+ attr_form = DW_FORM_data1;
+ size = 1;
+ } else if (value <= USHRT_MAX) {
+ attr_form = DW_FORM_data2;
+ size = 2;
+ } else if (value <= UINT_MAX) {
+ attr_form = DW_FORM_data4;
+ size = 4;
+ } else {
+ attr_form = DW_FORM_data8;
+ size = 8;
+ }
+
+ new_attr = (Dwarf_P_Attribute)
+ _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
+ if (new_attr == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ new_attr->ar_attribute = attr;
+ new_attr->ar_attribute_form = attr_form;
+ new_attr->ar_rel_type = R_MIPS_NONE;
+ new_attr->ar_reloc_len = 0; /* irrelevant: unused with R_MIPS_NONE */
+ new_attr->ar_nbytes = size;
+ new_attr->ar_next = 0;
+
+ new_attr->ar_data = (char *)
+ _dwarf_p_get_alloc(dbg, size);
+ if (new_attr->ar_data == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+ WRITE_UNALIGNED(dbg, new_attr->ar_data,
+ (const void *) &value, sizeof(value), size);
+
+ /* add attribute to the die */
+ _dwarf_pro_add_at_to_die(ownerdie, new_attr);
+ return new_attr;
+}
+
+
+/* This function adds attributes whose value
+ is an signed constant. It determines the
+ size of the value field from the value of
+ the constant. */
+Dwarf_P_Attribute
+dwarf_add_AT_signed_const(Dwarf_P_Debug dbg,
+ Dwarf_P_Die ownerdie,
+ Dwarf_Half attr,
+ Dwarf_Signed value, Dwarf_Error * error)
+{
+ Dwarf_P_Attribute new_attr = 0;
+ Dwarf_Half attr_form = 0;
+ Dwarf_Small size = 0;
+
+ if (dbg == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ if (ownerdie == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ switch (attr) {
+ case DW_AT_lower_bound:
+ case DW_AT_upper_bound:
+ case DW_AT_const_value:
+ case DW_AT_bit_offset:
+ case DW_AT_bit_size:
+ case DW_AT_byte_size:
+ case DW_AT_count:
+ case DW_AT_byte_stride:
+ case DW_AT_bit_stride:
+ case DW_AT_allocated:
+ case DW_AT_associated:
+ break;
+
+ default:
+ if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) {
+ _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+ break;
+ }
+
+ /* Compute the number of bytes needed to hold constant. */
+ if (value >= SCHAR_MIN && value <= SCHAR_MAX) {
+ attr_form = DW_FORM_data1;
+ size = 1;
+ } else if (value >= SHRT_MIN && value <= SHRT_MAX) {
+ attr_form = DW_FORM_data2;
+ size = 2;
+ } else if (value >= INT_MIN && value <= INT_MAX) {
+ attr_form = DW_FORM_data4;
+ size = 4;
+ } else {
+ attr_form = DW_FORM_data8;
+ size = 8;
+ }
+
+ new_attr = (Dwarf_P_Attribute)
+ _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
+ if (new_attr == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ new_attr->ar_attribute = attr;
+ new_attr->ar_attribute_form = attr_form;
+ new_attr->ar_rel_type = R_MIPS_NONE;
+ new_attr->ar_reloc_len = 0; /* irrelevant: unused with R_MIPS_NONE */
+ new_attr->ar_nbytes = size;
+ new_attr->ar_next = 0;
+
+ new_attr->ar_data = (char *)
+ _dwarf_p_get_alloc(dbg, size);
+ if (new_attr->ar_data == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+ WRITE_UNALIGNED(dbg, new_attr->ar_data,
+ (const void *) &value, sizeof(value), size);
+
+ /* add attribute to the die */
+ _dwarf_pro_add_at_to_die(ownerdie, new_attr);
+ return new_attr;
+}
+
+
+/* This function adds attributes whose value
+ is a location expression. */
+Dwarf_P_Attribute
+dwarf_add_AT_location_expr(Dwarf_P_Debug dbg,
+ Dwarf_P_Die ownerdie,
+ Dwarf_Half attr,
+ Dwarf_P_Expr loc_expr, Dwarf_Error * error)
+{
+ char encode_buffer[ENCODE_SPACE_NEEDED];
+ int res = 0;
+ Dwarf_P_Attribute new_attr = 0;
+ Dwarf_Half attr_form = 0;
+ char *len_str = 0;
+ int len_size = 0;
+ int block_size = 0;
+ char *block_dest_ptr = 0;
+ int do_len_as_int = 0;
+
+ if (dbg == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ if (ownerdie == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ if (loc_expr == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_EXPR_NULL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ if (loc_expr->ex_dbg != dbg) {
+ _dwarf_p_error(dbg, error, DW_DLE_LOC_EXPR_BAD);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+ block_size = loc_expr->ex_next_byte_offset;
+
+ switch (attr) {
+ case DW_AT_location:
+ case DW_AT_string_length:
+ case DW_AT_const_value:
+ case DW_AT_use_location:
+ case DW_AT_return_addr:
+ case DW_AT_data_member_location:
+ case DW_AT_frame_base:
+ case DW_AT_static_link:
+ case DW_AT_vtable_elem_location:
+ case DW_AT_lower_bound:
+ case DW_AT_upper_bound:
+ case DW_AT_count:
+ case DW_AT_associated:
+ case DW_AT_allocated:
+ case DW_AT_data_location:
+ case DW_AT_byte_stride:
+ case DW_AT_bit_stride:
+ case DW_AT_byte_size:
+ case DW_AT_bit_size:
+ break;
+
+ default:
+ if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) {
+ _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+ break;
+ }
+
+ /* Compute the number of bytes needed to hold constant. */
+ if (block_size <= UCHAR_MAX) {
+ attr_form = DW_FORM_block1;
+ len_size = 1;
+ do_len_as_int = 1;
+ } else if (block_size <= USHRT_MAX) {
+ attr_form = DW_FORM_block2;
+ len_size = 2;
+ do_len_as_int = 1;
+ } else if (block_size <= UINT_MAX) {
+ attr_form = DW_FORM_block4;
+ len_size = 4;
+ do_len_as_int = 1;
+ } else {
+ attr_form = DW_FORM_block;
+ res = _dwarf_pro_encode_leb128_nm(block_size, &len_size,
+ encode_buffer,
+ sizeof(encode_buffer));
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+ len_str = (char *) encode_buffer;
+ }
+
+ new_attr = (Dwarf_P_Attribute)
+ _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
+ if (new_attr == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ new_attr->ar_attribute = attr;
+ new_attr->ar_attribute_form = attr_form;
+ new_attr->ar_reloc_len = dbg->de_pointer_size;
+ if (loc_expr->ex_reloc_sym_index != NO_ELF_SYM_INDEX) {
+ new_attr->ar_rel_type = dbg->de_ptr_reloc;
+ } else {
+ new_attr->ar_rel_type = R_MIPS_NONE;
+ }
+ new_attr->ar_rel_symidx = loc_expr->ex_reloc_sym_index;
+ new_attr->ar_rel_offset =
+ (Dwarf_Word) loc_expr->ex_reloc_offset + len_size;
+
+ new_attr->ar_nbytes = block_size + len_size;
+
+ new_attr->ar_next = 0;
+ new_attr->ar_data = block_dest_ptr =
+ (char *) _dwarf_p_get_alloc(dbg, block_size + len_size);
+ if (new_attr->ar_data == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ if (do_len_as_int) {
+ WRITE_UNALIGNED(dbg, block_dest_ptr, (const void *) &block_size,
+ sizeof(block_size), len_size);
+ } else {
+ /* Is uleb number form, DW_FORM_block. See above. */
+ memcpy(block_dest_ptr, len_str, len_size);
+ }
+ block_dest_ptr += len_size;
+ memcpy(block_dest_ptr, &(loc_expr->ex_byte_stream[0]), block_size);
+
+ /* add attribute to the die */
+ _dwarf_pro_add_at_to_die(ownerdie, new_attr);
+ return new_attr;
+}
+
+
+/* This function adds attributes of reference class.
+ The references here are local CU references,
+ not DW_FORM_ref_addr.
+ The offset field is 4 bytes for 32-bit objects,
+ and 8-bytes for 64-bit objects. Otherdie is the
+ that is referenced by ownerdie.
+
+ For reference attributes, the ar_data and ar_nbytes
+ are not needed. Instead, the ar_ref_die points to
+ the other die, and its di_offset value is used as
+ the reference value. */
+Dwarf_P_Attribute
+dwarf_add_AT_reference(Dwarf_P_Debug dbg,
+ Dwarf_P_Die ownerdie,
+ Dwarf_Half attr,
+ Dwarf_P_Die otherdie, Dwarf_Error * error)
+{
+ Dwarf_P_Attribute new_attr;
+
+ if (dbg == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ if (ownerdie == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ if (otherdie == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ switch (attr) {
+ case DW_AT_specification:
+ case DW_AT_discr:
+ case DW_AT_common_reference:
+ case DW_AT_import:
+ case DW_AT_containing_type:
+ case DW_AT_default_value:
+ case DW_AT_abstract_origin:
+ case DW_AT_friend:
+ case DW_AT_priority:
+ case DW_AT_type:
+ case DW_AT_lower_bound:
+ case DW_AT_upper_bound:
+ case DW_AT_count:
+ case DW_AT_associated:
+ case DW_AT_allocated:
+ case DW_AT_bit_offset:
+ case DW_AT_bit_size:
+ case DW_AT_byte_size:
+ case DW_AT_sibling:
+ case DW_AT_bit_stride:
+ case DW_AT_byte_stride:
+ case DW_AT_namelist_item:
+ break;
+
+ default:
+ if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) {
+ _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+ break;
+ }
+
+ new_attr = (Dwarf_P_Attribute)
+ _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
+ if (new_attr == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ new_attr->ar_attribute = attr;
+ new_attr->ar_attribute_form = dbg->de_ar_ref_attr_form;
+ new_attr->ar_nbytes = dbg->de_offset_size;
+ new_attr->ar_reloc_len = dbg->de_offset_size;
+ new_attr->ar_ref_die = otherdie;
+ new_attr->ar_rel_type = R_MIPS_NONE;
+ new_attr->ar_next = 0;
+
+ /* Add attribute to the die */
+ _dwarf_pro_add_at_to_die(ownerdie, new_attr);
+ return new_attr;
+}
+
+
+/* This function adds attributes of the flag class. */
+Dwarf_P_Attribute
+dwarf_add_AT_flag(Dwarf_P_Debug dbg,
+ Dwarf_P_Die ownerdie,
+ Dwarf_Half attr,
+ Dwarf_Small flag, Dwarf_Error * error)
+{
+ Dwarf_P_Attribute new_attr = 0;
+
+ if (dbg == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ if (ownerdie == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+#if 0
+ switch (attr) {
+ case DW_AT_is_optional:
+ case DW_AT_artificial:
+ case DW_AT_declaration:
+ case DW_AT_external:
+ case DW_AT_prototyped:
+ case DW_AT_variable_parameter:
+ break;
+
+ default:
+ if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) {
+ _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+ break;
+ }
+#endif
+
+ new_attr = (Dwarf_P_Attribute)
+ _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
+ if (new_attr == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ new_attr->ar_attribute = attr;
+ new_attr->ar_attribute_form = DW_FORM_flag;
+ new_attr->ar_nbytes = 1;
+ new_attr->ar_reloc_len = 0; /* not used */
+ new_attr->ar_rel_type = R_MIPS_NONE;
+ new_attr->ar_next = 0;
+
+ new_attr->ar_data = (char *)
+ _dwarf_p_get_alloc(dbg, 1);
+ if (new_attr->ar_data == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+ memcpy(new_attr->ar_data, &flag, 1);
+
+ /* Add attribute to the die */
+ _dwarf_pro_add_at_to_die(ownerdie, new_attr);
+ return new_attr;
+}
+
+
+/* This function adds values of attributes
+ belonging to the string class. */
+Dwarf_P_Attribute
+dwarf_add_AT_string(Dwarf_P_Debug dbg,
+ Dwarf_P_Die ownerdie,
+ Dwarf_Half attr, char *string, Dwarf_Error * error)
+{
+ Dwarf_P_Attribute new_attr;
+
+ if (dbg == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ if (ownerdie == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ new_attr = (Dwarf_P_Attribute)
+ _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
+ if (new_attr == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ switch (attr) {
+ case DW_AT_name:
+ case DW_AT_comp_dir:
+ case DW_AT_const_value:
+ case DW_AT_producer:
+ break;
+
+ default:
+ if ( attr < DW_AT_lo_user || attr > DW_AT_hi_user ) {
+ _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+ break;
+ }
+
+ new_attr->ar_attribute = attr;
+ new_attr->ar_attribute_form = DW_FORM_string;
+ new_attr->ar_nbytes = strlen(string) + 1;
+ new_attr->ar_next = 0;
+
+ new_attr->ar_data =
+ (char *) _dwarf_p_get_alloc(dbg, strlen(string)+1);
+ if (new_attr->ar_data == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ strcpy(new_attr->ar_data, string);
+ new_attr->ar_rel_type = R_MIPS_NONE;
+ new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */
+
+ /* add attribute to the die */
+ _dwarf_pro_add_at_to_die(ownerdie, new_attr);
+ return new_attr;
+}
+
+
+Dwarf_P_Attribute
+dwarf_add_AT_const_value_string(Dwarf_P_Die ownerdie,
+ char *string_value, Dwarf_Error * error)
+{
+ Dwarf_P_Attribute new_attr;
+
+ if (ownerdie == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_DIE_NULL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ new_attr = (Dwarf_P_Attribute)
+ _dwarf_p_get_alloc(ownerdie->di_dbg, sizeof(struct Dwarf_P_Attribute_s));
+ if (new_attr == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ new_attr->ar_attribute = DW_AT_const_value;
+ new_attr->ar_attribute_form = DW_FORM_string;
+ new_attr->ar_nbytes = strlen(string_value) + 1;
+ new_attr->ar_next = 0;
+
+ new_attr->ar_data =
+ (char *) _dwarf_p_get_alloc(ownerdie->di_dbg, strlen(string_value)+1);
+ if (new_attr->ar_data == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ strcpy(new_attr->ar_data, string_value);
+ new_attr->ar_rel_type = R_MIPS_NONE;
+ new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */
+
+ /* add attribute to the die */
+ _dwarf_pro_add_at_to_die(ownerdie, new_attr);
+ return new_attr;
+}
+
+
+Dwarf_P_Attribute
+dwarf_add_AT_producer(Dwarf_P_Die ownerdie,
+ char *producer_string, Dwarf_Error * error)
+{
+ Dwarf_P_Attribute new_attr;
+
+ if (ownerdie == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_DIE_NULL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ new_attr = (Dwarf_P_Attribute)
+ _dwarf_p_get_alloc(ownerdie->di_dbg, sizeof(struct Dwarf_P_Attribute_s));
+ if (new_attr == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ new_attr->ar_attribute = DW_AT_producer;
+ new_attr->ar_attribute_form = DW_FORM_string;
+ new_attr->ar_nbytes = strlen(producer_string) + 1;
+ new_attr->ar_next = 0;
+
+ new_attr->ar_data =
+ (char *) _dwarf_p_get_alloc(ownerdie->di_dbg, strlen(producer_string)+1);
+ if (new_attr->ar_data == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ strcpy(new_attr->ar_data, producer_string);
+ new_attr->ar_rel_type = R_MIPS_NONE;
+ new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */
+
+ /* add attribute to the die */
+ _dwarf_pro_add_at_to_die(ownerdie, new_attr);
+ return new_attr;
+}
+
+
+Dwarf_P_Attribute
+dwarf_add_AT_const_value_signedint(Dwarf_P_Die ownerdie,
+ Dwarf_Signed signed_value,
+ Dwarf_Error * error)
+{
+ Dwarf_P_Attribute new_attr = 0;
+ int leb_size = 0;
+ char encode_buffer[ENCODE_SPACE_NEEDED];
+ int res = 0;
+
+ if (ownerdie == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_DIE_NULL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ new_attr = (Dwarf_P_Attribute)
+ _dwarf_p_get_alloc(ownerdie->di_dbg, sizeof(struct Dwarf_P_Attribute_s));
+ if (new_attr == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ new_attr->ar_attribute = DW_AT_const_value;
+ new_attr->ar_attribute_form = DW_FORM_sdata;
+ new_attr->ar_rel_type = R_MIPS_NONE;
+ new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */
+ new_attr->ar_next = 0;
+
+ res = _dwarf_pro_encode_signed_leb128_nm(signed_value, &leb_size,
+ encode_buffer,
+ sizeof(encode_buffer));
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+ new_attr->ar_data = (char *)
+ _dwarf_p_get_alloc(ownerdie->di_dbg, leb_size);
+ if (new_attr->ar_data == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+ memcpy(new_attr->ar_data, encode_buffer, leb_size);
+ new_attr->ar_nbytes = leb_size;
+
+ /* add attribute to the die */
+ _dwarf_pro_add_at_to_die(ownerdie, new_attr);
+ return new_attr;
+}
+
+
+Dwarf_P_Attribute
+dwarf_add_AT_const_value_unsignedint(Dwarf_P_Die ownerdie,
+ Dwarf_Unsigned unsigned_value,
+ Dwarf_Error * error)
+{
+ Dwarf_P_Attribute new_attr;
+ int leb_size;
+ char encode_buffer[ENCODE_SPACE_NEEDED];
+ int res;
+
+ if (ownerdie == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_DIE_NULL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ new_attr = (Dwarf_P_Attribute)
+ _dwarf_p_get_alloc(ownerdie->di_dbg, sizeof(struct Dwarf_P_Attribute_s));
+ if (new_attr == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+
+ new_attr->ar_attribute = DW_AT_const_value;
+ new_attr->ar_attribute_form = DW_FORM_udata;
+ new_attr->ar_rel_type = R_MIPS_NONE;
+ new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */
+ new_attr->ar_next = 0;
+
+ res = _dwarf_pro_encode_leb128_nm(unsigned_value, &leb_size,
+ encode_buffer,
+ sizeof(encode_buffer));
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+ new_attr->ar_data = (char *)
+ _dwarf_p_get_alloc(ownerdie->di_dbg, leb_size);
+ if (new_attr->ar_data == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
+ return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
+ }
+ memcpy(new_attr->ar_data, encode_buffer, leb_size);
+ new_attr->ar_nbytes = leb_size;
+
+ /* add attribute to the die */
+ _dwarf_pro_add_at_to_die(ownerdie, new_attr);
+ return new_attr;
+}
diff --git a/libdwarf/pro_frame.c b/libdwarf/pro_frame.c
new file mode 100644
index 0000000..d43f292
--- /dev/null
+++ b/libdwarf/pro_frame.c
@@ -0,0 +1,582 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include "pro_incl.h"
+#include "pro_frame.h"
+
+static void _dwarf_pro_add_to_fde(Dwarf_P_Fde fde,
+ Dwarf_P_Frame_Pgm inst);
+
+/* This function adds a cie struct to the debug pointer. Its in the
+ form of a linked list.
+ augmenter: string reps augmentation (implementation defined)
+ code_align: alignment of code
+ data_align: alignment of data
+ init_bytes: byts having initial instructions
+ init_n_bytes: number of bytes of initial instructions */
+Dwarf_Unsigned
+dwarf_add_frame_cie(Dwarf_P_Debug dbg,
+ char *augmenter,
+ Dwarf_Small code_align,
+ Dwarf_Small data_align,
+ Dwarf_Small return_reg,
+ Dwarf_Ptr init_bytes,
+ Dwarf_Unsigned init_n_bytes, Dwarf_Error * error)
+{
+ Dwarf_P_Cie curcie;
+
+ if (dbg->de_frame_cies == NULL) {
+ dbg->de_frame_cies = (Dwarf_P_Cie)
+ _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Cie_s));
+ if (dbg->de_frame_cies == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_ALLOC, DW_DLV_NOCOUNT);
+ }
+ curcie = dbg->de_frame_cies;
+ dbg->de_n_cie = 1;
+ dbg->de_last_cie = curcie;
+ } else {
+ curcie = dbg->de_last_cie;
+ curcie->cie_next = (Dwarf_P_Cie)
+ _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Cie_s));
+ if (curcie->cie_next == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_ALLOC, DW_DLV_NOCOUNT);
+ }
+ curcie = curcie->cie_next;
+ dbg->de_n_cie++;
+ dbg->de_last_cie = curcie;
+ }
+ curcie->cie_version = DW_CIE_VERSION;
+ curcie->cie_aug = augmenter;
+ curcie->cie_code_align = code_align;
+ curcie->cie_data_align = data_align;
+ curcie->cie_ret_reg = return_reg;
+ curcie->cie_inst = (char *) init_bytes;
+ curcie->cie_inst_bytes = (long) init_n_bytes;
+ curcie->cie_next = NULL;
+ return dbg->de_n_cie;
+}
+
+
+/* This functions adds a fde struct to the debug pointer. Its in the
+ form of a linked list.
+ die: subprogram/function die corresponding to this fde
+ cie: cie referred to by this fde, obtained from call to
+ add_frame_cie() routine.
+ virt_addr: beginning address
+ code_len: length of code reps by the fde */
+/*ARGSUSED*/ /* pretend all args used */
+Dwarf_Unsigned
+dwarf_add_frame_fde(Dwarf_P_Debug dbg,
+ Dwarf_P_Fde fde,
+ Dwarf_P_Die die,
+ Dwarf_Unsigned cie,
+ Dwarf_Unsigned virt_addr,
+ Dwarf_Unsigned code_len,
+ Dwarf_Unsigned symidx, Dwarf_Error * error)
+{
+ return dwarf_add_frame_fde_b(dbg, fde, die, cie, virt_addr,
+ code_len, symidx, 0, 0, error);
+}
+
+/*ARGSUSED10*/
+Dwarf_Unsigned
+dwarf_add_frame_fde_b(Dwarf_P_Debug dbg,
+ Dwarf_P_Fde fde,
+ Dwarf_P_Die die,
+ Dwarf_Unsigned cie,
+ Dwarf_Unsigned virt_addr,
+ Dwarf_Unsigned code_len,
+ Dwarf_Unsigned symidx,
+ Dwarf_Unsigned symidx_of_end,
+ Dwarf_Addr offset_from_end_sym,
+ Dwarf_Error * error)
+{
+ Dwarf_P_Fde curfde;
+
+ fde->fde_die = die;
+ fde->fde_cie = (long) cie;
+ fde->fde_initloc = virt_addr;
+ fde->fde_r_symidx = symidx;
+ fde->fde_addr_range = code_len;
+ fde->fde_offset_into_exception_tables = DW_DLX_NO_EH_OFFSET;
+ fde->fde_exception_table_symbol = 0;
+ fde->fde_end_symbol_offset = offset_from_end_sym;
+ fde->fde_end_symbol = symidx_of_end;
+ fde->fde_dbg = dbg;
+
+ curfde = dbg->de_last_fde;
+ if (curfde == NULL) {
+ dbg->de_frame_fdes = fde;
+ dbg->de_last_fde = fde;
+ dbg->de_n_fde = 1;
+ } else {
+ curfde->fde_next = fde;
+ dbg->de_last_fde = fde;
+ dbg->de_n_fde++;
+ }
+ return dbg->de_n_fde;
+}
+
+/* This function adds information to an fde. The fde is
+ linked into the linked list of fde's maintained in the Dwarf_P_Debug
+ structure.
+ dbg: The debug descriptor.
+ fde: The fde to be added.
+ die: subprogram/function die corresponding to this fde
+ cie: cie referred to by this fde, obtained from call to
+ add_frame_cie() routine.
+ virt_addr: beginning address
+ code_len: length of code reps by the fde
+ symidx: The symbol id of the symbol wrt to which relocation needs
+ to be performed for 'virt_addr'.
+ offset_into_exception_tables: The start of exception tables for
+ this function (indicated as an offset into the exception
+ tables). A value of -1 indicates that there is no exception
+ table entries associated with this function.
+ exception_table_symbol: The symbol id of the section for exception
+ tables wrt to which the offset_into_exception_tables will
+ be relocated. */
+Dwarf_Unsigned
+dwarf_add_frame_info(Dwarf_P_Debug dbg,
+ Dwarf_P_Fde fde,
+ Dwarf_P_Die die,
+ Dwarf_Unsigned cie,
+ Dwarf_Unsigned virt_addr,
+ Dwarf_Unsigned code_len,
+ Dwarf_Unsigned symidx,
+ Dwarf_Signed offset_into_exception_tables,
+ Dwarf_Unsigned exception_table_symbol,
+ Dwarf_Error * error)
+{
+
+ return dwarf_add_frame_info_b(dbg, fde, die, cie, virt_addr,
+ code_len, symidx,
+ /* end_symbol */ 0,
+ /* offset_from_end */ 0,
+ offset_into_exception_tables,
+ exception_table_symbol, error);
+
+}
+
+/*ARGSUSED*/ /* pretend all args used */
+Dwarf_Unsigned
+dwarf_add_frame_info_b(Dwarf_P_Debug dbg,
+ Dwarf_P_Fde fde,
+ Dwarf_P_Die die,
+ Dwarf_Unsigned cie,
+ Dwarf_Unsigned virt_addr,
+ Dwarf_Unsigned code_len,
+ Dwarf_Unsigned symidx,
+ Dwarf_Unsigned end_symidx,
+ Dwarf_Unsigned offset_from_end_symbol,
+ Dwarf_Signed offset_into_exception_tables,
+ Dwarf_Unsigned exception_table_symbol,
+ Dwarf_Error * error)
+{
+ Dwarf_P_Fde curfde;
+
+ fde->fde_die = die;
+ fde->fde_cie = (long) cie;
+ fde->fde_initloc = virt_addr;
+ fde->fde_r_symidx = symidx;
+ fde->fde_addr_range = code_len;
+ fde->fde_offset_into_exception_tables =
+ offset_into_exception_tables;
+ fde->fde_exception_table_symbol = exception_table_symbol;
+ fde->fde_end_symbol_offset = offset_from_end_symbol;
+ fde->fde_end_symbol = end_symidx;
+ fde->fde_dbg = dbg;
+
+ curfde = dbg->de_last_fde;
+ if (curfde == NULL) {
+ dbg->de_frame_fdes = fde;
+ dbg->de_last_fde = fde;
+ dbg->de_n_fde = 1;
+ } else {
+ curfde->fde_next = fde;
+ dbg->de_last_fde = fde;
+ dbg->de_n_fde++;
+ }
+ return dbg->de_n_fde;
+}
+
+/* This is an alternate to inserting frame instructions
+ one instruction at a time. But use either this
+ or instruction level, not both in one fde. */
+int
+dwarf_insert_fde_inst_bytes(Dwarf_P_Debug dbg,
+ Dwarf_P_Fde fde,Dwarf_Unsigned len, Dwarf_Ptr ibytes,
+ Dwarf_Error *error)
+{
+ if( len == 0) {
+ return DW_DLV_OK;
+ }
+ if(fde->fde_block || fde->fde_inst) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_DUPLICATE_INST_BLOCK,
+ (int)DW_DLV_BADADDR);
+ }
+ fde->fde_block = (Dwarf_Ptr)_dwarf_p_get_alloc(dbg, len);
+ memcpy(fde->fde_block,ibytes,len);
+ fde->fde_inst_block_size = len;
+ fde->fde_n_bytes += len;
+ return DW_DLV_OK;
+}
+
+
+
+/* Create a new fde. */
+Dwarf_P_Fde
+dwarf_new_fde(Dwarf_P_Debug dbg, Dwarf_Error * error)
+{
+ Dwarf_P_Fde fde;
+
+ fde = (Dwarf_P_Fde)
+ _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Fde_s));
+ if (fde == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_FDE_ALLOC,
+ (Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+ fde->fde_uwordb_size = dbg->de_offset_size;
+ return fde;
+}
+
+
+/* Add a cfe_offset instruction to the fde passed in. */
+Dwarf_P_Fde
+dwarf_fde_cfa_offset(Dwarf_P_Fde fde,
+ Dwarf_Unsigned reg,
+ Dwarf_Signed offset, Dwarf_Error * error)
+{
+ Dwarf_Ubyte opc, regno;
+ char *ptr = 0;
+ Dwarf_P_Frame_Pgm curinst;
+ int nbytes = 0;
+ int res = 0;
+ char buff1[ENCODE_SPACE_NEEDED];
+ Dwarf_P_Debug dbg = fde->fde_dbg;
+
+ curinst = (Dwarf_P_Frame_Pgm)
+ _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Frame_Pgm_s));
+ if (curinst == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_FPGM_ALLOC,
+ (Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+ opc = DW_CFA_offset;
+ regno = reg;
+ if (regno & 0xc0) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_REGNO_OVFL,
+ (Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+ opc = opc | regno; /* lower 6 bits are register number */
+ curinst->dfp_opcode = opc;
+ res = _dwarf_pro_encode_leb128_nm(offset, &nbytes,
+ buff1, sizeof(buff1));
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
+ return ((Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+ ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes);
+ if (ptr == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
+ return ((Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+ memcpy(ptr, buff1, nbytes);
+
+ curinst->dfp_args = ptr;
+ curinst->dfp_nbytes = nbytes;
+ curinst->dfp_next = NULL;
+
+ _dwarf_pro_add_to_fde(fde, curinst);
+ return fde;
+}
+
+/* Generic routine to add opcode to fde instructions. val1 and
+ val2 are parameters whose interpretation depends on the 'op'.
+
+ This does not work properly for DW_DLC_SYMBOLIC_RELOCATIONS
+ for DW_CFA_set_loc or DW_DVA_advance_loc* 'op', as
+ these ops normally are addresses or (DW_CFA_set_loc)
+ or code lengths (DW_DVA_advance_loc*) and such must be
+ represented with relocations and symbol indices for
+ DW_DLC_SYMBOLIC_RELOCATIONS.
+
+ This does not treat all DW_CFA instructions yet.
+
+ For certain operations a val? value must be
+ signed (though passed in as unsigned here).
+
+ Currently this does not check that the frame
+ version is 3(for dwarf3) or 4 (for dwarf4)
+ when applying operations that are only valid for
+ dwarf3 or dwarf4. */
+Dwarf_P_Fde
+dwarf_add_fde_inst(Dwarf_P_Fde fde,
+ Dwarf_Small op,
+ Dwarf_Unsigned val1,
+ Dwarf_Unsigned val2, Dwarf_Error * error)
+{
+ Dwarf_P_Frame_Pgm curinst;
+ int nbytes, nbytes1, nbytes2;
+ Dwarf_Ubyte db;
+ Dwarf_Half dh;
+ Dwarf_Word dw;
+ Dwarf_Unsigned du;
+ char *ptr;
+ int res;
+ char buff1[ENCODE_SPACE_NEEDED];
+ char buff2[ENCODE_SPACE_NEEDED];
+ Dwarf_P_Debug dbg = fde->fde_dbg;
+ /* This is a hack telling the code when to transform
+ a value to a signed leb number. */
+ int signed_second = 0;
+ int signed_first = 0;
+
+
+ nbytes = 0;
+ ptr = NULL;
+ curinst = (Dwarf_P_Frame_Pgm)
+ _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Frame_Pgm_s));
+ if (curinst == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_FPGM_ALLOC);
+ return ((Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+
+ switch (op) {
+
+ case DW_CFA_advance_loc:
+ if (val1 <= 0x3f) {
+ db = val1;
+ op |= db;
+ }
+ /* test not portable FIX */
+ else if (val1 <= UCHAR_MAX) {
+ op = DW_CFA_advance_loc1;
+ db = val1;
+ ptr = (char *) _dwarf_p_get_alloc(dbg, 1);
+ if (ptr == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
+ return ((Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+ memcpy((void *) ptr, (const void *) &db, 1);
+ nbytes = 1;
+ }
+ /* test not portable FIX */
+ else if (val1 <= USHRT_MAX) {
+ op = DW_CFA_advance_loc2;
+ dh = val1;
+ ptr = (char *) _dwarf_p_get_alloc(dbg, 2);
+ if (ptr == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
+ return ((Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+ memcpy((void *) ptr, (const void *) &dh, 2);
+ nbytes = 2;
+ }
+ /* test not portable FIX */
+ else if (val1 <= ULONG_MAX) {
+ op = DW_CFA_advance_loc4;
+ dw = (Dwarf_Word) val1;
+ ptr = (char *) _dwarf_p_get_alloc(dbg, 4);
+ if (ptr == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
+ return ((Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+ memcpy((void *) ptr, (const void *) &dw, 4);
+ nbytes = 4;
+ } else {
+ op = DW_CFA_MIPS_advance_loc8;
+ du = val1;
+ ptr =
+ (char *) _dwarf_p_get_alloc(dbg,
+ sizeof(Dwarf_Unsigned));
+ if (ptr == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
+ return ((Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+ memcpy((void *) ptr, (const void *) &du, 8);
+ nbytes = 8;
+ }
+ break;
+
+ case DW_CFA_offset:
+ if (val1 <= MAX_6_BIT_VALUE) {
+ db = val1;
+ op |= db;
+ res = _dwarf_pro_encode_leb128_nm(val2, &nbytes,
+ buff1, sizeof(buff1));
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
+ return ((Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+ ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes);
+ if (ptr == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
+ return ((Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+ memcpy(ptr, buff1, nbytes);
+
+ } else {
+ op = DW_CFA_offset_extended;
+ goto two_leb;
+ }
+ break;
+ case DW_CFA_offset_extended_sf: /* DWARF3 */
+ signed_second = 1;
+ goto two_leb;
+ case DW_CFA_offset_extended:
+ goto two_leb;
+
+ case DW_CFA_undefined:
+ case DW_CFA_same_value:
+ goto one_leb;
+
+ case DW_CFA_val_offset:
+ goto two_leb;
+ case DW_CFA_val_offset_sf:
+ signed_second = 1;
+ goto two_leb;
+ case DW_CFA_def_cfa_sf:
+ signed_second = 1;
+ goto two_leb;
+ case DW_CFA_register:
+ case DW_CFA_def_cfa:
+ two_leb:
+ res = _dwarf_pro_encode_leb128_nm(val1, &nbytes1,
+ buff1, sizeof(buff1));
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
+ return ((Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+ if (!signed_second) {
+ res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2,
+ buff2, sizeof(buff2));
+ } else {
+ Dwarf_Signed val2s = val2;
+ res = _dwarf_pro_encode_signed_leb128_nm(val2s, &nbytes2,
+ buff2, sizeof(buff2));
+ }
+
+ res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2,
+ buff2, sizeof(buff2));
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
+ return ((Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+
+ ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes1 + nbytes2);
+ if (ptr == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
+ return ((Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+ memcpy(ptr, buff1, nbytes1);
+ memcpy(ptr + nbytes1, buff2, nbytes2);
+ nbytes = nbytes1 + nbytes2;
+ break;
+
+ case DW_CFA_def_cfa_offset_sf: /* DWARF3 */
+ signed_first = 1;
+ goto one_leb;
+ case DW_CFA_def_cfa_register:
+ case DW_CFA_def_cfa_offset:
+ one_leb:
+ if(!signed_first) {
+ res = _dwarf_pro_encode_leb128_nm(val1, &nbytes,
+ buff1, sizeof(buff1));
+ } else {
+ Dwarf_Signed val1s = val1;
+ res = _dwarf_pro_encode_signed_leb128_nm(val1s, &nbytes,
+ buff1, sizeof(buff1));
+ }
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
+ return ((Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+ ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes);
+ if (ptr == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
+ return ((Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+ memcpy(ptr, buff1, nbytes);
+ break;
+ case DW_CFA_def_cfa_expression: /* DWARF3 */
+ /* FIXME: argument is dwarf expr, not handled yet. */
+ case DW_CFA_expression: /* DWARF3 */
+ /* First arg: ULEB reg num. 2nd arg dwarf expr in form block.
+ FIXME: not handled yet. */
+ case DW_CFA_val_expression: /* DWARF3f */
+ /* First arg: ULEB reg num. 2nd arg dwarf expr in form block.
+ FIXME: not handled yet. */
+ default:
+ _dwarf_p_error(dbg, error, DW_DLE_DEBUGFRAME_ERROR);
+ return ((Dwarf_P_Fde) DW_DLV_BADADDR);
+ }
+
+ curinst->dfp_opcode = op;
+ curinst->dfp_args = ptr;
+ curinst->dfp_nbytes = nbytes;
+ curinst->dfp_next = NULL;
+
+ _dwarf_pro_add_to_fde(fde, curinst);
+ return fde;
+}
+
+
+/* Instructions are added to an fde in the form of a linked
+ list. This function manages the linked list. */
+void
+_dwarf_pro_add_to_fde(Dwarf_P_Fde fde, Dwarf_P_Frame_Pgm curinst)
+{
+ if (fde->fde_last_inst) {
+ fde->fde_last_inst->dfp_next = curinst;
+ fde->fde_last_inst = curinst;
+ fde->fde_n_inst++;
+ fde->fde_n_bytes +=
+ (long) (curinst->dfp_nbytes + sizeof(Dwarf_Ubyte));
+ } else {
+ fde->fde_last_inst = curinst;
+ fde->fde_inst = curinst;
+ fde->fde_n_inst = 1;
+ fde->fde_n_bytes =
+ (long) (curinst->dfp_nbytes + sizeof(Dwarf_Ubyte));
+ }
+}
diff --git a/libdwarf/pro_frame.h b/libdwarf/pro_frame.h
new file mode 100644
index 0000000..883f084
--- /dev/null
+++ b/libdwarf/pro_frame.h
@@ -0,0 +1,129 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+/*
+ Largest register value that can be coded into
+ the opcode since there are only 6 bits in the
+ register field.
+*/
+#define MAX_6_BIT_VALUE 0x3f
+
+/* This struct holds debug_frame instructions */
+typedef struct Dwarf_P_Frame_Pgm_s *Dwarf_P_Frame_Pgm;
+
+struct Dwarf_P_Frame_Pgm_s {
+ Dwarf_Ubyte dfp_opcode; /* opcode - includes reg # */
+ char *dfp_args; /* operands */
+ int dfp_nbytes; /* number of bytes in args */
+#if 0
+ Dwarf_Unsigned dfp_sym_index; /* 0 unless reloc needed */
+#endif
+ Dwarf_P_Frame_Pgm dfp_next;
+};
+
+
+/*
+ This struct has cie related information. Used to gather data
+ from user program, and later to transform to disk form
+*/
+struct Dwarf_P_Cie_s {
+ Dwarf_Ubyte cie_version;
+ char *cie_aug; /* augmentation */
+ Dwarf_Ubyte cie_code_align; /* alignment of code */
+ Dwarf_Sbyte cie_data_align;
+ Dwarf_Ubyte cie_ret_reg; /* return register # */
+ char *cie_inst; /* initial instruction */
+ long cie_inst_bytes;
+ /* no of init_inst */
+ Dwarf_P_Cie cie_next;
+};
+
+
+/* producer fields */
+struct Dwarf_P_Fde_s {
+ Dwarf_Unsigned fde_unused1;
+
+ /* function/subr die for this fde */
+ Dwarf_P_Die fde_die;
+
+ /* index to asso. cie */
+ Dwarf_Word fde_cie;
+
+ /* Address of first location of the code this frame applies to If
+ fde_end_symbol non-zero, this represents the offset from the
+ symbol indicated by fde_r_symidx */
+ Dwarf_Addr fde_initloc;
+
+ /* Relocation symbol for address of the code this frame applies to. */
+ Dwarf_Unsigned fde_r_symidx;
+
+ /* Bytes of instr for this fde, if known */
+ Dwarf_Unsigned fde_addr_range;
+
+ /* linked list of instructions we will put in fde. */
+ Dwarf_P_Frame_Pgm fde_inst;
+
+ /* number of instructions in fde */
+ long fde_n_inst;
+
+ /* number of bytes of inst in fde */
+ long fde_n_bytes;
+
+ /* offset into exception table for this function. */
+ Dwarf_Signed fde_offset_into_exception_tables;
+
+ /* The symbol for the exception table elf section. */
+ Dwarf_Unsigned fde_exception_table_symbol;
+
+ /* pointer to last inst */
+ Dwarf_P_Frame_Pgm fde_last_inst;
+
+ Dwarf_P_Fde fde_next;
+
+ /* The symbol and offset of the end symbol. When fde_end_symbol is
+ non-zero we must represent the */
+ Dwarf_Addr fde_end_symbol_offset;
+ Dwarf_Unsigned fde_end_symbol;
+
+ int fde_uwordb_size;
+ Dwarf_P_Debug fde_dbg;
+
+ /* If fde_block is non-null, then it is the set of instructions.
+ so we should use it rather than fde_inst. */
+ Dwarf_Unsigned fde_inst_block_size;
+ void *fde_block;
+};
diff --git a/libdwarf/pro_funcs.c b/libdwarf/pro_funcs.c
new file mode 100644
index 0000000..2c6b114
--- /dev/null
+++ b/libdwarf/pro_funcs.c
@@ -0,0 +1,61 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_ELFACCESS_H
+#include <elfaccess.h>
+#endif
+#include "pro_incl.h"
+#include "pro_section.h"
+
+/* This function adds another function name to the
+ list of function names for the given Dwarf_P_Debug.
+ It returns 0 on error, and 1 otherwise. */
+Dwarf_Unsigned
+dwarf_add_funcname(Dwarf_P_Debug dbg,
+ Dwarf_P_Die die,
+ char *function_name, Dwarf_Error * error)
+{
+ return
+ _dwarf_add_simple_name_entry(dbg, die, function_name,
+ dwarf_snk_funcname, error);
+
+}
diff --git a/libdwarf/pro_incl.h b/libdwarf/pro_incl.h
new file mode 100644
index 0000000..9052dba
--- /dev/null
+++ b/libdwarf/pro_incl.h
@@ -0,0 +1,95 @@
+/*
+
+ Copyright (C) 2000,2002,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2008-2010 David Anderson. All rights reserved.
+ Portions Copyright 2010 SN Systems Ltd. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+#ifdef HAVE_ELF_H
+#include <elf.h>
+#elif defined(HAVE_LIBELF_H)
+/* On one platform without elf.h this gets Elf32_Rel
+ type defined (a required type). */
+#include <libelf.h>
+/* Consider the other known directory too */
+#elif defined(HAVE_LIBELF_LIBELF_H)
+#include <libelf/libelf.h>
+#endif
+
+#if defined(sun)
+#include <sys/elf_SPARC.h>
+#include <sys/elf_386.h>
+#endif
+
+/* The target address is given: the place in the source integer
+ is to be determined.
+*/
+#ifdef WORDS_BIGENDIAN
+#define WRITE_UNALIGNED(dbg,dest,source, srclength,len_out) \
+ { \
+ dbg->de_copy_word(dest, \
+ ((char *)source) +(srclength)-(len_out),\
+ (len_out)) ; \
+ }
+
+
+#else /* LITTLE ENDIAN */
+
+#define WRITE_UNALIGNED(dbg,dest,source, srclength,len_out) \
+ { \
+ dbg->de_copy_word( (dest) , \
+ ((char *)source) , \
+ (len_out)) ; \
+ }
+#endif
+
+
+#if defined(sparc) && defined(sun)
+#define REL32 Elf32_Rela
+#define REL64 Elf64_Rela
+#define REL_SEC_PREFIX ".rela"
+#else
+#define REL32 Elf32_Rel
+#define REL64 Elf64_Rel
+#define REL_SEC_PREFIX ".rel"
+#endif
+
+#include "dwarf.h"
+#include "libdwarf.h"
+
+#include "pro_opaque.h"
+#include "pro_error.h"
+#include "pro_util.h"
+#include "pro_encode_nm.h"
+#include "pro_alloc.h"
diff --git a/libdwarf/pro_init.c b/libdwarf/pro_init.c
new file mode 100644
index 0000000..d293136
--- /dev/null
+++ b/libdwarf/pro_init.c
@@ -0,0 +1,291 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson, Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#include "pro_incl.h"
+#include "pro_section.h" /* for MAGIC_SECT_NO */
+#include "pro_reloc_symbolic.h"
+#include "pro_reloc_stream.h"
+
+
+static void common_init(Dwarf_P_Debug dbg, Dwarf_Unsigned flags);
+
+void *_dwarf_memcpy_swap_bytes(void *s1, const void *s2, size_t len);
+
+/* This function sets up a new dwarf producing region.
+ flags: Indicates type of access method, one of DW_DLC* macros
+ func(): Used to create a new object file, a call back function
+ errhand(): Error Handler provided by user
+ errarg: Argument to errhand()
+ error: returned error value */
+ /* We want the following to have an elf section number that matches
+ 'nothing' */
+static struct Dwarf_P_Section_Data_s init_sect = {
+ MAGIC_SECT_NO, 0, 0, 0, 0
+};
+
+/* New June, 2011, this is the latest, most flexible
+ version. It adds (compared to *_b) the user_data
+ pointer which is passed back (unchanged) in
+ each callback call. */
+Dwarf_P_Debug
+dwarf_producer_init_c(Dwarf_Unsigned flags,
+ Dwarf_Callback_Func_c func,
+ Dwarf_Handler errhand,
+ Dwarf_Ptr errarg,
+ void * user_data,
+ Dwarf_Error * error)
+{
+ Dwarf_P_Debug dbg;
+ dbg = (Dwarf_P_Debug) _dwarf_p_get_alloc(NULL,
+ sizeof(struct Dwarf_P_Debug_s));
+ if (dbg == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_DBG_ALLOC,
+ (Dwarf_P_Debug) DW_DLV_BADADDR);
+ }
+ memset((void *) dbg, 0, sizeof(struct Dwarf_P_Debug_s));
+ /* For the time being */
+ if (func == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_NO_CALLBACK_FUNC,
+ (Dwarf_P_Debug) DW_DLV_BADADDR);
+ }
+ dbg->de_callback_func_c = func;
+ dbg->de_errhand = errhand;
+ dbg->de_errarg = errarg;
+ dbg->de_user_data = user_data;
+ common_init(dbg, flags);
+ return dbg;
+
+}
+
+
+Dwarf_P_Debug
+dwarf_producer_init_b(Dwarf_Unsigned flags,
+ Dwarf_Callback_Func_b func,
+ Dwarf_Handler errhand,
+ Dwarf_Ptr errarg, Dwarf_Error * error)
+{
+ Dwarf_P_Debug dbg;
+ dbg = (Dwarf_P_Debug) _dwarf_p_get_alloc(NULL,
+ sizeof(struct Dwarf_P_Debug_s));
+ if (dbg == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_DBG_ALLOC,
+ (Dwarf_P_Debug) DW_DLV_BADADDR);
+ }
+ memset((void *) dbg, 0, sizeof(struct Dwarf_P_Debug_s));
+ /* For the time being */
+ if (func == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_NO_CALLBACK_FUNC,
+ (Dwarf_P_Debug) DW_DLV_BADADDR);
+ }
+ dbg->de_callback_func_b = func;
+ dbg->de_errhand = errhand;
+ dbg->de_errarg = errarg;
+ dbg->de_user_data = 0;
+ common_init(dbg, flags);
+ return dbg;
+
+}
+
+Dwarf_P_Debug
+dwarf_producer_init(Dwarf_Unsigned flags,
+ Dwarf_Callback_Func func,
+ Dwarf_Handler errhand,
+ Dwarf_Ptr errarg, Dwarf_Error * error)
+{
+ Dwarf_P_Debug dbg = 0;
+
+ dbg = (Dwarf_P_Debug) _dwarf_p_get_alloc(NULL,
+ sizeof(struct Dwarf_P_Debug_s));
+ if (dbg == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_DBG_ALLOC,
+ (Dwarf_P_Debug) DW_DLV_BADADDR);
+ }
+ memset((void *) dbg, 0, sizeof(struct Dwarf_P_Debug_s));
+ /* For the time being */
+ if (func == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_NO_CALLBACK_FUNC,
+ (Dwarf_P_Debug) DW_DLV_BADADDR);
+ }
+ dbg->de_callback_func = func;
+ dbg->de_errhand = errhand;
+ dbg->de_errarg = errarg;
+ dbg->de_user_data = 0;
+ common_init(dbg, flags);
+ return dbg;
+}
+static void
+common_init(Dwarf_P_Debug dbg, Dwarf_Unsigned flags)
+{
+ unsigned int k = 0;
+
+ dbg->de_version_magic_number = PRO_VERSION_MAGIC;
+ dbg->de_n_debug_sect = 0;
+ dbg->de_debug_sects = &init_sect;
+ dbg->de_current_active_section = &init_sect;
+ dbg->de_flags = flags;
+ _dwarf_init_default_line_header_vals(dbg);
+
+ /* Now, with flags set, can use 64bit tests */
+
+
+
+#if defined(HAVE_STRICT_DWARF2_32BIT_OFFSET)
+ /* This is cygnus 32bit offset, as specified in pure dwarf2 v2.0.0.
+ It is consistent with normal DWARF2/3 generation of always
+ generating 32 bit offsets. */
+ dbg->de_64bit_extension = 0;
+ dbg->de_pointer_size = (IS_64BIT(dbg) ? 8 : 4);
+ dbg->de_offset_size = (IS_64BIT(dbg) ? 4 : 4);
+ dbg->de_ptr_reloc =
+ IS_64BIT(dbg) ? Get_REL64_isa(dbg) : Get_REL32_isa(dbg);
+ /* non-MIPS, dwarf lengths and offsets are 32 bits even for 64bit
+ pointer environments. */
+ /* Get_REL32_isa here supports 64-bit-pointer dwarf with pure
+ dwarf2 v2.0.0 32bit offsets, as emitted by cygnus tools. And
+ pure 32 bit offset dwarf for 32bit pointer apps. */
+
+ dbg->de_offset_reloc = Get_REL32_isa(dbg);
+#elif defined(HAVE_SGI_IRIX_OFFSETS)
+ /* MIPS-SGI-IRIX 32 or 64, where offsets and lengths are both 64 bit for
+ 64bit pointer objects and both 32 bit for 32bit pointer objects.
+ And a dwarf-reader must check elf info to tell which applies. */
+ dbg->de_64bit_extension = 0;
+ dbg->de_pointer_size = (IS_64BIT(dbg) ? 8 : 4);
+ dbg->de_offset_size = (IS_64BIT(dbg) ? 8 : 4);
+ dbg->de_ptr_reloc =
+ IS_64BIT(dbg) ? Get_REL64_isa(dbg) : Get_REL32_isa(dbg);
+ dbg->de_offset_reloc = dbg->de_ptr_reloc;
+#else /* HAVE_DWARF2_99_EXTENSION or default. */
+ /* Revised 64 bit output, using distingushed values. Per 1999
+ dwarf3. This allows run-time selection of offset size. */
+ dbg->de_64bit_extension = (IS_64BIT(dbg) ? 1 : 0);
+ dbg->de_pointer_size = (IS_64BIT(dbg) ? 8 : 4);
+ if( flags & DW_DLC_OFFSET_SIZE_64 && (dbg->de_pointer_size == 8)) {
+ /* When it's 64 bit address, a 64bit offset is sensible.
+ Arguably a 32 bit address with 64 bit offset could be
+ sensible, but who would want that? */
+ dbg->de_offset_size = 8;
+ dbg->de_64bit_extension = 1;
+ } else {
+ dbg->de_offset_size = 4;
+ dbg->de_64bit_extension = 0;
+ }
+ dbg->de_ptr_reloc =
+ IS_64BIT(dbg) ? Get_REL64_isa(dbg) : Get_REL32_isa(dbg);
+ /* Non-MIPS, dwarf lengths and offsets are 32 bits even for 64bit
+ pointer environments. */
+ /* Get_REL??_isa here supports 64bit-offset dwarf. For 64bit, we
+ emit the extension bytes. */
+
+ dbg->de_offset_reloc = IS_64BIT(dbg) ? Get_REL64_isa(dbg)
+ : Get_REL32_isa(dbg);
+#endif /* HAVE_DWARF2_99_EXTENSION etc. */
+
+ dbg->de_exc_reloc = Get_REL_SEGREL_isa(dbg);
+
+ dbg->de_is_64bit = IS_64BIT(dbg);
+
+
+ if (flags & DW_DLC_SYMBOLIC_RELOCATIONS) {
+ dbg->de_relocation_record_size =
+ sizeof(struct Dwarf_Relocation_Data_s);
+ } else {
+
+#if HAVE_ELF64_GETEHDR
+ dbg->de_relocation_record_size =
+ IS_64BIT(dbg)? sizeof(REL64) : sizeof(REL32);
+#else
+ dbg->de_relocation_record_size = sizeof(REL32);
+#endif
+
+ }
+
+ if (dbg->de_offset_size == 8) {
+ dbg->de_ar_data_attribute_form = DW_FORM_data8;
+ dbg->de_ar_ref_attr_form = DW_FORM_ref8;
+ } else {
+ dbg->de_ar_data_attribute_form = DW_FORM_data4;
+ dbg->de_ar_ref_attr_form = DW_FORM_ref4;
+ }
+
+ if (flags & DW_DLC_SYMBOLIC_RELOCATIONS) {
+ dbg->de_reloc_name = _dwarf_pro_reloc_name_symbolic;
+ dbg->de_reloc_pair = _dwarf_pro_reloc_length_symbolic;
+ dbg->de_transform_relocs_to_disk =
+ _dwarf_symbolic_relocs_to_disk;
+ } else {
+ if (IS_64BIT(dbg)) {
+ dbg->de_reloc_name = _dwarf_pro_reloc_name_stream64;
+ } else {
+ dbg->de_reloc_name = _dwarf_pro_reloc_name_stream32;
+ }
+ dbg->de_reloc_pair = 0;
+ dbg->de_transform_relocs_to_disk = _dwarf_stream_relocs_to_disk;
+ }
+ for (k = 0; k < NUM_DEBUG_SECTIONS; ++k) {
+
+ Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[k];
+
+ prel->pr_slots_per_block_to_alloc = DEFAULT_SLOTS_PER_BLOCK;
+ }
+ /* First assume host, target same endianness */
+ dbg->de_same_endian = 1;
+ dbg->de_copy_word = memcpy;
+#ifdef WORDS_BIGENDIAN
+ /* host is big endian, so what endian is target? */
+ if (flags & DW_DLC_TARGET_LITTLEENDIAN) {
+ dbg->de_same_endian = 0;
+ dbg->de_copy_word = _dwarf_memcpy_swap_bytes;
+ }
+#else /* little endian */
+ /* host is little endian, so what endian is target? */
+ if (flags & DW_DLC_TARGET_BIGENDIAN) {
+ dbg->de_same_endian = 0;
+ dbg->de_copy_word = _dwarf_memcpy_swap_bytes;
+ }
+#endif /* !WORDS_BIGENDIAN */
+
+
+ return;
+
+}
diff --git a/libdwarf/pro_line.c b/libdwarf/pro_line.c
new file mode 100644
index 0000000..5860f13
--- /dev/null
+++ b/libdwarf/pro_line.c
@@ -0,0 +1,384 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_ELF_H
+#include <elf.h>
+#endif
+#include "pro_incl.h"
+#include "pro_line.h"
+
+static
+Dwarf_Unsigned _dwarf_pro_add_line_entry(Dwarf_P_Debug,
+ Dwarf_Unsigned file_index,
+ Dwarf_Addr code_address,
+ Dwarf_Unsigned symidx,
+ Dwarf_Unsigned line_no,
+ Dwarf_Signed col_no,
+ Dwarf_Bool is_stmt_begin,
+ Dwarf_Bool is_bb_begin,
+ Dwarf_Ubyte opc,
+ Dwarf_Bool isepilbeg,
+ Dwarf_Bool isprolend,
+ Dwarf_Unsigned isa,
+ Dwarf_Unsigned discriminator,
+ Dwarf_Error * error);
+
+/* Add a entry to the line information section
+ file_index: index of file in file entries, obtained from
+ add_file_entry() call.
+
+ This function actually calls _dwarf_pro_add_line_entry(), with
+ an extra parameter, the opcode. Done so that interface calls
+ dwarf_lne_set_address() and dwarf_lne_end_sequence() can use
+ this internal routine. */
+Dwarf_Unsigned
+dwarf_add_line_entry_b(Dwarf_P_Debug dbg,
+ Dwarf_Unsigned file_index,
+ Dwarf_Addr code_address,
+ Dwarf_Unsigned line_no,
+ Dwarf_Signed col_no,
+ Dwarf_Bool is_stmt_begin,
+ Dwarf_Bool is_bb_begin,
+ Dwarf_Bool isepilbeg,
+ Dwarf_Bool isprolend,
+ Dwarf_Unsigned isa,
+ Dwarf_Unsigned discriminator,
+ Dwarf_Error * error)
+{
+ Dwarf_Unsigned retval = 0;
+ Dwarf_Ubyte opc = 0;
+ Dwarf_Unsigned symidx = 0;
+
+ retval = _dwarf_pro_add_line_entry(dbg, file_index, code_address,
+ symidx,
+ line_no, col_no, is_stmt_begin,
+ is_bb_begin,
+ opc,
+ isepilbeg,isprolend,isa,discriminator, error);
+ return retval;
+}
+Dwarf_Unsigned
+dwarf_add_line_entry(Dwarf_P_Debug dbg,
+ Dwarf_Unsigned file_index,
+ Dwarf_Addr code_address,
+ Dwarf_Unsigned line_no,
+ Dwarf_Signed col_no, /* Wrong, should be unsigned. */
+ Dwarf_Bool is_stmt_begin,
+ Dwarf_Bool is_bb_begin, Dwarf_Error * error)
+{
+ Dwarf_Unsigned retval = 0;
+ Dwarf_Ubyte opc = 0;
+ Dwarf_Unsigned symidx = 0;
+ Dwarf_Bool isepilbeg = 0;
+ Dwarf_Bool isprolend = 0;
+ Dwarf_Unsigned isa = 0;
+ Dwarf_Unsigned discriminator = 0;
+
+ retval = _dwarf_pro_add_line_entry(dbg, file_index, code_address,
+ symidx,
+ line_no, col_no, is_stmt_begin,
+ is_bb_begin,
+ opc,
+ isepilbeg, isprolend, isa, discriminator,
+ error);
+ return retval;
+}
+
+void
+_dwarf_init_default_line_header_vals(Dwarf_P_Debug dbg)
+{
+ dbg->de_line_inits.pi_version = DW_LINE_VERSION2;
+ dbg->de_line_inits.pi_default_is_stmt = DEFAULT_IS_STMT;
+ dbg->de_line_inits.pi_minimum_instruction_length = MIN_INST_LENGTH;
+ dbg->de_line_inits.pi_maximum_operations_per_instruction = 1;
+ dbg->de_line_inits.pi_opcode_base = OPCODE_BASE;
+ dbg->de_line_inits.pi_line_base = LINE_BASE;
+ dbg->de_line_inits.pi_line_range = LINE_RANGE;
+}
+
+
+/* Ask to emit DW_LNE_set_address opcode explicitly. Used by be
+ to emit start of a new .text section, or to force a relocated
+ address into debug line information entry. */
+Dwarf_Unsigned
+dwarf_lne_set_address(Dwarf_P_Debug dbg,
+ Dwarf_Addr offs,
+ Dwarf_Unsigned symidx, Dwarf_Error * error)
+{
+ Dwarf_Ubyte opc = 0;
+ Dwarf_Unsigned retval = 0;
+ Dwarf_Unsigned file_index = 0;
+ Dwarf_Unsigned line_no = 0;
+ Dwarf_Signed col_no = 0;
+ Dwarf_Bool is_stmt = 0;
+ Dwarf_Bool is_bb = 0;
+ Dwarf_Bool isepilbeg = 0;
+ Dwarf_Bool isprolend = 0;
+ Dwarf_Unsigned isa = 0;
+ Dwarf_Unsigned discriminator = 0;
+
+
+ opc = DW_LNE_set_address;
+ retval =
+ _dwarf_pro_add_line_entry(dbg, file_index, offs,
+ symidx,
+ line_no, col_no, is_stmt,
+ is_bb,
+ opc,
+ isepilbeg, isprolend, isa, discriminator,
+ error);
+ return retval;
+}
+
+/* Ask to emit end_seqence opcode. Used normally at the end of a
+ compilation unit. Can also be used in the middle if there
+ are gaps in the region described by the code address. */
+Dwarf_Unsigned
+dwarf_lne_end_sequence(Dwarf_P_Debug dbg,
+ Dwarf_Addr end_address, Dwarf_Error * error)
+{
+ Dwarf_Ubyte opc = 0;
+ Dwarf_Unsigned retval = 0;
+ Dwarf_Unsigned file_index = 0;
+ Dwarf_Unsigned symidx = 0;
+ Dwarf_Unsigned line_no = 0;
+ Dwarf_Bool is_stmt = 0;
+ Dwarf_Bool is_bb = 0;
+ Dwarf_Signed col_no = 0;/* Wrong, should be unsigned. */
+ Dwarf_Bool isepilbeg = 0;
+ Dwarf_Bool isprolend = 0;
+ Dwarf_Unsigned isa = 0;
+ Dwarf_Unsigned discriminator = 0;
+
+ opc = DW_LNE_end_sequence;
+ retval =
+ _dwarf_pro_add_line_entry(dbg, file_index, end_address,
+ symidx,
+ line_no, col_no, is_stmt,
+ is_bb,
+ opc,
+ isepilbeg, isprolend, isa, discriminator,
+ error);
+ return retval;
+}
+
+/* Add an entry in the internal list of lines mantained by producer.
+ Opc indicates if an opcode needs to be generated, rather than just
+ an entry in the matrix. During opcodes generation time, these
+ opcodes will be used. */
+static Dwarf_Unsigned
+_dwarf_pro_add_line_entry(Dwarf_P_Debug dbg,
+ Dwarf_Unsigned file_index,
+ Dwarf_Addr code_address,
+ Dwarf_Unsigned symidx,
+ Dwarf_Unsigned line_no,
+ Dwarf_Signed col_no,
+ Dwarf_Bool is_stmt_begin,
+ Dwarf_Bool is_bb_begin,
+ Dwarf_Ubyte opc,
+ Dwarf_Bool isepilbeg,
+ Dwarf_Bool isprolend,
+ Dwarf_Unsigned isa,
+ Dwarf_Unsigned discriminator,
+ Dwarf_Error * error)
+{
+ if (dbg->de_lines == NULL) {
+ dbg->de_lines = (Dwarf_P_Line)
+ _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Line_s));
+ if (dbg->de_lines == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_LINE_ALLOC, DW_DLV_NOCOUNT);
+ }
+ dbg->de_last_line = dbg->de_lines;
+ _dwarf_pro_reg_init(dbg,dbg->de_lines);
+
+ } else {
+ dbg->de_last_line->dpl_next = (Dwarf_P_Line)
+ _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Line_s));
+ if (dbg->de_last_line->dpl_next == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_LINE_ALLOC, DW_DLV_NOCOUNT);
+ }
+ dbg->de_last_line = dbg->de_last_line->dpl_next;
+ _dwarf_pro_reg_init(dbg,dbg->de_last_line);
+ }
+ dbg->de_last_line->dpl_address = code_address;
+ dbg->de_last_line->dpl_file = (unsigned long) file_index;
+ dbg->de_last_line->dpl_line = (unsigned long) line_no;
+ dbg->de_last_line->dpl_column = (unsigned long) col_no;
+ dbg->de_last_line->dpl_is_stmt = is_stmt_begin;
+ dbg->de_last_line->dpl_basic_block = is_bb_begin;
+ dbg->de_last_line->dpl_opc = opc;
+ dbg->de_last_line->dpl_r_symidx = symidx;
+ dbg->de_last_line->dpl_prologue_end = isprolend;
+ dbg->de_last_line->dpl_epilogue_begin = isepilbeg;
+ dbg->de_last_line->dpl_isa = isa;
+ dbg->de_last_line->dpl_discriminator = discriminator;
+ return (0);
+}
+
+/* Add a directory declaration to the debug_line section. Stored
+ in linked list. */
+Dwarf_Unsigned
+dwarf_add_directory_decl(Dwarf_P_Debug dbg,
+ char *name, Dwarf_Error * error)
+{
+ if (dbg->de_inc_dirs == NULL) {
+ dbg->de_inc_dirs = (Dwarf_P_Inc_Dir)
+ _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Inc_Dir_s));
+ if (dbg->de_inc_dirs == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_INCDIR_ALLOC, DW_DLV_NOCOUNT);
+ }
+ dbg->de_last_inc_dir = dbg->de_inc_dirs;
+ dbg->de_n_inc_dirs = 1;
+ } else {
+ dbg->de_last_inc_dir->did_next = (Dwarf_P_Inc_Dir)
+ _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Inc_Dir_s));
+ if (dbg->de_last_inc_dir->did_next == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_INCDIR_ALLOC, DW_DLV_NOCOUNT);
+ }
+ dbg->de_last_inc_dir = dbg->de_last_inc_dir->did_next;
+ dbg->de_n_inc_dirs++;
+ }
+ dbg->de_last_inc_dir->did_name =
+ (char *) _dwarf_p_get_alloc(dbg, strlen(name) + 1);
+ if (dbg->de_last_inc_dir->did_name == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_STRING_ALLOC, DW_DLV_NOCOUNT);
+ }
+ strcpy(dbg->de_last_inc_dir->did_name, name);
+ dbg->de_last_inc_dir->did_next = NULL;
+
+ return dbg->de_n_inc_dirs;
+}
+
+/* Add a file entry declaration to the debug_line section. Stored
+ in linked list. The data is immediately encoded as leb128
+ and stored in Dwarf_P_F_Entry_s struct. */
+Dwarf_Unsigned
+dwarf_add_file_decl(Dwarf_P_Debug dbg,
+ char *name,
+ Dwarf_Unsigned dir_idx,
+ Dwarf_Unsigned time_mod,
+ Dwarf_Unsigned length, Dwarf_Error * error)
+{
+ Dwarf_P_F_Entry cur;
+ char *ptr = 0;
+ int nbytes_idx, nbytes_time, nbytes_len;
+ char buffidx[ENCODE_SPACE_NEEDED];
+ char bufftime[ENCODE_SPACE_NEEDED];
+ char bufflen[ENCODE_SPACE_NEEDED];
+ int res = 0;
+
+ if (dbg->de_file_entries == NULL) {
+ dbg->de_file_entries = (Dwarf_P_F_Entry)
+ _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_F_Entry_s));
+ if (dbg->de_file_entries == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_FILE_ENTRY_ALLOC,
+ DW_DLV_NOCOUNT);
+ }
+ cur = dbg->de_file_entries;
+ dbg->de_last_file_entry = cur;
+ dbg->de_n_file_entries = 1;
+ } else {
+ cur = dbg->de_last_file_entry;
+ cur->dfe_next = (Dwarf_P_F_Entry)
+ _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_F_Entry_s));
+ if (cur->dfe_next == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_FILE_ENTRY_ALLOC,
+ DW_DLV_NOCOUNT);
+ }
+ cur = cur->dfe_next;
+ dbg->de_last_file_entry = cur;
+ dbg->de_n_file_entries++;
+ }
+ cur->dfe_name = (char *) _dwarf_p_get_alloc(dbg, strlen(name) + 1);
+ if (cur->dfe_name == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_ALLOC_FAIL, DW_DLV_NOCOUNT);
+ }
+ strcpy((char *) cur->dfe_name, name);
+ res = _dwarf_pro_encode_leb128_nm(dir_idx, &nbytes_idx,
+ buffidx, sizeof(buffidx));
+ if (res != DW_DLV_OK) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_ALLOC_FAIL, DW_DLV_NOCOUNT);
+ }
+ res = _dwarf_pro_encode_leb128_nm(time_mod, &nbytes_time,
+ bufftime, sizeof(bufftime));
+ if (res != DW_DLV_OK) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_ALLOC_FAIL, DW_DLV_NOCOUNT);
+ }
+ res = _dwarf_pro_encode_leb128_nm(length, &nbytes_len,
+ bufflen, sizeof(bufflen));
+ cur->dfe_args = (char *)
+ _dwarf_p_get_alloc(dbg, nbytes_idx + nbytes_time + nbytes_len);
+ if (cur->dfe_args == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_ALLOC_FAIL, DW_DLV_NOCOUNT);
+ }
+ ptr = cur->dfe_args;
+ memcpy((void *) ptr, buffidx, nbytes_idx);
+ ptr += nbytes_idx;
+ memcpy((void *) ptr, bufftime, nbytes_time);
+ ptr += nbytes_time;
+ memcpy((void *) ptr, bufflen, nbytes_len);
+ ptr += nbytes_len;
+ cur->dfe_nbytes = nbytes_idx + nbytes_time + nbytes_len;
+ cur->dfe_next = NULL;
+
+ return dbg->de_n_file_entries;
+}
+
+
+/* Initialize a row of the matrix for line numbers, meaning
+ initialize the struct corresponding to it */
+void
+_dwarf_pro_reg_init(Dwarf_P_Debug dbg, Dwarf_P_Line cur_line)
+{
+ cur_line->dpl_address = 0;
+ cur_line->dpl_file = 1;
+ cur_line->dpl_line = 1;
+ cur_line->dpl_column = 0;
+ cur_line->dpl_is_stmt = dbg->de_line_inits.pi_default_is_stmt;
+ cur_line->dpl_basic_block = false;
+ cur_line->dpl_next = NULL;
+ cur_line->dpl_prologue_end = 0;
+ cur_line->dpl_epilogue_begin = 0;
+ cur_line->dpl_isa = 0;
+ cur_line->dpl_discriminator = 0;
+ cur_line->dpl_opc = 0;
+}
diff --git a/libdwarf/pro_line.h b/libdwarf/pro_line.h
new file mode 100644
index 0000000..dd2c4e6
--- /dev/null
+++ b/libdwarf/pro_line.h
@@ -0,0 +1,121 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+#define DW_LINE_VERSION2 2
+#define DW_LINE_VERSION3 3
+#define DW_LINE_VERSION4 4
+
+#if defined(__i386) || defined(__x86_64)
+#define MIN_INST_LENGTH 1
+#else
+#define MIN_INST_LENGTH 4
+#endif
+#define DEFAULT_IS_STMT false
+/* line base and range are temporarily defines.
+ They need to be calculated later */
+#define LINE_BASE -1
+#define LINE_RANGE 4
+
+#define OPCODE_BASE 10 /* DWARF2. 13 in DWARF3, DWARF4 */
+#define MAX_OPCODE 255
+
+
+/* This struct is used to hold entries in the include directories
+ part of statement prologue. */
+struct Dwarf_P_Inc_Dir_s {
+ char *did_name; /* name of directory */
+ Dwarf_P_Inc_Dir did_next;
+};
+
+
+/* This struct holds file entries for the statement prologue.
+ Defined in pro_line.h */
+struct Dwarf_P_F_Entry_s {
+ char *dfe_name;
+ char *dfe_args; /* has dir index, time of modification,
+ length in bytes. Encodes as leb128 */
+ int dfe_nbytes; /* number of bytes in args */
+ Dwarf_P_F_Entry dfe_next;
+};
+
+
+/*
+ Struct holding line number information for each of the producer
+ line entries
+*/
+struct Dwarf_P_Line_s {
+ /* code address */
+ Dwarf_Addr dpl_address;
+
+ /* file index, index into file entry */
+ Dwarf_Word dpl_file;
+
+ /* line number */
+ Dwarf_Word dpl_line;
+
+ /* column number */
+ Dwarf_Word dpl_column;
+
+ /* whether its a beginning of a stmt */
+ Dwarf_Ubyte dpl_is_stmt;
+
+ /* whether its a beginning of basic blk */
+ Dwarf_Ubyte dpl_basic_block;
+
+ /* used to store opcodes set_address, and end_seq */
+ Dwarf_Ubyte dpl_opc;
+
+ /* Used only for relocations. Has index of symbol relative to
+ which relocation has to be done (the S part in S + A) */
+ Dwarf_Unsigned dpl_r_symidx;
+
+ Dwarf_P_Line dpl_next;
+
+ Dwarf_Ubyte dpl_prologue_end; /* DWARF3 */
+ Dwarf_Ubyte dpl_epilogue_begin; /* DWARF3 */
+ Dwarf_Unsigned dpl_isa; /* DWARF3 */
+ Dwarf_Unsigned dpl_discriminator; /* DWARF4 */
+
+};
+
+/*
+ to initialize state machine registers, definition in
+ pro_line.c
+*/
+void _dwarf_pro_reg_init(Dwarf_P_Debug dbg,Dwarf_P_Line);
+
+void _dwarf_init_default_line_header_vals(Dwarf_P_Debug dbg);
diff --git a/libdwarf/pro_macinfo.c b/libdwarf/pro_macinfo.c
new file mode 100644
index 0000000..7985262
--- /dev/null
+++ b/libdwarf/pro_macinfo.c
@@ -0,0 +1,468 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#include "pro_incl.h"
+#include "pro_section.h"
+#include "pro_macinfo.h"
+
+/* I don't much like the error strings this generates, since
+ like the rest of libdwarf they are simple strings with
+ no useful numbers in them. But that's not something I can
+ fix without more work than I have time for
+ right now. davea Nov 94.
+*/
+
+/* these are gross overestimates of the number of
+** bytes needed to store a number in LEB form.
+** Just estimates, and since blocks are reasonable size,
+** the end-block waste is small.
+** Of course the waste is NOT present on disk.
+*/
+
+#define COMMAND_LEN ENCODE_SPACE_NEEDED
+#define LINE_LEN ENCODE_SPACE_NEEDED
+#define BASE_MACINFO_MALLOC_LEN 2048
+
+static int
+libdwarf_compose_begin(Dwarf_P_Debug dbg, int code,
+ size_t maxlen, int *compose_error_type)
+{
+ unsigned char *nextchar;
+ struct dw_macinfo_block_s *curblk = dbg->de_current_macinfo;
+
+ if (curblk == 0) {
+ struct dw_macinfo_block_s *newb;
+ size_t len;
+
+ /* initial allocation */
+ size_t blen = BASE_MACINFO_MALLOC_LEN;
+
+ if (blen < maxlen) {
+ blen = 2 * maxlen;
+ }
+ len = sizeof(struct dw_macinfo_block_s) + blen;
+ newb =
+ (struct dw_macinfo_block_s *) _dwarf_p_get_alloc(dbg, len);
+ if (!newb) {
+ *compose_error_type = DW_DLE_MACINFO_MALLOC_FAIL;
+ return DW_DLV_ERROR;
+ }
+ newb->mb_data =
+ (char *) newb + sizeof(struct dw_macinfo_block_s);
+ newb->mb_avail_len = blen;
+ newb->mb_used_len = 0;
+ newb->mb_macinfo_data_space_len = blen;
+ dbg->de_first_macinfo = newb;
+ dbg->de_current_macinfo = newb;
+ curblk = newb;
+ } else if (curblk->mb_avail_len < maxlen) {
+ struct dw_macinfo_block_s *newb;
+ size_t len;
+
+ /* no space left in block: allocate a new block */
+ size_t blen =
+ dbg->de_current_macinfo->mb_macinfo_data_space_len * 2;
+ if (blen < maxlen) {
+ blen = 2 * maxlen;
+ }
+ len = sizeof(struct dw_macinfo_block_s) + blen;
+ newb =
+ (struct dw_macinfo_block_s *) _dwarf_p_get_alloc(dbg, len);
+ if (!newb) {
+ *compose_error_type = DW_DLE_MACINFO_MALLOC_FAIL;
+ return DW_DLV_ERROR;
+ }
+ newb->mb_data =
+ (char *) newb + sizeof(struct dw_macinfo_block_s);
+ newb->mb_avail_len = blen;
+ newb->mb_used_len = 0;
+ newb->mb_macinfo_data_space_len = blen;
+ dbg->de_first_macinfo->mb_next = newb;
+ dbg->de_current_macinfo = newb;
+ curblk = newb;
+ }
+ /* now curblk has enough room */
+ dbg->de_compose_avail = curblk->mb_avail_len;
+ dbg->de_compose_used_len = curblk->mb_used_len;
+ nextchar =
+ (unsigned char *) (curblk->mb_data + dbg->de_compose_used_len);
+ *nextchar = code;
+ dbg->de_compose_avail--;
+ ++dbg->de_compose_used_len;
+ return DW_DLV_OK;
+}
+
+
+
+static void
+libdwarf_compose_add_string(Dwarf_P_Debug dbg, char *string, size_t len)
+{
+ struct dw_macinfo_block_s *curblk = dbg->de_current_macinfo;
+ unsigned char *nextchar;
+
+ nextchar =
+ (unsigned char *) (curblk->mb_data + dbg->de_compose_used_len);
+
+ len += 1; /* count the null terminator */
+
+ memcpy(nextchar, string, len);
+ dbg->de_compose_avail -= len;
+ dbg->de_compose_used_len += len;
+ return;
+
+}
+static int
+libdwarf_compose_add_line(Dwarf_P_Debug dbg,
+ Dwarf_Unsigned line, int *compose_error_type)
+{
+ struct dw_macinfo_block_s *curblk = dbg->de_current_macinfo;
+ unsigned char *nextchar;
+ int res;
+ int nbytes;
+
+ nextchar =
+ (unsigned char *) (curblk->mb_data + dbg->de_compose_used_len);
+
+ /* Put the created leb number directly into the macro buffer If
+ dbg->de_compose_avail is > INT_MAX this will not work as the
+ 'int' will look negative to _dwarf_pro_encode_leb128_nm! */
+
+ res = _dwarf_pro_encode_leb128_nm(line, &nbytes,
+ (char *) nextchar,
+ (int) dbg->de_compose_avail);
+ if (res != DW_DLV_OK) {
+ *compose_error_type = DW_DLE_MACINFO_INTERNAL_ERROR_SPACE;
+ return DW_DLV_ERROR;
+ }
+
+ dbg->de_compose_avail -= nbytes;
+ dbg->de_compose_used_len += nbytes;
+ return DW_DLV_OK;
+}
+
+/* This function actually 'commits' the space used by the
+ preceeding calls. */
+static int
+libdwarf_compose_complete(Dwarf_P_Debug dbg, int *compose_error_type)
+{
+ struct dw_macinfo_block_s *curblk = dbg->de_current_macinfo;
+
+ if (dbg->de_compose_used_len > curblk->mb_macinfo_data_space_len) {
+ *compose_error_type = DW_DLE_MACINFO_INTERNAL_ERROR_SPACE;
+ return DW_DLV_ERROR;
+ }
+ curblk->mb_avail_len = dbg->de_compose_avail;
+ curblk->mb_used_len = dbg->de_compose_used_len;
+ return DW_DLV_OK;
+}
+
+
+
+int
+dwarf_def_macro(Dwarf_P_Debug dbg,
+ Dwarf_Unsigned line,
+ char *macname, char *macvalue, Dwarf_Error * error)
+{
+ size_t len;
+ size_t len2;
+ size_t length_est;
+ int res;
+ int compose_error_type;
+
+ if (dbg == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+ if (macname == 0) {
+ _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_NULL);
+ return (DW_DLV_ERROR);
+ }
+ len = strlen(macname) + 1;
+ if (len == 0) {
+ _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_EMPTY);
+ return (DW_DLV_ERROR);
+ }
+ if (macvalue) {
+ len2 = strlen(macvalue) + 1;
+ } else {
+ len2 = 0;
+ }
+
+ /* 1 for space character we add */
+ length_est = COMMAND_LEN + LINE_LEN + len + len2 + 1;
+
+ res = libdwarf_compose_begin(dbg, DW_MACINFO_define, length_est,
+ &compose_error_type);
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(NULL, error, compose_error_type);
+ return (DW_DLV_ERROR);
+ }
+ res = libdwarf_compose_add_line(dbg, line, &compose_error_type);
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(NULL, error, compose_error_type);
+ return (DW_DLV_ERROR);
+ }
+ libdwarf_compose_add_string(dbg, macname, len);
+ libdwarf_compose_add_string(dbg, " ", 1);
+ if (macvalue) {
+ libdwarf_compose_add_string(dbg, " ", 1);
+ libdwarf_compose_add_string(dbg, macvalue, len2);
+ }
+ res = libdwarf_compose_complete(dbg, &compose_error_type);
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(NULL, error, compose_error_type);
+ return (DW_DLV_ERROR);
+ }
+ return DW_DLV_OK;
+}
+
+int
+dwarf_undef_macro(Dwarf_P_Debug dbg,
+ Dwarf_Unsigned line,
+ char *macname, Dwarf_Error * error)
+{
+
+ size_t len;
+ size_t length_est;
+ int res;
+ int compose_error_type;
+
+ if (dbg == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+ if (macname == 0) {
+ _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_NULL);
+ return (DW_DLV_ERROR);
+ }
+ len = strlen(macname) + 1;
+ if (len == 0) {
+ _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_EMPTY);
+ return (DW_DLV_ERROR);
+ }
+ length_est = COMMAND_LEN + LINE_LEN + len;
+ res = libdwarf_compose_begin(dbg, DW_MACINFO_undef, length_est,
+ &compose_error_type);
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(NULL, error, compose_error_type);
+ return (DW_DLV_ERROR);
+ }
+ res = libdwarf_compose_add_line(dbg, line, &compose_error_type);
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(NULL, error, compose_error_type);
+ return (DW_DLV_ERROR);
+ }
+ libdwarf_compose_add_string(dbg, macname, len);
+ res = libdwarf_compose_complete(dbg, &compose_error_type);
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(NULL, error, compose_error_type);
+ return (DW_DLV_ERROR);
+ }
+ return DW_DLV_OK;
+}
+
+int
+dwarf_start_macro_file(Dwarf_P_Debug dbg,
+ Dwarf_Unsigned fileindex,
+ Dwarf_Unsigned linenumber, Dwarf_Error * error)
+{
+ size_t length_est;
+ int res;
+ int compose_error_type;
+
+ if (dbg == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+ length_est = COMMAND_LEN + LINE_LEN + LINE_LEN;
+ res = libdwarf_compose_begin(dbg, DW_MACINFO_start_file, length_est,
+ &compose_error_type);
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(NULL, error, compose_error_type);
+ return (DW_DLV_ERROR);
+ }
+ res = libdwarf_compose_add_line(dbg, fileindex,
+ &compose_error_type);
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(NULL, error, compose_error_type);
+ return (DW_DLV_ERROR);
+ }
+ res = libdwarf_compose_add_line(dbg, linenumber,
+ &compose_error_type);
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(NULL, error, compose_error_type);
+ return (DW_DLV_ERROR);
+ }
+ return DW_DLV_OK;
+}
+
+int
+dwarf_end_macro_file(Dwarf_P_Debug dbg, Dwarf_Error * error)
+{
+ size_t length_est;
+ int res;
+ int compose_error_type;
+
+ if (dbg == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+ length_est = COMMAND_LEN;
+ res = libdwarf_compose_begin(dbg, DW_MACINFO_end_file, length_est,
+ &compose_error_type);
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(NULL, error, compose_error_type);
+ return (DW_DLV_ERROR);
+ }
+ res = libdwarf_compose_complete(dbg, &compose_error_type);
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(NULL, error, compose_error_type);
+ return (DW_DLV_ERROR);
+ }
+ return DW_DLV_OK;
+}
+
+int
+dwarf_vendor_ext(Dwarf_P_Debug dbg,
+ Dwarf_Unsigned constant,
+ char *string, Dwarf_Error * error)
+{
+ size_t len;
+ size_t length_est;
+ int res;
+ int compose_error_type;
+
+ if (dbg == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
+ return (DW_DLV_ERROR);
+ }
+ if (string == 0) {
+ _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_NULL);
+ return (DW_DLV_ERROR);
+ }
+ len = strlen(string) + 1;
+ if (len == 0) {
+ _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_EMPTY);
+ return (DW_DLV_ERROR);
+ }
+ length_est = COMMAND_LEN + LINE_LEN + len;
+ res = libdwarf_compose_begin(dbg, DW_MACINFO_vendor_ext, length_est,
+ &compose_error_type);
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(NULL, error, compose_error_type);
+ return (DW_DLV_ERROR);
+ }
+ res = libdwarf_compose_add_line(dbg, constant, &compose_error_type);
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(NULL, error, compose_error_type);
+ return (DW_DLV_ERROR);
+ }
+ libdwarf_compose_add_string(dbg, string, len);
+ libdwarf_compose_complete(dbg, &compose_error_type);
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(NULL, error, compose_error_type);
+ return (DW_DLV_ERROR);
+ }
+ return DW_DLV_OK;
+}
+
+
+
+int
+_dwarf_pro_transform_macro_info_to_disk(Dwarf_P_Debug dbg,
+ Dwarf_Error * error)
+{
+ /* Total num of bytes in .debug_macinfo section. */
+ Dwarf_Unsigned mac_num_bytes;
+
+ /* Points to first byte of .debug_macinfo buffer. */
+ Dwarf_Small *macinfo;
+
+ /* Fills in the .debug_macinfo buffer. */
+ Dwarf_Small *macinfo_ptr;
+
+
+ /* Used to scan the section data buffers. */
+ struct dw_macinfo_block_s *m_prev;
+ struct dw_macinfo_block_s *m_sect;
+
+
+ /* Get the size of the debug_macinfo data */
+ mac_num_bytes = 0;
+ for (m_sect = dbg->de_first_macinfo; m_sect != NULL;
+ m_sect = m_sect->mb_next) {
+ mac_num_bytes += m_sect->mb_used_len;
+ }
+ /* The final entry has a type code of 0 to indicate It is final
+ for this CU Takes just 1 byte. */
+ mac_num_bytes += 1;
+
+ GET_CHUNK(dbg, dbg->de_elf_sects[DEBUG_MACINFO],
+ macinfo, (unsigned long) mac_num_bytes, error);
+ if (macinfo == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (0);
+ }
+
+ macinfo_ptr = macinfo;
+ m_prev = 0;
+ for (m_sect = dbg->de_first_macinfo; m_sect != NULL;
+ m_sect = m_sect->mb_next) {
+ memcpy(macinfo_ptr, m_sect->mb_data, m_sect->mb_used_len);
+ macinfo_ptr += m_sect->mb_used_len;
+ if (m_prev) {
+ _dwarf_p_dealloc(dbg, (Dwarf_Small *) m_prev);
+ m_prev = 0;
+ }
+ m_prev = m_sect;
+ }
+ *macinfo_ptr = 0; /* the type code of 0 as last entry */
+ if (m_prev) {
+ _dwarf_p_dealloc(dbg, (Dwarf_Small *) m_prev);
+ m_prev = 0;
+ }
+
+ dbg->de_first_macinfo = NULL;
+ dbg->de_current_macinfo = NULL;
+
+ return (int) dbg->de_n_debug_sect;
+}
diff --git a/libdwarf/pro_macinfo.h b/libdwarf/pro_macinfo.h
new file mode 100644
index 0000000..1b77b42
--- /dev/null
+++ b/libdwarf/pro_macinfo.h
@@ -0,0 +1,40 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+
+int _dwarf_pro_transform_macro_info_to_disk(Dwarf_P_Debug dbg,
+ Dwarf_Error * error);
diff --git a/libdwarf/pro_opaque.h b/libdwarf/pro_opaque.h
new file mode 100644
index 0000000..2b2f3dd
--- /dev/null
+++ b/libdwarf/pro_opaque.h
@@ -0,0 +1,516 @@
+/*
+
+ Copyright (C) 2000,2002,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+#include <stddef.h>
+
+/*
+ Sgidefs included to define __uint32_t,
+ a guaranteed 4-byte quantity.
+*/
+#include "libdwarfdefs.h"
+
+#define true 1
+#define false 0
+
+/* to identify a cie */
+#define DW_CIE_ID ~(0x0)
+#define DW_CIE_VERSION 1
+
+/*Dwarf_Word is unsigned word usable for index, count in memory */
+/*Dwarf_Sword is signed word usable for index, count in memory */
+/* The are 32 or 64 bits depending if 64 bit longs or not, which
+** fits the ILP32 and LP64 models
+** These work equally well with ILP64.
+*/
+
+typedef unsigned long Dwarf_Word;
+typedef long Dwarf_Sword;
+
+
+typedef signed char Dwarf_Sbyte;
+typedef unsigned char Dwarf_Ubyte;
+typedef signed short Dwarf_Shalf;
+
+/*
+ On any change that makes libdwarf producer
+ incompatible, increment this number.
+ 1->2->3 ... */
+#define PRO_VERSION_MAGIC 0xdead1
+
+
+/* these 2 are fixed sizes which must not vary with the
+** ILP32/LP64 model. These two stay at 32 bit.
+*/
+typedef __uint32_t Dwarf_ufixed;
+typedef __int32_t Dwarf_sfixed;
+
+/*
+ producer:
+ This struct is used to hold information about all
+ debug* sections. On creating a new section, section
+ names and indices are added to this struct
+ definition in pro_section.h */
+typedef struct Dwarf_P_Section_Data_s *Dwarf_P_Section_Data;
+
+/*
+ producer:
+ This struct is used to hold entries in the include directories
+ part of statement prologue. Definition in pro_line.h
+*/
+typedef struct Dwarf_P_Inc_Dir_s *Dwarf_P_Inc_Dir;
+
+/*
+ producer:
+ This struct holds file entries for the statement prologue.
+ Defined in pro_line.h
+*/
+typedef struct Dwarf_P_F_Entry_s *Dwarf_P_F_Entry;
+
+/*
+ producer:
+ This struct holds information for each cie. Defn in pro_frame.h
+*/
+typedef struct Dwarf_P_Cie_s *Dwarf_P_Cie;
+
+/*
+ producer:
+ Struct to hold line number information, different from
+ Dwarf_Line opaque type.
+*/
+typedef struct Dwarf_P_Line_s *Dwarf_P_Line;
+
+/*
+ producer:
+ Struct to hold information about address ranges.
+*/
+typedef struct Dwarf_P_Simple_nameentry_s *Dwarf_P_Simple_nameentry;
+typedef struct Dwarf_P_Simple_name_header_s *Dwarf_P_Simple_name_header;
+typedef struct Dwarf_P_Arange_s *Dwarf_P_Arange;
+typedef struct Dwarf_P_Per_Reloc_Sect_s *Dwarf_P_Per_Reloc_Sect;
+typedef struct Dwarf_P_Per_Sect_String_Attrs_s *Dwarf_P_Per_Sect_String_Attrs;
+
+/* Defined to get at the elf section numbers and section name
+ indices in symtab for the dwarf sections
+ Must match .rel.* names in _dwarf_rel_section_names
+ exactly.
+*/
+#define DEBUG_INFO 0
+#define DEBUG_LINE 1
+#define DEBUG_ABBREV 2
+#define DEBUG_FRAME 3
+#define DEBUG_ARANGES 4
+#define DEBUG_PUBNAMES 5
+#define DEBUG_STR 6
+#define DEBUG_FUNCNAMES 7
+#define DEBUG_TYPENAMES 8
+#define DEBUG_VARNAMES 9
+#define DEBUG_WEAKNAMES 10
+#define DEBUG_MACINFO 11
+#define DEBUG_LOC 12
+#define DEBUG_RANGES 13
+#define DEBUG_TYPES 14
+
+/* Maximum number of debug_* sections not including the relocations */
+#define NUM_DEBUG_SECTIONS 15
+
+/* Describes the data needed to generate line table header info
+ so we can vary the init at runtime. */
+struct Dwarf_P_Line_Inits_s {
+ unsigned pi_version; /* line table version number */
+ unsigned pi_default_is_stmt; /* default value for is_stmt */
+
+ /* Size of the smallest instruction, in bytes. */
+ unsigned pi_minimum_instruction_length;
+
+ /* Make this >1 for VLIW machines. */
+ unsigned pi_maximum_operations_per_instruction;
+
+ /* Normally opcode_base is determined by pi_version, but we
+ allow manual setting here so we can generate data like
+ GNU with a DWARF3 opcode base in a DWARF2 section.
+ This determines how much of the header_opcode_lengths
+ table is emitted in the line table header */
+ unsigned pi_opcode_base;
+
+ int pi_line_base; /* For line table header. */
+ int pi_line_range; /* For line table header. */
+};
+
+
+struct Dwarf_P_Die_s {
+ Dwarf_Unsigned di_offset; /* offset in debug info */
+ char *di_abbrev; /* abbreviation */
+ Dwarf_Word di_abbrev_nbytes; /* # of bytes in abbrev */
+ Dwarf_Tag di_tag;
+ Dwarf_P_Die di_parent; /* parent of current die */
+ Dwarf_P_Die di_child; /* first child */
+ /* The last child field makes linking up children an O(1) operation,
+ See pro_die.c. */
+ Dwarf_P_Die di_last_child;
+ Dwarf_P_Die di_left; /* left sibling */
+ Dwarf_P_Die di_right; /* right sibling */
+ Dwarf_P_Attribute di_attrs; /* list of attributes */
+ Dwarf_P_Attribute di_last_attr; /* last attribute */
+ int di_n_attr; /* number of attributes */
+ Dwarf_P_Debug di_dbg; /* For memory management */
+ Dwarf_Unsigned di_marker; /* used to attach symbols to dies */
+};
+
+
+/* producer fields */
+struct Dwarf_P_Attribute_s {
+ Dwarf_Half ar_attribute; /* Attribute Value. */
+ Dwarf_Half ar_attribute_form; /* Attribute Form. */
+ Dwarf_P_Die ar_ref_die; /* die pointer if form ref */
+ char *ar_data; /* data, format given by form */
+ Dwarf_Unsigned ar_nbytes; /* no. of bytes of data */
+ Dwarf_Unsigned ar_rel_symidx; /* when attribute has a
+ relocatable value, holds
+ index of symbol in SYMTAB */
+ Dwarf_Ubyte ar_rel_type; /* relocation type */
+ Dwarf_Word ar_rel_offset; /* Offset of relocation within block */
+ char ar_reloc_len; /* Number of bytes that relocation
+ applies to. 4 or 8. Unused and may
+ be 0 if if ar_rel_type is
+ R_MIPS_NONE */
+ Dwarf_P_Attribute ar_next;
+};
+
+/* A block of .debug_macinfo data: this forms a series of blocks.
+** Each macinfo input is compressed immediately and put into
+** the current block if room, else a newblock allocated.
+** The space allocation is such that the block and the macinfo
+** data are one malloc block: free with a pointer to this and the
+** mb_data is freed automatically.
+** Like the struct hack, but legal ANSI C.
+*/
+struct dw_macinfo_block_s {
+ struct dw_macinfo_block_s *mb_next;
+ unsigned long mb_avail_len;
+ unsigned long mb_used_len;
+ unsigned long mb_macinfo_data_space_len;
+ char *mb_data;/* original malloc ptr. */
+};
+
+/* dwarf_sn_kind is for the array of similarly-treated
+ name -> cu ties
+*/
+enum dwarf_sn_kind { dwarf_snk_pubname, dwarf_snk_funcname,
+ dwarf_snk_weakname, dwarf_snk_typename,
+ dwarf_snk_varname,
+ dwarf_snk_entrycount /* this one must be last */
+};
+
+
+
+/* The calls to add a varname etc use a list of
+ these as the list.
+*/
+struct Dwarf_P_Simple_nameentry_s {
+ Dwarf_P_Die sne_die;
+ char *sne_name;
+ int sne_name_len;
+ Dwarf_P_Simple_nameentry sne_next;
+};
+
+/* An array of these, each of which heads a list
+ of Dwarf_P_Simple_nameentry
+*/
+struct Dwarf_P_Simple_name_header_s {
+ Dwarf_P_Simple_nameentry sn_head;
+ Dwarf_P_Simple_nameentry sn_tail;
+ Dwarf_Signed sn_count;
+
+ /* Length that will be generated, not counting fixed header or
+ trailer */
+ Dwarf_Signed sn_net_len;
+};
+typedef int (*_dwarf_pro_reloc_name_func_ptr) (Dwarf_P_Debug dbg,
+ int sec_index,
+ Dwarf_Unsigned offset,/* r_offset */
+ Dwarf_Unsigned symidx,
+ enum Dwarf_Rel_Type type,
+ int reltarget_length);
+
+typedef int (*_dwarf_pro_reloc_length_func_ptr) (Dwarf_P_Debug dbg,
+ int sec_index, Dwarf_Unsigned offset,/* r_offset */
+ Dwarf_Unsigned start_symidx,
+ Dwarf_Unsigned end_symidx,
+ enum Dwarf_Rel_Type type,
+ int reltarget_length);
+typedef int (*_dwarf_pro_transform_relocs_func_ptr) (Dwarf_P_Debug dbg,
+ Dwarf_Signed *
+ new_sec_count);
+
+/*
+ Each slot in a block of slots could be:
+ a binary stream relocation entry (32 or 64bit relocation data)
+ a SYMBOLIC relocation entry.
+ During creation sometimes we create multiple chained blocks,
+ but sometimes we create a single long block.
+ Before returning reloc data to caller,
+ we switch to a single, long-enough,
+ block.
+
+ We make counters here Dwarf_Unsigned so that we
+ get sufficient alignment. Since we use space after
+ the struct (at malloc time) for user data which
+ must have Dwarf_Unsigned alignment, this
+ struct must have that alignment too.
+*/
+struct Dwarf_P_Relocation_Block_s {
+ Dwarf_Unsigned rb_slots_in_block; /* slots in block, as created */
+ Dwarf_Unsigned rb_next_slot_to_use; /* counter, start at 0. */
+ struct Dwarf_P_Relocation_Block_s *rb_next;
+ char *rb_where_to_add_next; /* pointer to next slot (might be past
+ end, depending on
+ rb_next_slot_to_use) */
+ char *rb_data; /* data area */
+};
+
+/* One of these per potential relocation section
+ So one per actual dwarf section.
+ Left zeroed when not used (some sections have
+ no relocations).
+*/
+struct Dwarf_P_Per_Reloc_Sect_s {
+ unsigned long pr_reloc_total_count; /* total number of entries
+ across all blocks */
+
+ unsigned long pr_slots_per_block_to_alloc; /* at Block alloc, this
+ is the default number of slots to use */
+
+ int pr_sect_num_of_reloc_sect; /* sect number returned by
+ de_callback_func() or de_callback_func_b() or_c()
+ call, this is the sect
+ number of the relocation section. */
+
+ /* singly-linked list. add at and ('last') with count of blocks */
+ struct Dwarf_P_Relocation_Block_s *pr_first_block;
+ struct Dwarf_P_Relocation_Block_s *pr_last_block;
+ unsigned long pr_block_count;
+};
+
+#define DEFAULT_SLOTS_PER_BLOCK 3
+
+typedef struct memory_list_s {
+ struct memory_list_s *prev;
+ struct memory_list_s *next;
+} memory_list_t;
+
+struct Dwarf_P_Per_Sect_String_Attrs_s {
+ int sect_sa_section_number;
+ unsigned sect_sa_n_alloc;
+ unsigned sect_sa_n_used;
+ Dwarf_P_String_Attr sect_sa_list;
+};
+
+/* Fields used by producer */
+struct Dwarf_P_Debug_s {
+ /* Used to catch dso passing dbg to another DSO with incompatible
+ version of libdwarf See PRO_VERSION_MAGIC */
+ int de_version_magic_number;
+
+ Dwarf_Handler de_errhand;
+ /* de_user_data is provided so users can use it to readily tie
+ a callback to anything they desire. The contents are not
+ used by libdwarf except to pass the data as a callback
+ argument. New in June 2011. Available in
+ dwarf_pro_init_c() and its callback function. */
+ void * de_user_data;
+ Dwarf_Ptr de_errarg;
+
+ /* Call back function, used to create .debug* sections. Provided
+ By user. Only of these used per dbg. */
+ Dwarf_Callback_Func de_callback_func;
+ Dwarf_Callback_Func_b de_callback_func_b;
+ Dwarf_Callback_Func_c de_callback_func_c;
+
+ /* Flags from producer_init call */
+ Dwarf_Unsigned de_flags;
+
+ /* This holds information on debug section stream output, including
+ the stream data */
+ Dwarf_P_Section_Data de_debug_sects;
+
+ /* Pointer to the 'current active' section */
+ Dwarf_P_Section_Data de_current_active_section;
+
+ /* Number of debug data streams globs. */
+ Dwarf_Word de_n_debug_sect;
+
+ /* File entry information, null terminated singly-linked list */
+ Dwarf_P_F_Entry de_file_entries;
+ Dwarf_P_F_Entry de_last_file_entry;
+ Dwarf_Unsigned de_n_file_entries;
+
+ /* Has the directories used to search for source files */
+ Dwarf_P_Inc_Dir de_inc_dirs;
+ Dwarf_P_Inc_Dir de_last_inc_dir;
+ Dwarf_Unsigned de_n_inc_dirs;
+
+ /* Has all the line number info for the stmt program */
+ Dwarf_P_Line de_lines;
+ Dwarf_P_Line de_last_line;
+
+ /* List of cie's for the debug unit */
+ Dwarf_P_Cie de_frame_cies;
+ Dwarf_P_Cie de_last_cie;
+ Dwarf_Unsigned de_n_cie;
+
+ /* Singly-linked list of fde's for the debug unit */
+ Dwarf_P_Fde de_frame_fdes;
+ Dwarf_P_Fde de_last_fde;
+ Dwarf_Unsigned de_n_fde;
+
+ /* First die, leads to all others */
+ Dwarf_P_Die de_dies;
+
+ /* Pointer to list of strings */
+ char *de_strings;
+
+ /* Pointer to chain of aranges */
+ Dwarf_P_Arange de_arange;
+ Dwarf_P_Arange de_last_arange;
+ Dwarf_Sword de_arange_count;
+
+ /* macinfo controls. */
+ /* first points to beginning of the list during creation */
+ struct dw_macinfo_block_s *de_first_macinfo;
+
+ /* current points to the current, unfilled, block */
+ struct dw_macinfo_block_s *de_current_macinfo;
+
+ /* Pointer to the first section, to support reset_section_bytes */
+ Dwarf_P_Section_Data de_first_debug_sect;
+
+ /* Handles pubnames, weaknames, etc. See dwarf_sn_kind in
+ pro_opaque.h */
+ struct Dwarf_P_Simple_name_header_s
+ de_simple_name_headers[dwarf_snk_entrycount];
+
+ /* Relocation data. not all sections will actally have relocation
+ info, of course */
+ struct Dwarf_P_Per_Reloc_Sect_s de_reloc_sect[NUM_DEBUG_SECTIONS];
+ int de_reloc_next_to_return; /* iterator on reloc sections
+ (SYMBOLIC output) */
+
+ /* used in remembering sections */
+ int de_elf_sects[NUM_DEBUG_SECTIONS]; /* elf sect number of
+ the section itself, DEBUG_LINE for example */
+
+ Dwarf_Unsigned de_sect_name_idx[NUM_DEBUG_SECTIONS]; /* section
+ name index or handle for the name of the symbol for
+ DEBUG_LINE for example */
+
+ int de_offset_reloc; /* offset reloc type, R_MIPS_32 for
+ example. Specific to the ABI being
+ produced. Relocates offset size
+ field */
+ int de_exc_reloc; /* reloc type specific to exception
+ table relocs. */
+ int de_ptr_reloc; /* standard reloc type, R_MIPS_32 for
+ example. Specific to the ABI being
+ produced. relocates pointer size
+ field */
+
+ unsigned char de_offset_size; /* section offset. Here to
+ avoid test of abi in macro
+ at run time MIPS -n32 4,
+ -64 8. */
+
+ unsigned char de_pointer_size; /* size of pointer in target.
+ Here to avoid test of abi in
+ macro at run time MIPS -n32
+ 4, -64 is 8. */
+
+ unsigned char de_is_64bit; /* non-zero if is 64bit. Else 32 bit:
+ used for passing this info as a flag */
+ unsigned char de_relocation_record_size; /* reloc record size
+ varies by ABI and
+ relocation-output
+ method (stream or
+ symbolic) */
+
+ unsigned char de_64bit_extension;/* non-zero if creating 64 bit
+ offsets using dwarf2-99
+ extension proposal */
+
+ int de_ar_data_attribute_form; /* data8, data4 abi dependent */
+ int de_ar_ref_attr_form; /* ref8 ref4 , abi dependent */
+
+ /* simple name relocations */
+ _dwarf_pro_reloc_name_func_ptr de_reloc_name;
+
+ /* relocations for a length, requiring a pair of symbols */
+ _dwarf_pro_reloc_length_func_ptr de_reloc_pair;
+
+ _dwarf_pro_transform_relocs_func_ptr de_transform_relocs_to_disk;
+
+ /* following used for macro buffers */
+ unsigned long de_compose_avail;
+ unsigned long de_compose_used_len;
+
+ unsigned char de_same_endian;
+ void *(*de_copy_word) (void *, const void *, size_t);
+
+ /* Add new fields at the END of this struct to preserve some hope
+ of sensible behavior on dbg passing between DSOs linked with
+ mismatched libdwarf producer versions. */
+
+ Dwarf_P_Marker de_markers; /* pointer to array of markers */
+ unsigned de_marker_n_alloc;
+ unsigned de_marker_n_used;
+ int de_sect_sa_next_to_return; /* Iterator on sring attrib sects */
+ /* String attributes data of each section. */
+ struct Dwarf_P_Per_Sect_String_Attrs_s de_sect_string_attr[NUM_DEBUG_SECTIONS];
+ /* Hold data needed to init new line output flexibly. */
+ struct Dwarf_P_Line_Inits_s de_line_inits;
+};
+
+#define CURRENT_VERSION_STAMP 2
+
+Dwarf_Unsigned _dwarf_add_simple_name_entry(Dwarf_P_Debug dbg,
+ Dwarf_P_Die die,
+ char *entry_name,
+ enum dwarf_sn_kind
+ entrykind,
+ Dwarf_Error * error);
+
+
+#define DISTINGUISHED_VALUE 0xffffffff /* 64bit extension flag */
diff --git a/libdwarf/pro_pubnames.c b/libdwarf/pro_pubnames.c
new file mode 100644
index 0000000..4758652
--- /dev/null
+++ b/libdwarf/pro_pubnames.c
@@ -0,0 +1,62 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_ELFACCESS_H
+#include <elfaccess.h>
+#endif
+#include "pro_incl.h"
+#include "pro_section.h"
+
+
+/* This function adds another public name to the
+ list of public names for the given Dwarf_P_Debug.
+ It returns 0 on error, and 1 otherwise. */
+
+Dwarf_Unsigned
+dwarf_add_pubname(Dwarf_P_Debug dbg,
+ Dwarf_P_Die die,
+ char *pubname_name, Dwarf_Error * error)
+{
+ return
+ _dwarf_add_simple_name_entry(dbg, die, pubname_name,
+ dwarf_snk_pubname, error);
+}
diff --git a/libdwarf/pro_reloc.c b/libdwarf/pro_reloc.c
new file mode 100644
index 0000000..48c8065
--- /dev/null
+++ b/libdwarf/pro_reloc.c
@@ -0,0 +1,263 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2008-2011 David Anderson, Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+/*#include <elfaccess.h> */
+#include "pro_incl.h"
+
+
+/*Do initial alloc of newslots slots.
+ Fails only if malloc fails.
+
+ Supposed to be called before any relocs allocated.
+ Ignored if after any allocated.
+
+ Part of an optimization, so that for a known 'newslots'
+ relocations count we can preallocate the right size block.
+ Called from just 2 places.
+
+ returns DW_DLV_OK or DW_DLV_ERROR
+*/
+int
+_dwarf_pro_pre_alloc_n_reloc_slots(Dwarf_P_Debug dbg,
+ int rel_sec_index,
+ Dwarf_Unsigned newslots)
+{
+ unsigned long len = 0;
+ struct Dwarf_P_Relocation_Block_s *data = 0;
+ Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[rel_sec_index];
+ unsigned long slots_in_blk = (unsigned long) newslots;
+ unsigned long rel_rec_size = dbg->de_relocation_record_size;
+
+ if (prel->pr_first_block)
+ return DW_DLV_OK; /* do nothing */
+
+ len = sizeof(struct Dwarf_P_Relocation_Block_s) +
+ slots_in_blk * rel_rec_size;
+
+
+ data = (struct Dwarf_P_Relocation_Block_s *)
+ _dwarf_p_get_alloc(dbg, len);
+ if (!data) {
+ return DW_DLV_ERROR;
+ }
+ data->rb_slots_in_block = slots_in_blk; /* could use default
+ here, as fallback in case our origininal
+ estimate wrong. When we call this we
+ presumably know what we are doing, so
+ keep this count for now */
+ data->rb_next_slot_to_use = 0;
+ data->rb_where_to_add_next =
+ ((char *) data) + sizeof(struct Dwarf_P_Relocation_Block_s);
+ data->rb_data = data->rb_where_to_add_next;
+
+ prel->pr_first_block = data;
+ prel->pr_last_block = data;
+ prel->pr_block_count = 1;
+
+
+ return DW_DLV_OK;
+}
+
+
+/*Do alloc of slots.
+ Fails only if malloc fails.
+
+ Only allocator used.
+
+ returns DW_DLV_OK or DW_DLV_ERROR
+*/
+int
+_dwarf_pro_alloc_reloc_slots(Dwarf_P_Debug dbg, int rel_sec_index)
+{
+ unsigned long len = 0;
+ struct Dwarf_P_Relocation_Block_s *data = 0;
+ Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[rel_sec_index];
+ unsigned long slots_in_blk = prel->pr_slots_per_block_to_alloc;
+ unsigned long rel_rec_size = dbg->de_relocation_record_size;
+
+ len = sizeof(struct Dwarf_P_Relocation_Block_s) +
+ slots_in_blk * rel_rec_size;
+
+ data = (struct Dwarf_P_Relocation_Block_s *)
+ _dwarf_p_get_alloc(dbg, len);
+ if (!data) {
+ return DW_DLV_ERROR;
+ }
+
+ if (prel->pr_first_block) {
+ prel->pr_last_block->rb_next = data;
+ prel->pr_last_block = data;
+ prel->pr_block_count += 1;
+
+ } else {
+
+ prel->pr_first_block = data;
+ prel->pr_last_block = data;
+ prel->pr_block_count = 1;
+ }
+
+ data->rb_slots_in_block = slots_in_blk;
+ data->rb_next_slot_to_use = 0;
+ data->rb_where_to_add_next =
+ ((char *) data) + sizeof(struct Dwarf_P_Relocation_Block_s);
+ data->rb_data = data->rb_where_to_add_next;
+
+ return DW_DLV_OK;
+
+}
+
+/* Reserve a slot. return DW_DLV_OK if succeeds.
+
+ Return DW_DLV_ERROR if fails (malloc error).
+
+ Use the relrec_to_fill to pass back a pointer to
+ a slot space to use. */
+int
+_dwarf_pro_reloc_get_a_slot(Dwarf_P_Debug dbg,
+ int base_sec_index, void **relrec_to_fill)
+{
+ struct Dwarf_P_Relocation_Block_s *data = 0;
+ Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[base_sec_index];
+ unsigned long rel_rec_size = dbg->de_relocation_record_size;
+
+ char *ret_addr = 0;
+
+ data = prel->pr_last_block;
+ if ((data == 0) ||
+ (data->rb_next_slot_to_use >= data->rb_slots_in_block)) {
+ int res;
+
+ res = _dwarf_pro_alloc_reloc_slots(dbg, base_sec_index);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ }
+
+ data = prel->pr_last_block;
+ /* now we have an empty slot */
+ ret_addr = data->rb_where_to_add_next;
+
+ data->rb_where_to_add_next += rel_rec_size;
+ data->rb_next_slot_to_use += 1;
+
+ prel->pr_reloc_total_count += 1;
+
+ *relrec_to_fill = (void *) ret_addr;
+
+ return DW_DLV_OK;
+
+}
+
+/*
+ On success returns count of
+ .rel.* sections that are symbolic
+ thru count_of_relocation_sections.
+
+ On success, returns DW_DLV_OK.
+
+ If this is not a 'symbolic' run, returns
+ DW_DLV_NO_ENTRY.
+
+ No errors are possible.
+
+
+
+
+*/
+
+/*ARGSUSED*/ int
+dwarf_get_relocation_info_count(Dwarf_P_Debug dbg,
+ Dwarf_Unsigned *
+ count_of_relocation_sections,
+ int *drd_buffer_version,
+ Dwarf_Error * error)
+{
+ if (dbg->de_flags & DW_DLC_SYMBOLIC_RELOCATIONS) {
+ int i;
+ unsigned int count = 0;
+
+ for (i = 0; i < NUM_DEBUG_SECTIONS; ++i) {
+ if (dbg->de_reloc_sect[i].pr_reloc_total_count > 0) {
+ ++count;
+ }
+ }
+ *count_of_relocation_sections = (Dwarf_Unsigned) count;
+ *drd_buffer_version = DWARF_DRD_BUFFER_VERSION;
+ return DW_DLV_OK;
+ }
+ return DW_DLV_NO_ENTRY;
+}
+
+int
+dwarf_get_relocation_info(Dwarf_P_Debug dbg,
+ Dwarf_Signed * elf_section_index,
+ Dwarf_Signed * elf_section_index_link,
+ Dwarf_Unsigned * relocation_buffer_count,
+ Dwarf_Relocation_Data * reldata_buffer,
+ Dwarf_Error * error)
+{
+ int next = dbg->de_reloc_next_to_return;
+
+ if (dbg->de_flags & DW_DLC_SYMBOLIC_RELOCATIONS) {
+ int i;
+
+ for (i = next; i < NUM_DEBUG_SECTIONS; ++i) {
+ Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[i];
+
+ if (prel->pr_reloc_total_count > 0) {
+ dbg->de_reloc_next_to_return = i + 1;
+
+
+ /* ASSERT: prel->.pr_block_count == 1 */
+
+ *elf_section_index = prel->pr_sect_num_of_reloc_sect;
+ *elf_section_index_link = dbg->de_elf_sects[i];
+ *relocation_buffer_count = prel->pr_reloc_total_count;
+ *reldata_buffer = (Dwarf_Relocation_Data)
+ (prel->pr_first_block->rb_data);
+ return DW_DLV_OK;
+ }
+ }
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, DW_DLV_ERROR);
+ }
+ return DW_DLV_NO_ENTRY;
+}
diff --git a/libdwarf/pro_reloc.h b/libdwarf/pro_reloc.h
new file mode 100644
index 0000000..81954fc
--- /dev/null
+++ b/libdwarf/pro_reloc.h
@@ -0,0 +1,47 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+
+int _dwarf_pro_pre_alloc_n_reloc_slots(Dwarf_P_Debug dbg,
+ int rel_sec_index,
+ Dwarf_Unsigned newslots);
+
+int _dwarf_pro_alloc_reloc_slots(Dwarf_P_Debug dbg, int rel_sec_index);
+
+int _dwarf_pro_reloc_get_a_slot(Dwarf_P_Debug dbg,
+ int base_sec_index,
+ void **relrec_to_fill);
diff --git a/libdwarf/pro_reloc_stream.c b/libdwarf/pro_reloc_stream.c
new file mode 100644
index 0000000..74d217b
--- /dev/null
+++ b/libdwarf/pro_reloc_stream.c
@@ -0,0 +1,291 @@
+/*
+
+ Copyright (C) 2000,2001,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved.
+ Portions Copyright 2008-2011 David Anderson, Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_ELFACCESS_H
+#include <elfaccess.h>
+#else
+/* Set r_info as defined by ELF generic ABI */
+#define Set_REL32_info(r,s,t) ((r).r_info = ELF32_R_INFO(s,t))
+#define Set_REL64_info(r,s,t) ((r).r_info = ELF64_R_INFO(s,t))
+#endif
+#include "pro_incl.h"
+#include "pro_section.h"
+#include "pro_reloc.h"
+#include "pro_reloc_stream.h"
+
+/* Return DW_DLV_ERROR on malloc error or reltarget_length error.
+ Return DW_DLV_OK otherwise */
+/*ARGSUSED*/ int
+_dwarf_pro_reloc_name_stream64(Dwarf_P_Debug dbg,
+ int base_sec_index,
+ Dwarf_Unsigned offset, /* r_offset of reloc */
+ Dwarf_Unsigned symidx,
+ enum Dwarf_Rel_Type type,
+ int reltarget_length)
+{
+#if HAVE_ELF64_GETEHDR
+ REL64 *elf64_reloc = 0;
+ void *relrec_to_fill = 0;
+ int res = 0;
+ int rel_type = 0;
+
+ res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index,
+ &relrec_to_fill);
+ if (res != DW_DLV_OK)
+ return res;
+
+
+ if (type == dwarf_drt_data_reloc) {
+ if (reltarget_length == dbg->de_offset_size) {
+ rel_type = dbg->de_offset_reloc;
+ } else if (reltarget_length == dbg->de_pointer_size) {
+ rel_type = dbg->de_ptr_reloc;
+ } else {
+ return DW_DLV_ERROR;
+ }
+ } else if (type == dwarf_drt_segment_rel) {
+ rel_type = dbg->de_exc_reloc;
+ } else {
+ /* We are in trouble: improper use of stream relocations.
+ Someone else will diagnose */
+ rel_type = 0;
+ }
+
+ elf64_reloc = (REL64 *)relrec_to_fill;
+ elf64_reloc->r_offset = offset;
+ Set_REL64_info(*elf64_reloc, symidx, rel_type);
+ return DW_DLV_OK;
+#else /* !HAVE_ELF64_GETEHDR */
+ return DW_DLV_ERROR;
+#endif /* #if HAVE_ELF64_GETEHDR */
+}
+
+/* Return DW_DLV_ERROR on malloc error or reltarget_length error.
+ Return DW_DLV_OK otherwise
+ a binary reloc: 32bit ABI */ int
+_dwarf_pro_reloc_name_stream32(Dwarf_P_Debug dbg, int base_sec_index,
+ Dwarf_Unsigned offset, /* r_offset of reloc */
+ Dwarf_Unsigned symidx,
+ enum Dwarf_Rel_Type type,
+ int reltarget_length)
+{
+ REL32 *elf32_reloc = 0;
+ void *relrec_to_fill = 0;
+ int res = 0;
+ int rel_type = 0;
+
+ res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index,
+ &relrec_to_fill);
+ if (res != DW_DLV_OK)
+ return res;
+ if (type == dwarf_drt_data_reloc) {
+ if (reltarget_length == dbg->de_offset_size) {
+ rel_type = dbg->de_offset_reloc;
+ } else if (reltarget_length == dbg->de_pointer_size) {
+ rel_type = dbg->de_ptr_reloc;
+ } else {
+ return DW_DLV_ERROR;
+ }
+ } else if (type == dwarf_drt_segment_rel) {
+ rel_type = dbg->de_exc_reloc;
+ } else {
+ /* We are in trouble: improper use of stream relocations.
+ Someone else will diagnose */
+ rel_type = 0;
+ }
+
+ elf32_reloc = (REL32*)relrec_to_fill;
+ elf32_reloc->r_offset = (Elf32_Addr) offset;
+ Set_REL32_info(*elf32_reloc, (Dwarf_Word) symidx, rel_type);
+ return DW_DLV_OK;
+
+ /* get a slot, fill in the slot entry */
+}
+
+
+
+/* Return DW_DLV_OK.
+ Never can really do anything: lengths cannot
+ be represented as end-start in a stream. */
+/*ARGSUSED*/ int
+_dwarf_pro_reloc_length_stream(Dwarf_P_Debug dbg,
+ int base_sec_index,
+ Dwarf_Unsigned offset, /* r_offset of reloc */
+ Dwarf_Unsigned start_symidx,
+ Dwarf_Unsigned end_symidx,
+ enum Dwarf_Rel_Type type,
+ int reltarget_length)
+{
+ /* get a slot, fill in the slot entry */
+ return DW_DLV_OK;
+}
+
+
+/* Ensure each stream is a single buffer and
+ add that single buffer to the set of stream buffers.
+
+ By creating a new buffer and copying if necessary.
+
+ Free the input set of buffers if we consolidate.
+ Return -1 on error (malloc failure)
+
+ Return DW_DLV_OK on success. Any other return indicates
+ malloc failed. */
+int
+_dwarf_stream_relocs_to_disk(Dwarf_P_Debug dbg,
+ Dwarf_Signed * new_sec_count)
+{
+ unsigned long total_size = 0;
+ Dwarf_Small *data = 0;
+ int sec_index = 0;
+ unsigned long i = 0;
+ Dwarf_Error err = 0;
+ Dwarf_Error *error = &err;
+
+ Dwarf_Signed sec_count = 0;
+
+ Dwarf_P_Per_Reloc_Sect p_reloc = &dbg->de_reloc_sect[0];
+
+ for (i = 0; i < NUM_DEBUG_SECTIONS; ++i, ++p_reloc) {
+ unsigned long ct = p_reloc->pr_reloc_total_count;
+ unsigned len = 0;
+ struct Dwarf_P_Relocation_Block_s *p_blk = 0;
+ struct Dwarf_P_Relocation_Block_s *p_blk_last = 0;
+ Dwarf_P_Per_Reloc_Sect prb = 0;
+
+ if (ct == 0) {
+ continue;
+ }
+ prb = &dbg->de_reloc_sect[i];
+ len = dbg->de_relocation_record_size;
+ ++sec_count;
+
+ total_size = ct * len;
+ sec_index = prb->pr_sect_num_of_reloc_sect;
+ if (sec_index == 0) {
+ /* Call de_callback_func or de_callback_func_b or _c, getting
+ section number of reloc section. */
+ int rel_section_index = 0;
+ Dwarf_Unsigned name_idx = 0;
+ int int_name = 0;
+ int err = 0;
+
+ if (dbg->de_callback_func_c) {
+ rel_section_index =
+ dbg->de_callback_func_c(_dwarf_rel_section_names[i],
+ /* size */ dbg->de_relocation_record_size,
+ /* type */ SHT_REL,
+ /* flags */ 0,
+ /* link to symtab, which we cannot
+ know */ 0,
+ /* info == link to sec rels apply to */
+ dbg->de_elf_sects[i],
+ &name_idx,
+ dbg->de_user_data,
+ &err);
+ } else if (dbg->de_callback_func_b) {
+ rel_section_index =
+ dbg->de_callback_func_b(_dwarf_rel_section_names[i],
+ /* size */ dbg->de_relocation_record_size,
+ /* type */ SHT_REL,
+ /* flags */ 0,
+ /* link to symtab, which we cannot
+ know */ 0,
+ /* info == link to sec rels apply to */
+ dbg->de_elf_sects[i],
+ &name_idx, &err);
+ } else {
+ rel_section_index =
+ dbg->de_callback_func(_dwarf_rel_section_names[i],
+ /* size */ dbg->de_relocation_record_size,
+ /* type */ SHT_REL,
+ /* flags */ 0,
+ /* link to symtab, which we cannot
+ know */ 0,
+ /* info == link to sec rels apply to */
+ dbg->de_elf_sects[i], &int_name, &err);
+ name_idx = int_name;
+ }
+ if (rel_section_index == -1) {
+ {
+ _dwarf_p_error(dbg, error, DW_DLE_ELF_SECT_ERR);
+ return (DW_DLV_ERROR);
+ }
+
+ }
+ prb->pr_sect_num_of_reloc_sect = rel_section_index;
+ sec_index = rel_section_index;
+ }
+ GET_CHUNK(dbg, sec_index, data, total_size, &err);
+ p_blk = p_reloc->pr_first_block;
+
+ /* Following loop executes at least once. Effects the
+ consolidation to a single block or, if already a single
+ block, simply copies to the output buffer. And frees the
+ input block. The new block is in the de_debug_sects list. */
+ while (p_blk) {
+
+ unsigned long len =
+ p_blk->rb_where_to_add_next - p_blk->rb_data;
+
+ memcpy(data, p_blk->rb_data, len);
+
+
+ data += len;
+
+ p_blk_last = p_blk;
+ p_blk = p_blk->rb_next;
+
+ _dwarf_p_dealloc(dbg, (Dwarf_Small *) p_blk_last);
+ }
+ /* ASSERT: sum of len copied == total_size */
+
+ /* We have copied the input, now drop the pointers to it. For
+ debugging, leave the other data untouched. */
+ p_reloc->pr_first_block = 0;
+ p_reloc->pr_last_block = 0;
+ }
+
+ *new_sec_count = sec_count;
+ return DW_DLV_OK;
+}
diff --git a/libdwarf/pro_reloc_stream.h b/libdwarf/pro_reloc_stream.h
new file mode 100644
index 0000000..22a3727
--- /dev/null
+++ b/libdwarf/pro_reloc_stream.h
@@ -0,0 +1,61 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+
+int _dwarf_pro_reloc_name_stream64(Dwarf_P_Debug dbg,
+ int base_sec_index,
+ Dwarf_Unsigned offset,/* r_offset of reloc */
+ Dwarf_Unsigned symidx,
+ enum Dwarf_Rel_Type,
+ int reltarget_length);
+int _dwarf_pro_reloc_name_stream32(Dwarf_P_Debug dbg,
+ int base_sec_index,
+ Dwarf_Unsigned offset,/* r_offset of reloc */
+ Dwarf_Unsigned symidx,
+ enum Dwarf_Rel_Type,
+ int reltarget_length);
+
+int _dwarf_pro_reloc_length_stream(Dwarf_P_Debug dbg,
+ int base_sec_index,
+ Dwarf_Unsigned offset, /* r_offset of reloc */
+ Dwarf_Unsigned start_symidx,
+ Dwarf_Unsigned end_symidx,
+ enum Dwarf_Rel_Type,
+ int reltarget_length);
+
+int _dwarf_stream_relocs_to_disk(Dwarf_P_Debug dbg,
+ Dwarf_Signed * new_sec_count);
diff --git a/libdwarf/pro_reloc_symbolic.c b/libdwarf/pro_reloc_symbolic.c
new file mode 100644
index 0000000..3db4505
--- /dev/null
+++ b/libdwarf/pro_reloc_symbolic.c
@@ -0,0 +1,279 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+/*#include <elfaccess.h> */
+#include "pro_incl.h"
+#include "pro_section.h"
+#include "pro_reloc.h"
+#include "pro_reloc_symbolic.h"
+
+/* Return DW_DLV_ERROR on malloc error.
+ Return DW_DLV_OK otherwise */
+
+int
+_dwarf_pro_reloc_name_symbolic(Dwarf_P_Debug dbg,
+ int base_sec_index,
+ Dwarf_Unsigned offset, /* r_offset of reloc */
+ Dwarf_Unsigned symidx,
+ enum Dwarf_Rel_Type type,
+ int reltarget_length)
+{
+ /* get a slot, fill in the slot entry */
+ void *relrec_to_fill = 0;
+ int res = 0;
+ struct Dwarf_Relocation_Data_s *slotp;
+
+ res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index,
+ &relrec_to_fill);
+ if (res != DW_DLV_OK)
+ return res;
+ slotp = (struct Dwarf_Relocation_Data_s *) relrec_to_fill;
+ slotp->drd_type = type;
+ slotp->drd_length = reltarget_length;
+ slotp->drd_offset = offset;
+ slotp->drd_symbol_index = symidx;
+ return DW_DLV_OK;
+}
+
+
+
+/* Return DW_DLV_ERROR on malloc error.
+ Return DW_DLV_OK otherwise */
+int
+_dwarf_pro_reloc_length_symbolic(Dwarf_P_Debug dbg,
+ int base_sec_index,
+ Dwarf_Unsigned offset, /* r_offset of reloc */
+ Dwarf_Unsigned start_symidx,
+ Dwarf_Unsigned end_symidx,
+ enum Dwarf_Rel_Type type,
+ int reltarget_length)
+{
+ /* get a slot, fill in the slot entry */
+ void *relrec_to_fill = 0;
+ int res = 0;
+ struct Dwarf_Relocation_Data_s *slotp1 = 0;
+ struct Dwarf_Relocation_Data_s *slotp2 = 0;
+
+ res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index,
+ &relrec_to_fill);
+ if (res != DW_DLV_OK)
+ return res;
+ slotp1 = (struct Dwarf_Relocation_Data_s *) relrec_to_fill;
+ res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index,
+ &relrec_to_fill);
+ if (res != DW_DLV_OK)
+ return res;
+ slotp2 = (struct Dwarf_Relocation_Data_s *) relrec_to_fill;
+
+ /* ASSERT: type == dwarf_drt_first_of_length_type_pair */
+ slotp1->drd_type = type;
+ slotp1->drd_length = reltarget_length;
+ slotp1->drd_offset = offset;
+ slotp1->drd_symbol_index = start_symidx;
+
+ slotp2->drd_type = dwarf_drt_second_of_length_pair;
+ slotp2->drd_length = reltarget_length;
+ slotp2->drd_offset = offset;
+ slotp2->drd_symbol_index = end_symidx;
+ return DW_DLV_OK;
+}
+
+/* Reset whatever fields of Dwarf_P_Per_Reloc_Sect_s
+ we must to allow adding a fresh new single
+ block easily (block consolidation use only). */
+static void
+_dwarf_reset_reloc_sect_info(struct Dwarf_P_Per_Reloc_Sect_s *pblk,
+ unsigned long ct)
+{
+
+
+ /* Do not zero pr_sect_num_of_reloc_sect */
+ pblk->pr_reloc_total_count = 0;
+ pblk->pr_first_block = 0;
+ pblk->pr_last_block = 0;
+ pblk->pr_block_count = 0;
+ pblk->pr_slots_per_block_to_alloc = ct;
+}
+
+/* Ensure each stream is a single buffer and
+ add that single buffer to the set of stream buffers.
+
+ By creating a new buffer and copying if necessary.
+ (If > 1 block, reduce to 1 block)
+
+ Free the input set of buffers if we consolidate.
+
+ We pass back *new_sec_count as zero because we
+ are not creating normal sections for a .o, but
+ symbolic relocations, separately counted.
+
+ Return -1 on error (malloc failure)
+
+ Return DW_DLV_OK on success. Any other return indicates
+ malloc failed. */
+int
+_dwarf_symbolic_relocs_to_disk(Dwarf_P_Debug dbg,
+ Dwarf_Signed * new_sec_count)
+{
+ /* unsigned long total_size =0; */
+ Dwarf_Small *data = 0;
+ int sec_index = 0;
+ int res = 0;
+ unsigned long i = 0;
+ Dwarf_Error error = 0;
+ Dwarf_Signed sec_count = 0;
+ Dwarf_P_Per_Reloc_Sect p_reloc = &dbg->de_reloc_sect[0];
+
+ for (i = 0; i < NUM_DEBUG_SECTIONS; ++i, ++p_reloc) {
+ unsigned long ct = p_reloc->pr_reloc_total_count;
+ struct Dwarf_P_Relocation_Block_s *p_blk;
+ struct Dwarf_P_Relocation_Block_s *p_blk_last;
+ int err;
+ if (ct == 0) {
+ continue;
+ }
+
+ /* len = dbg->de_relocation_record_size; */
+ ++sec_count;
+
+ /* total_size = ct *len; */
+ sec_index = p_reloc->pr_sect_num_of_reloc_sect;
+ if (sec_index == 0) {
+ /* Call de_callback_func or de_callback_func_b,
+ getting section number of reloc section. */
+ int rel_section_index = 0;
+ int int_name = 0;
+ Dwarf_Unsigned name_idx = 0;
+
+ /* This is a bit of a fake, as we do not really have true
+ elf sections at all. Just the data such might contain.
+ But this lets the caller eventually link things
+ together: without this call we would not know what rel
+ data goes with what section when we are asked for the
+ real arrays. */
+
+ if (dbg->de_callback_func_c) {
+ rel_section_index =
+ dbg->de_callback_func_c(_dwarf_rel_section_names[i],
+ dbg->de_relocation_record_size,
+ /* type */ SHT_REL,
+ /* flags */ 0,
+ /* link to symtab, which we cannot
+ know */ SHN_UNDEF,
+ /* sec rels apply to */
+ dbg->de_elf_sects[i],
+ &name_idx,
+ dbg->de_user_data,&err);
+ } else if (dbg->de_callback_func_b) {
+ rel_section_index =
+ dbg->de_callback_func_b(_dwarf_rel_section_names[i],
+ dbg->de_relocation_record_size,
+ /* type */ SHT_REL,
+ /* flags */ 0,
+ /* link to symtab, which we cannot
+ know */ SHN_UNDEF,
+ /* sec rels apply to */
+ dbg->de_elf_sects[i],
+ &name_idx, &err);
+ } else {
+ rel_section_index =
+ dbg->de_callback_func(_dwarf_rel_section_names[i],
+ dbg->de_relocation_record_size,
+ /* type */ SHT_REL,
+ /* flags */ 0,
+ /* link to symtab, which we cannot
+ know */ SHN_UNDEF,
+ /* sec rels apply to, in elf, sh_info */
+ dbg->de_elf_sects[i], &int_name, &err);
+ name_idx = int_name;
+ }
+ if (rel_section_index == -1) {
+ {
+ _dwarf_p_error(dbg, &error, DW_DLE_ELF_SECT_ERR);
+ return (DW_DLV_ERROR);
+ }
+ }
+ p_reloc->pr_sect_num_of_reloc_sect = rel_section_index;
+ sec_index = rel_section_index;
+ }
+
+ p_blk = p_reloc->pr_first_block;
+
+ if (p_reloc->pr_block_count > 1) {
+ struct Dwarf_P_Relocation_Block_s *new_blk;
+
+ /* HACK , not normal interfaces, trashing p_reloc current
+ contents! */
+ _dwarf_reset_reloc_sect_info(p_reloc, ct);
+
+ /* Creating new single block for all 'ct' entries */
+ res = _dwarf_pro_pre_alloc_n_reloc_slots(dbg, (int) i, ct);
+ if (res != DW_DLV_OK) {
+ return res;
+ }
+ new_blk = p_reloc->pr_first_block;
+
+ data = (Dwarf_Small *) new_blk->rb_data;
+
+ /* The following loop does the consolidation to a single
+ block and frees the input block(s). */
+ do {
+ unsigned long len =
+ p_blk->rb_where_to_add_next - p_blk->rb_data;
+ memcpy(data, p_blk->rb_data, len);
+ data += len;
+ p_blk_last = p_blk;
+ p_blk = p_blk->rb_next;
+ _dwarf_p_dealloc(dbg, (Dwarf_Small *) p_blk_last);
+ } while (p_blk);
+ /* ASSERT: sum of len copied == total_size */
+ new_blk->rb_next_slot_to_use = ct;
+ new_blk->rb_where_to_add_next = (char *) data;
+ p_reloc->pr_reloc_total_count = ct;
+
+ /* Have now created a single block, but no change in slots
+ used (pr_reloc_total_count) */
+ }
+ }
+ *new_sec_count = 0;
+ return DW_DLV_OK;
+}
diff --git a/libdwarf/pro_reloc_symbolic.h b/libdwarf/pro_reloc_symbolic.h
new file mode 100644
index 0000000..5c76cc3
--- /dev/null
+++ b/libdwarf/pro_reloc_symbolic.h
@@ -0,0 +1,54 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+int _dwarf_pro_reloc_name_symbolic(Dwarf_P_Debug dbg,
+ int base_sec_index,
+ Dwarf_Unsigned offset,/* r_offset of reloc */
+ Dwarf_Unsigned symidx,
+ enum Dwarf_Rel_Type,
+ int reltarget_length);
+
+int
+_dwarf_pro_reloc_length_symbolic(Dwarf_P_Debug dbg,
+ int base_sec_index,
+ Dwarf_Unsigned offset, /* r_offset of reloc */
+ Dwarf_Unsigned start_symidx,
+ Dwarf_Unsigned end_symidx,
+ enum Dwarf_Rel_Type,
+ int reltarget_length);
+
+int _dwarf_symbolic_relocs_to_disk(Dwarf_P_Debug dbg,
+ Dwarf_Signed * new_sec_count);
diff --git a/libdwarf/pro_section.c b/libdwarf/pro_section.c
new file mode 100644
index 0000000..b975d6c
--- /dev/null
+++ b/libdwarf/pro_section.c
@@ -0,0 +1,2263 @@
+/*
+ Copyright (C) 2000,2004,2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
+ Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+/*
+ SGI has moved from the Crittenden Lane address.
+*/
+
+
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_ELFACCESS_H
+#include <elfaccess.h>
+#endif
+#include "pro_incl.h"
+#include "pro_section.h"
+#include "pro_line.h"
+#include "pro_frame.h"
+#include "pro_die.h"
+#include "pro_macinfo.h"
+#include "pro_types.h"
+
+#ifndef SHF_MIPS_NOSTRIP
+/* if this is not defined, we probably don't need it: just use 0 */
+#define SHF_MIPS_NOSTRIP 0
+#endif
+#ifndef R_MIPS_NONE
+#define R_MIPS_NONE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+/* Must match up with pro_section.h defines of DEBUG_INFO etc
+and sectnames (below). REL_SEC_PREFIX is either ".rel" or ".rela"
+see pro_incl.h
+*/
+char *_dwarf_rel_section_names[] = {
+ REL_SEC_PREFIX ".debug_info",
+ REL_SEC_PREFIX ".debug_line",
+ REL_SEC_PREFIX ".debug_abbrev", /* no relocations on this, really */
+ REL_SEC_PREFIX ".debug_frame",
+ REL_SEC_PREFIX ".debug_aranges",
+ REL_SEC_PREFIX ".debug_pubnames",
+ REL_SEC_PREFIX ".debug_str",
+ REL_SEC_PREFIX ".debug_funcnames", /* sgi extension */
+ REL_SEC_PREFIX ".debug_typenames", /* sgi extension */
+ REL_SEC_PREFIX ".debug_varnames", /* sgi extension */
+ REL_SEC_PREFIX ".debug_weaknames", /* sgi extension */
+ REL_SEC_PREFIX ".debug_macinfo",
+ REL_SEC_PREFIX ".debug_loc",
+ REL_SEC_PREFIX ".debug_ranges",
+ REL_SEC_PREFIX ".debug_types"
+
+};
+
+/* names of sections. Ensure that it matches the defines
+ in pro_section.h, in the same order
+ Must match also _dwarf_rel_section_names above
+*/
+char *_dwarf_sectnames[] = {
+ ".debug_info",
+ ".debug_line",
+ ".debug_abbrev",
+ ".debug_frame",
+ ".debug_aranges",
+ ".debug_pubnames",
+ ".debug_str",
+ ".debug_funcnames", /* sgi extension */
+ ".debug_typenames", /* sgi extension */
+ ".debug_varnames", /* sgi extension */
+ ".debug_weaknames", /* sgi extension */
+ ".debug_macinfo",
+ ".debug_loc",
+ ".debug_ranges",
+ ".debug_types",
+};
+
+
+
+
+static Dwarf_Ubyte std_opcode_len[] = { 0, /* DW_LNS_copy */
+ 1, /* DW_LNS_advance_pc */
+ 1, /* DW_LNS_advance_line */
+ 1, /* DW_LNS_set_file */
+ 1, /* DW_LNS_set_column */
+ 0, /* DW_LNS_negate_stmt */
+ 0, /* DW_LNS_set_basic_block */
+ 0, /* DW_LNS_const_add_pc */
+ 1, /* DW_LNS_fixed_advance_pc */
+ /* The following for DWARF3 and DWARF4, though GNU
+ uses these in DWARF2 as well. */
+ 0, /* DW_LNS_set_prologue_end */
+ 0, /* DW_LNS_set_epilogue_begin */
+ 1, /* DW_LNS_set_isa */
+};
+
+/* struct to hold relocation entries. Its mantained as a linked
+ list of relocation structs, and will then be written at as a
+ whole into the relocation section. Whether its 32 bit or
+ 64 bit will be obtained from Dwarf_Debug pointer.
+*/
+
+typedef struct Dwarf_P_Rel_s *Dwarf_P_Rel;
+struct Dwarf_P_Rel_s {
+ Dwarf_P_Rel dr_next;
+ void *dr_rel_datap;
+};
+typedef struct Dwarf_P_Rel_Head_s *Dwarf_P_Rel_Head;
+struct Dwarf_P_Rel_Head_s {
+ struct Dwarf_P_Rel_s *drh_head;
+ struct Dwarf_P_Rel_s *drh_tail;
+};
+
+static int _dwarf_pro_generate_debugline(Dwarf_P_Debug dbg,
+ Dwarf_Error * error);
+static int _dwarf_pro_generate_debugframe(Dwarf_P_Debug dbg,
+ Dwarf_Error * error);
+static int _dwarf_pro_generate_debuginfo(Dwarf_P_Debug dbg,
+ Dwarf_Error * error);
+static Dwarf_P_Abbrev _dwarf_pro_getabbrev(Dwarf_P_Die, Dwarf_P_Abbrev);
+static int _dwarf_pro_match_attr
+ (Dwarf_P_Attribute, Dwarf_P_Abbrev, int no_attr);
+
+/* these macros used as return value for below functions */
+#define OPC_INCS_ZERO -1
+#define OPC_OUT_OF_RANGE -2
+#define LINE_OUT_OF_RANGE -3
+static int _dwarf_pro_get_opc(Dwarf_P_Debug dbg,Dwarf_Unsigned addr_adv, int line_adv);
+
+
+/* BEGIN_LEN_SIZE is the size of the 'length' field in total.
+ Which may be 4,8, or 12 bytes!
+ 4 is standard DWARF2.
+ 8 is non-standard MIPS-IRIX 64-bit.
+ 12 is standard DWARF3 for 64 bit offsets.
+ Used in various routines: local variable names
+ must match the names here.
+*/
+#define BEGIN_LEN_SIZE (uwordb_size + extension_size)
+
+/* Return TRUE if we need the section, FALSE otherwise
+
+ If any of the 'line-data-related' calls were made
+ including file or directory entries,
+ produce .debug_line .
+
+*/
+static int
+dwarf_need_debug_line_section(Dwarf_P_Debug dbg)
+{
+ if (dbg->de_lines == NULL && dbg->de_file_entries == NULL
+ && dbg->de_inc_dirs == NULL) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* Convert debug information to a format such that
+ it can be written on disk.
+ Called exactly once per execution.
+*/
+Dwarf_Signed
+dwarf_transform_to_disk_form(Dwarf_P_Debug dbg, Dwarf_Error * error)
+{
+ /* Section data in written out in a number of buffers. Each
+ _generate_*() function returns a cumulative count of buffers for
+ all the sections. get_section_bytes() returns pointers to these
+ buffers one at a time. */
+ int nbufs = 0;
+ int sect = 0;
+ int err = 0;
+ Dwarf_Unsigned du = 0;
+
+ if (dbg->de_version_magic_number != PRO_VERSION_MAGIC) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_IA, DW_DLV_NOCOUNT);
+ }
+
+ /* Create dwarf section headers */
+ for (sect = 0; sect < NUM_DEBUG_SECTIONS; sect++) {
+ long flags = 0;
+
+ switch (sect) {
+
+ case DEBUG_INFO:
+ if (dbg->de_dies == NULL) {
+ continue;
+ }
+ break;
+
+ case DEBUG_LINE:
+ if (dwarf_need_debug_line_section(dbg) == FALSE) {
+ continue;
+ }
+ break;
+
+ case DEBUG_ABBREV:
+ if (dbg->de_dies == NULL) {
+ continue;
+ }
+ break;
+
+ case DEBUG_FRAME:
+ if (dbg->de_frame_cies == NULL) {
+ continue;
+ }
+ flags = SHF_MIPS_NOSTRIP;
+ break;
+
+ case DEBUG_ARANGES:
+ if (dbg->de_arange == NULL) {
+ continue;
+ }
+ break;
+
+ case DEBUG_PUBNAMES:
+ if (dbg->de_simple_name_headers[dwarf_snk_pubname].
+ sn_head == NULL) {
+ continue;
+ }
+ break;
+
+ case DEBUG_STR:
+ if (dbg->de_strings == NULL) {
+ continue;
+ }
+ break;
+
+ case DEBUG_FUNCNAMES:
+ if (dbg->de_simple_name_headers[dwarf_snk_funcname].
+ sn_head == NULL) {
+ continue;
+ }
+ break;
+
+ case DEBUG_TYPENAMES:
+ if (dbg->de_simple_name_headers[dwarf_snk_typename].
+ sn_head == NULL) {
+ continue;
+ }
+ break;
+
+ case DEBUG_VARNAMES:
+ if (dbg->de_simple_name_headers[dwarf_snk_varname].
+ sn_head == NULL) {
+ continue;
+ }
+ break;
+
+ case DEBUG_WEAKNAMES:
+ if (dbg->de_simple_name_headers[dwarf_snk_weakname].
+ sn_head == NULL) {
+ continue;
+ }
+ break;
+
+ case DEBUG_MACINFO:
+ if (dbg->de_first_macinfo == NULL) {
+ continue;
+ }
+ break;
+ case DEBUG_LOC:
+ /* Not handled yet. */
+ continue;
+ case DEBUG_RANGES:
+ /* Not handled yet. */
+ continue;
+ case DEBUG_TYPES:
+ /* Not handled yet. */
+ continue;
+ default:
+ /* logic error: missing a case */
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_ELF_SECT_ERR, DW_DLV_NOCOUNT);
+ }
+ {
+ int new_base_elf_sect = 0;
+
+ if (dbg->de_callback_func_c) {
+ new_base_elf_sect =
+ dbg->de_callback_func_c(_dwarf_sectnames[sect],
+ /* rec size */ 1,
+ SECTION_TYPE,
+ flags, SHN_UNDEF, 0, &du,
+ dbg->de_user_data, &err);
+ } else if (dbg->de_callback_func_b) {
+ new_base_elf_sect =
+ dbg->de_callback_func_b(_dwarf_sectnames[sect],
+ /* rec size */ 1,
+ SECTION_TYPE,
+ flags, SHN_UNDEF, 0, &du, &err);
+ } else {
+ int name_idx = 0;
+ new_base_elf_sect = dbg->de_callback_func(
+ _dwarf_sectnames[sect],
+ dbg->de_relocation_record_size,
+ SECTION_TYPE, flags,
+ SHN_UNDEF, 0,
+ &name_idx, &err);
+ du = name_idx;
+ }
+ if (new_base_elf_sect == -1) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_ELF_SECT_ERR,
+ DW_DLV_NOCOUNT);
+ }
+ dbg->de_elf_sects[sect] = new_base_elf_sect;
+
+ dbg->de_sect_name_idx[sect] = du;
+ }
+ }
+
+ nbufs = 0;
+
+ /* Changing the order in which the sections are generated may cause
+ problems because of relocations. */
+
+ if (dwarf_need_debug_line_section(dbg) == TRUE) {
+ nbufs = _dwarf_pro_generate_debugline(dbg, error);
+ if (nbufs < 0) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGLINE_ERROR,
+ DW_DLV_NOCOUNT);
+ }
+ }
+
+ if (dbg->de_frame_cies) {
+ nbufs = _dwarf_pro_generate_debugframe(dbg, error);
+ if (nbufs < 0) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGFRAME_ERROR,
+ DW_DLV_NOCOUNT);
+ }
+ }
+ if (dbg->de_first_macinfo) {
+ nbufs = _dwarf_pro_transform_macro_info_to_disk(dbg, error);
+ if (nbufs < 0) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGMACINFO_ERROR,
+ DW_DLV_NOCOUNT);
+ }
+ }
+
+ if (dbg->de_dies) {
+ nbufs = _dwarf_pro_generate_debuginfo(dbg, error);
+ if (nbufs < 0) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
+ DW_DLV_NOCOUNT);
+ }
+ }
+
+ if (dbg->de_arange) {
+ nbufs = _dwarf_transform_arange_to_disk(dbg, error);
+ if (nbufs < 0) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
+ DW_DLV_NOCOUNT);
+ }
+ }
+
+ if (dbg->de_simple_name_headers[dwarf_snk_pubname].sn_head) {
+ nbufs = _dwarf_transform_simplename_to_disk(dbg,
+ dwarf_snk_pubname,
+ DEBUG_PUBNAMES,
+ error);
+ if (nbufs < 0) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
+ DW_DLV_NOCOUNT);
+ }
+ }
+
+ if (dbg->de_simple_name_headers[dwarf_snk_funcname].sn_head) {
+ nbufs = _dwarf_transform_simplename_to_disk(dbg,
+ dwarf_snk_funcname,
+ DEBUG_FUNCNAMES,
+ error);
+ if (nbufs < 0) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
+ DW_DLV_NOCOUNT);
+ }
+ }
+
+ if (dbg->de_simple_name_headers[dwarf_snk_typename].sn_head) {
+ nbufs = _dwarf_transform_simplename_to_disk(dbg,
+ dwarf_snk_typename,
+ DEBUG_TYPENAMES,
+ error);
+ if (nbufs < 0) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
+ DW_DLV_NOCOUNT);
+ }
+ }
+
+ if (dbg->de_simple_name_headers[dwarf_snk_varname].sn_head) {
+ nbufs = _dwarf_transform_simplename_to_disk(dbg,
+ dwarf_snk_varname,
+ DEBUG_VARNAMES,
+ error);
+
+ if (nbufs < 0) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
+ DW_DLV_NOCOUNT);
+ }
+ }
+
+ if (dbg->de_simple_name_headers[dwarf_snk_weakname].sn_head) {
+ nbufs = _dwarf_transform_simplename_to_disk(dbg,
+ dwarf_snk_weakname, DEBUG_WEAKNAMES, error);
+ if (nbufs < 0) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
+ DW_DLV_NOCOUNT);
+ }
+ }
+
+ {
+ Dwarf_Signed new_secs = 0;
+ int res = 0;
+
+ res = dbg->de_transform_relocs_to_disk(dbg, &new_secs);
+ if (res != DW_DLV_OK) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_DEBUGINFO_ERROR,
+ DW_DLV_NOCOUNT);
+ }
+ nbufs += new_secs;
+ }
+ return nbufs;
+}
+
+static unsigned
+write_fixed_size(Dwarf_Unsigned val,
+ Dwarf_P_Debug dbg,
+ int elfsectno,
+ Dwarf_Unsigned size,
+ Dwarf_Error* error)
+{
+ Dwarf_Ubyte db = val;
+ unsigned char *data = 0;
+ GET_CHUNK(dbg, elfsectno, data, size, error);
+ WRITE_UNALIGNED(dbg, (void *) data, (const void *) &val,
+ sizeof(val), size);
+ return size;
+}
+
+static unsigned
+write_ubyte(unsigned val,
+ Dwarf_P_Debug dbg,
+ int elfsectno,
+ Dwarf_Error* error)
+{
+ Dwarf_Ubyte db = val;
+ unsigned char *data = 0;
+ unsigned len = sizeof(Dwarf_Ubyte);
+ GET_CHUNK(dbg, elfsectno, data,
+ len, error);
+ WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
+ sizeof(db), len);
+ return 1;
+}
+static unsigned
+pretend_write_uval(Dwarf_Unsigned val,
+ Dwarf_P_Debug dbg,
+ int elfsectno,
+ Dwarf_Error* error)
+{
+ char buff1[ENCODE_SPACE_NEEDED];
+ int nbytes = 0;
+ int res = _dwarf_pro_encode_leb128_nm(val,
+ &nbytes, buff1,
+ sizeof(buff1));
+ return nbytes;
+}
+
+static unsigned
+write_sval(Dwarf_Signed val,
+ Dwarf_P_Debug dbg,
+ int elfsectno,
+ Dwarf_Error* error)
+{
+ char buff1[ENCODE_SPACE_NEEDED];
+ unsigned char *data = 0;
+ int nbytes = 0;
+ int res = _dwarf_pro_encode_signed_leb128_nm(val,
+ &nbytes, buff1,
+ sizeof(buff1));
+ if (res != DW_DLV_OK) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
+ }
+ GET_CHUNK(dbg, elfsectno, data, nbytes, error);
+ memcpy((void *) data, (const void *) buff1, nbytes);
+ return nbytes;
+}
+
+static unsigned
+write_uval(Dwarf_Unsigned val,
+ Dwarf_P_Debug dbg,
+ int elfsectno,
+ Dwarf_Error* error)
+{
+ char buff1[ENCODE_SPACE_NEEDED];
+ unsigned char *data = 0;
+ int nbytes = 0;
+ int res = _dwarf_pro_encode_leb128_nm(val,
+ &nbytes, buff1,
+ sizeof(buff1));
+ if (res != DW_DLV_OK) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
+ }
+ GET_CHUNK(dbg, elfsectno, data, nbytes, error);
+ memcpy((void *) data, (const void *) buff1, nbytes);
+ return nbytes;
+}
+static unsigned
+write_opcode_uval(int opcode,
+ Dwarf_P_Debug dbg,
+ int elfsectno,
+ Dwarf_Unsigned val,
+ Dwarf_Error* error)
+{
+ unsigned totallen = write_ubyte(opcode,dbg,elfsectno,error);
+ totallen += write_uval(val,dbg,elfsectno,error);
+ return totallen;
+}
+
+/* Generate debug_line section */
+static int
+_dwarf_pro_generate_debugline(Dwarf_P_Debug dbg, Dwarf_Error * error)
+{
+ Dwarf_P_Inc_Dir curdir = 0;
+ Dwarf_P_F_Entry curentry = 0;
+ Dwarf_P_Line curline = 0;
+ Dwarf_P_Line prevline = 0;
+
+ /* all data named cur* are used to loop thru linked lists */
+
+ int sum_bytes = 0;
+ int prolog_size = 0;
+ unsigned char *data = 0; /* holds disk form data */
+ int elfsectno = 0;
+ unsigned char *start_line_sec = 0; /* pointer to the buffer at
+ section start */
+ /* temps for memcpy */
+ Dwarf_Unsigned du = 0;
+ Dwarf_Ubyte db = 0;
+ Dwarf_Half dh = 0;
+ int res = 0;
+ int uwordb_size = dbg->de_offset_size;
+ int extension_size = dbg->de_64bit_extension ? 4 : 0;
+ int upointer_size = dbg->de_pointer_size;
+ char buff1[ENCODE_SPACE_NEEDED];
+
+
+
+ sum_bytes = 0;
+
+ elfsectno = dbg->de_elf_sects[DEBUG_LINE];
+
+ /* include directories */
+ curdir = dbg->de_inc_dirs;
+ while (curdir) {
+ prolog_size += strlen(curdir->did_name) + 1;
+ curdir = curdir->did_next;
+ }
+ prolog_size++; /* last null following last directory
+ entry. */
+
+ /* file entries */
+ curentry = dbg->de_file_entries;
+ while (curentry) {
+ prolog_size +=
+ strlen(curentry->dfe_name) + 1 + curentry->dfe_nbytes;
+ curentry = curentry->dfe_next;
+ }
+ prolog_size++; /* last null byte */
+
+
+ prolog_size += BEGIN_LEN_SIZE + sizeof_uhalf(dbg) + /* version # */
+ uwordb_size + /* header length */
+ sizeof_ubyte(dbg) + /* min_instr length */
+ sizeof_ubyte(dbg) + /* default is_stmt */
+ sizeof_ubyte(dbg) + /* linebase */
+ sizeof_ubyte(dbg) + /* linerange */
+ sizeof_ubyte(dbg); /* opcode base */
+
+ /* length of table specifying # of opnds */
+ prolog_size += dbg->de_line_inits.pi_opcode_base-1;
+ if(dbg->de_line_inits.pi_version == DW_LINE_VERSION4) {
+ /* For maximum_operations_per_instruction. */
+ prolog_size += sizeof_ubyte(dbg);
+ }
+
+ GET_CHUNK(dbg, elfsectno, data, prolog_size, error);
+ start_line_sec = data;
+
+ /* copy over the data */
+ /* total_length */
+ du = 0;
+ if (extension_size) {
+ Dwarf_Word x = DISTINGUISHED_VALUE;
+
+ WRITE_UNALIGNED(dbg, (void *) data, (const void *) &x,
+ sizeof(x), extension_size);
+ data += extension_size;
+ }
+
+ WRITE_UNALIGNED(dbg, (void *) data, (const void *) &du,
+ sizeof(du), uwordb_size);
+ data += uwordb_size;
+
+ dh = dbg->de_line_inits.pi_version;
+ WRITE_UNALIGNED(dbg, (void *) data, (const void *) &dh,
+ sizeof(dh), sizeof(Dwarf_Half));
+ data += sizeof(Dwarf_Half);
+
+ /* header length */
+ du = prolog_size - (BEGIN_LEN_SIZE + sizeof(Dwarf_Half) +
+ uwordb_size);
+ {
+ WRITE_UNALIGNED(dbg, (void *) data, (const void *) &du,
+ sizeof(du), uwordb_size);
+ data += uwordb_size;
+ }
+ db = dbg->de_line_inits.pi_minimum_instruction_length;
+ WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
+ sizeof(db), sizeof(Dwarf_Ubyte));
+ data += sizeof(Dwarf_Ubyte);
+
+ if(dbg->de_line_inits.pi_version == DW_LINE_VERSION4) {
+ db = dbg->de_line_inits.pi_maximum_operations_per_instruction;
+ WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
+ sizeof(db), sizeof(Dwarf_Ubyte));
+ data += sizeof(Dwarf_Ubyte);
+ }
+
+ db = dbg->de_line_inits.pi_default_is_stmt;
+ WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
+ sizeof(db), sizeof(Dwarf_Ubyte));
+ data += sizeof(Dwarf_Ubyte);
+ db = dbg->de_line_inits.pi_line_base;
+ WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
+ sizeof(db), sizeof(Dwarf_Ubyte));
+ data += sizeof(Dwarf_Ubyte);
+ db = dbg->de_line_inits.pi_line_range;
+ WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
+ sizeof(db), sizeof(Dwarf_Ubyte));
+ data += sizeof(Dwarf_Ubyte);
+ db = dbg->de_line_inits.pi_opcode_base;
+ WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
+ sizeof(db), sizeof(Dwarf_Ubyte));
+ data += sizeof(Dwarf_Ubyte);
+ WRITE_UNALIGNED(dbg, (void *) data, (const void *) std_opcode_len,
+ dbg->de_line_inits.pi_opcode_base-1,
+ dbg->de_line_inits.pi_opcode_base-1);
+ data += dbg->de_line_inits.pi_opcode_base-1;
+
+ /* copy over include directories */
+ curdir = dbg->de_inc_dirs;
+ while (curdir) {
+ strcpy((char *) data, curdir->did_name);
+ data += strlen(curdir->did_name) + 1;
+ curdir = curdir->did_next;
+ }
+ *data = '\0'; /* last null */
+ data++;
+
+ /* copy file entries */
+ curentry = dbg->de_file_entries;
+ while (curentry) {
+ strcpy((char *) data, curentry->dfe_name);
+ data += strlen(curentry->dfe_name) + 1;
+ /* copies of leb numbers, no endian issues */
+ memcpy((void *) data,
+ (const void *) curentry->dfe_args, curentry->dfe_nbytes);
+ data += curentry->dfe_nbytes;
+ curentry = curentry->dfe_next;
+ }
+ *data = '\0';
+ data++;
+
+ sum_bytes += prolog_size;
+
+ curline = dbg->de_lines;
+ prevline = (Dwarf_P_Line)
+ _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Line_s));
+ if (prevline == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_LINE_ALLOC, -1);
+ }
+ _dwarf_pro_reg_init(dbg,prevline);
+ /* generate opcodes for line numbers */
+ while (curline) {
+ int nbytes;
+ char *arg;
+ int opc;
+ int no_lns_copy; /* if lns copy opcode doesnt need to be
+ generated, if special opcode or end
+ sequence */
+ Dwarf_Unsigned addr_adv;
+ int line_adv; /* supposed to be a reasonably small
+ number, so the size should not be a
+ problem. ? */
+
+ no_lns_copy = 0;
+ if (curline->dpl_opc != 0) {
+ int inst_bytes; /* no of bytes in extended opcode */
+ char *str; /* hold leb encoded inst_bytes */
+ int str_nbytes; /* no of bytes in str */
+ unsigned writelen = 0;
+
+ switch (curline->dpl_opc) {
+ case DW_LNE_end_sequence:
+ /* Advance pc to end of text section. */
+ addr_adv = curline->dpl_address - prevline->dpl_address;
+ if (addr_adv > 0) {
+ writelen = write_opcode_uval(DW_LNS_advance_pc,dbg,
+ elfsectno,
+ addr_adv/
+ dbg->de_line_inits.pi_minimum_instruction_length,
+ error);
+ sum_bytes += writelen;
+ prevline->dpl_address = curline->dpl_address;
+ }
+
+ /* first null byte */
+ db = 0;
+ writelen = write_ubyte(db,dbg,elfsectno,error);
+ sum_bytes += writelen;
+
+ /* write length of extended opcode */
+ inst_bytes = sizeof(Dwarf_Ubyte);
+ writelen = write_uval(inst_bytes,dbg,elfsectno,error);
+ sum_bytes += writelen;
+
+ /* write extended opcode */
+ writelen = write_ubyte(DW_LNE_end_sequence,dbg,elfsectno,error);
+ sum_bytes += writelen;
+
+ /* reset value to original values */
+ _dwarf_pro_reg_init(dbg,prevline);
+ no_lns_copy = 1;
+ /* this is set only for end_sequence, so that a
+ dw_lns_copy is not generated */
+ break;
+
+ case DW_LNE_set_address:
+
+ /* first null byte */
+ db = 0;
+ writelen = write_ubyte(db,dbg,elfsectno,error);
+ sum_bytes += writelen;
+
+ /* write length of extended opcode */
+ inst_bytes = sizeof(Dwarf_Ubyte) + upointer_size;
+ writelen = write_uval(inst_bytes,dbg,elfsectno,error);
+ sum_bytes += writelen;
+
+ /* write extended opcode */
+ writelen = write_ubyte(DW_LNE_set_address,dbg,elfsectno,error);
+ sum_bytes += writelen;
+
+ /* reloc for address */
+ res = dbg->de_reloc_name(dbg, DEBUG_LINE,
+ sum_bytes, /* r_offset */
+ curline->dpl_r_symidx,
+ dwarf_drt_data_reloc,
+ uwordb_size);
+ if (res != DW_DLV_OK) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
+ }
+
+ /* write offset (address) */
+ du = curline->dpl_address;
+ writelen = write_fixed_size(du,dbg,elfsectno,
+ upointer_size,error);
+ sum_bytes += writelen;
+ prevline->dpl_address = curline->dpl_address;
+ no_lns_copy = 1;
+ break;
+ case DW_LNE_define_file:
+ /* Not supported, all add-file entries
+ are added via dbg -> de_file_entries,
+ which adds to the line table header. */
+ no_lns_copy = 1;
+ break;
+ case DW_LNE_set_discriminator: {/* DWARF4 */
+ unsigned val_len = 0;
+ /* first null byte */
+ db = 0;
+ writelen = write_ubyte(db,dbg,elfsectno,error);
+ sum_bytes += writelen;
+
+ /* Write len of opcode + value here. */
+ val_len = pretend_write_uval(curline->dpl_discriminator,
+ dbg, elfsectno,error) + 1;
+ writelen = write_uval(val_len +1,dbg,elfsectno,error);
+ sum_bytes += writelen;
+
+ /* Write opcode */
+ writelen = write_ubyte(DW_LNE_set_discriminator,
+ dbg,elfsectno,error);
+ sum_bytes += writelen;
+
+ /* Write the value itself. */
+ writelen = write_uval(curline->dpl_discriminator,
+ dbg,elfsectno,error);
+ sum_bytes += writelen;
+ no_lns_copy = 1;
+ }
+ break;
+ }
+ } else {
+ unsigned writelen = 0;
+ if (dbg->de_line_inits.pi_opcode_base >12) {
+ /* We have the newer standard opcodes
+ DW_LNS_set_prologue_end, DW_LNS_set_epilogue_end,
+ DW_LNS_set_isa, we do not write them if not
+ in the table. DWARF3 and DWARF4 */
+ /* Should we check if a change? These reset automatically
+ in the line processing/reading engine,
+ so I think no check of prevline is wanted. */
+ if (curline->dpl_epilogue_begin) {
+ writelen = write_ubyte(DW_LNS_set_epilogue_begin,dbg,
+ elfsectno, error);
+ sum_bytes += writelen;
+ }
+ if (curline->dpl_prologue_end) {
+ writelen = write_ubyte(DW_LNS_set_prologue_end,dbg,
+ elfsectno, error);
+ sum_bytes += writelen;
+ }
+ if (curline->dpl_isa != prevline->dpl_isa) {
+ writelen = write_opcode_uval(DW_LNS_set_isa,dbg,
+ elfsectno,
+ curline->dpl_isa ,error);
+ sum_bytes += writelen;
+ }
+ }
+ if (curline->dpl_file != prevline->dpl_file) {
+ db = DW_LNS_set_file;
+ writelen = write_opcode_uval(db,dbg,
+ elfsectno,
+ curline->dpl_file ,error);
+ sum_bytes += writelen;
+
+ prevline->dpl_file = curline->dpl_file;
+ }
+ if (curline->dpl_column != prevline->dpl_column) {
+ db = DW_LNS_set_column;
+ writelen = write_opcode_uval(db,dbg,
+ elfsectno,
+ curline->dpl_column ,error);
+ sum_bytes += writelen;
+ prevline->dpl_column = curline->dpl_column;
+ }
+ if (curline->dpl_is_stmt != prevline->dpl_is_stmt) {
+ writelen = write_ubyte(DW_LNS_negate_stmt,dbg,elfsectno,error);
+ sum_bytes += writelen;
+ prevline->dpl_is_stmt = curline->dpl_is_stmt;
+ }
+ if (curline->dpl_basic_block == true &&
+ prevline->dpl_basic_block == false) {
+ writelen = write_ubyte(DW_LNS_set_basic_block,dbg,
+ elfsectno,error);
+ sum_bytes += writelen;
+ prevline->dpl_basic_block = curline->dpl_basic_block;
+ }
+ if(curline->dpl_discriminator) {
+ /* This is dwarf4, but because it is an extended op
+ not a standard op,
+ we allow it without testing version.
+ GNU seems to set this from time to time. */
+ unsigned val_len = 0;
+ /* first null byte */
+ db = 0;
+ writelen = write_ubyte(db,dbg,elfsectno,error);
+ sum_bytes += writelen;
+
+ /* Write len of opcode + value here. */
+ val_len = pretend_write_uval(curline->dpl_discriminator,
+ dbg, elfsectno,error) + 1;
+ writelen = write_uval(val_len +1,dbg,elfsectno,error);
+ sum_bytes += writelen;
+
+ /* Write opcode */
+ writelen = write_ubyte(DW_LNE_set_discriminator,
+ dbg,elfsectno,error);
+ sum_bytes += writelen;
+
+ /* Write the value itself. */
+ writelen = write_uval(curline->dpl_discriminator,
+ dbg,elfsectno,error);
+ sum_bytes += writelen;
+ }
+
+ addr_adv = curline->dpl_address - prevline->dpl_address;
+
+ line_adv = (int) (curline->dpl_line - prevline->dpl_line);
+ if ((addr_adv % MIN_INST_LENGTH) != 0) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_WRONG_ADDRESS, -1);
+ }
+ opc = _dwarf_pro_get_opc(dbg,addr_adv, line_adv);
+ if (opc > 0) {
+ /* Use special opcode. */
+ no_lns_copy = 1;
+ writelen = write_ubyte(opc,dbg,elfsectno,error);
+ sum_bytes += writelen;
+ prevline->dpl_basic_block = false;
+ prevline->dpl_address = curline->dpl_address;
+ prevline->dpl_line = curline->dpl_line;
+ } else {
+ /* opc says use standard opcodes. */
+ if (addr_adv > 0) {
+ db = DW_LNS_advance_pc;
+ writelen = write_opcode_uval(db,dbg,
+ elfsectno,
+ addr_adv/
+ dbg->de_line_inits.pi_minimum_instruction_length,
+ error);
+ sum_bytes += writelen;
+ prevline->dpl_basic_block = false;
+ prevline->dpl_address = curline->dpl_address;
+ }
+ if (line_adv != 0) {
+ db = DW_LNS_advance_line;
+ writelen = write_ubyte(db,dbg,
+ elfsectno,
+ error);
+ sum_bytes += writelen;
+ writelen = write_sval(line_adv,dbg,
+ elfsectno,
+ error);
+ sum_bytes += writelen;
+ prevline->dpl_basic_block = false;
+ prevline->dpl_line = curline->dpl_line;
+ }
+ }
+ } /* ends else for opc <= 0 */
+ if (no_lns_copy == 0) { /* if not a special or dw_lne_end_seq
+ generate a matrix line */
+ unsigned writelen = 0;
+ writelen = write_ubyte(DW_LNS_copy,dbg,elfsectno,error);
+ sum_bytes += writelen;
+ prevline->dpl_basic_block = false;
+ }
+ curline = curline->dpl_next;
+ }
+
+ /* write total length field */
+ du = sum_bytes - BEGIN_LEN_SIZE;
+ {
+ start_line_sec += extension_size;
+ WRITE_UNALIGNED(dbg, (void *) start_line_sec,
+ (const void *) &du, sizeof(du), uwordb_size);
+ }
+
+ return (int) dbg->de_n_debug_sect;
+}
+
+/*
+ Generate debug_frame section */
+static int
+_dwarf_pro_generate_debugframe(Dwarf_P_Debug dbg, Dwarf_Error * error)
+{
+ int elfsectno = 0;
+ int i = 0;
+ int firsttime = 1;
+ int pad = 0; /* Pad for padding to align cies and fdes */
+ Dwarf_P_Cie curcie = 0;
+ Dwarf_P_Fde curfde = 0;
+ unsigned char *data = 0;
+ Dwarf_sfixed dsw = 0;
+ Dwarf_Unsigned du = 0;
+ Dwarf_Ubyte db = 0;
+ long *cie_offs = 0; /* Holds byte offsets for links to fde's */
+ unsigned long cie_length = 0;
+ int cie_no = 0;
+ int uwordb_size = dbg->de_offset_size;
+ int extension_size = dbg->de_64bit_extension ? 4 : 0;
+ int upointer_size = dbg->de_pointer_size;
+ Dwarf_Unsigned cur_off = 0; /* current offset of written data, held
+ for relocation info */
+
+ elfsectno = dbg->de_elf_sects[DEBUG_FRAME];
+
+ curcie = dbg->de_frame_cies;
+ cie_length = 0;
+ cur_off = 0;
+ cie_offs = (long *)
+ _dwarf_p_get_alloc(dbg, sizeof(long) * dbg->de_n_cie);
+ if (cie_offs == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1);
+ }
+ /* Generate cie number as we go along. This writes
+ all CIEs first before any FDEs, which is rather
+ different from the order a compiler might like (which
+ might be each CIE followed by its FDEs then the next CIE, and
+ so on). */
+ cie_no = 1;
+ while (curcie) {
+ char *code_al = 0;
+ int c_bytes = 0;
+ char *data_al = 0;
+ int d_bytes = 0;
+ int res = 0;
+ char buff1[ENCODE_SPACE_NEEDED];
+ char buff2[ENCODE_SPACE_NEEDED];
+ char buff3[ENCODE_SPACE_NEEDED];
+ char *augmentation = 0;
+ char *augmented_al = 0;
+ long augmented_fields_length = 0;
+ int a_bytes = 0;
+
+ res = _dwarf_pro_encode_leb128_nm(curcie->cie_code_align,
+ &c_bytes,
+ buff1, sizeof(buff1));
+ if (res != DW_DLV_OK) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1);
+ }
+ /* Before April 1999, the following was using an unsigned
+ encode. That worked ok even though the decoder used the
+ correct signed leb read, but doing the encode correctly
+ (according to the dwarf spec) saves space in the output file
+ and is completely compatible.
+
+ Note the actual stored amount on MIPS was 10 bytes (!) to
+ store the value -4. (hex)fc ffffffff ffffffff 01 The
+ libdwarf consumer consumed all 10 bytes too!
+
+ old version res =
+ _dwarf_pro_encode_leb128_nm(curcie->cie_data_align,
+
+ below is corrected signed version. */
+ res = _dwarf_pro_encode_signed_leb128_nm(curcie->cie_data_align,
+ &d_bytes,
+ buff2, sizeof(buff2));
+ if (res != DW_DLV_OK) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1);
+ }
+ code_al = buff1;
+ data_al = buff2;
+
+ /* get the correct offset */
+ if (firsttime) {
+ cie_offs[cie_no - 1] = 0;
+ firsttime = 0;
+ } else {
+ cie_offs[cie_no - 1] = cie_offs[cie_no - 2] +
+ (long) cie_length + BEGIN_LEN_SIZE;
+ }
+ cie_no++;
+ augmentation = curcie->cie_aug;
+ if (strcmp(augmentation, DW_CIE_AUGMENTER_STRING_V0) == 0) {
+ augmented_fields_length = 0;
+ res = _dwarf_pro_encode_leb128_nm(augmented_fields_length,
+ &a_bytes, buff3,
+ sizeof(buff3));
+ augmented_al = buff3;
+ if (res != DW_DLV_OK) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1);
+ }
+ cie_length = uwordb_size + /* cie_id */
+ sizeof(Dwarf_Ubyte) + /* cie version */
+ strlen(curcie->cie_aug) + 1 + /* augmentation */
+ c_bytes + /* code alignment factor */
+ d_bytes + /* data alignment factor */
+ sizeof(Dwarf_Ubyte) + /* return reg address */
+ a_bytes + /* augmentation length */
+ curcie->cie_inst_bytes;
+ } else {
+ cie_length = uwordb_size + /* cie_id */
+ sizeof(Dwarf_Ubyte) + /* cie version */
+ strlen(curcie->cie_aug) + 1 + /* augmentation */
+ c_bytes + d_bytes + sizeof(Dwarf_Ubyte) +
+ /* return reg address */ curcie->cie_inst_bytes;
+ }
+ pad = (int) PADDING(cie_length, upointer_size);
+ cie_length += pad;
+ GET_CHUNK(dbg, elfsectno, data, cie_length +
+ BEGIN_LEN_SIZE, error);
+ if (extension_size) {
+ Dwarf_Unsigned x = DISTINGUISHED_VALUE;
+
+ WRITE_UNALIGNED(dbg, (void *) data,
+ (const void *) &x,
+ sizeof(x), extension_size);
+ data += extension_size;
+
+ }
+ du = cie_length;
+ /* total length of cie */
+ WRITE_UNALIGNED(dbg, (void *) data,
+ (const void *) &du, sizeof(du), uwordb_size);
+ data += uwordb_size;
+
+ /* cie-id is a special value. */
+ du = DW_CIE_ID;
+ WRITE_UNALIGNED(dbg, (void *) data, (const void *) &du,
+ sizeof(du), uwordb_size);
+ data += uwordb_size;
+
+ db = curcie->cie_version;
+ WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
+ sizeof(db), sizeof(Dwarf_Ubyte));
+ data += sizeof(Dwarf_Ubyte);
+ strcpy((char *) data, curcie->cie_aug);
+ data += strlen(curcie->cie_aug) + 1;
+ memcpy((void *) data, (const void *) code_al, c_bytes);
+ data += c_bytes;
+ memcpy((void *) data, (const void *) data_al, d_bytes);
+ data += d_bytes;
+ db = curcie->cie_ret_reg;
+ WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
+ sizeof(db), sizeof(Dwarf_Ubyte));
+ data += sizeof(Dwarf_Ubyte);
+
+ if (strcmp(augmentation, DW_CIE_AUGMENTER_STRING_V0) == 0) {
+ memcpy((void *) data, (const void *) augmented_al, a_bytes);
+ data += a_bytes;
+ }
+ memcpy((void *) data, (const void *) curcie->cie_inst,
+ curcie->cie_inst_bytes);
+ data += curcie->cie_inst_bytes;
+ for (i = 0; i < pad; i++) {
+ *data = DW_CFA_nop;
+ data++;
+ }
+ curcie = curcie->cie_next;
+ }
+ /* calculate current offset */
+ cur_off = cie_offs[cie_no - 2] + cie_length + BEGIN_LEN_SIZE;
+
+ /* write out fde's */
+ curfde = dbg->de_frame_fdes;
+ while (curfde) {
+ Dwarf_P_Frame_Pgm curinst = 0;
+ long fde_length = 0;
+ int pad = 0;
+ Dwarf_P_Cie cie_ptr = 0;
+ Dwarf_Word cie_index = 0;
+ Dwarf_Word index = 0;
+ int oet_length = 0;
+ int afl_length = 0;
+ int res = 0;
+ int v0_augmentation = 0;
+#if 0
+ unsigned char *fde_start_point = 0;
+#endif
+ char afl_buff[ENCODE_SPACE_NEEDED];
+
+ /* Find the CIE associated with this fde. */
+ cie_ptr = dbg->de_frame_cies;
+ cie_index = curfde->fde_cie;
+ index = 1; /* The cie_index of the first cie is 1, not 0. */
+ while (cie_ptr && index < cie_index) {
+ cie_ptr = cie_ptr->cie_next;
+ index++;
+ }
+ if (cie_ptr == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_NULL, -1);
+ }
+
+ if (strcmp(cie_ptr->cie_aug, DW_CIE_AUGMENTER_STRING_V0) == 0) {
+ v0_augmentation = 1;
+ oet_length = sizeof(Dwarf_sfixed);
+ /* encode the length of augmented fields. */
+ res = _dwarf_pro_encode_leb128_nm(oet_length,
+ &afl_length, afl_buff,
+ sizeof(afl_buff));
+ if (res != DW_DLV_OK) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_OFFS_ALLOC, -1);
+ }
+
+ fde_length = curfde->fde_n_bytes +
+ BEGIN_LEN_SIZE + /* cie pointer */
+ upointer_size + /* initial loc */
+ upointer_size + /* address range */
+ afl_length + /* augmented field length */
+ oet_length; /* exception_table offset */
+ } else {
+ fde_length = curfde->fde_n_bytes + BEGIN_LEN_SIZE + /* cie
+ pointer */
+ upointer_size + /* initial loc */
+ upointer_size; /* address range */
+ }
+
+
+ if (curfde->fde_die) {
+ /* IRIX/MIPS extension:
+ Using fde offset, generate DW_AT_MIPS_fde attribute for the
+ die corresponding to this fde. */
+ if(_dwarf_pro_add_AT_fde(dbg, curfde->fde_die, cur_off,
+ error) < 0) {
+ return -1;
+ }
+ }
+
+ /* store relocation for cie pointer */
+ res = dbg->de_reloc_name(dbg, DEBUG_FRAME, cur_off +
+ BEGIN_LEN_SIZE /* r_offset */,
+ dbg->de_sect_name_idx[DEBUG_FRAME],
+ dwarf_drt_data_reloc, uwordb_size);
+ if (res != DW_DLV_OK) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
+ }
+
+ /* store relocation information for initial location */
+ res = dbg->de_reloc_name(dbg, DEBUG_FRAME,
+ cur_off + BEGIN_LEN_SIZE +
+ upointer_size /* r_offset */,
+ curfde->fde_r_symidx,
+ dwarf_drt_data_reloc, upointer_size);
+ if (res != DW_DLV_OK) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
+ }
+ /* Store the relocation information for the
+ offset_into_exception_info field, if the offset is valid (0
+ is a valid offset). */
+ if (v0_augmentation &&
+ curfde->fde_offset_into_exception_tables >= 0) {
+
+ res = dbg->de_reloc_name(dbg, DEBUG_FRAME,
+ /* r_offset, where in cie this field starts */
+ cur_off + BEGIN_LEN_SIZE +
+ uwordb_size + 2 * upointer_size +
+ afl_length,
+ curfde->fde_exception_table_symbol,
+ dwarf_drt_segment_rel,
+ sizeof(Dwarf_sfixed));
+ if (res != DW_DLV_OK) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_CHUNK_ALLOC, -1);
+ }
+ }
+
+ /* adjust for padding */
+ pad = (int) PADDING(fde_length, upointer_size);
+ fde_length += pad;
+
+
+ /* write out fde */
+ GET_CHUNK(dbg, elfsectno, data, fde_length + BEGIN_LEN_SIZE,
+ error);
+#if 0
+ fde_start_point = data;
+#endif
+ du = fde_length;
+ {
+ if (extension_size) {
+ Dwarf_Word x = DISTINGUISHED_VALUE;
+
+ WRITE_UNALIGNED(dbg, (void *) data,
+ (const void *) &x,
+ sizeof(x), extension_size);
+ data += extension_size;
+ }
+ /* length */
+ WRITE_UNALIGNED(dbg, (void *) data,
+ (const void *) &du,
+ sizeof(du), uwordb_size);
+ data += uwordb_size;
+
+ /* offset to cie */
+ du = cie_offs[curfde->fde_cie - 1];
+ WRITE_UNALIGNED(dbg, (void *) data,
+ (const void *) &du,
+ sizeof(du), uwordb_size);
+ data += uwordb_size;
+
+ du = curfde->fde_initloc;
+ WRITE_UNALIGNED(dbg, (void *) data,
+ (const void *) &du,
+ sizeof(du), upointer_size);
+ data += upointer_size;
+
+ if (dbg->de_reloc_pair &&
+ curfde->fde_end_symbol != 0 &&
+ curfde->fde_addr_range == 0) {
+ /* symbolic reloc, need reloc for length What if we
+ really know the length? If so, should use the other
+ part of 'if'. */
+ Dwarf_Unsigned val;
+
+ res = dbg->de_reloc_pair(dbg,
+ /* DEBUG_ARANGES, */ DEBUG_FRAME,
+ cur_off + 2 * uwordb_size + upointer_size,
+ /* r_offset */ curfde->fde_r_symidx,
+ curfde->fde_end_symbol,
+ dwarf_drt_first_of_length_pair,
+ upointer_size);
+ if (res != DW_DLV_OK) {
+ {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (0);
+ }
+ }
+
+ /* arrange pre-calc so assem text can do .word end -
+ begin + val (gets val from stream) */
+ val = curfde->fde_end_symbol_offset -
+ curfde->fde_initloc;
+ WRITE_UNALIGNED(dbg, data,
+ (const void *) &val,
+ sizeof(val), upointer_size);
+ data += upointer_size;
+ } else {
+
+ du = curfde->fde_addr_range;
+ WRITE_UNALIGNED(dbg, (void *) data,
+ (const void *) &du,
+ sizeof(du), upointer_size);
+ data += upointer_size;
+ }
+ }
+
+ if (v0_augmentation) {
+ /* write the encoded augmented field length. */
+ memcpy((void *) data, (const void *) afl_buff, afl_length);
+ data += afl_length;
+ /* write the offset_into_exception_tables field. */
+ dsw =
+ (Dwarf_sfixed) curfde->fde_offset_into_exception_tables;
+ WRITE_UNALIGNED(dbg, (void *) data, (const void *) &dsw,
+ sizeof(dsw), sizeof(Dwarf_sfixed));
+ data += sizeof(Dwarf_sfixed);
+ }
+
+ curinst = curfde->fde_inst;
+ if(curfde->fde_block) {
+ unsigned long size = curfde->fde_inst_block_size;
+ memcpy((void *) data, (const void *) curfde->fde_block, size);
+ data += size;
+ } else {
+ while (curinst) {
+ db = curinst->dfp_opcode;
+ WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
+ sizeof(db), sizeof(Dwarf_Ubyte));
+ data += sizeof(Dwarf_Ubyte);
+#if 0
+ if (curinst->dfp_sym_index) {
+ int res = dbg->de_reloc_name(dbg,
+ DEBUG_FRAME,
+ /* r_offset = */
+ (data - fde_start_point) + cur_off + uwordb_size,
+ curinst->dfp_sym_index,
+ dwarf_drt_data_reloc,
+ upointer_size);
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (0);
+ }
+ }
+#endif
+ memcpy((void *) data,
+ (const void *) curinst->dfp_args,
+ curinst->dfp_nbytes);
+ data += curinst->dfp_nbytes;
+ curinst = curinst->dfp_next;
+ }
+ }
+ /* padding */
+ for (i = 0; i < pad; i++) {
+ *data = DW_CFA_nop;
+ data++;
+ }
+ cur_off += fde_length + uwordb_size;
+ curfde = curfde->fde_next;
+ }
+
+
+ return (int) dbg->de_n_debug_sect;
+}
+
+/*
+ These functions remember all the markers we see along
+ with the right offset in the .debug_info section so that
+ we can dump them all back to the user with the section info.
+*/
+
+static int
+marker_init(Dwarf_P_Debug dbg,
+ unsigned count)
+{
+ dbg->de_marker_n_alloc = count;
+ dbg->de_markers = NULL;
+ if (count > 0) {
+ dbg->de_markers = _dwarf_p_get_alloc(dbg,
+ sizeof(struct Dwarf_P_Marker_s) * dbg->de_marker_n_alloc);
+ if (dbg->de_markers == NULL) {
+ dbg->de_marker_n_alloc = 0;
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int
+marker_add(Dwarf_P_Debug dbg,
+ Dwarf_Unsigned offset,
+ Dwarf_Unsigned marker)
+{
+ if (dbg->de_marker_n_alloc >= (dbg->de_marker_n_used + 1)) {
+ unsigned n = dbg->de_marker_n_used++;
+ dbg->de_markers[n].ma_offset = offset;
+ dbg->de_markers[n].ma_marker = marker;
+ return 0;
+ }
+
+ return -1;
+}
+
+Dwarf_Signed
+dwarf_get_die_markers(Dwarf_P_Debug dbg,
+ Dwarf_P_Marker * marker_list, /* pointer to a pointer */
+ Dwarf_Unsigned * marker_count,
+ Dwarf_Error * error)
+{
+ if (marker_list == NULL || marker_count == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_IA, DW_DLV_BADADDR);
+ }
+ if (dbg->de_marker_n_used != dbg->de_marker_n_alloc) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_MAF, DW_DLV_BADADDR);
+ }
+
+ *marker_list = dbg->de_markers;
+ *marker_count = dbg->de_marker_n_used;
+ return DW_DLV_OK;
+}
+
+/* These functions provide the offsets of DW_FORM_string
+ attributes in the section section_index. These information
+ will enable a producer app that is generating assembly
+ text output to easily emit those attributes in ascii form
+ without having to decode the byte stream. */
+static int
+string_attr_init (Dwarf_P_Debug dbg,
+ Dwarf_Signed section_index,
+ unsigned count)
+{
+ Dwarf_P_Per_Sect_String_Attrs sect_sa = &dbg->de_sect_string_attr[section_index];
+
+ sect_sa->sect_sa_n_alloc = count;
+ sect_sa->sect_sa_list = NULL;
+ if (count > 0) {
+ sect_sa->sect_sa_section_number = section_index;
+ sect_sa->sect_sa_list = _dwarf_p_get_alloc(dbg,
+ sizeof(struct Dwarf_P_String_Attr_s) * sect_sa->sect_sa_n_alloc);
+ if (sect_sa->sect_sa_list == NULL) {
+ sect_sa->sect_sa_n_alloc = 0;
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int
+string_attr_add (Dwarf_P_Debug dbg,
+ Dwarf_Signed section_index,
+ Dwarf_Unsigned offset,
+ Dwarf_P_Attribute attr)
+{
+ Dwarf_P_Per_Sect_String_Attrs sect_sa = &dbg->de_sect_string_attr[section_index];
+ if (sect_sa->sect_sa_n_alloc >= (sect_sa->sect_sa_n_used + 1)) {
+ unsigned n = sect_sa->sect_sa_n_used++;
+ sect_sa->sect_sa_list[n].sa_offset = offset;
+ sect_sa->sect_sa_list[n].sa_nbytes = attr->ar_nbytes;
+ return 0;
+ }
+
+ return -1;
+}
+
+int
+dwarf_get_string_attributes_count(Dwarf_P_Debug dbg,
+ Dwarf_Unsigned *
+ count_of_sa_sections,
+ int *drd_buffer_version,
+ Dwarf_Error *error)
+{
+ int i = 0;
+ unsigned int count = 0;
+
+ for (i = 0; i < NUM_DEBUG_SECTIONS; ++i) {
+ if (dbg->de_sect_string_attr[i].sect_sa_n_used > 0) {
+ ++count;
+ }
+ }
+ *count_of_sa_sections = (Dwarf_Unsigned) count;
+ *drd_buffer_version = DWARF_DRD_BUFFER_VERSION;
+
+ return DW_DLV_OK;
+}
+
+int
+dwarf_get_string_attributes_info(Dwarf_P_Debug dbg,
+ Dwarf_Signed *elf_section_index,
+ Dwarf_Unsigned *sect_sa_buffer_count,
+ Dwarf_P_String_Attr *sect_sa_buffer,
+ Dwarf_Error *error)
+{
+ int i = 0;
+ int next = dbg->de_sect_sa_next_to_return;
+
+ for (i = next; i < NUM_DEBUG_SECTIONS; ++i) {
+ Dwarf_P_Per_Sect_String_Attrs sect_sa = &dbg->de_sect_string_attr[i];
+ if (sect_sa->sect_sa_n_used > 0) {
+ dbg->de_sect_sa_next_to_return = i + 1;
+ *elf_section_index = sect_sa->sect_sa_section_number;
+ *sect_sa_buffer_count = sect_sa->sect_sa_n_used;
+ *sect_sa_buffer = sect_sa->sect_sa_list;
+ return DW_DLV_OK;
+ }
+ }
+ return DW_DLV_NO_ENTRY;
+}
+
+
+
+/* Generate debug_info and debug_abbrev sections */
+
+static int
+_dwarf_pro_generate_debuginfo(Dwarf_P_Debug dbg, Dwarf_Error * error)
+{
+ int elfsectno_of_debug_info = 0;
+ int abbrevsectno = 0;
+ unsigned char *data = 0;
+ int cu_header_size = 0;
+ Dwarf_P_Abbrev curabbrev = 0;
+ Dwarf_P_Abbrev abbrev_head = 0;
+ Dwarf_P_Abbrev abbrev_tail = 0;
+ Dwarf_P_Die curdie = 0;
+ Dwarf_P_Die first_child = 0;
+ Dwarf_Word dw = 0;
+ Dwarf_Unsigned du = 0;
+ Dwarf_Half dh = 0;
+ Dwarf_Ubyte db = 0;
+ Dwarf_Half version = 0; /* Need 2 byte quantity. */
+ Dwarf_Unsigned die_off = 0; /* Offset of die in debug_info. */
+ int n_abbrevs = 0;
+ int res = 0;
+ unsigned marker_count = 0;
+ unsigned string_attr_count = 0;
+ unsigned string_attr_offset = 0;
+
+ Dwarf_Small *start_info_sec = 0;
+
+ int uwordb_size = dbg->de_offset_size;
+ int extension_size = dbg->de_64bit_extension ? 4 : 0;
+
+ abbrev_head = abbrev_tail = NULL;
+ elfsectno_of_debug_info = dbg->de_elf_sects[DEBUG_INFO];
+
+ /* write cu header */
+ cu_header_size = BEGIN_LEN_SIZE +
+ sizeof(Dwarf_Half) + /* version stamp */
+ uwordb_size + /* offset into abbrev table */
+ sizeof(Dwarf_Ubyte); /* size of target address */
+ GET_CHUNK(dbg, elfsectno_of_debug_info, data, cu_header_size,
+ error);
+ start_info_sec = data;
+ if (extension_size) {
+ du = DISTINGUISHED_VALUE;
+ WRITE_UNALIGNED(dbg, (void *) data,
+ (const void *) &du, sizeof(du), extension_size);
+ data += extension_size;
+ }
+ du = 0; /* length of debug_info, not counting
+ this field itself (unknown at this point). */
+ WRITE_UNALIGNED(dbg, (void *) data,
+ (const void *) &du, sizeof(du), uwordb_size);
+ data += uwordb_size;
+
+ version = CURRENT_VERSION_STAMP;
+ WRITE_UNALIGNED(dbg, (void *) data, (const void *) &version,
+ sizeof(version), sizeof(Dwarf_Half));
+ data += sizeof(Dwarf_Half);
+
+ du = 0;/* offset into abbrev table, not yet known. */
+ WRITE_UNALIGNED(dbg, (void *) data,
+ (const void *) &du, sizeof(du), uwordb_size);
+ data += uwordb_size;
+
+
+ db = dbg->de_pointer_size;
+
+ WRITE_UNALIGNED(dbg, (void *) data, (const void *) &db,
+ sizeof(db), 1);
+
+ /* We have filled the chunk we got with GET_CHUNK. At this point we
+ no longer dare use "data" or "start_info_sec" as a pointer any
+ longer except to refer to that first small chunk for the cu
+ header. */
+
+ curdie = dbg->de_dies;
+
+ /* Create AT_macro_info if appropriate */
+ if (dbg->de_first_macinfo != NULL) {
+ if (_dwarf_pro_add_AT_macro_info(dbg, curdie, 0, error) < 0)
+ return -1;
+ }
+
+ /* Create AT_stmt_list attribute if necessary */
+ if (dwarf_need_debug_line_section(dbg) == TRUE)
+ if (_dwarf_pro_add_AT_stmt_list(dbg, curdie, error) < 0)
+ return -1;
+
+ die_off = cu_header_size;
+
+ /* Relocation for abbrev offset in cu header store relocation
+ record in linked list */
+ res = dbg->de_reloc_name(dbg, DEBUG_INFO, BEGIN_LEN_SIZE +
+ sizeof(Dwarf_Half),
+ /* r_offset */
+ dbg->de_sect_name_idx[DEBUG_ABBREV],
+ dwarf_drt_data_reloc, uwordb_size);
+ if (res != DW_DLV_OK) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, -1);
+ }
+
+ /* Pass 0: only top level dies, add at_sibling attribute to those
+ dies with children */
+ first_child = curdie->di_child;
+ while (first_child && first_child->di_right) {
+ if (first_child->di_child)
+ dwarf_add_AT_reference(dbg,
+ first_child,
+ DW_AT_sibling,
+ first_child->di_right, error);
+ first_child = first_child->di_right;
+ }
+
+ /* Pass 1: create abbrev info, get die offsets, calc relocations */
+ marker_count = 0;
+ string_attr_count = 0;
+ while (curdie != NULL) {
+ int nbytes = 0;
+ Dwarf_P_Attribute curattr;
+ Dwarf_P_Attribute new_first_attr;
+ Dwarf_P_Attribute new_last_attr;
+ char *space = 0;
+ int res = 0;
+ char buff1[ENCODE_SPACE_NEEDED];
+ int i = 0;
+
+ curdie->di_offset = die_off;
+
+ if (curdie->di_marker != 0)
+ marker_count++;
+
+ curabbrev = _dwarf_pro_getabbrev(curdie, abbrev_head);
+ if (curabbrev == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
+ }
+ if (abbrev_head == NULL) {
+ n_abbrevs = 1;
+ curabbrev->abb_idx = n_abbrevs;
+ abbrev_tail = abbrev_head = curabbrev;
+ } else {
+ /* check if its a new abbreviation, if yes, add to tail */
+ if (curabbrev->abb_idx == 0) {
+ n_abbrevs++;
+ curabbrev->abb_idx = n_abbrevs;
+ abbrev_tail->abb_next = curabbrev;
+ abbrev_tail = curabbrev;
+ }
+ }
+ res = _dwarf_pro_encode_leb128_nm(curabbrev->abb_idx,
+ &nbytes,
+ buff1, sizeof(buff1));
+ if (res != DW_DLV_OK) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
+ }
+ space = _dwarf_p_get_alloc(dbg, nbytes);
+ if (space == NULL) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
+ }
+ memcpy(space, buff1, nbytes);
+ curdie->di_abbrev = space;
+ curdie->di_abbrev_nbytes = nbytes;
+ die_off += nbytes;
+
+ /* Resorting the attributes!! */
+ new_first_attr = new_last_attr = NULL;
+ curattr = curdie->di_attrs;
+ for (i = 0; i < (int)curabbrev->abb_n_attr; i++) {
+ Dwarf_P_Attribute ca;
+ Dwarf_P_Attribute cl;
+
+ /* The following should always find an attribute! */
+ for (ca = cl = curattr;
+ ca && curabbrev->abb_attrs[i] != ca->ar_attribute;
+ cl = ca, ca = ca->ar_next)
+ {
+ }
+
+ if (!ca) {
+ DWARF_P_DBG_ERROR(dbg,DW_DLE_ABBREV_ALLOC, -1);
+ }
+
+ /* Remove the attribute from the old list. */
+ if (ca == curattr) {
+ curattr = ca->ar_next;
+ } else {
+ cl->ar_next = ca->ar_next;
+ }
+
+ ca->ar_next = NULL;
+
+ /* Add the attribute to the new list. */
+ if (new_first_attr == NULL) {
+ new_first_attr = new_last_attr = ca;
+ } else {
+ new_last_attr->ar_next = ca;
+ new_last_attr = ca;
+ }
+ }
+
+ curdie->di_attrs = new_first_attr;
+
+ curattr = curdie->di_attrs;
+
+ while (curattr) {
+ if (curattr->ar_rel_type != R_MIPS_NONE) {
+ switch (curattr->ar_attribute) {
+ case DW_AT_stmt_list:
+ curattr->ar_rel_symidx =
+ dbg->de_sect_name_idx[DEBUG_LINE];
+ break;
+ case DW_AT_MIPS_fde:
+ curattr->ar_rel_symidx =
+ dbg->de_sect_name_idx[DEBUG_FRAME];
+ break;
+ case DW_AT_macro_info:
+ curattr->ar_rel_symidx =
+ dbg->de_sect_name_idx[DEBUG_MACINFO];
+ break;
+ default:
+ break;
+ }
+ res = dbg->de_reloc_name(dbg, DEBUG_INFO,
+ die_off + curattr->ar_rel_offset,/* r_offset */
+ curattr->ar_rel_symidx,
+ dwarf_drt_data_reloc,
+ curattr->ar_reloc_len);
+
+ if (res != DW_DLV_OK) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, -1);
+ }
+
+ }
+ if (curattr->ar_attribute_form == DW_FORM_string) {
+ string_attr_count++;
+ }
+ die_off += curattr->ar_nbytes;
+ curattr = curattr->ar_next;
+ }
+
+ /* depth first search */
+ if (curdie->di_child)
+ curdie = curdie->di_child;
+ else {
+ while (curdie != NULL && curdie->di_right == NULL) {
+ curdie = curdie->di_parent;
+ die_off++; /* since we are writing a null die at
+ the end of each sibling chain */
+ }
+ if (curdie != NULL)
+ curdie = curdie->di_right;
+ }
+
+ } /* end while (curdie != NULL) */
+
+ res = marker_init(dbg, marker_count);
+ if (res == -1) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, -1);
+ }
+ res = string_attr_init(dbg, DEBUG_INFO, string_attr_count);
+ if (res == -1) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, -1);
+ }
+
+ /* Pass 2: Write out the die information Here 'data' is a
+ temporary, one block for each GET_CHUNK. 'data' is overused. */
+ curdie = dbg->de_dies;
+ while (curdie != NULL) {
+ Dwarf_P_Attribute curattr;
+
+ if (curdie->di_marker != 0) {
+ res = marker_add(dbg, curdie->di_offset, curdie->di_marker);
+ if (res == -1) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, -1);
+ }
+ }
+
+ /* Index to abbreviation table */
+ GET_CHUNK(dbg, elfsectno_of_debug_info,
+ data, curdie->di_abbrev_nbytes, error);
+
+ memcpy((void *) data,
+ (const void *) curdie->di_abbrev,
+ curdie->di_abbrev_nbytes);
+
+ /* Attribute values - need to fill in all form attributes */
+ curattr = curdie->di_attrs;
+ string_attr_offset = curdie->di_offset + curdie->di_abbrev_nbytes;
+
+ while (curattr) {
+ GET_CHUNK(dbg, elfsectno_of_debug_info, data,
+ (unsigned long) curattr->ar_nbytes, error);
+ switch (curattr->ar_attribute_form) {
+ case DW_FORM_ref1:
+ {
+ if (curattr->ar_ref_die->di_offset >
+ (unsigned) 0xff) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_OFFSET_UFLW, -1);
+ }
+ db = curattr->ar_ref_die->di_offset;
+ WRITE_UNALIGNED(dbg, (void *) data,
+ (const void *) &db,
+ sizeof(db), sizeof(Dwarf_Ubyte));
+ break;
+ }
+ case DW_FORM_ref2:
+ {
+ if (curattr->ar_ref_die->di_offset >
+ (unsigned) 0xffff) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_OFFSET_UFLW, -1);
+ }
+ dh = curattr->ar_ref_die->di_offset;
+ WRITE_UNALIGNED(dbg, (void *) data,
+ (const void *) &dh,
+ sizeof(dh), sizeof(Dwarf_Half));
+ break;
+ }
+ case DW_FORM_ref_addr:
+ {
+ /* curattr->ar_ref_die == NULL!
+
+ ref_addr doesn't take a CU-offset.
+ This is different than other refs.
+ This value will be set by the user of the
+ producer library using a relocation.
+ No need to set a value here. */
+#if 0
+ du = curattr->ar_ref_die->di_offset;
+ {
+ /* ref to offset of die */
+ WRITE_UNALIGNED(dbg, (void *) data,
+ (const void *) &du,
+ sizeof(du), uwordb_size);
+ }
+#endif
+ break;
+
+ }
+ case DW_FORM_ref4:
+ {
+ if (curattr->ar_ref_die->di_offset >
+ (unsigned) 0xffffffff) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_OFFSET_UFLW, -1);
+ }
+ dw = (Dwarf_Word) curattr->ar_ref_die->di_offset;
+ WRITE_UNALIGNED(dbg, (void *) data,
+ (const void *) &dw,
+ sizeof(dw), sizeof(Dwarf_ufixed));
+ break;
+ }
+ case DW_FORM_ref8:
+ du = curattr->ar_ref_die->di_offset;
+ WRITE_UNALIGNED(dbg, (void *) data,
+ (const void *) &du,
+ sizeof(du), sizeof(Dwarf_Unsigned));
+ break;
+ case DW_FORM_ref_udata:
+ { /* unsigned leb128 offset */
+
+ int nbytes;
+ char buff1[ENCODE_SPACE_NEEDED];
+
+ res =
+ _dwarf_pro_encode_leb128_nm(curattr->
+ ar_ref_die->
+ di_offset, &nbytes,
+ buff1,
+ sizeof(buff1));
+ if (res != DW_DLV_OK) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_ABBREV_ALLOC, -1);
+ }
+
+ memcpy(data, buff1, nbytes);
+ break;
+ }
+ default:
+ memcpy((void *) data,
+ (const void *) curattr->ar_data,
+ curattr->ar_nbytes);
+ break;
+ }
+ if (curattr->ar_attribute_form == DW_FORM_string) {
+ string_attr_add(dbg, DEBUG_INFO, string_attr_offset, curattr);
+ }
+ string_attr_offset += curattr->ar_nbytes;
+ curattr = curattr->ar_next;
+ }
+
+ /* depth first search */
+ if (curdie->di_child)
+ curdie = curdie->di_child;
+ else {
+ while (curdie != NULL && curdie->di_right == NULL) {
+ GET_CHUNK(dbg, elfsectno_of_debug_info, data, 1, error);
+ *data = '\0';
+ curdie = curdie->di_parent;
+ }
+ if (curdie != NULL)
+ curdie = curdie->di_right;
+ }
+ } /* end while (curdir != NULL) */
+
+ /* Write out debug_info size */
+ /* Do not include length field or extension bytes */
+ du = die_off - BEGIN_LEN_SIZE;
+ WRITE_UNALIGNED(dbg, (void *) (start_info_sec + extension_size),
+ (const void *) &du, sizeof(du), uwordb_size);
+
+
+ data = 0; /* Emphasise not usable now */
+
+ /* Write out debug_abbrev section */
+ abbrevsectno = dbg->de_elf_sects[DEBUG_ABBREV];
+
+ curabbrev = abbrev_head;
+ while (curabbrev) {
+ char *val;
+ int nbytes;
+ int idx;
+ int res;
+ char buff1[ENCODE_SPACE_NEEDED];
+
+ write_uval(curabbrev->abb_idx,dbg,abbrevsectno,error);
+ write_uval(curabbrev->abb_tag,dbg,abbrevsectno,error);
+
+ db = curabbrev->abb_children;
+ write_ubyte(db,dbg,abbrevsectno,error);
+
+ /* add attributes and forms */
+ for (idx = 0; idx < curabbrev->abb_n_attr; idx++) {
+ write_uval(curabbrev->abb_attrs[idx],
+ dbg,abbrevsectno,error);
+
+ write_uval(curabbrev->abb_forms[idx],
+ dbg,abbrevsectno,error);
+ }
+ /* Two zeros, for last entry, see dwarf2 sec 7.5.3 */
+ GET_CHUNK(dbg, abbrevsectno, data, 2, error);
+ *data = 0;
+ data++;
+ *data = 0;
+
+ curabbrev = curabbrev->abb_next;
+ }
+
+ /* one zero, for end of cu, see dwarf2 sec 7.5.3 */
+ GET_CHUNK(dbg, abbrevsectno, data, 1, error);
+ *data = 0;
+ return (int) dbg->de_n_debug_sect;
+}
+
+
+/* Get a buffer of section data.
+ section_idx is the elf-section number that this data applies to.
+ length shows length of returned data */
+
+/*ARGSUSED*/ /* pretend all args used */
+Dwarf_Ptr
+dwarf_get_section_bytes(Dwarf_P_Debug dbg,
+ Dwarf_Signed dwarf_section,
+ Dwarf_Signed * section_idx,
+ Dwarf_Unsigned * length, Dwarf_Error * error)
+{
+ Dwarf_Ptr buf = 0;
+
+ if (dbg->de_version_magic_number != PRO_VERSION_MAGIC) {
+ DWARF_P_DBG_ERROR(dbg, DW_DLE_IA, NULL);
+ }
+
+ if (dbg->de_debug_sects == 0) {
+ /* no more data !! */
+ return NULL;
+ }
+ if (dbg->de_debug_sects->ds_elf_sect_no == MAGIC_SECT_NO) {
+ /* no data ever entered !! */
+ return NULL;
+ }
+ *section_idx = dbg->de_debug_sects->ds_elf_sect_no;
+ *length = dbg->de_debug_sects->ds_nbytes;
+
+ buf = (Dwarf_Ptr *) dbg->de_debug_sects->ds_data;
+
+ dbg->de_debug_sects = dbg->de_debug_sects->ds_next;
+
+ /* We may want to call the section stuff more than once: see
+ dwarf_reset_section_bytes() do not do: dbg->de_n_debug_sect--; */
+
+ return buf;
+}
+
+/* No errors possible. */
+void
+dwarf_reset_section_bytes(Dwarf_P_Debug dbg)
+{
+ dbg->de_debug_sects = dbg->de_first_debug_sect;
+ /* No need to reset; commented out decrement. dbg->de_n_debug_sect
+ = ???; */
+ dbg->de_reloc_next_to_return = 0;
+ dbg->de_sect_sa_next_to_return = 0;
+}
+
+/* Storage handler. Gets either a new chunk of memory, or
+ a pointer in existing memory, from the linked list attached
+ to dbg at de_debug_sects, depending on size of nbytes
+
+ Assume dbg not null, checked in top level routine
+
+ Returns a pointer to the allocated buffer space for the
+ lib to fill in, predincrements next-to-use count so the
+ space requested is already counted 'used'
+ when this returns (ie, reserved).
+
+*/
+Dwarf_Small *
+_dwarf_pro_buffer(Dwarf_P_Debug dbg,
+ int elfsectno, unsigned long nbytes)
+{
+ Dwarf_P_Section_Data cursect = 0;
+
+ cursect = dbg->de_current_active_section;
+ /* By using MAGIC_SECT_NO we allow the following MAGIC_SECT_NO must
+ not match any legit section number. test to have just two
+ clauses (no NULL pointer test) See dwarf_producer_init(). */
+ if ((cursect->ds_elf_sect_no != elfsectno) ||
+ ((cursect->ds_nbytes + nbytes) > cursect->ds_orig_alloc)
+ ) {
+
+ /* Either the elf section has changed or there is not enough
+ space in the current section.
+
+ Create a new Dwarf_P_Section_Data_s for the chunk. and have
+ space 'on the end' for the buffer itself so we just do one
+ malloc (not two). */
+ unsigned long space = nbytes;
+
+ if (nbytes < CHUNK_SIZE)
+ space = CHUNK_SIZE;
+
+ cursect = (Dwarf_P_Section_Data)
+ _dwarf_p_get_alloc(dbg,
+ sizeof(struct Dwarf_P_Section_Data_s)
+ + space);
+ if (cursect == NULL) {
+ return (NULL);
+ }
+
+ /* _dwarf_p_get_alloc zeroes the space... */
+
+ cursect->ds_data = (char *) cursect +
+ sizeof(struct Dwarf_P_Section_Data_s);
+ cursect->ds_orig_alloc = space;
+ cursect->ds_elf_sect_no = elfsectno;
+ cursect->ds_nbytes = nbytes; /* reserve this number of bytes
+ of space for caller to fill in */
+ /* Now link on the end of the list, and mark this one as the
+ current one */
+
+ if (dbg->de_debug_sects->ds_elf_sect_no == MAGIC_SECT_NO) {
+ /* The only entry is the special one for 'no entry' so
+ delete that phony one while adding this initial real
+ one. */
+ dbg->de_debug_sects = cursect;
+ dbg->de_current_active_section = cursect;
+ dbg->de_first_debug_sect = cursect;
+ } else {
+ dbg->de_current_active_section->ds_next = cursect;
+ dbg->de_current_active_section = cursect;
+ }
+ dbg->de_n_debug_sect++;
+
+ return ((Dwarf_Small *) cursect->ds_data);
+ }
+
+ /* There is enough space in the current buffer */
+ {
+ Dwarf_Small *space_for_caller = (Dwarf_Small *)
+ (cursect->ds_data + cursect->ds_nbytes);
+
+ cursect->ds_nbytes += nbytes;
+ return space_for_caller;
+ }
+}
+
+
+/* Given address advance and line advance, it gives
+ either special opcode, or a number < 0 */
+static int
+_dwarf_pro_get_opc(Dwarf_P_Debug dbg,Dwarf_Unsigned addr_adv, int line_adv)
+{
+ int line_base = dbg->de_line_inits.pi_line_base;
+ int line_range = dbg->de_line_inits.pi_line_range;
+ Dwarf_Unsigned factored_adv = 0;
+
+ factored_adv = addr_adv / dbg->de_line_inits.pi_minimum_instruction_length;
+ if (line_adv == 0 && factored_adv == 0) {
+ return OPC_INCS_ZERO;
+ }
+ if (line_adv >= line_base && line_adv < line_base + line_range) {
+ int opc = (line_adv - line_base) + (factored_adv * line_range) +
+ dbg->de_line_inits.pi_opcode_base;
+ if (opc > 255) {
+ return OPC_OUT_OF_RANGE;
+ }
+ return opc;
+ }
+ return LINE_OUT_OF_RANGE;
+}
+
+/* Handles abbreviations. It takes a die, searches through
+ current list of abbreviations for matching one. If it
+ finds one, it returns a pointer to it, and if it doesnt,
+ it returns a new one. Upto the user of this function to
+ link it up to the abbreviation head. If its a new one,
+ abb_idx has 0. */
+static Dwarf_P_Abbrev
+_dwarf_pro_getabbrev(Dwarf_P_Die die, Dwarf_P_Abbrev head)
+{
+ Dwarf_P_Abbrev curabbrev;
+ Dwarf_P_Attribute curattr;
+ int res1;
+ int nattrs;
+ int match;
+ Dwarf_ufixed *forms = 0;
+ Dwarf_ufixed *attrs = 0;
+
+ curabbrev = head;
+ while (curabbrev) {
+ if ((die->di_tag == curabbrev->abb_tag) &&
+ ((die->di_child != NULL &&
+ curabbrev->abb_children == DW_CHILDREN_yes) ||
+ (die->di_child == NULL &&
+ curabbrev->abb_children == DW_CHILDREN_no)) &&
+ (die->di_n_attr == curabbrev->abb_n_attr)) {
+
+ /* There is a chance of a match. */
+ curattr = die->di_attrs;
+ match = 1; /* Assume match found. */
+ while (match && curattr) {
+ res1 = _dwarf_pro_match_attr(curattr,
+ curabbrev,
+ (int) curabbrev->
+ abb_n_attr);
+ if (res1 == 0) {
+ match = 0;
+ }
+ curattr = curattr->ar_next;
+ }
+ if (match == 1) {
+ return curabbrev;
+ }
+ }
+ curabbrev = curabbrev->abb_next;
+ }
+
+ /* no match, create new abbreviation */
+ if (die->di_n_attr != 0) {
+ forms = (Dwarf_ufixed *)
+ _dwarf_p_get_alloc(die->di_dbg,
+ sizeof(Dwarf_ufixed) * die->di_n_attr);
+ if (forms == NULL) {
+ return NULL;
+ }
+ attrs = (Dwarf_ufixed *)
+ _dwarf_p_get_alloc(die->di_dbg,
+ sizeof(Dwarf_ufixed) * die->di_n_attr);
+ if (attrs == NULL)
+ return NULL;
+ }
+ nattrs = 0;
+ curattr = die->di_attrs;
+ while (curattr) {
+ attrs[nattrs] = curattr->ar_attribute;
+ forms[nattrs] = curattr->ar_attribute_form;
+ nattrs++;
+ curattr = curattr->ar_next;
+ }
+
+ curabbrev = (Dwarf_P_Abbrev)
+ _dwarf_p_get_alloc(die->di_dbg, sizeof(struct Dwarf_P_Abbrev_s));
+ if (curabbrev == NULL) {
+ return NULL;
+ }
+
+ if (die->di_child == NULL) {
+ curabbrev->abb_children = DW_CHILDREN_no;
+ } else {
+ curabbrev->abb_children = DW_CHILDREN_yes;
+ }
+ curabbrev->abb_tag = die->di_tag;
+ curabbrev->abb_attrs = attrs;
+ curabbrev->abb_forms = forms;
+ curabbrev->abb_n_attr = die->di_n_attr;
+ curabbrev->abb_idx = 0;
+ curabbrev->abb_next = NULL;
+
+ return curabbrev;
+}
+
+/* Tries to see if given attribute and form combination
+ exists in the given abbreviation */
+static int
+_dwarf_pro_match_attr(Dwarf_P_Attribute attr,
+ Dwarf_P_Abbrev abbrev, int no_attr)
+{
+ int i;
+ int found = 0;
+
+ for (i = 0; i < no_attr; i++) {
+ if (attr->ar_attribute == abbrev->abb_attrs[i] &&
+ attr->ar_attribute_form == abbrev->abb_forms[i]) {
+ found = 1;
+ break;
+ }
+ }
+ return found;
+}
diff --git a/libdwarf/pro_section.h b/libdwarf/pro_section.h
new file mode 100644
index 0000000..d6e1627
--- /dev/null
+++ b/libdwarf/pro_section.h
@@ -0,0 +1,109 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+
+
+/* relocation section names */
+extern char *_dwarf_rel_section_names[];
+
+/* section names */
+extern char *_dwarf_sectnames[];
+
+/* struct to hold relocation entries. Its mantained as a linked
+ list of relocation structs, and will then be written at as a
+ whole into the relocation section. Whether its 32 bit or
+ 64 bit will be obtained from Dwarf_Debug pointer. */
+
+
+
+
+
+/* struct stores a chunk of data pertaining to a section */
+struct Dwarf_P_Section_Data_s {
+ int ds_elf_sect_no; /* elf section number */
+ char *ds_data; /* data contained in section */
+ unsigned long ds_nbytes; /* bytes of data used so far */
+ unsigned long ds_orig_alloc; /* bytes allocated originally */
+ Dwarf_P_Section_Data ds_next; /* next on the list */
+};
+
+/* Used to allow a dummy initial struct (which we
+ drop before it gets used
+ This must not match any legitimate 'section' number.
+*/
+#define MAGIC_SECT_NO -3
+
+/* Size of chunk of data allocated in one alloc
+ Not clear if this is the best size.
+ Used to be just 4096 for user data, the section data struct
+ was a separate malloc.
+*/
+#define CHUNK_SIZE (4096 - sizeof (struct Dwarf_P_Section_Data_s))
+
+/*
+ chunk alloc routine -
+ if chunk->ds_data is nil, it will alloc CHUNK_SIZE bytes,
+ and return pointer to the beginning. If chunk is not nil,
+ it will see if there's enoungh space for nbytes in current
+ chunk, if not, add new chunk to linked list, and return
+ a char * pointer to it. Return null if unsuccessful.
+*/
+Dwarf_Small *_dwarf_pro_buffer(Dwarf_P_Debug dbg, int sectno,
+ unsigned long nbytes);
+
+#define GET_CHUNK(dbg,sectno,ptr,nbytes,error) \
+{ \
+ (ptr) = _dwarf_pro_buffer((dbg),(sectno),(nbytes)); \
+ if ((ptr) == NULL) { \
+ DWARF_P_DBG_ERROR(dbg,DW_DLE_CHUNK_ALLOC,-1); \
+ } \
+}
+
+
+
+int
+ _dwarf_transform_arange_to_disk(Dwarf_P_Debug dbg,
+ Dwarf_Error * error);
+
+/* These are for creating ELF section type codes.
+*/
+#if defined(linux) || defined(__BEOS__) || !defined(SHT_MIPS_DWARF)
+/* Intel's SoftSdv accepts only this */
+#define SECTION_TYPE SHT_PROGBITS
+#else
+#define SECTION_TYPE SHT_MIPS_DWARF
+#endif
diff --git a/libdwarf/pro_types.c b/libdwarf/pro_types.c
new file mode 100644
index 0000000..ad14164
--- /dev/null
+++ b/libdwarf/pro_types.c
@@ -0,0 +1,284 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_ELFACCESS_H
+#include <elfaccess.h>
+#endif
+#include "pro_incl.h"
+#include "pro_section.h"
+
+
+/*
+ This function adds another type name to the
+ list of type names for the given Dwarf_P_Debug.
+ It returns 0 on error, and 1 otherwise.
+*/
+Dwarf_Unsigned
+dwarf_add_typename(Dwarf_P_Debug dbg,
+ Dwarf_P_Die die,
+ char *type_name, Dwarf_Error * error)
+{
+ return
+ _dwarf_add_simple_name_entry(dbg, die, type_name,
+ dwarf_snk_typename, error);
+}
+
+/*
+ The following is the generic 'add a simple name entry'
+ for any of the simple name sections.
+
+ See enum dwarf_sn_kind in pro_opaque.h
+
+*/
+Dwarf_Unsigned
+_dwarf_add_simple_name_entry(Dwarf_P_Debug dbg,
+ Dwarf_P_Die die,
+ char *entry_name,
+ enum dwarf_sn_kind entrykind,
+ Dwarf_Error * error)
+{
+ Dwarf_P_Simple_nameentry nameentry;
+ Dwarf_P_Simple_name_header hdr;
+ char *name;
+ int uword_size;
+
+ if (dbg == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
+ return (0);
+ }
+
+ if (die == NULL) {
+ _dwarf_p_error(NULL, error, DW_DLE_DIE_NULL);
+ return (0);
+ }
+
+
+ nameentry = (Dwarf_P_Simple_nameentry)
+ _dwarf_p_get_alloc(dbg,
+ sizeof(struct Dwarf_P_Simple_nameentry_s));
+ if (nameentry == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (0);
+ }
+
+ name = _dwarf_p_get_alloc(dbg, strlen(entry_name) + 1);
+ if (name == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (0);
+ }
+ strcpy(name, entry_name);
+
+ nameentry->sne_die = die;
+ nameentry->sne_name = name;
+ nameentry->sne_name_len = strlen(name);
+ uword_size = dbg->de_offset_size;
+
+ hdr = &dbg->de_simple_name_headers[entrykind];
+ if (hdr->sn_head == NULL)
+ hdr->sn_head = hdr->sn_tail = nameentry;
+ else {
+ hdr->sn_tail->sne_next = nameentry;
+ hdr->sn_tail = nameentry;
+ }
+ hdr->sn_count++;
+ hdr->sn_net_len += uword_size + nameentry->sne_name_len + 1;
+
+ return (1);
+}
+
+
+
+/*
+ _dwarf_transform_simplename_to_disk writes
+ ".rel.debug_pubnames",
+ ".rel.debug_funcnames", sgi extension
+ ".rel.debug_typenames", sgi extension
+ ".rel.debug_varnames", sgi extension
+ ".rel.debug_weaknames", sgi extension
+ to disk.
+ section_index indexes one of those sections.
+ entrykind is one of those 'kind's. */
+int
+_dwarf_transform_simplename_to_disk(Dwarf_P_Debug dbg,
+ enum dwarf_sn_kind entrykind,
+ int section_index, /* in de_elf_sects etc */
+ Dwarf_Error * error)
+{
+
+
+ /* Used to fill in 0. */
+ const Dwarf_Signed big_zero = 0;
+
+ /* Used to scan the section data buffers. */
+ Dwarf_P_Section_Data debug_sect;
+
+ Dwarf_Signed debug_info_size;
+
+ Dwarf_P_Simple_nameentry nameentry_original;
+ Dwarf_P_Simple_nameentry nameentry;
+ Dwarf_Small *stream_bytes;
+ Dwarf_Small *cur_stream_bytes_ptr;
+ Dwarf_Unsigned stream_bytes_count;
+ Dwarf_Unsigned adjusted_length; /* count excluding length field */
+
+
+ int uword_size = dbg->de_offset_size;
+ int extension_size = dbg->de_64bit_extension ? 4 : 0;
+
+ Dwarf_P_Simple_name_header hdr;
+
+
+ /* ***** BEGIN CODE ***** */
+
+ debug_info_size = 0;
+ for (debug_sect = dbg->de_debug_sects; debug_sect != NULL;
+ debug_sect = debug_sect->ds_next) {
+ /* We want the size of the .debug_info section for this CU
+ because the dwarf spec requires us to output it below so we
+ look for it specifically. */
+ if (debug_sect->ds_elf_sect_no == dbg->de_elf_sects[DEBUG_INFO]) {
+ debug_info_size += debug_sect->ds_nbytes;
+ }
+ }
+
+ hdr = &dbg->de_simple_name_headers[entrykind];
+ /* Size of the .debug_typenames (or similar) section header. */
+ stream_bytes_count = extension_size + uword_size + /* Size of
+ length field. */
+ sizeof(Dwarf_Half) + /* Size of version field. */
+ uword_size + /* Size of .debug_info offset. */
+ uword_size; /* Size of .debug_names. */
+
+
+
+ nameentry_original = hdr->sn_head;
+ nameentry = nameentry_original;
+ /* add in the content size */
+ stream_bytes_count += hdr->sn_net_len;
+
+ /* Size of the last 0 offset. */
+ stream_bytes_count += uword_size;
+
+ /* Now we know how long the entire section is */
+ GET_CHUNK(dbg, dbg->de_elf_sects[section_index],
+ stream_bytes, (unsigned long) stream_bytes_count, error);
+ if (stream_bytes == NULL) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (0);
+ }
+ cur_stream_bytes_ptr = stream_bytes;
+
+ if (extension_size) {
+ Dwarf_Unsigned x = DISTINGUISHED_VALUE;
+
+ WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr,
+ (const void *) &x, sizeof(x), extension_size);
+ cur_stream_bytes_ptr += extension_size;
+
+ }
+ /* Write the adjusted length of .debug_*names section. */
+ adjusted_length = stream_bytes_count - uword_size - extension_size;
+ WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr,
+ (const void *) &adjusted_length,
+ sizeof(adjusted_length), uword_size);
+ cur_stream_bytes_ptr += uword_size;
+
+ /* Write the version as 2 bytes. */
+ {
+ Dwarf_Half verstamp = CURRENT_VERSION_STAMP;
+
+ WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr,
+ (const void *) &verstamp,
+ sizeof(verstamp), sizeof(Dwarf_Half));
+ cur_stream_bytes_ptr += sizeof(Dwarf_Half);
+ }
+
+ /* Write the offset of the compile-unit. */
+ WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr,
+ (const void *) &big_zero,
+ sizeof(big_zero), uword_size);
+ cur_stream_bytes_ptr += uword_size;
+
+ /* now create the relocation for the compile_unit offset */
+ {
+ int res = dbg->de_reloc_name(dbg,
+ section_index,
+ extension_size + uword_size +
+ sizeof(Dwarf_Half) /* r_offset */ ,
+ /* debug_info section name symbol */
+ dbg->de_sect_name_idx[DEBUG_INFO],
+ dwarf_drt_data_reloc,
+ uword_size);
+
+ if (res != DW_DLV_OK) {
+ _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (0);
+ }
+ }
+
+ /* Write the size of .debug_info section. */
+ WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr,
+ (const void *) &debug_info_size,
+ sizeof(debug_info_size), uword_size);
+ cur_stream_bytes_ptr += uword_size;
+
+
+ for (nameentry = nameentry_original;
+ nameentry != NULL; nameentry = nameentry->sne_next) {
+
+ /* Copy offset of die from start of compile-unit. */
+ WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr,
+ (const void *) &nameentry->sne_die->di_offset,
+ sizeof(nameentry->sne_die->di_offset),
+ uword_size);
+ cur_stream_bytes_ptr += uword_size;
+
+ /* Copy the type name. */
+ strcpy((char *) cur_stream_bytes_ptr, nameentry->sne_name);
+ cur_stream_bytes_ptr += nameentry->sne_name_len + 1;
+ }
+
+ WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr,
+ (const void *) &big_zero,
+ sizeof(big_zero), uword_size);
+ return (int) dbg->de_n_debug_sect;
+}
diff --git a/libdwarf/pro_types.h b/libdwarf/pro_types.h
new file mode 100644
index 0000000..03d3549
--- /dev/null
+++ b/libdwarf/pro_types.h
@@ -0,0 +1,43 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+/* pro_types.h */
+
+
+int _dwarf_transform_simplename_to_disk(Dwarf_P_Debug dbg,
+ enum dwarf_sn_kind entrykind,
+ int section_index,/* in de_elf_sects etc */
+ Dwarf_Error * error);
diff --git a/libdwarf/pro_util.h b/libdwarf/pro_util.h
new file mode 100644
index 0000000..6a8e8e1
--- /dev/null
+++ b/libdwarf/pro_util.h
@@ -0,0 +1,146 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+
+#define IS_64BIT(dbg) ((dbg)->de_flags & DW_DLC_SIZE_64 ? 1 : 0)
+#define ISA_IA64(dbg) ((dbg)->de_flags & DW_DLC_ISA_IA64 ? 1 : 0)
+
+/* definition of sizes of types, given target machine */
+#define sizeof_sbyte(dbg) sizeof(Dwarf_Sbyte)
+#define sizeof_ubyte(dbg) sizeof(Dwarf_Ubyte)
+#define sizeof_uhalf(dbg) sizeof(Dwarf_Half)
+/* certain sizes not defined here, but set in dbg record.
+ See pro_init.c
+*/
+
+/* Computes amount of padding necessary to align n to a k-boundary. */
+/* Important: Assumes n, k both GREATER than zero. */
+#define PADDING(n, k) ( (k)-1 - ((n)-1)%(k) )
+
+/* The following defines are only important for users of the
+** producer part of libdwarf, and such should have these
+** defined correctly (as necessary)
+** by the #include <elf.h> done in pro_incl.h
+** before the #include "pro_util.h".
+** For others producer macros do not matter so 0 is a usable value, and
+** zero values let compilation succeed on more non-MIPS architectures.
+** A better approach would be welcome.
+*/
+/* R_MIPS* are #define so #ifndef works */
+/* R_IA_64* are not necessarily #define (might be enum) so #ifndef
+ is useless, we use the configure script generating
+ HAVE_R_IA_64_DIR32LSB and HAVE_R_IA64_DIR32LSB.
+*/
+#ifndef R_MIPS_64
+#define R_MIPS_64 0
+#endif
+#ifndef R_MIPS_32
+#define R_MIPS_32 0
+#endif
+#ifndef R_MIPS_SCN_DISP
+#define R_MIPS_SCN_DISP 0
+#endif
+
+/* R_IA_64_DIR32LSB came before the now-standard R_IA64_DIR32LSB
+ (etc) was defined. This now deals with either form,
+ preferring the new form if available. */
+#ifdef HAVE_R_IA64_DIR32LSB
+#define DWARF_PRO_R_IA64_DIR32LSB R_IA64_DIR32LSB
+#define DWARF_PRO_R_IA64_DIR64LSB R_IA64_DIR64LSB
+#define DWARF_PRO_R_IA64_SEGREL64LSB R_IA64_SEGREL64LSB
+#define DWARF_PRO_R_IA64_SEGREL32LSB R_IA64_SEGREL32LSB
+#endif
+#if defined(HAVE_R_IA_64_DIR32LSB) && !defined(HAVE_R_IA64_DIR32LSB)
+#define DWARF_PRO_R_IA64_DIR32LSB R_IA_64_DIR32LSB
+#define DWARF_PRO_R_IA64_DIR64LSB R_IA_64_DIR64LSB
+#define DWARF_PRO_R_IA64_SEGREL64LSB R_IA_64_SEGREL64LSB
+#define DWARF_PRO_R_IA64_SEGREL32LSB R_IA_64_SEGREL32LSB
+#endif
+#if !defined(HAVE_R_IA_64_DIR32LSB) && !defined(HAVE_R_IA64_DIR32LSB)
+#define DWARF_PRO_R_IA64_DIR32LSB 0
+#define DWARF_PRO_R_IA64_DIR64LSB 0
+#define DWARF_PRO_R_IA64_SEGREL64LSB 0
+#define DWARF_PRO_R_IA64_SEGREL32LSB 0
+#endif
+
+/* The default "I don't know" value can't be zero.
+ Because that's the sentinel value that means "no relocation".
+ In order to use this library in 'symbolic relocation mode we
+ don't care if this value is the right relocation value,
+ only that it's non-NULL. So at the end, we define it
+ to something sensible. */
+
+
+
+#if defined(sun)
+#if defined(sparc)
+#define Get_REL64_isa(dbg) (R_SPARC_UA64)
+#define Get_REL32_isa(dbg) (R_SPARC_UA32)
+#define Get_REL_SEGREL_isa(dbg) (R_SPARC_NONE) /* I don't know! */
+#else /* i386 */
+#define Get_REL64_isa(dbg) (R_386_32) /* Any non-zero value is ok */
+#define Get_REL32_isa(dbg) (R_386_32)
+#define Get_REL_SEGREL_isa(dbg) (R_386_NONE) /* I don't know! */
+#endif /* sparc || i386 */
+#else /* !sun */
+#ifdef HAVE_SYS_IA64_ELF_H
+#define Get_REL64_isa(dbg) (ISA_IA64(dbg) ? \
+ DWARF_PRO_R_IA64_DIR64LSB : R_MIPS_64)
+#define Get_REL32_isa(dbg) (ISA_IA64(dbg) ? \
+ DWARF_PRO_R_IA64_DIR32LSB : R_MIPS_32)
+
+
+/* ia64 uses 32bit dwarf offsets for sections */
+#define Get_REL_SEGREL_isa(dbg) (ISA_IA64(dbg) ? \
+ DWARF_PRO_R_IA64_SEGREL32LSB : R_MIPS_SCN_DISP)
+#else /* HAVE_SYS_IA64_ELF_H */
+
+#if !defined(linux) && !defined(__BEOS__)
+#define Get_REL64_isa(dbg) (R_MIPS_64)
+#define Get_REL32_isa(dbg) (R_MIPS_32)
+#define Get_REL_SEGREL_isa(dbg) (R_MIPS_SCN_DISP)
+#else
+#define Get_REL64_isa(dbg) (1)
+#define Get_REL32_isa(dbg) (1) /* these are used on linux */
+#define Get_REL_SEGREL_isa(dbg) (1) /* non zero values, see comments above */
+#endif
+
+#endif /* HAVE_SYS_IA64_ELF_H */
+#endif /* !sun */
+
+
diff --git a/libdwarf/pro_vars.c b/libdwarf/pro_vars.c
new file mode 100644
index 0000000..b2e42f9
--- /dev/null
+++ b/libdwarf/pro_vars.c
@@ -0,0 +1,63 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_ELFACCESS_H
+#include <elfaccess.h>
+#endif
+#include "pro_incl.h"
+#include "pro_section.h"
+
+/*
+ This function adds another variable name to the
+ list of variable names for the given Dwarf_P_Debug.
+ It returns 0 on error, and 1 otherwise.
+*/
+Dwarf_Unsigned
+dwarf_add_varname(Dwarf_P_Debug dbg,
+ Dwarf_P_Die die, char *var_name, Dwarf_Error * error)
+{
+ return
+ _dwarf_add_simple_name_entry(dbg, die, var_name,
+ dwarf_snk_varname, error);
+
+
+}
diff --git a/libdwarf/pro_weaks.c b/libdwarf/pro_weaks.c
new file mode 100644
index 0000000..2e3de72
--- /dev/null
+++ b/libdwarf/pro_weaks.c
@@ -0,0 +1,62 @@
+/*
+
+ Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright 2011 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2.1 of the GNU Lesser General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
+ USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+*/
+
+
+
+#include "config.h"
+#include "libdwarfdefs.h"
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_ELFACCESS_H
+#include <elfaccess.h>
+#endif
+#include "pro_incl.h"
+#include "pro_section.h"
+
+/*
+ This function adds another weak name to the
+ list of weak names for the given Dwarf_P_Debug.
+ It returns 0 on error, and 1 otherwise.
+*/
+Dwarf_Unsigned
+dwarf_add_weakname(Dwarf_P_Debug dbg,
+ Dwarf_P_Die die,
+ char *weak_name, Dwarf_Error * error)
+{
+ return
+ _dwarf_add_simple_name_entry(dbg, die, weak_name,
+ dwarf_snk_weakname, error);
+}