diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2012-10-20 14:42:03 +0400 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2012-10-20 14:42:03 +0400 |
commit | bb1c3da3c12651f1c408d96dd6d33ae157bdadd6 (patch) | |
tree | 4a535b35500684ac6a928bf0fd661325b5a04697 /dwarfdump2 | |
download | dwarfutils-bb1c3da3c12651f1c408d96dd6d33ae157bdadd6.tar.gz |
Imported Upstream version 20120410upstream/20120410upstream
Diffstat (limited to 'dwarfdump2')
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, + §ion_name, + §ion_addr, + §ion_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, ®num); + 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, ®num, &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(®Table_,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_, ®tab2 ,&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 = + ®tab2.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_, ®Table_,&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( ®Table_.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, + ¤t_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); + |