summaryrefslogtreecommitdiff
path: root/dwarfdump2
diff options
context:
space:
mode:
Diffstat (limited to 'dwarfdump2')
-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
57 files changed, 24984 insertions, 0 deletions
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);
+