diff options
Diffstat (limited to 'dwarfdump')
67 files changed, 27434 insertions, 0 deletions
diff --git a/dwarfdump/CODINGSTYLE b/dwarfdump/CODINGSTYLE new file mode 100644 index 0000000..64bbb48 --- /dev/null +++ b/dwarfdump/CODINGSTYLE @@ -0,0 +1,44 @@ +This document is a brief description of the main +coding style conventions in dwarfdump. Many of them +will be obvious from the code, but over time some +accidental diffences crept in. + + +Code should be indented in multiples of 4 spaces, and +tabs should not be used to indent the source code. +Use the dicheck program to check indenting. + +The struct naming convention is 'struct my_struct_s' for the +struct defined here (meaning the name should end with _s). +It is better to not do struct typedefs of local structs. +Coders should type 'struct mystruct_s'. Readability +is much more important than brevity. + +Any data or function not referenced outside the +defining source file should be declared 'static'. + +Any duplicated code is a candidate for refactoring +into a subprogram. + +Function names should be all lower case with underbars +with the goal that statements and comments 'read well'. + +Variables should be lower-case with +underbars for readability. It's ok for a small loop +with counters to use single letter names like i or k or m. + +Structure members should have a struct-specific +2-character prefix to the name (followed by +an underbar). That makes it much +easier to grep for uses of members. + +Try to keep lines under 80 characters in length. + +Ensure every if() has {} to enclose the actions. + +Use libdwarf.h types for all the data objects you define, +though sometimes an 'unsigned' or 'int' or 'size_t' is +ok in restricted circumstances. Dwarf_Unsigned and +Dwarf_Signed are the preferred integer types for general use. + +------------ diff --git a/dwarfdump/COPYING b/dwarfdump/COPYING new file mode 100644 index 0000000..355bd60 --- /dev/null +++ b/dwarfdump/COPYING @@ -0,0 +1,31 @@ + +David Anderson: December 2006 +The code in the dwarfdump directory is (if you look +in each file) covered by the GPL (not the LGPL). The +DWARFDUMPCOPYRIGHT file, though, said (before December 24, +2006) the copyright is LGPL. There is no doubt in my (David +Anderson) mind that the intent was always that dwarfdump be +GPL and the copyright markings in each file are correct. + +There are three files marked with the LGPL: tag_tree.list +tag_attr.list acconfig.h. These markings are left as is and +these are are therefore LGPL files. + +The DWARFDUMPCOPYRIGHT file now (Dec 24 2006) has both +copyrights and an explanation of where each applies. + + + +------------------------------------------- +The text present for years, thru Dec 23, 2006: +The files: + dwarfdump.c + and all the .h and .c files in this implementation of + dwarfdump are copyrighted according to the file + DWARFDUMPCOPYRIGHT. + + + +$Source: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/COPYING,v $ +$Revision: 1.1 $ +$Date: 2001/01/16 17:47:55 $ diff --git a/dwarfdump/ChangeLog b/dwarfdump/ChangeLog new file mode 100644 index 0000000..03bb4a1 --- /dev/null +++ b/dwarfdump/ChangeLog @@ -0,0 +1,2 @@ +2012-04-10 DavidAnderson <davea42@earthlink.net> + * dwarfdump.c, common.c: Updated version string. diff --git a/dwarfdump/ChangeLog2006 b/dwarfdump/ChangeLog2006 new file mode 100644 index 0000000..dbedb67 --- /dev/null +++ b/dwarfdump/ChangeLog2006 @@ -0,0 +1,332 @@ +2006-12-24 David Anderson <davea@sgi.com> + * DWARFDUMPCOPYRIGHT: Added GPL copyright text with + explanation of the intended content. + * COPYING: added text explaining confusion of GPL vs LGPL. + Thanks to Chris Quenelle for pointing out the disconnect + between DWARFDUMPCOPYRIGHT and the source files in dwarfdump. +2006-12-21 David Anderson <davea@sgi.com> + * tag_tree.list: add tags to make allowed list more complete. + Omission noticed by Marcel Mettes. +2006-06-14 David Anderson <davea@sgi.com> + * print_frames.c: Clean up printing of augmentation data by + eliminating dangling 0x (for eh_frame). +2006-04-28 David Anderson <davea@sgi.com> + * dwarfdump.conf: Now has x86_64 register names. + x86_64 with help from Tom Hughes (verified + from independent sources). + Added m68k register names and refined x86 list + by looking at various information-sources. +2006-04-18 David Anderson <davea@sgi.com> + * *.c: Ran indent so all now follow a standard look. + * dwconf.c: Added fclose(conf_stream). +2006-04-18 David Anderson <davea@sgi.com> + * dwarfdump.c: Forgot to call key new functions for + handling variable-size frame data and different + frame rule initialization value. + * dwconf.c: Add a default print for CFA in case of + an omission in dwarfdump.conf. + * dwarfdump.conf: Move setup and rename the ABIs slightly. +2006-04-17 David Anderson <davea@sgi.com> + * dwarfdump.conf: Correct typos. Remove some register names. + * dwarfdump.c: Fix compiler warnings, fix -x option usage message. + * dwconf.h: Fix compiler warnings by changing types. + * dwconf.c: Change error checking so we check all errors, do + not stop at first error. Ran indent. Added code to check + for extra junk after operand(s). + * print_frames.c: Fix compiler warnings. + * Makefile.in: get <prefix> used in install rule and creating + places to search for dwarfdump.conf +2006-04-16 David Anderson <davea@sgi.com> + * dwarfdump.conf: New dwarfdump configuration file. Makes using frame + information easy to read and correct for any ABI/ISA + without rebuilding dwarfdump. + * Makefile.in: Added new files dwconf.h dwconf.c + * dwconf.h dwconf.c: New files implement reading dwarfdump.conf + and help print_frames.c print frame information correctly + for ABIs specified at runtime. + * dwarfdump.1: document -x commands. + * globals.h: Minor changes to support dwarfdump.conf + * print_frames.c: Major changes to support a run-time description of + the frames info and dwarfdump.conf. + * print_frames.h: Changes to support a run-time description of + the frames info and dwarfdump.conf. + * print_sections.c: Minor tweaks to support a run-time + description of the frames info and dwarfdump.conf. + +2006-03-31 David Anderson <davea@sgi.com> + * Makefile.in globals.h print_sections.c: Refer to new + print_frames.h print_frames.c. + * print_frames.h print_frames.c: Extract cie, fde printing + to separate file, separating loop logic from the printing + of an entry from the loop. +2006-03-31 David Anderson <davea@sgi.com> + * dwarfdump.c global.h print_sections.c: Preparing for + dwarf3 frame interface. + * print_die.c: Corrects handling of DW_AT_encoding (etc) value. +2006-03-29 David Anderson <davea@sgi.com> + * print_sections.c: define DWARFDUMP_TURN_OFF_MIPS_REG_NAMES + at compile time + to turn off the MIPS register names printing. Instead + (aside from cfa) use a name like r4 (where the DWARF + register number follows the letter 'r'). + Indent. Initialize some local variables at declarations. +2006-03-13 David Anderson <davea@sgi.com> + * print_sections.c: Now gets gnu eh_augmentation data by calling + dwarf_get_cie_augmentation_data() or dwarf_get_fde_augmentation_data() + and prints it (use -v to see cie data). + Now prints DWARF3 frame information. +2006-03-08 David Anderson <davea@sgi.com> + * print_sections.c: Add 'break;' at line 710. + Thanks to Richard Stuckey for noticing. +2005-12-01 David Anderson <davea@sgi.com> + * dwarf_names.awk: use snprintf instead of sprintf for safety. +2005-12-01 David Anderson <davea@sgi.com> + * Makefile.in: Build attr/tag trees with + individual commands to catch build errors. + * tag_attr.c,tag_tree.c: Verify that + tables fit in the generated C code and check for + format errors in the *.list files. + * tag_attr.list, tag_tree.list: Added some valid entries. + * globals.h: add DWARF_ERROR3 macro for better diagnostics. + * print_die.c: Show both sides of questionable tag relation + in CHECK -k diagnostic output. + +2005-11-25 David Anderson <davea@sgi.com> + * print_die.c: DW_AT_stride_size changed to DW_AT_bit_stride, + added DW_AT_byte_stride. + * tag_attr.c,tag_tree.c: fixed array size now a #define for + readability. + * tag_attr.list: Added DWARF3 attributes, also new TAGs. + * tag_tree.list: Added DWARF3 TAGs. + +2005-11-08 David Anderson <davea@sgi.com> + * makename.c: remove non-standard malloc.h include, + stdlib.h suffices and is already included. + +2005-10-24 David Anderson <davea@sgi.com> + * tag_attr.c tag_tree.c: added DWARF3 TAGs to string array. + +2005-08-01 David Anderson <davea@sgi.com> + * Makefile.in: Add esb.o and test rule (test code for esb.c). + * dwarfdump.c: Remove old static buffer initialization. + * print_die.c: Use esb now, avoid crash due to long loclist + overrunning static buffer. Uses snprintf now, not sprintf. + snprintf is for safety. + * esb.h esb.c: Adding extensible string buffer (esb) code. + * testesb.c: Test code for esb.c. + * print_reloc.c: size field is now Elf64_Xword for + Elf64 as Elf64_Word is only 32 bits. + +2005-07-15 David Anderson <davea@sgi.com> + * dwarfdump.c: Add print of .debug_pubtypes, remove + erroneous dealloc after dwarf_formstring() call. + * globals.h: Add declarations for .debug_pubtypes print. Add + declaration for full dealloc. + * print_die.c: Remove erroneous dealloc after dwarf_formstring() call. + * print_exception_tables.c: Call dwarf_fde_cie_list_dealloc() + for complete dealloc. + * print_sections.c: Remove incorrect dealloc() call. + Add calls to new dealloc routines. Add support of .debug_pubtypes + print. +2005-07-14 David Anderson <davea@sgi.com> + * print_sections.c (print_line_numbers_this_cu): Use new + dwarf_srclines_dealloc() for deallocation after + dwarf_srclines() called. + +2005-04-13 David Anderson <davea@sgi.com> + * print_sections.c: Factors out common print code into + a new routine. Avoid indexing past end of register names + array. Adds checks and prints so that certain errors + in pubnames-like sections are printed usefully (and dwarfdump + then stops if libdwarf gave an error). + +2005-03-21 David Anderson <davea@sgi.com> + * dwarfdump.c: Add -F flag to + request .eh_frame section print. Changed -f flag meaning + to print .debug_frame only. -a flag no longer + prints .debug_frame by default. + * print_sections.c: avoid printing an eh_frame we don't understand. + Add new information per CU when printing line info: specifically + the line section offset. + * globals.h: Added arguments to print_frames() for -F flag. + +2005-03-18 David Anderson <davea@sgi.com> + * print_sections.c: Correct macro section printing. + +2004-10-28 David Anderson <davea@sgi.com> + * DWARFDUMPCOPYRIGHT config.h defs.h dwarfdump.c globals.h + makename.c makename.h print_die.c print_exception_tables.c + print_reloc.c print_sections.c tag_attr.c tag_attr.list + tag_tree.c tag_tree.list: Copyright update, SGI + corporate address change. + +2004-10-26 David Anderson <davea@sgi.com> + * acconfig.h: removed. Was old style autoconf usage. + * configure.in: Updated AC_DEFINE usage, adding args 2 & 3. + * config.guess: Updated. timestamp='2004-06-11'. + * config.sub: Updated. timestamp='2004-03-12'. + * configure config.h.in: regenerated with autoconf 2.58. + +2004-05-14 David Anderson <davea@sgi.com> + + * print_die.c (print_die_and_children): Change to iteration + on siblings (still recursing on children). + + +2004-03-30 David Anderson <davea@sgi.com> + * dwarfdump.c (main): getopt() string should contain k:g + not kg: Thanks to Peter Seiderer for pointing this out. + +2003-12-31 David Anderson <davea@sgi.com> + * README: Added configure example. + * Makefile.in: Removed bogus LIBS line, updated copyright date. + * acconfig.h: Added LGPL copyright to match libdwarf + Silly, but it matches libdwarf version boilerplate. + * config.guess config.sub: new versions from automake-1.6. + * config.h.in configure: Regenerated. + + +2003-10-06 David Anderson <davea@sgi.com> + * dwarfdump.c print_sections.c: applied indent(1). + * print_die.c: applied indent and added ; after + invocations of macros PUSH_DIE_STACK POP_DIE_STACK SPACE + as these were confusing indent a bit. + The indent control file .indent.pro contained: + -bad -bap -nbbo -br -ce -brs + -l72 -lc72 -hnl -nprs + -fca -i4 -lp -psl -npcs + + + +2003-10-02 David Anderson <davea@sgi.com> + * dwarfdump.c: Add -g to indicate use of older + location entry code in libdwarf. So dwarf_loclist + and dwarf_loclist_n are testable. + * globals.h: Added use_old_dwarf_loclist flag so one + can choose the old dwarf_loclist() interface. + For testing. + * print_die.c: Rearranged to avoid code duplication. + Now supports .debug_loc fully. + * print_sections.c: Prints .debug_loc now. + +2003-09-29 David Anderson <davea@sgi.com> + + * print_die.c: with -v, print 'loclist' start and + end addr and also a hint that DW_FORM_indirect is used. + No change for normal output (for now). + +2003-05-19 David Anderson <davea@sgi.com> + * dwarfdump.c call dwarf_srcfiles() to get file names + per cu and pass down to die print routines. + Removed incorrect tests for when to print ".debug_info", + leaving simpler test. + * print_die.c globals.h: print file name (from line info) + with DW_AT_decl_file, adding data from dwarf_srcfiles + to argument list of a few routines to make that possible. + * print_sections.c: moved "line number info" string print so + it prints for -v as well as normal line ouput. + +2002-10-23 Amaury Le Leyzour amaury@sgi.com + * print_sections.c (print_weaknames): Changed + DW_DLA_TYPENAME to DW_DLA_WEAK at dwarf_dealloc(). + +2002-10-22 Tom Hughes <thh@cyberscience.com> + * print_sections.c: macro printing now supported. + * dwarfdump.c: removed erroneous dwarf_dealloc() + of string returned by dwarf_errmsg(). + +2002-11-22 David Anderson <davea@sgi.com> + * dwarf_names.awk at_list.awk: Allow an name to have two + spellings so the historical name preserved yet the dwarf3 + version is supported. First name seen is used/reported + by dwarfdump. + * dwarf.h: DW_TAG_template_type_param(eter) + DW_TAG_template_value_param(eter) DW_AT_namelist_itm(s) + are the ones with alternate spellings now. + Added Universal Parallel C TAGs/Attributes in + user namespace. + * tag_attr.c tag_attr.list tag_tree.c tag_tree.list: + Use the DW_TAG_template_* dwarf3 spellings. + + +2002-05-08 David Anderson <davea@sgi.com> + * tag_attr.list dwarf.h: DW_AT_namelist_items is + wrong, changed to DW_AT_namelist_item + +2002-04-29 Stephen Clarke <stephen.clarke@superh.com> + * dwarfdump.c (main): #ifdef for __CYGWIN__ on open(). + +2001-06-14 David Anderson <davea@sgi.com> + + * print_sections.c: Calling the new libdwarf function + dwarf_get_arange_cu_header_offset() so we can print + the cu header offset for aranges. + + +2000-07-14 Fred Fish <fnf@ninemoons.com> + + * configure.in (LOCATION_OF_LIBELFHEADER): Fix typo for configure + variable to be tested and enclose libelf/libelf.h in <>. + * configure: Regenerated. + +2000-07-10 Fred Fish <fnf@ninemoons.com> + + * Makefile.in (install): Install dwarfdump.1 from $(srcdir). + +2000 June 12 davea@sgi.com + print_sections.c the DW_CFA_offset_extended print + did not multiply by data-alignment factor in the + -v -v detailed output. + And the offsets used %2d when the values were + unsigned int, so now %2u. + + And not all cfa prints of values had + necessarily a type to match + %llu or %lld where required. Depended on the size of Dwarf_Signed + and Dwarf_Unsigned. + So now explicitly use cast to the + right type to match the % format. +2000 April 13 davea@sgi.com + print_sections.c - 1.56 + - A single byte of zero is a perfectly legitmate null + abbreviation entry (in .debug_abbrev) + now we print those directly and avoid a warning + from dwarfdump + + print_die.c - 1.42 + - Explain what combo checker is doing and make it + more maintainable (and fix bug which would + not be hit, but was real enough (in combo checker), + using too large a number as highest tag number). + + tag_tree.list - 1.2 + - Add valid parent/child relationships so checker + does not report valid entries as bogus. + + + + +2000 Feb 24 + Jason Merrill <jason@cygnus.com> noticed that gcc did + not like gcc -E foo.list, so incorporated his fix so + now the Makefile.in makes a link and does gcc -E _tmp.c + +2000 Jan 26 + elena.demikhovsky@intel.com noticed that 3 statements in + print_sections.c got warnings from the compiler + she was using. Simple casts (provided by her) fixed these. + +1999 July 21 + davea@sgi.com + print_sections changed to allow printing + of dwarf-ish egcs c++ .eh_frame data + + +1999 June 14 + Fred Fish fnf@ninemoons.com contributed + autoconf'ing of the libdwarf and dwarfdump source. + + + +1999 June 10 + ChangeLog started. davea@sgi.com David Anderson diff --git a/dwarfdump/ChangeLog2007 b/dwarfdump/ChangeLog2007 new file mode 100644 index 0000000..d1230b5 --- /dev/null +++ b/dwarfdump/ChangeLog2007 @@ -0,0 +1,108 @@ +2007-12-09 DavidAnderson <davea42@earthlink.net> + * print_sections.c print_frames.c: Forgot to commit yesterday. + yesterday's commit includes renaming _dwarf_fde_section_offset + _dwarf_cie_section_offset, _dwarf_print_lines, _dwarf_ld_sort_lines + to dwarf_* form while retaining support for the now obsolete + _dwarf_* form. +2007-12-08 DavidAnderson <davea42@earthlink.net> + * config.h.in, configure.in: Latest linux libelf.h requires + _GNU_SOURCE to get off64_t defined so dwarfdump compiles. + Only define _GNU_SOURCE if libelf.h defines off64_t. + Regenerated configure. + * config.guess, config.sub: Updated to 2.61 + * acconfig.h: Deleted, removing autoconf complaint. +2007-10-15 DavidAnderson <davea42@earthlink.net> + * print_die.c (clean_up_die_esb): New function + cleans up malloc space. + * print_reloc.c (clean_up_syms_malloc_data): New function + cleans up malloc space. + * dwarfdump.c (main): Call new cleanup functions at end. + * globals.h: Declare new cleanup functions. + +2007-09-04 DavidAnderson <davea42@earthlink.net> + * print_die.c (print_attribute): For DWARF4: DW_AT_high_pc: + add qualifier to value when the value is an offset from + DW_AT_low_pc (thus not itself a address). + Update the address of the FSF. + * print_frames.h DWARFDUMPCOPYRIGHT print_sections.c + print_reloc.c dwarfdump.c tag_tree.c tag_attr.c + esb.c esb.h makename.c acconfig.h dwconf.c makename.h + dwconf.h globals.h print_frames.c: + Update the address of the FSF. + +2007-07-03 DavidAnderson <davea42@earthlink.net> + * print_sections.c (dump_block): Removed superfluous return byte from + printed characters. Removed unused variables. + * print_die.c: A little refactoring for clarity. + * globals.h: dwarfdump_print_one_locdesc() is now a + global-to-dwarfdump function. + * print_frames.c: Now (with -v) prints dwarf expression bytes + in frame expressions readably. +2007-07-02 DavidAnderson <davea42@earthlink.net> + * dwarfdump.c: Add new -R option for 'generic' register sets. + * dwarfdump.1: document -R, add new -x documentation. + * dwconf.c: Set up -R configuration. Slight revision of + register printing code. + * dwconf.h: Interface to register name printing simplified. + * print_frames.c: Use the simpler register name interface. + * dwarfdump.conf: Add new 'generic' abi for up to 1000 registers. + +2007-07-01 DavidAnderson <davea42@earthlink.net> + * print_frames.c: For DW_CFA_def_cfa_sf & DW_CFA_def_cfa_offset_sf + print a computed data alignment factor. +2007-06-29 DavidAnderson <davea42@earthlink.net> + * dwarfdump.1: Corrected spelling error. +2007-05-25 DavidAnderson <davea42@earthlink.net> + * dwconf.h dwconf.c: Changed field name to + cf_named_regs_table_size as old name was less than clear. + * dwarfdump.c: Call frame table setup with + cf_table_entry_count not cf_named_regs_table_size. The newly + renamed field makes it clearer the call was wrong. +2007-05-04 DavidAnderson <davea42@earthlink.net> + * print_die.c: printing of global offset of DIEs + with -G is now more in the style of previous output. +2007-04-18 Chris Quenelle <chris.quenelle@sun.com> + * Makefile.in: + - use $(srcdir) for files in source directory + - support running rules in parallel by + - use different tmp file names in different rules. + - use more accurate target for dwarf_names.{c,h} + * dwarf_names.awk: Enhance script to be able to generate either + #define-style headers or enum-style headers + * dwarfdump.c: dump most everything by default if no arguments + are given to dwarfdump. This seems to be a more useful default + than showing nothing at all. Also add a -G option to show + the (G)lobal section offset for each die within an a.out. If you + think you're seeing data corruption inside a .debug_info + section, this is a useful option to have. + * print_die.c: Support compressed integer blocks. This is an + array (DW_FORM_block) of LEB numbers used as part of a Sun + extension, DW_AT_SUN_func_offsets. Also add support for + a new dwarf enum DW_ATCF_xxxx. This is used in DW_AT_SUN_cf_kind. + Also, fix DW_AT_upper_bound so it can be a constant or a location + list. DW_AT_count and DW_AT_data_member_location should also be + fixed eventually. + * print_sections.c: Changes to support zero-padding in the middle of + section data. Change offset labels to be a little more clear. + Not sure about the get_str failure. + * tag_tree.list: DW_TAG_compile_unit can contain a DW_TAG_namespace +2007-04-10 David Anderson <davea42@earthlink.net> + * print_reloc.c dwarfdump.c print_frames.c: Unified + copyright to the SGI form. No copyright change. + +2007-04-06 David Anderson <davea42@earthlink.net> + * print_die.c (print_die_and_children): Increase static + depth of die stack. Notice if it overflows and + print error. +2007-02-23 David Anderson <davea42@earthlink.net> + * print_reloc.c: 2 lines added (long) cast in printf + and made %3ld instead of %3d to fix compiler warning. + * print_frames.c: newline was missing from the output. + Thanks to Chris Quenelle for noticing. +2007-02-20 David Anderson <davea42@earthlink.net> + * print_frame.c (print_frame_inst_bytes): Fixed + an off by one error (several places) + when printing dwarf expressions and added commentary about it. + Thanks to Julian Seward for pointing out it was off by one. + * dwarfdump.c (print_error): added fflush of stdout, stderr + where we are going to exit right away anyway. diff --git a/dwarfdump/ChangeLog2008 b/dwarfdump/ChangeLog2008 new file mode 100644 index 0000000..24a1ffa --- /dev/null +++ b/dwarfdump/ChangeLog2008 @@ -0,0 +1,96 @@ +2008-12-30 David Anderson <davea42@earthlink.net> + * tag_attr.list: Mark DW_AT_artificial as sensible on + DW_TAG_variable. + * dwarfdump.1: Document -N option to print .debug_ranges. + * Makefile.in: add new source header files + * dwarfdump.c: Implement -N to print .debug_ranges. + * print_sections.c: Allow more flexible printing + of function names for .debug_frame section. + With -N, print .debug_ranges. + * print_die.c: Print .debug_ranges details. + * print_frames.c: Delete useless comment. + * globals.h: Allow re-use of debug_ranges formatting code. + * Makefile.in: Make the header dependency list more complete. + * makename.h: Comment tweaked. +2008-12-08 David Anderson <davea42@earthlink.net> + * print_die.c: the -M option now also prints the form + number (after the form name). And -v prints the DIE + abbreviation code, the index into the relevant abbreviation + table. + * globals.h: Removed unused global variable. + * dwarfdump.c: Removed unused global variable. + * dwarfdump.1: document -M and the new -v features. +2008-12-07 David Anderson <davea42@earthlink.net> + * print_reloc.c (print_relocinfo): Removed unused local variable. +2008-11-19 David Anderson <davea42@earthlink.net> + * globals.h: Added new boolean to support -M. + * dwarfdump.1: Mentioning the -M option. + * dwarfdump.c: Implementing -M, which has each attribute line + show the name of the form. + * print_die.c: Implementing -M option. +2008-10-12 David Anderson <davea42@earthlink.net> + * dwarfdump.conf: Adding power pc register names and table + size for use with -x abi=ppc . +2008-08-13 David Anderson <davea42@earthlink.net> + * dwarfdump.1: When no options (just object files) present + all sections print, now we say that. Renamed fields + in synopsis for readability. +2008-06-23 David Anderson <davea42@earthlink.net> + * print_reloc.c (print_reloc_information_64): Was testing + sym_data_entry_count one place where sym_data_64_entry_count + should have been tested. Thanks to Carlos Alberto Enciso + for noticing. +2008-06-17 David Anderson <davea42@earthlink.net> + * print_die.c: Add to dwarf_formstring failure message. + * README: Correct email: the old sgi.com address is no + longer correct. +2008-06-13 David Anderson <davea42@earthlink.net> + * dwconf.c: Fix an off-by-one condition where + we could index off the end of the cf_regs array in printing + a register name. +2008-04-12 David Anderson <davea42@earthlink.net> + * print_reloc.c: Verify stringtab exists and is + large enough before indexing into it to get a string + in printing relocations. + (Providing default name "<no name>" so it's evident from + the output that we used a default name string). +2008-04-09 David Anderson <davea42@earthlink.net> + * print_sections.c (get_fde_proc_name): Initialize some + local variables at declaration. The function is very slow + and needs a replacement. + * print_die.c: Fixes a typo in a comment. + * dwarfdump.c: Added -n option to suppress function name search + when printing FDEs. Current dwarfdump is n-squared at least + getting those names, this is a bandage-type-workaround when + there are so many FDEs the slowness is painful. + * globals.h: Support for -n option. + * print_frames.c: Support for -n option. +2008-04-08 David Anderson <davea42@earthlink.net> + * dwarfdump.c: Added -H option for testing + (it limits the run length). + And the support for -H in printing DIEs. + * globals.h: Added extern for -H option declaration. + * print_sections.c: Added -H option support to limit frames printing. + +2008-04-04 David Anderson <davea42@earthlink.net> + * print_die.c (tag_tree_combination, tag_attr_combination): + Ensure we do not index off the end of the -k checking arrays. + * print_sections.c: Increase the size of a local variable,. +2008-03-03 David Anderson <davea42@earthlink.net> + * dwarfdump.1: Add description of -ka option. + * print_frames.h print_sections.c testesb.c print_die.c print_reloc.c + dwarfdump.c tag_tree.c tag_attr.c esb.c esb.h makename.c dwconf.c + makename.h dwconf.h globals.h print_frames.c: Change tabs + to spaces with expand(1). +2008-03-03 David Anderson <davea42@earthlink.net> + * print_die.c: Now check that DW_AT_decl_file + and DW_AT_call_file indexes are valid and count instances of the + attribute and errors found in it. + * dwarfdump.c: With -ka and -ky now check that DW_AT_decl_file + and DW_AT_call_file indexes are valid and warn if bad. + Thanks to Carlos Alberto Enciso for the suggestion. + * globals.h: Declare new fields for the DW_AT_decl_file + DW_AT_call_file checks. +2008-02-26 David Anderson <davea42@earthlink.net> + * print_die.c (get_attr_value): Print DW_AT_call_file, + DW_AT_call_line, DW_AT_call_column nicely. diff --git a/dwarfdump/ChangeLog2009 b/dwarfdump/ChangeLog2009 new file mode 100644 index 0000000..9d9a2d5 --- /dev/null +++ b/dwarfdump/ChangeLog2009 @@ -0,0 +1,280 @@ +2009-12-30 DavidAnderson <davea42@earthlink.net> + * configure: Regenerated with autoconf 2.64. + * config.guess, config.sub: Delete these, best not + to have them. +2009-11-24 DavidAnderson <davea42@earthlink.net> + * tag_common.h: Updated 'standard tag table row' and + tag table column maximums now the DWARF4 entries are + in the .list files. Removed dos 'CR' characters at line ends. + * tag_tree.list, tag_attr.list: Added various + DWARF4 entries and added DW_TAG_enumeration_type + under DW_TAG_union_type. +2009-11-17 DavidAnderson <davea42@earthlink.net> + * dwarfdump.1: Document the -u option more fully. + * print_die.c: Check for both info_flag and + cu_name_flag to decide when to print DIEs. +2009-10-12 DavidAnderson <davea42@earthlink.net> + * dwarfdump.c: Updated dwarfdump version string to today. +2009-09-30 DavidAnderson <davea42@earthlink.net> + * dwarfdump.c: Added globals for aranges checking and + to print the resulting error count. + * print_aranges.c: Added checking that all 3 ways + of computing a cu_die_offset from an arange get + the same offset (checked with -r -ka). + * print_frames.c: DW_CFA_cfa_offset_extended_sf + corrected to DW_CFA_offset_extended_sf. +2009-09-01 DavidAnderson <davea42@earthlink.net> + * tag_tree.list: We add + DW_TAG_class_type as a valid child of a DW_TAG_union_type. +2009-08-05 DavidAnderson <davea42@earthlink.net> + * gennames.c: Change include from getopt.h to unistd.h + so the code is more universally compilable. +2009-07-24: David Anderson <davea42@earthlink.net> + * tag_attr.c: Remove duplicate include of naming.h. +2009-06-23: David Anderson <davea42@earthlink.net> + * strstrnocase.c: Corrected typo in TEST code and + added a new test. +2009-06-22: David Anderson <davea42@earthlink.net> + * Makefile.in: switched to personally written + string comparison, strstrnocase.c. + * stristr.c: deleted. + * strstrnocase.c: New code, written by me so no + license issues. + * print_die.c: Call is_strstrnocase(), the new function. + * dwarfdump.1: More fully document -S. + * globals.h: Create extern for is_strstrnocase(). +2009-06-18: David Anderson <davea42@earthlink.net> + * configure: Regenerated. + * Makefile.in: Add stristr.o + * stristr.c: public domain source added to dwarfdump + * print_die.c: Add code and arguments to support -S. + * print_lines.c: print_one_die argument list changed, added + the require argument.. + * dwarfdump.c: Added the -S option. + + * configure.in: Add test to set HAVE_REGEX for the -S option. + * dwarfdump.1: Document the -S options. + * config.h.in: Set the default HAVE_REGEX + * globals.h: Add -S globals, change the print_one_die() + prototype to support -S. + * print_aranges.c: Alter the print_one_die calls added + to support -S. +2009-06-06: David Anderson <davea42@earthlink.net> + * naming.c,naming.h: New files that implement the + ellipsis functionality of dwarfdump and defer to + libdwarf to get the names of the TAGs, attributes, FORMs, etc. + * gennames.c: This file has moved to libdwarf, no longer + present in dwarfdump. + * esb.h, esb.c: Change certain char* arguments to const char* + to avoid compiler warnings. + * print_static_vars.c,print_static_funcs.c, + print_sections.c,print_strings.c, print_locs.c, + print_lines.c, print_pubnames.c,print_ranges.c, + print_macros.c,print_types.c,tag_common.c, + print_weaknames.c, print_aranges.c: Include + changed from dwarf_names.h to naming.h + * tag_common.h: Removed the tag_name array, libdwarf + provides the TAG, ATTR, etc name strings now. + * dwarfdump.c: Updated DWARFDUMP_VERSION string. + * tag_tree.c,tag_attr.c: Include changed from dwarf_names.h to + naming.h. simplified long complicated lines, remove dbg argument + to get_TAG_name. + * print_die.c,print_abbrevs.c: Include changed from dwarf_names.h + to naming.h. + Calls to get_TAG_name (etc) no longer have a dbg argument. + * Makefile.in: We no longer build generated file names.c, + we build naming.c (hand coded, not generated). +2009-05-07: David Anderson <davea42@earthlink.net> + * dwarfdump.cc: updated DWARF_VERSION string. + * Makefile.in: dwarf_names* are now generated by C, + so 'clean' now cleans them out. +2009-05-04: David Anderson <davea42@earthlink.net> + * common.h, common.c: Extracted simple utility routines + into their own files. + * dwarf_names.awk, at_list.awk: deleted. gennames.c replaces these. + * tag_common.c, tag_common.h: Removed the simple utility + routines from these files to simplify dependencies. + * tag_attr.c, tag_tree.c: Include new common.h. + * print_frames.c: Adding address_size argument to call. + * print_frames.h: Adding new address_size argument to + get_string_from_locs() declaration. + * print_locs.c: Gets and uses CU-specific address_size. + * print_ranges.c: Adding commentary. + * print_die.c: adding DIE argument to ensure correct + address size used for the CU in question. + * Makefile.in: Now handles common.* and gennames.c changes. + * gennames.c: New code emitting string 'get name' source. + Replaces awk source. +2009-04-04: David Anderson <davea42@earthlink.net> + * Makefile.in: clean up 'clean' and 'distclean' + so that distributed files are not cleaned out by 'clean' + and all generated files (even those shipped in + distribution) are cleaned out by distclean. + * dwarfdump.c: Now calls the new + libdwarf function dwarf_set_frame_cfa_value() and other + such functions to specify all the values libdwarf needs. + * dwarfdump.conf: Sets the cfa_reg: value to + a new higher value (1436) to avoid conflict with largest + known register count. + * dwconf.h: Corrected commentary on DW_FRAME_CFA_COL3. + * dwconf.c: Now uses DW_FRAME_CFA_COL3 as default for + interface 3, rather than a directly typed number. + Sets undefined-value and same-value pseudo-register numbers. +2009-04-03: David Anderson <davea42@earthlink.net> + * dwarfdump.1: Amplified -R and -x abi= documentation. + * dwarfdump.conf: Added generic500 generic100 abis. +2009-03-29: David Anderson <davea42@earthlink.net> + * print_die.c: Moved print_infos() to here. + * dwarfdump.c: Moved print_infos() out of here. + * globals.h: Declarations changed to allow moving + print_infos(). + * dwarf_names.awk: Eliminate a pointless space before + a newline in the generated code. + * print_locs.c: Add -v section offset output to loclist printing + of the debug_loc section so the entries can be matched to + loclist printing initiated from .debug_info. +2009-03-24: David Anderson <davea42@earthlink.net> + * README: Would be nice if all could use dwarfdump2, + not this C dwarfdump. + * dwconf.c: Initialize new frame regs configure data and + parse it in the .conf file. Fixed old formatting mistakes. + * dwconf.h: Add new fields to frame regs configure struct. Make -R + be 1200 regs so that -R covers all the currently popular ABIs. + * print_die.c, print_lines.c, print_frames.c: Change %# to + 0x% so that zero prints with leading 0x consistently. + * dwarfdump.c: -R is now 1200 registers. So config function + changed and usage message needed update. + * dwarfdump.1: Change -R to 1200 and document -C. + * dwarfdump.conf: Add same_val_reg: and undefined_val_reg: + initial values where needed or interesting. + * print_macros.c: Fix old formatting mistake. +2009-03-23: David Anderson <davea42@earthlink.net> + * print_sections.h: New file for print_*.c + sources. + * dwarfdump.1: Added -C documentation. + * Makefile.in: updated 'mandir' so it works with + current configure (so now make install properly installs + the man page). + * print_sections.c: Moved get_fde_proc_name() and related + code to print_frames.c, where it is referenced. + * dwarfdump.c: No longer turn on info_flag with -f or -F. + Moved the Usage strings into a string table and loop through + to print them. + * globals.h: Removed get_fde_proc_name() declaration. + * print_frames.c: Added get_fde_proc_name() here + and removed the 'inlined:' from the abstract origin + name. +2009-03-20: David Anderson <davea42@earthlink.net> + * print_static_vars.c, print_static_funcs.c, print_strings.c, + print_locs.c, print_pubnames.c, print_lines.c, print_ranges.c, + print_abbrevs.c, print_macros.c, print_types.c, print_weaknames.c, + print_aranges.c: Moved the print_* functions from print_sections.c + into individual sourcefiles. + * Makefile.in: Now lists the new sourcefiles. + * print_sections.c: Deleted code moved to individual sourcefiles. + Added code to try to find the name from a DW_AT_abstract_origin + DIE when a subprogram DIE itself has no DW_AT_name; + * dwarfdump.c: Remove unused local variables. Use DWARFDUMP_VERSION + #define to set version string. + * tag_tree.c: Fix && || problem with parentheses. + * tag_attr.c: Fix && || problem with parentheses. + * print_frames.c: Moved the 'print_frames' function itself from + print_sections.c to here. +2009-03-17: David Anderson <davea42@earthlink.net> + * globals.h: Created predicate function + should_skip_this_cu() predicate function. Eliminating + code duplication. + * print_frames.c: Fix a hex value output to have a leading + 0x as all hex values should (when printed). + * print_sections.c: Call should_skip_this_cu(), which + replaces duplicate code. + Fix the arange print: now the hex value has a leading 0x + as all hex values should. get_proc_name() had local + variable funcnamefound initialized incorrectly, now is + set to 0 as it should be. get_nested_proc_name() + now initializes string buffers. get_fde_proc_name() + now initializes its string buffer. Surprisingly + things worked adequately before in spite of the errors. + * dwarfdump.c: Call should_skip_this_cu(). Implementation + of that new function is in this source file. +2009-03-16: David Anderson <davea42@earthlink.net> + * print_frames.c:DW_CFA_restore output had a spurious newline. + Removed 2 pointless blank lines an initialized 2 local variables. + * print_sections.c: Removed a pointless redeclaration of a function + in libdwarf.h. check_info_offset_sanity() was missing a + return statement in one place, which could lead to spurious + extra (and silly) error text. +2009-03-09: David Anderson <davea42@earthlink.net> + * print_die.c: Make a comment easier to understand. +2009-02-28: David Anderson <davea42@earthlink.net> + * Makefile.in: add tmp-*.tmp to the 'clean' rule. +2009-02-17: David Anderson <davea42@earthlink.net> + * print_sections.c,print_die.c,tag_common.c,print_frames.c: C99 + in-line declarations and // comments are not intended here, + this removes a few that were introduced accidentally. +2009-02-16: David Anderson <davea42@earthlink.net> + * Makefile.in: Removed some use of awk and + simplified some shell scripting here. + renamed temp files, no longer named with + underbars, they uniformly start with 'tmp-'. + * print_sections.c: Added the new argument required + by the updated dwarf_names.c functions argument lists. + * tag_tree_ext.list: List 'common extensions' + of tag->tag relationships. + * tag_attr_ext.list: List 'common extensions' + of tag->attr relationships. + * print_die.c: New 'common extension' tables used + for checking tag->tag and tag->attr relationships + unless turned off with -C. + * dwarf_names.awk: Removed tabs so generated names.c not so + spread out. Added argument to the generated functions so + tag_tree.c, tag_attr.c can use these generated functions nicely. + * dwarfdump.c: Adding -C option, which exposes + some 'common extensions' of dwarf uses as DWARF CHECK + (-ka) warnings. By default these extensions not reported + as warnings. + * tag_tree.c: Now generates base and extensions tables. + Code in common with tag_attr.c is in tag_common* files. + * tag_attr.c: Now generates base and extensions tables. + Code in common with tag_tree.c is in tag_common* files. + * tag_common.c, tag_common.h: New files with the common + data extracted from tag_tree.c and tag_attr.c + * globals.h: global flag added for -C. + +2009-02-14: David Anderson <davea42@earthlink.net> + * configure.in: Define --enable-nonstandardprintf + * config.h.in: new #undef HAVE_NONSTANDARD_PRINTF_64_FORMAT + * configure: Regenerated. + * config.guess, config.sub: Latest version from GNU. + * Makefile.in: Referenced configure variable to avoid + irritating message at configure time. + * README: document --enable-nonstandardprintf + * print_sections.c, print_die.c, print_reloc.c, dwarfdump.c, + dwconf.c, print_frames.c: Use libdwarf.h DW_PR_ printf macros + for for better portability. +2009-02-13: David Anderson <davea42@earthlink.net> + * print_sections.c: Ensure we are checking line table header + correctness whichever line-table-print code is being used. + Allow ARM line header table (which has a bug) to be used. + * dwarfdump.c: Print lines_result total with checking on. + * globals.h: Add lines_result global to count line botches. +2009-02-11: David Anderson <davea42@earthlink.net> + * print_sections.c, print_die.c: DWARF_CHECK_ERROR* + macros now get the count struct passed in. + * tag_tree.c, tag_attr.c: Add a comment in the output + identifying the output as generated code and + with the generation date/time inserted. + * globals.h: Accept the struct in DWARF_CHECK_ERROR* + macros so we can update the error count in the macro. +2009-01-31: David Anderson <davea42@earthlink.net> + * Makefile.in: Remove compilation of _tag_attr_table.c + and _tag_tree_table.c as those are #included in + print_die.c, not separately compiled. + * print_frames.c: A formerly-static function now called + from another file, so declare it here. + * print_sections.c: Improve the printing of the .debug_loc + section. + * print_die.c: A couple of errors were missing their error + count increment. + * tag_attr.list tag_tree.list: Some normal relationships + were left out of the tables: fixed now. diff --git a/dwarfdump/ChangeLog2010 b/dwarfdump/ChangeLog2010 new file mode 100644 index 0000000..e281cae --- /dev/null +++ b/dwarfdump/ChangeLog2010 @@ -0,0 +1,105 @@ +2010-09-30 DavidAnderson <davea42@earthlink.net> + * dwarfdump.c: Now -a no longer implies -c because + the -c option is not guaranteed to work by the DWARF spec, + nor is -c really necessary. + * README: More tweaks on the 'install' issue. +2010-09-29 DavidAnderson <davea42@earthlink.net> + * README, Makefile.in: Amplified make install instructions. +2010-09-20 DavidAnderson <da + * dwarfdump.1: The -c option is not guaranteed to work. + Because .debug_loc can have garbage bytes in areas + not referenced by .debug_info. +2010-06-29 DavidAnderson <davea42@earthlink.net> + * print_die.c: If a location form is wrong report + an error but continue operating. + * dwarfdump.c: Implement print_error_and_continue(). + Fix mistakes in usage message. + * globals.h: Declare print_error_and_continue(). +2010-04-04 DavidAnderson + * dwarfdump.c: New version date. + * configure: regenerated. + * addrmap.c: Added a comment to mention that tdestroy is + GNU only, POSIX does not mention a way to delete the + tsearch tree. Hence the code does #define USE_GNU 1 + to expose the tdestroy function prototype. +2010-04-03 DavidAnderson <davea42@earthlink.net> + * print_frames.h: Added new arguments to a function to get better + function names printing. + * configure.in: Added test for tsearch functions so dwarfdump + will still compile if they are not present. + See HAVE_TSEARCH macro. + * configure: regenerated. + * Makefile.in: Now names object for addrmap.c + * addrmap.c: New file to map pc address to function names + so fde printing gets functions named properly (using tsearch). + * addrmap.h: New file to map pc address to function names + so fde printing gets functions named properly (using tsearch). + * print_lines.c: Correct the calculation of the number + of error checks. + * dwarfdump.c: Added fdes error check print. + * config.h.in: Now handles the HAVE_TSEARCH macro. + * globals.h: Added declarations for the fde error check + globals. + * print_frames.c: Now uses addrmap.h functions to do a + better job of printing function names in the frame output. +2010-03-31 DavidAnderson <davea42@earthlink.net> + * dwarfdump.1: Added some text about 'harmless' + errors. + * dwarfdump.c: Change the size of the harmless error list + to 50. Change harmless error reporting to be associated + with -k flags. + * dwconf.c: Initialize uninitialized fields to satisfy + a compiler warning. + * globals.h: Declarations added for 'harmless' error + reporting. + * print_die.c: Added commentary. + * print_frames.cc: Change harmless error reporting to be + associated with -k flags. + * print_aranges.c: Now calls dwarf_get_arange_info_b() + allowing proper printing of DWARF4 segment-sensitive + aranges. Change harmless error reporting to be + associated with -k flags. +2010-03-28 DavidAnderson <davea42@earthlink.net> + * dwarf_globals.h: Added interface to print_any_harmless_errors(). + * dwarfdump.c: Added print_any_harmless_errors() implementation + and we call it just before closing libdwarf. + * print_frames.c: Call print_any_harmless_errors after + getting cie/fde list. + * dwarfdump.conf: Add abi named 'arm' for Arm users. + * print_die.c: Initialize a local string pointer to NULL at + the point of definition. +2010-02-14 DavidAnderson <davea42@earthlink.net> + * print_die.c: Add newer DW_OP operators, remove + bogus test of DW_OP_nop as the highest valid operator. + Add table of DW_OPs to simplify testing for zero-operand + operators. + Revise so that the FORM of all attributes print with -M. + Move a local variable declaration to the front of a block + to match C 1990 rules. + String searches now also match on attribute name. + * tag_attr.list: Updated copyright. + * dwarfdump.c: Remove a switch FALL THROUGH in the 'g' case. + * tag_tree_ext.list, tag_attr_ext.list: Added GNU template + parameter tags, attributes. Updated copyright. + * tag_tree.list: Added template parameter tags. Added + entry for nested classes. Updated copyright. + * tag_common.h: Increased STD_TAG_TABLE_COLUMNS and + EXT_ATTR_TABLE_COLS. +2010-01-30 DavidAnderson <davea42@earthlink.net> + * print_die.c: Changed the spelling of one + 'DW_AT_type offset does not point to type info' error message so + one can distinguish which check lead to the message. +2010-01-26 DavidAnderson <davea42@earthlink.net> + * dwarfdump.1, dwconf.c, dwconf.h, dwarfdump.conf: The default + frame values in frame + output are now generic registers like r0 to r99 + instead of MIPS register names. + For the MIPS register names use '-x abi=mips'. + * print_frames.c: Added commentary. +2010-01-17 DavidAnderson <davea42@earthlink.net> + * print_die.c: The special case DW_AT_SUN_func_offsets + now prints identically in dwarfdump and dwarfdump2. +2010-01-03 DavidAnderson <davea42@earthlink.net> + * tag_common.c, common.h, common.c: Remove <cr> line + terminator characters. Update copyright year. + * All other files: Update copyright year. diff --git a/dwarfdump/DWARFDUMPCOPYRIGHT b/dwarfdump/DWARFDUMPCOPYRIGHT new file mode 100644 index 0000000..cf465e2 --- /dev/null +++ b/dwarfdump/DWARFDUMPCOPYRIGHT @@ -0,0 +1,85 @@ + +========The dwarfdump copyright======= + +The full text of the GPL version 2 is provided in the file GPL.txt. + +Nearly all the files in this directory have contained a GPL +copyright, not an LGPL copyright, for years. The following +is an example of that copyright as used in the dwarfdump +source, and is what SGI always intended (in David +Anderson's opinion) to have present in +the DWARFDUMPCOPYRIGHT file. (tag_tree.list tag_attr.list +acconfig.h have long been marked LGPL and therefore the LGPL +copyright, not GPL, applies to those three files.) This GPL +copyright text added here to DWARFDUMPCOPYRIGHT Dec 4, 2006 + + Copyright (C) 2000,2002,2004,2005 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + +The following was the entire content of this file before +December 24 2006, Being the LGPL text this is in conflict +with the individual source files and I (David Anderson) +believe the source file copyright was intended for dwarfdump +not the LGPL source directly following this note. However the +3 files tag_tree.list tag_attr.list acconfig.h have long been +marked LGPL and the following copyright applies to those three. + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + diff --git a/dwarfdump/GPL.txt b/dwarfdump/GPL.txt new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/dwarfdump/GPL.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/dwarfdump/Makefile.in b/dwarfdump/Makefile.in new file mode 100644 index 0000000..19278f3 --- /dev/null +++ b/dwarfdump/Makefile.in @@ -0,0 +1,191 @@ +# +# Makefile for dwarfdump +# This is made very simple so it should work with +# any 'make'. +# The Makefile does assume that libdwarf is at ../libdwarf +# from the dwarfdump2 source directory. +# + +srcdir = @srcdir@ +VPATH = @srcdir@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = $(exec_prefix)/bin +libdir = $(exec_prefix)/lib +mandir = $(exec_prefix)/share/man +man1dir = $(mandir)/man1 + + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +DATAROOT = @datarootdir@ +SHELL = /bin/sh +CC = @CC@ +AR = @AR@ +ARFLAGS = @ARFLAGS@ +RM = rm +RANLIB = @RANLIB@ +DEFS = @DEFS@ +# ../libdwarf gets us to local headers and a libdwarf +# archive, usually, so we assume it. +DIRINC = $(srcdir)/../libdwarf +LIBS = @LIBS@ -L../libdwarf -ldwarf -lelf +INCLUDES = -I. -I$(srcdir) -I$(srcdir)/../libdwarf +CFLAGS = $(PREINCS) @CFLAGS@ $(INCLUDES) -DCONFPREFIX=${libdir} $(POSTINCS) +LDFLAGS = $(PRELIBS) @LDFLAGS@ $(LIBS) $(POSTLIBS) + + +INSTALL = cp + +binprefix = + +FINALOBJECTS = \ + addrmap.o \ + checkutil.o \ + dwarfdump.o \ + dwconf.o \ + esb.o \ + print_abbrevs.o \ + print_aranges.o \ + print_die.o \ + print_frames.o \ + print_lines.o \ + print_locs.o \ + print_macros.o \ + print_pubnames.o \ + print_ranges.o \ + print_reloc.o \ + print_sections.o \ + print_static_funcs.o \ + print_static_vars.o \ + print_strings.o \ + print_types.o \ + print_weaknames.o \ + strstrnocase.o \ + uri.o +GEN_HFILES = common.o \ + tmp-tt-table.c \ + tmp-ta-table.c \ + tmp-ta-ext-table.c \ + tmp-tt-ext-table.c + +all: dwarfdump + +HEADERS = $(srcdir)/checkutil.h \ + $(srcdir)/common.h \ + $(srcdir)/dwconf.h \ + $(srcdir)/esb.h \ + $(srcdir)/globals.h \ + $(srcdir)/makename.h \ + $(srcdir)/print_frames.h \ + $(srcdir)/uri.h + +$(FINALOBJECTS): $(GEN_HFILES) $(HEADERS) $(srcdir)/naming.c + +default: $(TARGETS) + +dwarfdump: $(FINALOBJECTS) makename.o naming.o common.o + $(CC) $(CFLAGS) -o $@ $(FINALOBJECTS) common.o makename.o naming.o $(LDFLAGS) + +#tag_common.o: $(srcdir)/tag_common.c $(HEADERS) dwarf_names.h +# $(CC) $(CFLAGS) -c $(srcdir)/tag_common.c +makename.o: $(srcdir)/makename.h $(srcdir)/makename.c + $(CC) $(CFLAGS) -c $(srcdir)/makename.c +common.o: $(srcdir)/common.c $(srcdir)/common.h + $(CC) $(CFLAGS) -c $(srcdir)/common.c +gennames: $(srcdir)/gennames.c $(DIRINC)/dwarf.h $(HEADERS) common.o + $(CC) $(CFLAGS) $(srcdir)/gennames.c common.o $(LDFLAGS) -o gennames +naming.o: $(srcdir)/naming.c $(srcdir)/naming.h + $(CC) $(CFLAGS) -c $(srcdir)/naming.c + +# We need this as naming.o has external references we cannot have +# in the tree builds. +trivial_naming.o: $(srcdir)/naming.c + $(CC) $(CFLAGS) -DTRIVIAL_NAMING -c $(srcdir)/naming.c -o trivial_naming.o + +tag_tree_build: $(srcdir)/tag_tree.c $(DIRINC)/dwarf.h $(HEADERS) tag_common.o makename.o common.o trivial_naming.o + $(CC) $(CFLAGS) $(srcdir)/tag_tree.c tag_common.o common.o makename.o trivial_naming.o $(LDFLAGS) -o tag_tree_build + +tag_attr_build: $(srcdir)/tag_attr.c $(DIRINC)/dwarf.h $(HEADERS) tag_common.o makename.o common.o trivial_naming.o + $(CC) $(CFLAGS) $(srcdir)/tag_attr.c tag_common.o common.o makename.o trivial_naming.o $(LDFLAGS) -o tag_attr_build + +tmp-tt-table.c tmp-tt-ext-table.c: $(srcdir)/tag_tree_ext.list $(srcdir)/tag_tree.list tag_tree_build + # gcc -E tag_tree.list does not work, so use a .c name + -rm -f tmp-t1.c + cp $(srcdir)/tag_tree.list tmp-t1.c + $(CC) $(CFLAGS) -E tmp-t1.c > ./tmp-tag-tree-build1.tmp + ./tag_tree_build -s -i tmp-tag-tree-build1.tmp -o tmp-tt-table.c + -rm -f tmp-t4.c + cp $(srcdir)/tag_tree_ext.list tmp-t4.c + $(CC) $(CFLAGS) -E tmp-t4.c > ./tmp-tag-tree-build4.tmp + ./tag_tree_build -e -i tmp-tag-tree-build4.tmp -o tmp-tt-ext-table.c + +tmp-ta-table.c tmp-ta-ext-table.c: $(srcdir)/tag_attr_ext.list $(srcdir)/tag_attr.list tag_attr_build + # gcc -E tag_attr.list does not work, so use a .c name + -rm -f tmp-t2.c + cp $(srcdir)/tag_attr.list tmp-t2.c + $(CC) $(CFLAGS) -E tmp-t2.c > ./tmp-tag-attr-build2.tmp + ./tag_attr_build -s -i tmp-tag-attr-build2.tmp -o tmp-ta-table.c + -rm -f tmp-t3.c + cp $(srcdir)/tag_attr_ext.list tmp-t3.c + $(CC) $(CFLAGS) -E tmp-t3.c > ./tmp-tag-attr-build3.tmp + ./tag_attr_build -e -i tmp-tag-attr-build3.tmp -o tmp-ta-ext-table.c + + +# The file dwarf_names.awk generates BOTH dwarf_names.h and dwarf_names.c +# be careful of the make dependencies here +dwarf_names.h: gennames $(DIRINC)/dwarf.h + rm -f dwarf_names.h dwarf_names.c + ./gennames -s -i ../libdwarf -o . +dwarf_names.c: dwarf_names.h + +test: esb.o $(srcdir)/testesb.c + $(CC) -o test $(srcdir)/testesb.c esb.o + ./test + -rm -f ./test + + +# This simply assumes that a default INSTALL (cp) command +# will work and leave sensible permissions on the resulting files. +# Some adjustment might be required, see README. +install: all + $(INSTALL) dwarfdump $(bindir)/dwarfdump + $(INSTALL) $(srcdir)/dwarfdump.conf $(libdir)/dwarfdump.conf + $(INSTALL) $(srcdir)/dwarfdump.1 $(man1dir)/dwarfdump.1 + +uninstall: + -rm -f $(bindir)/dwarfdump + -rm -f $(man1dir)/dwarfdump.1 + -rm -f $(libdir)/dwarfdump.conf + +clean: + rm -f *.o dwarfdump + rm -f _tag_attr_table.c + rm -f _tag_attr_ext_table.c + rm -f _tag_tree_table.c + rm -f _tag_tree_ext_table.c + -rm -f tag_attr_build*.tmp + -rm -f tag_tree_build*.tmp + rm -f tag_tree_build + rm -f tag_attr_build + -rm -f _*.c _*.h + -rm -f tmp-*.c tmp-*.h tmp-*.tmp + rm -f gennames + rm -f dwarf_names_new.c + rm -f dwarf_names_new.h + rm -f dwarf_names_enum.h + rm -f dwarf_names.h + rm -f dwarf_names.c + + +distclean: clean + rm -f config.log config.h config.cache config.status + rm -rf autom4te.cache + rm -rf Makefile + +shar: + @echo "shar not set up yet" +dist: + @echo "dist not set up yet" diff --git a/dwarfdump/NEWS b/dwarfdump/NEWS new file mode 100644 index 0000000..ed4428b --- /dev/null +++ b/dwarfdump/NEWS @@ -0,0 +1,206 @@ +December 13, 2011 + Now prints missing line table column number as 0 (now + matching the DWARF spec), the previous + practice of printing -1 was always wrong. + And prints the DWARF3/4 new line table fields (when present). +October 29, 2011 + Added support for printing .debug_types (type unit) data. +October 26, 2011 + Added new features to Makefile.in and documented in README + how to build dwarfdump with headers or libraries in + non-standard places. +October 23, 2011 + By default the various places with string option values + and file paths all use URI transformation on input and + if the transformation does anything at all dwarfdump reports + the input and transformed strings. This makes it easy + to deal with strings and expressions and file paths + that are difficult to express in a shell (or that getopt + mangles). Options -q and -U give you control over this process. +October 07, 2011 + The -x abi=mips frame register abi in dwarfdump.conf is now + usable with modern MIPS objects as well as old IRIX objects. + There are other mips-* frame register setups described + in dwarfdump.conf for anyone testing that nothing new has + been added that conflicts with old IRIX/MIPS frame generation. +June 04, 2011 + Error checking is now distinct from section printing, making + error checking (the -k options) much easier to work with on + large objects. + So compiler-created errors can be found, the error reporting + now prints context information. +March 29, 2011 + Added many new correctness tests. Changed the format of + various items (line data prints in a more compact form, numbers + are more uniformly hexadecimal fixed length where that makes sense). + All the source files are uniformly indented to a multiple of 4 + characters and all intent-tabs in the source have been removed. + Major logic changes involved changing error-reporting to be + more detailed and adding new tests for incorrect DWARF. + Now reports error summary by the compiler name, not just overall. +January 26, 2010 + Changed the default frame-data register names from MIPS to + a generic set of registers. + Try '-x abi=mips' to get the traditional old MIPS register + naming. +June 22, 2009 + Added the -S option to dwarfdump. +June 10, 2009 + Moved the gennames.c code to libdwarf. +May 4, 2009 + Replaced awk source-generation of certain functions + with new gennames.c code. + Now we can print an object with an address_size that + varies by compilation unit. +April 4, 2009 + Corrected aspects of the frame-printing by ensuring we pass + all the information libdwarf needs for fully consistent behavior. + Three newly defined libdwarf calls calls made to ensure + that better behavior (specifically having dwarfdump consistently + recognize when registers are the cfa, undefined-value or same-value + pseudo registers). Updated dwarfdump.conf to set these same + things consistently. +Mar 22, 2009 + The -f and -F flags no longer also imply -i (it just + did not make sense to tie them (cannot recall why + it might have been tied before). +Mar 20, 2009 + Moved print_* functions from print_sections.c to individual + source files. Hopefully making the code a bit easier + to read. +Feb 16, 2009 + Added the -C option. It is a sort of 'pedantic' option + as it turns on warnings about certain commonly used + non-standard tag->tag and tag->attr relationships. + Added the tag_attr_ext.list tag_tree_ext.list files which + define the 'common use' extensions. +Feb 14, 2009 + Added configure option --enable-nonstandardprintf + which makes it easy to get printf of Dwarf_Unsigned (etc) + types correct even for non-standard compilers. +December 30, 2008 + Now we print the .debug_ranges section (with -N) + and the data for DW_AT_ranges (with -i). +December 8, 2008 + The -M option now causes printing of FORM details. + And -v adds details about abbreviation 'indexes' into + an abbreviation table (.debug_abbrev) + providing more detail for folks debugging or + improving their understanding of DWARF data. +April 9, 2008 + Added -H <num> to limit the number of compilation-units/FDEs + dwarfdump prints in one run. Added -n to eliminate function-name + printing in .debug_frame output (with a large-enough debug_info + section function-name printing is too slow). The function name + printing will be fixed in another release. +December 8, 2007 + Had to add an ugly configure conditional as libelf has + unconditional use of off64_t in recent libelf.h +July 3, 2007 + Now with -v dwarf expression blocks in frame operations + are printed expanded out. +July 2, 2007 + Added a new abi -x abi=general usable for any cpu with + up to 1000 registers. +May 7, 2007 + Sun Microsystems contributes new dwarf.h extensions and a new -G option + to dwarfdump -i (so one can see the 'global' offset to DIEs). + Thanks to Chris Quenelle of Sun. +April 17, 2006 + New -x name=<conf file> -x abi=<abiname> and configuration file + enable sensible printing of a wide range of .debug_frame eh_frame + correctly without recompiling dwarfdump or touching libdwarf.h or + dwarf.h. +March 29, 2005 + Now handles DWARF3. For non-MIPS objects, the list of register + names in print_sections.c is not appropriate, #define + DWARFDUMP_TURN_OFF_MIPS_REG_NAMES to turn off the MIPS names. +December 1, 2005 + Added new DWARF3 TAGs and ATtributes to the -k lists, + clarified the -k reporting, and made the build more robust + in the face of errors in the *.list relationship-spec-files. + +August 1, 2005 + Now print_die.c deals with long loclists without a coredump. + Added esb.h esb.c (and testesb.c for testing) to encapsulate + getting space for possibly-long strings. + Now print_die.c uses snprintf() not sprintf (hopefully this + will not inconvenience anyone, snprintf() has been available + on most systems for years now). + Altered print of location lists a little bit - for better appearance. + +July 15, 2005 + Now completely frees all allocated memory. Various + routines were not calling dealloc() code and + new libdwarf dealloc routines are now used where those + are needed. + + Now prints DWARF3 .debug_pubtypes section (with -a or -y). + The .debug_pubtypes section and SGI-specific .debug_typenames + are equvalent so they are treated alike. + +Mar 21, 2005 + The -f flag now prints only .debug_frame data. The .eh_frame section + (GNU exceptions data) now prints with -F (not -a). + Printing gcc 3.3 or 3.4 .eh_frame with zR augmentation + does not work at this time, so do not use -F + to print such an object. + The line section print now prints a CU-DIE offset for each such DIEs + line information. This makes it much easier to correctly associate + -l (or -v -l) output with -v -v -l when debugging a faulty + linetable in an executable. + With -v -v -l (two -v) the output of line info continues to be a + completely different format than zero or one -v, the two-v + form showing the detailed line table opcodes. + With g++ 3.3.3 one sees bad line addresses at times as the + DW_LNE_set_address address for header files do not always + get their relocations applied. I am told this is fixed in 3.4.x. + + +Mar 18, 2005 + In correcting printing of macro information the format + of the macro (-m) output has changed substantially. + Much more complete now. Still could use enhancement. + +Oct 28, 2004 + Updated contact address in copyright: SGI moved 1/4 mile + to a new address: 1500 Crittenden Lane. + +Oct 02, 2003 + Now fully supports .debug_loc section. + +June 14, 2001 + Now calling a new function dwarf_get_arange_cu_header_offset() + in libdwarf and printing the returned cu header offset for + aranges entries. Making it easier to track down internal + errors in the dwarf2 data. Also added small other + consistency checks, printing a message and exit()ing on + error. + +April 14, 2000 + The libdwarf copyright has changed to + version 2.1 of the GNU Lesser General Public License. + Anyone holding a version of libdwarf that was published + before this new copyright + is allowed to use + the copyright published in that earlier libdwarf source + on the earlier source + or to use + this new copyright on the earlier source, + at their option. + +July 21, 1999 + Added gnu extensions to the frame information printer + and handling for egcs eh_frame printing. + libdwarf changes mean this now can print little-endian + object dwarf on a big-endian system and vice-versa. + +December, 1998 + added dwarfdump to the dwarf public source distribution. + +June, 1994 + libdwarf consumer interface changed completely so updated to match. + +May, 1993 + Initial version of dwarfdump for dwarf version 2 + written at sgi. diff --git a/dwarfdump/README b/dwarfdump/README new file mode 100644 index 0000000..515e2b6 --- /dev/null +++ b/dwarfdump/README @@ -0,0 +1,82 @@ +I would prefer you try using ../dwarfdump2, not this source. +If you must use this for some reason, could you let me know why? +Thanks. + +To build dwarfdump, first build libdwarf in the neighboring +directory then type + ./configure + make + +Installation is a bit primitive. + sudo make install +may or may not work. +Some or all of the following might be required on Unix or Linux or MacOS: + sudo mkdir -p /usr/local/share/man/man1/ + sudo mkdir -p /usr/local/lib + sudo mkdir -p /usr/local/bin +Then retry the 'sudo make install' and (if necessary) try + sudo chmod a+x /usr/local/bin/dwarfdump + sudo chmod a+r /usr/local/share/man/man1/dwarfdump.1 + sudo chmod a+r /usr/local/lib/dwarfdump.conf +You don't really need the dwarfdump.1 man page, +but you might as well have it. If the man page is not visible +with 'man dwarfdump' try 'man manpath' for hints. + +If you don't need others using dwarfdump on your computer, +just + cp dwarfdump $HOME/bin/dwarfdump +(by convention many people put personal executables in $HOME/bin +and fix up $PATH to refer there) which suffices as 'installation'. +Also + cp dwarfdump.conf $HOME + +To use dwarf or libdwarf, you may want to install dwarf.h +and libdwarf.h somewhere convenient. +You can just copy those two headers to /usr/local/include by hand +(or anywhere, really, that you have permission to copy to) +(you may need to use -I/usr/local/include on compile lines +to reference them there, but see below on configure and make). + +Notice that dwarf_names.c and dwarf_names.h are supplied by +the release though the Makefile can and may rebuild them. +Some users find it difficult to get a reliable awk(1) program, +so for them these prebuilt versions may be useful. + +If your headers or libelf/libdwarf are not in the expected places, +use the make command line to add flags and include directories. +For example + ./configure + PREINCS="-I /usr/local/include" POSTINCS="-I /home/x/include" make +PREINCS content is inserted before CFLAGS as make(1) is running. +POSTINCS content is added after the CFLAGS value. + +To set LDFLAGS, +do so at configure time, for example: + ./configure LDFLAGS="-L /some/dir" +And/or use PRELIBS and/or POSTLIBS at 'make' time similar to the use +of PREINCS and POSTINCS. + +If the libdwarf directory +has both libdwarf.so and libdwarf.a, the libdwarf.so +will be picked up and + "./tag_tree_build: error while loading shared libraries: + libdwarf.so: cannot open shared object file: + No such file or directory" +will probably result. +Either: remove libdwarf.so and rebuild or set +the environment variable LD_LIBRARY_PATH to the directory +containing the .so or use LDFLAGS to set rpath (see just below). +It is perhaps simpler to ensure that the libdwarf directory +only has an archive, not a shared-library. +But sometimes one wants a shared library. +In that case +one can set ld's -rpath on the gcc command line like this: + LDFLAGS="-Wl,-rpath=/some/path/libdir" +so the shared library can be found at run time automatically. + +The same problem may arise with libelf, and the same approach +will solve the problem. + + + +David Anderson. davea42 at earthlink dot net. diff --git a/dwarfdump/addrmap.c b/dwarfdump/addrmap.c new file mode 100644 index 0000000..fb7ba79 --- /dev/null +++ b/dwarfdump/addrmap.c @@ -0,0 +1,149 @@ +/* + Copyright 2010-2011 David Anderson. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + +*/ + +/* If memory full we do not exit, we just keep going as if + all were well. */ + +#include "globals.h" +#include <stdio.h> +#include "addrmap.h" +#ifndef HAVE_TSEARCH +struct Addr_Map_Entry * addr_map_insert( Dwarf_Unsigned addr, + char *name,void **tree1) +{ return 0; } +struct Addr_Map_Entry * addr_map_find(Dwarf_Unsigned addr,void **tree1) +{ return 0; } +void addr_map_destroy(void *map) +{ return;} + + + +#else /* HAVE_TSEARCH */ +#define __USE_GNU 1 +#include <search.h> + +char firststringcontent[100]; +char *firststring = 0; +struct Addr_Map_Entry *firstaddr = 0; + +static struct Addr_Map_Entry * +addr_map_create_entry(Dwarf_Unsigned k,char *name) +{ + struct Addr_Map_Entry *mp = + (struct Addr_Map_Entry *)malloc(sizeof(struct Addr_Map_Entry)); + if(!mp) { + return 0; + } + mp->mp_key = k; + if(name) { + mp->mp_name = strdup(name); + } else { + mp->mp_name = 0; + } + return mp; +} +static void +addr_map_free_func(void *mx) +{ + struct Addr_Map_Entry *m = mx; + if(!m) { + return; + } + free(m->mp_name); + m->mp_name = 0; + free(m); + return; +} + +static void +DUMPFIRST(int line) +{ + if(!firststring) { + return; + } +} + +static int +addr_map_compare_func(const void *l, const void *r) +{ + const struct Addr_Map_Entry *ml = l; + const struct Addr_Map_Entry *mr = r; + if(ml->mp_key < mr->mp_key) { + return -1; + } + if(ml->mp_key > mr->mp_key) { + return 1; + } + return 0; +} +struct Addr_Map_Entry * +addr_map_insert( Dwarf_Unsigned addr,char *name,void **tree1) +{ + void *retval = 0; + struct Addr_Map_Entry *re = 0; + struct Addr_Map_Entry *e; + e = addr_map_create_entry(addr,name); + DUMPFIRST(__LINE__); + /* tsearch records e's contents unless e + is already present . We must not free it till + destroy time if it got added to tree1. */ + retval = tsearch(e,tree1, addr_map_compare_func); + if(retval) { + re = *(struct Addr_Map_Entry **)retval; + if ( re != e) { + /* We returned an existing record, e not needed. */ + addr_map_free_func(e); + } else { + /* Record e got added to tree1, do not free record e. */ + } + } + return re; +} +struct Addr_Map_Entry * +addr_map_find(Dwarf_Unsigned addr,void **tree1) +{ + void *retval = 0; + struct Addr_Map_Entry *re = 0; + struct Addr_Map_Entry *e = 0; + + e = addr_map_create_entry(addr,NULL); + DUMPFIRST(__LINE__); + retval = tfind(e,tree1, addr_map_compare_func); + if(retval) { + re = *(struct Addr_Map_Entry **)retval; + } + /* The one we created here must be deleted, it is dead. + We look at the returned one instead. */ + addr_map_free_func(e); + return re; +} + +void +addr_map_destroy(void *map) +{ + /* tdestroy is not part of Posix, it is a GNU libc function. */ + tdestroy(map,addr_map_free_func); +} + +#endif /* HAVE_TSEARCH */ diff --git a/dwarfdump/addrmap.h b/dwarfdump/addrmap.h new file mode 100644 index 0000000..a7b26df --- /dev/null +++ b/dwarfdump/addrmap.h @@ -0,0 +1,33 @@ +/* + Copyright 2010 David Anderson. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + +*/ + +struct Addr_Map_Entry { + Dwarf_Unsigned mp_key; + char * mp_name; +}; + +struct Addr_Map_Entry * addr_map_insert(Dwarf_Unsigned addr, + char *name, void **map); +struct Addr_Map_Entry * addr_map_find(Dwarf_Unsigned addr, void **map); +void addr_map_destroy(void *map); diff --git a/dwarfdump/checkutil.c b/dwarfdump/checkutil.c new file mode 100644 index 0000000..6ba756c --- /dev/null +++ b/dwarfdump/checkutil.c @@ -0,0 +1,565 @@ +/* + Copyright (C) 2011 SN Systems Ltd. All Rights Reserved. + Portions Copyright (C) 2011 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + +*/ +/* + + These simple list-processing functions are in support + of checking DWARF for compiler-errors of various sorts. + + +*/ + +#include "globals.h" +#include <assert.h> + +/* Private function */ +static void DumpFullBucketGroup(Bucket_Group *pBucketGroup); +static int FindDataIndexInBucket(Bucket_Group *pBucketGroup, + Bucket_Data *pBucketData); +static void PrintBucketData(Bucket_Group *pBucketGroup, + Bucket_Data *pBucketData); +static void ProcessBucketGroup(Bucket_Group *pBucketGroup, + void (*pFunction)(Bucket_Group *pBucketGroup,Bucket_Data *pBucketData)); + +Bucket_Group * +AllocateBucketGroup(int kind) +{ + Bucket_Group *pBucketGroup = (Bucket_Group *)calloc(1,sizeof(Bucket_Group)); + pBucketGroup->kind = kind; + return pBucketGroup; +} + +void +ReleaseBucketGroup(Bucket_Group *pBucketGroup) +{ + Bucket *pBucket = 0; + Bucket *pNext = 0; + + assert(pBucketGroup); + for (pBucket = pBucketGroup->pHead; pBucket; /*pBucket = pBucket->pNext*/) { + pNext = pBucket->pNext; + free(pBucket); + pBucket = pNext; + } + pBucketGroup->pHead = NULL; + pBucketGroup->pTail = NULL; + free(pBucketGroup); +} + +void +ResetBucketGroup(Bucket_Group *pBucketGroup) +{ + Bucket *pBucket = 0; + + assert(pBucketGroup); + for (pBucket = pBucketGroup->pHead; pBucket; pBucket = pBucket->pNext) { + pBucket->nEntries = 0; + } + ResetSentinelBucketGroup(pBucketGroup); +} + +/* Reset sentinels in a Bucket Group. */ +void +ResetSentinelBucketGroup(Bucket_Group *pBucketGroup) +{ + /* Sanity checks */ + assert(pBucketGroup); + pBucketGroup->pFirst = NULL; + pBucketGroup->pLast = NULL; +} + +void PrintBucketGroup(Bucket_Group *pBucketGroup,Dwarf_Bool bFull) +{ + assert(pBucketGroup); + if (bFull) { + DumpFullBucketGroup(pBucketGroup); + } else { + if (pBucketGroup->pFirst && pBucketGroup->pLast) { + printf("\nBegin Traversing, First = 0x%08" DW_PR_DUx + ", Last = 0x%08" DW_PR_DUx "\n", + pBucketGroup->pFirst->key,pBucketGroup->pLast->key); + ProcessBucketGroup(pBucketGroup,PrintBucketData); + } + } +} + +static void +PrintBucketData(Bucket_Group *pBucketGroup,Bucket_Data *pBucketData) +{ + int nCount = 0; + assert(pBucketGroup); + assert(pBucketData); + + nCount = FindDataIndexInBucket(pBucketGroup,pBucketData); + printf("[%06d] Key = 0x%08" DW_PR_DUx ", Base = 0x%08" DW_PR_DUx + ", Low = 0x%08" DW_PR_DUx ", High = 0x%08" DW_PR_DUx + ", Flag = %d, Name = '%s'\n", + ++nCount, + pBucketData->key, + pBucketData->base, + pBucketData->low, + pBucketData->high, + pBucketData->bFlag, + pBucketData->name); +} + +static void +DumpFullBucketGroup(Bucket_Group *pBucketGroup) +{ + int nBucketNo = 1; + int nIndex = 0; + int nCount = 0; + Bucket *pBucket = 0; + Bucket_Data *pBucketData = 0; + + assert(pBucketGroup); + for (pBucket = pBucketGroup->pHead; pBucket && pBucket->nEntries; + pBucket = pBucket->pNext) { + + printf("\nLowPC & HighPC records for bucket %d, at 0x%08lx\n", + nBucketNo++,(unsigned long)pBucket); + for (nIndex = 0; nIndex < pBucket->nEntries; ++nIndex) { + pBucketData = &pBucket->Entries[nIndex]; + printf("[%06d] Key = 0x%08" DW_PR_DUx ", Base = 0x%08" DW_PR_DUx + ", Low = 0x%08" DW_PR_DUx ", High = 0x%08" DW_PR_DUx + ", Flag = %d, Name = '%s'\n", + ++nCount, + pBucketData->key, + pBucketData->base, + pBucketData->low, + pBucketData->high, + pBucketData->bFlag, + pBucketData->name); + } + } +} + +/* Insert entry into Bucket Group. + We make no check for duplicate information. */ +void +AddEntryIntoBucketGroup(Bucket_Group *pBucketGroup, + Dwarf_Addr key,Dwarf_Addr base, + Dwarf_Addr low,Dwarf_Addr high, + const char *name, + Dwarf_Bool bFlag) +{ + Bucket *pBucket = 0; + Bucket_Data data; + + data.bFlag = bFlag; + data.name = name; + data.key = key; + data.base = base; + data.low = low; + data.high = high; + + assert(pBucketGroup); + if (!pBucketGroup->pHead) { + /* Allocate first bucket */ + pBucket = (Bucket *)calloc(1,sizeof(Bucket)); + pBucketGroup->pHead = pBucket; + pBucketGroup->pTail = pBucket; + pBucket->nEntries = 1; + pBucket->Entries[0] = data; + return; + } + + pBucket = pBucketGroup->pTail; + + /* Check if we have a previous allocated set of + buckets (have been cleared */ + if (pBucket->nEntries) { + if (pBucket->nEntries < BUCKET_SIZE) { + pBucket->Entries[pBucket->nEntries++] = data; + } else { + /* Allocate new bucket */ + pBucket = (Bucket *)calloc(1,sizeof(Bucket)); + pBucketGroup->pTail->pNext = pBucket; + pBucketGroup->pTail = pBucket; + pBucket->nEntries = 1; + pBucket->Entries[0] = data; + } + } else { + /* We have an allocated bucket with zero entries; search for the + first available bucket to be used as the current + insertion point */ + for (pBucket = pBucketGroup->pHead; pBucket; + pBucket = pBucket->pNext) { + + if (pBucket->nEntries < BUCKET_SIZE) { + pBucket->Entries[pBucket->nEntries++] = data; + break; + } + } + } +} + +/* For Groups where entries are individually deleted, this does + that work. */ +Dwarf_Bool +DeleteKeyInBucketGroup(Bucket_Group *pBucketGroup,Dwarf_Addr key) +{ + int nIndex = 0; + Bucket *pBucket = 0; + Bucket_Data *pBucketData = 0; + + /* Sanity checks */ + assert(pBucketGroup); + + /* For now do a linear search */ + for (pBucket = pBucketGroup->pHead; pBucket && pBucket->nEntries; + pBucket = pBucket->pNext) { + + for (nIndex = 0; nIndex < pBucket->nEntries; ++nIndex) { + pBucketData = &pBucket->Entries[nIndex]; + if (pBucketData->key == key) { + Bucket_Data data = {FALSE,NULL,0,0,0,0}; + int nStart; + for (nStart = nIndex + 1; nStart < pBucket->nEntries; + ++nStart) { + + pBucket->Entries[nIndex] = pBucket->Entries[nStart]; + ++nIndex; + } + pBucket->Entries[nIndex] = data; + --pBucket->nEntries; + return TRUE; + } + } + } + return FALSE; +} + +/* Search to see if the address is in the range between + low and high addresses in some Bucked Data record. + This matches == if high is exact match (which usually means + one-past-true-high). */ +Dwarf_Bool +FindAddressInBucketGroup(Bucket_Group *pBucketGroup,Dwarf_Addr address) +{ + int nIndex = 0; + Bucket *pBucket = 0; + Bucket_Data *pBucketData = 0; + + assert(pBucketGroup); + /* For now do a linear search */ + for (pBucket = pBucketGroup->pHead; pBucket && pBucket->nEntries; + pBucket = pBucket->pNext) { + + for (nIndex = 0; nIndex < pBucket->nEntries; ++nIndex) { + pBucketData = &pBucket->Entries[nIndex]; + if (address >= pBucketData->low && + address <= pBucketData->high) { + return TRUE; + } + } + } + return FALSE; +} + +/* Search an entry (Bucket Data) in the Bucket Set */ +Bucket_Data *FindDataInBucketGroup(Bucket_Group *pBucketGroup,Dwarf_Addr key) +{ + int mid = 0; + int low = 0; + int high = 0; + Bucket *pBucket = 0; + Bucket_Data *pBucketData = 0; + + assert(pBucketGroup); + + for (pBucket = pBucketGroup->pHead; pBucket; pBucket = pBucket->pNext) { + /* Get lower and upper references */ + if (pBucket->nEntries) { + low = 0; + high = pBucket->nEntries; + while (low < high) { + mid = low + (high - low) / 2; + if (pBucket->Entries[mid].key < key) { + low = mid + 1; + } else { + high = mid; + } + } + if ((low < pBucket->nEntries) && + (pBucket->Entries[low].key == key)) { + + pBucketData = &pBucket->Entries[low]; + /* Update sentinels to allow traversing the table */ + if (!pBucketGroup->pFirst) { + pBucketGroup->pFirst = pBucketData; + } + pBucketGroup->pLast = pBucketData; + return pBucketData; + } + } + } + return (Bucket_Data *)NULL; +} + +/* Find the Bucket that contains a given Bucket Data + and return its local index. Else return -1. */ +static int +FindDataIndexInBucket(Bucket_Group *pBucketGroup,Bucket_Data *pBucketData) +{ + Bucket *pBucket = 0; + Bucket_Data *pLower = 0; + Bucket_Data *pUpper = 0; + + /* Sanity checks */ + assert(pBucketGroup); + assert(pBucketData); + + /* Use sentinels if any. */ + if (pBucketGroup->pFirst && pBucketGroup->pLast && + pBucketData >= pBucketGroup->pFirst && + pBucketData <= pBucketGroup->pLast) { + + /* Find bucket that contains the first sentinel */ + for (pBucket = pBucketGroup->pHead; pBucket && pBucket->nEntries; + pBucket = pBucket->pNext) { + + pLower = &pBucket->Entries[0]; + pUpper = &pBucket->Entries[pBucket->nEntries - 1]; + + /* Check if the first sentinel is in this bucket. */ + if (pBucketGroup->pFirst >= pLower && + pBucketGroup->pFirst <= pUpper) { + /* We have found the bucket, return the index. */ + return pBucketData - pBucketGroup->pFirst; + } + } + } else { + /* Find bucket that contains the entry */ + for (pBucket = pBucketGroup->pHead; pBucket && pBucket->nEntries; + pBucket = pBucket->pNext) { + + pLower = &pBucket->Entries[0]; + pUpper = &pBucket->Entries[pBucket->nEntries - 1]; + + /* Check if the first sentinel is in this bucket */ + if (pBucketData >= pLower && pBucketData <= pUpper) { + /* We have found the bucket, return the index */ + return pBucketData - pLower; + } + } + } + /* Invalid data; just return index indicating not-found */ + return -1; +} + +/* Search an entry (Bucket Data) in the Bucket Group. + The key is an offset, a DIE offset + within Visited info. */ +Bucket_Data *FindKeyInBucketGroup(Bucket_Group *pBucketGroup,Dwarf_Addr key) +{ + int nIndex = 0; + Bucket *pBucket = 0; + Bucket_Data *pBucketData = 0; + + /* Sanity checks */ + assert(pBucketGroup); + + /* For now do a linear search */ + for (pBucket = pBucketGroup->pHead; pBucket && pBucket->nEntries; + pBucket = pBucket->pNext) { + for (nIndex = 0; nIndex < pBucket->nEntries; ++nIndex) { + pBucketData = &pBucket->Entries[nIndex]; + if (pBucketData->key == key) { + return pBucketData; + } + } + } + return (Bucket_Data *)NULL; +} + +/* Search an entry (Bucket Data) in the Bucket Set by name. + Used to find link-once section names. */ +Bucket_Data * +FindNameInBucketGroup(Bucket_Group *pBucketGroup,char *name) +{ + int nIndex = 0; + Bucket *pBucket = 0; + Bucket_Data *pBucketData = 0; + + assert(pBucketGroup); + /* For now do a linear search. */ + for (pBucket = pBucketGroup->pHead; pBucket && pBucket->nEntries; + pBucket = pBucket->pNext) { + for (nIndex = 0; nIndex < pBucket->nEntries; ++nIndex) { + pBucketData = &pBucket->Entries[nIndex]; + if (!strcmp(pBucketData->name,name)) { + return pBucketData; + } + } + } + return (Bucket_Data *)NULL; +} + +/* Check if an address valid or not. That is, + check if it is in the lower -> upper range of a bucket. + It checks <= and >= so the lower end + and one-past on the upper end matches. +*/ +Dwarf_Bool +IsValidInBucketGroup(Bucket_Group *pBucketGroup,Dwarf_Addr address) +{ + Bucket *pBucket = 0; + Bucket_Data *pBucketData = 0; + int nIndex = 0; + + assert(pBucketGroup); + /* Check the address is within the allowed limits */ + if (address >= pBucketGroup->lower && address <= pBucketGroup->upper) { + for (pBucket = pBucketGroup->pHead; pBucket && pBucket->nEntries; + pBucket = pBucket->pNext) { + + for (nIndex = 0; nIndex < pBucket->nEntries; ++nIndex) { + pBucketData = &pBucket->Entries[nIndex]; + if (address >= pBucketData->low && + address <= pBucketData->high) { + return TRUE; + } + } + } + } + return FALSE; +} + +/* Reset limits for values in the Bucket Set */ +void +ResetLimitsBucketSet(Bucket_Group *pBucketGroup) +{ + assert(pBucketGroup); + pBucketGroup->lower = 0; + pBucketGroup->upper = 0; +} + +/* Limits are set only for ranges, so only in pRangesInfo. */ +void +SetLimitsBucketGroup(Bucket_Group *pBucketGroup, + Dwarf_Addr lower,Dwarf_Addr upper) +{ + assert(pBucketGroup); + if (lower < upper) { + pBucketGroup->lower = lower; + pBucketGroup->upper = upper; + } +} + +/* Traverse Bucket Set and execute a supplied function */ +static void +ProcessBucketGroup(Bucket_Group *pBucketGroup, + void (*pFunction)(Bucket_Group *pBucketGroup,Bucket_Data *pBucketData)) +{ + int nIndex = 0; + int nStart = 0; + Bucket *pBucket = 0; + Bucket_Data *pBucketData = 0; + Bucket_Data *pLower = 0; + Bucket_Data *pUpper = 0; + Dwarf_Bool bFound = FALSE; + + /* Sanity checks */ + assert(pBucketGroup); + + /* No sentinels present; do nothing */ + if (!pBucketGroup->pFirst || !pBucketGroup->pLast) { + return; + } + + /* Find bucket that contains the first sentinel */ + for (pBucket = pBucketGroup->pHead; pBucket && pBucket->nEntries; + pBucket = pBucket->pNext) { + + pLower = &pBucket->Entries[0]; + pUpper = &pBucket->Entries[pBucket->nEntries - 1]; + + /* Check if the first sentinel is in this bucket */ + if (pBucketGroup->pFirst >= pLower && pBucketGroup->pFirst <= pUpper) { + /* Low sentinel is in this bucket */ + bFound = TRUE; + break; + } + } + + /* Invalid sentinel; do nothing */ + if (!bFound) { + return; + } + + /* Calculate index for first sentinel */ + nStart = pBucketGroup->pFirst - pLower; + + /* Start traversing from found bucket */ + for (; pBucket && pBucket->nEntries; pBucket = pBucket->pNext) { + for (nIndex = nStart; nIndex < pBucket->nEntries; ++nIndex) { + pBucketData = &pBucket->Entries[nIndex]; + if (pBucketData > pBucketGroup->pLast) { + return; + } + /* Call the user supplied function */ + if (pFunction) { + pFunction(pBucketGroup,pBucketData); + } + } + /* For next bucket start with first entry */ + nStart = 0; + } +} + +/* Check if a given (lopc,hipc) are valid for a linkonce. + We pass in the linkonce (instead of + referencing the global pLinkonceInfo) as that means + searches for pLinkonceInfo find all the uses, + making understanding of the code a tiny bit easier. + The section name created is supposed to be the appropriate + linkonce section name. +*/ +Dwarf_Bool IsValidInLinkonce(Bucket_Group *pLo, + const char *name,Dwarf_Addr lopc,Dwarf_Addr hipc) +{ +#define SECTION_NAME_LEN 2048 /* Guessing a sensible length */ + static char section_name[SECTION_NAME_LEN]; + Bucket_Data *pBucketData = 0; + /* Since text is quite uniformly just this name, no need to get it + from elsewhere, though it will not work for non-elf. */ + const char *lo_text = ".text"; + + /* Build the name that represents the linkonce section (.text). + This is not defined in DWARF so not correct for all + compilers. */ + snprintf(section_name,sizeof(section_name),"%s%s",lo_text,name); + + pBucketData = FindNameInBucketGroup(pLo,section_name); + if (pBucketData) { + if (lopc >= pBucketData->low && lopc <= pBucketData->high) { + if (hipc >= pBucketData->low && hipc <= pBucketData->high) { + return TRUE; + } + } + } + return FALSE; +} + diff --git a/dwarfdump/checkutil.h b/dwarfdump/checkutil.h new file mode 100644 index 0000000..d922b98 --- /dev/null +++ b/dwarfdump/checkutil.h @@ -0,0 +1,98 @@ +/* + Copyright (C) 2011 SN Systems Ltd. All Rights Reserved. + Portions Copyright (C) 2011 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + +*/ + +#ifndef CHECKUTIL_H +#define CHECKUTIL_H + +/* Map information. + Depending on the specific functions used various + fields here are either used or ignored. + +*/ +typedef struct { + Dwarf_Bool bFlag; /* General flag */ + const char *name; /* Generic name */ + Dwarf_Addr key; /* Used for binary search, the key + is either a pc address or a DIE offset + depending on which bucket table is in use. */ + Dwarf_Addr base; /* Used for base address */ + Dwarf_Addr low; /* Used for Low PC */ + Dwarf_Addr high; /* Used for High PC */ +} Bucket_Data; + +/* This groups Bucket_Data records into + a 'bucket' so that a single malloc creates + BUCKET_SIZE entries. The intent is to reduce + overhead (as compared to having next/previous + pointers in each Bucket_Data and mallocing + each Bucket_Data individually. +*/ + +#define BUCKET_SIZE 2040 +typedef struct bucket { + int nEntries; + Bucket_Data Entries[BUCKET_SIZE]; + struct bucket *pNext; +} Bucket; + +/* This Forms the head record of a list of Buckets. +*/ +typedef struct { + int kind; /* Kind of bucket */ + Dwarf_Addr lower; /* Lower value for data */ + Dwarf_Addr upper; /* Upper value for data */ + Bucket_Data *pFirst; /* First sentinel */ + Bucket_Data *pLast; /* Last sentinel */ + Bucket *pHead; /* First bucket in set */ + Bucket *pTail; /* Last bucket in set */ +} Bucket_Group; + +Bucket_Group *AllocateBucketGroup(int kind); +void ReleaseBucketGroup(Bucket_Group *pBucketGroup); +void ResetBucketGroup(Bucket_Group *pBucketGroup); +void ResetSentinelBucketGroup(Bucket_Group *pBucketGroup); + +void PrintBucketGroup(Bucket_Group *pBucketGroup,Dwarf_Bool bFull); + +void AddEntryIntoBucketGroup(Bucket_Group *pBucketGroup, + Dwarf_Addr key,Dwarf_Addr base,Dwarf_Addr low,Dwarf_Addr high, + const char *name, Dwarf_Bool bFlag); + +Dwarf_Bool DeleteKeyInBucketGroup(Bucket_Group *pBucketGroup,Dwarf_Addr key); + +Dwarf_Bool FindAddressInBucketGroup(Bucket_Group *pBucketGroup,Dwarf_Addr address); +Bucket_Data *FindDataInBucketGroup(Bucket_Group *pBucketGroup,Dwarf_Addr key); +Bucket_Data *FindKeyInBucketGroup(Bucket_Group *pBucketGroup,Dwarf_Addr key); +Bucket_Data *FindNameInBucketGroup(Bucket_Group *pBucketGroup,char *name); + +Dwarf_Bool IsValidInBucketGroup(Bucket_Group *pBucketGroup,Dwarf_Addr pc); + +void ResetLimitsBucketSet(Bucket_Group *pBucketGroup); +void SetLimitsBucketGroup(Bucket_Group *pBucketGroup,Dwarf_Addr lower,Dwarf_Addr upper); +Dwarf_Bool IsValidInLinkonce(Bucket_Group *pLo, + const char *name,Dwarf_Addr lopc,Dwarf_Addr hipc); + + +#endif /* CHECKUTIL_H */ diff --git a/dwarfdump/common.c b/dwarfdump/common.c new file mode 100644 index 0000000..2788578 --- /dev/null +++ b/dwarfdump/common.c @@ -0,0 +1,88 @@ +/* + Copyright (C) 2008-2010 SN Systems. All Rights Reserved. + Portions Copyright (C) 2008-2011 David Anderson. All Rights Reserved. + Portions Copyright (C) 2011 SN Systems Ltd. . All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + +/* These do little except on Windows */ + +#include "common.h" +#include <stdio.h> +#define DWARFDUMP_VERSION " Tue Apr 10 11:43:32 PDT 2012 " + +/* The Linux/Unix version does not want a version string to print + unless -V is on the command line. */ +void +print_version_details(const char * name,int alwaysprint) +{ +#ifdef WIN32 +# ifdef _DEBUG + char *acType = "Debug"; +# else + char *acType = "Release"; +# endif /* _DEBUG */ + static char acVersion[32]; + snprintf(acVersion,sizeof(acVersion), + "[%s %s %s]",__DATE__,__TIME__,acType); + printf("%s %s\n",name,acVersion); +#else /* !WIN32 */ + if(alwaysprint) { + printf("%s\n",DWARFDUMP_VERSION); + } +#endif /* WIN32 */ +} + + +void +print_args(int argc, char *argv[]) +{ +#ifdef WIN32 + int index = 1; + printf("Arguments: "); + for (index = 1; index < argc; ++index) { + printf("%s ",argv[index]); + } + printf("\n"); +#endif /* WIN32 */ +} + +void +print_usage_message(const char *program_name, const char **text) +{ + unsigned i = 0; +#ifndef WIN32 + fprintf(stderr,"Usage: %s <options> <object file>\n", program_name); +#endif + for (i = 0; *text[i]; ++i) { + fprintf(stderr,"%s\n", text[i]); + } +} diff --git a/dwarfdump/common.h b/dwarfdump/common.h new file mode 100644 index 0000000..f1a598e --- /dev/null +++ b/dwarfdump/common.h @@ -0,0 +1,42 @@ +/* + Copyright (C) 2009-2010 SN Systems. All Rights Reserved. + Portions Copyright (C) 2009-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + +#ifndef COMMON_INCLUDED_H +#define COMMON_INCLUDED_H + +void print_args(int argc, char *argv[]); +void print_version_details(const char *name, int alwaysprint); +void print_usage_message(const char *program_name, const char **text); + +#endif /* COMMON_INCLUDED_H */ diff --git a/dwarfdump/config.h.in b/dwarfdump/config.h.in new file mode 100644 index 0000000..a1a11db --- /dev/null +++ b/dwarfdump/config.h.in @@ -0,0 +1,100 @@ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* Define to 1 if the elf64_getehdr function is in libelf.a. */ +#undef HAVE_ELF64_GETEHDR + +/* Define to 1 if the Elf64_Rel structure has r_info field. */ +#undef HAVE_ELF64_R_INFO + +/* Define to 1 if you have the <elf.h> header file. */ +#undef HAVE_ELF_H + +/* Define to 1 if you have the <getopt.h> header file. */ +#undef HAVE_GETOPT_H + +/* Define to 1 if you have the <inttypes.h> header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the <libelf.h> header file. */ +#undef HAVE_LIBELF_H + +/* Define to 1 if you have the <libelf/libelf.h> header file. */ +#undef HAVE_LIBELF_LIBELF_H + +/* Define 1 if off64 is defined via libelf with GNU_SOURCE. */ +#undef HAVE_LIBELF_OFF64_OK + +/* Define to 1 if you have the <memory.h> header file. */ +#undef HAVE_MEMORY_H + +/* Define 1 if need nonstandard printf format for 64bit */ +#undef HAVE_NONSTANDARD_PRINTF_64_FORMAT + +/* Define 1 if plain libelf builds. */ +#undef HAVE_RAW_LIBELF_OK + +/* Define 1 if regex seems to be defined */ +#undef HAVE_REGEX + +/* Define to 1 if you have the <sgidefs.h> header file. */ +#undef HAVE_SGIDEFS_H + +/* Define 1 if we have the Windows specific header stdafx.h */ +#undef HAVE_STDAFX_H + +/* Define to 1 if you have the <stdint.h> header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the <stdlib.h> header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the <strings.h> header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the <string.h> header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the <sys/types.h> header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define 1 if the tsearch functions seem to be defined */ +#undef HAVE_TSEARCH + +/* Define to 1 if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* See if __uint32_t is predefined in the compiler. */ +#undef HAVE___UINT32_T + +/* Define 1 if sys/types.h defines __uint32_t. */ +#undef HAVE___UINT32_T_IN_SYS_TYPES_H + +/* See if __uint64_t is predefined in the compiler. */ +#undef HAVE___UINT64_T + +/* Define to header that first defines elf. */ +#undef LOCATION_OF_LIBELFHEADER + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS diff --git a/dwarfdump/configure b/dwarfdump/configure new file mode 100755 index 0000000..67ede72 --- /dev/null +++ b/dwarfdump/configure @@ -0,0 +1,5109 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.68. +# +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software +# Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + # We cannot yet assume a decent shell, so we have to provide a + # neutralization value for shells without unset; and this also + # works around shells that cannot unset nonexistent variables. + # Preserve -v and -x to the replacement shell. + BASH_ENV=/dev/null + ENV=/dev/null + (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV + export CONFIG_SHELL + case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; + esac + exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"} +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 </dev/null +exec 6>&1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= +PACKAGE_URL= + +ac_unique_file="dwarfdump.c" +# Factoring default headers for most tests. +ac_includes_default="\ +#include <stdio.h> +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif +#ifdef HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# ifdef HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include <memory.h> +# endif +# include <string.h> +#endif +#ifdef HAVE_STRINGS_H +# include <strings.h> +#endif +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif" + +ac_subst_vars='LTLIBOBJS +LIBOBJS +AR +RANLIB +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +EGREP +GREP +CPP +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_nonstandardprintf +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used" >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures this package to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-nonstandardprintf + Use a special printf format for 64bit (default is + NO) + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a + nonstandard directory <lib dir> + LIBS libraries to pass to the linker, e.g. -l<library> + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if + you have headers in a nonstandard directory <include dir> + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to the package provider. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +configure +generated by GNU Autoconf 2.68 + +Copyright (C) 2010 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.68. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +ac_config_headers="$ac_config_headers config.h" + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdio.h> +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +if test $ac_cv_c_compiler_gnu = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC needs -traditional" >&5 +$as_echo_n "checking whether $CC needs -traditional... " >&6; } +if ${ac_cv_prog_gcc_traditional+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_pattern="Autoconf.*'x'" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sgtty.h> +Autoconf TIOCGETP +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "$ac_pattern" >/dev/null 2>&1; then : + ac_cv_prog_gcc_traditional=yes +else + ac_cv_prog_gcc_traditional=no +fi +rm -f conftest* + + + if test $ac_cv_prog_gcc_traditional = no; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <termio.h> +Autoconf TCGETA +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "$ac_pattern" >/dev/null 2>&1; then : + ac_cv_prog_gcc_traditional=yes +fi +rm -f conftest* + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_gcc_traditional" >&5 +$as_echo "$ac_cv_prog_gcc_traditional" >&6; } + if test $ac_cv_prog_gcc_traditional = yes; then + CC="$CC -traditional" + fi +fi + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. +set dummy ${ac_tool_prefix}ar; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AR="${ac_tool_prefix}ar" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_AR"; then + ac_ct_AR=$AR + # Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_AR="ar" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_AR" = x; then + AR="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +else + AR="$ac_cv_prog_AR" +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ctype.h> +#include <stdlib.h> +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in elf.h getopt.h libelf.h libelf/libelf.h sgidefs.h sys/types.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for elf64_getehdr in -lelf" >&5 +$as_echo_n "checking for elf64_getehdr in -lelf... " >&6; } +if ${ac_cv_lib_elf_elf64_getehdr+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lelf $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char elf64_getehdr (); +int +main () +{ +return elf64_getehdr (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_elf_elf64_getehdr=yes +else + ac_cv_lib_elf_elf64_getehdr=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_elf_elf64_getehdr" >&5 +$as_echo "$ac_cv_lib_elf_elf64_getehdr" >&6; } +if test "x$ac_cv_lib_elf_elf64_getehdr" = xyes; then : + +$as_echo "#define HAVE_ELF64_GETEHDR 1" >>confdefs.h + +fi + + +if test "$ac_cv_header_elf_h" = yes; then + +$as_echo "#define LOCATION_OF_LIBELFHEADER <elf.h>" >>confdefs.h + +elif test "$ac_cv_header_libelf_h" = yes; then + +$as_echo "#define LOCATION_OF_LIBELFHEADER <libelf.h>" >>confdefs.h + +elif test "$ac_cv_header_libelf_libelf_h" = yes; then + +$as_echo "#define LOCATION_OF_LIBELFHEADER <libelf/libelf.h>" >>confdefs.h + +fi + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include "stdafx.h" +int +main () +{ + int p; p = 27; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define HAVE_STDAFX_H 1" >>confdefs.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include LOCATION_OF_LIBELFHEADER +int +main () +{ +Elf64_Rel *p; int i; i = p->r_info; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define HAVE_ELF64_R_INFO 1" >>confdefs.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +__uint32_t p; p = 3; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define HAVE___UINT32_T 1" >>confdefs.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +__uint64_t p; p = 3; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define HAVE___UINT64_T 1" >>confdefs.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/types.h> +int +main () +{ + __uint32_t p; p = 3; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define HAVE___UINT32_T_IN_SYS_TYPES_H 1" >>confdefs.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/types.h> + #include <regex.h> +int +main () +{ + int i; + regex_t r; + int cflags = REG_EXTENDED; + const char *s = "abc"; + i = regcomp(&r,s,cflags); + regfree(&r); + ; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define HAVE_REGEX 1" >>confdefs.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdio.h> +#include <stdlib.h> +/* On Ubuntu 10.x, tsearch is in package libc6-dev. */ +/* The tdestroy function is GNU, not POSIX. */ +#define __USE_GNU 1 +#include <search.h> +struct my_tentry { + long mt_key; + char * mt_name; +}; +struct my_tentry * make_my_tentry(long k,char *name) { return 0; } +void mt_free_func(void *mt_data) { return; } +int mt_compare_func(const void *l, const void *r) { return 0; } +int +main () +{ + + long i = 1; + void *tree1 = 0; + char *dbuf = 0; + struct my_tentry *mt = 0; + struct my_tentry *retval = 0; + mt = make_my_tentry(i,dbuf); + retval = tsearch(mt,&tree1, mt_compare_func ); + tdestroy(tree1,mt_free_func); + exit(0); +; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + +$as_echo "#define HAVE_TSEARCH 1" >>confdefs.h + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + +# Check whether --enable-nonstandardprintf was given. +if test "${enable_nonstandardprintf+set}" = set; then : + enableval=$enable_nonstandardprintf; +$as_echo "#define HAVE_NONSTANDARD_PRINTF_64_FORMAT 1" >>confdefs.h + +fi + + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <libelf.h> + +int +main () +{ + int p; p = 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define HAVE_RAW_LIBELF_OK 1" >>confdefs.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define _GNU_SOURCE +#include <libelf.h> + +int +main () +{ + off64_t p; p = 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define HAVE_LIBELF_OFF64_OK 1" >>confdefs.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + + +ac_config_files="$ac_config_files Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by $as_me, which was +generated by GNU Autoconf 2.68. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to the package provider." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.68, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2010 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' <conf$$subs.awk | sed ' +/^[^""]/{ + N + s/\n// +} +' >>$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' <confdefs.h | sed ' +s/'"$ac_delim"'/"\\\ +"/g' >>$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi + ;; + + + esac + +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/dwarfdump/configure.in b/dwarfdump/configure.in new file mode 100644 index 0000000..753a1b4 --- /dev/null +++ b/dwarfdump/configure.in @@ -0,0 +1,98 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(dwarfdump.c) +AC_CONFIG_HEADER(config.h) + +AC_PROG_CC +AC_GCC_TRADITIONAL +AC_PROG_INSTALL +AC_CHECK_TOOL(RANLIB, ranlib, :) +AC_CHECK_TOOL(AR, ar) +dnl AC_ARFLAGS + +AC_CHECK_HEADERS(elf.h getopt.h libelf.h libelf/libelf.h sgidefs.h sys/types.h) +AC_CHECK_LIB(elf,elf64_getehdr, + AC_DEFINE(HAVE_ELF64_GETEHDR,1, + [Define to 1 if the elf64_getehdr function is in libelf.a.])) + +dnl Find out where the elf header is. +if test "$ac_cv_header_elf_h" = yes; then + AC_DEFINE(LOCATION_OF_LIBELFHEADER,[<elf.h>], [Define to header that first defines elf]) +elif test "$ac_cv_header_libelf_h" = yes; then + AC_DEFINE(LOCATION_OF_LIBELFHEADER, [<libelf.h>], + [Define to header that first defines elf.]) +elif test "$ac_cv_header_libelf_libelf_h" = yes; then + AC_DEFINE(LOCATION_OF_LIBELFHEADER,[<libelf/libelf.h>], + [Define to header that first defines elf.]) +fi + +AC_TRY_COMPILE([#include "stdafx.h"],[ int p; p = 27;] , + AC_DEFINE(HAVE_STDAFX_H,1, + [Define 1 if we have the Windows specific header stdafx.h])) + +AC_TRY_COMPILE([#include LOCATION_OF_LIBELFHEADER], Elf64_Rel *p; int i; i = p->r_info; ,AC_DEFINE(HAVE_ELF64_R_INFO,1, + [Define to 1 if the Elf64_Rel structure has r_info field.])) +AC_TRY_COMPILE([], __uint32_t p; p = 3; ,AC_DEFINE(HAVE___UINT32_T, + 1,[See if __uint32_t is predefined in the compiler. ])) +AC_TRY_COMPILE([], __uint64_t p; p = 3; ,AC_DEFINE(HAVE___UINT64_T, + 1,[See if __uint64_t is predefined in the compiler. ])) +AC_TRY_COMPILE([#include <sys/types.h>],[ __uint32_t p; p = 3]; , + AC_DEFINE(HAVE___UINT32_T_IN_SYS_TYPES_H,1, + [Define 1 if sys/types.h defines __uint32_t.])) +AC_TRY_COMPILE([#include <sys/types.h> + #include <regex.h>],[ int i; + regex_t r; + int cflags = REG_EXTENDED; + const char *s = "abc"; + i = regcomp(&r,s,cflags); + regfree(&r); + ]; , + AC_DEFINE(HAVE_REGEX,1, + [Define 1 if regex seems to be defined])) +AC_TRY_LINK([#include <stdio.h> +#include <stdlib.h> +/* On Ubuntu 10.x, tsearch is in package libc6-dev. */ +/* The tdestroy function is GNU, not POSIX. */ +#define __USE_GNU 1 +#include <search.h> +struct my_tentry { + long mt_key; + char * mt_name; +}; +struct my_tentry * make_my_tentry(long k,char *name) { return 0; } +void mt_free_func(void *mt_data) { return; } +int mt_compare_func(const void *l, const void *r) { return 0; }],[ + long i = 1; + void *tree1 = 0; + char *dbuf = 0; + struct my_tentry *mt = 0; + struct my_tentry *retval = 0; + mt = make_my_tentry(i,dbuf); + retval = tsearch(mt,&tree1, mt_compare_func ); + tdestroy(tree1,mt_free_func); + exit(0); +];, + AC_DEFINE(HAVE_TSEARCH,1, + [Define 1 if the tsearch functions seem to be defined])) + + +AC_ARG_ENABLE(nonstandardprintf,AC_HELP_STRING([--enable-nonstandardprintf], + [Use a special printf format for 64bit (default is NO)]), + [ AC_DEFINE([HAVE_NONSTANDARD_PRINTF_64_FORMAT],[1], + [Define 1 if need nonstandard printf format for 64bit] )], + []) + +AC_TRY_COMPILE([ +#include <libelf.h> +],[ int p; p = 0; ] , + AC_DEFINE(HAVE_RAW_LIBELF_OK,1, + [Define 1 if plain libelf builds.])) +AC_TRY_COMPILE([ +#define _GNU_SOURCE +#include <libelf.h> +],[ off64_t p; p = 0;] , + AC_DEFINE(HAVE_LIBELF_OFF64_OK,1, + [Define 1 if off64 is defined via libelf with GNU_SOURCE.])) + + + +AC_OUTPUT(Makefile) diff --git a/dwarfdump/dwarfdump.1 b/dwarfdump/dwarfdump.1 new file mode 100644 index 0000000..bb7ee37 --- /dev/null +++ b/dwarfdump/dwarfdump.1 @@ -0,0 +1,523 @@ +.TH DWARFDUMP +.SH NAME +dwarfdump \- dumps DWARF debug information of an ELF object +.SH SYNOPSIS +.B dwarfdump [options] \f2objectfilename\fP +.SH DESCRIPTION +The +.B dwarfdump +command prints or checks DWARF sections as requested by specific options. +With no options (but with the required \f2objectfilename\fP ) +all sections print (but some sections cannot be printed independently +safely, so those are only printed at offsets where the .debug_info section +refers to those sections). +.PP +As of June 2011 the printing options and the checking options +are mutually exclusive (if checking options are selected +the section details are not printed). When errors are encountered +dwarfdump does attempt to print sufficient context so that +one can understand exactly where the error is in the DWARF. +This change makes checking really large object files +much easier. +.PP +The format is intended to be human readable. +If a script is to parse the output, the +.B \-d +option is useful. +.PP +Not all sections actually exist in any given object file. +.PP +The format may change from release to release, so it is +unwise to depend too heavily on the format. +.PP +Frame information (.debug_frame and .eh_frame) is heavily +dependent on the ABI/ISA of the object file. +By default we use a generic set of register names +handling up to 100 registers named r0-100. +The '-R' option uses a built-in generic register name set +handling up to 1200 registers named r0-r1199. +The '-x abi=<abi>' +description below shows how to name an abi and use that to guide +the -f or -F processing. +Unless the cpu for the object file being dumped has many registers, +do not use -R or -x abi=generic as those can be needlessly +slow dumping frame sections. Instead, use the correct +abi (if it exists in dwarfdump.conf) or a generic such +as -x abi=generic100 or -x abi=generic500. +To get MIPS/IRIX register names names and call the old version 2 libdwarf +frame interface use the option '-x abi=mips'. +Without '-R' or '-x abi=<abi>' dwarfdump ignores +the dwarfdump.conf file and uses compiled-in generic set of +register names. +If no '-x name=<path>' is given, dwarfdump +looks for "./dwarfdump.conf", "$HOME/.dwarfdump.conf", "<install-prefix>/lib/dwarfdump.conf" and takes the first it finds. +If one or more '-x name=<path>' is given the last of these is +used and all other such files are ignored. +.PP +Some -k (checking) options print so-called harmless errors. +These are compiler errors that do not cause any +known problem and are only detected inside libdwarf itself. +These are difficult to properly report in dwarfdump and +any error strings may not appear close to the time the +error was encountered. +.SH URI STYLE INPUT STRINGS +.PP +The <objectfilename> and the options taking name strings look for URIs and +translate the URI strings to characters by default +(see -x, -c<compiler name>, -S, -u). +So any single % character is treated as if the following two +characters are hex digits representing the underlying true character. +Various characters are meaningful to shells (such as bash or sh) +and to getopt (such as the space character) +If the URI translation does anything it prints the before and after +of the URI translation on standard output, so inspection of the first +lines of output will show if URI did anything. +The actual options themselves are assumed to be non-URI. +So in the option '-cS&T' the -c portion must be non-URI, but the +& character might cause input issues so '-cS%26T' could be used instead. +To actually input a single % character (in a name, for example), +double it to %% on the command line. +.PP +Options -U (turning off URI interpretation) and -q (making finding +URI sequences silent) give finer control of URI interpretation. +PP +As an example, to get a string'a b' make the string 'a%20b' +(here the quote (') is for exposition not part of the string, though +quote is certainly problematic in a name). +Instead of escaping " quotes in the string, type %25, as in + 'a "b' should be typed 'a%20%25b' +Any characters can be typed in URI style, not just characters +which are problematic to the shell or getopt. +We strongly suggest you not type URI-style characters where +such are not needed or use +the % character itself in command line strings unless you must. +.SH PRINTING OPTIONS +.TP +.B \-a +Print each section as independently as possible. Sections that +can safely be printed independently (like .debug_abbrev) +have relevant info printed in the report (sometimes dependent +on -v). + +.TP +.B \-b +Print the .debug_abbrev section. Because the DWARF specfications +do not rule out garbage data areas in .debug_abbrev (if they are not +referenced from .debug_info) any garbage bytes can result in +this print failing. + +.TP +.B \-c +Print locations lists. + +.TP +.B \-f +Print the .debug_frame section. +.TP +.B \-F +Print the .eh_frame section. + +.TP +.B \-i +Print the .debug_info section. + +.TP +.B \-l +Print the .debug_info section and the associated line section data. + +.TP +.B \-m +Print the .debug_macinfo section. + +.TP +.B \-N +Print .debug_ranges section. Because the DWARF specfications +do not rule out garbage data areas in .debug_ranges (if they are not +referenced from .debug_info) any garbage bytes can result in +this print failing. + +.TP +.B \-p +Print the .debug_pubnames section. + +.TP +.B \-r +Print the .debug_aranges section. +.TP +.B \-s +Print .debug_string section. + +.TP +.B \-ta +Print the IRIX only sections .debug_static_funcs and .debug_static_vars. + +.TP +.B \-tf +Print the IRIX only section .debug_static_funcs. +.TP +.B \-tv +Print the IRIX only section .debug_static_vars. + +.TP +.B \-w +Print the IRIX-only .debug_weaknames section. + +.TP +.B \-y +Print the .debug_pubtypes section (and .debug_typenames, +an SGI IRIX-only section). + +.PP +Having dwarfdump print relocations may help establish whether +dwarfdump understands any relocations that might exist. + +.TP +.B \-o +Print all relocation records as well as we can manage. +.TP +.B \-oi +Print .rel*debug_info relocations. +.TP +.B \-ol +Print .rel*debug_line relocation. +.TP +.B \-op +Print .rel*debug_pubnames relocation. +.TP +.B \-oa +Has no effect. +.TP +.B \-or +Print .rel*debug_aranges relocations. +.TP +.B \-of +Print .rel*debug_frame relocations. +.TP +.B \-oo +Print .rel*debug_loc relocations. +.TP +.B \-oR +Print .rel*debug_ranges relocations. + +.TP +.B \-g +Normally used only for testing libdwarf, this tells dwarfdump to +print .debug_info and use an older dwarf_loclist() interface +function (a function that cannot handle all current +location lists). +.TP +.B \-V +Print a dwarfdump date/version string and stop. + +.SH CHECKING OPTIONS +.TP +.B \-cg +Restricts checking to compilers whose +producer string starts with 'GNU' +and turns off -cs . + +.TP +.B \-cs +Restricts checking to compilers whose +producer string starts with 'SN' +and turns off -cg . +.TP +.B \-cname +Restricts checking to compilers whose +producer string contains 'name' (not case sensitive). +The 'name' is read as a URI string. + +.TP +.B \ +-ka : Turns on all checking options except -kxe (-kxe might + be slow enough one mignt not want to use it routinely.) + +.TP +.B \ +-kb : Checks for certain abbreviations section errors when reading + DIEs. +.TP +.B \-kc +Checks for errors in constants in debug_info. +.TP +.B \-kd +Turns on full reporting of error totals per producer. +(the default shows less detail). +.TP +.B \-ke +Turns on reading pubnames and checking for fde errors. +.TP +.B \-kf +Turns on checking for FDE errors. +.TP +.B \-kF +Turns on checking for line table errors. +.TP +.B \-kg +Turns on checking for unused gaps in .debug_info (these +gaps are not an error, just a waste of space). + +.TP +.B \-ki +Causes a summary of checking results per compiler (producer) +to be printed at the end. +.TP +.B \-kl +Turns on locations list checking. +.TP +.B \-km +Turns on checking of ranges. +.TP +.B \-kM +Turns on checking of aranges. +.TP +.B \-kr +Turns on DIE tag-attr combinations checking. +.TP +.B \-kR +Turns on reading DIEs and checking for forward declarations +rom DW_AT_specification attributes. +(which are not an error but can be a source of inefficiency +for debuggers). +.TP +.B \-ks +Turns on extra reporting for some DIE errors checking detects . +.TP +.B \-kS +Turns on checking DIE references for circular references. +.TP +.B \-kt +Turns on tag-tag combinations checking. +.TP +.B \-kx +Turns on check_frames. +.TP +.B \-kxe +Turns off basic check_frames and turns on extended frame checking. +.TP +.B \-ky +Turns on type_offset, decl_file checking, + +.SH OPTION MODIFIERS + +.TP +.B \-C +Normally when checking for tag-tag or tag-attribute combinations +both the standard combinations and some common extensions are allowed. +With -C the extensions are taken out of the allowed class of combinations. + +.TP +.B \-d +When printing DIEs, put all the attributes for each DIE on the same (long) +line as the TAG. This makes searching for DIE information +(as with grep) much simpler as the entire DIE is on one line. + +.TP +.B \-D +Turns off the display of section offsets and attribute values in printed output. +So the .debug_info output isjust TAGs and Attributes. +For pubnames (and the like) it removes offsets from the output. +For locations lists it removes offsets from the output, but that +is useless since the attribute values don't show so neither does +the location data. + +.TP +.B \-e +Turns on truncation of attribute and tag names. For example +DW_TAG_foo becomes foo . Not compatible with +checking, only useful for printing DIEs. + +.TP +.B \-G +When printing, add global offsets to the offsets printed. + +.TP +.B \-H number +When printing or checking .debug_info, this terminates +the search after 'number' compilation units. When printing +frame information this terminates the FDE reporting +after 'number' FDEs and the CIE reporting (which occurs if one adds -v) +after 'number' CIEs. Example '-H 1' + +.TP +.B \-M +When printing, this means one want to have the FORM show for each attribute. +If a -v is also added (or more than one) then details of any form indirection +are also shown. + +.TP +.B \-n +When printing frames, this turns off the search for function names. +In a really large object the search can take more time than +one wants to wait, so this avoids the search. + +.TP +.B \-Q +Suppresses section data printing (set automatically with a checking option). + +.TP +.B \-R +When printing frames for ABIs with lots of registers, this allows +up to 1200 registers to be named (like R999) without choosing an ABI +with, for example '-x abi=ppc' + +.TP +.B \-v +Increases the detail shown when printing. +In some sections, using more -v options +will increase the detail (one to three are useful) or may +change the report to show, for example, the actual +line-data-commands instead of the resultant line-table. + +.SH SELECTIVE ENTRY PRINTING + +.PP +These -S options stand alone and basic print information about the compilation +unit and DIE where the string(s) appear. +At most one of each of the following is effective (so for example +one can only have one 'match', but one can +have a 'match', an 'any', and a 'regex'). +Any -S causes the .debug_info section to be inspected. +No checking options or printing options should be supplied with -S. + +.TP +.B \-S match=string +When printing DIEs +for each tag value or attribute name that matches 'string' exactly +print the compilation unit information and its section offset. +Any CU with no match is not printed. +The 'string' is read as a URI string. +.TP +.B \-S any=string +When printing DIEs +for each tag value or attribute name that contains 'string' +somewhere in the tag or attribute (case insensitive) +print the compilation unit information and its section offset. +Any CU with no match is not printed. +The 'string' is read as a URI string. +.TP +.B \-S regex=string +When printing DIEs +for each tag value or attribute name where the 'string' reqular +expression matches print the compilation unit information +and its section offset. +Any CU with no match is not printed. +The 'string' is read as a URI string. + +.PP +The string cannot have spaces or other characters which are +meaningful to getopt(3) and the shell will strip off quotes and +other characters. +So the string is assumed to be in URI style and is translated. +In other words, to match 'a b' make the -S string 'a%20b' +Instead of escaping " quotes in the string, type %25, as in + 'a "b' should be typed 'a%20%25b' +(the ' are for exposition here, not part of the strings). +Any characters can be typed in URI style, not just characters +which are problematic to the shell or getopt. +.PP +The -S any= and -S regex= options are only usable +if the library functions required are found at configure time. +.PP +The -W option is a modifier to the -S option, and +increases the amount of output -W prints. +Now we show the -W in context with a -S option. + +.TP +.B \-S match=string1 -W +Prints the parent tree and the children tree for the +DIEs that -S matches. + +.TP +.B \-S match=string2 -Wp +Prints the parent tree for the DIEs that -S matches. + +.TP +.B \-S match=string3 -Wc +Prints the parent tree for the DIEs that -S matches. + +.SH OTHER OPTIONS + +.TP +.B \-# number +This option controls internal debugging output, +higher numbers mean more debug actions. See the source code. + + +.TP +.B \-x name=/p/a/t/h.conf +The file path given is the name of a file assumed to be +a dwarfdump.conf-like file. +The file path is read as a URI string. + +.TP +.B \-x abi=ppc +Selects the abi (from a dwarfdump.conf file) to be used in +printing frame information (here using ppc as an example). +The abi is read as a URI string. + +.TP +.B \-P +When checking this adds the list of compilation-unit names +seen for each producer-compiler to the printed checking results. +.TP +.B \-q +When a URI is found and translated while reading +the command line, be quiet about +the URI translation. That is, don't print the +original and translated option strings. + +.TP +.B \-E +Turns on printing object-internal header data for some +systems (for Unix/Linux does nothing). + +.TP +.B \-u cuname +Turns on selective printing of DIEs (printing like -i). +Only the DIEs for a compilation unit that match the +name provided are printed. +If the compilation unit is ./a/b/c.c +the 'cuname' you provide should be c.c as the characters +through the final path-separating / are ignored. +If 'cuname' begins with a / then the entire name string +of a compilation unit must match 'cuname'. +The 'cuname' is read as a URI string. + +.TP +.B \-U +Turn off the URI interpretation of the command line +strings entirely. Must be be on the command line before +any URI strings encountered to be fully effective. + +.TP +.B \-z +No longer suported. + + +.SH FILES +dwarfdump + +dwarfdump.conf + +./dwarfdump.conf + +$(HOME)/.dwarfdump.conf + +$(HOME)/dwarfdump.conf + +<install-prefix>/lib/dwarfdump.conf +.SH NOTES +In some cases compilers use DW_FORM_data1 (for example) +and in such cases the signedness of the value must be taken +from context. Rather than attempt to determine the +context, dwarfdump prints the value with both signednesses +whenever there is ambiguity about the correct interpretation. +For example, +"DW_AT_const_value 176(as signed = -80)". +For normal DWARF consumers that correctly and fully +evaluate all attributes there is no ambiguity of signedness: +the ambiguity for dwarfdump is due to dwarfdump evaluating +DIEs in a simple order and not keeping track of much context. +.SH BUGS +Support for DWARF3 is being completed but may not be complete. diff --git a/dwarfdump/dwarfdump.c b/dwarfdump/dwarfdump.c new file mode 100644 index 0000000..f8bc309 --- /dev/null +++ b/dwarfdump/dwarfdump.c @@ -0,0 +1,2357 @@ +/* + Copyright (C) 2000,2002,2004,2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. + Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. + + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + +$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/dwarfdump.c,v 1.48 2006/04/18 18:05:57 davea Exp $ */ + +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + +#include "globals.h" +/* for 'open' */ +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <limits.h> +#include <unistd.h> /* For getopt */ +#include "makename.h" +#include "dwconf.h" +#include "common.h" +#include "esb.h" /* For flexible string buffer. */ + +#ifdef WIN32 +extern int elf_open(char *name,int mode); +#endif + +#define DWARFDUMP_VERSION " Tue Apr 10 11:43:32 PDT 2012 " + +extern char *optarg; + + +#define OKAY 0 +#define BYTES_PER_INSTRUCTION 4 + +static const char* process_args(int argc, char *argv[]); + +char * program_name; +static int check_error = 0; + +/* The type of Bucket. */ +#define KIND_RANGES_INFO 1 +#define KIND_SECTIONS_INFO 2 +#define KIND_VISITED_INFO 3 + +/* pRangesInfo records the DW_AT_high_pc and DW_AT_low_pc + and is used to check that line range info falls inside + the known valid ranges. The data is per CU, and is + reset per CU in tag_specific_checks_setup(). */ +Bucket_Group *pRangesInfo = NULL; + +/* pLinkonceInfo records data about the link once sections. + If a line range is not valid in the current CU it might + be valid in a linkonce section, this data records the + linkonce sections. So it is filled in when an + object file is read and remains unchanged for an entire + object file. */ +Bucket_Group *pLinkonceInfo = NULL; +/* pVisitedInfo records a recursive traversal of DIE attributes + DW_AT_specification DW_AT_abstract_origin DW_AT_type + that let DWARF refer (as in a general graph) to + arbitrary other DIEs. + These traversals use pVisitedInfo to + detect any compiler errors that introduce circular references. + Printing of the traversals is also done on request. + Entries are added and deleted as they are visited in + a depth-first traversal. */ +Bucket_Group *pVisitedInfo = NULL; + +/* Options to enable debug tracing */ +int nTrace[MAX_TRACE_LEVEL + 1]; + +/* Build section information */ +void build_linkonce_info(Dwarf_Debug dbg); +static const char * do_uri_translation(const char *s, + const char *context); +static void reset_overall_CU_error_data(); + +boolean info_flag = FALSE; +boolean use_old_dwarf_loclist = FALSE; /* This so both dwarf_loclist() + and dwarf_loclist_n() can be + tested. Defaults to new + dwarf_loclist_n() */ + +boolean line_flag = FALSE; +static boolean abbrev_flag = FALSE; +static boolean frame_flag = FALSE; /* .debug_frame section. */ +static boolean eh_frame_flag = FALSE; /* GNU .eh_frame section. */ +static boolean pubnames_flag = FALSE; +static boolean macinfo_flag = FALSE; +static boolean loc_flag = FALSE; +static boolean aranges_flag = FALSE; /* .debug_aranges section. */ +static boolean ranges_flag = FALSE; /* .debug_ranges section. */ +static boolean string_flag = FALSE; +static boolean reloc_flag = FALSE; +static boolean static_func_flag = FALSE; +static boolean static_var_flag = FALSE; +static boolean type_flag = FALSE; +static boolean weakname_flag = FALSE; +static boolean header_flag = FALSE; /* Control printing of Elf header. */ +boolean producer_children_flag = FALSE; /* List of CUs per compiler */ + +/* Bitmap for relocations. See globals.h for DW_SECTION_REL_DEBUG_RANGES etc.*/ +static unsigned reloc_map = 0; + +/* Start verbose at zero. verbose can + be incremented with -v but not decremented. */ +int verbose = 0; + +boolean dense = FALSE; +boolean ellipsis = FALSE; +boolean show_global_offsets = FALSE; /* Show global and relative offsets */ +boolean show_form_used = FALSE; +boolean display_offsets = TRUE; /* Emit offsets */ + +boolean check_abbrev_code = FALSE; +boolean check_pubname_attr = FALSE; +boolean check_reloc_offset = FALSE; +boolean check_attr_tag = FALSE; +boolean check_tag_tree = FALSE; +boolean check_type_offset = FALSE; +boolean check_decl_file = FALSE; +boolean check_lines = FALSE; +boolean check_fdes = FALSE; +boolean check_ranges = FALSE; +boolean check_aranges = FALSE; +boolean check_harmless = FALSE; +boolean check_abbreviations = FALSE; +boolean check_dwarf_constants = FALSE; +boolean check_di_gaps = FALSE; +boolean check_forward_decl = FALSE; +boolean check_self_references = FALSE; +boolean generic_1200_regs = FALSE; +boolean suppress_check_extensions_tables = FALSE; + +/* suppress_nested_name_search is a band-aid. + A workaround. A real fix for N**2 behavior is needed. +*/ +boolean suppress_nested_name_search = FALSE; +static boolean uri_options_translation = TRUE; +static boolean do_print_uri_in_input = TRUE; + + +/* break_after_n_units is mainly for testing. + It enables easy limiting of output size/running time + when one wants the output limited. + For example, + -H 2 + limits the -i output to 2 compilation units and + the -f or -F output to 2 FDEs and 2 CIEs. +*/ +int break_after_n_units = INT_MAX; + +boolean check_names = FALSE; +boolean check_verbose_mode = TRUE; /* During '-k' mode, display errors */ +boolean check_frames = FALSE; +boolean check_frames_extended = FALSE; /* Extensive frames check */ +boolean check_locations = FALSE; /* Location list check */ + +static boolean check_all_compilers = TRUE; +static boolean check_snc_compiler = FALSE; /* Check SNC compiler */ +static boolean check_gcc_compiler = FALSE; +static boolean print_summary_all = FALSE; + +#define COMPILER_TABLE_MAX 100 +typedef struct anc { + struct anc *next; + char *item; +} a_name_chain; + +/* Records information about compilers (producers) found in the + debug information, including the check results for several + categories (see -k option). */ +typedef struct { + const char *name; + boolean verified; + a_name_chain *cu_list; + a_name_chain *cu_last; + Dwarf_Check_Result results[LAST_CATEGORY]; +} Compiler; + +/* Record compilers whose CU names have been seen. + Full CU names recorded here, though only a portion + of the name may have been checked to cause the + compiler data to be entered here. + The +1 guarantees we do not overstep the array. +*/ +static Compiler compilers_detected[COMPILER_TABLE_MAX]; +static int compilers_detected_count = 0; + +/* compilers_targeted is a list of indications of compilers + on which we wish error checking (and the counts + of checks made and errors found). We do substring + comparisons, so the compilers_targeted name might be simply a + compiler version number or a short substring of a + CU producer name. + The +1 guarantees we do not overstep the array. +*/ +static Compiler compilers_targeted[COMPILER_TABLE_MAX]; +static int compilers_targeted_count = 0; +static int current_compiler = -1; + +static void reset_compiler_entry(Compiler *compiler); +static void PRINT_CHECK_RESULT(char *str, + Compiler *pCompiler, Dwarf_Check_Categories category); + + +/* The check and print flags here make it easy to + allow check-only or print-only. We no longer support + check-and-print in a single run. */ +boolean do_check_dwarf = FALSE; +boolean do_print_dwarf = FALSE; +boolean check_show_results = FALSE; /* Display checks results. */ +boolean record_dwarf_error = FALSE; /* A test has failed, this + is normally set FALSE shortly after being set TRUE, it is + a short-range hint we should print something we might not + otherwise print (under the circumstances). */ + + +/* These names make diagnostic messages more complete, the + fixed length is safe, though ultra long names will get + truncated. */ +char PU_name[COMPILE_UNIT_NAME_LEN]; +char CU_name[COMPILE_UNIT_NAME_LEN]; +char CU_producer[COMPILE_UNIT_NAME_LEN]; + +boolean seen_PU = FALSE; /* Detected a PU */ +boolean seen_CU = FALSE; /* Detected a CU */ +boolean need_CU_name = TRUE; /* Need CU name */ +boolean need_CU_base_address = TRUE; /* Need CU Base address */ +boolean need_CU_high_address = TRUE; /* Need CU High address */ +boolean need_PU_valid_code = TRUE; /* Need PU valid code */ + +boolean seen_PU_base_address = FALSE; /* Detected a Base address for PU */ +boolean seen_PU_high_address = FALSE; /* Detected a High address for PU */ +Dwarf_Addr PU_base_address = 0; /* PU Base address */ +Dwarf_Addr PU_high_address = 0; /* PU High address */ + +Dwarf_Off DIE_offset = 0; /* DIE offset in compile unit */ +Dwarf_Off DIE_overall_offset = 0; /* DIE offset in .debug_info */ + +/* These globals enable better error reporting. */ +Dwarf_Off DIE_CU_offset = 0; /* CU DIE offset in compile unit */ +Dwarf_Off DIE_CU_overall_offset = 0; /* CU DIE offset in .debug_info */ +int current_section_id = 0; /* Section being process */ + +Dwarf_Addr CU_base_address = 0; /* CU Base address */ +Dwarf_Addr CU_high_address = 0; /* CU High address */ + +Dwarf_Addr elf_max_address = 0; /* Largest representable address offset */ +Dwarf_Half elf_address_size = 0; /* Target pointer size */ + +/* Display parent/children when in wide format? */ +boolean display_parent_tree = FALSE; +boolean display_children_tree = FALSE; +int stop_indent_level = 0; + +/* Print search results in wide format? */ +boolean search_wide_format = FALSE; +/* -S option: strings for 'any' and 'match' */ +boolean search_is_on = FALSE; +const char *search_any_text = 0; +const char *search_match_text = 0; +const char *search_regex_text = 0; +#ifdef HAVE_REGEX +/* -S option: the compiled_regex */ +regex_t search_re; +#endif + + +/* These configure items are for the + frame data. We're pretty flexible in + the path to dwarfdump.conf . +*/ +static const char *config_file_path = 0; +static const char *config_file_abi = 0; +static char *config_file_defaults[] = { + "dwarfdump.conf", + "./dwarfdump.conf", + "HOME/.dwarfdump.conf", + "HOME/dwarfdump.conf", +#ifdef CONFPREFIX +/* See Makefile.in "libdir" and CFLAGS */ +/* We need 2 levels of macro to get the name turned into + the string we want. */ +#define STR2(s) # s +#define STR(s) STR2(s) + STR(CONFPREFIX) + "/dwarfdump.conf", +#else + "/usr/lib/dwarfdump.conf", +#endif + 0 +}; +static struct dwconf_s config_file_data; + +char cu_name[BUFSIZ]; +boolean cu_name_flag = FALSE; +Dwarf_Unsigned cu_offset = 0; + +Dwarf_Error err; + +static void suppress_check_dwarf() +{ + do_print_dwarf = TRUE; + if(do_check_dwarf) { + fprintf(stderr,"Warning: check flag turned off, " + "checking and printing are separate.\n"); + } + do_check_dwarf = FALSE; +} +static void suppress_print_dwarf() +{ + do_print_dwarf = FALSE; + do_check_dwarf = TRUE; +} + +static int process_one_file(Elf * elf, const char * file_name, int archive, + struct dwconf_s *conf); +static int +open_a_file(const char * name) +{ + /* Set to a file number that cannot be legal. */ + int f = -1; + +#if defined(__CYGWIN__) || defined(WIN32) + /* It is not possible to share file handles + between applications or DLLs. Each application has its own + file-handle table. For two applications to use the same file + using a DLL, they must both open the file individually. + Let the 'libelf' dll to open and close the file. */ + + /* For WIN32 open the file as binary */ + f = elf_open(name, O_RDONLY | O_BINARY); +#else + f = open(name, O_RDONLY); +#endif + return f; + +} +static void +close_a_file(int f) +{ + close(f); +} + +/* + Iterate through dwarf and print all info. +*/ +int +main(int argc, char *argv[]) +{ + const char * file_name = 0; + int f = 0; + Elf_Cmd cmd = 0; + Elf *arf = 0; + Elf *elf = 0; + int archive = 0; + +#ifdef WIN32 + /* Windows specific. */ + /* Redirect stderr to stdout. */ + /* Tried to use SetStdHandle, but it does not work properly. */ + //BOOL bbb = SetStdHandle(STD_ERROR_HANDLE,GetStdHandle(STD_OUTPUT_HANDLE)); + //_iob[2]._file = _iob[1]._file; + stderr->_file = stdout->_file; +#endif /* WIN32 */ + + print_version_details(argv[0],FALSE); + + (void) elf_version(EV_NONE); + if (elf_version(EV_CURRENT) == EV_NONE) { + (void) fprintf(stderr, "dwarfdump: libelf.a out of date.\n"); + exit(1); + } + + file_name = process_args(argc, argv); + + /* Because LibDwarf now generates some new warnings, + allow the user to hide them by using command line options */ + { + Dwarf_Cmdline_Options cmd; + cmd.check_verbose_mode = check_verbose_mode; + dwarf_record_cmdline_options(cmd); + } + print_args(argc,argv); + f = open_a_file(file_name); + if (f == -1) { + fprintf(stderr, "%s ERROR: can't open %s\n", program_name, + file_name); + return (FAILED); + } + + cmd = ELF_C_READ; + arf = elf_begin(f, cmd, (Elf *) 0); + if (elf_kind(arf) == ELF_K_AR) { + archive = 1; + } + + /* If we are checking .debug_line, .debug_ranges, .debug_aranges, + or .debug_loc build the tables containing + the pairs LowPC and HighPC. It is safer (and not + expensive) to build all + of these at once so mistakes in options do not lead + to coredumps (like -ka -p did once). */ + if (check_decl_file || check_ranges || check_locations || + do_check_dwarf || check_self_references) { + pRangesInfo = AllocateBucketGroup(KIND_RANGES_INFO); + pLinkonceInfo = AllocateBucketGroup(KIND_SECTIONS_INFO); + pVisitedInfo = AllocateBucketGroup(KIND_VISITED_INFO); + } + + while ((elf = elf_begin(f, cmd, arf)) != 0) { + Elf32_Ehdr *eh32; + +#ifdef HAVE_ELF64_GETEHDR + Elf64_Ehdr *eh64; +#endif /* HAVE_ELF64_GETEHDR */ + eh32 = elf32_getehdr(elf); + if (!eh32) { +#ifdef HAVE_ELF64_GETEHDR + /* not a 32-bit obj */ + eh64 = elf64_getehdr(elf); + if (!eh64) { + /* not a 64-bit obj either! */ + /* dwarfdump is almost-quiet when not an object */ + fprintf(stderr, "Can't process %s: unknown format\n",file_name); + check_error = 1; + } else { + process_one_file(elf, file_name, archive, + &config_file_data); + } +#endif /* HAVE_ELF64_GETEHDR */ + } else { + process_one_file(elf, file_name, archive, + &config_file_data); + } + cmd = elf_next(elf); + elf_end(elf); + } + elf_end(arf); + /* Trivial malloc space cleanup. */ + clean_up_die_esb(); + clean_up_syms_malloc_data(); + + if(pRangesInfo) { + ReleaseBucketGroup(pRangesInfo); + pRangesInfo = 0; + } + + if(pLinkonceInfo) { + ReleaseBucketGroup(pLinkonceInfo); + pLinkonceInfo = 0; + } + + if(pVisitedInfo) { + ReleaseBucketGroup(pVisitedInfo); + pVisitedInfo = 0; + } + +#ifdef HAVE_REGEX + if(search_regex_text) { + regfree(&search_re); + } +#endif + close_a_file(f); + if (check_error) + return FAILED; + else + return OKAY; +} + +void +print_any_harmless_errors(Dwarf_Debug dbg) +{ +#define LOCAL_PTR_ARY_COUNT 50 + /* We do not need to initialize the local array, + libdwarf does it. */ + const char *buf[LOCAL_PTR_ARY_COUNT]; + unsigned totalcount = 0; + unsigned i = 0; + unsigned printcount = 0; + int res = dwarf_get_harmless_error_list(dbg,LOCAL_PTR_ARY_COUNT,buf, + &totalcount); + if(res == DW_DLV_NO_ENTRY) { + return; + } + if(totalcount > 0) { + printf("\n*** HARMLESS ERROR COUNT: %u ***\n",totalcount); + } + for(i = 0 ; buf[i]; ++i) { + ++printcount; + DWARF_CHECK_COUNT(harmless_result,1); + DWARF_CHECK_ERROR(harmless_result,buf[i]); + } + if(totalcount > printcount) { + //harmless_result.checks += (totalcount - printcount); + DWARF_CHECK_COUNT(harmless_result,(totalcount - printcount)); + //harmless_result.errors += (totalcount - printcount); + DWARF_ERROR_COUNT(harmless_result,(totalcount - printcount)); + } +} + +static void +print_object_header(Elf *elf,Dwarf_Debug dbg) +{ +#ifdef WIN32 + /* Standard libelf has no function generating the names of the + encodings, but this libelf apparently does. */ + Elf_Ehdr_Literal eh_literals; + Elf32_Ehdr *eh32; +#ifdef HAVE_ELF64_GETEHDR + Elf64_Ehdr *eh64; +#endif /* HAVE_ELF64_GETEHDR */ + + eh32 = elf32_getehdr(elf); + if (eh32) { + /* Get literal strings for header fields */ + elf32_gethdr_literals(eh32,&eh_literals); + /* Print 32-bit obj header */ + printf("\nObject Header:\ne_ident:\n"); + printf(" File ID = %s\n",eh_literals.e_ident_file_id); + printf(" File class = %02x (%s)\n", + eh32->e_ident[EI_CLASS], eh_literals.e_ident_file_class); + printf(" Data encoding = %02x (%s)\n", + eh32->e_ident[EI_DATA], eh_literals.e_ident_data_encoding); + printf(" File version = %02x (%s)\n", + eh32->e_ident[EI_VERSION], eh_literals.e_ident_file_version); + printf(" OS ABI = %02x (%s) (%s)\n", eh32->e_ident[EI_OSABI], + eh_literals.e_ident_os_abi_s, eh_literals.e_ident_os_abi_l); + //printf(" ABI version = %02x (%s)\n", + // eh32->e_ident[EI_ABIVERSION], eh_literals.e_ident_abi_version); + printf("e_type : 0x%x (%s)\n", + eh32->e_type, eh_literals.e_type); + printf("e_machine: 0x%x (%s) (%s)\n", eh32->e_machine, + eh_literals.e_machine_s, eh_literals.e_machine_l); + printf("e_version: 0x%x\n", eh32->e_version); + //printf("e_entry = 0x%I64x\n", eh32->e_entry); + printf("e_flags : 0x%x\n", eh32->e_flags); + printf("e_phnum : 0x%x\n", eh32->e_phnum); + printf("e_shnum : 0x%x\n", eh32->e_shnum); + } + else { +#ifdef HAVE_ELF64_GETEHDR + /* not a 32-bit obj */ + eh64 = elf64_getehdr(elf); + if (eh64) { + /* Get literal strings for header fields */ + elf64_gethdr_literals(eh64,&eh_literals); + /* Print 64-bit obj header */ + printf("\nObject Header:\ne_ident:\n"); + printf(" File ID = %s\n",eh_literals.e_ident_file_id); + printf(" File class = %02x (%s)\n", + eh64->e_ident[EI_CLASS], eh_literals.e_ident_file_class); + printf(" Data encoding = %02x (%s)\n", + eh64->e_ident[EI_DATA], eh_literals.e_ident_data_encoding); + printf(" File version = %02x (%s)\n", + eh64->e_ident[EI_VERSION], eh_literals.e_ident_file_version); + printf(" OS ABI = %02x (%s) (%s)\n", eh64->e_ident[EI_OSABI], + eh_literals.e_ident_os_abi_s, eh_literals.e_ident_os_abi_l); + //printf(" ABI version = %02x (%s)\n", + // eh64->e_ident[EI_ABIVERSION], eh_literals.e_ident_abi_version); + printf("e_type : 0x%x (%s)\n", + eh64->e_type, eh_literals.e_type); + printf("e_machine: 0x%x (%s) (%s)\n", eh64->e_machine, + eh_literals.e_machine_s, eh_literals.e_machine_l); + printf("e_version: 0x%x\n", eh64->e_version); + //printf("e_entry = 0x%I64x\n", eh64->e_entry); + printf("e_flags : 0x%x\n", eh64->e_flags); + printf("e_phnum : 0x%x\n", eh64->e_phnum); + printf("e_shnum : 0x%x\n", eh64->e_shnum); + } +#endif /* HAVE_ELF64_GETEHDR */ + } +#endif /* WIN32 */ +} + +/* Print checks and errors for a specific compiler */ +static void +print_specific_checks_results(Compiler *pCompiler) +{ + fprintf(stderr, "\nDWARF CHECK RESULT\n"); + fprintf(stderr, "<item> <checks> <errors>\n"); + if (check_pubname_attr) { + PRINT_CHECK_RESULT("pubname_attr", pCompiler, pubname_attr_result); + } + if (check_attr_tag) { + PRINT_CHECK_RESULT("attr_tag", pCompiler, attr_tag_result); + } + if (check_tag_tree) { + PRINT_CHECK_RESULT("tag_tree", pCompiler, tag_tree_result); + } + if (check_type_offset) { + PRINT_CHECK_RESULT("type_offset", pCompiler, type_offset_result); + } + if (check_decl_file) { + PRINT_CHECK_RESULT("decl_file", pCompiler, decl_file_result); + } + if (check_ranges) { + PRINT_CHECK_RESULT("ranges", pCompiler, ranges_result); + } + if (check_lines) { + PRINT_CHECK_RESULT("line_table", pCompiler, lines_result); + } + if (check_fdes) { + PRINT_CHECK_RESULT("fde table", pCompiler, fde_duplication); + } + if (check_aranges) { + PRINT_CHECK_RESULT("aranges", pCompiler, aranges_result); + } + + if (check_names) { + PRINT_CHECK_RESULT("names",pCompiler, names_result); + } + if (check_frames) { + PRINT_CHECK_RESULT("frames",pCompiler, frames_result); + } + if (check_locations) { + PRINT_CHECK_RESULT("locations",pCompiler, locations_result); + } + + if(check_harmless) { + PRINT_CHECK_RESULT("harmless_errors", pCompiler, harmless_result); + } + + if (check_abbreviations) { + PRINT_CHECK_RESULT("abbreviations", pCompiler, abbreviations_result); + } + + if (check_dwarf_constants) { + PRINT_CHECK_RESULT("dwarf_constants", + pCompiler, dwarf_constants_result); + } + + if (check_di_gaps) { + PRINT_CHECK_RESULT("debug_info_gaps", pCompiler, di_gaps_result); + } + + if (check_forward_decl) { + PRINT_CHECK_RESULT("forward_declarations", + pCompiler, forward_decl_result); + } + + if (check_self_references) { + PRINT_CHECK_RESULT("self_references", + pCompiler, self_references_result); + } + + PRINT_CHECK_RESULT("** Summarize **",pCompiler, total_check_result); +} + +static int +qsort_compare_compiler(const void *elem1,const void *elem2) +{ + Compiler cmp1 = *(Compiler *)elem1; + Compiler cmp2 = *(Compiler *)elem2; + int cnt1 = cmp1.results[total_check_result].errors; + int cnt2 = cmp2.results[total_check_result].errors; + int sc = 0; + + if (cnt1 < cnt2) { + return 1; + } else if (cnt1 > cnt2) { + return -1; + } + /* When error counts match, sort on name. */ + sc = strcmp(cmp2.name,cmp1.name); + return sc; +} + +/* Print a summary of checks and errors */ +static void +print_checks_results() +{ + int index = 0; + Compiler *pCompilers; + Compiler *pCompiler; + + fflush(stdout); + + /* Sort based on errors detected; the first entry is reserved */ + pCompilers = &compilers_detected[1]; + qsort((void *)pCompilers, compilers_detected_count, + sizeof(Compiler),qsort_compare_compiler); + + /* Print list of CUs for each compiler detected */ + if (producer_children_flag) { + + a_name_chain *nc = 0; + a_name_chain *nc_next = 0; + int count = 0; + int total = 0; + + fprintf(stderr,"\n*** CU NAMES PER COMPILER ***\n"); + for (index = 1; index <= compilers_detected_count; ++index) { + pCompiler = &compilers_detected[index]; + fprintf(stderr,"\n%02d: %s\n",index,pCompiler->name); + count = 0; + for (nc = pCompiler->cu_list; nc; nc = nc_next) { + fprintf(stderr,"\n %02d: '%s'",++count,nc->item); + nc_next = nc->next; + free(nc); + } + total += count; + fprintf(stderr,"\n"); + } + fprintf(stderr,"\nDetected %d CU names\n",total); + } + + /* Print error report only if errors have been detected */ + /* Print error report if the -kd option */ + if ((do_check_dwarf && check_error) || check_show_results) { + int count = 0; + int compilers_not_detected = 0; + int compilers_verified = 0; + + /* Find out how many compilers have been verified. */ + for (index = 1; index <= compilers_detected_count; ++index) { + if (compilers_detected[index].verified) { + ++compilers_verified; + } + } + /* Find out how many compilers have been not detected. */ + for (index = 1; index <= compilers_targeted_count; ++index) { + if (!compilers_targeted[index].verified) { + ++compilers_not_detected; + } + } + + /* Print compilers detected list */ + fprintf(stderr, + "\n%d Compilers detected:\n",compilers_detected_count); + for (index = 1; index <= compilers_detected_count; ++index) { + pCompiler = &compilers_detected[index]; + fprintf(stderr,"%02d: %s\n",index,pCompiler->name); + } + + /* Print compiler list specified by the user with the + '-c<str>', that were not detected. */ + if (compilers_not_detected) { + count = 0; + fprintf(stderr, + "\n%d Compilers not detected:\n",compilers_not_detected); + for (index = 1; index <= compilers_targeted_count; ++index) { + if (!compilers_targeted[index].verified) { + fprintf(stderr, + "%02d: '%s'\n", + ++count,compilers_targeted[index].name); + } + } + } + + count = 0; + fprintf(stderr,"\n%d Compilers verified:\n",compilers_verified); + for (index = 1; index <= compilers_detected_count; ++index) { + pCompiler = &compilers_detected[index]; + if (pCompiler->verified) { + fprintf(stderr,"%02d: errors = %5d, %s\n", + ++count, + pCompiler->results[total_check_result].errors, + pCompiler->name); + } + } + + /* Print summary if we have verified compilers or + if the -kd option used. */ + if (compilers_verified || check_show_results) { + /* Print compilers detected summary*/ + if (print_summary_all) { + count = 0; + fprintf(stderr,"\n*** ERRORS PER COMPILER ***\n"); + for (index = 1; index <= compilers_detected_count; ++index) { + pCompiler = &compilers_detected[index]; + if (pCompiler->verified) { + fprintf(stderr,"%02d: %s\n", + ++count,pCompiler->name); + print_specific_checks_results(pCompiler); + } + } + } + + /* Print general summary (all compilers checked) */ + fprintf(stderr,"\n*** TOTAL ERRORS FOR ALL COMPILERS ***\n"); + print_specific_checks_results(&compilers_detected[0]); + } + } +} + +/* + Given a file which we know is an elf file, process + the dwarf data. + +*/ +static int +process_one_file(Elf * elf, const char * file_name, int archive, + struct dwconf_s *config_file_data) +{ + Dwarf_Debug dbg; + int dres; + + dres = dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL, &dbg, &err); + if (dres == DW_DLV_NO_ENTRY) { + printf("No DWARF information present in %s\n", file_name); + return 0; + } + if (dres != DW_DLV_OK) { + print_error(dbg, "dwarf_elf_init", dres, err); + } + + if (archive) { + Elf_Arhdr *mem_header = elf_getarhdr(elf); + + printf("\narchive member \t%s\n", + mem_header ? mem_header->ar_name : ""); + } + dwarf_set_frame_rule_initial_value(dbg, + config_file_data->cf_initial_rule_value); + dwarf_set_frame_rule_table_size(dbg, + config_file_data->cf_table_entry_count); + dwarf_set_frame_cfa_value(dbg, + config_file_data->cf_cfa_reg); + dwarf_set_frame_same_value(dbg, + config_file_data->cf_same_val); + dwarf_set_frame_undefined_value(dbg, + config_file_data->cf_undefined_val); + if(config_file_data->cf_address_size) { + dwarf_set_default_address_size(dbg, config_file_data->cf_address_size); + } + dwarf_set_harmless_error_list_size(dbg,50); + + + /* Get address size and largest representable address */ + dres = dwarf_get_address_size(dbg,&elf_address_size,&err); + if (dres != DW_DLV_OK) { + print_error(dbg, "get_location_list", dres, err); + } + + elf_max_address = (elf_address_size == 8 ) ? + 0xffffffffffffffffULL : 0xffffffff; + + /* Get .text and .debug_ranges info if in check mode */ + if (do_check_dwarf) { + Dwarf_Addr lower = 0; + Dwarf_Addr upper = 0; + Dwarf_Unsigned size = 0; + int res = 0; + res = dwarf_get_section_info_by_name(dbg,".text",&lower,&size,&err); + if (DW_DLV_OK == res) { + upper = lower + size; + } + + /* Set limits for Ranges Information */ + if (pRangesInfo) { + SetLimitsBucketGroup(pRangesInfo,lower,upper); + } + + /* Build section information */ + build_linkonce_info(dbg); + } + + if (header_flag) { + print_object_header(elf,dbg); + } + reset_overall_CU_error_data(); + if (info_flag || line_flag || cu_name_flag || search_is_on || + producer_children_flag) { + print_infos(dbg,TRUE); + reset_overall_CU_error_data(); + print_infos(dbg,FALSE); + } + if (pubnames_flag) { + reset_overall_CU_error_data(); + print_pubnames(dbg); + } + if (macinfo_flag) { + reset_overall_CU_error_data(); + print_macinfo(dbg); + } + if (loc_flag) { + reset_overall_CU_error_data(); + print_locs(dbg); + } + if (abbrev_flag) { + reset_overall_CU_error_data(); + print_abbrevs(dbg); + } + if (string_flag) { + reset_overall_CU_error_data(); + print_strings(dbg); + } + if (aranges_flag) { + reset_overall_CU_error_data(); + print_aranges(dbg); + } + if (ranges_flag) { + reset_overall_CU_error_data(); + print_ranges(dbg); + } + if (frame_flag || eh_frame_flag) { + reset_overall_CU_error_data(); + current_cu_die_for_print_frames = 0; + print_frames(dbg, frame_flag, eh_frame_flag, config_file_data); + } + if (static_func_flag) { + reset_overall_CU_error_data(); + print_static_funcs(dbg); + } + if (static_var_flag) { + reset_overall_CU_error_data(); + print_static_vars(dbg); + } + /* DWARF_PUBTYPES is the standard typenames dwarf section. + SGI_TYPENAME is the same concept but is SGI specific ( it was + defined 10 years before dwarf pubtypes). */ + + if (type_flag) { + reset_overall_CU_error_data(); + print_types(dbg, DWARF_PUBTYPES); + reset_overall_CU_error_data(); + print_types(dbg, SGI_TYPENAME); + } + if (weakname_flag) { + reset_overall_CU_error_data(); + print_weaknames(dbg); + } + if (reloc_flag) { + reset_overall_CU_error_data(); + print_relocinfo(dbg, reloc_map); + } + /* The right time to do this is unclear. But we need to do it. */ + print_any_harmless_errors(dbg); + + /* Print error report only if errors have been detected */ + /* Print error report if the -kd option */ + print_checks_results(); + + dres = dwarf_finish(dbg, &err); + if (dres != DW_DLV_OK) { + print_error(dbg, "dwarf_finish", dres, err); + } + + printf("\n"); + fflush(stderr); + return 0; + +} + +/* Do printing of most sections. + Do not do detailed checking. +*/ +static void +do_all() +{ + info_flag = line_flag = frame_flag = TRUE; + pubnames_flag = macinfo_flag = TRUE; + aranges_flag = TRUE; + /* Do not do + loc_flag = TRUE + abbrev_flag = TRUE; + ranges_flag = TRUE; + because nothing in + the DWARF spec guarantees the sections are free of random bytes + in areas not referenced by .debug_info */ + string_flag = TRUE; + /* Do not do + reloc_flag = TRUE; + as print_relocs makes no sense for non-elf dwarfdump users. */ + static_func_flag = static_var_flag = TRUE; + type_flag = weakname_flag = TRUE; + header_flag = TRUE; /* Dump header info */ +} + + +static const char *usage_text[] = { +"options:\t-a\tprint all .debug_* sections", +"\t\t-b\tprint abbrev section", +"\t\t-c\tprint loc section", +"\t\t-c<str>\tcheck only specific compiler objects", +"\t\t \t <str> is described by 'DW_AT_producer'. Examples:", +"\t\t \t -cg check only GCC compiler objects", +"\t\t \t -cs check only SNC compiler objects", +"\t\t \t -c'350.1' check only compiler objects with 350.1 in the CU name", +"\t\t-C\tactivate printing (with -i) of warnings about", +"\t\t\tcertain common extensions of DWARF.", +"\t\t-d\tdense: one line per entry (info section only)", +"\t\t-D\tdo not show offsets", /* Do not show any offsets */ +"\t\t-e\tellipsis: short names for tags, attrs etc.", +"\t\t-E\tprint object Header information", +"\t\t-f\tprint dwarf frame section", +"\t\t-F\tprint gnu .eh_frame section", +"\t\t-g\t(use incomplete loclist support)", +"\t\t-G\tshow global die offsets", +"\t\t-h\tprint IRIX exception tables (unsupported)", +"\t\t-H <num>\tlimit output to the first <num> major units", +"\t\t\t example: to stop after <num> compilation units", +"\t\t-i\tprint info section", +"\t\t-k[abcdeEfFgilmMnrRsStx[e]y] check dwarf information", +"\t\t a\tdo all checks", +"\t\t b\tcheck abbreviations", /* Check abbreviations */ +"\t\t c\texamine DWARF constants", /* Check for valid DWARF constants */ +"\t\t d\tshow check results", /* Show check results */ +"\t\t e\texamine attributes of pubnames", +"\t\t E\tignore DWARF extensions", /* Ignore DWARF extensions */ +"\t\t f\texamine frame information (use with -f or -F)", +"\t\t F\texamine integrity of files-lines attributes", /* Files-Lines integrity */ +"\t\t g\tcheck debug info gaps", /* Check for debug info gaps */ +"\t\t i\tdisplay summary for all compilers", /* Summary all compilers */ +"\t\t l\tcheck location list (.debug_loc)", /* Location list integrity */ +"\t\t m\tcheck ranges list (.debug_ranges)", /* Ranges list integrity */ +"\t\t M\tcheck ranges list (.debug_aranges)",/* Aranges list integrity */ +"\t\t n\texamine names in attributes", /* Check for valid names */ +"\t\t r\texamine tag-attr relation", +"\t\t R\tcheck forward references to DIEs (declarations)", /* Check DW_AT_specification references */ +"\t\t s\tperform checks in silent mode", +"\t\t S\tcheck self references to DIEs", +"\t\t t\texamine tag-tag relations", +"\t\t x\tbasic frames check (.eh_frame, .debug_frame)", +"\t\t xe\textensive frames check (.eh_frame, .debug_frame)", +"\t\t y\texamine type info", +"\t\t\tUnless -C option given certain common tag-attr and tag-tag", +"\t\t\textensions are assumed to be ok (not reported).", +"\t\t-l\tprint line section", +"\t\t-m\tprint macinfo section", +"\t\t-M\tprint the form name for each attribute", +"\t\t-n\tsuppress frame information function name lookup", +"\t\t \t(when printing frame information from multi-gigabyte", +"\t\t \tobject files this option may save significant time).", +"\t\t-N\tprint ranges section", +"\t\t-o[liaprfoR]\tprint relocation info", +"\t\t \tl=line,i=info,a=abbrev,p=pubnames,r=aranges,f=frames,o=loc,R=Ranges", +"\t\t-p\tprint pubnames section", +"\t\t-P\tprint list of compile units per producer", /* List of CUs per compiler */ +"\t\t-Q\tsuppress printing section data", +"\t\t-r\tprint aranges section", +"\t\t-R\tPrint frame register names as r33 etc", +"\t\t \t and allow up to 1200 registers.", +"\t\t \t Print using a 'generic' register set.", +"\t\t-s\tprint string section", +"\t\t-S <option>=<text>\tsearch for <text> in attributes", +"\t\t \twith <option>:", +"\t\t \t-S any=<text>\tany <text>", +"\t\t \t-S match=<text>\tmatching <text>", +#ifdef HAVE_REGEX +"\t\t \t-S regex=<text>\tuse regular expression matching", +#endif +"\t\t \t (only one -S option allowed, any= and regex= ", +"\t\t \t only usable if the functions required are ", +"\t\t \t found at configure time)", +"\t\t-t[afv] static: ", +"\t\t a\tprint both sections", +"\t\t f\tprint static func section", +"\t\t v\tprint static var section", +"\t\t-u<file> print sections only for specified file", +"\t\t-v\tverbose: show more information", +"\t\t-vv verbose: show even more information", +"\t\t-V print version information", +"\t\t-x name=<path>\tname dwarfdump.conf", +"\t\t-x abi=<abi>\tname abi in dwarfdump.conf", +"\t\t-w\tprint weakname section", +"\t\t-W\tprint parent and children tree (wide format) with the -S option", +"\t\t-Wp\tprint parent tree (wide format) with the -S option", +"\t\t-Wc\tprint children tree (wide format) with the -S option", +"\t\t-y\tprint type section", +"", + +0 +}; + + +/* Remove matching leading/trailing quotes. + Does not alter the passed in string. + If quotes removed does a makename on a modified string. */ +static const char * +remove_quotes_pair(const char *text) +{ + static char single_quote = '\''; + static char double_quote = '\"'; + char quote = 0; + const char *p = text; + int len = strlen(text); + + if (len < 2) { + return p; + } + + /* Compare first character with ' or " */ + if (p[0] == single_quote) { + quote = single_quote; + } else { + if (p[0] == double_quote) { + quote = double_quote; + } + else { + return p; + } + } + { + if (p[len - 1] == quote) { + char *altered = calloc(1,len+1); + const char *str2 = 0; + strcpy(altered,p+1); + altered[len - 2] = '\0'; + str2 = makename(altered); + free(altered); + return str2; + } + } + return p; +} + +/* process arguments and return object filename */ +static const char * +process_args(int argc, char *argv[]) +{ + extern int optind; + int c = 0; + boolean usage_error = FALSE; + int oarg = 0; + + program_name = argv[0]; + + suppress_check_dwarf(); + if (argv[1] != NULL && argv[1][0] != '-') { + do_all(); + } + + /* j unused */ + while ((c = getopt(argc, argv, + "#:abc::CdDeEfFgGhH:ik:lmMnNo::pPqQrRsS:t:u:UvVwW::x:yz")) != EOF) { + + switch (c) { + /* Internal debug level setting. */ + case '#': + { + int nTraceLevel = atoi(optarg); + if (nTraceLevel > 0 && nTraceLevel <= MAX_TRACE_LEVEL) { + nTrace[nTraceLevel] = 1; + } + break; + } + case 'M': + show_form_used = TRUE; + break; + case 'x': /* Select abi/path to use */ + { + const char *path = 0; + const char *abi = 0; + /* -x name=<path> meaning name dwarfdump.conf file -x + abi=<abi> meaning select abi from dwarfdump.conf + file. Must always select abi to use dwarfdump.conf */ + if (strncmp(optarg, "name=", 5) == 0) { + path = do_uri_translation(&optarg[5],"-x name="); + if (strlen(path) < 1) { + goto badopt; + } + config_file_path = path; + } else if (strncmp(optarg, "abi=", 4) == 0) { + abi = do_uri_translation(&optarg[4],"-x abi="); + if (strlen(abi) < 1) { + goto badopt; + } + config_file_abi = abi; + break; + } else { + badopt: + fprintf(stderr, "-x name=<path-to-conf> \n"); + fprintf(stderr, " and \n"); + fprintf(stderr, "-x abi=<abi-in-conf> \n"); + fprintf(stderr, "are legal, not -x %s\n", optarg); + usage_error = TRUE; + break; + } + } + break; + case 'C': + suppress_check_extensions_tables = TRUE; + break; + case 'g': + use_old_dwarf_loclist = TRUE; + info_flag = TRUE; + suppress_check_dwarf(); + break; + case 'i': + info_flag = TRUE; + suppress_check_dwarf(); + break; + case 'n': + suppress_nested_name_search = TRUE; + break; + case 'l': + line_flag = TRUE; + suppress_check_dwarf(); + break; + case 'f': + frame_flag = TRUE; + suppress_check_dwarf(); + break; + case 'H': + { + int break_val = atoi(optarg); + if(break_val > 0) { + break_after_n_units = break_val; + } + } + break; + case 'F': + eh_frame_flag = TRUE; + suppress_check_dwarf(); + break; + case 'b': + abbrev_flag = TRUE; + suppress_check_dwarf(); + break; + case 'p': + pubnames_flag = TRUE; + suppress_check_dwarf(); + break; + case 'P': + /* List of CUs per compiler */ + producer_children_flag = TRUE; + break; + case 'r': + aranges_flag = TRUE; + suppress_check_dwarf(); + break; + case 'N': + ranges_flag = TRUE; + suppress_check_dwarf(); + break; + case 'R': + generic_1200_regs = TRUE; + break; + case 'm': + macinfo_flag = TRUE; + suppress_check_dwarf(); + break; + case 'c': + /* Specify compiler name. */ + if (optarg) { + if ('s' == optarg[0]) { + /* -cs : Check SNC compiler */ + check_snc_compiler = TRUE; + check_all_compilers = FALSE; + } + else { + if ('g' == optarg[0]) { + /* -cg : Check GCC compiler */ + check_gcc_compiler = TRUE; + check_all_compilers = FALSE; + } + else { + /* Assume a compiler version to check, + most likely a substring of a compiler name. */ + if ((compilers_targeted_count+1) < COMPILER_TABLE_MAX) { + Compiler *pCompiler = 0; + const char *cmp = 0; + cmp = do_uri_translation(optarg,"-c<compiler name>"); + /* First compiler at position [1] */ + compilers_targeted_count++; + pCompiler = &compilers_targeted[compilers_targeted_count]; + reset_compiler_entry(pCompiler); + pCompiler->name = cmp; + check_all_compilers = FALSE; + } else { + fprintf(stderr, "Compiler table max %d exceeded, " + "limiting the tracked compilers to %d\n", + COMPILER_TABLE_MAX,COMPILER_TABLE_MAX); + } + } + } + } else { + loc_flag = TRUE; + suppress_check_dwarf(); + } + break; + case 'Q': + /* Q suppresses section data printing. */ + do_print_dwarf = FALSE; + break; + case 'q': + /* Suppress uri-did-transate notification */ + do_print_uri_in_input = FALSE; + break; + case 's': + string_flag = TRUE; + suppress_check_dwarf(); + break; + case 'S': + /* -S option: strings for 'any' and 'match' */ + { + boolean err = TRUE; + search_is_on = TRUE; + const char *tempstr = 0; + /* -S text */ + if (strncmp(optarg,"match=",6) == 0) { + + search_match_text = makename(&optarg[6]); + tempstr = remove_quotes_pair(search_match_text); + search_match_text = do_uri_translation(tempstr,"-S match="); + if (strlen(search_match_text) > 0) { + err = FALSE; + } + } + else { + if (strncmp(optarg,"any=",4) == 0) { + search_any_text = makename(&optarg[4]); + tempstr = remove_quotes_pair(search_any_text); + search_any_text = do_uri_translation(tempstr,"-S any="); + if (strlen(search_any_text) > 0) { + err = FALSE; + } + } +#ifdef HAVE_REGEX + else { + if (strncmp(optarg,"regex=",6) == 0) { + search_regex_text = makename(&optarg[6]); + tempstr = remove_quotes_pair( + search_regex_text); + search_regex_text = do_uri_translation(tempstr, + "-S regex="); + if (strlen(search_regex_text) > 0) { + if (regcomp(&search_re,search_regex_text, + REG_EXTENDED)) { + fprintf(stderr, + "regcomp: unable to compile %s\n", + search_regex_text); + } + else { + err = FALSE; + } + } + } + } +#endif /* HAVE_REGEX */ + } + if (err) { + fprintf(stderr,"-S any=<text> or -S match=<text> or -S regex=<text>\n"); + fprintf(stderr, "is allowed, not -S %s\n",optarg); + usage_error = TRUE; + } + } + break; + + case 'a': + suppress_check_dwarf(); + do_all(); + break; + case 'v': + verbose++; + break; + case 'V': + /* Display dwarfdump compilation date and time */ + print_version_details(argv[0],TRUE); + exit(OKAY); + break; + case 'd': + /* This is sort of useless unless printing, + but harmless, so we do not insist we + are printing with suppress_check_dwarf(). */ + dense = TRUE; + break; + case 'D': + /* Do not emit offset in output */ + display_offsets = FALSE; + break; + case 'e': + suppress_check_dwarf(); + ellipsis = TRUE; + break; + case 'E': + /* Object Header information (but maybe really print) */ + header_flag = TRUE; + break; + case 'o': + reloc_flag = TRUE; + if (optarg) { + switch (optarg[0]) { + case 'i': + reloc_map |= (1 << DW_SECTION_REL_DEBUG_INFO); break; + reloc_map |= (1 << DW_SECTION_REL_DEBUG_TYPES); break; + case 'l': reloc_map |= (1 << DW_SECTION_REL_DEBUG_LINE); break; + case 'p': reloc_map |= (1 << DW_SECTION_REL_DEBUG_PUBNAMES); break; + /* Case a has no effect, no relocations can point out + of the abbrev section. */ + case 'a': reloc_map |= (1 << DW_SECTION_REL_DEBUG_ABBREV); break; + case 'r': reloc_map |= (1 << DW_SECTION_REL_DEBUG_ARANGES); break; + case 'f': reloc_map |= (1 << DW_SECTION_REL_DEBUG_FRAME); break; + case 'o': reloc_map |= (1 << DW_SECTION_REL_DEBUG_LOC); break; + case 'R': reloc_map |= (1 << DW_SECTION_REL_DEBUG_RANGES); break; + default: usage_error = TRUE; break; + } + } else { + /* Display all relocs */ + reloc_map = 0x00ff; + } + break; + case 'k': + suppress_print_dwarf(); + oarg = optarg[0]; + switch (oarg) { + case 'a': + check_pubname_attr = TRUE; + check_attr_tag = TRUE; + check_tag_tree = check_type_offset = TRUE; + check_names = TRUE; + pubnames_flag = info_flag = TRUE; + check_decl_file = TRUE; + check_frames = TRUE; + /*check_frames_extended = FALSE; */ + check_locations = TRUE; + frame_flag = eh_frame_flag = TRUE; + check_ranges = TRUE; + check_lines = TRUE; + check_fdes = TRUE; + check_harmless = TRUE; + check_aranges = TRUE; + aranges_flag = TRUE; /* Aranges section */ + check_abbreviations = TRUE; + check_dwarf_constants = TRUE; + check_di_gaps = TRUE; /* Check debug info gaps */ + check_forward_decl = TRUE; /* Check forward declarations */ + check_self_references = TRUE; /* Check self references */ + break; + /* Abbreviations */ + case 'b': + check_abbreviations = TRUE; + info_flag = TRUE; + break; + /* DWARF constants */ + case 'c': + check_dwarf_constants = TRUE; + info_flag = TRUE; + break; + /* Display check results */ + case 'd': + check_show_results = TRUE; + break; + case 'e': + check_pubname_attr = TRUE; + pubnames_flag = TRUE; + check_harmless = TRUE; + check_fdes = TRUE; + break; + case 'f': + check_harmless = TRUE; + check_fdes = TRUE; + break; + /* files-lines */ + case 'F': + check_decl_file = TRUE; + check_lines = TRUE; + info_flag = TRUE; + break; + /* Check debug info gaps */ + case 'g': + check_di_gaps = TRUE; + info_flag = TRUE; + break; + /* Locations list */ + case 'l': + check_locations = TRUE; + info_flag = TRUE; + loc_flag = TRUE; + break; + /* Ranges */ + case 'm': + check_ranges = TRUE; + info_flag = TRUE; + break; + /* Aranges */ + case 'M': + check_aranges = TRUE; + aranges_flag = TRUE; + break; + /* invalid names */ + case 'n': + check_names = TRUE; + info_flag = TRUE; + break; + case 'r': + check_attr_tag = TRUE; + info_flag = TRUE; + check_harmless = TRUE; + break; + /* forward declarations in DW_AT_specification */ + case 'R': + check_forward_decl = TRUE; + info_flag = TRUE; + break; + /* Check verbose mode */ + case 's': + check_verbose_mode = FALSE; + break; + /* self references in: + DW_AT_specification, DW_AT_type, DW_AT_abstract_origin */ + case 'S': + check_self_references = TRUE; + info_flag = TRUE; + break; + case 't': + check_tag_tree = TRUE; + check_harmless = TRUE; + info_flag = TRUE; + break; + case 'y': + check_type_offset = TRUE; + check_harmless = TRUE; + check_decl_file = TRUE; + info_flag = TRUE; + check_ranges = TRUE; + check_aranges = TRUE; + break; + /* Summary for each compiler */ + case 'i': + print_summary_all = TRUE; + break; + /* Frames check */ + case 'x': + check_frames = TRUE; + frame_flag = TRUE; + eh_frame_flag = TRUE; + if (optarg[1]) { + if ('e' == optarg[1]) { + /* -xe : Extended frames check */ + check_frames = FALSE; + check_frames_extended = TRUE; + } else { + usage_error = TRUE; + } + } + break; + default: + usage_error = TRUE; + break; + } + break; + case 'u': { /* compile unit */ + const char *tstr = 0; + cu_name_flag = TRUE; + tstr = do_uri_translation(optarg,"-u<cu name>"); + safe_strcpy(cu_name,sizeof(cu_name), tstr,strlen(tstr)); + } + break; + case 'U': + uri_options_translation = FALSE; + break; + case 't': + oarg = optarg[0]; + switch (oarg) { + case 'a': + /* all */ + static_func_flag = static_var_flag = TRUE; + suppress_check_dwarf(); + break; + case 'f': + /* .debug_static_func */ + static_func_flag = TRUE; + suppress_check_dwarf(); + break; + case 'v': + /* .debug_static_var */ + static_var_flag = TRUE; + suppress_check_dwarf(); + break; + default: + usage_error = TRUE; + break; + } + break; + case 'y': /* .debug_types */ + suppress_check_dwarf(); + type_flag = TRUE; + break; + case 'w': /* .debug_weaknames */ + weakname_flag = TRUE; + suppress_check_dwarf(); + break; + case 'z': + fprintf(stderr, "-z is no longer supported:ignored\n"); + break; + case 'G': + show_global_offsets = TRUE; + break; + case 'W': + /* Search results in wide format */ + search_wide_format = TRUE; + if (optarg) { + if ('c' == optarg[0]) { + /* -Wc : Display children tree */ + display_children_tree = TRUE; + } else { + if ('p' == optarg[0]) { + /* -Wp : Display parent tree */ + display_parent_tree = TRUE; + } else { + usage_error = TRUE; + } + } + } + else { + /* -W : Display parent and children tree */ + display_children_tree = TRUE; + display_parent_tree = TRUE; + } + break; + default: + usage_error = TRUE; + break; + } + } + + init_conf_file_data(&config_file_data); + if (config_file_abi && generic_1200_regs) { + printf("Specifying both -R and -x abi= is not allowed. Use one " + "or the other. -x abi= ignored.\n"); + config_file_abi = FALSE; + } + if(generic_1200_regs) { + init_generic_config_1200_regs(&config_file_data); + } + if (config_file_abi && (frame_flag || eh_frame_flag)) { + int res = find_conf_file_and_read_config(config_file_path, + config_file_abi, + config_file_defaults, + &config_file_data); + + if (res > 0) { + printf + ("Frame not configured due to error(s). Giving up.\n"); + eh_frame_flag = FALSE; + frame_flag = FALSE; + } + } + if (usage_error || (optind != (argc - 1))) { + print_usage_message(program_name,usage_text); + exit(FAILED); + } + + if (do_check_dwarf) { + /* Reduce verbosity when checking (checking means checking-only). */ + verbose = 1; + } + return do_uri_translation(argv[optind],"file-to-process"); +} + + +void +print_error(Dwarf_Debug dbg, string msg, int dwarf_code, + Dwarf_Error err) +{ + print_error_and_continue(dbg,msg,dwarf_code,err); + dwarf_finish(dbg, &err); + exit(FAILED); +} +/* ARGSUSED */ +void +print_error_and_continue(Dwarf_Debug dbg, string msg, int dwarf_code, + Dwarf_Error err) +{ + fflush(stdout); + fflush(stderr); + + fprintf(stderr,"\n"); + + if (dwarf_code == DW_DLV_ERROR) { + string errmsg = dwarf_errmsg(err); + Dwarf_Unsigned myerr = dwarf_errno(err); + + fprintf(stderr, "%s ERROR: %s: %s (%lu)\n", + program_name, msg, errmsg, (unsigned long) myerr); + } else if (dwarf_code == DW_DLV_NO_ENTRY) { + fprintf(stderr, "%s NO ENTRY: %s: \n", program_name, msg); + } else if (dwarf_code == DW_DLV_OK) { + fprintf(stderr, "%s: %s \n", program_name, msg); + } else { + fprintf(stderr, "%s InternalError: %s: code %d\n", + program_name, msg, dwarf_code); + } + fflush(stderr); + + /* Display compile unit name */ + PRINT_CU_INFO(); +} + +/* Predicate function. Returns 'true' if the CU should + be skipped as the DW_AT_name of the CU + does not match the command-line-supplied + cu name. Else returns false.*/ +boolean +should_skip_this_cu(Dwarf_Debug dbg, Dwarf_Die cu_die, Dwarf_Error err) +{ + Dwarf_Half tag = 0; + Dwarf_Attribute attrib = 0; + Dwarf_Half theform = 0; + int dares = 0; + int tres = 0; + int fres = 0; + + tres = dwarf_tag(cu_die, &tag, &err); + if (tres != DW_DLV_OK) { + print_error(dbg, "dwarf_tag in aranges", + tres, err); + } + dares = dwarf_attr(cu_die, DW_AT_name, &attrib, + &err); + if (dares != DW_DLV_OK) { + print_error(dbg, "dwarf_attr arange" + " derived die has no name", + dares, err); + } + fres = dwarf_whatform(attrib, &theform, &err); + if (fres == DW_DLV_OK) { + if (theform == DW_FORM_string + || theform == DW_FORM_strp) { + char * temps = 0; + int sres = dwarf_formstring(attrib, &temps, + &err); + if (sres == DW_DLV_OK) { + char *p = temps; + if (cu_name[0] != '/') { + p = strrchr(temps, '/'); + if (p == NULL) { + p = temps; + } else { + p++; + } + } + /* Ignore case if Windows */ +#if WIN32 + if (stricmp(cu_name, p)) { + // skip this cu. + return TRUE; + } +#else + if (strcmp(cu_name, p)) { + // skip this cu. + return TRUE; + } +#endif /* WIN32 */ + + } else { + print_error(dbg, + "arange: string missing", + sres, err); + } + } + } else { + print_error(dbg, + "dwarf_whatform unexpected value", + fres, err); + } + dwarf_dealloc(dbg, attrib, DW_DLA_ATTR); + return FALSE; +} + +/* Returns the DW_AT_name of the CU */ +string +old_get_cu_name(Dwarf_Debug dbg, Dwarf_Die cu_die, Dwarf_Error err) +{ + static struct esb_s esb_attr_name; + Dwarf_Half tag; + Dwarf_Attribute attrib; + Dwarf_Half theform; + int dares; + int tres; + int fres; + + /* Initialize flexible string buffer */ + esb_empty_string(&esb_attr_name); + + tres = dwarf_tag(cu_die, &tag, &err); + if (tres != DW_DLV_OK) { + print_error(dbg, "dwarf_tag in aranges", + tres, err); + } + dares = dwarf_attr(cu_die, DW_AT_name, &attrib, + &err); + if (dares != DW_DLV_OK) { + print_error(dbg, "dwarf_attr arange" + " derived die has no name", + dares, err); + } + fres = dwarf_whatform(attrib, &theform, &err); + if (fres == DW_DLV_OK) { + if (theform == DW_FORM_string + || theform == DW_FORM_strp) { + char * temps = 0; + int sres = dwarf_formstring(attrib, &temps, + &err); + if (sres == DW_DLV_OK) { + char *p = temps; + if (cu_name[0] != '/') { + p = strrchr(temps, '/'); + if (p == NULL) { + p = temps; + } else { + p++; + } + } + esb_append(&esb_attr_name,p); + } else { + print_error(dbg, + "arange: string missing", + sres, err); + } + } + } else { + print_error(dbg, + "dwarf_whatform unexpected value", + fres, err); + } + dwarf_dealloc(dbg, attrib, DW_DLA_ATTR); + + /* Return the esb internal string */ + return esb_get_string(&esb_attr_name); +} + +/* Returns the cu of the CU */ +int get_cu_name(Dwarf_Debug dbg, Dwarf_Die cu_die, + Dwarf_Error err, string *short_name, string *long_name) +{ + Dwarf_Attribute name_attr = 0; + int ares; + + ares = dwarf_attr(cu_die, DW_AT_name, &name_attr, &err); + if (ares == DW_DLV_ERROR) { + print_error(dbg, "hassattr on DW_AT_name", ares, err); + } else { + if (ares == DW_DLV_NO_ENTRY) { + *short_name = "<unknown name>"; + *long_name = "<unknown name>"; + } else { + /* DW_DLV_OK */ + /* The string return is valid until the next call to this + function; so if the caller needs to keep the returned + string, the string must be copied (makename()). */ + static struct esb_s esb_short_name; + static struct esb_s esb_long_name; + char *filename; + esb_empty_string(&esb_long_name); + get_attr_value(dbg, DW_TAG_compile_unit, + cu_die, name_attr, NULL, 0, &esb_long_name, + 0 /*show_form_used*/,0 /* verbose */); + *long_name = esb_get_string(&esb_long_name); + /* Generate the short name (filename) */ + filename = strrchr(*long_name,'/'); + if (!filename) { + filename = strrchr(*long_name,'\\'); + } + if (filename) { + ++filename; + } else { + filename = *long_name; + } + esb_empty_string(&esb_short_name); + esb_append(&esb_short_name,filename); + *short_name = esb_get_string(&esb_short_name); + } + } + + dwarf_dealloc(dbg, name_attr, DW_DLA_ATTR); + return ares; +} + +/* Returns the producer of the CU */ +int get_producer_name(Dwarf_Debug dbg, Dwarf_Die cu_die, + Dwarf_Error err, string *producer_name) +{ + Dwarf_Attribute producer_attr = 0; + int ares; + + ares = dwarf_attr(cu_die, DW_AT_producer, &producer_attr, &err); + if (ares == DW_DLV_ERROR) { + print_error(dbg, "hassattr on DW_AT_producer", ares, err); + } else { + if (ares == DW_DLV_NO_ENTRY) { + /* We add extra quotes so it looks more like + the names for real producers that get_attr_value + produces. */ + *producer_name = "\"<CU-missing-DW_AT_producer>\""; + } else { + /* DW_DLV_OK */ + /* The string return is valid until the next call to this + function; so if the caller needs to keep the returned + string, the string must be copied (makename()). */ + static struct esb_s esb_producer; + esb_empty_string(&esb_producer); + get_attr_value(dbg, DW_TAG_compile_unit, + cu_die, producer_attr, NULL, 0, &esb_producer, + 0 /*show_form_used*/,0 /* verbose */); + *producer_name = esb_get_string(&esb_producer); + } + } + + dwarf_dealloc(dbg, producer_attr, DW_DLA_ATTR); + return ares; +} + +/* GCC linkonce names */ +char *lo_text = ".text."; /*".gnu.linkonce.t.";*/ +char *lo_debug_abbr = ".gnu.linkonce.wa."; +char *lo_debug_aranges = ".gnu.linkonce.wr."; +char *lo_debug_frame_1 = ".gnu.linkonce.wf."; +char *lo_debug_frame_2 = ".gnu.linkonce.wF."; +char *lo_debug_info = ".gnu.linkonce.wi."; +char *lo_debug_line = ".gnu.linkonce.wl."; +char *lo_debug_macinfo = ".gnu.linkonce.wm."; +char *lo_debug_loc = ".gnu.linkonce.wo."; +char *lo_debug_pubnames = ".gnu.linkonce.wp."; +char *lo_debug_ranges = ".gnu.linkonce.wR."; +char *lo_debug_str = ".gnu.linkonce.ws."; + +/* SNC compiler/linker linkonce names */ +char *nlo_text = ".text."; +char *nlo_debug_abbr = ".debug.wa."; +char *nlo_debug_aranges = ".debug.wr."; +char *nlo_debug_frame_1 = ".debug.wf."; +char *nlo_debug_frame_2 = ".debug.wF."; +char *nlo_debug_info = ".debug.wi."; +char *nlo_debug_line = ".debug.wl."; +char *nlo_debug_macinfo = ".debug.wm."; +char *nlo_debug_loc = ".debug.wo."; +char *nlo_debug_pubnames = ".debug.wp."; +char *nlo_debug_ranges = ".debug.wR."; +char *nlo_debug_str = ".debug.ws."; + +/* Build linkonce section information */ +void +build_linkonce_info(Dwarf_Debug dbg) +{ + int nCount = 0; + int section_index = 0; + int res = 0; + + static char **linkonce_names[] = { + &lo_text, /* .text */ + &nlo_text, /* .text */ + &lo_debug_abbr, /* .debug_abbr */ + &nlo_debug_abbr, /* .debug_abbr */ + &lo_debug_aranges, /* .debug_aranges */ + &nlo_debug_aranges, /* .debug_aranges */ + &lo_debug_frame_1, /* .debug_frame */ + &nlo_debug_frame_1, /* .debug_frame */ + &lo_debug_frame_2, /* .debug_frame */ + &nlo_debug_frame_2, /* .debug_frame */ + &lo_debug_info, /* .debug_info */ + &nlo_debug_info, /* .debug_info */ + &lo_debug_line, /* .debug_line */ + &nlo_debug_line, /* .debug_line */ + &lo_debug_macinfo, /* .debug_macinfo */ + &nlo_debug_macinfo, /* .debug_macinfo */ + &lo_debug_loc, /* .debug_loc */ + &nlo_debug_loc, /* .debug_loc */ + &lo_debug_pubnames, /* .debug_pubnames */ + &nlo_debug_pubnames, /* .debug_pubnames */ + &lo_debug_ranges, /* .debug_ranges */ + &nlo_debug_ranges, /* .debug_ranges */ + &lo_debug_str, /* .debug_str */ + &nlo_debug_str, /* .debug_str */ + NULL + }; + + const char *section_name = NULL; + Dwarf_Addr section_addr = 0; + Dwarf_Unsigned section_size = 0; + Dwarf_Error error = 0; + int nIndex = 0; + + nCount = dwarf_get_section_count(dbg); + + /* Ignore section with index=0 */ + for (section_index = 1; section_index < nCount; ++section_index) { + res = dwarf_get_section_info_by_index(dbg,section_index, + §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 */ + AddEntryIntoBucketGroup(pLinkonceInfo, + section_index, + section_addr,section_addr, + section_addr + section_size, + section_name, + TRUE); + break; + } + } + } + } + + if (dump_linkonce_info) { + PrintBucketGroup(pLinkonceInfo,TRUE); + } +} + +/* Check for specific TAGs and initialize some + information used by '-k' options */ +void +tag_specific_checks_setup(Dwarf_Half val,int die_indent_level) +{ + switch (val) { + case DW_TAG_compile_unit: + /* To help getting the compile unit name */ + seen_CU = TRUE; + /* If we are checking line information, build + the table containing the pairs LowPC and HighPC */ + if (check_decl_file || check_ranges || check_locations) { + ResetBucketGroup(pRangesInfo); + } + /* The following flag indicate that only low_pc and high_pc + values found in DW_TAG_subprograms are going to be considered when + building the address table used to check ranges, lines, etc */ + need_PU_valid_code = TRUE; + break; + + case DW_TAG_subprogram: + /* Keep track of a PU */ + if (die_indent_level == 1) { + /* A DW_TAG_subprogram can be nested, when is used to + declare a member function for a local class; process the DIE + only if we are at level zero in the DIEs tree */ + seen_PU = TRUE; + seen_PU_base_address = FALSE; + seen_PU_high_address = FALSE; + PU_name[0] = 0; + need_PU_valid_code = TRUE; + } + break; + } +} + +/* Indicates if the current CU is a target */ +static boolean current_cu_is_checked_compiler = TRUE; + +/* Are we checking for errors from the + compiler of the current compilation unit? +*/ +boolean +checking_this_compiler() +{ + /* This flag has been update by 'update_compiler_target()' + and indicates if the current CU is in a targeted compiler + specified by the user. Default value is TRUE, which + means test all compilers until a CU is detected. */ + return current_cu_is_checked_compiler || check_all_compilers; +} + +static int +hasprefix(const char *sample, const char *prefix) +{ + unsigned prelen = strlen(prefix); + if ( strncmp(sample,prefix,prelen) == 0) { + return TRUE; + } + return FALSE; +} + +/* Record which compiler was used (or notice we saw + it before) and set a couple variables as + a side effect (which are used all over): + current_cu_is_checked_compiler (used in checking_this_compiler() ) + current_compiler + The compiler name is from DW_AT_producer. +*/ +void +update_compiler_target(const char *producer_name) +{ + Dwarf_Bool cFound = FALSE; + int index = 0; + + safe_strcpy(CU_producer,sizeof(CU_producer),producer_name, + strlen(producer_name)); + current_cu_is_checked_compiler = FALSE; + + /* This list of compilers is just a start: + GCC id : "GNU" + SNC id : "SN Systems" */ + + /* Find a compiler version to check */ + if (compilers_targeted_count) { + for (index = 1; index <= compilers_targeted_count; ++index) { + if (is_strstrnocase(CU_producer,compilers_targeted[index].name)) { + compilers_targeted[index].verified = TRUE; + current_cu_is_checked_compiler = TRUE; + break; + } + } + } else { + /* Take into account that internally all strings are double quoted */ + boolean snc_compiler = hasprefix(CU_producer,"\"SN")? TRUE : FALSE; + boolean gcc_compiler = hasprefix(CU_producer,"\"GNU")?TRUE : FALSE; + current_cu_is_checked_compiler = check_all_compilers || + (snc_compiler && check_snc_compiler) || + (gcc_compiler && check_gcc_compiler) ; + } + + /* Check for already detected compiler */ + for (index = 1; index <= compilers_detected_count; ++index) { + if ( +#if WIN32 + !stricmp(compilers_detected[index].name,CU_producer) +#else + !strcmp(compilers_detected[index].name,CU_producer) +#endif + ) { + /* Set current compiler index */ + current_compiler = index; + cFound = TRUE; + break; + } + } + if (!cFound) { + /* Record a new detected compiler name. */ + if (compilers_detected_count + 1 < COMPILER_TABLE_MAX) { + Compiler *pCompiler = 0; + char *cmp = makename(CU_producer); + /* Set current compiler index, first compiler at position [1] */ + current_compiler = ++compilers_detected_count; + pCompiler = &compilers_detected[current_compiler]; + reset_compiler_entry(pCompiler); + pCompiler->name = cmp; + } + } +} + +/* Add a CU name to the current compiler entry, specified by the + 'current_compiler'; the name is added to the 'compilers_detected' + table and is printed if the '-P' option is specified in the + command line. */ +void +add_cu_name_compiler_target(char *name) +{ + a_name_chain *cu_last = 0; + a_name_chain *nc = 0; + Compiler *pCompiler = 0; + + if (current_compiler < 1) { + fprintf(stderr,"Current compiler set to %d, cannot add " + "Compilation unit name. Giving up.",current_compiler); + exit(1); + } + pCompiler = &compilers_detected[current_compiler]; + cu_last = pCompiler->cu_last; + /* Record current cu name */ + nc = (a_name_chain *)malloc(sizeof(a_name_chain)); + nc->item = makename(name); + nc->next = NULL; + if (cu_last) { + cu_last->next = nc; + } else { + pCompiler->cu_list = nc; + } + pCompiler->cu_last = nc; +} + +/* Reset a compiler entry, so all fields are properly set */ +static void +reset_compiler_entry(Compiler *compiler) +{ + memset(compiler,0,sizeof(Compiler)); +} + +/* Making this a named string makes it simpler to change + what the reset,or 'I do not know' value is for + CU name or producer name for PRINT_CU_INFO. */ +static const char * default_cu_producer = "<unknown>"; +static void +reset_overall_CU_error_data() +{ + strcpy(CU_name,default_cu_producer); + strcpy(CU_producer,default_cu_producer); + DIE_offset = 0; + DIE_overall_offset = 0; + DIE_CU_offset = 0; + DIE_CU_overall_offset = 0; + CU_base_address = 0; + CU_high_address = 0; +} + + +static boolean +cu_data_is_set() +{ + if(strcmp(CU_name,default_cu_producer) || + strcmp(CU_producer,default_cu_producer)) { + return 1; + } + if(DIE_offset || DIE_overall_offset) { + return 1; + } + if(CU_base_address || CU_high_address) { + return 1; + } + return 0; +} +/* Print CU basic information */ +void PRINT_CU_INFO() +{ + if (current_section_id == DEBUG_LINE || + current_section_id == DEBUG_ARANGES) { + /* Only in the DEBUG_LINE/ARANGES case is DIE_CU_offset or + DIE_CU_overall_offset what we want to print here. + In other cases DIE_CU_offset is not really a CU + offset at all. */ + DIE_offset = DIE_CU_offset; + DIE_overall_offset = DIE_CU_overall_offset; + } + if(!cu_data_is_set()) { + return; + } + printf("\n"); + printf("CU Name = %s\n",CU_name); + printf("CU Producer = %s\n",CU_producer); + printf("DIE OFF = 0x%08" DW_PR_DUx + " GOFF = 0x%08" DW_PR_DUx ,DIE_offset,DIE_overall_offset); + printf(", Low PC = 0x%08" DW_PR_DUx ", High PC = 0x%08" DW_PR_DUx , + CU_base_address,CU_high_address); + printf("\n"); + fflush(stdout); +} + +void DWARF_CHECK_COUNT(Dwarf_Check_Categories category, int inc) +{ + compilers_detected[0].results[category].checks += inc; + compilers_detected[0].results[total_check_result].checks += inc; + if(current_compiler > 0 && current_compiler < COMPILER_TABLE_MAX) { + compilers_detected[current_compiler].results[category].checks += inc; + compilers_detected[current_compiler].results[total_check_result].checks + += inc; + compilers_detected[current_compiler].verified = TRUE; + } +} + +void DWARF_ERROR_COUNT(Dwarf_Check_Categories category, int inc) +{ + compilers_detected[0].results[category].errors += inc; + compilers_detected[0].results[total_check_result].errors += inc; + if(current_compiler > 0 && current_compiler < COMPILER_TABLE_MAX) { + compilers_detected[current_compiler].results[category].errors += inc; + compilers_detected[current_compiler].results[total_check_result].errors + += inc; + } +} + +void PRINT_CHECK_RESULT(char *str, + Compiler *pCompiler, Dwarf_Check_Categories category) +{ + Dwarf_Check_Result result = pCompiler->results[category]; + fprintf(stderr, "%-24s%10d %10d\n", str, result.checks, result.errors); +} + +void DWARF_CHECK_ERROR_PRINT_CU() +{ + if (check_verbose_mode) { + PRINT_CU_INFO(); + } + check_error++; + record_dwarf_error = TRUE; +} + +void DWARF_CHECK_ERROR(Dwarf_Check_Categories category, + const char *str) +{ + if (checking_this_compiler()) { + DWARF_ERROR_COUNT(category,1); + if (check_verbose_mode) { + printf("\n*** DWARF CHECK: %s ***\n", str); + } + DWARF_CHECK_ERROR_PRINT_CU(); + } +} + +void DWARF_CHECK_ERROR2(Dwarf_Check_Categories category, + const char *str1, const char *str2) +{ + if (checking_this_compiler()) { + DWARF_ERROR_COUNT(category,1); + if (check_verbose_mode) { + printf("\n*** DWARF CHECK: %s: %s ***\n", str1, str2); + } + DWARF_CHECK_ERROR_PRINT_CU(); + } +} + +void DWARF_CHECK_ERROR3(Dwarf_Check_Categories category, + const char *str1, const char *str2, const char *strexpl) +{ + if (checking_this_compiler()) { + DWARF_ERROR_COUNT(category,1); + if (check_verbose_mode) { + printf("\n*** DWARF CHECK: %s -> %s: %s ***\n", + str1, str2,strexpl); + } + DWARF_CHECK_ERROR_PRINT_CU(); + } +} + +/* Precondition: 'out' is already constructed and empty. */ +static const char * +do_uri_translation(const char *s,const char *context) +{ + struct esb_s str; + char *finalstr = 0; + if (!uri_options_translation) { + return makename(s); + } + esb_constructor(&str); + translate_from_uri(s,&str); + if (do_print_uri_in_input) { + if(strcmp(s,esb_get_string(&str))) { + printf("Uri Translation on option %s\n",context); + printf(" \'%s\'\n",s); + printf(" \'%s\'\n",esb_get_string(&str)); + } + } + finalstr = makename(esb_get_string(&str)); + esb_destructor(&str); + return finalstr; +} diff --git a/dwarfdump/dwarfdump.conf b/dwarfdump/dwarfdump.conf new file mode 100644 index 0000000..d70bab8 --- /dev/null +++ b/dwarfdump/dwarfdump.conf @@ -0,0 +1,810 @@ +# MIPS/IRIX ISA/ABI +# Used to configure dwarfdump printing of .debug_frame and +# .eh_frame. + +# Any number of abi's can be described. Only one can be selected +# in a given dwarfdump run (see dwarfdump options) +# Available commands are +# beginabi: <abiname> +# reg: <regname> <dwarf regnumber> +# frame_interface: <integer value 2 or 3> +# cfa_reg: <number> +# initial_reg_value: <number: often 1034 or 1035 > +# same_val_reg: 1035 +# undefined_val_reg: 1034 +# reg_table_size: <size of table> +# address_size: <4 or 8, Rarely needed, see example below. > +# includeabi: <abiname Inserts the referenced abi as if its text was +# directly inserted at this point.> +# endabi: <abiname> +# +# Symbolic names do not work here, use literal numbers +# where applicable (in C standard decimal, octal (leading 0) or +# hexadecimal <leading 0x>). +# +# Whitespace is required to separate command: from operands and +# operands from each other on a line. +# +# There is no ordering required within a beginabi/endabi pair. +# As many ABIs as required may be listed. +# dwarfdump will choose exactly one abi to dump frame information. +# + + +# MIPS abi,the old IRIX form, not to be used on modern objects. +# Begin with abi name (use here and on dwarfdump command line). +beginabi: mips-irix + +# Instructs dwarfdump to default to the older frame interface. +# Use value 3 to use the newer interface. +# The '2' interface is supported but deprecated (deprecated +# because it cannot work with all popular ABIs: mixing +# the cfa-rule into the table column set was not a good idea +# but it is part of the MIPS/IRIX standard usage). +frame_interface: 2 + +# If (and only if) using frame_interface: 2 tell dwarfdump +# what table colum that DW_FRAME_CFA_COL is. +# If using frame_interface: 3 cfa_reg: should be +# DW_FRAME_CFA_COL3 (1436) +cfa_reg: 0 + +# For MIPS, the same as DW_FRAME_SAME_VAL (1035). +# For other ISA/ABIs 1034 (DW_FRAME_UNDEFINED_VAL) might be better. +# Depends on the ABI convention, if set wrong way too many +# regs will be listed in the frame output. +# This instructs dwarfdump to set libdwarf to this value, +# overriding the libdwarf default. +# If initial_reg_value not set the libdwarf default is used +# (see libdwarf.h DW_FRAME_REG_INITIAL_VALUE). +initial_reg_value: 1035 # DW_FRAME_SAME_VAL +same_val_reg: 1035 +undefined_val_reg: 1034 + +# Built in to frame_interface: 2 as 66. +reg_table_size: 66 + + +# Only name registers for wich a r4 (for example) is not what you +# want to see +# No particular order of the reg: lines required. +reg: cfa 0 # Used with MIPS/IRIX original DWARF2 interface +reg: r1/at 1 +reg: r2/v0 2 +reg: r3/v1 3 +reg: r4/a0 4 +reg: r5/a1 5 +reg: r6/a2 6 +reg: r7/a3 7 +reg: r8/t0 8 +reg: r9/t1 9 +reg: r10/t2 10 +reg: r11/t3 11 +reg: r12/t4 12 +reg: r13/t5 13 +reg: r14/t6 14 +reg: r15/t7 15 +reg: r16/s0 16 +reg: r17/s1 17 +reg: r18/s2 18 +reg: r19/s3 19 +reg: r20/s4 20 +reg: r21/s5 21 +reg: r22/s6 22 +reg: r23/s7 23 +reg: r24/t8 24 +reg: r25/t9 25 +reg: r26/k0 26 +reg: r27/k1 27 +reg: r28/gp 28 +reg: r29/sp 29 +reg: r30/s8 30 +reg: r31 31 + +reg: $f0 32 +reg: $f1 33 +reg: $f2 34 +reg: $f3 35 +reg: $f4 36 +reg: $f5 37 +reg: $f6 38 +reg: $f7 39 +reg: $f8 40 +reg: $f9 41 +reg: $f10 42 +reg: $f11 43 +reg: $f12 44 +reg: $f13 45 +reg: $f14 46 +reg: $f15 47 +reg: $f16 48 +reg: $f17 49 +reg: $f18 50 +reg: $f19 51 +reg: $f20 52 +reg: $f21 53 +reg: $f22 54 +reg: $f23 55 +reg: $f24 56 +reg: $f25 57 +reg: $f26 58 +reg: $f27 59 +reg: $f28 60 +reg: $f29 61 +reg: $f30 62 +reg: $f31 63 +reg: ra 64 +reg: slk 65 + + +# End of abi definition. +endabi: mips-irix + + +# Make 'mips' abi be a modern MIPS, not an old IRIX version. +beginabi: mips +includeabi: mips-simple3 +endabi: mips + + +# MIPS/IRIX ISA/ABI for testing libdwarf. +beginabi: mips-irix2 +frame_interface: 2 +reg_table_size: 66 +cfa_reg: 0 +same_val_reg: 1035 +undefined_val_reg: 1034 +initial_reg_value: 1035 + +reg: cfa 0 # Used with MIPS/IRIX original DWARF2 interface +reg: ra 64 +reg: slk 65 + +# End of abi definition. +endabi: mips-irix2 + +# MIPS/IRIX ISA/ABI for testing the new frame interface +# with libdwarf. +beginabi: mips-simple3 +frame_interface: 3 + +# When using frame_interface: 3 the size of the register table +# is not fixed. It can be as large as needed. +reg_table_size: 66 +cfa_reg: 1436 # DW_FRAME_CFA_COL3 +initial_reg_value: 1035 +same_val_reg: 1035 +undefined_val_reg: 1034 + +# No cfa as a 'normal' register. +# Rule 0 is just register 0, which is not used +# in frame descriptions. +# (so cfa does not have a number here, and dwarfdump gives +# it the name 'cfa' automatically). +reg: ra 64 +reg: slk 65 +# End of abi definition. +endabi: mips-simple3 + + +beginabi: ia64 +frame_interface: 3 +initial_reg_value: 1034 # DW_FRAME_UNDEFINED_VAL +cfa_reg: 1436 # DW_FRAME_CFA_COL3 +reg_table_size: 695 +same_val_reg: 1035 +undefined_val_reg: 1034 + +# The following register names are not necessarily correct... +# Register indexes r32-r127 not used. +reg: f0 128 +# ... +reg: f127 255 +reg: b0 321 +reg: b1 322 +reg: b2 323 +reg: b3 324 +reg: b4 325 +reg: b5 326 +reg: b6 327 +reg: b7 328 +reg: vfp 329 +reg: vrap 330 +reg: pr 331 +reg: ip 332 +reg: psr 333 +reg: cfm 334 +reg: k0 335 +reg: k1 336 +reg: k2 337 +reg: k3 338 +reg: k4 339 +reg: k5 340 +reg: k6 341 +reg: k7 342 +reg: rsc 350 +reg: bsp 351 +reg: bspstore 352 +reg: rnat 353 +reg: fcr 355 +reg: eflag 358 +reg: csd 359 +reg: ssd 360 +reg: cflg 361 +reg: fsr 362 +reg: fir 363 +reg: fdr 364 +reg: pfs 398 +reg: lc 399 +reg: ec 400 + +endabi: ia64 + + +beginabi: x86 +frame_interface: 3 +initial_reg_value: 1035 # DW_FRAME_SAME_VAL +reg_table_size: 66 # more than large enough, hopefully. +cfa_reg: 1436 # DW_FRAME_CFA_COL3 +same_val_reg: 1035 +undefined_val_reg: 1034 + +# The following register names are not necessarily correct... +reg: eax 0 +reg: ecx 1 +reg: edx 2 +reg: ebx 3 +reg: esp 4 +reg: ebp 5 +reg: esi 6 +reg: edi 7 +reg: eip 8 +reg: eflags 9 + +reg: trapno 10 +reg: st0 11 +reg: st1 12 +reg: st2 13 +reg: st3 14 +reg: st4 15 +reg: st5 16 +reg: st6 17 +reg: st7 18 +# 19 is ? 20 is ? +reg: xmm0 21 +reg: xmm1 22 +reg: xmm2 23 +reg: xmm3 24 +reg: xmm4 25 +reg: xmm5 26 +reg: xmm6 27 +reg: xmm7 28 + +reg: mm0 29 +reg: mm1 30 +reg: mm2 31 +reg: mm3 32 +reg: mm4 33 +reg: mm5 34 +reg: mm6 35 +reg: mm7 36 + +reg: fcw 37 +reg: fsw 38 +reg: mxcsr 39 + +reg: es 40 +reg: cs 41 +reg: ss 42 +reg: ds 43 +reg: fs 44 +reg: gs 45 +# 46 47 are ? +reg: tr 48 +reg: ldtr 49 + + +endabi: x86 + + +beginabi: x86_64 +frame_interface: 3 +initial_reg_value: 1035 # DW_FRAME_SAME_VAL +reg_table_size: 66 # more than large enough, hopefully. +cfa_reg: 1436 # DW_FRAME_CFA_COL3 +same_val_reg: 1035 +undefined_val_reg: 1034 + +# The following register names are not necessarily correct... +reg: rax 0 +reg: rdx 1 +reg: rcx 2 +reg: rbx 3 +reg: rsi 4 +reg: rdi 5 +reg: rbp 6 +reg: rsp 7 +reg: r8 8 +reg: r9 9 +reg: r10 10 +reg: r11 11 +reg: r12 12 +reg: r13 13 +reg: r14 14 +reg: r15 15 +reg: rip 16 +reg: xmm0 17 +reg: xmm1 18 +reg: xmm2 19 +reg: xmm3 20 +reg: xmm4 21 +reg: xmm5 22 +reg: xmm6 23 +reg: xmm7 24 +reg: xmm8 25 +reg: xmm9 26 +reg: xmm10 27 +reg: xmm11 28 +reg: xmm12 29 +reg: xmm13 30 +reg: xmm14 31 +reg: xmm15 32 + +reg: st0 33 +reg: st1 34 +reg: st2 35 +reg: st3 36 +reg: st4 37 +reg: st5 38 +reg: st6 39 +reg: st7 40 + +reg: mm0 41 +reg: mm1 42 +reg: mm2 43 +reg: mm3 44 +reg: mm4 45 +reg: mm5 46 +reg: mm6 47 +reg: mm7 48 + +reg: rflags 49 +reg: es 50 +reg: cs 51 +reg: ss 52 +reg: ds 53 +reg: fs 54 +reg: gs 55 +# 56, 57 are ? +reg: fs.base 58 +reg: gs.base 59 +# 60 61 are ? +reg: tr 62 +reg: ldtr 63 + +endabi: x86_64 + +beginabi: m68k +frame_interface: 3 +initial_reg_value: 1035 # DW_FRAME_SAME_VAL +reg_table_size: 66 # more than large enough, hopefully. +cfa_reg: 1436 # DW_FRAME_CFA_COL3 +same_val_reg: 1035 +undefined_val_reg: 1034 + +reg: d0 0 +reg: d1 1 +reg: d2 2 +reg: d3 3 +reg: d4 4 +reg: d5 5 +reg: d6 6 +reg: d7 7 + +reg: a0 8 +reg: a1 9 +reg: a2 10 +reg: a3 11 +reg: a4 12 +reg: a5 13 +reg: a6 14 +reg: sp 15 + +reg: fp0 16 +reg: fp1 17 +reg: fp2 18 +reg: fp3 19 +reg: fp4 20 +reg: fp5 21 +reg: fp6 22 +reg: pc 23 + +endabi: m68k + +# Demonstrates use of address_size and includeabi keywords. +# address_size is useful when an Elf64 object has DWARF2 +# 32bit (4 byte) address-size frame data (which has no address_size field) +# and no .debug_info section to provide the 32bit address size. +beginabi: ppc32bitaddress +address_size: 4 +includeabi: ppc +endabi: ppc32bitaddress + +beginabi: ppc +# This abi defined Oct 2008 based on: +# http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html +frame_interface: 3 +# abi dwarf table uses up thru 1155. +# As of Oct 2008, the only ABI requiring a higher +# DW_FRAME_SAME_VAL and DW_FRAME_CFA_COL3. +initial_reg_value: 1235 # DW_FRAME_SAME_VAL +cfa_reg: 1436 # DW_FRAME_CFA_COL3 +same_val_reg: 1235 +undefined_val_reg: 1234 +reg_table_size: 1200 + +reg: r0 0 +reg: f0 32 +reg: f1 33 +reg: f2 34 +reg: f3 35 +reg: f4 36 +reg: f5 37 +reg: f6 38 +reg: f7 39 +reg: f8 40 +reg: f9 41 +reg: f10 42 +reg: f11 43 +reg: f12 44 +reg: f13 45 +reg: f14 46 +reg: f16 47 +reg: f17 48 +reg: f18 49 +reg: f19 50 +reg: f20 51 +reg: f21 52 +reg: f22 53 +reg: f23 54 +reg: f24 55 +reg: f25 56 +reg: f26 57 +reg: f27 58 +reg: f28 59 +reg: f29 60 +reg: f30 62 +reg: f31 63 +reg: cr 64 +reg: fpcsr 65 +# spr0 is also called MQ +reg: spr0 100 +# spr1 is also called XER +reg: spr1 101 +# spr4 also called rtcu +reg: spr4 104 +# spr5 also called rtcl +reg: spr5 105 +#spr8 also called LR +reg: spr8 108 +# spr9 also called ctr +reg: spr9 109 +reg: msr 66 +reg: sr0 70 +reg: sr1 71 +reg: sr2 72 +reg: sr3 73 +reg: sr4 74 +reg: sr5 75 +reg: sr6 76 +reg: sr7 77 +reg: sr8 78 +reg: sr9 79 + +#dsisr also called spr18 +reg: spr18 118 +# dar also called spr19 +reg: spr19 119 +#dec also called spr22 +reg: spr22 122 +#sdr1 also called spr25 +reg: spr25 125 +#srr0 also called spr26 +reg: spr26 126 +#srr1 also called spr27 +reg: spr27 127 + +#vrsave also called spr256 +reg: spr256 356 +#sprg0 also called spr272 +reg: spr272 372 +#sprg1 also called spr273 +reg: spr273 373 +#sprg2 also called spr274 +reg: spr274 374 +#sprg3 also called spr275 +reg: spr275 375 +#asr also called spr280 +reg: spr280 380 +#ear also called spr282 +reg: spr282 382 +#tb also called spr284 +reg: spr284 384 +#tbu also called spr285 +reg: spr285 385 +#pvr also called spr287 +reg: spr287 387 +#ibat0u also called spr528 +reg: spr528 628 +#ibat0l also called spr529 +reg: spr529 629 +#ibat1u also called spr530 +reg: spr530 630 +#ibat1l also called spr531 +reg: spr531 631 +#ibat2u also called spr532 +reg: spr532 632 +#ibat2l also called spr533 +reg: spr533 633 +#ibat3u also called spr534 +reg: spr534 634 +#ibat3l also called spr535 +reg: spr535 635 +#dbat0u also called spr536 +reg: spr536 636 +#dbat0l also called spr537 +reg: spr537 637 +#dbat1u also called spr538 +reg: spr538 638 +#dbat1l also called spr539 +reg: spr539 639 +#dbat2u also called spr540 +reg: spr540 640 +#dbat2l also called spr541 +reg: spr541 641 +#dbat3u also called spr542 +reg: spr542 642 +#dbat3l also called spr543 +reg: spr543 643 + +#hid0 also called spr1008 +reg: spr1008 1108 +#hid1 also called spr1009 +reg: spr1009 1109 +#hid2 also called iabr or spr1010 +reg: spr1010 1110 +#hid5 also called dabr or spr1013 +reg: spr1013 1113 +#hid15 also called pir or spr1023 +reg: spr1023 1123 + +# vector registers 0-31 +reg: vr0 1124 +reg: vr1 1125 +reg: vr2 1126 +reg: vr3 1127 +reg: vr4 1128 +reg: vr5 1129 +reg: vr6 1130 +reg: vr7 1131 +reg: vr8 1132 +reg: vr9 1133 +reg: vr10 1134 +reg: vr11 1135 +reg: vr12 1136 +reg: vr13 1137 +reg: vr14 1138 +reg: vr15 1130 +reg: vr16 1140 +reg: vr17 1141 +reg: vr18 1142 +reg: vr19 1143 +reg: vr20 1144 +reg: vr21 1145 +reg: vr22 1146 +reg: vr23 1147 +reg: vr24 1148 +reg: vr25 1149 +reg: vr26 1150 +reg: vr27 1151 +reg: vr28 1152 +reg: vr29 1153 +reg: vr30 1154 +reg: vr31 1155 +endabi: ppc + +# 'Generic 1000 register abi'. +# This is useful as a 'general' ABI settings for +# cpus using up to 1000 registers. The register names +# show as a number, like 'r991'. +beginabi: generic +frame_interface: 3 +initial_reg_value: 1035 # DW_FRAME_SAME_VAL +cfa_reg: 1436 # DW_FRAME_CFA_COL3 +reg_table_size: 1000 +same_val_reg: 1035 +undefined_val_reg: 1034 +reg: r0 0 +endabi: generic + +# 'Generic 500 register abi'. +# This is useful as a 'general' ABI settings for +# cpus using up to 500 registers. The register names +# show as a number, like 'r91'. +beginabi: generic500 +frame_interface: 3 +initial_reg_value: 1035 # DW_FRAME_SAME_VAL +cfa_reg: 1436 # DW_FRAME_CFA_COL3 +reg_table_size: 500 +same_val_reg: 1035 +undefined_val_reg: 1034 +reg: r0 0 +endabi: generic500 + +# 'Generic 100 register abi'. +# This is useful as a 'general' ABI settings for +# cpus using up to 100 registers. The register names +# show as a number, like 'r91'. +beginabi: generic100 +frame_interface: 3 +initial_reg_value: 1035 # DW_FRAME_SAME_VAL +cfa_reg: 1436 # DW_FRAME_CFA_COL3 +reg_table_size: 100 +same_val_reg: 1035 +undefined_val_reg: 1034 +reg: r0 0 +endabi: generic100 + + +beginabi: arm +frame_interface: 3 +# When using frame_interface: 3 the size of the register +# table is not fixed. It can be as large as needed. +reg_table_size: 288 +cfa_reg: 1436 # DW_FRAME_CFA_COL3 +initial_reg_value: 1034 +same_val_reg: 1035 +undefined_val_reg: 1034 +# If the vendor co-processor registers are allowed +# or other numbers above 287 used then +# the reg_table_size must be increased and (possibly) +# the cfa, same_value, undefined_value reg values changed +# here. +# r0-r15 are 0 through 15. +# Numbers 16 through 63 had meaning +# in some ARM DWARF register mappings. +reg: s0 64 +reg: s1 65 +reg: s2 66 +reg: s3 67 +reg: s4 68 +reg: s5 69 +reg: s6 70 +reg: s7 71 +reg: s8 72 +reg: s9 73 +reg: s10 74 +reg: s11 75 +reg: s12 76 +reg: s13 77 +reg: s14 78 +reg: s15 79 +reg: s16 80 +reg: s17 81 +reg: s18 82 +reg: s19 83 +reg: s20 84 +reg: s21 85 +reg: s22 86 +reg: s23 87 +reg: s24 88 +reg: s25 89 +reg: s26 90 +reg: s27 91 +reg: s28 92 +reg: s29 93 +reg: s30 94 +reg: s31 95 +reg: f0 96 +reg: f1 97 +reg: f2 98 +reg: f3 99 +reg: f4 100 +reg: f5 101 +reg: f6 102 +reg: f7 103 +reg: wcgr0 104 +reg: wcgr0 105 +reg: wcgr0 106 +reg: wcgr0 107 +reg: wcgr0 108 +reg: wcgr0 109 +reg: wcgr0 110 +reg: wcgr0 111 +reg: wr0 112 +reg: wr1 113 +reg: wr2 114 +reg: wr3 115 +reg: wr4 116 +reg: wr5 117 +reg: wr6 118 +reg: wr7 119 +reg: wr8 120 +reg: wr9 121 +reg: wr10 122 +reg: wr11 123 +reg: wr12 124 +reg: wr13 125 +reg: wr14 126 +reg: wr15 127 +reg: spsr 128 +reg: spsr_fiq 129 +reg: spsr_irq 130 +reg: spsr_abt 131 +reg: spsr_und 132 +reg: spsr_svc 133 +reg: r8_usr 144 +reg: r9_usr 145 +reg: r10_usr 146 +reg: r11_usr 147 +reg: r12_usr 148 +reg: r13_usr 149 +reg: r14_usr 150 +reg: r8_fiq 151 +reg: r9_fiq 152 +reg: r10_fiq 153 +reg: r11_fiq 154 +reg: r12_fiq 155 +reg: r13_fiq 156 +reg: r14_fiq 157 +reg: r13_riq 158 +reg: r14_riq 159 +reg: r14_abt 160 +reg: r13_abt 161 +reg: r14_und 162 +reg: r13_und 163 +reg: r14_svc 164 +reg: r13_svc 165 +reg: wc0 192 +reg: wc1 193 +reg: wc2 192 +reg: wc3 192 +reg: wc4 192 +reg: wc5 197 +reg: wc6 198 +reg: wc7 199 +reg: d0 256 +reg: d1 257 +reg: d2 258 +reg: d3 259 +reg: d4 260 +reg: d5 261 +reg: d6 262 +reg: d7 263 +reg: d8 264 +reg: d9 265 +reg: d10 266 +reg: d11 267 +reg: d12 268 +reg: d13 269 +reg: d14 270 +reg: d15 271 +reg: d16 272 +reg: d17 273 +reg: d18 274 +reg: d19 275 +reg: d20 266 +reg: d21 277 +reg: d22 278 +reg: d23 279 +reg: d24 280 +reg: d25 281 +reg: d26 282 +reg: d27 283 +reg: d28 284 +reg: d29 285 +reg: d30 286 +reg: d31 287 +# End of abi definition. +endabi: arm + diff --git a/dwarfdump/dwconf.c b/dwarfdump/dwconf.c new file mode 100644 index 0000000..1b59053 --- /dev/null +++ b/dwarfdump/dwconf.c @@ -0,0 +1,1424 @@ +/* + Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2011 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + + $Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/dwconf.c,v 1.4 2006/04/18 18:05:57 davea Exp $ */ + + +/* Windows specific */ +#ifdef HAVE_STDAFX_H +#include "stdafx.h" +#endif /* HAVE_STDAFX_H */ + +#include "globals.h" +#include "dwarf.h" +#include "libdwarf.h" + +#include <ctype.h> +#include "dwconf.h" +#include "makename.h" + +extern int verbose; + +/* The nesting level is arbitrary, 2 should suffice. + But at least this prevents an infinite loop. +*/ +#define MAX_NEST_LEVEL 3 + +struct token_s { + unsigned tk_len; + char *tk_data; +}; +enum linetype_e { + LT_ERROR, + LT_COMMENT, + LT_BLANK, + LT_BEGINABI, + LT_REG, + LT_FRAME_INTERFACE, + LT_CFA_REG, + LT_INITIAL_REG_VALUE, + LT_SAME_VAL_REG, + LT_UNDEFINED_VAL_REG, + LT_REG_TABLE_SIZE, + LT_ADDRESS_SIZE, + LT_INCLUDEABI, + LT_ENDABI +}; + +struct comtable_s { + enum linetype_e type; + char *name; + size_t namelen; +}; + +static int errcount = 0; /* Count errors found in this scan of + the configuration file. */ + +static char name_begin_abi[] = "beginabi:"; +static char name_reg[] = "reg:"; +static char name_frame_interface[] = "frame_interface:"; +static char name_cfa_reg[] = "cfa_reg:"; +static char name_initial_reg_value[] = "initial_reg_value:"; +static char name_same_val_reg[] = "same_val_reg:"; +static char name_undefined_val_reg[] = "undefined_val_reg:"; +static char name_reg_table_size[] = "reg_table_size:"; +static char name_address_size[] = "address_size:"; +static char name_includeabi[] = "includeabi:"; +static char name_endabi[] = "endabi:"; + +static struct comtable_s comtable[] = { + {LT_BEGINABI, name_begin_abi}, + {LT_REG, name_reg}, + {LT_FRAME_INTERFACE, name_frame_interface}, + {LT_CFA_REG, name_cfa_reg}, + {LT_INITIAL_REG_VALUE, name_initial_reg_value}, + {LT_SAME_VAL_REG, name_same_val_reg}, + {LT_UNDEFINED_VAL_REG, name_undefined_val_reg}, + {LT_REG_TABLE_SIZE, name_reg_table_size}, + {LT_ADDRESS_SIZE, name_address_size}, + {LT_INCLUDEABI, name_includeabi}, + {LT_ENDABI, name_endabi}, +}; + +struct conf_internal_s { + unsigned long beginabi_lineno; + unsigned long frame_interface_lineno; + unsigned long initial_reg_value_lineno; + unsigned long reg_table_size_lineno; + unsigned long address_size_lineno; + unsigned long same_val_reg_lineno; + unsigned long undefined_val_reg_lineno; + unsigned long cfa_reg_lineno; + unsigned long regcount; + struct dwconf_s * conf_out; + const char * conf_name_used; + char ** conf_defaults; +}; +static void +init_conf_internal(struct conf_internal_s *s, + struct dwconf_s * conf_out) +{ + s->beginabi_lineno = 0; + s->frame_interface_lineno = 0; + s->initial_reg_value_lineno = 0; + s->reg_table_size_lineno = 0; + s->address_size_lineno = 0; + s->same_val_reg_lineno = 0; + s->undefined_val_reg_lineno = 0; + s->cfa_reg_lineno = 0; + s->cfa_reg_lineno = 0; + s->conf_name_used = 0; + s->conf_defaults = 0; + s->regcount = 0; + s->conf_out = conf_out; +} + +static int size_of_comtable = sizeof(comtable) / sizeof(comtable[0]); + +static FILE *find_a_file(const char *named_file, char **defaults, + const char** name_used); +static int find_abi_start(FILE * stream, const char *abi_name, long *offset, + unsigned long *lineno_out); +static int parse_abi(FILE * stream, const char *fname, const char *abiname, + struct conf_internal_s *out, unsigned long lineno, unsigned nest_level); +static char *get_token(char *cp, struct token_s *outtok); + +/* This finds a dwarfdump.conf file and + then parses it. It updates + conf_out as appropriate. + + This finds the first file (looking in a set of places) + with that name. It then looks for the right ABI entry. + If the first file it finds does not have that ABI entry it + gives up. + + It would also be reasonable to search every 'dwarfdump.conf' + it finds for the abi. But we stop at the first dwarfdump.conf + we find. + This is the internal call to get the conf data to implement + a crude 'includeabi' feature. + + Returns 0 if no errors found, else returns > 0. +*/ +static int +find_conf_file_and_read_config_inner(const char *named_file, + const char *named_abi, + struct conf_internal_s *conf_internal, + unsigned nest_level) +{ + + FILE *conf_stream = 0; + const char *name_used = 0; + long offset = 0; + int res = FALSE; + unsigned long lineno = 0; + + errcount = 0; + + conf_stream = find_a_file(named_file, conf_internal->conf_defaults, + &name_used); + if (!conf_stream) { + ++errcount; + printf("dwarfdump found no file %s!\n", + named_file ? named_file : "readable for configuration. " + "(add options -v -v to see what file names tried)\n"); + return errcount; + } + if (verbose > 1) { + printf("dwarfdump using configuration file %s\n", name_used); + } + conf_internal->conf_name_used = name_used; + + res = find_abi_start(conf_stream, named_abi, &offset, &lineno); + if (errcount > 0) { + ++errcount; + printf("dwarfdump found no ABI %s in file %s.\n", + named_abi, name_used); + return errcount; + } + res = fseek(conf_stream, offset, SEEK_SET); + if (res != 0) { + ++errcount; + printf("dwarfdump seek to %ld offset in %s failed!\n", + offset, name_used); + return errcount; + } + parse_abi(conf_stream, name_used, named_abi, conf_internal, lineno, + nest_level); + fclose(conf_stream); + return errcount; +} + +/* This is the external-facing call to get the conf data. */ +int +find_conf_file_and_read_config(const char *named_file, + const char *named_abi, char **defaults, + struct dwconf_s *conf_out) +{ + int res = 0; + struct conf_internal_s conf_internal; + init_conf_file_data(conf_out); + init_conf_internal(&conf_internal,conf_out); + conf_internal.conf_defaults = defaults; + res = find_conf_file_and_read_config_inner(named_file, + named_abi, + &conf_internal,0); + return res; +} + +/* Given path strings, attempt to make a canonical file name: + that is, avoid superfluous '/' so that no + '//' (or worse) is created in the output. The path components + are to be separated so at least one '/' + is to appear between the two 'input strings' when + creating the output. +*/ +static char * +canonical_append(char *target, unsigned int target_size, + const char *first_string, const char *second_string) +{ + size_t firstlen = strlen(first_string); + + /* +1 +1: Leave room for added "/" and final NUL, though that is + overkill, as we drop a NUL byte too. */ + if ((firstlen + strlen(second_string) + 1 + 1) >= target_size) { + /* Not enough space. */ + return NULL; + } + for (; *second_string == '/'; ++second_string) { + } + for (; firstlen > 0 && first_string[firstlen - 1] == '/'; + --firstlen) { + } + target[0] = 0; + if (firstlen > 0) { + strncpy(target, first_string, firstlen); + target[firstlen + 1] = 0; + } + target[firstlen] = '/'; + firstlen++; + target[firstlen] = 0; + strcat(target, second_string); + return target; +} + +#ifdef BUILD_FOR_TEST +#define CANBUF 25 +struct canap_s { + char *res_exp; + char *first; + char *second; +} canap[] = { + { + "ab/c", "ab", "c"}, { + "ab/c", "ab/", "c"}, { + "ab/c", "ab", "/c"}, { + "ab/c", "ab////", "/////c"}, { + "ab/", "ab", ""}, { + "ab/", "ab////", ""}, { + "ab/", "ab////", ""}, { + "/a", "", "a"}, { + 0, "/abcdefgbijkl", "pqrstuvwxyzabcd"}, { + 0, 0, 0} +}; +static void +test_canonical_append(void) +{ + /* Make buf big, this is test code, so be safe. */ + char lbuf[1000]; + unsigned i; + unsigned failcount = 0; + + printf("Entry test_canonical_append\n"); + for (i = 0;; ++i) { + char *res = 0; + + if (canap[i].first == 0 && canap[i].second == 0) + break; + + res = canonical_append(lbuf, CANBUF, canap[i].first, + canap[i].second); + if (res == 0) { + if (canap[i].res_exp == 0) { + /* GOOD */ + printf("PASS %u\n", i); + } else { + ++failcount; + printf("FAIL: entry %u wrong, expected %s, got NULL\n", + i, canap[i].res_exp); + } + } else { + if (canap[i].res_exp == 0) { + ++failcount; + printf("FAIL: entry %u wrong, got %s expected NULL\n", + i, res); + } else { + if (strcmp(res, canap[i].res_exp) == 0) { + printf("PASS %u\n", i); + /* GOOD */ + } else { + ++failcount; + printf("FAIL: entry %u wrong, expected %s got %s\n", + i, canap[i].res_exp, res); + } + } + } + } + printf("FAIL count %u\n", failcount); + +} +#endif /* BUILD_FOR_TEST */ +/* Try to find a file as named and open for read. + We treat each name as a full name, we are not + combining separate name and path components. + This is an arbitrary choice... + + The defaults are listed in dwarfdump.c in the array + config_file_defaults[]. +*/ +static FILE * +find_a_file(const char *named_file, char **defaults, const char ** name_used) +{ + FILE *fin = 0; + const char *lname = named_file; + const char *type = "rw"; + int i = 0; + +#ifdef BUILD_FOR_TEST + test_canonical_append(); +#endif /* BUILD_FOR_TEST */ + + if (lname) { + /* Name given, just assume it is fully correct, try no other. */ + if (verbose > 1) { + printf("dwarfdump looking for configuration as %s\n", + lname); + } + fin = fopen(lname, type); + if (fin) { + *name_used = lname; + return fin; + } + return 0; + } + /* No name given, find a default, if we can. */ + for (i = 0; defaults[i]; ++i) { + lname = defaults[i]; +#ifdef WIN32 + /* Open the configuration file, located + in the directory where the tool is loaded from */ + { + static char szPath[MAX_PATH]; + if (GetModuleFileName(NULL,szPath,MAX_PATH)) { + char *pDir = strrchr(szPath,'/'); + if (!pDir) { + pDir = strrchr(szPath,'\\'); + if (!pDir) { + /* No file was found */ + return 0; + } + } + /* Add the configuration name to the pathname */ + ++pDir; + strcpy(pDir,"dwarfdump.conf"); + lname = szPath; + } + } +#else /* non-Win */ + if (strncmp(lname, "HOME/", 5) == 0) { + /* arbitrary size */ + char buf[2000]; + char *homedir = getenv("HOME"); + if (homedir) { + char *cp = canonical_append(buf, sizeof(buf), + homedir, lname + 5); + if (!cp) { + /* OOps, ignore this one. */ + continue; + } + lname = makename(buf); + } + } +#endif /* WIN32 */ + if (verbose > 1) { + printf("dwarfdump looking for configuration as %s\n", + lname); + } + fin = fopen(lname, type); + if (fin) { + *name_used = lname; + return fin; + } + } + return 0; +} + +/* Start at a token begin, see how long it is, + return length. */ +unsigned +find_token_len(char *cp) +{ + unsigned len = 0; + + for (; *cp; ++cp) { + if (isspace(*cp)) { + return len; + } + if (*cp == '#') { + return len; /* begins comment */ + } + ++len; + } + return len; +} + +/* + Skip past all whitespace: the only code that even knows + what whitespace is. +*/ +static char * +skipwhite(char *cp) +{ + for (; *cp; ++cp) { + if (!isspace(*cp)) { + return cp; + } + } + return cp; +} + +/* Return TRUE if ok. FALSE if find more tokens. + Emit error message if error. +*/ +static int +ensure_has_no_more_tokens(char *cp, const char *fname, unsigned long lineno) +{ + struct token_s tok; + + cp = get_token(cp, &tok); + if (tok.tk_len > 0) { + printf("dwarfdump.conf error: " + "extra characters after command operands, found " + "\"%s\" in %s line %lu\n", tok.tk_data, fname, lineno); + ++errcount; + return FALSE; + } + return TRUE; +} + + +/* There may be many beginabi: lines in a dwarfdump.conf file, + find the one we want and return its file offset. +*/ +static int +find_abi_start(FILE * stream, const char *abi_name, + long *offset, unsigned long *lineno_out) +{ + char buf[100]; + unsigned long lineno = 0; + + for (; !feof(stream);) { + + struct token_s tok; + char *line = 0; + long loffset = ftell(stream); + + line = fgets(buf, sizeof(buf), stream); + ++lineno; + if (!line) { + ++errcount; + return FALSE; + } + + line = get_token(buf, &tok); + + if (strcmp(tok.tk_data, name_begin_abi) != 0) { + continue; + } + get_token(line, &tok); + if (strcmp(tok.tk_data, abi_name) != 0) { + continue; + } + + *offset = loffset; + *lineno_out = lineno; + return TRUE; + } + + ++errcount; + return FALSE; +} + +static char *tempstr = 0; +static unsigned tempstr_len = 0; + +/* Use a global buffer (tempstr) to turn a non-delimited + input char array into a NUL-terminated C string + (with the help of makename() to get a permanent + address for the result ing string). +*/ +static char * +build_string(unsigned tlen, char *cp) +{ + if (tlen >= tempstr_len) { + free(tempstr); + tempstr = malloc(tlen + 100); + } + strncpy(tempstr, cp, tlen); + tempstr[tlen] = 0; + return makename(tempstr); +} + +/* The tokenizer for our simple parser. +*/ +static char * +get_token(char *cp, struct token_s *outtok) +{ + char *lcp = skipwhite(cp); + unsigned tlen = find_token_len(lcp); + + outtok->tk_len = tlen; + if (tlen > 0) { + outtok->tk_data = build_string(tlen, lcp); + } else { + outtok->tk_data = ""; + } + return lcp + tlen; + +} + +/* + We can't get all the field set up statically very easily, + so we get the command string length set here. +*/ +static void +finish_comtable_setup(void) +{ + unsigned i; + + for (i = 0; i < size_of_comtable; ++i) { + comtable[i].namelen = strlen(comtable[i].name); + } +} + +/* + Given a line of the table, determine if it is a command + or not, and if a command, which one is it. + Return LT_ERROR if it's not recognized. +*/ +static enum linetype_e +which_command(char *cp, struct comtable_s **tableentry) +{ + int i; + struct token_s tok; + + if (*cp == '#') + return LT_COMMENT; + if (!*cp) + return LT_BLANK; + + get_token(cp, &tok); + + for (i = 0; i < size_of_comtable; ++i) { + if (tok.tk_len == comtable[i].namelen && + strcmp(comtable[i].name, tok.tk_data) == 0) { + + *tableentry = &comtable[i]; + return comtable[i].type; + } + } + + return LT_ERROR; +} + +/* We are promised it's an abiname: command + find the name on the line. +*/ +static int +parsebeginabi(char *cp, const char *fname, const char *abiname, + unsigned long lineno, struct comtable_s *comtab) +{ + size_t clen = comtab->namelen; + size_t abinamelen = strlen(abiname); + struct token_s tok; + + + cp = cp + clen + 1; + cp = skipwhite(cp); + get_token(cp, &tok); + if (tok.tk_len != abinamelen || + strncmp(cp, abiname, abinamelen) != 0) { + printf("dwarfdump internal error: " + "mismatch %s with %s %s line %lu\n", + cp, tok.tk_data, fname, lineno); + ++errcount; + return FALSE; + } + ensure_has_no_more_tokens(cp + tok.tk_len, fname, lineno); + return TRUE; +} + +/* This expands register names as required, but does not + ensure no names duplicated. +*/ +#define CONF_TABLE_OVERSIZE 100 +static void +add_to_reg_table(struct dwconf_s *conf, + char *rname, unsigned long rval, const char *fname, + unsigned long lineno) +{ + if (conf->cf_regs_malloced == 0) { + conf->cf_regs = 0; + conf->cf_named_regs_table_size = 0; + } + if (rval >= conf->cf_named_regs_table_size) { + char **newregs = 0; + unsigned long newtablen = rval + CONF_TABLE_OVERSIZE; + unsigned long newtabsize = newtablen * sizeof(char *); + unsigned long oldtabsize = + conf->cf_named_regs_table_size * sizeof(char *); + newregs = realloc(conf->cf_regs, newtabsize); + if (!newregs) { + printf("dwarfdump: unable to malloc table %lu bytes. " + " %s line %lu\n", newtabsize, fname, lineno); + exit(1); + } + /* Zero out the new entries. */ + memset((char *) newregs + (oldtabsize), 0, + (newtabsize - oldtabsize)); + conf->cf_named_regs_table_size = (unsigned long) newtablen; + conf->cf_regs = newregs; + conf->cf_regs_malloced = 1; + } + conf->cf_regs[rval] = rname; + return; +} + +/* Our input is supposed to be a number. + Determine the value (and return it) or generate an error message. +*/ +static int +make_a_number(char *cmd, const char *filename, unsigned long + lineno, struct token_s *tok, unsigned long *val_out) +{ + char *endnum = 0; + unsigned long val = 0; + + val = strtoul(tok->tk_data, &endnum, 0); + if (val == 0 && endnum == (tok->tk_data)) { + printf("dwarfdump.conf error: " + "%s missing register number (\"%s\" not valid) %s line %lu\n", + cmd, tok->tk_data, filename, lineno); + ++errcount; + return FALSE; + } + if (endnum != (tok->tk_data + tok->tk_len)) { + printf("dwarfdump.conf error: " + "%s Missing register number (\"%s\" not valid) %s line %lu\n", + cmd, tok->tk_data, filename, lineno); + ++errcount; + return FALSE; + } + *val_out = val; + return TRUE; + + + +} + +/* We are guaranteed it's a reg: command, so parse that command + and record the interesting data. +*/ +static int +parsereg(char *cp, const char *fname, unsigned long lineno, + struct conf_internal_s *conf, struct comtable_s *comtab) +{ + size_t clen = comtab->namelen; + struct token_s regnum; + struct token_s tokreg; + unsigned long val = 0; + int ok = FALSE; + int res = FALSE; + + cp = cp + clen + 1; + cp = get_token(cp, &tokreg); + cp = get_token(cp, ®num); + if (tokreg.tk_len == 0) { + printf("dwarfdump.conf error: " + "reg: missing register name %s line %lu", + fname, lineno); + ++errcount; + return FALSE; + + } + if (regnum.tk_len == 0) { + printf("dwarfdump.conf error: " + "reg: missing register number %s line %lu", + fname, lineno); + ++errcount; + return FALSE; + } + + ok = make_a_number(comtab->name, fname, lineno, ®num, &val); + + if (!ok) { + ++errcount; + return FALSE; + } + + add_to_reg_table(conf->conf_out, tokreg.tk_data, val, fname, lineno); + + res = ensure_has_no_more_tokens(cp, fname, lineno); + return res; +} + +/* + We are guaranteed it's an frame_interface: command. + Parse it and record the value data. +*/ +static int +parseframe_interface(char *cp, const char *fname, unsigned long lineno, + struct conf_internal_s *conf, struct comtable_s *comtab) +{ + size_t clen = comtab->namelen; + struct token_s tok; + unsigned long val = 0; + int ok = FALSE; + int res = FALSE; + + cp = cp + clen + 1; + cp = get_token(cp, &tok); + if (tok.tk_len == 0) { + printf("dwarfdump.conf error: " + "%s missing interface number %s line %lu", + comtab->name, fname, lineno); + ++errcount; + return FALSE; + } + + ok = make_a_number(comtab->name, fname, lineno, &tok, &val); + + if (!ok) { + ++errcount; + return FALSE; + } + if (val != 2 && val != 3) { + printf("dwarfdump.conf error: " + "%s only interface numbers 2 or 3 are allowed, " + " not %lu. %s line %lu", + comtab->name, val, fname, lineno); + ++errcount; + return FALSE; + } + + conf->conf_out->cf_interface_number = (int) val; + res = ensure_has_no_more_tokens(cp, fname, lineno); + return res; +} + +/* + We are guaranteed it's a cfa_reg: command. Parse it + and record the important data. +*/ +static int +parsecfa_reg(char *cp, const char *fname, unsigned long lineno, + struct conf_internal_s *conf, struct comtable_s *comtab) +{ + size_t clen = comtab->namelen; + struct token_s tok; + unsigned long val = 0; + int ok = FALSE; + int res = FALSE; + + cp = cp + clen + 1; + cp = get_token(cp, &tok); + if (tok.tk_len == 0) { + printf("dwarfdump.conf error: " + "%s missing cfa_reg number %s line %lu", + comtab->name, fname, lineno); + ++errcount; + return FALSE; + } + + ok = make_a_number(comtab->name, fname, lineno, &tok, &val); + + if (!ok) { + ++errcount; + return FALSE; + } + conf->conf_out->cf_cfa_reg = (int) val; + res = ensure_has_no_more_tokens(cp, fname, lineno); + return res; +} + + +/* We are guaranteed it's an initial_reg_value: command, + parse it and put the reg value where it will be remembered. +*/ +static int +parseinitial_reg_value(char *cp, const char *fname, + unsigned long lineno, + struct conf_internal_s *conf, struct comtable_s *comtab) +{ + size_t clen = comtab->namelen; + struct token_s tok; + unsigned long val = 0; + int ok = FALSE; + int res = FALSE; + + cp = cp + clen + 1; + cp = get_token(cp, &tok); + if (tok.tk_len == 0) { + printf("dwarfdump.conf error: " + "%s missing initial reg value %s line %lu", + comtab->name, fname, lineno); + ++errcount; + return FALSE; + } + + ok = make_a_number(comtab->name, fname, lineno, &tok, &val); + + if (!ok) { + + ++errcount; + return FALSE; + } + conf->conf_out->cf_initial_rule_value = (int) val; + res = ensure_has_no_more_tokens(cp, fname, lineno); + return res; +} + +static int +parsesame_val_reg(char *cp, const char *fname, + unsigned long lineno, + struct conf_internal_s *conf, struct comtable_s *comtab) +{ + size_t clen = comtab->namelen; + struct token_s tok; + unsigned long val = 0; + int ok = FALSE; + int res = FALSE; + + cp = cp + clen + 1; + cp = get_token(cp, &tok); + if (tok.tk_len == 0) { + printf("dwarfdump.conf error: " + "%s missing same_reg value %s line %lu", + comtab->name, fname, lineno); + ++errcount; + return FALSE; + } + + ok = make_a_number(comtab->name, fname, lineno, &tok, &val); + + if (!ok) { + + ++errcount; + return FALSE; + } + conf->conf_out->cf_same_val = (int) val; + res = ensure_has_no_more_tokens(cp, fname, lineno); + return res; +} + +static int +parseundefined_val_reg(char *cp, const char *fname, + unsigned long lineno, + struct conf_internal_s *conf, struct comtable_s *comtab) +{ + size_t clen = comtab->namelen; + struct token_s tok; + unsigned long val = 0; + int ok = FALSE; + int res = FALSE; + + cp = cp + clen + 1; + cp = get_token(cp, &tok); + if (tok.tk_len == 0) { + printf("dwarfdump.conf error: " + "%s missing undefined_reg value %s line %lu", + comtab->name, fname, lineno); + ++errcount; + return FALSE; + } + + ok = make_a_number(comtab->name, fname, lineno, &tok, &val); + + if (!ok) { + + ++errcount; + return FALSE; + } + conf->conf_out->cf_undefined_val = (int) val; + res = ensure_has_no_more_tokens(cp, fname, lineno); + return res; +} + + + +/* We are guaranteed it's a table size command, parse it + and record the table size. +*/ +static int +parsereg_table_size(char *cp, const char *fname, unsigned long lineno, + struct conf_internal_s *conf, struct comtable_s *comtab) +{ + size_t clen = comtab->namelen; + struct token_s tok; + unsigned long val = 0; + int ok = FALSE; + int res = FALSE; + + cp = cp + clen + 1; + cp = get_token(cp, &tok); + if (tok.tk_len == 0) { + printf("dwarfdump.conf error: " + "%s missing reg table size value %s line %lu", + comtab->name, fname, lineno); + ++errcount; + return FALSE; + } + + ok = make_a_number(comtab->name, fname, lineno, &tok, &val); + + if (!ok) { + ++errcount; + return FALSE; + } + conf->conf_out->cf_table_entry_count = (unsigned long) val; + res = ensure_has_no_more_tokens(cp, fname, lineno); + return res; +} + +/* We are guaranteed it's a table size command, parse it + and record the table size. +*/ +static int +parseaddress_size(char *cp, const char *fname, unsigned long lineno, + struct conf_internal_s *conf, struct comtable_s *comtab) +{ + size_t clen = comtab->namelen; + struct token_s tok; + unsigned long val = 0; + int ok = FALSE; + int res = FALSE; + + cp = cp + clen + 1; + cp = get_token(cp, &tok); + if (tok.tk_len == 0) { + printf("dwarfdump.conf error: " + "%s missing address size value %s line %lu", + comtab->name, fname, lineno); + ++errcount; + return FALSE; + } + + ok = make_a_number(comtab->name, fname, lineno, &tok, &val); + + if (!ok) { + ++errcount; + return FALSE; + } + conf->conf_out->cf_address_size = (unsigned long) val; + res = ensure_has_no_more_tokens(cp, fname, lineno); + return res; +} + + +/* We are guaranteed it's an endabi: command, parse it and + check we have the right abi. +*/ +static int +parseendabi(char *cp, const char *fname, + const char *abiname, unsigned long lineno, + struct comtable_s *comtab) +{ + size_t clen = comtab->namelen; + struct token_s tok; + int res = 0; + + + cp = cp + clen + 1; + cp = get_token(cp, &tok); + if (strcmp(abiname, tok.tk_data) != 0) { + printf("%s error: " + "mismatch abi name %s (here) vs. %s (beginabi:) %s line %lu\n", + comtab->name, tok.tk_data, abiname, fname, lineno); + ++errcount; + return FALSE; + } + res = ensure_has_no_more_tokens(cp, fname, lineno); + return res; +} +static int +parseincludeabi(char *cp, const char *fname, unsigned long lineno, + char **abiname_out, + struct comtable_s *comtab) +{ + size_t clen = comtab->namelen; + struct token_s tok; + char *name = 0; + int res = FALSE; + + cp = cp + clen + 1; + cp = get_token(cp, &tok); + name = makename(tok.tk_data); + + *abiname_out = name; + res = ensure_has_no_more_tokens(cp, fname, lineno); + return res; +} + + + + +/* Return TRUE if we succeeded and filed in *out. + Return FALSE if we failed (and fill in nothing). + beginabi: <abiname> + reg: <regname> <dwarf regnumber> + frame_interface: <integer value 2 or 3> + cfa_reg: <number> + initial_reg_value: <number: normally 1034 or 1035 > + reg_table_size: <size of table> + endabi: <abiname> + + We are positioned at the start of a beginabi: line when + called. + +*/ +static int +parse_abi(FILE * stream, const char *fname, const char *abiname, + struct conf_internal_s *conf_internal, + unsigned long lineno, + unsigned int nest_level) +{ + struct dwconf_s *localconf = conf_internal->conf_out; + char buf[1000]; + int comtype = 0; + + static int first_time_done = 0; + struct comtable_s *comtabp = 0; + + if( nest_level > MAX_NEST_LEVEL) { + ++errcount; + printf("dwarfdump.conf: includeabi nest too deep in %s at line %lu\n", + fname, lineno); + return FALSE; + } + + + if (first_time_done == 0) { + finish_comtable_setup(); + first_time_done = 1; + } + + for (; !feof(stream);) { + char *line = 0; + + /* long loffset = ftell(stream); */ + line = fgets(buf, sizeof(buf), stream); + if (!line) { + ++errcount; + printf + ("dwarfdump: end of file or error before endabi: in %s, line %lu\n", + fname, lineno); + return FALSE; + } + ++lineno; + line = skipwhite(line); + comtype = which_command(line, &comtabp); + switch (comtype) { + case LT_ERROR: + ++errcount; + printf + ("dwarfdump: Unknown text in %s is \"%s\" at line %lu\n", + fname, line, lineno); + break; + case LT_COMMENT: + break; + case LT_BLANK: + break; + case LT_BEGINABI: + if (conf_internal->beginabi_lineno > 0) { + ++errcount; + printf + ("dwarfdump: Encountered beginabi: when not expected. " + "%s line %lu previous beginabi line %lu\n", fname, + lineno, conf_internal->beginabi_lineno); + } + conf_internal->beginabi_lineno = lineno; + parsebeginabi(line, fname, abiname, lineno, comtabp); + break; + + case LT_REG: + parsereg(line, fname, lineno, conf_internal, comtabp); + conf_internal->regcount++; + break; + case LT_FRAME_INTERFACE: + if (conf_internal->frame_interface_lineno > 0) { + ++errcount; + printf + ("dwarfdump: Encountered duplicate frame_interface: " + "%s line %lu previous frame_interface: line %lu\n", + fname, lineno, conf_internal->frame_interface_lineno); + } + conf_internal->frame_interface_lineno = lineno; + parseframe_interface(line, fname, + lineno, conf_internal, comtabp); + break; + case LT_CFA_REG: + if (conf_internal->cfa_reg_lineno > 0) { + printf("dwarfdump: Encountered duplicate cfa_reg: " + "%s line %lu previous cfa_reg line %lu\n", + fname, lineno, conf_internal->cfa_reg_lineno); + ++errcount; + } + conf_internal->cfa_reg_lineno = lineno; + parsecfa_reg(line, fname, lineno, conf_internal, comtabp); + break; + case LT_INITIAL_REG_VALUE: + if (conf_internal->initial_reg_value_lineno > 0) { + printf + ("dwarfdump: Encountered duplicate initial_reg_value: " + "%s line %lu previous initial_reg_value: line %lu\n", + fname, lineno, conf_internal->initial_reg_value_lineno); + ++errcount; + } + conf_internal->initial_reg_value_lineno = lineno; + parseinitial_reg_value(line, fname, + lineno, conf_internal, comtabp); + break; + case LT_SAME_VAL_REG: + if (conf_internal->same_val_reg_lineno > 0) { + ++errcount; + printf + ("dwarfdump: Encountered duplicate same_val_reg: " + "%s line %lu previous initial_reg_value: line %lu\n", + fname, lineno, conf_internal->initial_reg_value_lineno); + } + conf_internal->same_val_reg_lineno = lineno; + parsesame_val_reg(line, fname, + lineno, conf_internal, comtabp); + break; + case LT_UNDEFINED_VAL_REG: + if (conf_internal->undefined_val_reg_lineno > 0) { + ++errcount; + printf + ("dwarfdump: Encountered duplicate undefined_val_reg: " + "%s line %lu previous initial_reg_value: line %lu\n", + fname, lineno, conf_internal->initial_reg_value_lineno); + } + conf_internal->undefined_val_reg_lineno = lineno; + parseundefined_val_reg(line, fname, + lineno, conf_internal, comtabp); + break; + case LT_REG_TABLE_SIZE: + if (conf_internal->reg_table_size_lineno > 0) { + printf("dwarfdump: duplicate reg_table_size: " + "%s line %lu previous reg_table_size: line %lu\n", + fname, lineno, conf_internal->reg_table_size_lineno); + ++errcount; + } + conf_internal->reg_table_size_lineno = lineno; + parsereg_table_size(line, fname, + lineno, conf_internal, comtabp); + break; + case LT_ENDABI: + parseendabi(line, fname, abiname, lineno, comtabp); + + if (conf_internal->regcount > localconf->cf_table_entry_count) { + printf("dwarfdump: more registers named than " + " in %s ( %lu named vs %s %lu) %s line %lu\n", + abiname, (unsigned long) conf_internal->regcount, + name_reg_table_size, + (unsigned long) localconf->cf_table_entry_count, + fname, (unsigned long) lineno); + ++errcount; + } + return TRUE; + case LT_ADDRESS_SIZE: + if (conf_internal->address_size_lineno > 0) { + printf("dwarfdump: duplicate address_size: " + "%s line %lu previous address_size: line %lu\n", + fname, lineno, conf_internal->address_size_lineno); + ++errcount; + } + conf_internal->address_size_lineno = lineno; + parseaddress_size(line, fname, + lineno, conf_internal, comtabp); + break; + case LT_INCLUDEABI: { + char *abiname_inner = 0; + unsigned long abilno = conf_internal->beginabi_lineno; + int ires = 0; + ires = parseincludeabi(line,fname,lineno, &abiname_inner,comtabp); + if(ires == FALSE) { + return FALSE; + } + /* For the nested abi read, the abi line number must be + set as if not-yet-read, and then restored. */ + conf_internal->beginabi_lineno = 0; + find_conf_file_and_read_config_inner( + conf_internal->conf_name_used, + abiname_inner, conf_internal,nest_level+1); + conf_internal->beginabi_lineno = abilno; + } + break; + default: + printf + ("dwarfdump internal error, impossible line type %d %s %lu \n", + (int) comtype, fname, lineno); + exit(1); + + } + } + ++errcount; + printf("End of file, no endabi: found. %s, line %lu\n", + fname, lineno); + return FALSE; +} + +/* MIPS/IRIX frame register names. + For alternate name sets, use dwarfdump.conf or + revise dwarf.h and libdwarf.h and this table. +*/ +static char *regnames[] = { + "cfa", + "r1/at", "r2/v0", "r3/v1", + "r4/a0", "r5/a1", "r6/a2", "r7/a3", + "r8/t0", "r9/t1", "r10/t2", "r11/t3", + "r12/t4", "r13/t5", "r14/t6", "r15/t7", + "r16/s0", "r17/s1", "r18/s2", "r19/s3", + "r20/s4", "r21/s5", "r22/s6", "r23/s7", + "r24/t8", "r25/t9", "r26/k0", "r27/k1", + "r28/gp", "r29/sp", "r30/s8", "r31", + + "$f0", "$f1", + "$f2", "$f3", + "$f4", "$f5", + "$f6", "$f7", + "$f8", "$f9", + "$f10", "$f11", + "$f12", "$f13", + "$f14", "$f15", + "$f16", "$f17", + "$f18", "$f19", + "$f20", "$f21", + "$f22", "$f23", + "$f24", "$f25", + "$f26", "$f27", + "$f28", "$f29", + "$f30", "$f31", + "ra", "slk", +}; + + +/* Naming a few registers makes printing these just + a little bit faster. +*/ +static char *genericregnames[] = { + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", + "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", + "r20" +}; + +/* This is a simple generic set of registers. The + table entry count is pretty arbitrary. +*/ +void +init_conf_file_data(struct dwconf_s *config_file_data) +{ + unsigned generic_table_count; + config_file_data->cf_abi_name = ""; + config_file_data->cf_config_file_path = ""; + config_file_data->cf_interface_number = 3; + config_file_data->cf_table_entry_count = 100; + config_file_data->cf_initial_rule_value = DW_FRAME_UNDEFINED_VAL; + config_file_data->cf_cfa_reg = DW_FRAME_CFA_COL3; + config_file_data->cf_address_size = 0; + config_file_data->cf_same_val = DW_FRAME_SAME_VAL; + config_file_data->cf_undefined_val = DW_FRAME_UNDEFINED_VAL; + config_file_data->cf_regs = genericregnames; + generic_table_count = + sizeof(genericregnames) / sizeof(genericregnames[0]); + config_file_data->cf_named_regs_table_size = generic_table_count; + config_file_data->cf_regs_malloced = 0; +} + +/* These defaults match MIPS/IRIX ABI defaults, but this + function is not actually used. + For a 'generic' ABI, see -R or init_conf_file_data(). + To really get the old MIPS, use '-x abi=mips'. + For other ABIs, see -x abi=<whatever> + to configure dwarfdump (and libdwarf) frame + data reporting at runtime. +*/ +void +init_mips_conf_file_data(struct dwconf_s *config_file_data) +{ + unsigned long base_table_count = + sizeof(regnames) / sizeof(regnames[0]); + + memset(config_file_data, 0, sizeof(*config_file_data)); + /* Interface 2 is deprecated, but for testing purposes + is acceptable. */ + config_file_data->cf_interface_number = 2; + config_file_data->cf_table_entry_count = DW_REG_TABLE_SIZE; + config_file_data->cf_initial_rule_value = + DW_FRAME_REG_INITIAL_VALUE; + config_file_data->cf_cfa_reg = DW_FRAME_CFA_COL; + config_file_data->cf_address_size = 0; + config_file_data->cf_same_val = DW_FRAME_SAME_VAL; + config_file_data->cf_undefined_val = DW_FRAME_UNDEFINED_VAL; + config_file_data->cf_regs = regnames; + config_file_data->cf_named_regs_table_size = base_table_count; + config_file_data->cf_regs_malloced = 0; + if (config_file_data->cf_table_entry_count != base_table_count) { + printf("dwarfdump: improper base table initization, " + "header files wrong: " + "DW_REG_TABLE_SIZE %u != string table size %lu\n", + (unsigned) DW_REG_TABLE_SIZE, + (unsigned long) base_table_count); + exit(1); + } + return; +} + +/* A 'generic' ABI. For up to 1200 registers. + Perhaps cf_initial_rule_value should be d + UNDEFINED VALUE (1034) instead, but for the purposes of + getting the dwarfdump output correct + either will work. +*/ +void +init_generic_config_1200_regs(struct dwconf_s *config_file_data) +{ + unsigned long generic_table_count = + sizeof(genericregnames) / sizeof(genericregnames[0]); + config_file_data->cf_interface_number = 3; + config_file_data->cf_table_entry_count = 1200; + /* There is no defined name for cf_initial_rule_value, + cf_same_val, or cf_undefined_val in libdwarf.h, + these must just be high enough to be higher than + any real register number. + DW_FRAME_CFA_COL3 must also be higher than any + real register number. */ + config_file_data->cf_initial_rule_value = 1235; /* SAME VALUE */ + config_file_data->cf_cfa_reg = DW_FRAME_CFA_COL3; + config_file_data->cf_address_size = 0; + config_file_data->cf_same_val = 1235; + config_file_data->cf_undefined_val = 1234; + config_file_data->cf_regs = genericregnames; + config_file_data->cf_named_regs_table_size = generic_table_count; + config_file_data->cf_regs_malloced = 0; +} + +/* Print the 'right' string for the register we are given. + Deal sensibly with the special regs as well as numbers + we know and those we have not been told about. + +*/ +void +print_reg_from_config_data(Dwarf_Signed reg, + struct dwconf_s *config_data) +{ + char *name = 0; + + if (reg == config_data->cf_cfa_reg) { + fputs("cfa",stdout); + return; + } + if (reg == config_data->cf_undefined_val) { + fputs("u",stdout); + return; + } + if (reg == config_data->cf_same_val) { + fputs("s",stdout); + return; + } + + if (config_data->cf_regs == 0 || + reg < 0 || + reg >= config_data->cf_named_regs_table_size) { + printf("r%" DW_PR_DSd "", (Dwarf_Signed) reg); + return; + } + name = config_data->cf_regs[reg]; + if (!name) { + /* Can happen, the reg names table can be sparse. */ + printf("r%" DW_PR_DSd "", (Dwarf_Signed) reg); + return; + } + fputs(name,stdout); + return; +} diff --git a/dwarfdump/dwconf.h b/dwarfdump/dwconf.h new file mode 100644 index 0000000..471a3d4 --- /dev/null +++ b/dwarfdump/dwconf.h @@ -0,0 +1,106 @@ +/* + Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2011 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + + $Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/dwconf.h,v 1.2 2006/04/18 04:29:39 davea Exp $ */ + + +/* declarations helping configure the frame reader. */ +struct dwconf_s { + char *cf_config_file_path; + char *cf_abi_name; + + /* 2 for old, 3 for frame interface 3. 2 means use the old + mips-abi-oriented frame interface. 3 means use the new + DWARF3-capable and configureable-abi interface. + + Now, anyone who revises dwarf.h and libdwarf.h to match their + abi-of-interest will still be able to use cf_interface_number 2 + as before. But most folks don't update those header files and + instead of making *them* configurable we make dwarfdump (and + libdwarf) configurable sufficiently to print frame information + sensibly. */ + int cf_interface_number; + + /* The number of table rules , aka columns. For MIPS/IRIX is 66. */ + unsigned long cf_table_entry_count; + + /* Array of cf_table_entry_count reg names. Names not filled in + from dwarfdump.conf have NULL (0) pointer value. + cf_named_regs_table_size must match size of cf_regs array. + Set cf_regs_malloced 1 if table was malloced. Set 0 + if static. + */ + char **cf_regs; + unsigned long cf_named_regs_table_size; + int cf_regs_malloced; + + /* The 'default initial value' when intializing a table. for MIPS + is DW_FRAME_SAME_VAL(1035). For other ISA/ABIs may be + DW_FRAME_UNDEFINED_VAL(1034). */ + int cf_initial_rule_value; + int cf_same_val; + int cf_undefined_val; + + /* The number of the cfa 'register'. For cf_interface_number 2 of + MIPS this is 0. For other architectures (and anytime using + cf_interface_number 3) this should be outside the table, a + special value such as 1436, not a table column at all). */ + int cf_cfa_reg; + + /* If non-zero it is the number of bytes in an address + for the frame data. Normally it will be zero because + there are usually other sources for the correct address size. + However, with DWARF2 frame data there is no explicit address + size in the frame data and the object file might not have + other .debug_ sections to work with. + If zero, no address size was supplied, and that is normal and + the already-set (or defaulted) address size is to be used. + Only an exceptional frame configure will specify address + size here. This won't work at all if the object needing + this setting has different address size in different CUs. */ + int cf_address_size; +}; + + +/* Returns DW_DLV_OK if works. DW_DLV_ERROR if cannot do what is asked. */ +int find_conf_file_and_read_config(const char *named_file, + const char *named_abi, char **defaults, + struct dwconf_s *conf_out); +void init_conf_file_data(struct dwconf_s *config_file_data); +void init_mips_conf_file_data(struct dwconf_s *config_file_data); + +void print_reg_from_config_data(Dwarf_Signed reg, + struct dwconf_s *config_data); + + +void init_generic_config_1200_regs(struct dwconf_s *conf); diff --git a/dwarfdump/esb.c b/dwarfdump/esb.c new file mode 100644 index 0000000..8c806c8 --- /dev/null +++ b/dwarfdump/esb.c @@ -0,0 +1,242 @@ +/* + Copyright (C) 2005 Silicon Graphics, Inc. All Rights Reserved. + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + +$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/esb.c,v 1.1 2005/08/04 05:09:37 davea Exp $ */ + +/* esb.c + extensible string buffer. + + A simple means (vaguely like a C++ class) that + enables safely saving strings of arbitrary length built up + in small pieces. + +*/ + +#include "globals.h" +#include <stdarg.h> /* For va_start etc. */ +#include "esb.h" + +#define INITIAL_ALLOC 1024 +static size_t alloc_size = INITIAL_ALLOC; + + +static void +init_esb_string(struct esb_s *data, size_t min_len) +{ + string d; + + if (data->esb_allocated_size > 0) { + return; + } + if (min_len < alloc_size) { + min_len = alloc_size; + } + d = malloc(min_len); + if (!d) { + fprintf(stderr, + "dwarfdump is out of memory allocating %lu bytes\n", + (unsigned long) min_len); + exit(5); + } + data->esb_string = d; + data->esb_allocated_size = min_len; + data->esb_string[0] = 0; + data->esb_used_bytes = 0; +} + +/* Make more room. Leaving contents unchanged, effectively. +*/ +static void +allocate_more(struct esb_s *data, size_t len) +{ + size_t new_size = data->esb_allocated_size + len; + string newd = 0; + + if (new_size < alloc_size) + new_size = alloc_size; + newd = realloc(data->esb_string, new_size); + if (!newd) { + fprintf(stderr, "dwarfdump is out of memory re-allocating " + "%lu bytes\n", (unsigned long) new_size); + exit(5); + } + data->esb_string = newd; + data->esb_allocated_size = new_size; +} + +static void +esb_appendn_internal(struct esb_s *data, const char * in_string, size_t len); + +void +esb_appendn(struct esb_s *data, const char * in_string, size_t len) +{ + size_t full_len = strlen(in_string); + + if (full_len < len) { + fprintf(stderr, "dwarfdump internal error, bad string length " + " %lu < %lu \n", + (unsigned long) full_len, (unsigned long) len); + len = full_len; + } + + esb_appendn_internal(data, in_string, len); +} + +/* The length is gotten from the in_string itself. */ +void +esb_append(struct esb_s *data, const char * in_string) +{ + size_t len = strlen(in_string); + + esb_appendn_internal(data, in_string, len); +} + +/* The 'len' is believed. Do not pass in strings < len bytes long. */ +static void +esb_appendn_internal(struct esb_s *data, const char * in_string, size_t len) +{ + size_t remaining = 0; + size_t needed = len + 1; + + if (data->esb_allocated_size == 0) { + size_t maxlen = (len > alloc_size) ? len : alloc_size; + + init_esb_string(data, maxlen); + } + remaining = data->esb_allocated_size - data->esb_used_bytes; + if (remaining < needed) { + allocate_more(data, needed); + } + strncpy(&data->esb_string[data->esb_used_bytes], in_string, len); + data->esb_used_bytes += len; + /* Insist on explicit NUL terminator */ + data->esb_string[data->esb_used_bytes] = 0; +} + +/* Always returns an empty string or a non-empty string. Never 0. */ +string +esb_get_string(struct esb_s *data) +{ + if (data->esb_allocated_size == 0) { + init_esb_string(data, alloc_size); + } + return data->esb_string; +} + + +/* Sets esb_used_bytes to zero. The string is not freed and + esb_allocated_size is unchanged. */ +void +esb_empty_string(struct esb_s *data) +{ + if (data->esb_allocated_size == 0) { + init_esb_string(data, alloc_size); + } + data->esb_used_bytes = 0; + data->esb_string[0] = 0; + +} + + +/* Return esb_used_bytes. */ +size_t +esb_string_len(struct esb_s *data) +{ + return data->esb_used_bytes; +} + + +/* The following are for testing esb, not use by dwarfdump. */ + +/* *data is presumed to contain garbage, not values, and + is properly initialized. */ +void +esb_constructor(struct esb_s *data) +{ + memset(data, 0, sizeof(*data)); +} + +/* The string is freed, contents of *data set to zeroes. */ +void +esb_destructor(struct esb_s *data) +{ + if (data->esb_string) { + free(data->esb_string); + } + esb_constructor(data); +} + + +/* To get all paths in the code tested, this sets the + allocation/reallocation to the given value, which can be quite small + but must not be zero. */ +void +esb_alloc_size(size_t size) +{ + alloc_size = size; +} + +size_t +esb_get_allocated_size(struct esb_s *data) +{ + return data->esb_allocated_size; +} + +/* Append a formatted string */ +void +esb_append_printf(struct esb_s *data,const char *in_string, ...) +{ +#if WIN32 + #define NULL_DEVICE_FILE "NUL" +#else + #define NULL_DEVICE_FILE "/dev/null" +#endif /* WIN32 */ + + static FILE *null_file = NULL; + + int needed_size = 0; + int length = 0; + va_list ap; + va_start(ap,in_string); + if (null_file == NULL) { + null_file = fopen(NULL_DEVICE_FILE,"w"); + } + length = vfprintf(null_file,in_string,ap); + + /* Check if we require allocate more space */ + needed_size = data->esb_used_bytes + length; + if (needed_size > data->esb_allocated_size) { + allocate_more(data,length); + } + vsprintf(&data->esb_string[data->esb_used_bytes],in_string,ap); + data->esb_used_bytes += length; + va_end(ap); +} diff --git a/dwarfdump/esb.h b/dwarfdump/esb.h new file mode 100644 index 0000000..260db07 --- /dev/null +++ b/dwarfdump/esb.h @@ -0,0 +1,86 @@ +/* + Copyright (C) 2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2011 David Anderson. All Rights Reserved. + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + + $Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/esb.h,v 1.1 2005/08/04 05:09:37 davea Exp $ */ + + +/* esb.h + Extensible string buffer. + A simple vaguely object oriented extensible string buffer. + + The struct could be opaque here, but it seems ok to expose + the contents: simplifies debugging. +*/ + + +struct esb_s { + string esb_string; /* pointer to the data itself, or NULL. */ + size_t esb_allocated_size; /* Size of allocated data or 0 */ + size_t esb_used_bytes; /* Amount of space used or 0 */ +}; + +/* string length taken from string itself. */ +void esb_append(struct esb_s *data, const char * in_string); + +/* The 'len' is believed. Do not pass in strings < len bytes long. */ +void esb_appendn(struct esb_s *data, const char * in_string, size_t len); + +/* Always returns an empty string or a non-empty string. Never 0. */ +string esb_get_string(struct esb_s *data); + + +/* Sets esb_used_bytes to zero. The string is not freed and + esb_allocated_size is unchanged. */ +void esb_empty_string(struct esb_s *data); + + +/* Return esb_used_bytes. */ +size_t esb_string_len(struct esb_s *data); + +/* The following are for testing esb, not use by dwarfdump. */ + +/* *data is presumed to contain garbage, not values, and + is properly initialized. */ +void esb_constructor(struct esb_s *data); + +/* The string is freed, contents of *data set to zeroes. */ +void esb_destructor(struct esb_s *data); + + +/* To get all paths in the code tested, this sets the + allocation/reallocation to the given value, which can be quite small + but must not be zero. */ +void esb_alloc_size(size_t size); +size_t esb_get_allocated_size(struct esb_s *data); + +/* Append a formatted string */ +void esb_append_printf(struct esb_s *data,const char *in_string, ...); diff --git a/dwarfdump/globals.h b/dwarfdump/globals.h new file mode 100644 index 0000000..46cbc11 --- /dev/null +++ b/dwarfdump/globals.h @@ -0,0 +1,459 @@ +/* + Copyright (C) 2000,2004,2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + + +$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/globals.h,v 1.25 2006/04/17 00:09:56 davea Exp $ */ + +#ifndef globals_INCLUDED +#define globals_INCLUDED + +#include "config.h" +#if (!defined(HAVE_RAW_LIBELF_OK) && defined(HAVE_LIBELF_OFF64_OK) ) +/* At a certain point libelf.h requires _GNU_SOURCE. + here we assume the criteria in configure determine that + usefully. +*/ +#define _GNU_SOURCE 1 +#endif + +/* We want __uint32_t and __uint64_t and __int32_t __int64_t + properly defined but not duplicated, since duplicate typedefs + are not legal C. + HAVE___UINT32_T + HAVE___UINT64_T will be set by configure if + our 4 types are predefined in compiler +*/ + + +#if (!defined(HAVE___UINT32_T)) && defined(HAVE_SGIDEFS_H) +#include <sgidefs.h> /* sgidefs.h defines them */ +#define HAVE___UINT32_T 1 +#define HAVE___UINT64_T 1 +#endif + + + +#if (!defined(HAVE___UINT32_T)) && defined(HAVE_SYS_TYPES_H) && defined(HAVE___UINT32_T_IN_SYS_TYPES_H) +# include <sys/types.h> +/* we assume __[u]int32_t and __[u]int64_t defined + since __uint32_t defined in the sys/types.h in use */ +#define HAVE___UINT32_T 1 +#define HAVE___UINT64_T 1 +#endif + +#ifndef HAVE___UINT32_T +typedef int __int32_t; +typedef unsigned __uint32_t; +#define HAVE___UINT32_T 1 +#endif +#ifndef HAVE___UINT64_T +typedef long long __int64_t; +typedef unsigned long long __uint64_t; +#define HAVE___UINT64_T 1 +#endif + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* Windows specific */ +#ifdef HAVE_STDAFX_H +#include "stdafx.h" +#endif /* HAVE_STDAFX_H */ + +#ifdef HAVE_ELF_H +#include <elf.h> +#endif +#ifdef HAVE_LIBELF_H +#include <libelf.h> +#else +#ifdef HAVE_LIBELF_LIBELF_H +#include <libelf/libelf.h> +#endif +#endif +#include <dwarf.h> +#include <libdwarf.h> +#ifdef HAVE_REGEX +#include <regex.h> +#endif +typedef char * string; + +#include "checkutil.h" +#ifndef BOOLEAN_TYPEDEFED +#define BOOLEAN_TYPEDEFED +typedef int boolean; +#endif /* BOOLEAN_TYPEDEFED */ +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FAILED +#define FAILED 1 +#endif + +/* size of attrib_buffer, defined in print_die.c */ +#define ATTRIB_BUFSIZ 999 + +typedef struct { + int checks; + int errors; +} Dwarf_Check_Result; + +extern boolean do_check_dwarf; +extern boolean do_print_dwarf; + +extern boolean record_dwarf_error; /* A test has failed, this + is normally set FALSE shortly after being set TRUE, it is + a short-range hint we should print something we might not + otherwise print (under the circumstances). */ + +/* Compilation Unit information for improved error messages. + If the strings are too short we just truncate so fixed length + here is fine. */ +#define COMPILE_UNIT_NAME_LEN 512 +extern char PU_name[COMPILE_UNIT_NAME_LEN]; /* PU Name */ +extern char CU_name[COMPILE_UNIT_NAME_LEN]; /* CU Name */ +extern char CU_producer[COMPILE_UNIT_NAME_LEN]; /* CU Producer Name */ + +extern boolean seen_PU; /* Detected a PU. */ +extern boolean seen_CU; /* Detected a CU. */ +extern boolean need_CU_name; /* Need CU name. */ +extern boolean need_CU_base_address; /* Need CU Base address. */ +extern boolean need_CU_high_address; /* Need CU High address. */ +extern boolean need_PU_valid_code; /* Need PU valid code. */ + +extern boolean seen_PU_base_address; /* Detected a Base address for PU */ +extern boolean seen_PU_high_address; /* Detected a High address for PU */ +extern Dwarf_Addr PU_base_address; /* PU Base address */ +extern Dwarf_Addr PU_high_address; /* PU High address */ + +extern Dwarf_Off DIE_offset; /* DIE offset in compile unit. */ +extern Dwarf_Off DIE_overall_offset; /* DIE offset in .debug_info. */ + +/* Current CU information for better error reporting. */ +extern Dwarf_Off DIE_CU_offset; /* CU DIE offset in compile unit */ +extern Dwarf_Off DIE_CU_overall_offset; /* CU DIE offset in .debug_info */ +extern int current_section_id; /* Section being process. */ + +extern Dwarf_Addr CU_base_address; /* CU Base address. */ +extern Dwarf_Addr CU_high_address; /* CU High address. */ + +extern Dwarf_Addr elf_max_address; /* Largest representable + address offset. */ +extern Dwarf_Half elf_address_size; /* Target pointer size. */ + +/* Ranges and Location tables for better error checking: see + dwarfdump.c comments for more information. */ +extern Bucket_Group *pRangesInfo; +extern Bucket_Group *pLinkonceInfo; +extern Bucket_Group *pVisitedInfo; + +/* Display parent/children when in wide format. */ +extern boolean display_parent_tree; +extern boolean display_children_tree; +extern int stop_indent_level; + +/* Print search results when in wide format. */ +extern boolean search_wide_format; +extern boolean search_is_on; + +const extern char *search_any_text; +const extern char *search_match_text; +const extern char *search_regex_text; +#ifdef HAVE_REGEX +extern regex_t search_re; +#endif +extern boolean is_strstrnocase(const char *data, const char *pattern); + +/* Options to enable debug tracing. */ +#define MAX_TRACE_LEVEL 10 +extern int nTrace[MAX_TRACE_LEVEL + 1]; + +#define DUMP_RANGES_INFO 1 /* Dump RangesInfo Table. */ +#define DUMP_LOCATION_SECTION_INFO 2 /* Dump Location (.debug_loc) Info. */ +#define DUMP_RANGES_SECTION_INFO 3 /* Dump Ranges (.debug_ranges) Info. */ +#define DUMP_LINKONCE_INFO 4 /* Dump Linkonce Table. */ +#define DUMP_VISITED_INFO 5 /* Dump Visited Info. */ + +#define dump_ranges_info nTrace[DUMP_RANGES_INFO] +#define dump_location_section_info nTrace[DUMP_LOCATION_SECTION_INFO] +#define dump_ranges_section_info nTrace[DUMP_RANGES_SECTION_INFO] +#define dump_linkonce_info nTrace[DUMP_LINKONCE_INFO] +#define dump_visited_info nTrace[DUMP_VISITED_INFO] + +/* Section IDs */ +#define DEBUG_ABBREV 1 +#define DEBUG_ARANGES 2 +#define DEBUG_FRAME 3 +#define DEBUG_INFO 4 +#define DEBUG_LINE 5 +#define DEBUG_LOC 6 +#define DEBUG_MACINFO 7 +#define DEBUG_PUBNAMES 8 +#define DEBUG_RANGES 9 +#define DEBUG_STATIC_VARS 10 +#define DEBUG_STATIC_FUNC 11 +#define DEBUG_STR 12 +#define DEBUG_WEAKNAMES 13 +#define DEBUG_TYPES 14 + +extern int verbose; +extern boolean dense; +extern boolean ellipsis; +extern boolean use_mips_regnames; +extern boolean show_global_offsets; +extern boolean show_form_used; +extern boolean display_offsets; + +extern boolean check_pubname_attr; +extern boolean check_attr_tag; +extern boolean check_tag_tree; +extern boolean check_type_offset; +extern boolean check_decl_file; +extern boolean check_lines; +extern boolean check_ranges; /* Ranges (aranges & ranges) check */ +extern boolean check_fdes; +extern boolean check_aranges; +extern boolean check_harmless; +extern boolean check_abbreviations; +extern boolean check_dwarf_constants; +extern boolean check_di_gaps; +extern boolean check_forward_decl; +extern boolean check_self_references; +extern boolean suppress_nested_name_search; +extern boolean suppress_check_extensions_tables; + +extern int break_after_n_units; + +extern boolean check_names; /* Check for invalid names */ +extern boolean check_verbose_mode; /* During '-k' mode, display errors */ +extern boolean check_frames; /* Frames check */ +extern boolean check_frames_extended;/* Extensive frames check */ +extern boolean check_locations; /* Location list check */ + +/* Check categories corresponding to the -k option */ +typedef enum /* Dwarf_Check_Categories */ { + abbrev_code_result, + pubname_attr_result, + reloc_offset_result, + attr_tag_result, + tag_tree_result, + type_offset_result, + decl_file_result, + ranges_result, + lines_result, + aranges_result, + /* Harmless errors are errors detected inside libdwarf but + not reported via DW_DLE_ERROR returns because the errors + won't really affect client code. The 'harmless' errors + are reported and otherwise ignored. It is difficult to report + the error when the error is noticed by libdwarf, the error + is reported at a later time. + The other errors dwarfdump reports are also generally harmless + but are detected by dwarfdump so it's possble to report the + error as soon as the error is discovered. */ + harmless_result, + fde_duplication, + frames_result, + locations_result, + names_result, + abbreviations_result, + dwarf_constants_result, + di_gaps_result, + forward_decl_result, + self_references_result, + total_check_result, + LAST_CATEGORY /* Must be last */ +} Dwarf_Check_Categories; + +extern boolean info_flag; +extern boolean line_flag; +extern boolean use_old_dwarf_loclist; +extern boolean producer_children_flag; /* List of CUs per compiler */ + +extern char cu_name[ ]; +extern boolean cu_name_flag; +extern Dwarf_Unsigned cu_offset; +extern Dwarf_Off fde_offset_for_cu_low; +extern Dwarf_Off fde_offset_for_cu_high; + +/* Process TAGs for checking mode and reset pRangesInfo table + if appropriate. */ +extern void tag_specific_checks_setup(Dwarf_Half val,int die_indent_level); + +extern char *program_name; +extern Dwarf_Error err; +extern void print_error_and_continue (Dwarf_Debug dbg, string msg,int res, Dwarf_Error err); +extern void print_error (Dwarf_Debug dbg, string msg,int res, Dwarf_Error err); + +extern void print_line_numbers_this_cu (Dwarf_Debug dbg, Dwarf_Die in_die); + +struct dwconf_s; +extern void print_frames (Dwarf_Debug dbg, int print_debug_frame, + int print_eh_frame,struct dwconf_s *); +extern void print_ranges (Dwarf_Debug dbg); +extern void print_pubnames (Dwarf_Debug dbg); +extern void print_macinfo (Dwarf_Debug dbg); +extern void print_infos (Dwarf_Debug dbg,Dwarf_Bool is_info); +extern void print_locs (Dwarf_Debug dbg); +extern void print_abbrevs (Dwarf_Debug dbg); +extern void print_strings (Dwarf_Debug dbg); +extern void print_aranges (Dwarf_Debug dbg); +extern void print_relocinfo (Dwarf_Debug dbg,unsigned reloc_map); +extern void print_static_funcs(Dwarf_Debug dbg); +extern void print_static_vars(Dwarf_Debug dbg); +enum type_type_e {SGI_TYPENAME, DWARF_PUBTYPES} ; +extern void print_types(Dwarf_Debug dbg,enum type_type_e type_type); +extern void print_weaknames(Dwarf_Debug dbg); +extern void print_exception_tables(Dwarf_Debug dbg); + +struct esb_s; +extern void print_ranges_list_to_extra(Dwarf_Debug dbg, + Dwarf_Unsigned off, + Dwarf_Ranges *rangeset, + Dwarf_Signed rangecount, + Dwarf_Unsigned bytecount, + struct esb_s *stringbuf); +boolean should_skip_this_cu(Dwarf_Debug dbg, Dwarf_Die cu_die, Dwarf_Error err); + +/* Returns the DW_AT_name of the CU */ +string old_get_cu_name(Dwarf_Debug dbg,Dwarf_Die cu_die,Dwarf_Error err); + +/* Returns the producer of the CU */ +int get_cu_name(Dwarf_Debug dbg,Dwarf_Die cu_die, + Dwarf_Error err,char **short_name,char **long_name); +int get_producer_name(Dwarf_Debug dbg,Dwarf_Die cu_die, + Dwarf_Error err,char **producer_name); + +/* Get number of abbreviations for a CU */ +extern void get_abbrev_array_info(Dwarf_Debug dbg,Dwarf_Unsigned offset); +/* Validate an abbreviation */ +extern void validate_abbrev_code(Dwarf_Debug dbg,Dwarf_Unsigned abbrev_code); + +extern void print_die_and_children( + Dwarf_Debug dbg, + Dwarf_Die in_die, + Dwarf_Bool is_info, + char **srcfiles, + Dwarf_Signed cnt); +extern boolean print_one_die( + Dwarf_Debug dbg, + Dwarf_Die die, + boolean print_information, + int die_indent_level, + char **srcfiles, + Dwarf_Signed cnt, + boolean ignore_die_stack); + +/* Check for specific compiler */ +extern boolean checking_this_compiler(); +extern void update_compiler_target(const char *producer_name); +extern void add_cu_name_compiler_target(char *name); + +/* General error reporting routines. These were + macros for a short time and when changed into functions + they kept (for now) their capitalization. + The capitalization will likely change. */ +extern void PRINT_CU_INFO(); +extern void DWARF_CHECK_COUNT(Dwarf_Check_Categories category, int inc); +extern void DWARF_ERROR_COUNT(Dwarf_Check_Categories category, int inc); +extern void DWARF_CHECK_ERROR_PRINT_CU(); +extern void DWARF_CHECK_ERROR(Dwarf_Check_Categories category, + const char *str); +extern void DWARF_CHECK_ERROR2(Dwarf_Check_Categories category, + const char *str1, const char *str2); +extern void DWARF_CHECK_ERROR3(Dwarf_Check_Categories category, + const char *str1, const char *str2, const char *strexpl); + +struct esb_s; + +extern Dwarf_Die current_cu_die_for_print_frames; /* This is + an awful hack, making current_cu_die_for_print_frames public. + But it enables cleaning up (doing all dealloc needed). */ + +extern void printreg(Dwarf_Signed reg,struct dwconf_s *config_data); +extern void print_frame_inst_bytes(Dwarf_Debug dbg, + Dwarf_Ptr cie_init_inst, Dwarf_Signed len, + Dwarf_Signed data_alignment_factor, + int code_alignment_factor, Dwarf_Half addr_size, + struct dwconf_s *config_data); + +int +get_proc_name(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr low_pc, + char *proc_name_buf, int proc_name_buf_len, void **pcMap); + +void get_attr_value(Dwarf_Debug dbg, Dwarf_Half tag, + Dwarf_Die die, + Dwarf_Attribute attrib, + char **srcfiles, + Dwarf_Signed cnt, struct esb_s *esbp, + int show_form,int local_verbose); + + +extern Dwarf_Unsigned local_dwarf_decode_u_leb128(unsigned char *leb128, + unsigned int *leb128_length); + +extern Dwarf_Signed local_dwarf_decode_s_leb128(unsigned char *leb128, + unsigned int *leb128_length); + +extern void dump_block(char *prefix, char *data, Dwarf_Signed len); + +extern void format_sig8_string(Dwarf_Sig8 *data,struct esb_s *out); + +int +dwarfdump_print_one_locdesc(Dwarf_Debug dbg, + Dwarf_Locdesc * llbuf, + int skip_locdesc_header, + struct esb_s *string_out); +void clean_up_die_esb(); +void clean_up_syms_malloc_data(); +void safe_strcpy(char *out, long outlen, const char *in, long inlen); + + +void print_any_harmless_errors(Dwarf_Debug dbg); + +/* Definitions for printing relocations. */ +#define DW_SECTION_REL_DEBUG_INFO 0 +#define DW_SECTION_REL_DEBUG_LINE 1 +#define DW_SECTION_REL_DEBUG_PUBNAMES 2 +#define DW_SECTION_REL_DEBUG_ABBREV 3 +#define DW_SECTION_REL_DEBUG_ARANGES 4 +#define DW_SECTION_REL_DEBUG_FRAME 5 +#define DW_SECTION_REL_DEBUG_LOC 6 +#define DW_SECTION_REL_DEBUG_RANGES 7 +#define DW_SECTION_REL_DEBUG_TYPES 8 + +#endif /* globals_INCLUDED */ diff --git a/dwarfdump/install.sh b/dwarfdump/install.sh new file mode 100755 index 0000000..0ff4b6a --- /dev/null +++ b/dwarfdump/install.sh @@ -0,0 +1,119 @@ +#!/bin/sh + +# +# install - install a program, script, or datafile +# This comes from X11R5; it is not part of GNU. +# +# $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $ +# +# This script is compatible with the BSD install script, but was written +# from scratch. +# + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" + +instcmd="$mvprog" +chmodcmd="" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +fi + +if [ x"$dst" = x ] +then + echo "install: no destination specified" + exit 1 +fi + + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + +if [ -d $dst ] +then + dst="$dst"/`basename $src` +fi + +# Make a temp file name in the proper directory. + +dstdir=`dirname $dst` +dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + +$doit $instcmd $src $dsttmp + +# and set any options; do chmod last to preserve setuid bits + +if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi +if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi +if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi +if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi + +# Now rename the file to the real destination. + +$doit $rmcmd $dst +$doit $mvcmd $dsttmp $dst + + +exit 0 diff --git a/dwarfdump/makename.c b/dwarfdump/makename.c new file mode 100644 index 0000000..e97e1d0 --- /dev/null +++ b/dwarfdump/makename.c @@ -0,0 +1,68 @@ + +/* + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + makename.c + $Revision: 1.4 $ + $Date: 2005/11/08 21:48:42 $ + + This used to be elaborate stuff. + Now it is trivial, as duplicating names is + unimportant in dwarfdump (in general). + + And in fact, this is only called for attributes and + tags etc whose true name is unknown. Not for + any normal case. + +*/ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include "makename.h" + +char * +makename(const char *s) +{ + char *newstr; + + if (!s) { + return ""; + } + + newstr = strdup(s); + if (newstr == 0) { + fprintf(stderr, "Out of memory mallocing %d bytes\n", + (int) strlen(s)); + exit(1); + } + return newstr; +} diff --git a/dwarfdump/makename.h b/dwarfdump/makename.h new file mode 100644 index 0000000..da1f798 --- /dev/null +++ b/dwarfdump/makename.h @@ -0,0 +1,53 @@ +#ifndef names_h +#define names_h +/* + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2011 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan +*/ + +/* makename.h + $Revision: 1.3 $ + $Date: 2004/10/28 22:26:58 $ + + This is for putting strings into stable storage. + + Effectively an strdup() wrapper. + + Rarely called. + + It leaks memory, (the memory + is never freed) but that seems unimportant since + use of this is very rare. +*/ + +char * makename(const char *); /* Makes a copy of the string in + a malloc area. Can never return 0. */ +#endif diff --git a/dwarfdump/naming.c b/dwarfdump/naming.c new file mode 100644 index 0000000..115fd09 --- /dev/null +++ b/dwarfdump/naming.c @@ -0,0 +1,261 @@ +/* + Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved. + Portions Copyright (C) 2010-2011 SN Systems Ltd. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + + + +/* naming.c */ +#include "globals.h" +#include "dwarf.h" +#include "libdwarf.h" +#include "makename.h" + +static const char * +skipunder(const char *v) +{ + const char *cp = v; + int undercount = 0; + for( ; *cp ; ++cp) { + if( *cp == '_') { + ++undercount; + if(undercount == 2) { + return cp+1; + } + } + } + return ""; +} + +static const char * +ellipname(int res, int val_in, const char *v,const char *ty,int printonerr) +{ +#ifndef TRIVIAL_NAMING + if (check_dwarf_constants && checking_this_compiler()) { + DWARF_CHECK_COUNT(dwarf_constants_result,1); + } +#endif + if(res != DW_DLV_OK) { + char buf[100]; + char *n; + snprintf(buf,sizeof(buf),"<Unknown %s value 0x%x>",ty,val_in); + /* Capture any name error in DWARF constants */ +#ifndef TRIVIAL_NAMING + if(printonerr && check_dwarf_constants && checking_this_compiler()) { + if (check_verbose_mode) { + fprintf(stderr,"%s of %d (0x%x) is unknown to dwarfdump. " + "Continuing. \n",ty,val_in,val_in ); + } + DWARF_ERROR_COUNT(dwarf_constants_result,1); + DWARF_CHECK_ERROR_PRINT_CU(); + } +#else + /* This is for the tree-generation, not dwarfdump itself. */ + if(printonerr) { + fprintf(stderr,"%s of %d (0x%x) is unknown to dwarfdump. " + "Continuing. \n",ty,val_in,val_in ); + } +#endif + n = makename(buf); + return n; + } + if(ellipsis) { + return skipunder(v); + } + return v; +} + +const char * get_TAG_name(unsigned int val_in,int printonerr) +{ + const char *v = 0; + int res = dwarf_get_TAG_name(val_in,&v); + return ellipname(res,val_in,v,"TAG",printonerr); +} +const char * get_children_name(unsigned int val_in,int printonerr) +{ + const char *v = 0; + int res = dwarf_get_children_name(val_in,&v); + return ellipname(res,val_in,v,"children",printonerr); +} +const char * get_FORM_name(unsigned int val_in,int printonerr) +{ + const char *v = 0; + int res = dwarf_get_FORM_name(val_in,&v); + return ellipname(res,val_in,v,"FORM",printonerr); +} +const char * get_AT_name(unsigned int val_in,int printonerr) +{ + const char *v = 0; + int res = dwarf_get_AT_name(val_in,&v); + return ellipname(res,val_in,v,"AT",printonerr); +} +const char * get_OP_name(unsigned int val_in,int printonerr) +{ + const char *v = 0; + int res = dwarf_get_OP_name(val_in,&v); + return ellipname(res,val_in,v,"OP",printonerr); +} +const char * get_ATE_name(unsigned int val_in,int printonerr) +{ + const char *v = 0; + int res = dwarf_get_ATE_name(val_in,&v); + return ellipname(res,val_in,v,"ATE",printonerr); +} +const char * get_DS_name(unsigned int val_in,int printonerr) +{ + const char *v = 0; + int res = dwarf_get_DS_name(val_in,&v); + return ellipname(res,val_in,v,"DS",printonerr); +} +const char * get_END_name(unsigned int val_in,int printonerr) +{ + const char *v = 0; + int res = dwarf_get_END_name(val_in,&v); + return ellipname(res,val_in,v,"END",printonerr); +} +const char * get_ATCF_name(unsigned int val_in,int printonerr) +{ + const char *v = 0; + int res = dwarf_get_ATCF_name(val_in,&v); + return ellipname(res,val_in,v,"ATCF",printonerr); +} +const char * get_ACCESS_name(unsigned int val_in,int printonerr) +{ + const char *v = 0; + int res = dwarf_get_ACCESS_name(val_in,&v); + return ellipname(res,val_in,v,"ACCESS",printonerr); +} +const char * get_VIS_name(unsigned int val_in,int printonerr) +{ + const char *v = 0; + int res = dwarf_get_VIS_name(val_in,&v); + return ellipname(res,val_in,v,"VIS",printonerr); +} +const char * get_VIRTUALITY_name(unsigned int val_in,int printonerr) +{ + const char *v = 0; + int res = dwarf_get_VIRTUALITY_name(val_in,&v); + return ellipname(res,val_in,v,"VIRTUALITY",printonerr); +} +const char * get_LANG_name(unsigned int val_in,int printonerr) +{ + const char *v = 0; + int res = dwarf_get_LANG_name(val_in,&v); + return ellipname(res,val_in,v,"LANG",printonerr); +} +const char * get_ID_name(unsigned int val_in,int printonerr) +{ + const char *v = 0; + int res = dwarf_get_ID_name(val_in,&v); + return ellipname(res,val_in,v,"ID",printonerr); +} +const char * get_CC_name(unsigned int val_in,int printonerr) +{ + const char *v = 0; + int res = dwarf_get_CC_name(val_in,&v); + return ellipname(res,val_in,v,"CC",printonerr); +} +const char * get_INL_name(unsigned int val_in,int printonerr) +{ + const char *v = 0; + int res = dwarf_get_INL_name(val_in,&v); + return ellipname(res,val_in,v,"INL",printonerr); +} +const char * get_ORD_name(unsigned int val_in,int printonerr) +{ + const char *v = 0; + int res = dwarf_get_ORD_name(val_in,&v); + return ellipname(res,val_in,v,"ORD",printonerr); +} +const char * get_DSC_name(unsigned int val_in,int printonerr) +{ + const char *v = 0; + int res = dwarf_get_DSC_name(val_in,&v); + return ellipname(res,val_in,v,"DSC",printonerr); +} +const char * get_LNS_name(unsigned int val_in,int printonerr) +{ + const char *v = 0; + int res = dwarf_get_LNS_name(val_in,&v); + return ellipname(res,val_in,v,"LNS",printonerr); +} +const char * get_LNE_name(unsigned int val_in,int printonerr) +{ + const char *v = 0; + int res = dwarf_get_LNE_name(val_in,&v); + return ellipname(res,val_in,v,"LNE",printonerr); +} +const char * get_MACINFO_name(unsigned int val_in,int printonerr) +{ + const char *v = 0; + int res = dwarf_get_MACINFO_name(val_in,&v); + return ellipname(res,val_in,v,"MACINFO",printonerr); +} +const char * get_CFA_name(unsigned int val_in,int printonerr) +{ + const char *v = 0; + int res = dwarf_get_CFA_name(val_in,&v); + return ellipname(res,val_in,v,"CFA",printonerr); +} +const char * get_EH_name(unsigned int val_in,int printonerr) +{ + const char *v = 0; + int res = dwarf_get_EH_name(val_in,&v); + return ellipname(res,val_in,v,"EH",printonerr); +} +const char * get_FRAME_name(unsigned int val_in,int printonerr) +{ + const char *v = 0; + int res = dwarf_get_FRAME_name(val_in,&v); + return ellipname(res,val_in,v,"FRAME",printonerr); +} +const char * get_CHILDREN_name(unsigned int val_in,int printonerr) +{ + const char *v = 0; + int res = dwarf_get_CHILDREN_name(val_in,&v); + return ellipname(res,val_in,v,"CHILDREN",printonerr); +} +const char * get_ADDR_name(unsigned int val_in,int printonerr) +{ + const char *v = 0; + int res = dwarf_get_ADDR_name(val_in,&v); + return ellipname(res,val_in,v,"ADDR",printonerr); +} + + diff --git a/dwarfdump/naming.h b/dwarfdump/naming.h new file mode 100644 index 0000000..89a1594 --- /dev/null +++ b/dwarfdump/naming.h @@ -0,0 +1,73 @@ + +/* + Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved. + + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + + +/* naming.h */ + +extern const char * get_TAG_name(unsigned int val_in,int printonerr); +extern const char * get_children_name(unsigned int val_in,int printonerr); +extern const char * get_FORM_name(unsigned int val_in,int printonerr); +extern const char * get_AT_name(unsigned int val_in,int printonerr); +extern const char * get_OP_name(unsigned int val_in,int printonerr); +extern const char * get_ATE_name(unsigned int val_in,int printonerr); +extern const char * get_DS_name(unsigned int val_in,int printonerr); +extern const char * get_END_name(unsigned int val_in,int printonerr); +extern const char * get_ATCF_name(unsigned int val_in,int printonerr); +extern const char * get_ACCESS_name(unsigned int val_in,int printonerr); +extern const char * get_VIS_name(unsigned int val_in,int printonerr); +extern const char * get_VIRTUALITY_name(unsigned int val_in,int printonerr); +extern const char * get_LANG_name(unsigned int val_in,int printonerr); +extern const char * get_ID_name(unsigned int val_in,int printonerr); +extern const char * get_CC_name(unsigned int val_in,int printonerr); +extern const char * get_INL_name(unsigned int val_in,int printonerr); +extern const char * get_ORD_name(unsigned int val_in,int printonerr); +extern const char * get_DSC_name(unsigned int val_in,int printonerr); +extern const char * get_LNS_name(unsigned int val_in,int printonerr); +extern const char * get_LNE_name(unsigned int val_in,int printonerr); +extern const char * get_MACINFO_name(unsigned int val_in,int printonerr); +extern const char * get_CFA_name(unsigned int val_in,int printonerr); +extern const char * get_EH_name(unsigned int val_in,int printonerr); +extern const char * get_FRAME_name(unsigned int val_in,int printonerr); +extern const char * get_CHILDREN_name(unsigned int val_in,int printonerr); +extern const char * get_ADDR_name(unsigned int val_in,int printonerr); + + diff --git a/dwarfdump/print_abbrevs.c b/dwarfdump/print_abbrevs.c new file mode 100644 index 0000000..76a08f5 --- /dev/null +++ b/dwarfdump/print_abbrevs.c @@ -0,0 +1,304 @@ +/* + Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. + Portions Copyright 2009-2011 SN Systems Ltd. All rights reserved. + Portions Copyright 2008-2011 David Anderson. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + + +$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + +#include "globals.h" +#include "naming.h" +#include "dwconf.h" +#include "esb.h" + +#include "print_sections.h" + + +/* The following relevent for one specific Linker. */ +#define SNLINKER_MAX_ATTRIB_COUNT 16 + +/* Print data in .debug_abbrev + This is inherently unsafe as it assumes there + are no byte sequences in .debug_abbrev other than + legal abbrev sequences. But the Dwarf spec + does not promise that. The spec only promises + that any bytes at an offset referred to from + .debug_info are legal sequences. +*/ +extern void +print_abbrevs(Dwarf_Debug dbg) +{ + Dwarf_Abbrev ab; + Dwarf_Unsigned offset = 0; + Dwarf_Unsigned length = 0; + Dwarf_Unsigned abbrev_entry_count = 0; + /* Maximum defined tag is 0xffff, DW_TAG_hi_user. */ + Dwarf_Half tag = 0; + Dwarf_Half attr = 0; + Dwarf_Signed form = 0; + Dwarf_Off off = 0; + Dwarf_Unsigned i = 0; + const char * child_name = 0; + Dwarf_Unsigned abbrev_num = 1; + Dwarf_Signed child_flag = 0; + int abres = 0; + int tres = 0; + int acres = 0; + Dwarf_Unsigned abbrev_code = 0; + + current_section_id = DEBUG_ABBREV; + + if (do_print_dwarf) { + printf("\n.debug_abbrev\n"); + } + while ((abres = dwarf_get_abbrev(dbg, offset, &ab, + &length, &abbrev_entry_count, + &err)) == DW_DLV_OK) { + + if (abbrev_entry_count == 0) { + /* Simple innocuous zero : null abbrev entry */ + if (dense) { + printf("<%" DW_PR_DUu "><0x%" DW_PR_XZEROS DW_PR_DUx "><%" + DW_PR_DSd "><%s>\n", + abbrev_num, + offset, + (Dwarf_Signed) /* abbrev_code */ 0, + "null .debug_abbrev entry"); + } else { + printf("<%5" DW_PR_DUu "><0x%" DW_PR_XZEROS DW_PR_DUx + "><code: %3" DW_PR_DSd "> %-20s\n", + abbrev_num, + offset, + (Dwarf_Signed) /* abbrev_code */ 0, + "null .debug_abbrev entry"); + } + + offset += length; + ++abbrev_num; + dwarf_dealloc(dbg, ab, DW_DLA_ABBREV); + continue; + } + tres = dwarf_get_abbrev_tag(ab, &tag, &err); + if (tres != DW_DLV_OK) { + dwarf_dealloc(dbg, ab, DW_DLA_ABBREV); + print_error(dbg, "dwarf_get_abbrev_tag", tres, err); + } + tres = dwarf_get_abbrev_code(ab, &abbrev_code, &err); + if (tres != DW_DLV_OK) { + dwarf_dealloc(dbg, ab, DW_DLA_ABBREV); + print_error(dbg, "dwarf_get_abbrev_code", tres, err); + } + if (dense) { + printf("<%" DW_PR_DUu "><0x%" DW_PR_XZEROS DW_PR_DUx + "><%" DW_PR_DSd "><%s>", + abbrev_num, + offset, abbrev_code, + get_TAG_name(tag,dwarf_names_print_on_error)); + } + else { + printf("<%5" DW_PR_DUu "><0x%" DW_PR_XZEROS DW_PR_DUx "><code: %3" + DW_PR_DSd "> %-20s", + abbrev_num, + offset, abbrev_code, + get_TAG_name(tag,dwarf_names_print_on_error)); + } + /* Process specific TAGs specially. */ + tag_specific_checks_setup(tag,0); + ++abbrev_num; + acres = dwarf_get_abbrev_children_flag(ab, &child_flag, &err); + if (acres == DW_DLV_ERROR) { + dwarf_dealloc(dbg, ab, DW_DLA_ABBREV); + print_error(dbg, "dwarf_get_abbrev_children_flag", acres, + err); + } + if (acres == DW_DLV_NO_ENTRY) { + child_flag = 0; + } + child_name = get_children_name(child_flag, + dwarf_names_print_on_error); + if (dense) + printf(" %s", child_name); + else + printf(" %s\n", child_name); + /* Abbrev just contains the format of a die, which debug_info + then points to with the real data. So here we just print the + given format. */ + for (i = 0; i < abbrev_entry_count; i++) { + int aeres = 0; + + aeres = + dwarf_get_abbrev_entry(ab, i, &attr, &form, &off, &err); + if (aeres == DW_DLV_ERROR) { + dwarf_dealloc(dbg, ab, DW_DLA_ABBREV); + print_error(dbg, "dwarf_get_abbrev_entry", aeres, err); + } + if (aeres == DW_DLV_NO_ENTRY) { + attr = -1LL; + form = -1LL; + } + if (dense) { + printf(" <%ld>%s<%s>", (unsigned long) off, + get_AT_name(attr,dwarf_names_print_on_error), + get_FORM_name((Dwarf_Half) form, + dwarf_names_print_on_error)); + } else { + printf(" <0x%08lx> %-28s%s\n", + (unsigned long) off, + get_AT_name(attr, + dwarf_names_print_on_error), + get_FORM_name((Dwarf_Half) form, + dwarf_names_print_on_error)); + } + } + dwarf_dealloc(dbg, ab, DW_DLA_ABBREV); + offset += length; + if (dense) { + printf("\n"); + } + } + if (abres == DW_DLV_ERROR) { + print_error(dbg, "dwarf_get_abbrev", abres, err); + } +} + +/* Number of abbreviations for current CU */ +static Dwarf_Unsigned CU_abbrev_count = 0; + +/* Abbreviations array info for checking abbrev tags. + The [zero] entry is not used. + We never shrink the array, but it never grows beyond + the largest abbreviation count of all the CUs. +*/ + +static Dwarf_Signed *abbrev_array = NULL; +/* Size of the array, the same as the abbrev tag + count of the CU with the most of them. */ +static Dwarf_Unsigned abbrev_array_size = 0; +#define ABBREV_ARRAY_INITIAL_SIZE 64 + +/* Calculate the number of abbreviations for the + current CU and set up a basic abbreviations array info, + storing the number of attributes per abbreviation. +*/ +void +get_abbrev_array_info(Dwarf_Debug dbg, Dwarf_Unsigned offset_in) +{ + Dwarf_Unsigned offset = offset_in; + if (check_abbreviations) { + Dwarf_Abbrev ab; + Dwarf_Unsigned length = 0; + Dwarf_Unsigned abbrev_entry_count = 0; + Dwarf_Unsigned abbrev_code; + int abres = DW_DLV_OK; + Dwarf_Error err; + + Dwarf_Bool bMore = TRUE; + CU_abbrev_count = 0; + + if (abbrev_array == NULL) { + /* Allocate initial abbreviation array info */ + abbrev_array = (Dwarf_Signed *) + calloc(ABBREV_ARRAY_INITIAL_SIZE+1,sizeof(Dwarf_Signed)); + abbrev_array_size = ABBREV_ARRAY_INITIAL_SIZE; + } else { + /* Clear out values from previous CU */ + memset((void *)abbrev_array,0, + (abbrev_array_size+1) * sizeof(Dwarf_Signed)); + } + + while (bMore && (abres = dwarf_get_abbrev(dbg, offset, &ab, + &length, &abbrev_entry_count, + &err)) == DW_DLV_OK) { + dwarf_get_abbrev_code(ab,&abbrev_code,&err); + if (abbrev_code == 0) { + /* End of abbreviation table for this CU */ + ++offset; /* Skip abbreviation code */ + bMore = FALSE; + } else { + /* Valid abbreviation code */ + if (abbrev_code > 0) { + if (abbrev_code > abbrev_array_size) { + /* Resize abbreviation array */ + abbrev_array_size *= 2; + abbrev_array = (Dwarf_Signed *) + realloc(abbrev_array, + (abbrev_array_size+1) * sizeof(Dwarf_Signed)); + } + abbrev_array[abbrev_code] = abbrev_entry_count; + ++CU_abbrev_count; + offset += length; + } else { + /* Invalid abbreviation code */ + print_error(dbg, "get_abbrev_array_info", abres, err); + } + } + dwarf_dealloc(dbg, ab, DW_DLA_ABBREV); + } + } +} + +/* Validate an abbreviation for the current CU. */ +void +validate_abbrev_code(Dwarf_Debug dbg,Dwarf_Unsigned abbrev_code) +{ + char buf[128]; + + DWARF_CHECK_COUNT(abbreviations_result,1); + if (abbrev_code < 0 || (abbrev_code && abbrev_code > CU_abbrev_count)) { + snprintf(buf, sizeof(buf), + "Abbrev code %" DW_PR_DUu + " outside valid range of [0-%" DW_PR_DUu "]", + abbrev_code,CU_abbrev_count); + DWARF_CHECK_ERROR2(abbreviations_result,buf, + "Invalid abbreviation code."); + } else { + Dwarf_Signed abbrev_entry_count = + abbrev_array[abbrev_code]; + if (abbrev_entry_count < 0 || + abbrev_entry_count > SNLINKER_MAX_ATTRIB_COUNT) { + snprintf(buf, sizeof(buf), + "Abbrev code %" DW_PR_DUu + ", with %" DW_PR_DUu " attributes: " + "outside valid range.", + abbrev_code, + abbrev_entry_count); + DWARF_CHECK_ERROR2(abbreviations_result,buf, + "Invalid number of attributes."); + } + } +} diff --git a/dwarfdump/print_aranges.c b/dwarfdump/print_aranges.c new file mode 100644 index 0000000..f3e076c --- /dev/null +++ b/dwarfdump/print_aranges.c @@ -0,0 +1,267 @@ +/* + Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. + Portions Copyright 2009-2011 SN Systems Ltd. All rights reserved. + Portions Copyright 2008-2011 David Anderson. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + + +$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + +#include "globals.h" +#include "naming.h" +#include "dwconf.h" +#include "esb.h" + +#include "print_sections.h" + + +static void +do_checking(Dwarf_Debug dbg, Dwarf_Arange *arange_buf,Dwarf_Signed i, + Dwarf_Off cu_die_offset,Dwarf_Bool first_cu, + Dwarf_Off cu_die_offset_prev, Dwarf_Die cu_die ) +{ + int dres = 0; + Dwarf_Off cuhdroff = 0; + Dwarf_Off cudieoff3 = 0; + dres = dwarf_get_arange_cu_header_offset( + arange_buf[i],&cuhdroff,&err); + if(dres == DW_DLV_OK) { + Dwarf_Off cudieoff2 = 0; + + /* Get the CU offset for easy error reporting */ + if (first_cu || cu_die_offset != cu_die_offset_prev) { + cu_die_offset_prev = cu_die_offset; + dres = dwarf_die_offsets(cu_die,&DIE_overall_offset,&DIE_offset,&err); + if (dres != DW_DLV_OK) { + print_error(dbg, "dwarf_die_offsets", dres, err); + } + } + dres = dwarf_get_cu_die_offset_given_cu_header_offset( + dbg,cuhdroff,&cudieoff2,&err); + if(dres == DW_DLV_OK) { + /* Get the CU offset for easy error reporting */ + dwarf_die_offsets(cu_die,&DIE_overall_offset,&DIE_offset,&err); + DWARF_CHECK_COUNT(aranges_result,1); + if(cudieoff2 != cu_die_offset) { + printf("Error, cu_die offsets mismatch, 0x%" + DW_PR_DUx + " != 0x%" DW_PR_DUx " from arange data", + cu_die_offset,cudieoff2); + DWARF_CHECK_ERROR(aranges_result, + " dwarf_get_cu_die_offset_given_cu..." + " gets wrong offset"); + } + } else { + print_error(dbg, "dwarf_get_cu_die_offset_given...", dres, err); + } + } else { + print_error(dbg, "dwarf_get_arange_cu_header_offset", dres, err); + } + dres = dwarf_get_cu_die_offset(arange_buf[i],&cudieoff3, + &err); + if(dres == DW_DLV_OK) { + DWARF_CHECK_COUNT(aranges_result,1); + if(cudieoff3 != cu_die_offset) { + printf( + "Error, cu_die offsets (b) mismatch , 0x%" + DW_PR_DUx + " != 0x%" DW_PR_DUx " from arange data", + cu_die_offset,cudieoff3); + DWARF_CHECK_ERROR(aranges_result, + " dwarf_get_cu_die_offset " + " gets wrong offset"); + } + } else { + print_error(dbg, "dwarf_get_cu_die_offset failed ", + dres,err); + } +} + +/* get all the data in .debug_aranges */ +extern void +print_aranges(Dwarf_Debug dbg) +{ + Dwarf_Signed count = 0; + Dwarf_Signed i = 0; + Dwarf_Arange *arange_buf = NULL; + int ares = 0; + int aires = 0; + Dwarf_Off prev_off = 0; /* Holds previous CU offset */ + Dwarf_Bool first_cu = TRUE; + Dwarf_Off cu_die_offset_prev = 0; + + /* Reset the global state, so we can traverse the debug_info */ + seen_CU = FALSE; + need_CU_name = TRUE; + need_CU_base_address = TRUE; + need_CU_high_address = TRUE; + + current_section_id = DEBUG_ARANGES; + if (do_print_dwarf) { + printf("\n.debug_aranges\n"); + } + ares = dwarf_get_aranges(dbg, &arange_buf, &count, &err); + if (ares == DW_DLV_ERROR) { + print_error(dbg, "dwarf_get_aranges", ares, err); + } else if (ares == DW_DLV_NO_ENTRY) { + /* no arange is included */ + } else { + for (i = 0; i < count; i++) { + Dwarf_Unsigned segment = 0; + Dwarf_Unsigned segment_entry_size = 0; + Dwarf_Addr start = 0; + Dwarf_Unsigned length = 0; + Dwarf_Off cu_die_offset = 0; + Dwarf_Die cu_die = NULL; + aires = dwarf_get_arange_info_b(arange_buf[i], + &segment, + &segment_entry_size, + &start, &length, + &cu_die_offset, &err); + if (aires != DW_DLV_OK) { + print_error(dbg, "dwarf_get_arange_info", aires, err); + } else { + int dres; + char *producer_name = 0; + + /* Get basic locations for error reporting */ + dres = dwarf_offdie(dbg, cu_die_offset, &cu_die, &err); + if (dres != DW_DLV_OK) { + print_error(dbg, "dwarf_offdie", dres, err); + } + + if (cu_name_flag) { + if(should_skip_this_cu(dbg,cu_die,err)) { + continue; + } + } + /* Get producer name for this CU and update compiler list */ + get_producer_name(dbg,cu_die,err,&producer_name); + update_compiler_target(producer_name); + if (!checking_this_compiler()) { + continue; + } + + if (check_aranges) { + do_checking(dbg,arange_buf,i,cu_die_offset,first_cu, + cu_die_offset_prev,cu_die); + } + /* Get the offset of the cu header itself in the + section, but not for end-entries. */ + if(start || length) { + Dwarf_Off off = 0; + int cures3 = dwarf_get_arange_cu_header_offset( + arange_buf[i], &off, &err); + if (cures3 != DW_DLV_OK) { + print_error(dbg, "dwarf_get_cu_hdr_offset", + cures3, err); + } + + /* Print the CU information if different. */ + if (prev_off != off || first_cu) { + first_cu = FALSE; + prev_off = off; + /* We are faking the indent level. We do not know + what level it is, really. + + If do_check_dwarf we do not want to do + the die print call as it will do + check/print we may not have asked for. + And if we did ask for debug_info checks + this will do the checks a second time! + So only call print_one_die if printing. + */ + if(do_print_dwarf){ + /* There is no die if its a set-end entry */ + print_one_die(dbg, cu_die, + /* print_information= */ (boolean) TRUE, + /* indent_level = */0, + /* srcfiles= */ 0, + /* cnt= */ 0, + /* ignore_die_stack= */TRUE); + } + /* Reset the state, so we can traverse the debug_info */ + seen_CU = FALSE; + need_CU_name = TRUE; + if (do_print_dwarf) { + printf("\n"); + } + } + + if (do_print_dwarf) { + /* Print current aranges record */ + if(segment_entry_size) { + printf( + "\narange starts at seg,off 0x%" + DW_PR_XZEROS DW_PR_DUx + ",0x%" DW_PR_XZEROS DW_PR_DUx + ", ", + segment, + (Dwarf_Unsigned)start); + } else { + printf("\narange starts at 0x%" + DW_PR_XZEROS DW_PR_DUx ", ", + (Dwarf_Unsigned)start); + } + printf("length of 0x%" DW_PR_XZEROS DW_PR_DUx + ", cu_die_offset = 0x%" DW_PR_XZEROS DW_PR_DUx, + length, + (Dwarf_Unsigned)cu_die_offset); + + } + if (verbose && do_print_dwarf) { + printf(" cuhdr 0x%" DW_PR_XZEROS DW_PR_DUx "\n", + (Dwarf_Unsigned)off); + } + dwarf_dealloc(dbg, cu_die, DW_DLA_DIE); + cu_die = 0; + } else { + /* Must be a range end. We really do want to print + this as there is a real record here, an + 'arange end' record. */ + if (do_print_dwarf) { + printf("\narange end"); + } + }/* end start||length test */ + } /* end aires DW_DLV_OK test */ + + /* print associated die too? */ + dwarf_dealloc(dbg, arange_buf[i], DW_DLA_ARANGE); + } + dwarf_dealloc(dbg, arange_buf, DW_DLA_LIST); + } +} diff --git a/dwarfdump/print_die.c b/dwarfdump/print_die.c new file mode 100644 index 0000000..5951385 --- /dev/null +++ b/dwarfdump/print_die.c @@ -0,0 +1,3540 @@ +/* + + Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. + Portions Copyright 2009-2011 SN Systems Ltd. All rights reserved. + Portions Copyright 2007-2011 David Anderson. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + +$ Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_die.c,v 1.51 2006/04/01 16:20:21 davea Exp $ */ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. */ + + +#include "globals.h" +#include "naming.h" +#include "esb.h" /* For flexible string buffer. */ +#include "makename.h" /* Non-duplicating string table. */ +#include "print_frames.h" /* for get_string_from_locs() . */ +#include "tag_common.h" + +/* Traverse a DIE and attributes to check self references */ +static boolean traverse_one_die(Dwarf_Debug dbg, Dwarf_Attribute attrib, + Dwarf_Die die, char **srcfiles, + Dwarf_Signed cnt, int die_indent_level); +static boolean traverse_attribute(Dwarf_Debug dbg, Dwarf_Die die, + Dwarf_Half attr, Dwarf_Attribute attr_in, + boolean print_information, + char **srcfiles, Dwarf_Signed cnt, + int die_indent_level); +static void print_die_and_children_internal(Dwarf_Debug dbg, + Dwarf_Die in_die_in, + Dwarf_Bool is_info, + char **srcfiles, Dwarf_Signed cnt); +static int print_one_die_section(Dwarf_Debug dbg,Dwarf_Bool is_info); + +/* Is this a PU has been invalidated by the SN Systems linker? */ +#define IsInvalidCode(low,high) ((low == elf_max_address) || (low == 0 && high == 0)) + + +static int get_form_values(Dwarf_Attribute attrib, + Dwarf_Half * theform, Dwarf_Half * directform); +static void show_form_itself(int show_form,int verbose, + int theform, int directform, struct esb_s * str_out); +static void print_exprloc_content(Dwarf_Debug dbg,Dwarf_Die die, Dwarf_Attribute attrib, + int showhextoo, struct esb_s *esbp); +static boolean print_attribute(Dwarf_Debug dbg, Dwarf_Die die, + Dwarf_Half attr, + Dwarf_Attribute actual_addr, + boolean print_information, + int die_indent_level, char **srcfiles, + Dwarf_Signed cnt); +static void get_location_list(Dwarf_Debug dbg, Dwarf_Die die, + Dwarf_Attribute attr, struct esb_s *esbp); +static int legal_tag_attr_combination(Dwarf_Half tag, Dwarf_Half attr); +static int legal_tag_tree_combination(Dwarf_Half parent_tag, + Dwarf_Half child_tag); +static int _dwarf_print_one_expr_op(Dwarf_Debug dbg,Dwarf_Loc* expr, + int index, struct esb_s *string_out); +static int formxdata_print_value(Dwarf_Debug dbg,Dwarf_Attribute attrib, + struct esb_s *esbp, Dwarf_Error * err, Dwarf_Bool hex_format); + +/* esb_base is static so gets initialized to zeros. + It is not thread-safe or + safe for multiple open producer instances for + but that does not matter here in dwarfdump. + + The memory used by esb_base and esb_extra is never freed. +*/ +static struct esb_s esb_base; +static struct esb_s esb_extra; + +static int dwarf_names_print_on_error = 1; + +static int die_stack_indent_level = 0; +static boolean local_symbols_already_began = FALSE; + +typedef const char *(*encoding_type_func) (unsigned,int doprintingonerr); + +Dwarf_Off fde_offset_for_cu_low = DW_DLV_BADOFFSET; +Dwarf_Off fde_offset_for_cu_high = DW_DLV_BADOFFSET; + +/* Indicators to record a pair [low,high], these + are used in printing DIEs to accumulate the high + and low pc across attributes and to record the pair + as soon as both are known. Probably would be better to + use variables as arguments to + print_attribute(). */ +static Dwarf_Addr lowAddr = 0; +static Dwarf_Addr highAddr = 0; +static Dwarf_Bool bSawLow = FALSE; +static Dwarf_Bool bSawHigh = FALSE; + +/* The following too is related to high and low pc +attributes of a function. It's misnamed, it really means +'yes, we have high and low pc' if it is TRUE. Defaulting to TRUE +seems bogus. */ +static Dwarf_Bool in_valid_code = TRUE; + +struct operation_descr_s { + int op_code; + int op_count; + const char * op_1type; +}; +struct operation_descr_s opdesc[]= { + {DW_OP_addr,1,"addr" }, + {DW_OP_deref,0 }, + {DW_OP_const1u,1,"1u" }, + {DW_OP_const1s,1,"1s" }, + {DW_OP_const2u,1,"2u" }, + {DW_OP_const2s,1,"2s" }, + {DW_OP_const4u,1,"4u" }, + {DW_OP_const4s,1,"4s" }, + {DW_OP_const8u,1,"8u" }, + {DW_OP_const8s,1,"8s" }, + {DW_OP_constu,1,"uleb" }, + {DW_OP_consts,1,"sleb" }, + {DW_OP_dup,0,""}, + {DW_OP_drop,0,""}, + {DW_OP_over,0,""}, + {DW_OP_pick,1,"1u"}, + {DW_OP_swap,0,""}, + {DW_OP_rot,0,""}, + {DW_OP_xderef,0,""}, + {DW_OP_abs,0,""}, + {DW_OP_and,0,""}, + {DW_OP_div,0,""}, + {DW_OP_minus,0,""}, + {DW_OP_mod,0,""}, + {DW_OP_mul,0,""}, + {DW_OP_neg,0,""}, + {DW_OP_not,0,""}, + {DW_OP_or,0,""}, + {DW_OP_plus,0,""}, + {DW_OP_plus_uconst,1,"uleb"}, + {DW_OP_shl,0,""}, + {DW_OP_shr,0,""}, + {DW_OP_shra,0,""}, + {DW_OP_xor,0,""}, + {DW_OP_skip,1,"2s"}, + {DW_OP_bra,1,"2s"}, + {DW_OP_eq,0,""}, + {DW_OP_ge,0,""}, + {DW_OP_gt,0,""}, + {DW_OP_le,0,""}, + {DW_OP_lt,0,""}, + {DW_OP_ne,0,""}, + /* lit0 thru reg31 handled specially, no operands */ + /* breg0 thru breg31 handled specially, 1 operand */ + {DW_OP_regx,1,"uleb"}, + {DW_OP_fbreg,1,"sleb"}, + {DW_OP_bregx,2,"uleb"}, + {DW_OP_piece,1,"uleb"}, + {DW_OP_deref_size,1,"1u"}, + {DW_OP_xderef_size,1,"1u"}, + {DW_OP_nop,0,""}, + {DW_OP_push_object_address,0,""}, + {DW_OP_call2,1,"2u"}, + {DW_OP_call4,1,"4u"}, + {DW_OP_call_ref,1,"off"}, + {DW_OP_form_tls_address,0,""}, + {DW_OP_call_frame_cfa,0,""}, + {DW_OP_bit_piece,2,"uleb"}, + {DW_OP_implicit_value,2,"uleb"}, + {DW_OP_stack_value,0,""}, + {DW_OP_GNU_uninit,0,""}, + {DW_OP_GNU_encoded_addr,1,"addr"}, + {DW_OP_GNU_implicit_pointer,1,"addr" }, + {DW_OP_GNU_entry_value,1,"val" }, + /* terminator */ + {0,0,""} +}; + +struct die_stack_data_s { + Dwarf_Die die_; + boolean already_printed_; +}; +struct die_stack_data_s empty_stack_entry; + +#define DIE_STACK_SIZE 800 +static struct die_stack_data_s die_stack[DIE_STACK_SIZE]; + +#define SET_DIE_STACK_ENTRY(i,x) { die_stack[i].die_ = x; \ + die_stack[die_stack_indent_level].already_printed_ = FALSE; } +#define EMPTY_DIE_STACK_ENTRY(i) { die_stack[i] = empty_stack_entry; } + +static int +print_as_info_or_cu() +{ + return (info_flag || cu_name_flag); +} + + +/* process each compilation unit in .debug_info */ +void +print_infos(Dwarf_Debug dbg,Dwarf_Bool is_info) +{ + int nres = 0; + if(is_info) { + nres = print_one_die_section(dbg,TRUE); + if (nres == DW_DLV_ERROR) { + char * errmsg = dwarf_errmsg(err); + Dwarf_Unsigned myerr = dwarf_errno(err); + + fprintf(stderr, "%s ERROR: %s: %s (%lu)\n", + program_name, "attempting to print .debug_info", + errmsg, (unsigned long) myerr); + fprintf(stderr, "attempting to continue.\n"); + } + return; + } + nres = print_one_die_section(dbg,FALSE); + if (nres == DW_DLV_ERROR) { + char * errmsg = dwarf_errmsg(err); + Dwarf_Unsigned myerr = dwarf_errno(err); + + fprintf(stderr, "%s ERROR: %s: %s (%lu)\n", + program_name, "attempting to print .debug_types", + errmsg, (unsigned long) myerr); + fprintf(stderr, "attempting to continue.\n"); + } +} +static void +print_std_cu_hdr(Dwarf_Unsigned cu_header_length, + Dwarf_Unsigned abbrev_offset, + Dwarf_Half version_stamp, + Dwarf_Half address_size) +{ + if(dense) { + printf(" %s<0x%" DW_PR_XZEROS DW_PR_DUx + ">", "cu_header_length", + cu_header_length); + printf(" %s<0x%04x>", "version_stamp", + version_stamp); + printf(" %s<0x%" DW_PR_XZEROS DW_PR_DUx + ">", "abbrev_offset", abbrev_offset); + printf(" %s<0x%02x>", "address_size", + address_size); + } else { + printf(" %-16s = 0x%" DW_PR_XZEROS DW_PR_DUx + " %" DW_PR_DUu + "\n", "cu_header_length", + cu_header_length, + cu_header_length); + printf(" %-16s = 0x%04x %u\n", "version_stamp", + version_stamp,version_stamp); + printf(" %-16s = 0x%" DW_PR_XZEROS DW_PR_DUx + " %" DW_PR_DUu + "\n", "abbrev_offset", + abbrev_offset, + abbrev_offset); + printf(" %-16s = 0x%02x %u\n", "address_size", + address_size,address_size); + } +} +static void +print_std_cu_signature(Dwarf_Sig8 *signature,Dwarf_Unsigned typeoffset) +{ + if(dense) { + struct esb_s sig8str; + esb_constructor(&sig8str); + format_sig8_string(signature,&sig8str); + printf(" %s<%s>", "signature",esb_get_string(&sig8str)); + printf(" %s<0x%" DW_PR_XZEROS DW_PR_DUx ">", + "typeoffset", typeoffset); + esb_destructor(&sig8str); + } else { + struct esb_s sig8str; + esb_constructor(&sig8str); + format_sig8_string(signature,&sig8str); + printf(" %-16s = %s\n", "signature",esb_get_string(&sig8str)); + printf(" %-16s = 0x%" DW_PR_XZEROS DW_PR_DUx " %" DW_PR_DUu "\n", + "typeoffset", + typeoffset,typeoffset); + esb_destructor(&sig8str); + } +} + +static int +print_one_die_section(Dwarf_Debug dbg,Dwarf_Bool is_info) +{ + Dwarf_Unsigned cu_header_length = 0; + Dwarf_Unsigned abbrev_offset = 0; + Dwarf_Half version_stamp = 0; + Dwarf_Half address_size = 0; + Dwarf_Half extension_size = 0; + Dwarf_Half length_size = 0; + Dwarf_Sig8 signature; + Dwarf_Unsigned typeoffset = 0; + Dwarf_Unsigned next_cu_offset = 0; + unsigned loop_count = 0; + int nres = DW_DLV_OK; + int cu_count = 0; + char * cu_short_name = NULL; + char * cu_long_name = NULL; + char * producer_name = NULL; + + current_section_id = DEBUG_INFO; + + if (print_as_info_or_cu() && do_print_dwarf) { + if(is_info) { + printf("\n.debug_info\n"); + } + } + + /* Loop until it fails. */ + for(;;++loop_count) { + int sres = DW_DLV_OK; + Dwarf_Die cu_die = 0; + + nres = dwarf_next_cu_header_c(dbg, + is_info, + &cu_header_length, &version_stamp, + &abbrev_offset, &address_size, + &length_size,&extension_size, + &signature, &typeoffset, + &next_cu_offset, &err); + if (nres == DW_DLV_NO_ENTRY) { + return nres; + } + if( loop_count == 0 &&!is_info && + print_as_info_or_cu() && do_print_dwarf) { + printf("\n.debug_types\n"); + } + if (nres != DW_DLV_OK) { + return nres; + } + if(cu_count >= break_after_n_units) { + printf("Break at %d\n",cu_count); + break; + } + /* Regardless of any options used, get basic + information about the current CU: producer, name */ + sres = dwarf_siblingof_b(dbg, NULL,is_info, &cu_die, &err); + if (sres != DW_DLV_OK) { + print_error(dbg, "siblingof cu header", sres, err); + } + /* Get the CU offset for easy error reporting */ + dwarf_die_offsets(cu_die,&DIE_overall_offset,&DIE_offset,&err); + + if (cu_name_flag) { + if(should_skip_this_cu(dbg,cu_die,err)) { + dwarf_dealloc(dbg, cu_die, DW_DLA_DIE); + cu_die = 0; + ++cu_count; + cu_offset = next_cu_offset; + continue; + } + } + + /* Get producer name for this CU and update compiler list */ + get_producer_name(dbg,cu_die,err,&producer_name); + update_compiler_target(producer_name); + + /* Once the compiler table has been updated, see + if we need to generate the list of CU compiled + by all the producers contained in the elf file */ + if (producer_children_flag) { + get_cu_name(dbg,cu_die,err,&cu_short_name,&cu_long_name); + /* Add CU name to current compiler entry */ + add_cu_name_compiler_target(cu_long_name); + } + + /* If the current compiler is not requested by the + user, then move to the next CU */ + if (!checking_this_compiler()) { + dwarf_dealloc(dbg, cu_die, DW_DLA_DIE); + ++cu_count; + cu_offset = next_cu_offset; + cu_die = 0; + continue; + } + + /* We have not seen the compile unit yet, reset these + error-reporting globals. */ + seen_CU = FALSE; + need_CU_name = TRUE; + need_CU_base_address = TRUE; + need_CU_high_address = TRUE; + seen_PU_base_address = FALSE; + seen_PU_high_address = FALSE; + + /* Release the 'cu_die' created by the call + to 'dwarf_siblingof' at the top of the main loop. */ + dwarf_dealloc(dbg, cu_die, DW_DLA_DIE); + cu_die = 0; /* For debugging, stale die should be NULL. */ + + if (info_flag && do_print_dwarf) { + if(verbose) { + if (dense) { + printf("<%s>", "cu_header"); + } else { + printf("\nCU_HEADER:\n"); + } + print_std_cu_hdr(cu_header_length,abbrev_offset, + version_stamp,address_size); + if(!is_info) { + print_std_cu_signature(&signature,typeoffset); + } + if(dense) { + printf("\n"); + } + } else { + if(!is_info) { + if(dense) { + printf("<%s>", "cu_header"); + } else { + printf("\nCU_HEADER:\n"); + } + print_std_cu_signature(&signature,typeoffset); + if(dense) { + printf("\n"); + } + } + } + } + + /* Get abbreviation info for this CU */ + get_abbrev_array_info(dbg,abbrev_offset); + + /* process a single compilation unit in .debug_info. */ + sres = dwarf_siblingof_b(dbg, NULL,is_info, &cu_die, &err); + if (sres == DW_DLV_OK) { + if (print_as_info_or_cu() || search_is_on) { + Dwarf_Signed cnt = 0; + char **srcfiles = 0; + int srcf = dwarf_srcfiles(cu_die, + &srcfiles, &cnt, &err); + if (srcf != DW_DLV_OK) { + srcfiles = 0; + cnt = 0; + } + + /* Get the CU offset for easy error reporting */ + dwarf_die_offsets(cu_die,&DIE_CU_overall_offset, + &DIE_CU_offset,&err); + print_die_and_children(dbg, cu_die,is_info, srcfiles, cnt); + if (srcf == DW_DLV_OK) { + int si = 0; + for (si = 0; si < cnt; ++si) { + dwarf_dealloc(dbg, srcfiles[si], DW_DLA_STRING); + } + dwarf_dealloc(dbg, srcfiles, DW_DLA_LIST); + } + } + + /* Dump Ranges Information */ + if (dump_ranges_info) { + PrintBucketGroup(pRangesInfo,TRUE); + } + + /* Traverse the line section if in check mode */ + if (line_flag || check_decl_file) { + print_line_numbers_this_cu(dbg, cu_die); + } + dwarf_dealloc(dbg, cu_die, DW_DLA_DIE); + cu_die = 0; + } else if (sres == DW_DLV_NO_ENTRY) { + /* Do nothing I guess. */ + } else { + print_error(dbg, "Regetting cu_die", sres, err); + } + ++cu_count; + cu_offset = next_cu_offset; + } + return nres; +} + +static void +print_a_die_stack(Dwarf_Debug dbg,char **srcfiles,Dwarf_Signed cnt,int lev) +{ + boolean print_information = TRUE; + boolean ignore_die_stack = FALSE; + print_one_die(dbg,die_stack[lev].die_,print_information,lev,srcfiles,cnt, + ignore_die_stack); +} +extern void +print_die_and_children(Dwarf_Debug dbg, + Dwarf_Die in_die_in, + Dwarf_Bool is_info, + char **srcfiles, Dwarf_Signed cnt) +{ + print_die_and_children_internal(dbg, + in_die_in,is_info,srcfiles,cnt); +} + +static void +print_die_stack(Dwarf_Debug dbg,char **srcfiles,Dwarf_Signed cnt) +{ + int lev = 0; + boolean print_information = TRUE; + boolean ignore_die_stack = FALSE; + + for(lev = 0; lev <= die_stack_indent_level; ++lev) + { + print_one_die(dbg,die_stack[lev].die_,print_information, + lev,srcfiles,cnt, + ignore_die_stack); + } +} + +/* recursively follow the die tree */ +static void +print_die_and_children_internal(Dwarf_Debug dbg, + Dwarf_Die in_die_in, + Dwarf_Bool is_info, + char **srcfiles, Dwarf_Signed cnt) +{ + Dwarf_Die child = 0; + Dwarf_Die sibling = 0; + Dwarf_Error err = 0; + int tres = 0; + int cdres = 0; + Dwarf_Die in_die = in_die_in; + + for (;;) { + SET_DIE_STACK_ENTRY(die_stack_indent_level,in_die); + + /* Get the CU offset for easy error reporting */ + dwarf_die_offsets(in_die,&DIE_overall_offset,&DIE_offset,&err); + + if (check_tag_tree) { + DWARF_CHECK_COUNT(tag_tree_result,1); + if (die_stack_indent_level == 0) { + Dwarf_Half tag = 0; + + tres = dwarf_tag(in_die, &tag, &err); + if (tres != DW_DLV_OK) { + DWARF_CHECK_ERROR(tag_tree_result, + "Tag-tree root is not DW_TAG_compile_unit"); + } else if (tag == DW_TAG_compile_unit) { + /* OK */ + } else { + DWARF_CHECK_ERROR(tag_tree_result, + "tag-tree root is not DW_TAG_compile_unit"); + } + } else { + Dwarf_Half tag_parent = 0; + Dwarf_Half tag_child = 0; + int pres = 0; + int cres = 0; + const char *ctagname = "<child tag invalid>"; + const char *ptagname = "<parent tag invalid>"; + + pres = dwarf_tag(die_stack[die_stack_indent_level - 1].die_, + &tag_parent, &err); + cres = dwarf_tag(in_die, &tag_child, &err); + if (pres != DW_DLV_OK) + tag_parent = 0; + if (cres != DW_DLV_OK) + tag_child = 0; + + /* Check for specific compiler */ + if (checking_this_compiler()) { + /* Process specific TAGs. */ + tag_specific_checks_setup(tag_child,die_stack_indent_level); + if (cres != DW_DLV_OK || pres != DW_DLV_OK) { + if (cres == DW_DLV_OK) { + ctagname = get_TAG_name(tag_child, + dwarf_names_print_on_error); + } + if (pres == DW_DLV_OK) { + ptagname = get_TAG_name(tag_parent, + dwarf_names_print_on_error); + } + DWARF_CHECK_ERROR3(tag_tree_result,ptagname, + ctagname, + "Tag-tree relation is not standard.."); + } else if (legal_tag_tree_combination(tag_parent, + tag_child)) { + /* OK */ + } else { + DWARF_CHECK_ERROR3(tag_tree_result, + get_TAG_name(tag_parent, + dwarf_names_print_on_error), + get_TAG_name(tag_child, + dwarf_names_print_on_error), + "tag-tree relation is not standard."); + } + } + } + } + + if (record_dwarf_error && check_verbose_mode) { + record_dwarf_error = FALSE; + } + + /* Here do pre-descent processing of the die. */ + { + boolean retry_print_on_match = FALSE; + boolean ignore_die_stack = FALSE; + retry_print_on_match = print_one_die(dbg, in_die, + print_as_info_or_cu(), + die_stack_indent_level, srcfiles, cnt,ignore_die_stack); + if(!print_as_info_or_cu() && retry_print_on_match) { + if (display_parent_tree) { + print_die_stack(dbg,srcfiles,cnt); + } else { + if (display_children_tree) { + print_a_die_stack(dbg,srcfiles,cnt,die_stack_indent_level); + } + } + if (display_children_tree) { + stop_indent_level = die_stack_indent_level; + info_flag = TRUE; + } + } + } + + cdres = dwarf_child(in_die, &child, &err); + + /* Check for specific compiler */ + if (check_abbreviations && checking_this_compiler()) { + Dwarf_Half ab_has_child; + Dwarf_Bool bError = FALSE; + Dwarf_Half tag = 0; + tres = dwarf_die_abbrev_children_flag(in_die,&ab_has_child); + if (tres == DW_DLV_OK) { + DWARF_CHECK_COUNT(abbreviations_result,1); + tres = dwarf_tag(in_die, &tag, &err); + if (tres == DW_DLV_OK) { + switch (tag) { + case DW_TAG_array_type: + case DW_TAG_class_type: + case DW_TAG_compile_unit: + case DW_TAG_enumeration_type: + case DW_TAG_lexical_block: + case DW_TAG_namespace: + case DW_TAG_structure_type: + case DW_TAG_subprogram: + case DW_TAG_subroutine_type: + case DW_TAG_union_type: + case DW_TAG_entry_point: + case DW_TAG_inlined_subroutine: + break; + default: + bError = (cdres == DW_DLV_OK && !ab_has_child) || + (cdres == DW_DLV_NO_ENTRY && ab_has_child); + if (bError) { + DWARF_CHECK_ERROR(abbreviations_result, + "check 'dw_children' flag combination."); + } + break; + } + } + } + } + + + /* child first: we are doing depth-first walk */ + if (cdres == DW_DLV_OK) { + die_stack_indent_level++; + SET_DIE_STACK_ENTRY(die_stack_indent_level,0); + if(die_stack_indent_level >= DIE_STACK_SIZE ) { + print_error(dbg, + "compiled in DIE_STACK_SIZE limit exceeded", + DW_DLV_OK,err); + } + print_die_and_children_internal(dbg, child,is_info, srcfiles, cnt); + EMPTY_DIE_STACK_ENTRY(die_stack_indent_level); + die_stack_indent_level--; + if (die_stack_indent_level == 0) + local_symbols_already_began = FALSE; + dwarf_dealloc(dbg, child, DW_DLA_DIE); + child = 0; + } else if (cdres == DW_DLV_ERROR) { + print_error(dbg, "dwarf_child", cdres, err); + } + + /* Stop the display of all children */ + if (display_children_tree && info_flag && + stop_indent_level == die_stack_indent_level) { + + info_flag = FALSE; + } + + cdres = dwarf_siblingof_b(dbg, in_die,is_info, &sibling, &err); + if (cdres == DW_DLV_OK) { + /* print_die_and_children(dbg, sibling, srcfiles, cnt); We + loop around to actually print this, rather than + recursing. Recursing is horribly wasteful of stack + space. */ + } else if (cdres == DW_DLV_ERROR) { + print_error(dbg, "dwarf_siblingof", cdres, err); + } + + /* If we have a sibling, verify that its offset + is next to the last processed DIE; + An incorrect sibling chain is a nasty bug. */ + if (cdres == DW_DLV_OK && sibling && check_di_gaps && + checking_this_compiler()) { + + Dwarf_Off glb_off; + DWARF_CHECK_COUNT(di_gaps_result,1); + if (dwarf_validate_die_sibling(sibling,&glb_off) == DW_DLV_ERROR) { + static char msg[128]; + Dwarf_Off sib_off; + dwarf_dieoffset(sibling,&sib_off,&err); + sprintf(msg, + "GSIB = 0x%" DW_PR_XZEROS DW_PR_DUx + " GOFF = 0x%" DW_PR_XZEROS DW_PR_DUx + " Gap = %" DW_PR_DUu " bytes", + sib_off,glb_off,sib_off-glb_off); + DWARF_CHECK_ERROR2(di_gaps_result, + "Incorrect sibling chain",msg); + } + } + + /* Here do any post-descent (ie post-dwarf_child) processing of + the in_die. */ + + EMPTY_DIE_STACK_ENTRY(die_stack_indent_level); + if (in_die != in_die_in) { + /* Dealloc our in_die, but not the argument die, it belongs + to our caller. Whether the siblingof call worked or not. */ + dwarf_dealloc(dbg, in_die, DW_DLA_DIE); + in_die = 0; + } + if (cdres == DW_DLV_OK) { + /* Set to process the sibling, loop again. */ + in_die = sibling; + } else { + /* We are done, no more siblings at this level. */ + break; + } + } /* end for loop on siblings */ + return; +} + +/* Print one die on error and verbose or non check mode */ +#define PRINTING_DIES (do_print_dwarf || (record_dwarf_error && check_verbose_mode)) + +/* If print_information is FALSE, check the TAG and if it is a CU die + print the information anyway. */ +boolean +print_one_die(Dwarf_Debug dbg, Dwarf_Die die, + boolean print_information, + int die_indent_level, + char **srcfiles, Dwarf_Signed cnt, + boolean ignore_die_stack) +{ + Dwarf_Signed i = 0; + Dwarf_Off offset = 0; + Dwarf_Off overall_offset = 0; + const char * tagname = 0; + Dwarf_Half tag = 0; + Dwarf_Signed atcnt = 0; + Dwarf_Attribute *atlist = 0; + int tres = 0; + int ores = 0; + int atres = 0; + int abbrev_code = dwarf_die_abbrev_code(die); + boolean attribute_matched = FALSE; + + /* Print using indentation + < 1><0x000854ff GOFF=0x00546047> DW_TAG_pointer_type -> 34 + < 1><0x000854ff> DW_TAG_pointer_type -> 18 + DW_TAG_pointer_type -> 2 + */ + /* Attribute indent. */ + int nColumn = show_global_offsets ? 34 : 18; + + if (check_abbreviations && checking_this_compiler()) { + validate_abbrev_code(dbg,abbrev_code); + } + + if(!ignore_die_stack && die_stack[die_indent_level].already_printed_) { + /* FALSE seems like a safe return. */ + return FALSE; + } + + /* Reset indentation column if no offsets */ + if (!display_offsets) { + nColumn = 2; + } + + tres = dwarf_tag(die, &tag, &err); + if (tres != DW_DLV_OK) { + print_error(dbg, "accessing tag of die!", tres, err); + } + tagname = get_TAG_name(tag,dwarf_names_print_on_error); + + tag_specific_checks_setup(tag,die_indent_level); + ores = dwarf_dieoffset(die, &overall_offset, &err); + if (ores != DW_DLV_OK) { + print_error(dbg, "dwarf_dieoffset", ores, err); + } + ores = dwarf_die_CU_offset(die, &offset, &err); + if (ores != DW_DLV_OK) { + print_error(dbg, "dwarf_die_CU_offset", ores, err); + } + + if (dump_visited_info && check_self_references) { + printf("<%2d><0x%" DW_PR_XZEROS DW_PR_DUx + " GOFF=0x%" DW_PR_XZEROS DW_PR_DUx "> ", + die_indent_level, (Dwarf_Unsigned)offset, + (Dwarf_Unsigned)overall_offset); + printf("%*s%s\n",die_indent_level * 2 + 2," ",tagname); + } + + /* Print the die */ + if (PRINTING_DIES && print_information) { + if (!ignore_die_stack) { + die_stack[die_indent_level].already_printed_ = TRUE; + } + if (die_indent_level == 0) { + if (dense) { + printf("\n"); + } else { + printf("\nCOMPILE_UNIT<header overall offset = 0x%" + DW_PR_XZEROS DW_PR_DUx ">:\n", + (Dwarf_Unsigned)(overall_offset - offset)); + } + } else if (local_symbols_already_began == FALSE && + die_indent_level == 1 && !dense) { + + printf("\nLOCAL_SYMBOLS:\n"); + local_symbols_already_began = TRUE; + } + + /* Print just the Tags and Attributes */ + if (!display_offsets) { + /* Print using indentation */ + printf("%*s%s\n",die_stack_indent_level * 2 + 2," ",tagname); + } else { + if (dense) { + if (show_global_offsets) { + if (die_indent_level == 0) { + printf("<%d><0x%" DW_PR_DUx "+0x%" DW_PR_DUx " GOFF=0x%" + DW_PR_DUx ">", die_indent_level, + (Dwarf_Unsigned)(overall_offset - offset), + (Dwarf_Unsigned)offset, + (Dwarf_Unsigned)overall_offset); + } else { + printf("<%d><0x%" DW_PR_DUx " GOFF=0x%" DW_PR_DUx ">", + die_indent_level, + (Dwarf_Unsigned)offset, + (Dwarf_Unsigned)overall_offset); + } + } else { + if (die_indent_level == 0) { + printf("<%d><0x%" DW_PR_DUx "+0x%" DW_PR_DUx ">", + die_indent_level, + (Dwarf_Unsigned)(overall_offset - offset), + (Dwarf_Unsigned)offset); + } else { + printf("<%d><0x%" DW_PR_DUx ">", die_indent_level, + (Dwarf_Unsigned)offset); + } + } + printf("<%s>",tagname); + if(verbose) { + printf(" <abbrev %d>",abbrev_code); + } + } else { + if (show_global_offsets) { + printf("<%2d><0x%" DW_PR_XZEROS DW_PR_DUx + " GOFF=0x%" DW_PR_XZEROS DW_PR_DUx ">", + die_indent_level, (Dwarf_Unsigned)offset, + (Dwarf_Unsigned)overall_offset); + } else { + printf("<%2d><0x%" DW_PR_XZEROS DW_PR_DUx ">", + die_indent_level, + (Dwarf_Unsigned)offset); + } + + /* Print using indentation */ + printf("%*s%s",die_indent_level * 2 + 2," ",tagname); + if(verbose) { + printf(" <abbrev %d>",abbrev_code); + } + fputs("\n",stdout); + } + } + } + + atres = dwarf_attrlist(die, &atlist, &atcnt, &err); + if (atres == DW_DLV_ERROR) { + print_error(dbg, "dwarf_attrlist", atres, err); + } else if (atres == DW_DLV_NO_ENTRY) { + /* indicates there are no attrs. It is not an error. */ + atcnt = 0; + } + + /* Reset any loose references to low or high PC */ + bSawLow = FALSE; + bSawHigh = FALSE; + + /* Get the CU offset for easy error reporting */ + dwarf_die_offsets(die,&DIE_CU_overall_offset,&DIE_CU_offset,&err); + + for (i = 0; i < atcnt; i++) { + Dwarf_Half attr; + int ares; + + ares = dwarf_whatattr(atlist[i], &attr, &err); + if (ares == DW_DLV_OK) { + /* Print using indentation */ + if (!dense && PRINTING_DIES && print_information) { + printf("%*s",die_indent_level * 2 + 2 + nColumn," "); + } + + { + boolean attr_match = print_attribute(dbg, die, attr, + atlist[i], + print_information, die_indent_level, srcfiles, cnt); + if(print_information == FALSE && attr_match) { + attribute_matched = TRUE; + } + } + + if (record_dwarf_error && check_verbose_mode) { + record_dwarf_error = FALSE; + } + } else { + print_error(dbg, "dwarf_whatattr entry missing", ares, err); + } + } + + for (i = 0; i < atcnt; i++) { + dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR); + } + if (atres == DW_DLV_OK) { + dwarf_dealloc(dbg, atlist, DW_DLA_LIST); + } + + if (PRINTING_DIES && dense && print_information) { + printf("\n"); + } + return attribute_matched; +} + +/* Encodings have undefined signedness. Accept either + signedness. The values are integer-like (they are defined + in the DWARF specification), so the + form the compiler uses (as long as it is + a constant value) is a non-issue. + + The numbers need not be small (in spite of the + function name), but the result should be an integer. + + If string_out is non-NULL, construct a string output, either + an error message or the name of the encoding. + The function pointer passed in is to code generated + by a script at dwarfdump build time. The code for + the val_as_string function is generated + from dwarf.h. See <build dir>/dwarf_names.c + + The known_signed bool is set true(nonzero) or false (zero) + and *both* uval_out and sval_out are set to the value, + though of course uval_out cannot represent a signed + value properly and sval_out cannot represent all unsigned + values properly. + + If string_out is non-NULL then attr_name and val_as_string + must also be non-NULL. */ +static int +get_small_encoding_integer_and_name(Dwarf_Debug dbg, + Dwarf_Attribute attrib, + Dwarf_Unsigned * uval_out, + char *attr_name, + const char ** string_out, + encoding_type_func val_as_string, + Dwarf_Error * err, + int show_form) +{ + Dwarf_Unsigned uval = 0; + char buf[100]; /* The strings are small. */ + int vres = dwarf_formudata(attrib, &uval, err); + + if (vres != DW_DLV_OK) { + Dwarf_Signed sval = 0; + vres = dwarf_formsdata(attrib, &sval, err); + if (vres != DW_DLV_OK) { + vres = dwarf_global_formref(attrib,&uval,err); + if (vres != DW_DLV_OK) { + if (string_out != 0) { + snprintf(buf, sizeof(buf), + "%s has a bad form.", attr_name); + *string_out = makename(buf); + } + return vres; + } + *uval_out = uval; + } else { + uval = (Dwarf_Unsigned) sval; + *uval_out = uval; + } + } else { + *uval_out = uval; + } + if (string_out) { + Dwarf_Half theform = 0; + Dwarf_Half directform = 0; + get_form_values(attrib,&theform,&directform); + esb_empty_string(&esb_base); + esb_append(&esb_base, val_as_string((Dwarf_Half) uval, + dwarf_names_print_on_error)); + show_form_itself(show_form, verbose, theform, directform,&esb_base); + *string_out = makename(esb_get_string(&esb_base)); + } + return DW_DLV_OK; +} + + + + +/* We need a 32-bit signed number here, but there's no portable + way of getting that. So use __uint32_t instead. It's supplied + in a reliable way by the autoconf infrastructure. */ + +static void +get_FLAG_BLOCK_string(Dwarf_Debug dbg, Dwarf_Attribute attrib, + struct esb_s*esbp) +{ + int fres = 0; + Dwarf_Block *tempb = 0; + __uint32_t * array = 0; + Dwarf_Unsigned array_len = 0; + __uint32_t * array_ptr; + Dwarf_Unsigned array_remain = 0; + char linebuf[100]; + + /* first get compressed block data */ + fres = dwarf_formblock (attrib,&tempb, &err); + if (fres != DW_DLV_OK) { + print_error(dbg,"DW_FORM_blockn cannot get block\n",fres,err); + return; + } + + /* uncompress block into int array */ + array = dwarf_uncompress_integer_block(dbg, + 1, /* 'true' (meaning signed ints)*/ + 32, /* bits per unit */ + tempb->bl_data, + tempb->bl_len, + &array_len, /* len of out array */ + &err); + if (array == (void*) DW_DLV_BADOFFSET) { + print_error(dbg,"DW_AT_SUN_func_offsets cannot uncompress data\n",0,err); + return; + } + if (array_len == 0) { + print_error(dbg,"DW_AT_SUN_func_offsets has no data\n",0,err); + return; + } + + /* fill in string buffer */ + array_remain = array_len; + array_ptr = array; + while (array_remain > 8) { + /* Print a full line */ + /* If you touch this string, update the magic number 8 in + the += and -= below! */ + snprintf(linebuf, sizeof(linebuf), + "\n 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x", + array_ptr[0], array_ptr[1], + array_ptr[2], array_ptr[3], + array_ptr[4], array_ptr[5], + array_ptr[6], array_ptr[7]); + array_ptr += 8; + array_remain -= 8; + esb_append(&esb_base, linebuf); + } + + /* now do the last line */ + if (array_remain > 0) { + esb_append(&esb_base, "\n "); + while (array_remain > 0) { + snprintf(linebuf, sizeof(linebuf), " 0x%08x", *array_ptr); + array_remain--; + array_ptr++; + esb_append(&esb_base, linebuf); + } + } + + /* free array buffer */ + dwarf_dealloc_uncompressed_block(dbg, array); + +} + +static const char * +get_rangelist_type_descr(Dwarf_Ranges *r) +{ + switch(r->dwr_type) { + case DW_RANGES_ENTRY: return "range entry"; + case DW_RANGES_ADDRESS_SELECTION: return "addr selection"; + case DW_RANGES_END: return "range end"; + } + /* Impossible. */ + return "Unknown"; +} + + +void +print_ranges_list_to_extra(Dwarf_Debug dbg, + Dwarf_Unsigned off, + Dwarf_Ranges *rangeset, + Dwarf_Signed rangecount, + Dwarf_Unsigned bytecount, + struct esb_s *stringbuf) +{ + char tmp[200]; + Dwarf_Signed i; + if(dense) { + snprintf(tmp,sizeof(tmp), + "< ranges: %" DW_PR_DSd " ranges at .debug_ranges offset %" + DW_PR_DUu " (0x%" DW_PR_XZEROS DW_PR_DUx ") " + "(%" DW_PR_DUu " bytes)>", + rangecount, + off, + off, + bytecount); + esb_append(stringbuf,tmp); + } else { + snprintf(tmp,sizeof(tmp), + "\t\tranges: %" DW_PR_DSd " at .debug_ranges offset %" + DW_PR_DUu " (0x%" DW_PR_XZEROS DW_PR_DUx ") " + "(%" DW_PR_DUu " bytes)\n", + rangecount, + off, + off, + bytecount); + esb_append(stringbuf,tmp); + } + for(i = 0; i < rangecount; ++i) { + Dwarf_Ranges * r = rangeset +i; + const char *type = get_rangelist_type_descr(r); + if(dense) { + snprintf(tmp,sizeof(tmp), + "<[%2" DW_PR_DSd + "] %s 0x%" DW_PR_XZEROS DW_PR_DUx + " 0x%" DW_PR_XZEROS DW_PR_DUx ">", + (Dwarf_Signed)i, + type, + (Dwarf_Unsigned)r->dwr_addr1, + (Dwarf_Unsigned)r->dwr_addr2); + } else { + snprintf(tmp,sizeof(tmp), + "\t\t\t[%2" DW_PR_DSd + "] %-14s 0x%" DW_PR_XZEROS DW_PR_DUx + " 0x%" DW_PR_XZEROS DW_PR_DUx "\n", + (Dwarf_Signed)i, + type, + (Dwarf_Unsigned)r->dwr_addr1, + (Dwarf_Unsigned)r->dwr_addr2); + } + esb_append(stringbuf,tmp); + } +} + + +static boolean +is_location_form(int form) +{ + if(form == DW_FORM_block1 || + form == DW_FORM_block2 || + form == DW_FORM_block4 || + form == DW_FORM_block || + form == DW_FORM_data4 || + form == DW_FORM_data8 || + form == DW_FORM_sec_offset) { + return TRUE; + } + return FALSE; +} + +static void +show_attr_form_error(Dwarf_Debug dbg,unsigned attr,unsigned form,struct esb_s *out) +{ + const char *n = 0; + int res; + char buf[30]; + esb_append(out,"ERROR: Attribute "); + snprintf(buf,sizeof(buf),"%u",attr); + esb_append(out,buf); + esb_append(out," ("); + res = dwarf_get_AT_name(attr,&n); + if(res != DW_DLV_OK) { + n = "UknownAttribute"; + } + esb_append(out,n); + esb_append(out,") "); + esb_append(out," has form "); + snprintf(buf,sizeof(buf),"%u",form); + esb_append(out,buf); + esb_append(out," ("); + res = dwarf_get_FORM_name(form,&n); + if(res != DW_DLV_OK) { + n = "UknownForm"; + } + esb_append(out,n); + esb_append(out,"), a form which is not appropriate"); + print_error_and_continue(dbg,esb_get_string(out), DW_DLV_OK,err); +} + +/* Traverse an attribute and following any reference + in order to detect self references to DIES (loop). */ +static boolean +traverse_attribute(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Half attr, + Dwarf_Attribute attr_in, + boolean print_information, + char **srcfiles, Dwarf_Signed cnt, + int die_indent_level) +{ + Dwarf_Attribute attrib = 0; + const char * atname = 0; + const char * valname = 0; + int tres = 0; + Dwarf_Half tag = 0; + boolean circular_reference = FALSE; + Dwarf_Bool is_info = TRUE; + + is_info = dwarf_get_die_infotypes_flag(die); + atname = get_AT_name(attr,dwarf_names_print_on_error); + + /* The following gets the real attribute, even in the face of an + incorrect doubling, or worse, of attributes. */ + attrib = attr_in; + /* Do not get attr via dwarf_attr: if there are (erroneously) + multiple of an attr in a DIE, dwarf_attr will not get the + second, erroneous one and dwarfdump will print the first one + multiple times. Oops. */ + + tres = dwarf_tag(die, &tag, &err); + if (tres == DW_DLV_ERROR) { + tag = 0; + } else if (tres == DW_DLV_NO_ENTRY) { + tag = 0; + } else { + /* ok */ + } + + switch (attr) { + case DW_AT_specification: + case DW_AT_abstract_origin: + case DW_AT_type: { + int res = 0; + Dwarf_Off die_off = 0; + Dwarf_Off ref_off = 0; + Dwarf_Die ref_die = 0; + + ++die_indent_level; + esb_empty_string(&esb_base); + get_attr_value(dbg, tag, die, attrib, srcfiles, cnt, + &esb_base, show_form_used,verbose); + valname = esb_get_string(&esb_base); + + /* Get the global offset for reference */ + res = dwarf_global_formref(attrib, &ref_off, &err); + if (res != DW_DLV_OK) { + int errno = dwarf_errno(err); + if (errno == DW_DLE_REF_SIG8_NOT_HANDLED ) { + // No need to stop, ref_sig8 refers out of + // the current section. + break; + } else { + print_error(dbg, "dwarf_global_formref fails in traversal", + res, err); + } + } + res = dwarf_dieoffset(die, &die_off, &err); + if (res != DW_DLV_OK) { + int errno = dwarf_errno(err); + if (errno == DW_DLE_REF_SIG8_NOT_HANDLED ) { + // No need to stop, ref_sig8 refers out of + // the current section. + break; + } else { + print_error(dbg, "dwarf_dieoffset fails in traversal", res, err); + } + } + + /* Follow reference chain, looking for self references */ + res = dwarf_offdie_b(dbg,ref_off,is_info,&ref_die,&err); + if (res == DW_DLV_OK) { + ++die_indent_level; + /* Dump visited information */ + if (dump_visited_info) { + Dwarf_Off off = 0; + dwarf_die_CU_offset(die, &off, &err); + /* Check above call return status? FIXME */ + + printf("<%2d><0x%" DW_PR_XZEROS DW_PR_DUx + " GOFF=0x%" DW_PR_XZEROS DW_PR_DUx "> ", + die_indent_level, (Dwarf_Unsigned)off, + (Dwarf_Unsigned)die_off); + printf("%*s%s -> %s\n",die_indent_level * 2 + 2, + " ",atname,valname); + } + circular_reference = traverse_one_die(dbg,attrib,ref_die, + srcfiles,cnt,die_indent_level); + DeleteKeyInBucketGroup(pVisitedInfo,ref_off); + dwarf_dealloc(dbg,ref_die,DW_DLA_DIE); + --die_indent_level; + ref_die = 0; + } + } + break; + } /* End switch. */ + return circular_reference; +} + +/* Traverse one DIE in order to detect self references to DIES. */ +static boolean +traverse_one_die(Dwarf_Debug dbg, Dwarf_Attribute attrib, Dwarf_Die die, + char **srcfiles, Dwarf_Signed cnt, int die_indent_level) +{ + Dwarf_Half tag = 0; + Dwarf_Off overall_offset = 0; + Dwarf_Signed atcnt = 0; + int res = 0; + boolean circular_reference = FALSE; + boolean print_information = FALSE; + + res = dwarf_tag(die, &tag, &err); + if (res != DW_DLV_OK) { + print_error(dbg, "accessing tag of die!", res, err); + } + res = dwarf_dieoffset(die, &overall_offset, &err); + if (res != DW_DLV_OK) { + print_error(dbg, "dwarf_dieoffset", res, err); + } + + /* Print visited information */ + if (dump_visited_info) { + Dwarf_Off offset = 0; + const char * tagname = 0; + res = dwarf_die_CU_offset(die, &offset, &err); + if (res != DW_DLV_OK) { + print_error(dbg, "dwarf_die_CU_offsetC", res, err); + } + tagname = get_TAG_name(tag,dwarf_names_print_on_error); + printf("<%2d><0x%" DW_PR_XZEROS DW_PR_DUx + " GOFF=0x%" DW_PR_XZEROS DW_PR_DUx "> ", + die_indent_level, (Dwarf_Unsigned)offset, + (Dwarf_Unsigned)overall_offset); + printf("%*s%s\n",die_indent_level * 2 + 2," ",tagname); + } + + DWARF_CHECK_COUNT(self_references_result,1); + if (FindKeyInBucketGroup(pVisitedInfo,overall_offset)) { + char * valname = NULL; + Dwarf_Half attr = 0; + const char *atname = NULL; + esb_empty_string(&esb_base); + get_attr_value(dbg, tag, die, attrib, srcfiles, + cnt, &esb_base, show_form_used,verbose); + valname = esb_get_string(&esb_base); + dwarf_whatattr(attrib, &attr, &err); + atname = get_AT_name(attr,dwarf_names_print_on_error); + + /* We have a self reference */ + DWARF_CHECK_ERROR3(self_references_result, + "Invalid self reference to DIE: ",atname,valname); + circular_reference = TRUE; + } else { + Dwarf_Signed i = 0; + Dwarf_Attribute *atlist = 0; + + /* Add current DIE */ + AddEntryIntoBucketGroup(pVisitedInfo,overall_offset, + 0,0,0,NULL,FALSE); + + res = dwarf_attrlist(die, &atlist, &atcnt, &err); + if (res == DW_DLV_ERROR) { + print_error(dbg, "dwarf_attrlist", res, err); + } else if (res == DW_DLV_NO_ENTRY) { + /* indicates there are no attrs. It is not an error. */ + atcnt = 0; + } + + for (i = 0; i < atcnt; i++) { + Dwarf_Half attr; + int ares; + + ares = dwarf_whatattr(atlist[i], &attr, &err); + if (ares == DW_DLV_OK) { + circular_reference = traverse_attribute(dbg, die, attr, + atlist[i], + print_information, srcfiles, cnt, + die_indent_level); + } else { + print_error(dbg, "dwarf_whatattr entry missing", + ares, err); + } + } + + for (i = 0; i < atcnt; i++) { + dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR); + } + if (res == DW_DLV_OK) { + dwarf_dealloc(dbg, atlist, DW_DLA_LIST); + } + + /* Delete current DIE */ + DeleteKeyInBucketGroup(pVisitedInfo,overall_offset); + } + return circular_reference; +} + + +/* Extracted this from print_attribute() + to get tolerable indents. + In other words to make it readable. + It uses global data fields excessively, but so does + print_attribute(). + The majority of the code here is checking for + compiler errors. */ +static void +print_range_attribute(Dwarf_Debug dbg, + Dwarf_Die die, + Dwarf_Half attr, + Dwarf_Attribute attr_in, + Dwarf_Half theform, + int dwarf_names_print_on_error, + boolean print_information, + int *append_extra_string) +{ + Dwarf_Error err = 0; + Dwarf_Unsigned original_off = 0; + int fres = 0; + + fres = dwarf_global_formref(attr_in, &original_off, &err); + if( fres == DW_DLV_OK) { + Dwarf_Ranges *rangeset = 0; + Dwarf_Signed rangecount = 0; + Dwarf_Unsigned bytecount = 0; + int rres = dwarf_get_ranges_a(dbg,original_off, + die, + &rangeset, + &rangecount,&bytecount,&err); + if(rres == DW_DLV_OK) { + /* Ignore ranges inside a stripped function */ + if (check_ranges && + in_valid_code && checking_this_compiler()) { + Dwarf_Unsigned off = original_off; + + Dwarf_Signed index = 0; + Dwarf_Addr base_address = CU_base_address; + Dwarf_Addr lopc = 0; + Dwarf_Addr hipc = 0; + Dwarf_Bool bError = FALSE; + + /* Ignore last entry, is the end-of-list */ + for (index = 0; index < rangecount - 1; index++) { + Dwarf_Ranges *r = rangeset + index; + + if (r->dwr_addr1 == elf_max_address) { + /* (0xffffffff,addr), use specific address (current PU address) */ + base_address = r->dwr_addr2; + } else { + /* (offset,offset), update using CU address */ + lopc = r->dwr_addr1 + base_address; + hipc = r->dwr_addr2 + base_address; + DWARF_CHECK_COUNT(ranges_result,1); + + /* Check the low_pc and high_pc + are within a valid range in + the .text section */ + if (IsValidInBucketGroup(pRangesInfo,lopc) && + IsValidInBucketGroup(pRangesInfo,hipc)) { + /* Valid values; do nothing */ + } else { + /* At this point may be we + are dealing with a + linkonce symbol */ + if (IsValidInLinkonce(pLinkonceInfo, + PU_name,lopc,hipc)) { + /* Valid values; do nothing */ + } else { + bError = TRUE; + DWARF_CHECK_ERROR(ranges_result, + ".debug_ranges: Address outside a " + "valid .text range"); + if (check_verbose_mode) { + printf( + "Offset = 0x%" DW_PR_XZEROS DW_PR_DUx + ", Base = 0x%" DW_PR_XZEROS DW_PR_DUx + ", " + "Low = 0x%" DW_PR_XZEROS DW_PR_DUx + " (0x%" DW_PR_XZEROS DW_PR_DUx + "), High = 0x%" + DW_PR_XZEROS DW_PR_DUx + " (0x%" DW_PR_XZEROS DW_PR_DUx + ")\n", + off,base_address,lopc, + r->dwr_addr1,hipc, + r->dwr_addr2); + } + } + } + } + /* Each entry holds 2 addresses (offsets) */ + off += elf_address_size * 2; + } + if (bError && check_verbose_mode) { + printf("\n"); + } + } + if(print_information) { + *append_extra_string = 1; + esb_empty_string(&esb_extra); + print_ranges_list_to_extra(dbg,original_off, + rangeset,rangecount,bytecount, + &esb_extra); + } + dwarf_ranges_dealloc(dbg,rangeset,rangecount); + } else if (rres == DW_DLV_ERROR) { + if (do_print_dwarf) { + printf("\ndwarf_get_ranges() " + "cannot find DW_AT_ranges at offset 0x%" + DW_PR_XZEROS DW_PR_DUx + " (0x%" DW_PR_XZEROS DW_PR_DUx ").", + original_off, + original_off); + } else { + DWARF_CHECK_COUNT(ranges_result,1); + DWARF_CHECK_ERROR2(ranges_result, + get_AT_name(attr, + dwarf_names_print_on_error), + " cannot find DW_AT_ranges at offset"); + } + } else { + /* NO ENTRY */ + if (do_print_dwarf) { + printf("\ndwarf_get_ranges() " + "finds no DW_AT_ranges at offset 0x%" + DW_PR_XZEROS DW_PR_DUx + " (0x%" DW_PR_XZEROS DW_PR_DUx ").", + original_off, + original_off); + } else { + DWARF_CHECK_COUNT(ranges_result,1); + DWARF_CHECK_ERROR2(ranges_result, + get_AT_name(attr, + dwarf_names_print_on_error), + " fails to find DW_AT_ranges at offset"); + } + } + } else { + if (do_print_dwarf) { + struct esb_s local; + char tmp[100]; + + snprintf(tmp,sizeof(tmp)," attr 0x%x form 0x%x ", + (unsigned)attr,(unsigned)theform); + esb_constructor(&local); + esb_append(&local, + " fails to find DW_AT_ranges offset"); + esb_append(&local,tmp); + printf(" %s ",esb_get_string(&local)); + esb_destructor(&local); + } else { + DWARF_CHECK_COUNT(ranges_result,1); + DWARF_CHECK_ERROR2(ranges_result, + get_AT_name(attr, + dwarf_names_print_on_error), + " fails to find DW_AT_ranges offset"); + } + } +} + +/* A DW_AT_name in a CU DIE will likely have dots + and be entirely sensible. So lets + not call things a possible error when they are not. + Some assemblers allow '.' in an identifier too. + We should check for that, but we don't yet. + + We should check the compiler before checking + for 'altabi.' too (FIXME). + + This is a heuristic, not all that reliable. + + Return 0 if it is a vaguely standard identifier. + Else return 1, meaning 'it might be a file name + or have '.' in it quite sensibly.' + + If we don't do the TAG check we might report "t.c" + as a questionable DW_AT_name. Which would be silly. +*/ +static int +dot_ok_in_identifier(int tag,Dwarf_Die die, const char *val) +{ + if (strncmp(val,"altabi.",7)) { + /* Ignore the names of the form 'altabi.name', + which apply to one specific compiler. */ + return 1; + } + if(tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit || + tag == DW_TAG_imported_unit || tag == DW_TAG_type_unit) { + return 1; + } + return 0; +} + +static void +trim_quotes(const char *val,struct esb_s *es) +{ + if(val[0] == '"') { + size_t l = strlen(val); + if(l > 2 && val[l-1] == '"') { + esb_appendn(es,val+1,l-2); + return; + } + } + esb_append(es,val); +} + +static int +have_a_search_match(const char *valname,const char *atname) +{ + /* valname may have had quotes inserted, but search_match_text + will not. So we need to use a new copy, not valname here. + */ + struct esb_s esb_match; + char *s2; + esb_constructor(&esb_match); + + trim_quotes(valname,&esb_match); + s2 = esb_get_string(&esb_match); + if (search_match_text ) { + if(!strcmp(s2,search_match_text) || + !strcmp(atname,search_match_text)) { + + esb_destructor(&esb_match); + return TRUE; + } + } + if (search_any_text) { + if(is_strstrnocase(s2,search_any_text) || + is_strstrnocase(atname,search_any_text)) { + + esb_destructor(&esb_match); + return TRUE; + } + } +#ifdef HAVE_REGEX + if (search_regex_text) { + if(!regexec(&search_re,s2,0,NULL,0) || + !regexec(&search_re,atname,0,NULL,0)) { + + esb_destructor(&esb_match); + return TRUE; + } + } +#endif + esb_destructor(&esb_match); + return FALSE; +} + + +static boolean +print_attribute(Dwarf_Debug dbg, Dwarf_Die die, + Dwarf_Half attr, + Dwarf_Attribute attr_in, + boolean print_information, + int die_indent_level, + char **srcfiles, Dwarf_Signed cnt) +{ + Dwarf_Attribute attrib = 0; + Dwarf_Unsigned uval = 0; + const char * atname = 0; + const char * valname = 0; + int tres = 0; + Dwarf_Half tag = 0; + int append_extra_string = 0; + boolean found_search_attr = FALSE; + boolean bTextFound = FALSE; + Dwarf_Bool is_info = FALSE; + + is_info = dwarf_get_die_infotypes_flag(die); + esb_empty_string(&esb_extra); + atname = get_AT_name(attr,dwarf_names_print_on_error); + + /* The following gets the real attribute, even in the face of an + incorrect doubling, or worse, of attributes. */ + attrib = attr_in; + /* Do not get attr via dwarf_attr: if there are (erroneously) + multiple of an attr in a DIE, dwarf_attr will not get the + second, erroneous one and dwarfdump will print the first one + multiple times. Oops. */ + + tres = dwarf_tag(die, &tag, &err); + if (tres == DW_DLV_ERROR) { + tag = 0; + } else if (tres == DW_DLV_NO_ENTRY) { + tag = 0; + } else { + /* ok */ + } + if (check_attr_tag && checking_this_compiler()) { + const char *tagname = "<tag invalid>"; + + DWARF_CHECK_COUNT(attr_tag_result,1); + if (tres == DW_DLV_ERROR) { + DWARF_CHECK_ERROR3(attr_tag_result,tagname, + get_AT_name(attr,dwarf_names_print_on_error), + "check the tag-attr combination, dwarf_tag failed."); + } else if (tres == DW_DLV_NO_ENTRY) { + DWARF_CHECK_ERROR3(attr_tag_result,tagname, + get_AT_name(attr,dwarf_names_print_on_error), + "check the tag-attr combination, dwarf_tag NO ENTRY?."); + } else if (legal_tag_attr_combination(tag, attr)) { + /* OK */ + } else { + tagname = get_TAG_name(tag,dwarf_names_print_on_error); + tag_specific_checks_setup(tag,die_stack_indent_level); + DWARF_CHECK_ERROR3(attr_tag_result,tagname, + get_AT_name(attr,dwarf_names_print_on_error), + "check the tag-attr combination"); + } + } + + switch (attr) { + case DW_AT_language: + get_small_encoding_integer_and_name(dbg, attrib, &uval, + "DW_AT_language", &valname, + get_LANG_name, &err, + show_form_used); + break; + case DW_AT_accessibility: + get_small_encoding_integer_and_name(dbg, attrib, &uval, + "DW_AT_accessibility", + &valname, get_ACCESS_name, + &err, + show_form_used); + break; + case DW_AT_visibility: + get_small_encoding_integer_and_name(dbg, attrib, &uval, + "DW_AT_visibility", + &valname, get_VIS_name, + &err, + show_form_used); + break; + case DW_AT_virtuality: + get_small_encoding_integer_and_name(dbg, attrib, &uval, + "DW_AT_virtuality", + &valname, + get_VIRTUALITY_name, &err, + show_form_used); + break; + case DW_AT_identifier_case: + get_small_encoding_integer_and_name(dbg, attrib, &uval, + "DW_AT_identifier", + &valname, get_ID_name, + &err, + show_form_used); + break; + case DW_AT_inline: + get_small_encoding_integer_and_name(dbg, attrib, &uval, + "DW_AT_inline", &valname, + get_INL_name, &err, + show_form_used); + break; + case DW_AT_encoding: + get_small_encoding_integer_and_name(dbg, attrib, &uval, + "DW_AT_encoding", &valname, + get_ATE_name, &err, + show_form_used); + break; + case DW_AT_ordering: + get_small_encoding_integer_and_name(dbg, attrib, &uval, + "DW_AT_ordering", &valname, + get_ORD_name, &err, + show_form_used); + break; + case DW_AT_calling_convention: + get_small_encoding_integer_and_name(dbg, attrib, &uval, + "DW_AT_calling_convention", + &valname, get_CC_name, + &err, + show_form_used); + break; + case DW_AT_discr_list: /* DWARF3 */ + get_small_encoding_integer_and_name(dbg, attrib, &uval, + "DW_AT_discr_list", + &valname, get_DSC_name, + &err, + show_form_used); + break; + case DW_AT_data_member_location: + { + /* Value is a constant or a location + description or location list. + If a constant, it could be signed or + unsigned. Telling whether a constant + or a reference is nontrivial + since DW_FORM_data{4,8} + could be either in DWARF{2,3} */ + enum Dwarf_Form_Class fc = DW_FORM_CLASS_UNKNOWN; + Dwarf_Half theform = 0; + Dwarf_Half directform = 0; + Dwarf_Half version = 0; + Dwarf_Half offset_size = 0; + int wres = 0; + + get_form_values(attrib,&theform,&directform); + wres = dwarf_get_version_of_die(die , + &version,&offset_size); + if(wres != DW_DLV_OK) { + print_error(dbg,"Cannot get DIE context version number",wres,err); + break; + } + fc = dwarf_get_form_class(version,attr,offset_size,theform); + if(fc == DW_FORM_CLASS_CONSTANT) { + esb_empty_string(&esb_base); + wres = formxdata_print_value(dbg,attrib,&esb_base, + &err, FALSE); + show_form_itself(show_form_used,verbose, theform, + directform,&esb_base); + valname = esb_get_string(&esb_base); + if(wres == DW_DLV_OK){ + /* String appended already. */ + break; + } else if (wres == DW_DLV_NO_ENTRY) { + print_error(dbg,"Cannot get DW_AT_data_member_location, how can it be NO_ENTRY? ",wres,err); + break; + } else { + print_error(dbg,"Cannot get DW_AT_data_member_location ",wres,err); + break; + } + } + /* FALL THRU, this is a + a location description, or a reference + to one, or a mistake. */ + } + /* FALL THRU to location description */ + case DW_AT_location: + case DW_AT_vtable_elem_location: + case DW_AT_string_length: + case DW_AT_return_addr: + case DW_AT_use_location: + case DW_AT_static_link: + case DW_AT_frame_base: + { + /* The value is a location description + or location list. */ + + Dwarf_Half theform = 0; + Dwarf_Half directform = 0; + get_form_values(attrib,&theform,&directform); + esb_empty_string(&esb_base); + if(is_location_form(theform)) { + get_location_list(dbg, die, attrib, &esb_base); + show_form_itself(show_form_used,verbose, + theform, directform,&esb_base); + } else if (theform == DW_FORM_exprloc) { + int showhextoo = 1; + print_exprloc_content(dbg,die,attrib,showhextoo,&esb_base); + } else { + show_attr_form_error(dbg,attr,theform,&esb_base); + } + valname = esb_get_string(&esb_base); + } + break; + case DW_AT_SUN_func_offsets: + { + /* value is a location description or location list */ + Dwarf_Half theform = 0; + Dwarf_Half directform = 0; + get_form_values(attrib,&theform,&directform); + esb_empty_string(&esb_base); + get_FLAG_BLOCK_string(dbg, attrib,&esb_base); + show_form_itself(show_form_used,verbose, theform, + directform,&esb_base); + valname = esb_get_string(&esb_base); + } + break; + case DW_AT_SUN_cf_kind: + { + Dwarf_Half kind = 0; + Dwarf_Unsigned tempud = 0; + Dwarf_Error err = 0; + int wres = 0; + Dwarf_Half theform = 0; + Dwarf_Half directform = 0; + get_form_values(attrib,&theform,&directform); + wres = dwarf_formudata (attrib,&tempud, &err); + esb_empty_string(&esb_base); + if(wres == DW_DLV_OK) { + kind = tempud; + esb_append(&esb_base, + get_ATCF_name(kind,dwarf_names_print_on_error)); + } else if (wres == DW_DLV_NO_ENTRY) { + esb_append(&esb_base, "?"); + } else { + print_error(dbg,"Cannot get formudata....",wres,err); + esb_append(&esb_base, "??"); + } + show_form_itself(show_form_used,verbose, theform, + directform,&esb_base); + valname = esb_get_string(&esb_base); + } + break; + case DW_AT_upper_bound: + { + Dwarf_Half theform; + int rv; + rv = dwarf_whatform(attrib,&theform,&err); + /* depending on the form and the attribute, process the form */ + if(rv == DW_DLV_ERROR) { + print_error(dbg, "dwarf_whatform Cannot find attr form", + rv, err); + } else if (rv == DW_DLV_NO_ENTRY) { + break; + } + + esb_empty_string(&esb_base); + switch (theform) { + case DW_FORM_block1: { + Dwarf_Half theform = 0; + Dwarf_Half directform = 0; + get_form_values(attrib,&theform,&directform); + get_location_list(dbg, die, attrib, &esb_base); + show_form_itself(show_form_used,verbose, theform, + directform,&esb_base); + valname = esb_get_string(&esb_base); + } + break; + default: + get_attr_value(dbg, tag, die, + attrib, srcfiles, cnt, &esb_base, show_form_used,verbose); + valname = esb_get_string(&esb_base); + break; + } + break; + } + case DW_AT_low_pc: + case DW_AT_high_pc: + { + Dwarf_Half theform; + int rv; + rv = dwarf_whatform(attrib,&theform,&err); + /* Depending on the form and the attribute, + process the form. */ + if(rv == DW_DLV_ERROR) { + print_error(dbg, "dwarf_whatform cannot Find attr form", + rv, err); + } else if (rv == DW_DLV_NO_ENTRY) { + break; + } + esb_empty_string(&esb_base); + if( theform != DW_FORM_addr) { + /* New in DWARF4: other forms are not an address + but are instead offset from pc. + One could test for DWARF4 here before adding + this string, but that seems unnecessary as this + could not happen with DWARF3 or earlier. + A normal consumer would have to add this value to + DW_AT_low_pc to get a true pc. */ + esb_append(&esb_base,"<offset-from-lowpc>"); + } + get_attr_value(dbg, tag, die, attrib, srcfiles, cnt, + &esb_base,show_form_used,verbose); + valname = esb_get_string(&esb_base); + + /* Update base and high addresses for CU */ + if (seen_CU && (need_CU_base_address || + need_CU_high_address)) { + + /* Update base address for CU */ + if (need_CU_base_address && attr == DW_AT_low_pc) { + dwarf_formaddr(attrib, &CU_base_address, &err); + need_CU_base_address = FALSE; + } + + /* Update high address for CU */ + if (need_CU_high_address && attr == DW_AT_high_pc) { + dwarf_formaddr(attrib, &CU_high_address, &err); + need_CU_high_address = FALSE; + } + } + + /* Record the low and high addresses as we have them */ + if ((check_decl_file || check_ranges || + check_locations) && theform == DW_FORM_addr) { + Dwarf_Addr addr = 0; + dwarf_formaddr(attrib, &addr, &err); + if (attr == DW_AT_low_pc) { + lowAddr = addr; + bSawLow = TRUE; + /* Record the base address of the last seen PU + to be used when checking line information */ + if (seen_PU && !seen_PU_base_address) { + seen_PU_base_address = TRUE; + PU_base_address = addr; + } + } else { + highAddr = addr; + bSawHigh = TRUE; + /* Record the high address of the last seen PU + to be used when checking line information */ + if (seen_PU && !seen_PU_high_address) { + seen_PU_high_address = TRUE; + PU_high_address = addr; + } + } + + /* We have now both low_pc and high_pc values */ + if (bSawLow && bSawHigh) { + + /* We need to decide if this PU is + valid, as the SN Linker marks a stripped + function by setting lowpc to -1; + also for discarded comdat, both lowpc + and highpc are zero */ + if (need_PU_valid_code) { + need_PU_valid_code = FALSE; + + /* To ignore a PU as invalid code, + only consider the lowpc and + highpc values associated with the + DW_TAG_subprogram; other + instances of lowpc and highpc, + must be ignore (lexical blocks) */ + in_valid_code = TRUE; + if (IsInvalidCode(lowAddr,highAddr) && + tag == DW_TAG_subprogram) { + in_valid_code = FALSE; + } + } + + /* We have a low_pc/high_pc pair; + check if they are valid */ + if (in_valid_code) { + DWARF_CHECK_COUNT(ranges_result,1); + if (lowAddr != elf_max_address && + lowAddr > highAddr) { + DWARF_CHECK_ERROR(ranges_result, + ".debug_info: Incorrect values " + "for low_pc/high_pc"); + if (check_verbose_mode) { + printf("Low = 0x%" DW_PR_XZEROS DW_PR_DUx + ", High = 0x%" DW_PR_XZEROS DW_PR_DUx "\n", + lowAddr,highAddr); + } + } + if (check_decl_file || check_ranges || + check_locations) { + AddEntryIntoBucketGroup(pRangesInfo,0,lowAddr, + lowAddr,highAddr,NULL,FALSE); + } + } + bSawLow = FALSE; + bSawHigh = FALSE; + } + } + } + break; + case DW_AT_ranges: + { + Dwarf_Half theform = 0; + int rv; + + rv = dwarf_whatform(attrib,&theform,&err); + if(rv == DW_DLV_ERROR) { + print_error(dbg, "dwarf_whatform cannot find Attr Form", + rv, err); + } else if (rv == DW_DLV_NO_ENTRY) { + break; + } + + esb_empty_string(&esb_base); + get_attr_value(dbg, tag,die, attrib, srcfiles, cnt, &esb_base, + show_form_used,verbose); + print_range_attribute(dbg, die, attr,attr_in, theform, + dwarf_names_print_on_error,print_information, + &append_extra_string); + valname = esb_get_string(&esb_base); + } + break; + case DW_AT_MIPS_linkage_name: + esb_empty_string(&esb_base); + get_attr_value(dbg, tag, die, attrib, srcfiles, + cnt, &esb_base, show_form_used,verbose); + valname = esb_get_string(&esb_base); + + if (check_locations || check_ranges) { + int local_show_form = 0; + int local_verbose = 0; + struct esb_s lesb; + const char *name = 0; + esb_constructor(&lesb); + get_attr_value(dbg, tag, die, attrib, srcfiles, cnt, + &lesb, local_show_form,local_verbose); + /* Look for specific name forms, attempting to + notice and report 'odd' identifiers. */ + name = esb_get_string(&lesb); + safe_strcpy(PU_name,sizeof(PU_name),name,strlen(name)); + } + break; + case DW_AT_name: + case DW_AT_GNU_template_name: + esb_empty_string(&esb_base); + get_attr_value(dbg, tag, die, attrib, srcfiles, cnt, + &esb_base, show_form_used,verbose); + valname = esb_get_string(&esb_base); + + if (check_names && checking_this_compiler()) { + int local_show_form = FALSE; + int local_verbose = 0; + struct esb_s lesb; + const char *name = 0; + esb_constructor(&lesb); + get_attr_value(dbg, tag, die, attrib, srcfiles, cnt, + &lesb, local_show_form,local_verbose); + /* Look for specific name forms, attempting to + notice and report 'odd' identifiers. */ + name = esb_get_string(&lesb); + DWARF_CHECK_COUNT(names_result,1); + if (!strcmp("\"(null)\"",name)) { + DWARF_CHECK_ERROR(names_result, + "string attribute is \"(null)\"."); + } else { + if (!dot_ok_in_identifier(tag,die,name) + && !need_CU_name && strchr(name,'.')) { + /* This is a suggestion there 'might' be + a surprising name, not a guarantee of an + error. */ + DWARF_CHECK_ERROR(names_result, + "string attribute is invalid."); + } + } + esb_destructor(&lesb); + } + + /* If we are in checking mode and we do not have a PU name */ + if ((check_locations || check_ranges) && seen_PU && !PU_name[0]) { + int local_show_form = FALSE; + int local_verbose = 0; + const char *name = 0; + struct esb_s lesb; + esb_constructor(&lesb); + get_attr_value(dbg, tag, die, attrib, srcfiles, cnt, + &lesb, local_show_form,local_verbose); + name = esb_get_string(&lesb); + + safe_strcpy(PU_name,sizeof(PU_name),name,strlen(name)); + esb_destructor(&lesb); + } + + /* If we are processing the compile unit, record the name */ + if (seen_CU && need_CU_name) { + /* Lets not get the form name included. */ + struct esb_s lesb; + int local_show_form_used = FALSE; + int local_verbose = 0; + char *localname = 0; + esb_constructor(&lesb); + get_attr_value(dbg, tag, die, attrib, srcfiles, cnt, + &lesb, local_show_form_used,local_verbose); + localname = esb_get_string(&lesb); + safe_strcpy(CU_name,sizeof(CU_name),localname,strlen(localname)); + need_CU_name = FALSE; + esb_destructor(&lesb); + } + break; + + case DW_AT_producer: + esb_empty_string(&esb_base); + get_attr_value(dbg, tag, die, attrib, srcfiles, cnt, + &esb_base, show_form_used,verbose); + valname = esb_get_string(&esb_base); + /* If we are in checking mode, identify the compiler */ + if (do_check_dwarf || search_is_on) { + /* Do not use show-form here! We just want the producer name, not + the form name. */ + int show_form_local = FALSE; + int local_verbose = 0; + struct esb_s local_e; + esb_constructor(&local_e); + get_attr_value(dbg, tag, die, attrib, srcfiles, cnt, + &local_e, show_form_local,local_verbose); + /* Check if this compiler version is a target */ + update_compiler_target(esb_get_string(&local_e)); + esb_destructor(&local_e); + } + break; + + + /* When dealing with linkonce symbols, the low_pc and high_pc + are associated with a specific symbol; SNC always generate a name in + the for of DW_AT_MIPS_linkage_name; GCC does not; instead it generates + DW_AT_abstract_origin or DW_AT_specification; in that case we have to + traverse this attribute in order to get the name for the linkonce */ + case DW_AT_specification: + case DW_AT_abstract_origin: + case DW_AT_type: + esb_empty_string(&esb_base); + get_attr_value(dbg, tag, die, attrib, srcfiles, cnt, &esb_base, + show_form_used,verbose); + valname = esb_get_string(&esb_base); + if (check_forward_decl || check_self_references) { + Dwarf_Off die_off = 0; + Dwarf_Off ref_off = 0; + int res = 0; + int suppress_check = 0; + + /* Get the global offset for reference */ + res = dwarf_global_formref(attrib, &ref_off, &err); + if (res != DW_DLV_OK) { + int myerr = dwarf_errno(err); + if(myerr == DW_DLE_REF_SIG8_NOT_HANDLED) { + /* DW_DLE_REF_SIG8_NOT_HANDLED */ + /* No offset available, it makes little sense + to delve into this sort of reference unless + we think a graph of self-refs *across* + type-units is possible. Hmm. FIXME? */ + suppress_check = 1 ; + dwarf_dealloc(dbg,err,DW_DLA_ERROR); + err = 0; + } else { + print_error(dbg, "dwarf_die_CU_offsetD", res, err); + } + } + res = dwarf_dieoffset(die, &die_off, &err); + if (res != DW_DLV_OK) { + print_error(dbg, "ref formwith no ref?!", res, err); + } + + if (!suppress_check && check_self_references) { + Dwarf_Die ref_die = 0; + + ResetBucketGroup(pVisitedInfo); + AddEntryIntoBucketGroup(pVisitedInfo,die_off,0,0,0,NULL,FALSE); + + /* Follow reference chain, looking for self references */ + res = dwarf_offdie_b(dbg,ref_off,is_info,&ref_die,&err); + if (res == DW_DLV_OK) { + ++die_indent_level; + struct esb_s copy_base; + if (dump_visited_info) { + Dwarf_Off off; + dwarf_die_CU_offset(die, &off, &err); + printf("<%2d><0x%" DW_PR_XZEROS DW_PR_DUx + " GOFF=0x%" DW_PR_XZEROS DW_PR_DUx "> ", + die_indent_level, (Dwarf_Unsigned)off, + (Dwarf_Unsigned)die_off); + printf("%*s%s -> %s\n",die_indent_level * 2 + 2, + " ",atname,valname); + } + /* Because esb_base is global, lets not + let the traversal trash what we have here. */ + esb_constructor(©_base); + esb_append(©_base,esb_get_string(&esb_base)); + esb_empty_string(&esb_base); + traverse_one_die(dbg,attrib,ref_die,srcfiles,cnt,die_indent_level); + esb_empty_string(&esb_base); + esb_append(&esb_base,esb_get_string(©_base)); + esb_destructor(©_base); + dwarf_dealloc(dbg,ref_die,DW_DLA_DIE); + ref_die = 0; + --die_indent_level; + } + DeleteKeyInBucketGroup(pVisitedInfo,die_off); + } + + if (!suppress_check && check_forward_decl) { + if (attr == DW_AT_specification) { + /* Check the DW_AT_specification does not make forward + references to DIEs. + DWARF4 specifications, section 2.13.2, + but really they are legal, + this test is probably wrong. */ + DWARF_CHECK_COUNT(forward_decl_result,1); + if (ref_off > die_off) { + DWARF_CHECK_ERROR2(forward_decl_result, + "Invalid forward reference to DIE: ",valname); + } + } + } + } + /* If we are in checking mode and we do not have a PU name */ + if ((check_locations || check_ranges) && seen_PU && !PU_name[0]) { + if (tag == DW_TAG_subprogram) { + /* This gets the DW_AT_name if this DIE has one. */ + Dwarf_Addr low_pc = 0; + static char proc_name[BUFSIZ]; + proc_name[0] = 0; + get_proc_name(dbg,die,low_pc,proc_name,BUFSIZ,/*pcMap=*/0); + if (proc_name[0]) { + safe_strcpy(PU_name,sizeof(PU_name),proc_name, + strlen(proc_name)); + } + } + } + break; + default: + esb_empty_string(&esb_base); + get_attr_value(dbg, tag,die, attrib, srcfiles, cnt, &esb_base, + show_form_used,verbose); + valname = esb_get_string(&esb_base); + break; + } + if (!print_information) { + if(have_a_search_match(valname,atname) ) + { + if (search_wide_format) { + found_search_attr = TRUE; + } else { + PRINT_CU_INFO(); + bTextFound = TRUE; + } + } + } + if ((PRINTING_DIES && print_information) || bTextFound) { + /* Print just the Tags and Attributes */ + if (!display_offsets) { + printf("%-28s\n",atname); + } else { + if (dense) { + printf(" %s<%s>", atname, valname); + if(append_extra_string) { + char *v = esb_get_string(&esb_extra); + printf("%s", v); + } + } else { + printf("%-28s%s\n", atname, valname); + if( append_extra_string) { + char *v = esb_get_string(&esb_extra); + printf("%s", v); + } + } + } + /* Due to redirection of stderr */ + fflush(stdout); + bTextFound = FALSE; + } + return found_search_attr; +} + + +int +dwarfdump_print_one_locdesc(Dwarf_Debug dbg, + Dwarf_Locdesc * llbuf, + int skip_locdesc_header, + struct esb_s *string_out) +{ + + Dwarf_Locdesc *locd = 0; + Dwarf_Half no_of_ops = 0; + int i = 0; + char small_buf[100]; + + if (!skip_locdesc_header && (verbose || llbuf->ld_from_loclist)) { + snprintf(small_buf, sizeof(small_buf), + "<lowpc=0x%" DW_PR_XZEROS DW_PR_DUx ">", + (Dwarf_Unsigned) llbuf->ld_lopc); + esb_append(string_out, small_buf); + + + snprintf(small_buf, sizeof(small_buf), + "<highpc=0x%" DW_PR_XZEROS DW_PR_DUx ">", + (Dwarf_Unsigned) llbuf->ld_hipc); + esb_append(string_out, small_buf); + if (display_offsets && verbose) { + snprintf(small_buf, sizeof(small_buf), + "<from %s offset 0x%" DW_PR_XZEROS DW_PR_DUx ">", + llbuf->ld_from_loclist ? ".debug_loc" : ".debug_info", + llbuf->ld_section_offset); + esb_append(string_out, small_buf); + } + } + + locd = llbuf; + no_of_ops = llbuf->ld_cents; + for (i = 0; i < no_of_ops; i++) { + Dwarf_Loc * op = &locd->ld_s[i]; + + int res = _dwarf_print_one_expr_op(dbg,op,i,string_out); + if(res == DW_DLV_ERROR) { + return res; + } + } + return DW_DLV_OK; +} + + + +static int +op_has_no_operands(int op) +{ + unsigned i = 0; + if(op >= DW_OP_lit0 && op <= DW_OP_reg31) { + return TRUE; + } + for( ; ; ++i) { + struct operation_descr_s *odp = opdesc+i; + if(odp->op_code == 0) { + break; + } + if(odp->op_code != op) { + continue; + } + if (odp->op_count == 0) { + return TRUE; + } + return FALSE; + } + return FALSE; +} + +int +_dwarf_print_one_expr_op(Dwarf_Debug dbg,Dwarf_Loc* expr,int index, + struct esb_s *string_out) +{ + /* local_space_needed is intended to be 'more than big enough' + for a short group of loclist entries. */ + char small_buf[100]; + Dwarf_Small op; + Dwarf_Unsigned opd1; + Dwarf_Unsigned opd2; + const char * op_name; + + if (index > 0) { + esb_append(string_out, " "); + } + + op = expr->lr_atom; + + /* We have valid operands whose values are bigger than the + DW_OP_nop = 0x96; for example: DW_OP_GNU_push_tls_address = 0xe0 + Also, the function 'get_OP_name' handles this case, generating a + name 'Unknown OP value'. */ + if (op > DW_OP_hi_user) { + print_error(dbg, "dwarf_op unexpected value!", DW_DLV_OK, + err); + return DW_DLV_ERROR; + } + op_name = get_OP_name(op,dwarf_names_print_on_error); + esb_append(string_out, op_name); + + opd1 = expr->lr_number; + if(op_has_no_operands(op)) { + /* Nothing to add. */ + } else if (op >= DW_OP_breg0 && op <= DW_OP_breg31) { + snprintf(small_buf, sizeof(small_buf), + "%+" DW_PR_DSd , (Dwarf_Signed) opd1); + esb_append(string_out, small_buf); + } else { + switch (op) { + case DW_OP_addr: + snprintf(small_buf, sizeof(small_buf), + " 0x%" DW_PR_XZEROS DW_PR_DUx , opd1); + esb_append(string_out, small_buf); + break; + case DW_OP_const1s: + case DW_OP_const2s: + case DW_OP_const4s: + case DW_OP_const8s: + case DW_OP_consts: + case DW_OP_skip: + case DW_OP_bra: + case DW_OP_fbreg: + snprintf(small_buf, sizeof(small_buf), + " %" DW_PR_DSd, (Dwarf_Signed) opd1); + esb_append(string_out, small_buf); + break; + case DW_OP_const1u: + case DW_OP_const2u: + case DW_OP_const4u: + case DW_OP_const8u: + case DW_OP_constu: + case DW_OP_pick: + case DW_OP_plus_uconst: + case DW_OP_regx: + case DW_OP_piece: + case DW_OP_deref_size: + case DW_OP_xderef_size: + snprintf(small_buf, sizeof(small_buf), + " %" DW_PR_DUu , opd1); + esb_append(string_out, small_buf); + break; + case DW_OP_bregx: + snprintf(small_buf, sizeof(small_buf), + "0x%08" DW_PR_DUx , opd1); + esb_append(string_out, small_buf); + opd2 = expr->lr_number2; + snprintf(small_buf, sizeof(small_buf), + "+%" DW_PR_DSd , (Dwarf_Signed) opd2); + esb_append(string_out, small_buf); + break; + case DW_OP_call2: + snprintf(small_buf, sizeof(small_buf), + " 0x%" DW_PR_XZEROS DW_PR_DUx , opd1); + esb_append(string_out, small_buf); + break; + case DW_OP_call4: + snprintf(small_buf, sizeof(small_buf), + " 0x%" DW_PR_XZEROS DW_PR_DUx , opd1); + esb_append(string_out, small_buf); + break; + case DW_OP_call_ref: + snprintf(small_buf, sizeof(small_buf), + " 0x%" DW_PR_XZEROS DW_PR_DUx , opd1); + esb_append(string_out, small_buf); + break; + case DW_OP_bit_piece: + snprintf(small_buf, sizeof(small_buf), + " 0x%" DW_PR_XZEROS DW_PR_DUx , opd1); + esb_append(string_out, small_buf); + opd2 = expr->lr_number2; + snprintf(small_buf, sizeof(small_buf), + " offset 0x%" DW_PR_DUx , (Dwarf_Signed) opd2); + esb_append(string_out, small_buf); + break; + case DW_OP_implicit_value: + { +#define IMPLICIT_VALUE_PRINT_MAX 12 + unsigned int print_len = 0; + snprintf(small_buf, sizeof(small_buf), + " 0x%" DW_PR_XZEROS DW_PR_DUx , opd1); + esb_append(string_out, small_buf); + /* The other operand is a block of opd1 bytes. */ + /* FIXME */ + print_len = opd1; + if(print_len > IMPLICIT_VALUE_PRINT_MAX) { + print_len = IMPLICIT_VALUE_PRINT_MAX; + } +#undef IMPLICIT_VALUE_PRINT_MAX + if(print_len > 0) { + const unsigned char *bp = 0; + unsigned int i = 0; + opd2 = expr->lr_number2; + /* This is a really ugly cast, a way + to implement DW_OP_implicit value in + this libdwarf context. */ + bp = (const unsigned char *) opd2; + esb_append(string_out," contents 0x"); + for( ; i < print_len; ++i,++bp) { + /* Do not use DW_PR_DUx here, + the value *bp is a const unsigned char. */ + snprintf(small_buf, sizeof(small_buf), + "%02x", *bp); + esb_append(string_out,small_buf); + } + } + } + break; + + /* We do not know what the operands, if any, are. */ + case DW_OP_HP_unknown: + case DW_OP_HP_is_value: + case DW_OP_HP_fltconst4: + case DW_OP_HP_fltconst8: + case DW_OP_HP_mod_range: + case DW_OP_HP_unmod_range: + case DW_OP_HP_tls: + case DW_OP_INTEL_bit_piece: + break; + case DW_OP_stack_value: /* DWARF4 */ + break; + case DW_OP_GNU_uninit: /* DW_OP_APPLE_uninit */ + /* No operands. */ + break; + case DW_OP_GNU_encoded_addr: + snprintf(small_buf, sizeof(small_buf), + " 0x%" DW_PR_XZEROS DW_PR_DUx , opd1); + esb_append(string_out, small_buf); + break; + case DW_OP_GNU_implicit_pointer: + snprintf(small_buf, sizeof(small_buf), + " 0x%" DW_PR_XZEROS DW_PR_DUx , opd1); + esb_append(string_out, small_buf); + break; + case DW_OP_GNU_entry_value: + snprintf(small_buf, sizeof(small_buf), + " 0x%" DW_PR_XZEROS DW_PR_DUx , opd1); + esb_append(string_out, small_buf); + break; + default: + { + snprintf(small_buf, sizeof(small_buf), + " dwarf_op unknown 0x%x", (unsigned)op); + esb_append(string_out,small_buf); + } + break; + } + } + return DW_DLV_OK; +} + +/* Fill buffer with location lists + Buffer esbp expands as needed. +*/ +/*ARGSUSED*/ static void +get_location_list(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Attribute attr, + struct esb_s *esbp) +{ + Dwarf_Locdesc *llbuf = 0; + Dwarf_Locdesc **llbufarray = 0; + Dwarf_Signed no_of_elements; + Dwarf_Error err; + int i; + int lres = 0; + int llent = 0; + int skip_locdesc_header = 0; + + /* Base address used to update entries in .debug_loc */ + Dwarf_Addr base_address = CU_base_address; + Dwarf_Addr lopc = 0; + Dwarf_Addr hipc = 0; + Dwarf_Bool bError = FALSE; + + if (use_old_dwarf_loclist) { + lres = dwarf_loclist(attr, &llbuf, &no_of_elements, &err); + if (lres == DW_DLV_ERROR) { + print_error(dbg, "dwarf_loclist", lres, err); + } else if (lres == DW_DLV_NO_ENTRY) { + return; + } + dwarfdump_print_one_locdesc(dbg, llbuf,skip_locdesc_header,esbp); + dwarf_dealloc(dbg, llbuf->ld_s, DW_DLA_LOC_BLOCK); + dwarf_dealloc(dbg, llbuf, DW_DLA_LOCDESC); + return; + } + + lres = dwarf_loclist_n(attr, &llbufarray, &no_of_elements, &err); + if (lres == DW_DLV_ERROR) { + print_error(dbg, "dwarf_loclist", lres, err); + } else if (lres == DW_DLV_NO_ENTRY) { + return; + } + for (llent = 0; llent < no_of_elements; ++llent) { + char small_buf[100]; + Dwarf_Off offset = 0; + + llbuf = llbufarray[llent]; + /* If we have a location list refering to the .debug_loc + Check for specific compiler we are validating. */ + if (check_locations && in_valid_code && + llbuf->ld_from_loclist && checking_this_compiler()) { + /* To calculate the offset, we use: + sizeof(Dwarf_Half) -> number of expression list + 2 * address_size -> low_pc and high_pc */ + offset = llbuf->ld_section_offset - + llbuf->ld_cents * sizeof(Dwarf_Half) - + 2 * elf_address_size; + + if (llbuf->ld_lopc == elf_max_address) { + /* (0xffffffff,addr), use specific address + (current PU address) */ + base_address = llbuf->ld_hipc; + } else { + /* (offset,offset), update using CU address */ + lopc = llbuf->ld_lopc + base_address; + hipc = llbuf->ld_hipc + base_address; + + DWARF_CHECK_COUNT(locations_result,1); + + /* Check the low_pc and high_pc are within + a valid range in the .text section */ + if (IsValidInBucketGroup(pRangesInfo,lopc) && + IsValidInBucketGroup(pRangesInfo,hipc)) { + /* Valid values; do nothing */ + } else { + /* At this point may be we are dealing with + a linkonce symbol */ + if (IsValidInLinkonce(pLinkonceInfo,PU_name, + lopc,hipc)) { + /* Valid values; do nothing */ + } else { + bError = TRUE; + DWARF_CHECK_ERROR(locations_result, + ".debug_loc: Address outside a " + "valid .text range"); + if (check_verbose_mode) { + printf( + "Offset = 0x%" DW_PR_XZEROS DW_PR_DUx + ", Base = 0x%" DW_PR_XZEROS DW_PR_DUx ", " + "Low = 0x%" DW_PR_XZEROS DW_PR_DUx + " (0x%" DW_PR_XZEROS DW_PR_DUx + "), High = 0x%" DW_PR_XZEROS DW_PR_DUx + " (0x%" DW_PR_XZEROS DW_PR_DUx ")\n", + offset,base_address,lopc, + llbuf->ld_lopc, + hipc, + llbuf->ld_hipc); + } + } + } + } + } + + if (!dense && llbuf->ld_from_loclist) { + if (llent == 0) { + snprintf(small_buf, sizeof(small_buf), + "<loclist with %ld entries follows>", + (long) no_of_elements); + esb_append(esbp, small_buf); + } + esb_append(esbp, "\n\t\t\t"); + snprintf(small_buf, sizeof(small_buf), "[%2d]", llent); + esb_append(esbp, small_buf); + } + lres = dwarfdump_print_one_locdesc(dbg, + llbuf, + skip_locdesc_header, + esbp); + if (lres == DW_DLV_ERROR) { + return; + } else { + /* DW_DLV_OK so we add follow-on at end, else is + DW_DLV_NO_ENTRY (which is impossible, treat like + DW_DLV_OK). */ + } + } + + if (bError && check_verbose_mode) { + printf("\n"); + } + + for (i = 0; i < no_of_elements; ++i) { + dwarf_dealloc(dbg, llbufarray[i]->ld_s, DW_DLA_LOC_BLOCK); + dwarf_dealloc(dbg, llbufarray[i], DW_DLA_LOCDESC); + } + dwarf_dealloc(dbg, llbufarray, DW_DLA_LIST); +} + +static void +formx_unsigned(Dwarf_Unsigned u, struct esb_s *esbp, Dwarf_Bool hex_format) +{ + char small_buf[40]; + if (hex_format) { + snprintf(small_buf, sizeof(small_buf),"0x%" DW_PR_XZEROS DW_PR_DUx , u); + } else { + snprintf(small_buf, sizeof(small_buf), + "%" DW_PR_DUu , u); + } + esb_append(esbp, small_buf); +} +static void +formx_signed(Dwarf_Signed u, struct esb_s *esbp) +{ + char small_buf[40]; + snprintf(small_buf, sizeof(small_buf), + "%" DW_PR_DSd , u); + esb_append(esbp, small_buf); +} +/* We think this is an integer. Figure out how to print it. + In case the signedness is ambiguous (such as on + DW_FORM_data1 (ie, unknown signedness) print two ways. +*/ +static int +formxdata_print_value(Dwarf_Debug dbg,Dwarf_Attribute attrib, + struct esb_s *esbp, + Dwarf_Error * err, Dwarf_Bool hex_format) +{ + Dwarf_Signed tempsd = 0; + Dwarf_Unsigned tempud = 0; + int sres = 0; + int ures = 0; + Dwarf_Error serr = 0; + + ures = dwarf_formudata(attrib, &tempud, err); + sres = dwarf_formsdata(attrib, &tempsd, &serr); + if(ures == DW_DLV_OK) { + if(sres == DW_DLV_OK) { + if(tempud == tempsd && tempsd >= 0) { + /* Data is the same value and not negative, + so makes no difference which + we print. */ + formx_unsigned(tempud,esbp,hex_format); + } else { + formx_unsigned(tempud,esbp,hex_format); + esb_append(esbp,"(as signed = "); + formx_signed(tempsd,esbp); + esb_append(esbp,")"); + } + } else if (sres == DW_DLV_NO_ENTRY) { + formx_unsigned(tempud,esbp,hex_format); + } else /* DW_DLV_ERROR */{ + formx_unsigned(tempud,esbp,hex_format); + } + goto cleanup; + } else { + /* ures == DW_DLV_ERROR or DW_DLV_NO_ENTRY*/ + if(sres == DW_DLV_OK) { + formx_signed(tempsd,esbp); + } else { + /* Neither worked. */ + } + } + /* Clean up any unused Dwarf_Error data. + DW_DLV_NO_ENTRY cannot really happen, + so a complete cleanup for that is + not necessary. */ + cleanup: + if(sres == DW_DLV_OK || ures == DW_DLV_OK) { + if(sres == DW_DLV_ERROR) { + dwarf_dealloc(dbg,serr,DW_DLA_ERROR); + } + if(ures == DW_DLV_ERROR) { + dwarf_dealloc(dbg,*err,DW_DLA_ERROR); + *err = 0; + } + return DW_DLV_OK; + } + if(sres == DW_DLV_ERROR || ures == DW_DLV_ERROR) { + if(sres == DW_DLV_ERROR && ures == DW_DLV_ERROR) { + dwarf_dealloc(dbg,serr,DW_DLA_ERROR); + return DW_DLV_ERROR; + } + if(sres == DW_DLV_ERROR) { + *err = serr; + } + return DW_DLV_ERROR; + } + /* Both are DW_DLV_NO_ENTRY which is crazy, impossible. */ + return DW_DLV_NO_ENTRY; +} + +static char * +get_form_number_as_string(int form, char *buf, unsigned bufsize) +{ + snprintf(buf,bufsize," %d",form); + return buf; +} + +static void +print_exprloc_content(Dwarf_Debug dbg,Dwarf_Die die, Dwarf_Attribute attrib, + int showhextoo, struct esb_s *esbp) +{ + Dwarf_Ptr x = 0; + Dwarf_Unsigned tempud = 0; + char small_buf[80]; + Dwarf_Error err = 0; + int wres = 0; + wres = dwarf_formexprloc(attrib,&tempud,&x,&err); + if(wres == DW_DLV_NO_ENTRY) { + /* Show nothing? Impossible. */ + } else if(wres == DW_DLV_ERROR) { + print_error(dbg, "Cannot get a DW_FORM_exprbloc....", wres, err); + } else { + Dwarf_Half address_size = 0; + int ares = 0; + unsigned u = 0; + snprintf(small_buf, sizeof(small_buf), + "len 0x%04" DW_PR_DUx ": ",tempud); + esb_append(esbp, small_buf); + if(showhextoo) { + for (u = 0; u < tempud; u++) { + snprintf(small_buf, sizeof(small_buf), "%02x", + *(u + (unsigned char *) x)); + esb_append(esbp, small_buf); + } + esb_append(esbp,": "); + } + address_size = 0; + ares = dwarf_get_die_address_size(die,&address_size,&err); + if(wres == DW_DLV_NO_ENTRY) { + print_error(dbg,"Cannot get die address size for exprloc", + ares,err); + } else if(wres == DW_DLV_ERROR) { + print_error(dbg,"Cannot Get die address size for exprloc", + ares,err); + } else { + get_string_from_locs(dbg,x,tempud,address_size, esbp); + } + } +} + + + + +/* Fill buffer with attribute value. + We pass in tag so we can try to do the right thing with + broken compiler DW_TAG_enumerator + + We append to esbp's buffer. +*/ +void +get_attr_value(Dwarf_Debug dbg, Dwarf_Half tag, + Dwarf_Die die, Dwarf_Attribute attrib, + char **srcfiles, Dwarf_Signed cnt, struct esb_s *esbp, + int show_form, + int local_verbose) +{ + Dwarf_Half theform = 0; + char * temps = 0; + Dwarf_Block *tempb = 0; + Dwarf_Signed tempsd = 0; + Dwarf_Unsigned tempud = 0; + int i = 0; + Dwarf_Half attr = 0; + Dwarf_Off off = 0; + Dwarf_Off goff = 0; /* Global offset */ + Dwarf_Die die_for_check = 0; + Dwarf_Half tag_for_check = 0; + Dwarf_Bool tempbool = 0; + Dwarf_Addr addr = 0; + int fres = 0; + int bres = 0; + int wres = 0; + int dres = 0; + Dwarf_Half direct_form = 0; + char small_buf[COMPILE_UNIT_NAME_LEN]; /* Size to hold a filename */ + Dwarf_Bool is_info = TRUE; + + + is_info = dwarf_get_die_infotypes_flag(die); + /* Dwarf_whatform gets the real form, DW_FORM_indir is + never returned: instead the real form following + DW_FORM_indir is returned. */ + fres = dwarf_whatform(attrib, &theform, &err); + /* Depending on the form and the attribute, process the form. */ + if (fres == DW_DLV_ERROR) { + print_error(dbg, "dwarf_whatform cannot Find Attr Form", fres, + err); + } else if (fres == DW_DLV_NO_ENTRY) { + return; + } + + /* dwarf_whatform_direct gets the 'direct' form, so if + the form is DW_FORM_indir that is what is returned. */ + dwarf_whatform_direct(attrib, &direct_form, &err); + /* Ignore errors in dwarf_whatform_direct() */ + + + switch (theform) { + case DW_FORM_addr: + bres = dwarf_formaddr(attrib, &addr, &err); + if (bres == DW_DLV_OK) { + snprintf(small_buf, sizeof(small_buf), + "0x%" DW_PR_XZEROS DW_PR_DUx , + (Dwarf_Unsigned) addr); + esb_append(esbp, small_buf); + } else { + print_error(dbg, "addr formwith no addr?!", bres, err); + } + break; + case DW_FORM_ref_addr: + /* DW_FORM_ref_addr is not accessed thru formref: ** it is an + address (global section offset) in ** the .debug_info + section. */ + bres = dwarf_global_formref(attrib, &off, &err); + if (bres == DW_DLV_OK) { + snprintf(small_buf, sizeof(small_buf), + "<global die offset 0x%" DW_PR_XZEROS DW_PR_DUx + ">", + (Dwarf_Unsigned) off); + esb_append(esbp, small_buf); + } else { + print_error(dbg, + "DW_FORM_ref_addr form with no reference?!", + bres, err); + } + wres = dwarf_whatattr(attrib, &attr, &err); + if (wres == DW_DLV_ERROR) { + } else if (wres == DW_DLV_NO_ENTRY) { + } else { + if (attr == DW_AT_sibling) { + /* The value had better be inside the current CU + else there is a nasty error here, as a sibling + has to be in the same CU, it seems. */ + Dwarf_Off cuoff = 0; + Dwarf_Off culen = 0; + int res = dwarf_die_CU_offset_range(die,&cuoff, + &culen,&err); + DWARF_CHECK_COUNT(tag_tree_result,1); + if(res != DW_DLV_OK) { + } else { + Dwarf_Off cuend = cuoff+culen; + if(off < cuoff || off >= cuend) { + DWARF_CHECK_ERROR(tag_tree_result, + "DW_AT_sibling DW_FORM_ref_addr offset points " + "outside of current CU"); + } + } + } + } + + break; + case DW_FORM_ref1: + case DW_FORM_ref2: + case DW_FORM_ref4: + case DW_FORM_ref8: + case DW_FORM_ref_udata: + bres = dwarf_formref(attrib, &off, &err); + if (bres != DW_DLV_OK) { + /* Report incorrect offset */ + snprintf(small_buf,sizeof(small_buf), + "%s, offset=<0x%" DW_PR_XZEROS DW_PR_DUx + ">","reference form with no valid local ref?!",off); + print_error(dbg, small_buf, bres, err); + } + + /* Convert the local offset into a relative section offset */ + if (show_global_offsets) { + bres = dwarf_convert_to_global_offset(attrib, + off, &goff, &err); + if (bres != DW_DLV_OK) { + /* Report incorrect offset */ + snprintf(small_buf,sizeof(small_buf), + "%s, global die offset=<0x%" DW_PR_XZEROS DW_PR_DUx + ">","invalid offset",goff); + print_error(dbg, small_buf, bres, err); + } + } + + /* Do references inside <> to distinguish them ** from + constants. In dense form this results in <<>>. Ugly for + dense form, but better than ambiguous. davea 9/94 */ + if (show_global_offsets) { + snprintf(small_buf, sizeof(small_buf), + "<0x%" DW_PR_XZEROS DW_PR_DUx " GOFF=0x%" DW_PR_XZEROS DW_PR_DUx ">", + (Dwarf_Unsigned)off, goff); + } else { + snprintf(small_buf, sizeof(small_buf), + "<0x%" DW_PR_XZEROS DW_PR_DUx ">", off); + } + + esb_append(esbp, small_buf); + if (check_type_offset) { + attr = 0; + wres = dwarf_whatattr(attrib, &attr, &err); + if (wres == DW_DLV_ERROR) { + + } else if (wres == DW_DLV_NO_ENTRY) { + } + if (attr == DW_AT_type) { + dres = dwarf_offdie_b(dbg, cu_offset + off, + is_info, + &die_for_check, &err); + DWARF_CHECK_COUNT(type_offset_result,1); + if (dres != DW_DLV_OK) { + snprintf(small_buf,sizeof(small_buf), + "DW_AT_type offset does not point to a DIE for global offset 0x%" DW_PR_DUx " cu off 0x%" DW_PR_DUx " local offset 0x%" DW_PR_DUx, + cu_offset + off,cu_offset,off); + DWARF_CHECK_ERROR(type_offset_result,small_buf); + } else { + int tres2 = + dwarf_tag(die_for_check, &tag_for_check, &err); + if (tres2 == DW_DLV_OK) { + switch (tag_for_check) { + case DW_TAG_array_type: + case DW_TAG_class_type: + case DW_TAG_enumeration_type: + case DW_TAG_pointer_type: + case DW_TAG_reference_type: + case DW_TAG_string_type: + case DW_TAG_structure_type: + case DW_TAG_subroutine_type: + case DW_TAG_typedef: + case DW_TAG_union_type: + case DW_TAG_ptr_to_member_type: + case DW_TAG_set_type: + case DW_TAG_subrange_type: + case DW_TAG_base_type: + case DW_TAG_const_type: + case DW_TAG_file_type: + case DW_TAG_packed_type: + case DW_TAG_thrown_type: + case DW_TAG_volatile_type: + case DW_TAG_template_type_parameter: + case DW_TAG_template_value_parameter: + case DW_TAG_unspecified_type: + /* OK */ + break; + default: + { + snprintf(small_buf,sizeof(small_buf), + "DW_AT_type offset does not point to Type info we got tag 0x%x %s", + tag_for_check, + get_TAG_name(tag_for_check, + dwarf_names_print_on_error)); + DWARF_CHECK_ERROR(type_offset_result,small_buf); + } + break; + } + dwarf_dealloc(dbg, die_for_check, DW_DLA_DIE); + die_for_check = 0; + } else { + DWARF_CHECK_ERROR(type_offset_result, + "DW_AT_type offset does not exist"); + } + } + } + } + break; + case DW_FORM_block: + case DW_FORM_block1: + case DW_FORM_block2: + case DW_FORM_block4: + fres = dwarf_formblock(attrib, &tempb, &err); + if (fres == DW_DLV_OK) { + for (i = 0; i < tempb->bl_len; i++) { + snprintf(small_buf, sizeof(small_buf), "%02x", + *(i + (unsigned char *) tempb->bl_data)); + esb_append(esbp, small_buf); + } + dwarf_dealloc(dbg, tempb, DW_DLA_BLOCK); + tempb = 0; + } else { + print_error(dbg, "DW_FORM_blockn cannot get block\n", fres, + err); + } + break; + case DW_FORM_data1: + case DW_FORM_data2: + case DW_FORM_data4: + case DW_FORM_data8: + fres = dwarf_whatattr(attrib, &attr, &err); + if (fres == DW_DLV_ERROR) { + print_error(dbg, "FORM_datan cannot get attr", fres, err); + } else if (fres == DW_DLV_NO_ENTRY) { + print_error(dbg, "FORM_datan cannot get attr", fres, err); + } else { + switch (attr) { + case DW_AT_ordering: + case DW_AT_byte_size: + case DW_AT_bit_offset: + case DW_AT_bit_size: + case DW_AT_inline: + case DW_AT_language: + case DW_AT_visibility: + case DW_AT_virtuality: + case DW_AT_accessibility: + case DW_AT_address_class: + case DW_AT_calling_convention: + case DW_AT_discr_list: /* DWARF3 */ + case DW_AT_encoding: + case DW_AT_identifier_case: + case DW_AT_MIPS_loop_unroll_factor: + case DW_AT_MIPS_software_pipeline_depth: + case DW_AT_decl_column: + case DW_AT_decl_file: + case DW_AT_decl_line: + case DW_AT_call_column: + case DW_AT_call_file: + case DW_AT_call_line: + case DW_AT_start_scope: + case DW_AT_byte_stride: + case DW_AT_bit_stride: + case DW_AT_count: + case DW_AT_stmt_list: + case DW_AT_MIPS_fde: + { int show_form_here = 0; + wres = get_small_encoding_integer_and_name(dbg, + attrib, + &tempud, + /* attrname */ (char *) NULL, + /* err_string */ (const char **) NULL, + (encoding_type_func) 0, + &err,show_form_here); + + if (wres == DW_DLV_OK) { + snprintf(small_buf, sizeof(small_buf), + "0x%08" DW_PR_DUx , + tempud); + esb_append(esbp, small_buf); + if (attr == DW_AT_decl_file || attr == DW_AT_call_file) { + if (srcfiles && tempud > 0 && tempud <= cnt) { + /* added by user request */ + /* srcfiles is indexed starting at 0, but + DW_AT_decl_file defines that 0 means no + file, so tempud 1 means the 0th entry in + srcfiles, thus tempud-1 is the correct + index into srcfiles. */ + char *fname = srcfiles[tempud - 1]; + + esb_append(esbp, " "); + esb_append(esbp, fname); + } + + /* Validate integrity of files + referenced in .debug_line */ + if(check_decl_file) { + DWARF_CHECK_COUNT(decl_file_result,1); + /* Zero is always a legal index, it means + no source name provided. */ + if(tempud != 0 && tempud > cnt) { + if(!srcfiles) { + snprintf(small_buf,sizeof(small_buf), + "There is a file number=%" DW_PR_DUu + " but no source files " + " are known.",tempud); + } else { + snprintf(small_buf, sizeof(small_buf), + "Does not point to valid file info " + " filenum=%" DW_PR_DUu + " filecount=%" DW_PR_DUu ".", + tempud,cnt); + } + DWARF_CHECK_ERROR2(decl_file_result, + get_AT_name(attr, + dwarf_names_print_on_error), + small_buf); + } + } + } + } else { + print_error(dbg, "Cannot get encoding attribute ..", + wres, err); + } + } + break; + case DW_AT_const_value: + /* Do not use hexadecimal format */ + wres = formxdata_print_value(dbg,attrib,esbp, &err, FALSE); + if(wres == DW_DLV_OK){ + /* String appended already. */ + } else if (wres == DW_DLV_NO_ENTRY) { + /* nothing? */ + } else { + print_error(dbg,"Cannot get DW_AT_const_value ",wres,err); + } + + + break; + case DW_AT_upper_bound: + case DW_AT_lower_bound: + default: + /* Do not use hexadecimal format except for + DW_AT_ranges. */ + wres = formxdata_print_value(dbg,attrib,esbp, &err, + (DW_AT_ranges == attr)); + if (wres == DW_DLV_OK) { + /* String appended already. */ + } else if (wres == DW_DLV_NO_ENTRY) { + /* nothing? */ + } else { + print_error(dbg, "Cannot get form data..", wres, + err); + } + break; + } + } + if (cu_name_flag) { + if (attr == DW_AT_MIPS_fde) { + if (fde_offset_for_cu_low == DW_DLV_BADOFFSET) { + fde_offset_for_cu_low + = fde_offset_for_cu_high = tempud; + } else if (tempud < fde_offset_for_cu_low) { + fde_offset_for_cu_low = tempud; + } else if (tempud > fde_offset_for_cu_high) { + fde_offset_for_cu_high = tempud; + } + } + } + break; + case DW_FORM_sdata: + wres = dwarf_formsdata(attrib, &tempsd, &err); + if (wres == DW_DLV_OK) { + snprintf(small_buf, sizeof(small_buf), + "0x%" DW_PR_XZEROS DW_PR_DUx , tempsd); + esb_append(esbp, small_buf); + } else if (wres == DW_DLV_NO_ENTRY) { + /* nothing? */ + } else { + print_error(dbg, "Cannot get formsdata..", wres, err); + } + break; + case DW_FORM_udata: + wres = dwarf_formudata(attrib, &tempud, &err); + if (wres == DW_DLV_OK) { + snprintf(small_buf, sizeof(small_buf), "0x%" DW_PR_XZEROS DW_PR_DUx , + tempud); + esb_append(esbp, small_buf); + } else if (wres == DW_DLV_NO_ENTRY) { + /* nothing? */ + } else { + print_error(dbg, "Cannot get formudata....", wres, err); + } + break; + case DW_FORM_string: + case DW_FORM_strp: + wres = dwarf_formstring(attrib, &temps, &err); + if (wres == DW_DLV_OK) { + /* Print as quoted string for clarity. */ + esb_append(esbp, "\""); + esb_append(esbp, temps); + esb_append(esbp, "\""); + } else if (wres == DW_DLV_NO_ENTRY) { + /* nothing? */ + } else { + print_error(dbg, "Cannot get a formstr (or a formstrp)....", + wres, err); + } + + break; + case DW_FORM_flag: + wres = dwarf_formflag(attrib, &tempbool, &err); + if (wres == DW_DLV_OK) { + if (tempbool) { + snprintf(small_buf, sizeof(small_buf), "yes(%d)", + tempbool); + esb_append(esbp, small_buf); + } else { + snprintf(small_buf, sizeof(small_buf), "no"); + esb_append(esbp, small_buf); + } + } else if (wres == DW_DLV_NO_ENTRY) { + /* nothing? */ + } else { + print_error(dbg, "Cannot get formflag/p....", wres, err); + } + break; + case DW_FORM_indirect: + /* We should not ever get here, since the true form was + determined and direct_form has the DW_FORM_indirect if it is + used here in this attr. */ + esb_append(esbp, get_FORM_name(theform, + dwarf_names_print_on_error)); + break; + case DW_FORM_exprloc: { /* DWARF4 */ + int showhextoo = 1; + print_exprloc_content(dbg,die,attrib,showhextoo,esbp); + } + break; + case DW_FORM_sec_offset: { /* DWARF4 */ + string emptyattrname = 0; + int show_form_here = 0; + wres = get_small_encoding_integer_and_name(dbg, + attrib, + &tempud, + emptyattrname, + /* err_string */ NULL, + (encoding_type_func) 0, + &err,show_form_here); + if(wres == DW_DLV_NO_ENTRY) { + /* Show nothing? */ + } else if(wres == DW_DLV_ERROR) { + print_error(dbg, + "Cannot get a DW_FORM_sec_offset....", + wres, err); + } else { + snprintf(small_buf, sizeof(small_buf), + "0x%" DW_PR_XZEROS DW_PR_DUx, + tempud); + esb_append(esbp,small_buf); + } + } + + break; + case DW_FORM_flag_present: /* DWARF4 */ + esb_append(esbp,"yes(1)"); + break; + case DW_FORM_ref_sig8: { /* DWARF4 */ + Dwarf_Sig8 sig8data; + wres = dwarf_formsig8(attrib,&sig8data,&err); + if(wres != DW_DLV_OK) { + /* Show nothing? */ + print_error(dbg, + "Cannot get a DW_FORM_ref_sig8 ....", + wres, err); + } else { + struct esb_s sig8str; + esb_constructor(&sig8str); + format_sig8_string(&sig8data,&sig8str); + esb_append(esbp,esb_get_string(&sig8str)); + esb_destructor(&sig8str); + } + } + break; + + default: + print_error(dbg, "dwarf_whatform unexpected value", DW_DLV_OK, + err); + } + show_form_itself(show_form,local_verbose,theform, direct_form,esbp); +} + +void +format_sig8_string(Dwarf_Sig8*data, struct esb_s *out) +{ + unsigned i = 0; + char small_buf[40]; + esb_append(out,"0x"); + for( ; i < sizeof(data->signature); ++i) { + if (i == 4) { + esb_append(out," 0x"); + } + snprintf(small_buf,sizeof(small_buf), "%02x", + (unsigned char)(data->signature[i])); + esb_append(out,small_buf); + } +} + + +/* A cleanup so that when using a memory checker + we don't show irrelevant leftovers. +*/ +void +clean_up_die_esb() +{ + esb_destructor(&esb_base); +} + +static int +get_form_values(Dwarf_Attribute attrib, + Dwarf_Half * theform, Dwarf_Half * directform) +{ + Dwarf_Error err = 0; + int res = dwarf_whatform(attrib, theform, &err); + dwarf_whatform_direct(attrib, directform, &err); + return res; +} +static void +show_form_itself(int local_show_form, + int local_verbose, + int theform, + int directform, struct esb_s *esbp) +{ + char small_buf[100]; + if (local_show_form + && directform && directform == DW_FORM_indirect) { + char *form_indir = " (used DW_FORM_indirect"; + char *form_indir2 = ") "; + esb_append(esbp, form_indir); + if(local_verbose) { + esb_append(esbp, get_form_number_as_string(DW_FORM_indirect, + small_buf,sizeof(small_buf))); + } + esb_append(esbp, form_indir2); + } + if(local_show_form) { + esb_append(esbp," <form "); + esb_append(esbp,get_FORM_name(theform, + dwarf_names_print_on_error)); + if(local_verbose) { + esb_append(esbp, get_form_number_as_string(theform, + small_buf, sizeof(small_buf))); + } + esb_append(esbp,">"); + } +} + + +#include "tmp-ta-table.c" +#include "tmp-ta-ext-table.c" + +static int +legal_tag_attr_combination(Dwarf_Half tag, Dwarf_Half attr) +{ + if(tag <= 0) { + return FALSE; + } + if(tag < ATTR_TREE_ROW_COUNT) { + int index = attr / BITS_PER_WORD; + if ( index < ATTR_TREE_COLUMN_COUNT) { + unsigned bitflag = 1 << (attr % BITS_PER_WORD); + int known = ((tag_attr_combination_table[tag][index] + & bitflag) > 0 ? TRUE : FALSE); + if(known) { + return TRUE; + } + } + } + /* DW_AT_MIPS_fde used to return TRUE as that was + convenient for SGI/MIPS users. */ + if(!suppress_check_extensions_tables) { + int r = 0; + for ( ; r < ATTR_TREE_EXT_ROW_COUNT; ++r ) { + int c = 1; + if(tag != tag_attr_combination_ext_table[r][0]) { + continue; + } + for( ; c < ATTR_TREE_EXT_COLUMN_COUNT ; ++c) { + if (tag_attr_combination_ext_table[r][c] == attr) { + return TRUE; + } + } + } + } + return (FALSE); +} + +#include "tmp-tt-table.c" +#include "tmp-tt-ext-table.c" + +/* Look only at valid table entries + The check here must match the building-logic in + tag_tree.c + And must match the tags defined in dwarf.h + The tag_tree_combination_table is a table of bit flags. */ +static int +legal_tag_tree_combination(Dwarf_Half tag_parent, Dwarf_Half tag_child) +{ + if(tag_parent <= 0) { + return FALSE; + } + if ( tag_parent < TAG_TREE_ROW_COUNT) { + int index = tag_child / BITS_PER_WORD; + if ( index < TAG_TREE_COLUMN_COUNT) { + unsigned bitflag = 1 << (tag_child % BITS_PER_WORD); + int known = ((tag_tree_combination_table[tag_parent] + [index] & bitflag) > 0 ? TRUE : FALSE); + if(known) { + return TRUE; + } + } + } + if(!suppress_check_extensions_tables) { + int r = 0; + for ( ; r < TAG_TREE_EXT_ROW_COUNT; ++r ) { + int c = 1; + if(tag_parent != tag_tree_combination_ext_table[r][0]) { + continue; + } + for( ; c < TAG_TREE_EXT_COLUMN_COUNT ; ++c) { + if (tag_tree_combination_ext_table[r][c] == tag_child) { + return TRUE; + } + } + } + } + return (FALSE); +} + diff --git a/dwarfdump/print_frames.c b/dwarfdump/print_frames.c new file mode 100644 index 0000000..01e4130 --- /dev/null +++ b/dwarfdump/print_frames.c @@ -0,0 +1,1823 @@ +/* + Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2011 SN Systems Ltd. All Rights Reserved. + Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + + + $Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_frames.c,v 1.5 2006/06/14 20:34:02 davea Exp $ */ + +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + +/* From 199x through 2010 print_frames relied on + the order of the fdes matching the order of the functions + in the CUs when it came to printing a function name with + an FDE. This sometimes worked for SGI/IRIX because of + the way the compiler often emitted things. It always worked poorly + for gcc and other compilers. + + As of 2010 the addrmap.h addrmap.h code provides help + in doing a better job when the tsearch functions (part of + POSIX) are available. */ + +#include "globals.h" + +#include "print_frames.h" +#include "dwconf.h" +#include "esb.h" +#include "addrmap.h" + +static void +print_one_frame_reg_col(Dwarf_Debug dbg, + Dwarf_Unsigned rule_id, + Dwarf_Small value_type, + Dwarf_Unsigned reg_used, + Dwarf_Half addr_size, + struct dwconf_s *config_data, + Dwarf_Signed offset_relevant, + Dwarf_Signed offset, Dwarf_Ptr block_ptr); + +/* A strcpy which ensures NUL terminated string + and never overruns the output. +*/ +void +safe_strcpy(char *out, long outlen, const char *in, long inlen) +{ + if (inlen >= (outlen - 1)) { + strncpy(out, in, outlen - 1); + out[outlen - 1] = 0; + } else { + strcpy(out, in); + } +} + +/* For inlined functions, try to find name */ +static int +get_abstract_origin_funcname(Dwarf_Debug dbg,Dwarf_Attribute attr, + char *name_out, unsigned maxlen) +{ + Dwarf_Off off = 0; + Dwarf_Die origin_die = 0; + Dwarf_Attribute *atlist = NULL; + Dwarf_Signed atcnt = 0; + Dwarf_Signed i = 0; + int dres = 0; + int atres; + int name_found = 0; + int res = dwarf_global_formref(attr,&off,&err); + if(res != DW_DLV_OK) { + return DW_DLV_NO_ENTRY; + } + dres = dwarf_offdie(dbg,off,&origin_die,&err); + if(dres != DW_DLV_OK) { + return DW_DLV_NO_ENTRY; + } + atres = dwarf_attrlist(origin_die, &atlist, &atcnt, &err); + if (atres != DW_DLV_OK) { + dwarf_dealloc(dbg,origin_die,DW_DLA_DIE); + return DW_DLV_NO_ENTRY; + } + for (i = 0; i < atcnt; i++) { + Dwarf_Half lattr; + int ares; + ares = dwarf_whatattr(atlist[i], &lattr, &err); + if (ares == DW_DLV_ERROR) { + break; + } else if (ares == DW_DLV_OK) { + if(lattr == DW_AT_name) { + int sres = 0; + char* temps = 0; + sres = dwarf_formstring(atlist[i], &temps, &err); + if (sres == DW_DLV_OK) { + long len = (long) strlen(temps); + safe_strcpy(name_out, maxlen, temps, len); + name_found = 1; + break; + } + } + } + } + for (i = 0; i < atcnt; i++) { + dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR); + } + dwarf_dealloc(dbg, atlist, DW_DLA_LIST); + dwarf_dealloc(dbg,origin_die,DW_DLA_DIE); + if(!name_found) { + return DW_DLV_NO_ENTRY; + } + return DW_DLV_OK; +} +/* + Returns 1 if a proc with this low_pc found. + Else returns 0. + + From print_die.c this has no pcMap passed in, + we do not really have a sensible context, so this + really just looks at the current attributes for a name. +*/ +int +get_proc_name(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr low_pc, + char *proc_name_buf, int proc_name_buf_len, void **pcMap) +{ + Dwarf_Signed atcnt = 0; + Dwarf_Signed i = 0; + Dwarf_Attribute *atlist = NULL; + Dwarf_Addr low_pc_die = 0; + int atres = 0; + int funcres = 1; + int funcpcfound = 0; + int funcnamefound = 0; + + proc_name_buf[0] = 0; /* always set to something */ + if(pcMap) { + struct Addr_Map_Entry *ame = 0; + ame = addr_map_find(low_pc,pcMap); + if(ame && ame->mp_name) { + /* mp_name is NULL only if we ran out of heap space. */ + safe_strcpy(proc_name_buf, proc_name_buf_len, + ame->mp_name,(long) strlen(ame->mp_name)); + return 1; + } + } + + atres = dwarf_attrlist(die, &atlist, &atcnt, &err); + if (atres == DW_DLV_ERROR) { + print_error(dbg, "dwarf_attrlist", atres, err); + return 0; + } + if (atres == DW_DLV_NO_ENTRY) { + return 0; + } + for (i = 0; i < atcnt; i++) { + Dwarf_Half attr = 0; + int ares = 0; + string temps = 0; + int sres = 0; + int dres = 0; + + if (funcnamefound == 1 && funcpcfound == 1) { + /* stop as soon as both found */ + break; + } + ares = dwarf_whatattr(atlist[i], &attr, &err); + if (ares == DW_DLV_ERROR) { + print_error(dbg, "get_proc_name whatattr error", ares, err); + } else if (ares == DW_DLV_OK) { + switch (attr) { + case DW_AT_specification: + case DW_AT_abstract_origin: + { + if(!funcnamefound) { + /* Only use this if we have not seen DW_AT_name + yet .*/ + int aores = get_abstract_origin_funcname(dbg, + atlist[i], proc_name_buf,proc_name_buf_len); + if(aores == DW_DLV_OK) { + /* FOUND THE NAME */ + funcnamefound = 1; + } + } + } + break; + case DW_AT_name: + /* Even if we saw DW_AT_abstract_origin, go ahead + and take DW_AT_name. */ + sres = dwarf_formstring(atlist[i], &temps, &err); + if (sres == DW_DLV_ERROR) { + print_error(dbg, + "formstring in get_proc_name failed", + sres, err); + /* 50 is safe wrong length since is bigger than the + actual string */ + safe_strcpy(proc_name_buf, proc_name_buf_len, + "ERROR in dwarf_formstring!", 50); + } else if (sres == DW_DLV_NO_ENTRY) { + /* 50 is safe wrong length since is bigger than the + actual string */ + safe_strcpy(proc_name_buf, proc_name_buf_len, + "NO ENTRY on dwarf_formstring?!", 50); + } else { + long len = (long) strlen(temps); + + safe_strcpy(proc_name_buf, proc_name_buf_len, temps, + len); + } + funcnamefound = 1; /* FOUND THE NAME */ + break; + case DW_AT_low_pc: + dres = dwarf_formaddr(atlist[i], &low_pc_die, &err); + if (dres == DW_DLV_ERROR) { + print_error(dbg, "formaddr in get_proc_name failed", + dres, err); + low_pc_die = ~low_pc; + /* ensure no match */ + } + funcpcfound = 1; + + break; + default: + break; + } + } + } + for (i = 0; i < atcnt; i++) { + dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR); + } + dwarf_dealloc(dbg, atlist, DW_DLA_LIST); + if(funcnamefound && funcpcfound && pcMap ) { + /* Insert every name to map, not just the one + we are looking for. + This version does extra work in that + early symbols in a CU will be inserted + multiple times (the extra times have no + effect), the dwarfdump2 + version of this does less work. */ + addr_map_insert(low_pc_die,proc_name_buf,pcMap); + } + if (funcnamefound == 0 || funcpcfound == 0 || low_pc != low_pc_die) { + funcres = 0; + } + return (funcres); +} + +/* Modified Depth First Search looking for the procedure: + a) only looks for children of subprogram. + b) With subprogram looks at current die *before* looking + for a child. + + Needed since some languages, including SGI MP Fortran, + have nested functions. + Return 0 on failure, 1 on success. +*/ +static int +load_nested_proc_name(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr low_pc, + char *ret_name_buf, int ret_name_buf_len, + void **pcMap) +{ + char name_buf[BUFSIZ]; + Dwarf_Die curdie = die; + int die_locally_gotten = 0; + Dwarf_Die prev_child = 0; + Dwarf_Die newchild = 0; + Dwarf_Die newsibling = 0; + Dwarf_Half tag; + Dwarf_Error err = 0; + int chres = DW_DLV_OK; + + ret_name_buf[0] = 0; + name_buf[0] = 0; + while (chres == DW_DLV_OK) { + int tres; + + tres = dwarf_tag(curdie, &tag, &err); + newchild = 0; + err = 0; + if (tres == DW_DLV_OK) { + int lchres; + + if (tag == DW_TAG_subprogram) { + int proc_name_v = get_proc_name(dbg, curdie, low_pc, + name_buf, BUFSIZ,pcMap); + if (proc_name_v) { + safe_strcpy(ret_name_buf, ret_name_buf_len, + name_buf, (long) strlen(name_buf)); + if (die_locally_gotten) { + /* If we got this die from the parent, we do + not want to dealloc here! */ + dwarf_dealloc(dbg, curdie, DW_DLA_DIE); + } + return 1; + } + /* Check children of subprograms recursively should + this really be check children of anything, + or just children of subprograms? */ + + lchres = dwarf_child(curdie, &newchild, &err); + if (lchres == DW_DLV_OK) { + /* look for inner subprogram */ + int newprog = + load_nested_proc_name(dbg, newchild, low_pc, + name_buf, BUFSIZ, + pcMap); + + dwarf_dealloc(dbg, newchild, DW_DLA_DIE); + if (newprog) { + /* Found it. We could just take this name or + we could concatenate names together For now, + just take name */ + if (die_locally_gotten) { + /* If we got this die from the parent, we + do not want to dealloc here! */ + dwarf_dealloc(dbg, curdie, DW_DLA_DIE); + } + safe_strcpy(ret_name_buf, ret_name_buf_len, + name_buf, (long) strlen(name_buf)); + return 1; + } + } else if (lchres == DW_DLV_NO_ENTRY) { + /* nothing to do */ + } else { + print_error(dbg, + "load_nested_proc_name dwarf_child() failed ", + chres, err); + if (die_locally_gotten) { + /* If we got this die from the parent, we do + not want to dealloc here! */ + dwarf_dealloc(dbg, curdie, DW_DLA_DIE); + } + return 0; + } + } /* end if TAG_subprogram */ + } else { + print_error(dbg, "no tag on child read ", tres, err); + if (die_locally_gotten) { + /* If we got this die from the parent, we do not want + to dealloc here! */ + dwarf_dealloc(dbg, curdie, DW_DLA_DIE); + } + return 0; + } + /* try next sibling */ + prev_child = curdie; + chres = dwarf_siblingof(dbg, curdie, &newsibling, &err); + if (chres == DW_DLV_ERROR) { + print_error(dbg, "dwarf_cu_header On Child read ", chres, + err); + if (die_locally_gotten) { + /* If we got this die from the parent, we do not want + to dealloc here! */ + dwarf_dealloc(dbg, curdie, DW_DLA_DIE); + } + return 0; + } else if (chres == DW_DLV_NO_ENTRY) { + if (die_locally_gotten) { + /* If we got this die from the parent, we do not want + to dealloc here! */ + dwarf_dealloc(dbg, prev_child, DW_DLA_DIE); + } + return 0;/* proc name not at this level */ + } else { + /* DW_DLV_OK */ + curdie = newsibling; + if (die_locally_gotten) { + /* If we got this die from the parent, we do not want + to dealloc here! */ + dwarf_dealloc(dbg, prev_child, DW_DLA_DIE); + } + prev_child = 0; + die_locally_gotten = 1; + } + + } + if (die_locally_gotten) { + /* If we got this die from the parent, we do not want to + dealloc here! */ + dwarf_dealloc(dbg, curdie, DW_DLA_DIE); + } + return 0; +} + +/* For SGI MP Fortran and other languages, functions + nest! As a result, we must dig thru all functions, + not just the top level. + This remembers the CU die and restarts each search at the start + of the current cu. +*/ +static string +get_fde_proc_name(Dwarf_Debug dbg, Dwarf_Addr low_pc, + void **pcMap, + int *all_cus_seen) +{ + static char proc_name[BUFSIZ]; + Dwarf_Unsigned cu_header_length = 0; + Dwarf_Unsigned abbrev_offset = 0; + Dwarf_Half version_stamp = 0; + Dwarf_Half address_size = 0; + Dwarf_Unsigned next_cu_offset = 0; + int cures = DW_DLV_OK; + int dres = DW_DLV_OK; + int chres = DW_DLV_OK; + int looping = 0; + + proc_name[0] = 0; + { + struct Addr_Map_Entry *ame = 0; + ame = addr_map_find(low_pc,pcMap); + if(ame && ame->mp_name) { + /* mp_name is only NULL here if we just ran out of heap memory! */ + safe_strcpy(proc_name, sizeof(proc_name), + ame->mp_name,(long) strlen(ame->mp_name)); + return proc_name; + } + if (*all_cus_seen) { + return ""; + } + } + if (current_cu_die_for_print_frames == NULL) { + /* Call depends on dbg->cu_context to know what to do. */ + cures = dwarf_next_cu_header(dbg, &cu_header_length, + &version_stamp, &abbrev_offset, + &address_size, &next_cu_offset, + &err); + if (cures == DW_DLV_ERROR) { + return NULL; + } else if (cures == DW_DLV_NO_ENTRY) { + /* loop thru the list again */ + current_cu_die_for_print_frames = 0; + ++looping; + } else { /* DW_DLV_OK */ + dres = dwarf_siblingof(dbg, NULL, + ¤t_cu_die_for_print_frames, + &err); + if (dres == DW_DLV_ERROR) { + return NULL; + } + } + } + if (dres == DW_DLV_OK) { + Dwarf_Die child = 0; + + if (current_cu_die_for_print_frames == 0) { + /* no information. Possibly a stripped file */ + return NULL; + } + chres = + dwarf_child(current_cu_die_for_print_frames, &child, &err); + if (chres == DW_DLV_ERROR) { + print_error(dbg, "dwarf_cu_header on child read ", chres, + err); + } else if (chres == DW_DLV_NO_ENTRY) { + } else { /* DW_DLV_OK */ + int gotname = + load_nested_proc_name(dbg, child, low_pc, proc_name, + BUFSIZ,pcMap); + + dwarf_dealloc(dbg, child, DW_DLA_DIE); + if (gotname) { + return (proc_name); + } + child = 0; + } + } + for (;;) { + Dwarf_Die ldie = 0; + + cures = dwarf_next_cu_header(dbg, &cu_header_length, + &version_stamp, &abbrev_offset, + &address_size, &next_cu_offset, + &err); + if (cures != DW_DLV_OK) { + *all_cus_seen = 1; + break; + } + + dres = dwarf_siblingof(dbg, NULL, &ldie, &err); + if (current_cu_die_for_print_frames) { + dwarf_dealloc(dbg, current_cu_die_for_print_frames, + DW_DLA_DIE); + } + current_cu_die_for_print_frames = 0; + if (dres == DW_DLV_ERROR) { + print_error(dbg, + "dwarf_cu_header Child Read finding proc name for .debug_frame", + chres, err); + continue; + } else if (dres == DW_DLV_NO_ENTRY) { + ++looping; + if (looping > 1) { + print_error(dbg, "looping on cu headers!", dres, err); + return NULL; + } + continue; + } + /* DW_DLV_OK */ + current_cu_die_for_print_frames = ldie; + { + int chres = 0; + Dwarf_Die child = 0; + + chres = + dwarf_child(current_cu_die_for_print_frames, &child, + &err); + if (chres == DW_DLV_ERROR) { + print_error(dbg, "dwarf Child Read ", chres, err); + } else if (chres == DW_DLV_NO_ENTRY) { + + ;/* do nothing, loop on cu */ + } else { + /* DW_DLV_OK) */ + + int gotname = + load_nested_proc_name(dbg, child, low_pc, proc_name, + BUFSIZ,pcMap); + + dwarf_dealloc(dbg, child, DW_DLA_DIE); + if (gotname) { + return (proc_name); + } + } + } + } + return (NULL); +} + +/* Gather the fde print logic here so the control logic + determining what FDE to print is clearer. */ +static int +print_one_fde(Dwarf_Debug dbg, Dwarf_Fde fde, + Dwarf_Unsigned fde_index, + Dwarf_Cie * cie_data, + Dwarf_Signed cie_element_count, + Dwarf_Half address_size, int is_eh, + struct dwconf_s *config_data, + void **pcMap, + void **lowpcSet, + int * all_cus_seen) +{ + Dwarf_Addr j = 0; + Dwarf_Addr low_pc = 0; + Dwarf_Unsigned func_length = 0; + Dwarf_Ptr fde_bytes = NULL; + Dwarf_Unsigned fde_bytes_length = 0; + Dwarf_Off cie_offset = 0; + Dwarf_Signed cie_index = 0; + Dwarf_Off fde_offset = 0; + Dwarf_Signed eh_table_offset = 0; + int fres = 0; + int offres = 0; + string temps = 0; + Dwarf_Error err = 0; + int printed_intro_addr = 0; + + fres = dwarf_get_fde_range(fde, + &low_pc, &func_length, + &fde_bytes, + &fde_bytes_length, + &cie_offset, &cie_index, + &fde_offset, &err); + if (fres == DW_DLV_ERROR) { + print_error(dbg, "dwarf_get_fde_range", fres, err); + } + if (fres == DW_DLV_NO_ENTRY) { + return DW_DLV_NO_ENTRY; + } + if (cu_name_flag && + fde_offset_for_cu_low != DW_DLV_BADOFFSET && + (fde_offset < fde_offset_for_cu_low || + fde_offset > fde_offset_for_cu_high)) { + return DW_DLV_NO_ENTRY; + } + /* eh_table_offset is IRIX ONLY. */ + fres = dwarf_get_fde_exception_info(fde, &eh_table_offset, &err); + if (fres == DW_DLV_ERROR) { + print_error(dbg, "dwarf_get_fde_exception_info", fres, err); + } + if(suppress_nested_name_search) { + temps = 0; + } else { +#ifdef HAVE_TSEARCH + struct Addr_Map_Entry *mp = 0; + temps = get_fde_proc_name(dbg, low_pc,pcMap,all_cus_seen); + mp = addr_map_find(low_pc,lowpcSet); + if (check_frames || check_frames_extended) { + DWARF_CHECK_COUNT(fde_duplication,1); + } + if (mp) { + if (check_frames || check_frames_extended) { + char msg[400]; + if(temps && (strlen(temps) > 0)) { + snprintf(msg,sizeof(msg),"An fde low pc of 0x%" + DW_PR_DUx + " is not the first fde with that pc. " + "The first is named \"%s\"", + (Dwarf_Unsigned)low_pc, + temps); + } else { + snprintf(msg,sizeof(msg),"An fde low pc of 0x%" + DW_PR_DUx + " is not the first fde with that pc. " + "The first is not named.", + (Dwarf_Unsigned)low_pc); + + } + DWARF_CHECK_ERROR(fde_duplication,msg); + } + } else { + addr_map_insert(low_pc,0,lowpcSet); + } +#endif + } + + /* Do not print if in check mode */ + if (!check_frames_extended) { + printf("<%5" DW_PR_DSd "><0x%" DW_PR_XZEROS DW_PR_DUx + ":0x%" DW_PR_XZEROS DW_PR_DUx + "><%s><fde offset 0x%" DW_PR_XZEROS DW_PR_DUx + " length: 0x%" DW_PR_XZEROS DW_PR_DUx ">", + cie_index, (Dwarf_Unsigned)low_pc, + (Dwarf_Unsigned)(low_pc + func_length), + temps ? temps : "", (Dwarf_Unsigned)fde_offset, fde_bytes_length); + } + + + + if (!is_eh) { + /* IRIX uses eh_table_offset. */ + /* Do not print if in check mode */ + if (!check_frames_extended) { + if (eh_table_offset == DW_DLX_NO_EH_OFFSET) { + printf("<eh offset %s>\n", "none"); + } else if (eh_table_offset == DW_DLX_EH_OFFSET_UNAVAILABLE) { + printf("<eh offset %s>\n", "unknown"); + } else { + printf("<eh offset 0x%" DW_PR_XZEROS DW_PR_DUx + ">\n", eh_table_offset); + } + } + } else { + int ares = 0; + Dwarf_Small *data = 0; + Dwarf_Unsigned len = 0; + + ares = dwarf_get_fde_augmentation_data(fde, &data, &len, &err); + if (ares == DW_DLV_NO_ENTRY) { + /* do nothing. */ + } else if (ares == DW_DLV_OK) { + /* Do not print if in check mode */ + if (!check_frames_extended) { + int k2 = 0; + + printf("<eh aug data len 0x%" DW_PR_DUx , len); + for (k2 = 0; k2 < len; ++k2) { + if (k2 == 0) { + printf(" bytes 0x"); + } + printf("%02x ", (unsigned char) data[k2]); + } + printf(">"); + } + } /* else DW_DLV_ERROR, do nothing */ + + /* Do not print if in check mode */ + if (!check_frames_extended) { + printf("\n"); + + } + } + + for (j = low_pc; j < low_pc + func_length; j++) { + Dwarf_Half k = 0; + + if (config_data->cf_interface_number == 3) { + Dwarf_Signed reg = 0; + Dwarf_Signed offset_relevant = 0; + Dwarf_Small value_type = 0; + Dwarf_Signed offset_or_block_len = 0; + Dwarf_Signed offset = 0; + Dwarf_Ptr block_ptr = 0; + Dwarf_Addr row_pc = 0; + + int fires = dwarf_get_fde_info_for_cfa_reg3(fde, + j, + &value_type, + &offset_relevant, + ®, + &offset_or_block_len, + &block_ptr, + &row_pc, + &err); + offset = offset_or_block_len; + if (fires == DW_DLV_ERROR) { + print_error(dbg, + "dwarf_get_fde_info_for_reg", fires, err); + } + if (fires == DW_DLV_NO_ENTRY) { + continue; + } + if (row_pc != j) { + /* duplicate row */ + continue; + } + + /* Do not print if in check mode */ + if (!printed_intro_addr && !check_frames_extended) { + printf(" 0x%" DW_PR_XZEROS DW_PR_DUx + ": ", (Dwarf_Unsigned)j); + printed_intro_addr = 1; + } + print_one_frame_reg_col(dbg, config_data->cf_cfa_reg, + value_type, + reg, + address_size, + config_data, + offset_relevant, offset, block_ptr); + } + for (k = 0; k < config_data->cf_table_entry_count; k++) { + Dwarf_Signed reg = 0; + Dwarf_Signed offset_relevant = 0; + int fires = 0; + Dwarf_Small value_type = 0; + Dwarf_Ptr block_ptr = 0; + Dwarf_Signed offset_or_block_len = 0; + Dwarf_Signed offset = 0; + Dwarf_Addr row_pc = 0; + + if (config_data->cf_interface_number == 3) { + fires = dwarf_get_fde_info_for_reg3(fde, + k, + j, + &value_type, + &offset_relevant, + ®, + &offset_or_block_len, + &block_ptr, + &row_pc, &err); + offset = offset_or_block_len; + } else { + /* This interface is deprecated. Is the old + MIPS/DWARF2 interface. */ + /* ASSERT: config_data->cf_interface_number == 2 */ + value_type = DW_EXPR_OFFSET; + fires = dwarf_get_fde_info_for_reg(fde, + k, + j, + &offset_relevant, + ®, + &offset, &row_pc, + &err); + } + if (fires == DW_DLV_ERROR) { + printf("\n"); + print_error(dbg, + "dwarf_get_fde_info_for_reg", fires, err); + } + if (fires == DW_DLV_NO_ENTRY) { + continue; + } + if (row_pc != j) { + /* duplicate row */ + break; + } + + /* Do not print if in check mode */ + if (!printed_intro_addr && !check_frames_extended) { + printf(" 0x%" DW_PR_XZEROS DW_PR_DUx ": ", + (Dwarf_Unsigned)j); + printed_intro_addr = 1; + } + print_one_frame_reg_col(dbg,k, + value_type, + reg, + address_size, + config_data, + offset_relevant, offset, block_ptr); + } + if (printed_intro_addr) { + printf("\n"); + printed_intro_addr = 0; + } + } + if (verbose > 1) { + Dwarf_Off fde_off = 0; + Dwarf_Off cie_off = 0; + + /* Get the fde instructions and print them in raw form, just + like cie instructions */ + Dwarf_Ptr instrs = 0; + Dwarf_Unsigned ilen = 0; + int res = 0; + + res = dwarf_get_fde_instr_bytes(fde, &instrs, &ilen, &err); + offres = + dwarf_fde_section_offset(dbg, fde, &fde_off, &cie_off, + &err); + if (offres == DW_DLV_OK) { + /* Do not print if in check mode */ + if (!check_frames_extended) { + printf(" fde section offset %" DW_PR_DUu + " 0x%" DW_PR_XZEROS DW_PR_DUx + " cie offset for fde: %" DW_PR_DUu + " 0x%" DW_PR_XZEROS DW_PR_DUx "\n", + (Dwarf_Unsigned) fde_off, + (Dwarf_Unsigned) fde_off, + (Dwarf_Unsigned) cie_off, + (Dwarf_Unsigned) cie_off); + } + } + + + if (res == DW_DLV_OK) { + int cires = 0; + Dwarf_Unsigned cie_length = 0; + Dwarf_Small version = 0; + string augmenter = 0; + Dwarf_Unsigned code_alignment_factor = 0; + Dwarf_Signed data_alignment_factor = 0; + Dwarf_Half return_address_register_rule = 0; + Dwarf_Ptr initial_instructions = 0; + Dwarf_Unsigned initial_instructions_length = 0; + + if (cie_index >= cie_element_count) { + printf("Bad cie index %" DW_PR_DSd + " with fde index %" DW_PR_DUu "! " + "(table entry max %" DW_PR_DSd ")\n", + cie_index, fde_index, + cie_element_count); + exit(1); + } + cires = dwarf_get_cie_info(cie_data[cie_index], + &cie_length, + &version, + &augmenter, + &code_alignment_factor, + &data_alignment_factor, + &return_address_register_rule, + &initial_instructions, + &initial_instructions_length, + &err); + if (cires == DW_DLV_ERROR) { + printf + ("Bad cie index %" DW_PR_DSd + " with fde index %" DW_PR_DUu "!\n", + cie_index, fde_index); + print_error(dbg, "dwarf_get_cie_info", cires, err); + } + if (cires == DW_DLV_NO_ENTRY) { + ; /* ? */ + } else { + /* Do not print if in check mode */ + if (!check_frames_extended) { + print_frame_inst_bytes(dbg, instrs, + (Dwarf_Signed) ilen, + data_alignment_factor, + (int) code_alignment_factor, + address_size, config_data); + } + } + } else if (res == DW_DLV_NO_ENTRY) { + printf("Impossible: no instr bytes for fde index %" + DW_PR_DUu "?\n", + fde_index); + } else { + /* DW_DLV_ERROR */ + printf("Error: on gettinginstr bytes for fde index %" + DW_PR_DUu "?\n", + fde_index); + print_error(dbg, "dwarf_get_fde_instr_bytes", res, err); + } + + } + return DW_DLV_OK; +} + + +/* Print a cie. Gather the print logic here so the + control logic deciding what to print + is clearer. +*/ +int +print_one_cie(Dwarf_Debug dbg, Dwarf_Cie cie, + Dwarf_Unsigned cie_index, Dwarf_Half address_size, + struct dwconf_s *config_data) +{ + + int cires = 0; + Dwarf_Unsigned cie_length = 0; + Dwarf_Small version = 0; + string augmenter = ""; + Dwarf_Unsigned code_alignment_factor = 0; + Dwarf_Signed data_alignment_factor = 0; + Dwarf_Half return_address_register_rule = 0; + Dwarf_Ptr initial_instructions = 0; + Dwarf_Unsigned initial_instructions_length = 0; + Dwarf_Off cie_off = 0; + Dwarf_Error err = 0; + + cires = dwarf_get_cie_info(cie, + &cie_length, + &version, + &augmenter, + &code_alignment_factor, + &data_alignment_factor, + &return_address_register_rule, + &initial_instructions, + &initial_instructions_length, &err); + if (cires == DW_DLV_ERROR) { + print_error(dbg, "dwarf_get_cie_info", cires, err); + } + if (cires == DW_DLV_NO_ENTRY) { + printf("Impossible DW_DLV_NO_ENTRY on cie %" DW_PR_DUu "\n", + cie_index); + return DW_DLV_NO_ENTRY; + } + { + /* Do not print if in check mode */ + if (!check_frames_extended) { + printf("<%5" DW_PR_DUu ">\tversion\t\t\t\t%d\n", + cie_index, version); + cires = dwarf_cie_section_offset(dbg, cie, &cie_off, &err); + if (cires == DW_DLV_OK) { + printf("\tcie section offset\t\t%" DW_PR_DUu + " 0x%" DW_PR_XZEROS DW_PR_DUx "\n", + (Dwarf_Unsigned) cie_off, + (Dwarf_Unsigned) cie_off); + } + printf("\taugmentation\t\t\t%s\n", augmenter); + printf("\tcode_alignment_factor\t\t%" DW_PR_DUu "\n", + code_alignment_factor); + printf("\tdata_alignment_factor\t\t%" DW_PR_DSd "\n", + data_alignment_factor); + printf("\treturn_address_register\t\t%d\n", + return_address_register_rule); + } + + { + int ares = 0; + Dwarf_Small *data = 0; + Dwarf_Unsigned len = 0; + + ares = + dwarf_get_cie_augmentation_data(cie, &data, &len, &err); + if (ares == DW_DLV_NO_ENTRY) { + /* do nothing. */ + } else if (ares == DW_DLV_OK && len > 0) { + /* Do not print if in check mode */ + if (!check_frames_extended) { + int k2 = 0; + + printf(" eh aug data len 0x%" DW_PR_DUx , len); + for (k2 = 0; data && k2 < len; ++k2) { + if (k2 == 0) { + printf(" bytes 0x"); + } + printf("%02x ", (unsigned char) data[k2]); + } + printf("\n"); + } + } /* else DW_DLV_ERROR or no data, do nothing */ + } + + /* Do not print if in check mode */ + if (!check_frames_extended) { + printf("\tbytes of initial instructions\t%" DW_PR_DUu "\n", + initial_instructions_length); + printf("\tcie length\t\t\t%" DW_PR_DUu "\n", cie_length); + /* For better layout */ + printf("\tinitial instructions\n"); + print_frame_inst_bytes(dbg, initial_instructions, + (Dwarf_Signed) initial_instructions_length, + data_alignment_factor, + (int) code_alignment_factor, + address_size, config_data); + } + } + return DW_DLV_OK; +} + +void +get_string_from_locs(Dwarf_Debug dbg, + Dwarf_Ptr bytes_in, + Dwarf_Unsigned block_len, + Dwarf_Half addr_size, + struct esb_s *out_string) +{ + + Dwarf_Locdesc *locdescarray = 0; + Dwarf_Signed listlen = 0; + Dwarf_Error err2 =0; + int skip_locdesc_header=1; + int res = 0; + int res2 = dwarf_loclist_from_expr_a(dbg, + bytes_in,block_len, + addr_size, + &locdescarray, + &listlen,&err2); + if (res2 == DW_DLV_ERROR) { + print_error(dbg, "dwarf_get_loclist_from_expr_a", + res2, err2); + } + if(res2==DW_DLV_NO_ENTRY) { + return; + } + /* lcnt is always 1 */ + + /* Use locdescarray here.*/ + res = dwarfdump_print_one_locdesc(dbg, + locdescarray, + skip_locdesc_header, + out_string); + if(res != DW_DLV_OK) { + printf("Bad status from _dwarf_print_one_locdesc %d\n",res); + exit(1); + } + + dwarf_dealloc(dbg, locdescarray->ld_s, DW_DLA_LOC_BLOCK); + dwarf_dealloc(dbg, locdescarray, DW_DLA_LOCDESC); + return ; +} + +/* Print the frame instructions in detail for a glob of instructions. +*/ + +/*ARGSUSED*/ void +print_frame_inst_bytes(Dwarf_Debug dbg, + Dwarf_Ptr cie_init_inst, Dwarf_Signed len, + Dwarf_Signed data_alignment_factor, + int code_alignment_factor, Dwarf_Half addr_size, + struct dwconf_s *config_data) +{ + unsigned char *instp = (unsigned char *) cie_init_inst; + Dwarf_Unsigned uval = 0; + Dwarf_Unsigned uval2 = 0; + unsigned int uleblen = 0; + unsigned int off = 0; + unsigned int loff = 0; + unsigned short u16 = 0; + unsigned int u32 = 0; + unsigned long long u64; + + for (; len > 0;) { + unsigned char ibyte = *instp; + int top = ibyte & 0xc0; + int bottom = ibyte & 0x3f; + int delta = 0; + int reg = 0; + + switch (top) { + case DW_CFA_advance_loc: + delta = ibyte & 0x3f; + printf("\t%2u DW_CFA_advance_loc %d", off, + (int) (delta * code_alignment_factor)); + if (verbose) { + printf(" (%d * %d)", (int) delta, + (int) code_alignment_factor); + } + printf("\n"); + break; + case DW_CFA_offset: + loff = off; + reg = ibyte & 0x3f; + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_offset ", loff); + printreg((Dwarf_Signed) reg, config_data); + printf(" %" DW_PR_DSd , (Dwarf_Signed) + (((Dwarf_Signed) uval) * data_alignment_factor)); + if (verbose) { + printf(" (%" DW_PR_DUu " * %" DW_PR_DSd ")", uval, + data_alignment_factor); + } + printf("\n"); + break; + + case DW_CFA_restore: + reg = ibyte & 0x3f; + printf("\t%2u DW_CFA_restore ", off); + printreg((Dwarf_Signed) reg, config_data); + printf("\n"); + break; + + default: + loff = off; + switch (bottom) { + case DW_CFA_set_loc: + /* operand is address, so need address size */ + /* which will be 4 or 8. */ + switch (addr_size) { + case 4: + { + __uint32_t v32 = 0; + memcpy(&v32, instp + 1, addr_size); + uval = v32; + } + break; + case 8: + { + __uint64_t v64 = 0; + memcpy(&v64, instp + 1, addr_size); + uval = v64; + } + break; + default: + printf + ("Error: Unexpected address size %d in DW_CFA_set_loc!\n", + addr_size); + uval = 0; + } + + instp += addr_size; + len -= (Dwarf_Signed) addr_size; + off += addr_size; + printf("\t%2u DW_CFA_set_loc %" DW_PR_DUu "\n", + loff, uval); + break; + case DW_CFA_advance_loc1: + delta = (unsigned char) *(instp + 1); + uval2 = delta; + instp += 1; + len -= 1; + off += 1; + printf("\t%2u DW_CFA_advance_loc1 %" DW_PR_DUu "\n", + loff, uval2); + break; + case DW_CFA_advance_loc2: + memcpy(&u16, instp + 1, 2); + uval2 = u16; + instp += 2; + len -= 2; + off += 2; + printf("\t%2u DW_CFA_advance_loc2 %" DW_PR_DUu "\n", + loff, uval2); + break; + case DW_CFA_advance_loc4: + memcpy(&u32, instp + 1, 4); + uval2 = u32; + instp += 4; + len -= 4; + off += 4; + printf("\t%2u DW_CFA_advance_loc4 %" DW_PR_DUu "\n", + loff, uval2); + break; + case DW_CFA_MIPS_advance_loc8: + memcpy(&u64, instp + 1, 8); + uval2 = u64; + instp += 8; + len -= 8; + off += 8; + printf("\t%2u DW_CFA_MIPS_advance_loc8 %" DW_PR_DUu "\n", + loff, uval2); + break; + case DW_CFA_offset_extended: + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + uval2 = + local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_offset_extended ", loff); + printreg((Dwarf_Signed) uval, config_data); + printf(" %" DW_PR_DSd , + (Dwarf_Signed) (((Dwarf_Signed) uval2) * + data_alignment_factor)); + if (verbose) { + printf(" (%" DW_PR_DUu " * %d)", uval2, + (int) data_alignment_factor); + } + printf("\n"); + break; + + case DW_CFA_restore_extended: + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_restore_extended ", loff); + printreg((Dwarf_Signed) uval, config_data); + printf("\n"); + break; + case DW_CFA_undefined: + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_undefined ", loff); + printreg((Dwarf_Signed) uval, config_data); + printf("\n"); + break; + case DW_CFA_same_value: + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_same_value ", loff); + printreg((Dwarf_Signed) uval, config_data); + printf("\n"); + break; + case DW_CFA_register: + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + uval2 = + local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_register ", loff); + printreg((Dwarf_Signed) uval, config_data); + printf(" = "); + printreg((Dwarf_Signed) uval2, config_data); + printf("\n"); + break; + case DW_CFA_remember_state: + printf("\t%2u DW_CFA_remember_state\n", loff); + break; + case DW_CFA_restore_state: + printf("\t%2u DW_CFA_restore_state\n", loff); + break; + case DW_CFA_def_cfa: + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + uval2 = + local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_def_cfa ", loff); + printreg((Dwarf_Signed) uval, config_data); + printf(" %" DW_PR_DUu , (unsigned long long) uval2); + printf("\n"); + break; + case DW_CFA_def_cfa_register: + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_def_cfa_register ", loff); + printreg((Dwarf_Signed) uval, config_data); + printf("\n"); + break; + case DW_CFA_def_cfa_offset: + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_def_cfa_offset %" DW_PR_DUu "\n", + loff, uval); + break; + + case DW_CFA_nop: + printf("\t%2u DW_CFA_nop\n", loff); + break; + + case DW_CFA_def_cfa_expression: /* DWARF3 */ + { + Dwarf_Unsigned block_len = + local_dwarf_decode_u_leb128(instp + 1, + &uleblen); + + instp += uleblen; + len -= uleblen; + off += uleblen; + printf + ("\t%2u DW_CFA_def_cfa_expression expr block len %" + DW_PR_DUu "\n", + loff, + block_len); + dump_block("\t\t", (char *) instp+1, + (Dwarf_Signed) block_len); + printf("\n"); + if(verbose) { + struct esb_s exprstring; + esb_constructor(&exprstring); + get_string_from_locs(dbg, + instp+1,block_len,addr_size,&exprstring); + printf("\t\t%s\n",esb_get_string(&exprstring)); + esb_destructor(&exprstring); + } + instp += block_len; + len -= block_len; + off += block_len; + } + break; + case DW_CFA_expression: /* DWARF3 */ + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + { + /* instp is always 1 byte back, so we need +1 + when we use it. See the final increment + of this for loop. */ + Dwarf_Unsigned block_len = + local_dwarf_decode_u_leb128(instp + 1, + &uleblen); + + instp += uleblen; + len -= uleblen; + off += uleblen; + printf + ("\t%2u DW_CFA_expression %" DW_PR_DUu + " expr block len %" DW_PR_DUu "\n", + loff, uval, + block_len); + dump_block("\t\t", (char *) instp+1, + (Dwarf_Signed) block_len); + printf("\n"); + if(verbose) { + struct esb_s exprstring; + esb_constructor(&exprstring); + get_string_from_locs(dbg, + instp+1,block_len,addr_size,&exprstring); + printf("\t\t%s\n",esb_get_string(&exprstring)); + esb_destructor(&exprstring); + } + instp += block_len; + len -= block_len; + off += block_len; + } + break; + case DW_CFA_offset_extended_sf: /* DWARF3 */ + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + { + /* instp is always 1 byte back, so we need +1 + when we use it. See the final increment + of this for loop. */ + Dwarf_Signed sval2 = + local_dwarf_decode_s_leb128(instp + 1, + &uleblen); + + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_offset_extended_sf ", loff); + printreg((Dwarf_Signed) uval, config_data); + printf(" %" DW_PR_DSd , (Dwarf_Signed) + ((sval2) * data_alignment_factor)); + if (verbose) { + printf(" (%" DW_PR_DSd " * %d)", sval2, + (int) data_alignment_factor); + } + } + printf("\n"); + break; + case DW_CFA_def_cfa_sf: /* DWARF3 */ + /* instp is always 1 byte back, so we need +1 + when we use it. See the final increment + of this for loop. */ + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + { + Dwarf_Signed sval2 = + local_dwarf_decode_s_leb128(instp + 1, + &uleblen); + + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_def_cfa_sf ", loff); + printreg((Dwarf_Signed) uval, config_data); + printf(" %" DW_PR_DSd , (long long) sval2); + printf(" (*data alignment factor=>%" DW_PR_DSd ")", + (Dwarf_Signed)(sval2*data_alignment_factor)); + } + printf("\n"); + break; + case DW_CFA_def_cfa_offset_sf: /* DWARF3 */ + { + /* instp is always 1 byte back, so we need +1 + when we use it. See the final increment + of this for loop. */ + Dwarf_Signed sval = + local_dwarf_decode_s_leb128(instp + 1, + &uleblen); + + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_def_cfa_offset_sf %" + DW_PR_DSd " (*data alignment factor=> %" + DW_PR_DSd ")\n", + loff, sval, + (Dwarf_Signed)(data_alignment_factor*sval)); + + } + break; + case DW_CFA_val_offset: /* DWARF3 */ + /* instp is always 1 byte back, so we need +1 + when we use it. See the final increment + of this for loop. */ + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + { + Dwarf_Signed sval2 = + local_dwarf_decode_s_leb128(instp + 1, + &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_val_offset ", loff); + printreg((Dwarf_Signed)uval, config_data); + printf(" %" DW_PR_DSd , + (Dwarf_Signed) (sval2 * + data_alignment_factor)); + if (verbose) { + printf(" (%" DW_PR_DSd " * %d)", + (Dwarf_Signed) sval2, + (int) data_alignment_factor); + } + } + printf("\n"); + + break; + case DW_CFA_val_offset_sf: /* DWARF3 */ + /* instp is always 1 byte back, so we need +1 + when we use it. See the final increment + of this for loop. */ + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + { + Dwarf_Signed sval2 = + local_dwarf_decode_s_leb128(instp + 1, + &uleblen); + + instp += uleblen; + len -= uleblen; + off += uleblen; + printf("\t%2u DW_CFA_val_offset_sf ", loff); + printreg((Dwarf_Signed) uval, config_data); + printf(" %" DW_PR_DSd , (signed long long) + ((sval2) * data_alignment_factor)); + if (verbose) { + printf(" (%" DW_PR_DSd " * %d)", sval2, + (int) data_alignment_factor); + } + } + printf("\n"); + + break; + case DW_CFA_val_expression: /* DWARF3 */ + /* instp is always 1 byte back, so we need +1 + when we use it. See the final increment + of this for loop. */ + uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen); + instp += uleblen; + len -= uleblen; + off += uleblen; + { + Dwarf_Unsigned block_len = + local_dwarf_decode_u_leb128(instp + 1, + &uleblen); + + instp += uleblen; + len -= uleblen; + off += uleblen; + printf + ("\t%2u DW_CFA_val_expression %" DW_PR_DUu + " expr block len %" DW_PR_DUu "\n", + loff, uval, + block_len); + dump_block("\t\t", (char *) instp+1, + (Dwarf_Signed) block_len); + printf("\n"); + if(verbose) { + struct esb_s exprstring; + esb_constructor(&exprstring); + get_string_from_locs(dbg, + instp+1,block_len,addr_size,&exprstring); + printf("\t\t%s\n",esb_get_string(&exprstring)); + esb_destructor(&exprstring); + } + instp += block_len; + len -= block_len; + off += block_len; + } + + + break; + + +#ifdef DW_CFA_GNU_window_save + case DW_CFA_GNU_window_save:{ + /* no information: this just tells unwinder to + restore the window registers from the previous + frame's window save area */ + printf("\t%2u DW_CFA_GNU_window_save \n", loff); + } + break; +#endif +#ifdef DW_CFA_GNU_negative_offset_extended + case DW_CFA_GNU_negative_offset_extended:{ + printf("\t%2u DW_CFA_GNU_negative_offset_extended \n", + loff); + } + break; +#endif +#ifdef DW_CFA_GNU_args_size + /* single uleb128 is the current arg area size in + bytes. no register exists yet to save this in */ + case DW_CFA_GNU_args_size:{ + Dwarf_Unsigned lreg = 0; + + /* instp is always 1 byte back, so we need +1 + when we use it. See the final increment + of this for loop. */ + lreg = local_dwarf_decode_u_leb128(instp + 1, + &uleblen); + printf("\t%2u DW_CFA_GNU_args_size arg size: %" + DW_PR_DUu "\n", + loff, lreg); + instp += uleblen; + len -= uleblen; + off += uleblen; + } + break; +#endif + + default: + printf(" %u Unexpected op 0x%x: \n", + loff, (unsigned int) bottom); + len = 0; + break; + } + } + instp++; + len--; + off++; + } +} + +/* Print our register names for the cases we have a name. + Delegate to the configure code to actually do the print. +*/ +void +printreg(Dwarf_Signed reg, struct dwconf_s *config_data) +{ + print_reg_from_config_data(reg, config_data); +} + +/* Actually does the printing of a rule in the table. + This may print something or may print nothing! */ +static void +print_one_frame_reg_col(Dwarf_Debug dbg, + Dwarf_Unsigned rule_id, + Dwarf_Small value_type, + Dwarf_Unsigned reg_used, + Dwarf_Half addr_size, + struct dwconf_s *config_data, + Dwarf_Signed offset_relevant, + Dwarf_Signed offset, + Dwarf_Ptr block_ptr) +{ + char *type_title = ""; + int print_type_title = 1; + + if (check_frames_extended) { + return; + } + + if (config_data->cf_interface_number == 2) + print_type_title = 0; + + switch (value_type) { + case DW_EXPR_OFFSET: + type_title = "off"; + goto preg2; + case DW_EXPR_VAL_OFFSET: + type_title = "valoff"; + + preg2: + if (reg_used == config_data->cf_initial_rule_value) { + break; + } + if (print_type_title) + printf("<%s ", type_title); + printreg((Dwarf_Signed) rule_id, config_data); + printf("="); + if (offset_relevant == 0) { + printreg((Dwarf_Signed) reg_used, config_data); + printf(" "); + } else { + printf("%02" DW_PR_DSd , offset); + printf("("); + printreg((Dwarf_Signed) reg_used, config_data); + printf(") "); + } + if (print_type_title) + printf("%s", "> "); + break; + case DW_EXPR_EXPRESSION: + type_title = "expr"; + goto pexp2; + case DW_EXPR_VAL_EXPRESSION: + type_title = "valexpr"; + + pexp2: + if (print_type_title) + printf("<%s ", type_title); + printreg((Dwarf_Signed) rule_id, config_data); + printf("="); + printf("expr-block-len=%" DW_PR_DSd , offset); + if (print_type_title) + printf("%s", "> "); + if (verbose) { + char pref[40]; + + strcpy(pref, "<"); + strcat(pref, type_title); + strcat(pref, "bytes:"); + dump_block(pref, block_ptr, offset); + printf("%s", "> "); + if(verbose) { + struct esb_s exprstring; + esb_constructor(&exprstring); + get_string_from_locs(dbg, + block_ptr,offset,addr_size,&exprstring); + printf("<expr:%s>",esb_get_string(&exprstring)); + esb_destructor(&exprstring); + } + } + break; + default: + printf("Internal error in libdwarf, value type %d\n", + value_type); + exit(1); + } + return; +} + + +/* get all the data in .debug_frame (or .eh_frame). + The '3' versions mean print using the dwarf3 new interfaces. + The non-3 mean use the old interfaces. + All combinations of requests are possible. */ +extern void +print_frames(Dwarf_Debug dbg, int print_debug_frame, int print_eh_frame, + struct dwconf_s *config_data) +{ + Dwarf_Signed i; + int fres = 0; + Dwarf_Half address_size = 0; + int framed = 0; + void * map_lowpc_to_name = 0; + + current_section_id = DEBUG_FRAME; + + /* The address size here will not be right for all frames. + Only in DWARF4 is there a real address size known + in the frame data itself. If any DIE + is known then a real address size can be gotten from + dwarf_get_die_address_size(). */ + fres = dwarf_get_address_size(dbg, &address_size, &err); + if (fres != DW_DLV_OK) { + print_error(dbg, "dwarf_get_address_size", fres, err); + } + for (framed = 0; framed < 2; ++framed) { + Dwarf_Cie *cie_data = NULL; + Dwarf_Signed cie_element_count = 0; + Dwarf_Fde *fde_data = NULL; + Dwarf_Signed fde_element_count = 0; + int frame_count = 0; + int cie_count = 0; + int all_cus_seen = 0; + void * lowpcSet = 0; + char *framename = 0; + int silent_if_missing = 0; + int is_eh = 0; + + if (framed == 0) { + if (!print_debug_frame) { + continue; + } + framename = ".debug_frame"; + /* Big question here is how to print all the info? + Can print the logical matrix, but that is huge, + though could skip lines that don't change. + Either that, or print the instruction statement program + that describes the changes. */ + fres = dwarf_get_fde_list(dbg, &cie_data, &cie_element_count, + &fde_data, &fde_element_count, &err); + if(check_harmless) { + print_any_harmless_errors(dbg); + } + } else { + if (!print_eh_frame) { + continue; + } + is_eh = 1; + /* This is gnu g++ exceptions in a .eh_frame section. Which + is just like .debug_frame except that the empty, or + 'special' CIE_id is 0, not -1 (to distinguish fde from + cie). And the augmentation is "eh". As of egcs-1.1.2 + anyway. A non-zero cie_id is in a fde and is the + difference between the fde address and the beginning of + the cie it belongs to. This makes sense as this is + intended to be referenced at run time, and is part of + the running image. For more on augmentation strings, see + libdwarf/dwarf_frame.c. */ + + /* Big question here is how to print all the info? + Can print the logical matrix, but that is huge, + though could skip lines that don't change. + Either that, or print the instruction statement program + that describes the changes. */ + silent_if_missing = 1; + framename = ".eh_frame"; + fres = dwarf_get_fde_list_eh(dbg, &cie_data, + &cie_element_count, &fde_data, + &fde_element_count, &err); + if(check_harmless) { + print_any_harmless_errors(dbg); + } + } + + /* Do not print any frame info if in check mode */ + if (check_frames) { + addr_map_destroy(lowpcSet); + lowpcSet = 0; + continue; + } + + if (fres == DW_DLV_ERROR) { + printf("\n%s\n", framename); + print_error(dbg, "dwarf_get_fde_list", fres, err); + } else if (fres == DW_DLV_NO_ENTRY) { + if (!silent_if_missing) { + printf("\n%s\n", framename); + } + /* no frame information */ + } else { /* DW_DLV_OK */ + /* Do not print if in check mode */ + if (!check_frames_extended) { + printf("\n%s\n", framename); + printf("\nfde:\n"); + } + + for (i = 0; i < fde_element_count; i++) { + print_one_fde(dbg, fde_data[i], + i, cie_data, cie_element_count, + address_size, is_eh, config_data, + &map_lowpc_to_name, + &lowpcSet, + &all_cus_seen); + ++frame_count; + if(frame_count >= break_after_n_units) { + break; + } + } + /* Print the cie set. */ + if (verbose) { + /* Do not print if in check mode */ + if (!check_frames_extended) { + printf("\ncie:\n"); + } + for (i = 0; i < cie_element_count; i++) { + print_one_cie(dbg, cie_data[i], i, address_size, + config_data); + ++cie_count; + if(cie_count >= break_after_n_units) { + break; + } + } + } + dwarf_fde_cie_list_dealloc(dbg, cie_data, cie_element_count, + fde_data, fde_element_count); + } + addr_map_destroy(lowpcSet); + lowpcSet = 0; + } + if (current_cu_die_for_print_frames) { + dwarf_dealloc(dbg, current_cu_die_for_print_frames, DW_DLA_DIE); + current_cu_die_for_print_frames = 0; + } + addr_map_destroy(map_lowpc_to_name); +} + diff --git a/dwarfdump/print_frames.h b/dwarfdump/print_frames.h new file mode 100644 index 0000000..2a133d8 --- /dev/null +++ b/dwarfdump/print_frames.h @@ -0,0 +1,47 @@ +/* + Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + + + $Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_frames.h,v 1.2 2006/04/17 00:09:56 davea Exp $ */ + +int print_one_cie(Dwarf_Debug dbg, Dwarf_Cie cie, + Dwarf_Unsigned cie_index, + Dwarf_Half address_size, + struct dwconf_s * config_data); + +void get_string_from_locs(Dwarf_Debug dbg, + Dwarf_Ptr bytes_in, + Dwarf_Unsigned block_len, + Dwarf_Half addr_size, + struct esb_s *out_string); + diff --git a/dwarfdump/print_lines.c b/dwarfdump/print_lines.c new file mode 100644 index 0000000..4b33994 --- /dev/null +++ b/dwarfdump/print_lines.c @@ -0,0 +1,433 @@ + +/* + Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. + Portions Copyright 2009-2011 SN Systems Ltd. All rights reserved. + Portions Copyright 2008-2011 David Anderson. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + + +$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. */ + +#include "globals.h" +#include "naming.h" +#include "dwconf.h" +#include "esb.h" +#include "uri.h" +#include <ctype.h> + +#include "print_sections.h" + +/* + Print line number information: + [line] [address] <new statement> + new basic-block + filename +*/ + + +static void +print_source_intro(Dwarf_Die cu_die) +{ + Dwarf_Off off = 0; + int ores = dwarf_dieoffset(cu_die, &off, &err); + + if (ores == DW_DLV_OK) { + printf("Source lines (from CU-DIE at .debug_info offset 0x%" + DW_PR_XZEROS DW_PR_DUx "):\n", + (Dwarf_Unsigned) off); + } else { + printf("Source lines (for the CU-DIE at unknown location):\n"); + } +} + +static void +record_line_error(const char *where, Dwarf_Error err) +{ + char tmp_buff[500]; + if(check_lines && checking_this_compiler()) { + snprintf(tmp_buff, sizeof(tmp_buff), + "Error getting line details calling %s dwarf error is %s", + where,dwarf_errmsg(err)); + DWARF_CHECK_ERROR(lines_result,tmp_buff); + } +} + +extern void +print_line_numbers_this_cu(Dwarf_Debug dbg, Dwarf_Die cu_die) +{ + Dwarf_Signed linecount = 0; + Dwarf_Line *linebuf = NULL; + Dwarf_Signed i = 0; + Dwarf_Addr pc = 0; + Dwarf_Unsigned lineno = 0; + Dwarf_Unsigned column = 0; + + Dwarf_Bool newstatement = 0; + Dwarf_Bool lineendsequence = 0; + Dwarf_Bool new_basic_block = 0; + int lres = 0; + int sres = 0; + int ares = 0; + int lires = 0; + int cores = 0; + int line_errs = 0; + + Dwarf_Bool SkipRecord = FALSE; + + current_section_id = DEBUG_LINE; + + /* line_flag is TRUE */ + + if (do_print_dwarf) { + printf("\n.debug_line: line number info for a single cu\n"); + } + if (verbose > 1) { + int errcount = 0; + print_source_intro(cu_die); + print_one_die(dbg, cu_die, + /* print_information= */ 1, + /* indent level */0, + /* srcfiles= */ 0, /* cnt= */ 0, + /* ignore_die_stack= */TRUE); + DWARF_CHECK_COUNT(lines_result,1); + lres = dwarf_print_lines(cu_die, &err,&errcount); + if(errcount > 0) { + DWARF_ERROR_COUNT(lines_result,errcount); + DWARF_CHECK_COUNT(lines_result,(errcount-1)); + } + if (lres == DW_DLV_ERROR) { + print_error(dbg, "dwarf_srclines details", lres, err); + } + return; + } + + if(check_lines && checking_this_compiler()) { + DWARF_CHECK_COUNT(lines_result,1); + dwarf_check_lineheader(cu_die,&line_errs); + if(line_errs > 0) { + DWARF_CHECK_ERROR_PRINT_CU(); + DWARF_ERROR_COUNT(lines_result,line_errs); + DWARF_CHECK_COUNT(lines_result,(line_errs-1)); + } + } + lres = dwarf_srclines(cu_die, &linebuf, &linecount, &err); + if (lres == DW_DLV_ERROR) { + /* Do not terminate processing */ + if (check_decl_file) { + DWARF_CHECK_COUNT(decl_file_result,1); + DWARF_CHECK_ERROR2(decl_file_result,"dwarf_srclines", + dwarf_errmsg(err)); + record_dwarf_error = FALSE; /* Clear error condition */ + } else { + print_error(dbg, "dwarf_srclines", lres, err); + } + } else if (lres == DW_DLV_NO_ENTRY) { + /* no line information is included */ + } else { + struct esb_s lastsrc;; + esb_constructor(&lastsrc); + if (do_print_dwarf) { + print_source_intro(cu_die); + if (verbose) { + print_one_die(dbg, cu_die, + /* print_information= */ TRUE, + /* indent_level= */ 0, + /* srcfiles= */ 0, /* cnt= */ 0, + /* ignore_die_stack= */TRUE); + } + printf("\n<pc> [row,col] " + "NS BB ET PE EB IS= DI= uri: \"filepath\"\n"); + printf("NS new statement, BB new basic block, " + "ET end of text sequence\n"); + printf("PE prologue end, EB epilogue begin\n"); + printf("IA=val ISA number, DI=val discriminator value\n"); + } + for (i = 0; i < linecount; i++) { + Dwarf_Line line = linebuf[i]; + string filename = 0; + int nsres = 0; + Dwarf_Bool found_line_error = FALSE; + Dwarf_Bool has_is_addr_set = FALSE; + char *where = NULL; + + if (check_decl_file && checking_this_compiler()) { + /* A line record with addr=0 was detected */ + if (SkipRecord) { + /* Skip records that do not have ís_addr_set' */ + ares = dwarf_line_is_addr_set(line, &has_is_addr_set, &err); + if (ares == DW_DLV_OK && has_is_addr_set) { + SkipRecord = FALSE; + } + else { + /* Keep ignoring records until we have + one with 'is_addr_set' */ + continue; + } + } + } + + if(check_lines && checking_this_compiler()) { + DWARF_CHECK_COUNT(lines_result,1); + } + filename = "<unknown>"; + sres = dwarf_linesrc(line, &filename, &err); + if (sres == DW_DLV_ERROR) { + /* Do not terminate processing */ + where = "dwarf_linesrc()"; + record_line_error(where,err); + found_line_error = TRUE; + } + + ares = dwarf_lineaddr(line, &pc, &err); + + if (ares == DW_DLV_ERROR) { + /* Do not terminate processing */ + where = "dwarf_lineaddr()"; + record_line_error(where,err); + found_line_error = TRUE; + } + if (ares == DW_DLV_NO_ENTRY) { + pc = 0; + } + lires = dwarf_lineno(line, &lineno, &err); + if (lires == DW_DLV_ERROR) { + /* Do not terminate processing */ + where = "dwarf_lineno()"; + record_line_error(where,err); + found_line_error = TRUE; + } + if (lires == DW_DLV_NO_ENTRY) { + lineno = -1LL; + } + cores = dwarf_lineoff_b(line, &column, &err); + if (cores == DW_DLV_ERROR) { + /* Do not terminate processing */ + where = "dwarf_lineoff()"; + record_line_error(where,err); + found_line_error = TRUE; + } + if (cores == DW_DLV_NO_ENTRY) { + /* Zero was always the correct default, meaning + the left edge. DWARF2/3/4 spec sec 6.2.2 */ + column = 0; + } + + /* Process any possible error condition, though + we won't be at the first such error. */ + if (check_decl_file && checking_this_compiler()) { + DWARF_CHECK_COUNT(decl_file_result,1); + if (found_line_error) { + DWARF_CHECK_ERROR2(decl_file_result,where,dwarf_errmsg(err)); + } else if (do_check_dwarf) { + /* Check the address lies with a valid [lowPC:highPC] + in the .text section*/ + if (IsValidInBucketGroup(pRangesInfo,pc)) { + /* Valid values; do nothing */ + } else { + /* At this point may be we are dealing with + a linkonce symbol. The problem we have here + is we have consumed the deug_info section + and we are dealing just with the records + from the .debug_line, so no PU_name is + available and no high_pc. Traverse the linkonce + table if try to match the pc value with + one of those ranges. + */ + if(check_lines && checking_this_compiler()) { + DWARF_CHECK_COUNT(lines_result,1); + } + if (FindAddressInBucketGroup(pLinkonceInfo,pc)){ + /* Valid values; do nothing */ + } else { + /* The SN Systems Linker generates + line records + with addr=0, when dealing with linkonce + symbols and no stripping */ + if (pc) { + char addr_tmp[100]; + if(check_lines && checking_this_compiler()) { + snprintf(addr_tmp,sizeof(addr_tmp), + ".debug_line: Address" + " 0x%" DW_PR_XZEROS DW_PR_DUx + " outside a valid .text range",pc); + DWARF_CHECK_ERROR(lines_result, + addr_tmp); + } + } else { + SkipRecord = TRUE; + } + } + } + /* Check the last record for the .debug_line, + the one created by DW_LNE_end_sequence, + is the same as the high_pc + address for the last known user program + unit (PU) */ + if ((i + 1 == linecount) && + seen_PU_high_address) { + /* Ignore those PU that have been stripped + by the linker; their low_pc values are + set to -1 (snc linker only) */ + /* It is perfectly sensible for a compiler + to leave a few bytes of NOP or other stuff + after the last instruction in a subprogram, + for cache-alignment or other purposes, so + a mismatch here is not necessarily + an error. */ + + if (check_lines && checking_this_compiler()) { + DWARF_CHECK_COUNT(lines_result,1); + if ((pc != PU_high_address) && + (PU_base_address != elf_max_address)) { + char addr_tmp[100]; + snprintf(addr_tmp,sizeof(addr_tmp), + ".debug_line: Address" + " 0x%" DW_PR_XZEROS DW_PR_DUx + " may be incorrect" + " as DW_LNE_end_sequence address",pc); + DWARF_CHECK_ERROR(lines_result, + addr_tmp); + } + } + } + } + } + + /* Display the error information */ + if (found_line_error || record_dwarf_error) { + if (check_verbose_mode) { + /* Print the record number for better error description */ + printf("Record = %" DW_PR_DUu + " Addr = 0x%" DW_PR_XZEROS DW_PR_DUx + " [%4" DW_PR_DUu ",%2" DW_PR_DUu "] '%s'\n", + i, pc,lineno,column,filename); + /* Flush due to the redirection of stderr */ + fflush(stdout); + /* The compilation unit was already printed */ + if (!check_decl_file) { + PRINT_CU_INFO(); + } + } + record_dwarf_error = FALSE; + /* Due to a fatal error, skip current record */ + if (found_line_error) { + continue; + } + } + if (do_print_dwarf) { + printf("0x%08" DW_PR_DUx + " [%4" DW_PR_DUu ",%2" DW_PR_DUu "]", pc, lineno, + column); + } + + nsres = dwarf_linebeginstatement(line, &newstatement, &err); + if (nsres == DW_DLV_OK) { + if (newstatement && do_print_dwarf) { + printf(" %s","NS"); + } + } else if (nsres == DW_DLV_ERROR) { + print_error(dbg, "linebeginstatment failed", nsres, err); + } + nsres = dwarf_lineblock(line, &new_basic_block, &err); + if (nsres == DW_DLV_OK) { + if (new_basic_block && do_print_dwarf) { + printf(" %s","BB"); + } + } else if (nsres == DW_DLV_ERROR) { + print_error(dbg, "lineblock failed", nsres, err); + } + nsres = dwarf_lineendsequence(line, &lineendsequence, &err); + if (nsres == DW_DLV_OK) { + if (lineendsequence && do_print_dwarf) { + printf(" %s", "ET"); + } + } else if (nsres == DW_DLV_ERROR) { + print_error(dbg, "lineblock failed", nsres, err); + } + if(do_print_dwarf) { + Dwarf_Bool prologue_end = 0; + Dwarf_Bool epilogue_begin = 0; + Dwarf_Unsigned isa = 0; + Dwarf_Unsigned discriminator = 0; + int disres = dwarf_prologue_end_etc(line, + &prologue_end,&epilogue_begin, + &isa,&discriminator,&err); + if (disres == DW_DLV_ERROR) { + print_error(dbg, "dwarf_prologue_end_etc() failed", + disres, err); + } + if(prologue_end) { + printf(" PE"); + } + if(epilogue_begin) { + printf(" EB"); + } + if(isa) { + printf(" IS=0x%" DW_PR_DUx, isa); + } + if(discriminator) { + printf(" DI=0x%" DW_PR_DUx, discriminator); + } + } + + + if (i > 0 && verbose < 3 && + strcmp(filename,esb_get_string(&lastsrc)) == 0) { + /* Do not print name. */ + } else { + struct esb_s urs; + esb_constructor(&urs); + esb_append(&urs, " uri: \""); + translate_to_uri(filename,&urs); + esb_append(&urs,"\""); + if(do_print_dwarf) { + printf("%s",esb_get_string(&urs)); + } + esb_destructor(&urs); + esb_empty_string(&lastsrc); + esb_append(&lastsrc,filename); + } + if (sres == DW_DLV_OK) { + dwarf_dealloc(dbg, filename, DW_DLA_STRING); + } + if (do_print_dwarf) { + printf("\n"); + } + } + esb_destructor(&lastsrc); + dwarf_srclines_dealloc(dbg, linebuf, linecount); + } +} diff --git a/dwarfdump/print_locs.c b/dwarfdump/print_locs.c new file mode 100644 index 0000000..c7cf99f --- /dev/null +++ b/dwarfdump/print_locs.c @@ -0,0 +1,128 @@ +/* + Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. + Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved. + Portions Copyright 2008-2011 David Anderson. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + + +$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + +#include "globals.h" +#include "naming.h" +#include "dwconf.h" +#include "esb.h" + +#include "print_sections.h" +#include "print_frames.h" + +/* print data in .debug_loc + There is no guarantee this will work because we are assuming + that all bytes are valid loclist data, that there are no + odd padding or garbage bytes. In normal use one gets + into here via an offset from .debug_info, so it could be + that bytes not referenced from .debug_info are garbage + or even zero padding. So this can fail (error off) as such bytes + can lead dwarf_get_loclist_entry() astray. + + It's also wrong because we don't know what CU or frame each + loclist is from, so we don't know the address_size for sure. +*/ +extern void +print_locs(Dwarf_Debug dbg) +{ + Dwarf_Unsigned offset = 0; + Dwarf_Addr hipc_offset = 0; + Dwarf_Addr lopc_offset = 0; + Dwarf_Ptr data = 0; + Dwarf_Unsigned entry_len = 0; + Dwarf_Unsigned next_entry = 0; + struct esb_s exprstring; + int index = 0; + int lres = 0; + int fres = 0; + + /* This is sometimes wrong, we need a frame-specific size. */ + Dwarf_Half address_size = 0; + + current_section_id = DEBUG_LOC; + + /* Do nothing if not printing. */ + if (!do_print_dwarf) { + return; + } + + fres = dwarf_get_address_size(dbg, &address_size, &err); + if (fres != DW_DLV_OK) { + print_error(dbg, "dwarf_get_address_size", fres, err); + } + + printf("\n.debug_loc"); + + printf("\nFormat <i o b e l>: " + "index section-offset begin-addr end-addr length-of-block-entry\n"); + esb_constructor(&exprstring); + while ((lres = dwarf_get_loclist_entry(dbg, offset, + &hipc_offset, &lopc_offset, + &data, &entry_len, + &next_entry, + &err)) == DW_DLV_OK) { + get_string_from_locs(dbg,data,entry_len,address_size, + &exprstring); + /* Display offsets */ + if (display_offsets) { + ++index; + printf(" <iobel> [%8d] 0x%" DW_PR_XZEROS DW_PR_DUx, + index, offset); + if(verbose) { + printf(" <expr-off 0x%" DW_PR_XZEROS DW_PR_DUx ">", + next_entry - entry_len); + } + } + printf(" 0x%" DW_PR_XZEROS DW_PR_DUx + " 0x%" DW_PR_XZEROS DW_PR_DUx + " %8" DW_PR_DUu " %s\n", + (Dwarf_Unsigned) lopc_offset, + (Dwarf_Unsigned) hipc_offset, entry_len, + esb_get_string(&exprstring)); + esb_empty_string(&exprstring); + offset = next_entry; + } + esb_destructor(&exprstring); + if (lres == DW_DLV_ERROR) { + print_error(dbg, "dwarf_get_loclist_entry", lres, err); + } +} diff --git a/dwarfdump/print_macros.c b/dwarfdump/print_macros.c new file mode 100644 index 0000000..0a36fc9 --- /dev/null +++ b/dwarfdump/print_macros.c @@ -0,0 +1,216 @@ +/* + Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. + Portions Copyright 2009-2011 SN Systems Ltd. All rights reserved. + Portions Copyright 2008-2011 David Anderson. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + + +$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + +#include "globals.h" +#include "naming.h" +#include "dwconf.h" +#include "esb.h" + +#include "print_sections.h" +#include "print_frames.h" + + +struct macro_counts_s { + long mc_start_file; + long mc_end_file; + long mc_define; + long mc_undef; + long mc_extension; + long mc_code_zero; + long mc_unknown; +}; + +static void +print_one_macro_entry_detail(long i, + char *type, + struct Dwarf_Macro_Details_s *mdp) +{ + /* "DW_MACINFO_*: section-offset file-index [line] string\n" */ + if (mdp->dmd_macro) { + printf("%3ld %s: %6" DW_PR_DUu " %2" DW_PR_DSd " [%4" + DW_PR_DSd "] \"%s\" \n", + i, + type, + (Dwarf_Unsigned)mdp->dmd_offset, + mdp->dmd_fileindex, mdp->dmd_lineno, mdp->dmd_macro); + } else { + printf("%3ld %s: %6" DW_PR_DUu " %2" DW_PR_DSd " [%4" + DW_PR_DSd "] 0\n", + i, + type, + (Dwarf_Unsigned)mdp->dmd_offset, + mdp->dmd_fileindex, mdp->dmd_lineno); + } + +} + +static void +print_one_macro_entry(long i, + struct Dwarf_Macro_Details_s *mdp, + struct macro_counts_s *counts) +{ + + switch (mdp->dmd_type) { + case 0: + counts->mc_code_zero++; + print_one_macro_entry_detail(i, "DW_MACINFO_type-code-0", mdp); + break; + + case DW_MACINFO_start_file: + counts->mc_start_file++; + print_one_macro_entry_detail(i, "DW_MACINFO_start_file", mdp); + break; + + case DW_MACINFO_end_file: + counts->mc_end_file++; + print_one_macro_entry_detail(i, "DW_MACINFO_end_file ", mdp); + break; + + case DW_MACINFO_vendor_ext: + counts->mc_extension++; + print_one_macro_entry_detail(i, "DW_MACINFO_vendor_ext", mdp); + break; + + case DW_MACINFO_define: + counts->mc_define++; + print_one_macro_entry_detail(i, "DW_MACINFO_define ", mdp); + break; + + case DW_MACINFO_undef: + counts->mc_undef++; + print_one_macro_entry_detail(i, "DW_MACINFO_undef ", mdp); + break; + + default: + { + char create_type[50]; /* More than large enough. */ + + counts->mc_unknown++; + snprintf(create_type, sizeof(create_type), + "DW_MACINFO_0x%x", mdp->dmd_type); + print_one_macro_entry_detail(i, create_type, mdp); + } + break; + } +} + +/* print data in .debug_macinfo */ +/* FIXME: should print name of file whose index is in macro data + here -- somewhere. */ +/*ARGSUSED*/ extern void +print_macinfo(Dwarf_Debug dbg) +{ + Dwarf_Off offset = 0; + Dwarf_Unsigned max = 0; + Dwarf_Signed count = 0; + long group = 0; + Dwarf_Macro_Details *maclist = NULL; + int lres = 0; + + current_section_id = DEBUG_MACINFO; + if (!do_print_dwarf) { + return; + } + + printf("\n.debug_macinfo\n"); + + while ((lres = dwarf_get_macro_details(dbg, offset, + max, &count, &maclist, + &err)) == DW_DLV_OK) { + long i = 0; + struct macro_counts_s counts; + + + memset(&counts, 0, sizeof(counts)); + + printf("\n"); + printf("compilation-unit .debug_macinfo # %ld\n", group); + printf + ("num name section-offset file-index [line] \"string\"\n"); + for (i = 0; i < count; i++) { + struct Dwarf_Macro_Details_s *mdp = &maclist[i]; + + print_one_macro_entry(i, mdp, &counts); + } + + if (counts.mc_start_file == 0) { + printf + ("DW_MACINFO file count of zero is invalid DWARF2/3\n"); + } + if (counts.mc_start_file != counts.mc_end_file) { + printf("Counts of DW_MACINFO file (%ld) end_file (%ld) " + "do not match!.\n", + counts.mc_start_file, counts.mc_end_file); + } + if (counts.mc_code_zero < 1) { + printf("Count of zeros in macro group should be non-zero " + "(1 preferred), count is %ld\n", + counts.mc_code_zero); + } + printf("Macro counts: start file %ld, " + "end file %ld, " + "define %ld, " + "undef %ld, " + "ext %ld, " + "code-zero %ld, " + "unknown %ld\n", + counts.mc_start_file, + counts.mc_end_file, + counts.mc_define, + counts.mc_undef, + counts.mc_extension, + counts.mc_code_zero, counts.mc_unknown); + + + /* int type= maclist[count - 1].dmd_type; */ + /* ASSERT: type is zero */ + + offset = maclist[count - 1].dmd_offset + 1; + dwarf_dealloc(dbg, maclist, DW_DLA_STRING); + ++group; + } + if (lres == DW_DLV_ERROR) { + print_error(dbg, "dwarf_get_macro_details", lres, err); + } +} + diff --git a/dwarfdump/print_pubnames.c b/dwarfdump/print_pubnames.c new file mode 100644 index 0000000..8018152 --- /dev/null +++ b/dwarfdump/print_pubnames.c @@ -0,0 +1,300 @@ +/* + Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. +v Portions Copyright 2009-2011 SN Systems Ltd. All rights reserved. + Portions Copyright 2008-2011 David Anderson. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + + +$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + +#include "globals.h" +#include "naming.h" +#include "dwconf.h" +#include "esb.h" +#include "print_sections.h" + +/* This unifies the code for some error checks to + avoid code duplication. +*/ +static void +check_info_offset_sanity(char *sec, + char *field, + char *global, + Dwarf_Unsigned offset, Dwarf_Unsigned maxoff) +{ + if (maxoff == 0) { + /* Lets make a heuristic check. */ + if (offset > 0xffffffff) { + printf("Warning: section %s %s %s offset 0x%" + DW_PR_XZEROS DW_PR_DUx " " + "exceptionally large \n", + sec, field, global, offset); + } + return; + } + if (offset >= maxoff) { + printf("Warning: section %s %s %s offset 0x%" + DW_PR_XZEROS DW_PR_DUx " " + "larger than max of 0x%" DW_PR_DUx "\n", + sec, field, global, offset, maxoff); + } +} + +/* Unified pubnames style output. + The error checking here against maxoff may be useless + (in that libdwarf may return an error if the offset is bad + and we will not get called here). + But we leave it in nonetheless as it looks sensible. + In at least one gigantic executable such offsets turned out wrong. +*/ +void +print_pubname_style_entry(Dwarf_Debug dbg, + char *line_title, + char *name, + Dwarf_Unsigned die_off, + Dwarf_Unsigned cu_off, + Dwarf_Unsigned global_cu_offset, + Dwarf_Unsigned maxoff) +{ + Dwarf_Die die = NULL; + Dwarf_Off die_CU_off = 0; + int dres = 0; + int ddres = 0; + int cudres = 0; + char tmp_buf[100]; + + /* get die at die_off */ + dres = dwarf_offdie(dbg, die_off, &die, &err); + if (dres != DW_DLV_OK) { + struct esb_s details; + esb_constructor(&details); + esb_append(&details,line_title); + esb_append(&details," dwarf_offdie : " + "die offset does not reference valid DIE. "); + snprintf(tmp_buf,sizeof(tmp_buf),"0x%" DW_PR_DUx, die_off); + esb_append(&details,tmp_buf); + esb_append(&details,"."); + print_error(dbg, esb_get_string(&details), dres, err); + esb_destructor(&details); + } + + /* get offset of die from its cu-header */ + ddres = dwarf_die_CU_offset(die, &die_CU_off, &err); + if (ddres != DW_DLV_OK) { + struct esb_s details; + esb_constructor(&details); + esb_append(&details,line_title); + esb_append(&details," cannot get CU die offset"); + print_error(dbg, esb_get_string(&details), dres, err); + esb_destructor(&details); + die_CU_off = 0; + } + + /* Get die at offset cu_off to check its existence. */ + { + Dwarf_Die cu_die = NULL; + cudres = dwarf_offdie(dbg, cu_off, &cu_die, &err); + if (cudres != DW_DLV_OK) { + struct esb_s details; + esb_constructor(&details); + esb_append(&details,line_title); + esb_append(&details," dwarf_offdie: " + "cu die offset does not reference valid CU DIE. "); + snprintf(tmp_buf,sizeof(tmp_buf),"0x%" DW_PR_DUx, cu_off); + esb_append(&details,tmp_buf); + esb_append(&details,"."); + print_error(dbg, esb_get_string(&details), dres, err); + esb_destructor(&details); + } else { + /* It exists, all is well. */ + dwarf_dealloc(dbg, cu_die, DW_DLA_DIE); + } + } + /* Display offsets */ + if (display_offsets) { + /* Print 'name'at the end for better layout */ + printf("%s die-in-sect 0x%" DW_PR_XZEROS DW_PR_DUx + ", cu-in-sect 0x%" DW_PR_XZEROS DW_PR_DUx "," + " die-in-cu 0x%" DW_PR_XZEROS DW_PR_DUx + ", cu-header-in-sect 0x%" DW_PR_XZEROS DW_PR_DUx , + line_title, + die_off, cu_off, + (Dwarf_Unsigned) die_CU_off, + /* Following is absolute offset of the ** beginning of the + cu */ + (Dwarf_Signed) (die_off - die_CU_off)); + } + + if ((die_off - die_CU_off) != global_cu_offset) { + printf(" error: real cuhdr 0x%" DW_PR_XZEROS DW_PR_DUx, + global_cu_offset); + exit(1); + } + + /* Display offsets */ + if (display_offsets && verbose) { + printf(" cuhdr 0x%" DW_PR_XZEROS DW_PR_DUx , global_cu_offset); + } + + /* Print 'name'at the end for better layout */ + printf(" '%s'\n",name); + + dwarf_dealloc(dbg, die, DW_DLA_DIE); + + check_info_offset_sanity(line_title, + "die offset", name, die_off, maxoff); + check_info_offset_sanity(line_title, + "die cu offset", name, die_CU_off, maxoff); + check_info_offset_sanity(line_title, + "cu offset", name, + (die_off - die_CU_off), maxoff); + +} + +/* Get all the data in .debug_pubnames */ +void +print_pubnames(Dwarf_Debug dbg) +{ + Dwarf_Global *globbuf = NULL; + Dwarf_Signed count = 0; + Dwarf_Signed i = 0; + Dwarf_Off die_off = 0; + Dwarf_Off cu_off = 0; + + /* Offset to previous CU */ + Dwarf_Off prev_cu_off = elf_max_address; + + char *name = 0; + int res = 0; + + current_section_id = DEBUG_PUBNAMES; + if (do_print_dwarf) { + printf("\n.debug_pubnames\n"); + } + res = dwarf_get_globals(dbg, &globbuf, &count, &err); + if (res == DW_DLV_ERROR) { + print_error(dbg, "dwarf_get_globals", res, err); + } else if (res == DW_DLV_NO_ENTRY) { + /* (err == 0 && count == DW_DLV_NOCOUNT) means there are no + pubnames. */ + } else { + Dwarf_Unsigned maxoff = get_info_max_offset(dbg); + + for (i = 0; i < count; i++) { + int nres = 0; + int cures3 = 0; + Dwarf_Off global_cu_off = 0; + + nres = dwarf_global_name_offsets(globbuf[i], + &name, &die_off, &cu_off, + &err); + deal_with_name_offset_err(dbg, "dwarf_global_name_offsets", + name, die_off, nres, err); + cures3 = dwarf_global_cu_offset(globbuf[i], + &global_cu_off, &err); + if (cures3 != DW_DLV_OK) { + print_error(dbg, "dwarf_global_cu_offset", cures3, err); + } + + if (check_pubname_attr) { + Dwarf_Bool has_attr; + int ares; + int dres; + Dwarf_Die die; + + /* We are processing a new set of pubnames + for a different CU; get the producer ID, at 'cu_off' + to see if we need to skip these pubnames */ + if (cu_off != prev_cu_off) { + char *producer_name = 0; + + /* Record offset for previous CU */ + prev_cu_off = cu_off; + + dres = dwarf_offdie(dbg, cu_off, &die, &err); + if (dres != DW_DLV_OK) { + print_error(dbg, "print pubnames: dwarf_offdie a", dres,err); + } + + /* Get producer name for this CU and update compiler list */ + get_producer_name(dbg,die,err,&producer_name); + update_compiler_target(producer_name); + + dwarf_dealloc(dbg, die, DW_DLA_DIE); + } + + /* get die at die_off */ + dres = dwarf_offdie(dbg, die_off, &die, &err); + if (dres != DW_DLV_OK) { + print_error(dbg, "print pubnames: dwarf_offdie b", dres, err); + } + + + ares = + dwarf_hasattr(die, DW_AT_external, &has_attr, &err); + if (ares == DW_DLV_ERROR) { + print_error(dbg, "hassattr on DW_AT_external", ares, + err); + } + + /* Check for specific compiler */ + if (checking_this_compiler()) { + DWARF_CHECK_COUNT(pubname_attr_result,1); + if (ares == DW_DLV_OK && has_attr) { + /* Should the value of flag be examined? */ + } else { + DWARF_CHECK_ERROR2(pubname_attr_result,name, + "pubname does not have DW_AT_external"); + } + } + dwarf_dealloc(dbg, die, DW_DLA_DIE); + } + + /* Now print pubname, after the test */ + if (do_print_dwarf || (record_dwarf_error && check_verbose_mode)) { + print_pubname_style_entry(dbg, + "global", + name, die_off, cu_off, + global_cu_off, maxoff); + record_dwarf_error = FALSE; /* Clear error condition */ + } + + } + dwarf_globals_dealloc(dbg, globbuf, count); + } +} /* print_pubnames() */ + diff --git a/dwarfdump/print_ranges.c b/dwarfdump/print_ranges.c new file mode 100644 index 0000000..aee55e0 --- /dev/null +++ b/dwarfdump/print_ranges.c @@ -0,0 +1,106 @@ +/* + Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. + Portions Copyright 2009-2011 SN Systems Ltd. All rights reserved. + Portions Copyright 2008-2011 David Anderson. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + + +$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + +#include "globals.h" +#include "naming.h" +#include "dwconf.h" +#include "esb.h" +#include "print_sections.h" + +static struct esb_s esb_string; + +/* Because we do not know what DIE is involved, if the + object being printed has different address sizes + in different compilation units this will not work + properly: anything could happen. */ +extern void +print_ranges(Dwarf_Debug dbg) +{ + Dwarf_Unsigned off = 0; + int group_number = 0; + int wasdense = 0; + + current_section_id = DEBUG_RANGES; + if (!do_print_dwarf) { + return; + } + printf("\n.debug_ranges\n"); + + /* Turn off dense, we do not want print_ranges_list_to_extra + to use dense form here. */ + wasdense = dense; + dense = 0; + for(;;) { + Dwarf_Ranges *rangeset = 0; + Dwarf_Signed rangecount = 0; + Dwarf_Unsigned bytecount = 0; + + /* We do not know what DIE is involved, we use + the older call here. */ + int rres = dwarf_get_ranges(dbg,off,&rangeset, + &rangecount,&bytecount,&err); + if(rres == DW_DLV_OK) { + char *val = 0; + printf(" Ranges group %d:\n",group_number); + esb_empty_string(&esb_string); + print_ranges_list_to_extra(dbg,off, + rangeset,rangecount,bytecount, + &esb_string); + dwarf_ranges_dealloc(dbg,rangeset,rangecount); + val = esb_get_string(&esb_string); + printf("%s",val); + ++group_number; + } else if (rres == DW_DLV_NO_ENTRY) { + printf("End of .debug_ranges.\n"); + break; + } else { + /* ERROR, which does not quite mean a real error, + as we might just be misaligned reading things without + a DW_AT_ranges offset.*/ + printf("End of .debug_ranges..\n"); + break; + } + off += bytecount; + } + dense = wasdense; +} diff --git a/dwarfdump/print_reloc.c b/dwarfdump/print_reloc.c new file mode 100644 index 0000000..35a1574 --- /dev/null +++ b/dwarfdump/print_reloc.c @@ -0,0 +1,1150 @@ +/* + Copyright (C) 2000,2004,2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved. + Portions Copyright (C) 2011 SN Systems Ltd. All Rights Reserved + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + + +$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_reloc.c,v 1.11 2005/08/04 05:09:37 davea Exp $ */ + +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + + + + +#include "globals.h" +#include "print_reloc.h" + +#define DW_SECTION_REL_DEBUG_NUM 9 /* Number of sections */ +/* .debug_abbrev should never have a relocation applied to it as it + never refers to another section! (other sections refer to + .debug_abbrev) */ + +#define DW_SECTNAME_RELA_DEBUG ".rela.debug_" +#define DW_SECTNAME_RELA_DEBUG_INFO ".rela.debug_info" +#define DW_SECTNAME_RELA_DEBUG_LINE ".rela.debug_line" +#define DW_SECTNAME_RELA_DEBUG_PUBNAMES ".rela.debug_pubnames" +#define DW_SECTNAME_RELA_DEBUG_ABBREV ".rela.debug_abbrev" +#define DW_SECTNAME_RELA_DEBUG_ARANGES ".rela.debug_aranges" +#define DW_SECTNAME_RELA_DEBUG_FRAME ".rela.debug_frame" +#define DW_SECTNAME_RELA_DEBUG_LOC ".rela.debug_loc" +#define DW_SECTNAME_RELA_DEBUG_RANGES ".rela.debug_ranges" +#define DW_SECTNAME_RELA_DEBUG_TYPES ".rela.debug_types" + +#define DW_SECTNAME_REL_DEBUG ".rel.debug_" +#define DW_SECTNAME_REL_DEBUG_INFO ".rel.debug_info" +#define DW_SECTNAME_REL_DEBUG_LINE ".rel.debug_line" +#define DW_SECTNAME_REL_DEBUG_PUBNAMES ".rel.debug_pubnames" +#define DW_SECTNAME_REL_DEBUG_ABBREV ".rel.debug_abbrev" +#define DW_SECTNAME_REL_DEBUG_ARANGES ".rel.debug_aranges" +#define DW_SECTNAME_REL_DEBUG_FRAME ".rel.debug_frame" +#define DW_SECTNAME_REL_DEBUG_LOC ".rel.debug_loc" +#define DW_SECTNAME_REL_DEBUG_RANGES ".rel.debug_ranges" +#define DW_SECTNAME_REL_DEBUG_TYPES ".rel.debug_types" + + +#define STRING_FOR_DUPLICATE " duplicate" +#define STRING_FOR_NULL " null" + +static char *sectnames[] = { + DW_SECTNAME_REL_DEBUG_INFO, + DW_SECTNAME_REL_DEBUG_LINE, + DW_SECTNAME_REL_DEBUG_PUBNAMES, + DW_SECTNAME_REL_DEBUG_ABBREV, + DW_SECTNAME_REL_DEBUG_ARANGES, + DW_SECTNAME_REL_DEBUG_FRAME, + DW_SECTNAME_REL_DEBUG_LOC, + DW_SECTNAME_REL_DEBUG_RANGES, + DW_SECTNAME_REL_DEBUG_TYPES, +}; +static char *sectnamesa[] = { + DW_SECTNAME_RELA_DEBUG_INFO, + DW_SECTNAME_RELA_DEBUG_LINE, + DW_SECTNAME_RELA_DEBUG_PUBNAMES, + DW_SECTNAME_RELA_DEBUG_ABBREV, + DW_SECTNAME_RELA_DEBUG_ARANGES, + DW_SECTNAME_RELA_DEBUG_FRAME, + DW_SECTNAME_RELA_DEBUG_LOC, + DW_SECTNAME_RELA_DEBUG_RANGES, + DW_SECTNAME_RELA_DEBUG_TYPES, +}; + +static char *error_msg_duplicate[] = { + DW_SECTNAME_REL_DEBUG_INFO STRING_FOR_DUPLICATE, + DW_SECTNAME_REL_DEBUG_LINE STRING_FOR_DUPLICATE, + DW_SECTNAME_REL_DEBUG_PUBNAMES STRING_FOR_DUPLICATE, + DW_SECTNAME_REL_DEBUG_ABBREV STRING_FOR_DUPLICATE, + DW_SECTNAME_REL_DEBUG_ARANGES STRING_FOR_DUPLICATE, + DW_SECTNAME_REL_DEBUG_FRAME STRING_FOR_DUPLICATE, + DW_SECTNAME_REL_DEBUG_LOC STRING_FOR_DUPLICATE, + DW_SECTNAME_REL_DEBUG_RANGES STRING_FOR_DUPLICATE, + DW_SECTNAME_REL_DEBUG_TYPES STRING_FOR_DUPLICATE, +}; + +static char *error_msg_null[] = { + DW_SECTNAME_REL_DEBUG_INFO STRING_FOR_NULL, + DW_SECTNAME_REL_DEBUG_LINE STRING_FOR_NULL, + DW_SECTNAME_REL_DEBUG_PUBNAMES STRING_FOR_NULL, + DW_SECTNAME_REL_DEBUG_ABBREV STRING_FOR_NULL, + DW_SECTNAME_REL_DEBUG_ARANGES STRING_FOR_NULL, + DW_SECTNAME_REL_DEBUG_FRAME STRING_FOR_NULL, + DW_SECTNAME_REL_DEBUG_LOC STRING_FOR_NULL, + DW_SECTNAME_REL_DEBUG_RANGES STRING_FOR_NULL, + DW_SECTNAME_REL_DEBUG_TYPES STRING_FOR_NULL, +}; + +/* Include Section type, to be able to deal with all the + Elf32_Rel, Elf32_Rela, Elf64_Rel, Elf64_Rela relocation types */ +#define SECT_DATA_SET(x,t,n) { \ + if (sect_data[(x)].buf != NULL) { \ + print_error(dbg, error_msg_duplicate[(x)], DW_DLV_OK, err); \ + } \ + if ((data = elf_getdata(scn, 0)) == NULL || data->d_size == 0) {\ + print_error(dbg, error_msg_null[(x)],DW_DLV_OK, err); \ + } \ + sect_data[(x)].buf = data -> d_buf; \ + sect_data[(x)].size = data -> d_size; \ + sect_data[(x)].type = t; \ + sect_data[(x)].name = n; \ + } + +/* PowerPC relocations defined by the ABIs */ +static char *reloc_type_names_PPC[] = { + "R_PPC_NONE", /* 00 */ + "R_PPC_ADDR32", /* 01 */ + "R_PPC_ADDR24", /* 02 */ + "R_PPC_ADDR16", /* 03 */ + "R_PPC_ADDR16_LO", /* 04 */ + "R_PPC_ADDR16_HI", /* 05 */ + "R_PPC_ADDR16_HA", /* 06 */ + "R_PPC_ADDR14", /* 07 */ + "R_PPC_ADDR14_BRTAKEN", /* 08 */ + "R_PPC_ADDR14_BRNTAKEN", /* 09 */ + "R_PPC_REL24", /* 10 */ + "R_PPC_REL14", /* 11 */ + "R_PPC_REL14_BRTAKEN", /* 12 */ + "R_PPC_REL14_BRNTAKEN", /* 13 */ + "R_PPC_GOT16", /* 14 */ + "R_PPC_GOT16_LO", /* 15 */ + "R_PPC_GOT16_HI", /* 16 */ + "R_PPC_GOT16_HA", /* 17 */ + "R_PPC_PLTREL24", /* 18 */ + "R_PPC_COPY", /* 19 */ + "R_PPC_GLOB_DAT", /* 20 */ + "R_PPC_JMP_SLOT", /* 21 */ + "R_PPC_RELATIVE", /* 22 */ + "R_PPC_LOCAL24PC", /* 23 */ + "R_PPC_UADDR32", /* 24 */ + "R_PPC_UADDR16", /* 25 */ + "R_PPC_REL32", /* 26 */ + "R_PPC_PLT32", /* 27 */ + "R_PPC_PLTREL32", /* 28 */ + "R_PPC_PLT16_LO", /* 29 */ + "R_PPC_PLT16_HI", /* 30 */ + "R_PPC_PLT16_HA", /* 31 */ + "R_PPC_SDAREL16", /* 32 */ + "R_PPC_SECTOFF", /* 33 */ + "R_PPC_SECTOFF_LO", /* 34 */ + "R_PPC_SECTOFF_HI", /* 35 */ + "R_PPC_SECTOFF_HA", /* 36 */ + "R_PPC_37", /* 37 */ + "R_PPC_38", /* 38 */ + "R_PPC_39", /* 39 */ + "R_PPC_40", /* 40 */ + "R_PPC_41", /* 41 */ + "R_PPC_42", /* 42 */ + "R_PPC_43", /* 43 */ + "R_PPC_44", /* 44 */ + "R_PPC_45", /* 45 */ + "R_PPC_46", /* 46 */ + "R_PPC_47", /* 47 */ + "R_PPC_48", /* 48 */ + "R_PPC_49", /* 49 */ + "R_PPC_50", /* 50 */ + "R_PPC_51", /* 51 */ + "R_PPC_52", /* 52 */ + "R_PPC_53", /* 53 */ + "R_PPC_54", /* 54 */ + "R_PPC_55", /* 55 */ + "R_PPC_56", /* 56 */ + "R_PPC_57", /* 57 */ + "R_PPC_58", /* 58 */ + "R_PPC_59", /* 59 */ + "R_PPC_60", /* 60 */ + "R_PPC_61", /* 61 */ + "R_PPC_62", /* 62 */ + "R_PPC_63", /* 63 */ + "R_PPC_64", /* 64 */ + "R_PPC_65", /* 65 */ + "R_PPC_66", /* 66 */ + "R_PPC_TLS", /* 67 */ + "R_PPC_DTPMOD32", /* 68 */ + "R_PPC_TPREL16", /* 69 */ + "R_PPC_TPREL16_LO", /* 70 */ + "R_PPC_TPREL16_HI", /* 71 */ + "R_PPC_TPREL16_HA", /* 72 */ + "R_PPC_TPREL32", /* 73 */ + "R_PPC_DTPREL16", /* 74 */ + "R_PPC_DTPREL16_LO", /* 75 */ + "R_PPC_DTPREL16_HI", /* 76 */ + "R_PPC_DTPREL16_HA", /* 77 */ + "R_PPC_DTPREL64", /* 78 */ + "R_PPC_GOT_TLSGD16", /* 79 */ + "R_PPC_GOT_TLSGD16_LO", /* 80 */ + "R_PPC_GOT_TLSGD16_HI", /* 81 */ + "R_PPC_GOT_TLSGD16_HA", /* 82 */ + "R_PPC_GOT_TLSLD16", /* 83 */ + "R_PPC_GOT_TLSLD16_LO", /* 84 */ + "R_PPC_GOT_TLSLD16_HI", /* 85 */ + "R_PPC_GOT_TLSLD16_HA", /* 86 */ + "R_PPC_GOT_TPREL16_DS", /* 87 */ + "R_PPC_GOT_TPREL16_LO", /* 88 */ + "R_PPC_GOT_TPREL16_HI", /* 89 */ + "R_PPC_GOT_TPREL16_HA", /* 90 */ + "R_PPC_GOT_DTPREL16", /* 91 */ + "R_PPC_GOT_DTPREL16_LO", /* 92 */ + "R_PPC_GOT_DTPREL16_HI", /* 93 */ + "R_PPC_GOT_DTPREL16_HA", /* 94 */ +}; + +/* PowerPC64 relocations defined by the ABIs */ +static char *reloc_type_names_PPC64[] = { + "R_PPC64_NONE", /* 00 */ + "R_PPC64_ADDR32", /* 01 */ + "R_PPC64_ADDR24", /* 02 */ + "R_PPC64_ADDR16", /* 03 */ + "R_PPC64_ADDR16_LO", /* 04 */ + "R_PPC64_ADDR16_HI", /* 05 */ + "R_PPC64_ADDR16_HA", /* 06 */ + "R_PPC64_ADDR14", /* 07 */ + "R_PPC64_ADDR14_BRTAKEN", /* 08 */ + "R_PPC64_ADDR14_BRNTAKEN", /* 09 */ + "R_PPC64_REL24", /* 10 */ + "R_PPC64_REL14", /* 11 */ + "R_PPC64_REL14_BRTAKEN", /* 12 */ + "R_PPC64_REL14_BRNTAKEN", /* 13 */ + "R_PPC64_GOT16", /* 14 */ + "R_PPC64_GOT16_LO", /* 15 */ + "R_PPC64_GOT16_HI", /* 16 */ + "R_PPC64_GOT16_HA", /* 17 */ + "R_PPC64_PLTREL24", /* 18 */ + "R_PPC64_COPY", /* 19 */ + "R_PPC64_GLOB_DAT", /* 20 */ + "R_PPC64_JMP_SLOT", /* 21 */ + "R_PPC64_RELATIVE", /* 22 */ + "R_PPC64_LOCAL24PC", /* 23 */ + "R_PPC64_UADDR32", /* 24 */ + "R_PPC64_UADDR16", /* 25 */ + "R_PPC64_REL32", /* 26 */ + "R_PPC64_PLT32", /* 27 */ + "R_PPC64_PLTREL32", /* 28 */ + "R_PPC64_PLT16_LO", /* 29 */ + "R_PPC64_PLT16_HI", /* 30 */ + "R_PPC64_PLT16_HA", /* 31 */ + "R_PPC64_SDAREL16", /* 32 */ + "R_PPC64_SECTOFF", /* 33 */ + "R_PPC64_SECTOFF_LO", /* 34 */ + "R_PPC64_SECTOFF_HI", /* 35 */ + "R_PPC64_SECTOFF_HA", /* 36 */ + "R_PPC64_REL30", /* 37 */ + "R_PPC64_ADDR64", /* 38 */ + "R_PPC64_ADDR16_HIGHER", /* 39 */ + "R_PPC64_ADDR16_HIGHERA", /* 40 */ + "R_PPC64_ADDR16_HIGHEST", /* 41 */ + "R_PPC64_ADDR16_HIGHESTA", /* 42 */ + "R_PPC64_UADDR64", /* 43 */ + "R_PPC64_REL64", /* 44 */ + "R_PPC64_PLT64", /* 45 */ + "R_PPC64_PLTREL64", /* 46 */ + "R_PPC64_TOC16", /* 47 */ + "R_PPC64_TOC16_LO", /* 48 */ + "R_PPC64_TOC16_HI", /* 49 */ + "R_PPC64_TOC16_HA", /* 50 */ + "R_PPC64_TOC", /* 51 */ + "R_PPC64_PLTGOT16", /* 52 */ + "R_PPC64_PLTGOT16_LO", /* 53 */ + "R_PPC64_PLTGOT16_HI", /* 54 */ + "R_PPC64_PLTGOT16_HA", /* 55 */ + "R_PPC64_ADDR16_DS", /* 56 */ + "R_PPC64_ADDR16_LO_DS", /* 57 */ + "R_PPC64_GOT16_DS", /* 58 */ + "R_PPC64_GOT16_LO_DS", /* 59 */ + "R_PPC64_PLT16_LO_DS", /* 60 */ + "R_PPC64_SECTOFF_DS", /* 61 */ + "R_PPC64_SECTOFF_LO_DS", /* 62 */ + "R_PPC64_TOC16_DS", /* 63 */ + "R_PPC64_TOC16_LO_DS", /* 64 */ + "R_PPC64_PLTGOT16_DS", /* 65 */ + "R_PPC64_PLTGOT16_LO_DS", /* 66 */ + "R_PPC64_TLS", /* 67 */ + "R_PPC64_DTPMOD32", /* 68 */ + "R_PPC64_TPREL16", /* 69 */ + "R_PPC64_TPREL16_LO", /* 70 */ + "R_PPC64_TPREL16_HI", /* 71 */ + "R_PPC64_TPREL16_HA", /* 72 */ + "R_PPC64_TPREL32", /* 73 */ + "R_PPC64_DTPREL16", /* 74 */ + "R_PPC64_DTPREL16_LO", /* 75 */ + "R_PPC64_DTPREL16_HI", /* 76 */ + "R_PPC64_DTPREL16_HA", /* 77 */ + "R_PPC64_DTPREL64", /* 78 */ + "R_PPC64_GOT_TLSGD16", /* 79 */ + "R_PPC64_GOT_TLSGD16_LO", /* 80 */ + "R_PPC64_GOT_TLSGD16_HI", /* 81 */ + "R_PPC64_GOT_TLSGD16_HA", /* 82 */ + "R_PPC64_GOT_TLSLD16", /* 83 */ + "R_PPC64_GOT_TLSLD16_LO", /* 84 */ + "R_PPC64_GOT_TLSLD16_HI", /* 85 */ + "R_PPC64_GOT_TLSLD16_HA", /* 86 */ + "R_PPC64_GOT_TPREL16_DS", /* 87 */ + "R_PPC64_GOT_TPREL16_LO", /* 88 */ + "R_PPC64_GOT_TPREL16_HI", /* 89 */ + "R_PPC64_GOT_TPREL16_HA", /* 90 */ + "R_PPC64_GOT_DTPREL16", /* 91 */ + "R_PPC64_GOT_DTPREL16_LO", /* 92 */ + "R_PPC64_GOT_DTPREL16_HI", /* 93 */ + "R_PPC64_GOT_DTPREL16_HA", /* 94 */ + "R_PPC64_TPREL16_DS", /* 95 */ + "R_PPC64_TPREL16_LO_DS", /* 96 */ + "R_PPC64_TPREL16_HIGHER", /* 97 */ + "R_PPC64_TPREL16_HIGHERA", /* 98 */ + "R_PPC64_TPREL16_HIGHEST", /* 99 */ + "R_PPC64_TPREL16_HIGHESTA", /* 100 */ + "R_PPC64_DTPREL16_DS", /* 101 */ + "R_PPC64_DTPREL16_LO_DS", /* 102 */ + "R_PPC64_DTPREL16_HIGHER", /* 103 */ + "R_PPC64_DTPREL16_HIGHERA", /* 104 */ + "R_PPC64_DTPREL16_HIGHEST", /* 105 */ + "R_PPC64_DTPREL16_HIGHESTA", /* 106 */ + "R_PPC64_TOC32", /* 107 */ + "R_PPC64_DTPMOD32", /* 108 */ + "R_PPC64_TPREL32", /* 109 */ + "R_PPC64_DTPREL32", /* 110 */ +}; + +/* Relocation types for MIPS */ +static char *reloc_type_names_MIPS[] = { + "R_MIPS_NONE", "R_MIPS_16", "R_MIPS_32", "R_MIPS_REL32", + "R_MIPS_26", "R_MIPS_HI16", "R_MIPS_LO16", "R_MIPS_GPREL16", + "R_MIPS_LITERAL", "R_MIPS_GOT16", "R_MIPS_PC16", "R_MIPS_CALL16", + "R_MIPS_GPREL32", /* 12 */ + "reloc type 13?", "reloc type 14?", "reloc type 15?", + "R_MIPS_SHIFT5", /* 16 */ + "R_MIPS_SHIFT6", /* 17 */ + "R_MIPS_64", /* 18 */ + "R_MIPS_GOT_DISP", /* 19 */ + "R_MIPS_GOT_PAGE", /* 20 */ + "R_MIPS_GOT_OFST", /* 21 */ + "R_MIPS_GOT_HI16", /* 22 */ + "R_MIPS_GOT_LO16", /* 23 */ + "R_MIPS_SUB", /* 24 */ + "R_MIPS_INSERT_A", /* 25 */ + "R_MIPS_INSERT_B", /* 26 */ + "R_MIPS_DELETE", /* 27 */ + "R_MIPS_HIGHER", /* 28 */ + "R_MIPS_HIGHEST", /* 29 */ + "R_MIPS_CALL_HI16", /* 30 */ + "R_MIPS_CALL_LO16", /* 31 */ + "R_MIPS_SCN_DISP", /* 32 */ + "R_MIPS_REL16", /* 33 */ + "R_MIPS_ADD_IMMEDIATE", /* 34 */ +}; + +/* ARM relocations defined by the ABIs */ +static char *reloc_type_names_ARM[] = { + "R_ARM_NONE", /* 00 */ + "R_ARM_PC24", /* 01 */ + "R_ARM_ABS32", /* 02 */ + "R_ARM_REL32", /* 03 */ + "R_ARM_LDR_PC_G0", /* 04 */ + "R_ARM_ABS16", /* 05 */ + "R_ARM_ABS12", /* 06 */ + "R_ARM_THM_ABS5", /* 07 */ + "R_ARM_ABS8", /* 08 */ + "R_ARM_SBREL32", /* 09 */ + "R_ARM_THM_CALL", /* 10 */ + "R_ARM_THM_PC8", /* 11 */ + "R_ARM_BREL_ADJ", /* 12 */ + "R_ARM_TLS_DESC", /* 13 */ + "R_ARM_THM_SWI8", /* 14 */ + "R_ARM_XPC25", /* 15 */ + "R_ARM_THM_XPC22", /* 16 */ + "R_ARM_TLS_DTPMOD32", /* 17 */ + "R_ARM_TLS_DTPOFF32", /* 18 */ + "R_ARM_TLS_TPOFF32", /* 19 */ + "R_ARM_COPY", /* 20 */ + "R_ARM_GLOB_DAT", /* 21 */ + "R_ARM_JUMP_SLOT", /* 22 */ + "R_ARM_RELATIVE", /* 23 */ + "R_ARM_GOTOFF32", /* 24 */ + "R_ARM_BASE_PREL", /* 25 */ + "R_ARM_GOT_BREL", /* 26 */ + "R_ARM_PLT32", /* 27 */ + "R_ARM_CALL", /* 28 */ + "R_ARM_JUMP24", /* 29 */ + "R_ARM_THM_JUMP24", /* 30 */ + "R_ARM_BASE_ABS", /* 31 */ + "R_ARM_ALU_PCREL_7_0", /* 32 */ + "R_ARM_ALU_PCREL_15_8", /* 33 */ + "R_ARM_ALU_PCREL_23_15", /* 34 */ + "R_ARM_LDR_SBREL_11_0_NC", /* 35 */ + "R_ARM_ALU_SBREL_19_12_NC", /* 36 */ + "R_ARM_ALU_SBREL_27_20_CK", /* 37 */ + "R_ARM_TARGET1", /* 38 */ + "R_ARM_SBREL31", /* 39 */ + "R_ARM_V4BX", /* 40 */ + "R_ARM_TARGET2", /* 41 */ + "R_ARM_PREL31", /* 42 */ + "R_ARM_MOVW_ABS_NC", /* 43 */ + "R_ARM_MOVT_ABS", /* 44 */ + "R_ARM_MOVW_PREL_NC", /* 45 */ + "R_ARM_MOVT_PREL", /* 46 */ + "R_ARM_THM_MOVW_ABS_NC", /* 47 */ + "R_ARM_THM_MOVT_ABS", /* 48 */ + "R_ARM_THM_MOVW_PREL_NC", /* 49 */ + "R_ARM_THM_MOVT_PREL", /* 50 */ + "R_ARM_THM_JUMP19", /* 51 */ + "R_ARM_THM_JUMP6", /* 52 */ + "R_ARM_THM_ALU_PREL_11_0", /* 53 */ + "R_ARM_THM_PC12", /* 54 */ + "R_ARM_ABS32_NOI", /* 55 */ + "R_ARM_REL32_NOI", /* 56 */ + "R_ARM_ALU_PC_G0_NC", /* 57 */ + "R_ARM_ALU_PC_G0", /* 58 */ + "R_ARM_ALU_PC_G1_NC", /* 59 */ + "R_ARM_ALU_PC_G1", /* 60 */ + "R_ARM_ALU_PC_G2", /* 61 */ + "R_ARM_LDR_PC_G1", /* 62 */ + "R_ARM_LDR_PC_G2", /* 63 */ + "R_ARM_LDRS_PC_G0", /* 64 */ + "R_ARM_LDRS_PC_G1", /* 65 */ + "R_ARM_LDRS_PC_G2", /* 66 */ + "R_ARM_LDC_PC_G0", /* 67 */ + "R_ARM_LDC_PC_G1", /* 68 */ + "R_ARM_LDC_PC_G2", /* 69 */ + "R_ARM_ALU_SB_G0_NC", /* 70 */ + "R_ARM_ALU_SB_G0", /* 71 */ + "R_ARM_ALU_SB_G1_NC", /* 72 */ + "R_ARM_ALU_SB_G1", /* 73 */ + "R_ARM_ALU_SB_G2", /* 74 */ + "R_ARM_LDR_SB_G0", /* 75 */ + "R_ARM_LDR_SB_G1", /* 76 */ + "R_ARM_LDR_SB_G2", /* 77 */ + "R_ARM_LDRS_SB_G0", /* 78 */ + "R_ARM_LDRS_SB_G1", /* 79 */ + "R_ARM_LDRS_SB_G2", /* 80 */ + "R_ARM_LDC_SB_G0", /* 81 */ + "R_ARM_LDC_SB_G1", /* 82 */ + "R_ARM_LDC_SB_G2", /* 83 */ + "R_ARM_MOVW_BREL_NC", /* 84 */ + "R_ARM_MOVT_BREL", /* 85 */ + "R_ARM_MOVW_BREL", /* 86 */ + "R_ARM_THM_MOVW_BREL_NC", /* 87 */ + "R_ARM_THM_MOVT_BREL", /* 88 */ + "R_ARM_THM_MOVW_BREL", /* 89 */ + "R_ARM_TLS_GOTDESC", /* 90 */ + "R_ARM_TLS_CALL", /* 91 */ + "R_ARM_TLS_DESCSEQ", /* 92 */ + "R_ARM_THM_TLS_CALL", /* 93 */ + "R_ARM_PLT32_ABS", /* 94 */ + "R_ARM_GOT_ABS", /* 95 */ + "R_ARM_GOT_PREL", /* 96 */ + "R_ARM_GOT_BREL12", /* 97 */ + "R_ARM_GOTOFF12", /* 98 */ + "R_ARM_GOTRELAX", /* 99 */ + "R_ARM_GNU_VTENTRY", /* 100 */ + "R_ARM_GNU_VTINHERIT", /* 101 */ + "R_ARM_THM_JUMP11", /* 102 */ + "R_ARM_THM_JUMP8", /* 103 */ + "R_ARM_TLS_GD32", /* 104 */ + "R_ARM_TLS_LDM32", /* 105 */ + "R_ARM_TLS_LDO32", /* 106 */ + "R_ARM_TLS_IE32", /* 107 */ + "R_ARM_TLS_LE32", /* 108 */ + "R_ARM_TLS_LDO12", /* 109 */ + "R_ARM_TLS_LE12", /* 110 */ + "R_ARM_TLS_IE12GP", /* 111 */ + "R_ARM_TLS_MOVT_TPOFF32", /* 112 */ /* "R_ARM_PRIVATE_0" */ + "R_ARM_TLS_MOVW_TPOFF32", /* 113 */ /* "R_ARM_PRIVATE_1" */ + "R_ARM_THM_TLS_MOVT_TPOFF32", /* 114 */ /* "R_ARM_PRIVATE_2" */ + "R_ARM_THM_TLS_MOVT_TPOFF32", /* 115 */ /* "R_ARM_PRIVATE_3" */ + "R_ARM_PRIVATE_4", /* 116 */ + "R_ARM_PRIVATE_5", /* 117 */ + "R_ARM_PRIVATE_6", /* 118 */ + "R_ARM_PRIVATE_7", /* 119 */ + "R_ARM_PRIVATE_8", /* 120 */ + "R_ARM_PRIVATE_9", /* 121 */ + "R_ARM_PRIVATE_10", /* 122 */ + "R_ARM_PRIVATE_11", /* 123 */ + "R_ARM_PRIVATE_12", /* 124 */ + "R_ARM_PRIVATE_13", /* 125 */ + "R_ARM_PRIVATE_14", /* 126 */ + "R_ARM_PRIVATE_15", /* 127 */ + "R_ARM_ME_TOO", /* 128 */ + "R_ARM_THM_TLS_DESCSEQ16", /* 129 */ + "R_ARM_THM_TLS_DESCSEQ32", /* 130 */ +}; + +/* Record the relocation table name information */ +static char **reloc_type_names = NULL; +static Dwarf_Small number_of_reloc_type_names = 0; + +/* Set the relocation names based on the machine type */ +static void +set_relocation_table_names(Dwarf_Small machine_type) +{ + switch (machine_type) { + case EM_MIPS: + reloc_type_names = reloc_type_names_MIPS; + number_of_reloc_type_names = + sizeof(reloc_type_names_MIPS) / sizeof(char *); + break; + case EM_PPC: + reloc_type_names = reloc_type_names_PPC; + number_of_reloc_type_names = + sizeof(reloc_type_names_PPC) / sizeof(char *); + break; + case EM_PPC64: + reloc_type_names = reloc_type_names_PPC64; + number_of_reloc_type_names = + sizeof(reloc_type_names_PPC64) / sizeof(char *); + break; + case EM_ARM: + reloc_type_names = reloc_type_names_ARM; + number_of_reloc_type_names = + sizeof(reloc_type_names_ARM) / sizeof(char *); + break; + default: + /* We don't have others covered. */ + reloc_type_names = 0; + number_of_reloc_type_names = 0; + break; + } +} + +/* + Return valid reloc type names. + If buf is used, it is static, so beware: it + will be overwritten by the next call. +*/ +static char * +get_reloc_type_names(int index) +{ + static char buf[100]; + char *retval = 0; + + if (index < 0 || index >= number_of_reloc_type_names) { + sprintf(buf, "reloc type %d unknown", (int) index); + retval = buf; + } else { + retval = reloc_type_names[index]; + } + return retval; +} + +#ifndef HAVE_ELF64_GETEHDR +#define Elf64_Addr long +#define Elf64_Word unsigned long +#define Elf64_Xword unsigned long +#define Elf64_Sym long +#endif + +static struct { + Dwarf_Small *buf; + Dwarf_Unsigned size; + Dwarf_Bool display; /* Display reloc if TRUE */ + const char *name; /* Section name */ + Elf64_Xword type; /* To cover 32 and 64 records types */ +} sect_data[DW_SECTION_REL_DEBUG_NUM]; + + +typedef size_t indx_type; + +typedef struct { + indx_type indx; + char *name; + Elf32_Addr value; + Elf32_Word size; + int type; + int bind; + unsigned char other; + Elf32_Half shndx; +} SYM; + + +typedef struct { + indx_type indx; + char *name; + Elf64_Addr value; + Elf64_Xword size; + int type; + int bind; + unsigned char other; + unsigned short shndx; +} SYM64; + +static void print_reloc_information_64(int section_no, + Dwarf_Small * buf, + Dwarf_Unsigned size, + Elf64_Xword type, + char **scn_names,int scn_names_count); +static void print_reloc_information_32(int section_no, + Dwarf_Small * buf, + Dwarf_Unsigned size, + Elf64_Xword type, + char **scn_names,int scn_names_count); +static SYM *readsyms(Elf32_Sym * data, size_t num, Elf * elf, + Elf32_Word link); +static SYM64 *read_64_syms(Elf64_Sym * data, size_t num, Elf * elf, + Elf64_Word link); +static void *get_scndata(Elf_Scn * fd_scn, size_t * scn_size); +static void print_relocinfo_64(Dwarf_Debug dbg, Elf * elf); +static void print_relocinfo_32(Dwarf_Debug dbg, Elf * elf); + +static SYM *sym_data; +static SYM64 *sym_data_64; +static long sym_data_entry_count; +static long sym_data_64_entry_count; + +typedef struct { + indx_type index; + char *name_rel; /* .rel.debug_* names */ + char *name_rela; /* .rela.debug_* names */ +} REL_INFO; + +/* If the incoming scn_name is known, record the name + in our reloc section names table. + For a given (debug) section there can be a .rel or a .rela, + not both. + The name-to-index in this table is fixed, invariant. + It has to match other tables like +*/ +static int +get_reloc_section(Dwarf_Debug dbg, + Elf_Scn *scn, + char *scn_name, + Elf64_Word sh_type) +{ + static REL_INFO rel_info[DW_SECTION_REL_DEBUG_NUM] = { + {/*0*/ DW_SECTION_REL_DEBUG_INFO, + DW_SECTNAME_REL_DEBUG_INFO, + DW_SECTNAME_RELA_DEBUG_INFO}, + + {/*1*/ DW_SECTION_REL_DEBUG_LINE, + DW_SECTNAME_REL_DEBUG_LINE, + DW_SECTNAME_RELA_DEBUG_LINE}, + + {/*2*/ DW_SECTION_REL_DEBUG_PUBNAMES, + DW_SECTNAME_REL_DEBUG_PUBNAMES, + DW_SECTNAME_RELA_DEBUG_PUBNAMES}, + + {/*3*/ DW_SECTION_REL_DEBUG_ABBREV, + DW_SECTNAME_REL_DEBUG_ABBREV, + DW_SECTNAME_RELA_DEBUG_ABBREV}, + + {/*4*/ DW_SECTION_REL_DEBUG_ARANGES, + DW_SECTNAME_REL_DEBUG_ARANGES, + DW_SECTNAME_RELA_DEBUG_ARANGES}, + + {/*5*/ DW_SECTION_REL_DEBUG_FRAME, + DW_SECTNAME_REL_DEBUG_FRAME, + DW_SECTNAME_RELA_DEBUG_FRAME}, + + {/*6*/ DW_SECTION_REL_DEBUG_LOC, + DW_SECTNAME_REL_DEBUG_LOC, + DW_SECTNAME_RELA_DEBUG_LOC}, + + {/*7*/ DW_SECTION_REL_DEBUG_RANGES, + DW_SECTNAME_REL_DEBUG_RANGES, + DW_SECTNAME_RELA_DEBUG_RANGES}, + + {/*8*/ DW_SECTION_REL_DEBUG_TYPES, + DW_SECTNAME_REL_DEBUG_TYPES, + DW_SECTNAME_RELA_DEBUG_TYPES}, + }; + + Elf_Data *data; + int index; + for (index = 0; index < DW_SECTION_REL_DEBUG_NUM; ++index) { + const char *n = rel_info[index].name_rel; + const char *na = rel_info[index].name_rela; + if (strcmp(scn_name, n) == 0) { + SECT_DATA_SET(rel_info[index].index,sh_type,n) + return TRUE; + } + if (strcmp(scn_name, na) == 0) { + SECT_DATA_SET(rel_info[index].index,sh_type,na) + return TRUE; + } + } + return FALSE; +} + +void +print_relocinfo(Dwarf_Debug dbg, unsigned reloc_map) +{ + Elf *elf; + char *endr_ident; + int is_64bit; + int res; + int i; + + for (i = 0; i < DW_SECTION_REL_DEBUG_NUM; i++) { + sect_data[i].display = reloc_map & (1 << i); + sect_data[i].buf = 0; + sect_data[i].size = 0; + sect_data[i].type = SHT_NULL; + } + res = dwarf_get_elf(dbg, &elf, &err); + if (res != DW_DLV_OK) { + print_error(dbg, "dwarf_get_elf error", res, err); + } + if ((endr_ident = elf_getident(elf, NULL)) == NULL) { + print_error(dbg, "DW_ELF_GETIDENT_ERROR", res, err); + } + is_64bit = (endr_ident[EI_CLASS] == ELFCLASS64); + if (is_64bit) { + print_relocinfo_64(dbg, elf); + } else { + print_relocinfo_32(dbg, elf); + } +} + +static void +print_relocinfo_64(Dwarf_Debug dbg, Elf * elf) +{ +#ifdef HAVE_ELF64_GETEHDR + Elf_Scn *scn = NULL; + Elf64_Ehdr *ehdr64 = 0; + Elf64_Shdr *shdr64 = 0; + char *scn_name = 0; + int i = 0; + Elf64_Sym *sym_64 = 0; + char **scn_names = 0; + int scn_names_cnt = 0; + + ehdr64 = elf64_getehdr(elf); + if (ehdr64 == NULL) { + print_error(dbg, "DW_ELF_GETEHDR_ERROR", DW_DLV_OK, err); + } + + /* Make the section name array big enough + that we don't need to check for overrun in the loop. */ + scn_names = (char **)calloc(ehdr64->e_shnum + 1, sizeof(char *)); + + while ((scn = elf_nextscn(elf, scn)) != NULL) { + + shdr64 = elf64_getshdr(scn); + if (shdr64 == NULL) { + print_error(dbg, "DW_ELF_GETSHDR_ERROR", DW_DLV_OK, err); + } + scn_name = elf_strptr(elf, ehdr64->e_shstrndx, shdr64->sh_name); + if (scn_name == NULL) { + print_error(dbg, "DW_ELF_STRPTR_ERROR", DW_DLV_OK, err); + } + + if (scn_names) { + /* elf_nextscn() skips section with index '0' */ + scn_names[++scn_names_cnt] = scn_name; + } + if (shdr64->sh_type == SHT_SYMTAB) { + size_t sym_size = 0; + size_t count = 0; + + sym_64 = (Elf64_Sym *) get_scndata(scn, &sym_size); + if (sym_64 == NULL) { + print_error(dbg, "no symbol table data", DW_DLV_OK, + err); + } + count = sym_size / sizeof(Elf64_Sym); + sym_64++; + free(sym_data_64); + sym_data_64 = read_64_syms(sym_64, count, elf, shdr64->sh_link); + sym_data_64_entry_count = count; + if (sym_data_64 == NULL) { + print_error(dbg, "problem reading symbol table data", + DW_DLV_OK, err); + } + } else if (!get_reloc_section(dbg,scn,scn_name,shdr64->sh_type)) { + continue; + } + } /* while */ + + /* Set the relocation names based on the machine type */ + set_relocation_table_names(ehdr64->e_machine); + + for (i = 0; i < DW_SECTION_REL_DEBUG_NUM; i++) { + if (sect_data[i].display && + sect_data[i].buf != NULL && + sect_data[i].size > 0) { + print_reloc_information_64(i, sect_data[i].buf, + sect_data[i].size, sect_data[i].type,scn_names, + scn_names_cnt); + } + } + + if (scn_names) { + free(scn_names); + scn_names = 0; + scn_names_cnt = 0; + } +#endif +} + +static void +print_relocinfo_32(Dwarf_Debug dbg, Elf * elf) +{ + Elf_Scn *scn = NULL; + Elf32_Ehdr *ehdr32 = 0; + Elf32_Shdr *shdr32 = 0; + char *scn_name = 0; + int i = 0; + Elf32_Sym *sym = 0; + char **scn_names = 0; + int scn_names_cnt = 0; + + ehdr32 = elf32_getehdr(elf); + if (ehdr32 == NULL) { + print_error(dbg, "DW_ELF_GETEHDR_ERROR", DW_DLV_OK, err); + } + + /* Make the section name array big enough + that we don't need to check for overrun in the loop. */ + scn_names = (char **)calloc(ehdr32->e_shnum + 1, sizeof(char *)); + + while ((scn = elf_nextscn(elf, scn)) != NULL) { + shdr32 = elf32_getshdr(scn); + if (shdr32 == NULL) { + print_error(dbg, "DW_ELF_GETSHDR_ERROR", DW_DLV_OK, err); + } + scn_name = elf_strptr(elf, ehdr32->e_shstrndx, shdr32->sh_name); + if (scn_name == NULL) { + print_error(dbg, "DW_ELF_STRPTR_ERROR", DW_DLV_OK, err); + } + + if (scn_names) { + /* elf_nextscn() skips section with index '0' */ + scn_names[++scn_names_cnt] = scn_name; + } + + if (shdr32->sh_type == SHT_SYMTAB) { + size_t sym_size = 0; + size_t count = 0; + + sym = (Elf32_Sym *) get_scndata(scn, &sym_size); + if (sym == NULL) { + print_error(dbg, "no symbol table data", DW_DLV_OK, + err); + } + sym = (Elf32_Sym *) get_scndata(scn, &sym_size); + count = sym_size / sizeof(Elf32_Sym); + sym++; + free(sym_data); + sym_data = readsyms(sym, count, elf, shdr32->sh_link); + sym_data_entry_count = count; + if (sym_data == NULL) { + print_error(dbg, "problem reading symbol table data", + DW_DLV_OK, err); + } + } else if (!get_reloc_section(dbg,scn,scn_name,shdr32->sh_type)) { + continue; + } + } /* End while. */ + + /* Set the relocation names based on the machine type */ + set_relocation_table_names(ehdr32->e_machine); + + for (i = 0; i < DW_SECTION_REL_DEBUG_NUM; i++) { + if (sect_data[i].display && + sect_data[i].buf != NULL && + sect_data[i].size > 0) { + print_reloc_information_32(i, sect_data[i].buf, + sect_data[i].size,sect_data[i].type,scn_names, + scn_names_cnt); + } + } + + if (scn_names) { + free(scn_names); + scn_names = 0; + scn_names_cnt = 0; + } +} + +#if HAVE_ELF64_R_INFO +#ifndef ELF64_R_TYPE +#define ELF64_R_TYPE(x) 0 /* FIXME */ +#endif +#ifndef ELF64_R_SYM +#define ELF64_R_SYM(x) 0 /* FIXME */ +#endif +#ifndef ELF64_ST_TYPE +#define ELF64_ST_TYPE(x) 0 /* FIXME */ +#endif +#ifndef ELF64_ST_BIND +#define ELF64_ST_BIND(x) 0 /* FIXME */ +#endif +#endif /* HAVE_ELF64_R_INFO */ + + +static void +print_reloc_information_64(int section_no, Dwarf_Small * buf, + Dwarf_Unsigned size, Elf64_Xword type, + char **scn_names, int scn_names_count) +{ + /* Include support for Elf64_Rel and Elf64_Rela */ + Dwarf_Unsigned add = 0; + Dwarf_Half rel_size = SHT_RELA == type ? + sizeof(Elf64_Rela) : sizeof(Elf64_Rel); + Dwarf_Unsigned off = 0; + + printf("\n%s:\n", type== SHT_RELA?sectnamesa[section_no]: + sectnames[section_no]); + + /* Print some headers and change the order for better reading */ + printf("Offset Addend %-26s Index Symbol Name\n","Reloc Type"); + +#if HAVE_ELF64_GETEHDR + for (off = 0; off < size; off += rel_size) { +#if HAVE_ELF64_R_INFO + /* This works for the Elf64_Rel in linux */ + Elf64_Rel *p = (Elf64_Rel *) (buf + off); + char *name = 0; + if(sym_data ) { + size_t index = ELF64_R_SYM(p->r_info) - 1; + if(index < sym_data_entry_count) { + name = sym_data[index].name; + } + } else if (sym_data_64) { + size_t index = ELF64_R_SYM(p->r_info) - 1; + if(index < sym_data_64_entry_count) { + name = sym_data_64[index].name; + } + } + + /* When the name is not available, use the + section name as a reference for the name.*/ + if (!name || !name[0]) { + size_t index = ELF64_R_SYM(p->r_info) - 1; + if(index < sym_data_64_entry_count) { + SYM64 *sym_64 = &sym_data_64[index]; + if (sym_64->type == STT_SECTION && + sym_64->shndx < scn_names_count) { + name = scn_names[sym_64->shndx]; + } + } + } + if(!name || !name[0]) { + name = "<no name>"; + } + + if (SHT_RELA == type) { + Elf64_Rela *pa = (Elf64_Rela *)p; + add = pa->r_addend; + } + + printf("0x%08lx 0x%08lx %-26s <%5ld> %s\n", + (unsigned long int) (p->r_offset), + (unsigned long int) (add), + get_reloc_type_names(ELF64_R_TYPE(p->r_info)), + (long)ELF64_R_SYM(p->r_info), + name); +#else + /* sgi/mips -64 does not have r_info in the 64bit relocations, + but seperate fields, with 3 types, actually. Only one of + which prints here, as only one really used with dwarf */ + Elf64_Rel *p = (Elf64_Rel *) (buf + off); + char *name = 0; + if(sym_data ) { + size_t index = p->r_sym - 1; + if(index < sym_data_entry_count) { + name = sym_data[index].name; + } + } else if (sym_data_64) { + size_t index = p->r_sym - 1; + if(index < sym_data_64_entry_count) { + name = sym_data_64[index].name; + } + } + if(!name || !name[0]) { + name = "<no name>"; + } + printf("%5" DW_PR_DUu " %-26s <%3ld> %s\n", + (Dwarf_Unsigned) (p->r_offset), + get_reloc_type_names(p->r_type), + (long)p->r_sym, + name); +#endif + } +#endif /* HAVE_ELF64_GETEHDR */ +} + +static void +print_reloc_information_32(int section_no, Dwarf_Small * buf, + Dwarf_Unsigned size, Elf64_Xword type, char **scn_names, + int scn_names_count) +{ + /* Include support for Elf32_Rel and Elf32_Rela */ + Dwarf_Unsigned add = 0; + Dwarf_Half rel_size = SHT_RELA == type ? + sizeof(Elf32_Rela) : sizeof(Elf32_Rel); + Dwarf_Unsigned off = 0; + + printf("\n%s:\n", type== SHT_RELA?sectnamesa[section_no]: + sectnames[section_no]); + + + /* Print some headers and change the order for better reading. */ + printf("Offset Addend %-26s Index Symbol Name\n","Reloc Type"); + + for (off = 0; off < size; off += rel_size) { + Elf32_Rel *p = (Elf32_Rel *) (buf + off); + char *name = 0; + + if(sym_data) { + size_t index = ELF32_R_SYM(p->r_info) - 1; + if(index < sym_data_entry_count) { + name = sym_data[index].name; + } + } + + /* When the name is not available, use the + section name as a reference for the name. */ + if (!name || !name[0]) { + size_t index = ELF32_R_SYM(p->r_info) - 1; + if(index < sym_data_entry_count) { + SYM *sym = &sym_data[index]; + if (sym->type == STT_SECTION&& + sym->shndx < scn_names_count) { + name = scn_names[sym->shndx]; + } + } + } + if(!name || !name[0]) { + name = "<no name>"; + } + if (SHT_RELA == type) { + Elf32_Rela *pa = (Elf32_Rela *)p; + add = pa->r_addend; + } + printf("0x%08lx 0x%08lx %-26s <%5ld> %s\n", + (unsigned long int) (p->r_offset), + (unsigned long int) (add), + get_reloc_type_names(ELF32_R_TYPE(p->r_info)), + (long)ELF32_R_SYM(p->r_info), + name); + } +} + +static SYM * +readsyms(Elf32_Sym * data, size_t num, Elf * elf, Elf32_Word link) +{ + SYM *s, *buf; + indx_type i; + + buf = (SYM *) calloc(num, sizeof(SYM)); + if (buf == NULL) { + return NULL; + } + s = buf; /* save pointer to head of array */ + for (i = 1; i < num; i++, data++, buf++) { + buf->indx = i; + buf->name = (char *) elf_strptr(elf, link, data->st_name); + buf->value = data->st_value; + buf->size = data->st_size; + buf->type = ELF32_ST_TYPE(data->st_info); + buf->bind = ELF32_ST_BIND(data->st_info); + buf->other = data->st_other; + buf->shndx = data->st_shndx; + } /* end for loop */ + return (s); +} + +static SYM64 * +read_64_syms(Elf64_Sym * data, size_t num, Elf * elf, Elf64_Word link) +{ +#ifdef HAVE_ELF64_GETEHDR + + SYM64 *s, *buf; + indx_type i; + + buf = (SYM64 *) calloc(num, sizeof(SYM64)); + if (buf == NULL) { + return NULL; + } + s = buf; /* save pointer to head of array */ + for (i = 1; i < num; i++, data++, buf++) { + buf->indx = i; + buf->name = (char *) elf_strptr(elf, link, data->st_name); + buf->value = data->st_value; + buf->size = data->st_size; + buf->type = ELF64_ST_TYPE(data->st_info); + buf->bind = ELF64_ST_BIND(data->st_info); + buf->other = data->st_other; + buf->shndx = data->st_shndx; + } /* end for loop */ + return (s); +#else + return 0; +#endif /* HAVE_ELF64_GETEHDR */ +} + +static void * +get_scndata(Elf_Scn * fd_scn, size_t * scn_size) +{ + Elf_Data *p_data; + + p_data = 0; + if ((p_data = elf_getdata(fd_scn, p_data)) == 0 || + p_data->d_size == 0) { + return NULL; + } + *scn_size = p_data->d_size; + return (p_data->d_buf); +} + +/* Cleanup of malloc space (some of the pointers will be 0 here) + so dwarfdump looks 'clean' to a malloc checker. +*/ +void +clean_up_syms_malloc_data() +{ + free(sym_data); + sym_data = 0; + free(sym_data_64); + sym_data_64 = 0; + sym_data_64_entry_count = 0; + sym_data_entry_count = 0; +} diff --git a/dwarfdump/print_reloc.h b/dwarfdump/print_reloc.h new file mode 100644 index 0000000..d511b71 --- /dev/null +++ b/dwarfdump/print_reloc.h @@ -0,0 +1,307 @@ +/*
+ Copyright (C) 2000,2004,2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
+ Portions Copyright (C) 2011 SN Systems Ltd. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_reloc.c,v 1.11 2005/08/04 05:09:37 davea Exp $ */
+
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+/* PowerPC relocations defined by the ABIs */
+#define R_PPC_NONE 0
+#define R_PPC_ADDR32 1 /* 32bit absolute address */
+#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */
+#define R_PPC_ADDR16 3 /* 16bit absolute address */
+#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */
+#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */
+#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */
+#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */
+#define R_PPC_ADDR14_BRTAKEN 8
+#define R_PPC_ADDR14_BRNTAKEN 9
+#define R_PPC_REL24 10 /* PC relative 26 bit */
+#define R_PPC_REL14 11 /* PC relative 16 bit */
+#define R_PPC_REL14_BRTAKEN 12
+#define R_PPC_REL14_BRNTAKEN 13
+#define R_PPC_GOT16 14
+#define R_PPC_GOT16_LO 15
+#define R_PPC_GOT16_HI 16
+#define R_PPC_GOT16_HA 17
+#define R_PPC_PLTREL24 18
+#define R_PPC_COPY 19
+#define R_PPC_GLOB_DAT 20
+#define R_PPC_JMP_SLOT 21
+#define R_PPC_RELATIVE 22
+#define R_PPC_LOCAL24PC 23
+#define R_PPC_UADDR32 24
+#define R_PPC_UADDR16 25
+#define R_PPC_REL32 26
+#define R_PPC_PLT32 27
+#define R_PPC_PLTREL32 28
+#define R_PPC_PLT16_LO 29
+#define R_PPC_PLT16_HI 30
+#define R_PPC_PLT16_HA 31
+#define R_PPC_SDAREL16 32
+#define R_PPC_SECTOFF 33
+#define R_PPC_SECTOFF_LO 34
+#define R_PPC_SECTOFF_HI 35
+#define R_PPC_SECTOFF_HA 36
+
+/* Unused types */
+#define R_PPC_37 37
+#define R_PPC_38 38
+#define R_PPC_39 39
+#define R_PPC_40 40
+#define R_PPC_41 41
+#define R_PPC_42 42
+#define R_PPC_43 43
+#define R_PPC_44 44
+#define R_PPC_45 45
+#define R_PPC_46 46
+#define R_PPC_47 47
+#define R_PPC_48 48
+#define R_PPC_49 49
+#define R_PPC_50 50
+#define R_PPC_51 51
+#define R_PPC_52 52
+#define R_PPC_53 53
+#define R_PPC_54 54
+#define R_PPC_55 55
+
+/* Unused types */
+#define R_PPC_56 56
+#define R_PPC_57 57
+#define R_PPC_58 58
+#define R_PPC_59 59
+#define R_PPC_60 60
+#define R_PPC_61 61
+#define R_PPC_62 62
+#define R_PPC_63 63
+#define R_PPC_64 64
+#define R_PPC_65 65
+#define R_PPC_66 66
+
+/* PowerPC relocations defined for the TLS access ABI. */
+#define R_PPC_TLS 67 /* none (sym+add)@tls */
+#define R_PPC_DTPMOD32 68 /* word32 (sym+add)@dtpmod */
+#define R_PPC_TPREL16 69 /* half16* (sym+add)@tprel */
+#define R_PPC_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */
+#define R_PPC_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */
+#define R_PPC_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */
+#define R_PPC_TPREL32 73 /* word32 (sym+add)@tprel */
+#define R_PPC_DTPREL16 74 /* half16* (sym+add)@dtprel */
+#define R_PPC_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */
+#define R_PPC_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */
+#define R_PPC_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */
+#define R_PPC_DTPREL32 78 /* word32 (sym+add)@dtprel */
+#define R_PPC_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */
+#define R_PPC_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */
+#define R_PPC_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */
+#define R_PPC_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */
+#define R_PPC_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */
+#define R_PPC_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */
+#define R_PPC_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */
+#define R_PPC_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */
+#define R_PPC_GOT_TPREL16 87 /* half16* (sym+add)@got@tprel */
+#define R_PPC_GOT_TPREL16_LO 88 /* half16 (sym+add)@got@tprel@l */
+#define R_PPC_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */
+#define R_PPC_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */
+#define R_PPC_GOT_DTPREL16 91 /* half16* (sym+add)@got@dtprel */
+#define R_PPC_GOT_DTPREL16_LO 92 /* half16* (sym+add)@got@dtprel@l */
+#define R_PPC_GOT_DTPREL16_HI 93 /* half16* (sym+add)@got@dtprel@h */
+#define R_PPC_GOT_DTPREL16_HA 94 /* half16* (sym+add)@got@dtprel@ha */
+
+/* Keep this the last entry. */
+#define R_PPC_NUM 95
+
+/* PowerPC64 relocations defined by the ABIs */
+#define R_PPC64_NONE R_PPC_NONE
+#define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address. */
+#define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned. */
+#define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address. */
+#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of abs. address. */
+#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of abs. address. */
+#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */
+#define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned. */
+#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN
+#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN
+#define R_PPC64_REL24 R_PPC_REL24 /* PC relative 26 bit, word aligned. */
+#define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit. */
+#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN
+#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN
+#define R_PPC64_GOT16 R_PPC_GOT16
+#define R_PPC64_GOT16_LO R_PPC_GOT16_LO
+#define R_PPC64_GOT16_HI R_PPC_GOT16_HI
+#define R_PPC64_GOT16_HA R_PPC_GOT16_HA
+
+#define R_PPC64_COPY R_PPC_COPY
+#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT
+#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT
+#define R_PPC64_RELATIVE R_PPC_RELATIVE
+
+#define R_PPC64_UADDR32 R_PPC_UADDR32
+#define R_PPC64_UADDR16 R_PPC_UADDR16
+#define R_PPC64_REL32 R_PPC_REL32
+#define R_PPC64_PLT32 R_PPC_PLT32
+#define R_PPC64_PLTREL32 R_PPC_PLTREL32
+#define R_PPC64_PLT16_LO R_PPC_PLT16_LO
+#define R_PPC64_PLT16_HI R_PPC_PLT16_HI
+#define R_PPC64_PLT16_HA R_PPC_PLT16_HA
+
+#define R_PPC64_SECTOFF R_PPC_SECTOFF
+#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO
+#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI
+#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA
+#define R_PPC64_ADDR30 37 /* word30 (S + A - P) >> 2. */
+#define R_PPC64_ADDR64 38 /* doubleword64 S + A. */
+#define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A). */
+#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A). */
+#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A). */
+#define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A). */
+#define R_PPC64_UADDR64 43 /* doubleword64 S + A. */
+#define R_PPC64_REL64 44 /* doubleword64 S + A - P. */
+#define R_PPC64_PLT64 45 /* doubleword64 L + A. */
+#define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P. */
+#define R_PPC64_TOC16 47 /* half16* S + A - .TOC. */
+#define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.). */
+#define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.). */
+#define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.). */
+#define R_PPC64_TOC 51 /* doubleword64 .TOC. */
+#define R_PPC64_PLTGOT16 52 /* half16* M + A. */
+#define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A). */
+#define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A). */
+#define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A). */
+
+#define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2. */
+#define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2. */
+#define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2. */
+#define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2. */
+#define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2. */
+#define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2. */
+#define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2. */
+#define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2. */
+#define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2. */
+#define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2. */
+#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2. */
+
+/* PowerPC64 relocations defined for the TLS access ABI. */
+#define R_PPC64_TLS 67 /* none (sym+add)@tls */
+#define R_PPC64_DTPMOD64 68 /* doubleword64 (sym+add)@dtpmod */
+#define R_PPC64_TPREL16 69 /* half16* (sym+add)@tprel */
+#define R_PPC64_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */
+#define R_PPC64_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */
+#define R_PPC64_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */
+#define R_PPC64_TPREL64 73 /* doubleword64 (sym+add)@tprel */
+#define R_PPC64_DTPREL16 74 /* half16* (sym+add)@dtprel */
+#define R_PPC64_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */
+#define R_PPC64_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */
+#define R_PPC64_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */
+#define R_PPC64_DTPREL64 78 /* doubleword64 (sym+add)@dtprel */
+#define R_PPC64_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */
+#define R_PPC64_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */
+#define R_PPC64_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */
+#define R_PPC64_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */
+#define R_PPC64_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */
+#define R_PPC64_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */
+#define R_PPC64_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */
+#define R_PPC64_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */
+#define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got@tprel */
+#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got@tprel@l */
+#define R_PPC64_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */
+#define R_PPC64_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */
+#define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds* (sym+add)@got@dtprel */
+#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got@dtprel@l */
+#define R_PPC64_GOT_DTPREL16_HI 93 /* half16 (sym+add)@got@dtprel@h */
+#define R_PPC64_GOT_DTPREL16_HA 94 /* half16 (sym+add)@got@dtprel@ha */
+#define R_PPC64_TPREL16_DS 95 /* half16ds* (sym+add)@tprel */
+#define R_PPC64_TPREL16_LO_DS 96 /* half16ds (sym+add)@tprel@l */
+#define R_PPC64_TPREL16_HIGHER 97 /* half16 (sym+add)@tprel@higher */
+#define R_PPC64_TPREL16_HIGHERA 98 /* half16 (sym+add)@tprel@highera */
+#define R_PPC64_TPREL16_HIGHEST 99 /* half16 (sym+add)@tprel@highest */
+#define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel@highesta */
+#define R_PPC64_DTPREL16_DS 101 /* half16ds* (sym+add)@dtprel */
+#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel@l */
+#define R_PPC64_DTPREL16_HIGHER 103 /* half16 (sym+add)@dtprel@higher */
+#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */
+#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */
+#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel@highesta */
+
+/* Additional relocation types */
+#define R_PPC64_TOC32 107
+#define R_PPC64_DTPMOD32 108
+#define R_PPC64_TPREL32 109
+#define R_PPC64_DTPREL32 110
+
+/* Keep this the last entry. */
+#define R_PPC64_NUM 111
+
+/* Relocation types for MIPS */
+#define R_MIPS_NONE 0
+#define R_MIPS_16 1
+#define R_MIPS_32 2
+#define R_MIPS_ADD 2
+#define R_MIPS_REL 3
+#define R_MIPS_REL32 3
+#define R_MIPS_26 4
+#define R_MIPS_HI16 5
+#define R_MIPS_LO16 6
+#define R_MIPS_GPREL 7
+#define R_MIPS_GPREL16 7
+#define R_MIPS_LITERAL 8
+#define R_MIPS_GOT 9
+#define R_MIPS_GOT16 9
+#define R_MIPS_PC16 10
+#define R_MIPS_CALL 11
+#define R_MIPS_CALL16 11
+#define R_MIPS_GPREL32 12
+
+#define R_MIPS_SHIFT5 16
+#define R_MIPS_SHIFT6 17
+#define R_MIPS_64 18
+#define R_MIPS_GOT_DISP 19
+#define R_MIPS_GOT_PAGE 20
+#define R_MIPS_GOT_OFST 21
+#define R_MIPS_GOT_HI16 22
+#define R_MIPS_GOT_LO16 23
+#define R_MIPS_SUB 24
+#define R_MIPS_INSERT_A 25
+#define R_MIPS_INSERT_B 26
+#define R_MIPS_DELETE 27
+#define R_MIPS_HIGHER 28
+#define R_MIPS_HIGHEST 29
+#define R_MIPS_CALL_HI16 30
+#define R_MIPS_CALL_LO16 31
+#define R_MIPS_SCN_DISP 32
+#define R_MIPS_REL16 33
+#define R_MIPS_ADD_IMMEDIATE 34
diff --git a/dwarfdump/print_sections.c b/dwarfdump/print_sections.c new file mode 100644 index 0000000..a5e6ef1 --- /dev/null +++ b/dwarfdump/print_sections.c @@ -0,0 +1,206 @@ +/* + Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. + Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved. + Portions Copyright 2008-2011 David Anderson. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + + +$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + +#include "globals.h" +#include "naming.h" +#include "dwconf.h" +#include "esb.h" + +#include "print_sections.h" +#include "print_frames.h" + +/* + Print line number information: + filename + new basic-block + [line] [address] <new statement> +*/ + +int dwarf_names_print_on_error = 1; + +/* referred in dwarfdump.c */ +Dwarf_Die current_cu_die_for_print_frames; + +void +deal_with_name_offset_err(Dwarf_Debug dbg, + char *err_loc, + char *name, Dwarf_Unsigned die_off, + int nres, Dwarf_Error err) +{ + if (nres == DW_DLV_ERROR) { + Dwarf_Unsigned myerr = dwarf_errno(err); + + if (myerr == DW_DLE_OFFSET_BAD) { + printf("Error: bad offset %s, %s %" DW_PR_DUu + " (0x%08" DW_PR_DUx ")\n", + err_loc, + name, + die_off, + die_off); + } + print_error(dbg, err_loc, nres, err); + } +} + + + +/* The April 2005 dwarf_get_section_max_offsets() + in libdwarf returns all max-offsets, but we only + want one of those offsets. This function returns + the one we want from that set, + making functions needing this offset as readable as possible. + (avoiding code duplication). +*/ +Dwarf_Unsigned +get_info_max_offset(Dwarf_Debug dbg) +{ + Dwarf_Unsigned debug_info_size = 0; + Dwarf_Unsigned debug_abbrev_size = 0; + Dwarf_Unsigned debug_line_size = 0; + Dwarf_Unsigned debug_loc_size = 0; + Dwarf_Unsigned debug_aranges_size = 0; + Dwarf_Unsigned debug_macinfo_size = 0; + Dwarf_Unsigned debug_pubnames_size = 0; + Dwarf_Unsigned debug_str_size = 0; + Dwarf_Unsigned debug_frame_size = 0; + Dwarf_Unsigned debug_ranges_size = 0; + Dwarf_Unsigned debug_pubtypes_size = 0; + + dwarf_get_section_max_offsets(dbg, + &debug_info_size, + &debug_abbrev_size, + &debug_line_size, + &debug_loc_size, + &debug_aranges_size, + &debug_macinfo_size, + &debug_pubnames_size, + &debug_str_size, + &debug_frame_size, + &debug_ranges_size, + &debug_pubtypes_size); + + return debug_info_size; +} + +/* + decode ULEB +*/ +Dwarf_Unsigned +local_dwarf_decode_u_leb128(unsigned char *leb128, + unsigned int *leb128_length) +{ + unsigned char byte = 0; + Dwarf_Unsigned number = 0; + unsigned int shift = 0; + unsigned int byte_length = 1; + + byte = *leb128; + for (;;) { + number |= (byte & 0x7f) << shift; + shift += 7; + + if ((byte & 0x80) == 0) { + if (leb128_length != NULL) + *leb128_length = byte_length; + return (number); + } + + byte_length++; + byte = *(++leb128); + } +} + +#define BITSINBYTE 8 +Dwarf_Signed +local_dwarf_decode_s_leb128(unsigned char *leb128, + unsigned int *leb128_length) +{ + Dwarf_Signed number = 0; + Dwarf_Bool sign = 0; + Dwarf_Signed shift = 0; + unsigned char byte = *leb128; + Dwarf_Signed byte_length = 1; + + /* byte_length being the number of bytes of data absorbed so far in + turning the leb into a Dwarf_Signed. */ + + for (;;) { + sign = byte & 0x40; + number |= ((Dwarf_Signed) ((byte & 0x7f))) << shift; + shift += 7; + + if ((byte & 0x80) == 0) { + break; + } + ++leb128; + byte = *leb128; + byte_length++; + } + + if ((shift < sizeof(Dwarf_Signed) * BITSINBYTE) && sign) { + number |= -((Dwarf_Signed) 1 << shift); + } + + if (leb128_length != NULL) + *leb128_length = byte_length; + return (number); +} + + +/* Dumping a dwarf-expression as a byte stream. */ +void +dump_block(char *prefix, char *data, Dwarf_Signed len) +{ + char *end_data = data + len; + char *cur = data; + int i = 0; + + printf("%s", prefix); + for (; cur < end_data; ++cur, ++i) { + if (i > 0 && i % 4 == 0) + printf(" "); + printf("%02x", 0xff & *cur); + + } +} + diff --git a/dwarfdump/print_sections.h b/dwarfdump/print_sections.h new file mode 100644 index 0000000..63015cd --- /dev/null +++ b/dwarfdump/print_sections.h @@ -0,0 +1,54 @@ +/* + Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + +*/ + + +extern int dwarf_names_print_on_error; + +void deal_with_name_offset_err(Dwarf_Debug dbg, + char *err_loc, + char *name, + Dwarf_Unsigned die_off, + int nres, + Dwarf_Error err); + +Dwarf_Unsigned get_info_max_offset(Dwarf_Debug dbg); + +void print_pubname_style_entry(Dwarf_Debug dbg, + char *line_title, + char *name, + Dwarf_Unsigned die_off, + Dwarf_Unsigned cu_off, + Dwarf_Unsigned global_cu_off, + Dwarf_Unsigned maxoff); diff --git a/dwarfdump/print_static_funcs.c b/dwarfdump/print_static_funcs.c new file mode 100644 index 0000000..c3dc59d --- /dev/null +++ b/dwarfdump/print_static_funcs.c @@ -0,0 +1,137 @@ +/* + Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. + Portions Copyright 2009-2011 SN Systems Ltd. All rights reserved. + Portions Copyright 2008-2011 David Anderson. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + + +$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + +#include "globals.h" +#include "naming.h" +#include "dwconf.h" +#include "esb.h" + +#include "print_sections.h" +#include "print_frames.h" + + +/* Get all the data in .debug_static_funcs + On error, this allows some dwarf memory leaks. +*/ +extern void +print_static_funcs(Dwarf_Debug dbg) +{ + Dwarf_Func *funcbuf = NULL; + Dwarf_Signed count = 0; + Dwarf_Signed i = 0; + Dwarf_Off die_off = 0; + Dwarf_Off cu_off = 0; + int gfres = 0; + + current_section_id = DEBUG_STATIC_FUNC; + + if (!do_print_dwarf) { + return; + } + + printf("\n.debug_static_func\n"); + gfres = dwarf_get_funcs(dbg, &funcbuf, &count, &err); + if (gfres == DW_DLV_ERROR) { + print_error(dbg, "dwarf_get_funcs", gfres, err); + } else if (gfres == DW_DLV_NO_ENTRY) { + /* no static funcs */ + } else { + Dwarf_Unsigned maxoff = get_info_max_offset(dbg); + + for (i = 0; i < count; i++) { + int fnres = 0; + int cures3 = 0; + Dwarf_Unsigned global_cu_off = 0; + char *name = 0; + + fnres = dwarf_func_name_offsets(funcbuf[i], &name, &die_off, + &cu_off, &err); + deal_with_name_offset_err(dbg, "dwarf_func_name_offsets", + name, die_off, fnres, err); + cures3 = dwarf_func_cu_offset(funcbuf[i], + &global_cu_off, &err); + if (cures3 != DW_DLV_OK) { + print_error(dbg, "dwarf_global_cu_offset", cures3, err); + } + + if (check_pubname_attr) { + Dwarf_Bool has_attr; + int ares; + int dres; + Dwarf_Die die; + + /* get die at die_off */ + dres = dwarf_offdie(dbg, die_off, &die, &err); + if (dres != DW_DLV_OK) { + print_error(dbg, "dwarf_offdie", dres, err); + } + + + ares = + dwarf_hasattr(die, DW_AT_external, &has_attr, &err); + if (ares == DW_DLV_ERROR) { + print_error(dbg, "hassattr on DW_AT_external", ares, + err); + } + if (checking_this_compiler()) { + DWARF_CHECK_COUNT(pubname_attr_result,1); + if (ares == DW_DLV_OK && has_attr) { + /* Should the value of flag be examined? */ + } else { + DWARF_CHECK_ERROR2(pubname_attr_result,name, + "pubname (in static funcs section) does not have DW_AT_external"); + } + } + dwarf_dealloc(dbg, die, DW_DLA_DIE); + } + + if (do_print_dwarf || record_dwarf_error) { + print_pubname_style_entry(dbg, + "static-func", name, die_off, + cu_off, global_cu_off, maxoff); + record_dwarf_error = FALSE; /* Clear error condition */ + } + } + dwarf_funcs_dealloc(dbg, funcbuf, count); + } +} /* print_static_funcs() */ diff --git a/dwarfdump/print_static_vars.c b/dwarfdump/print_static_vars.c new file mode 100644 index 0000000..5e42b67 --- /dev/null +++ b/dwarfdump/print_static_vars.c @@ -0,0 +1,104 @@ +/* + Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. + Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved. + Portions Copyright 2008-2011 David Anderson. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + $Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */ + +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + +#include "globals.h" +#include "naming.h" +#include "dwconf.h" +#include "esb.h" + +#include "print_sections.h" +#include "print_frames.h" + +/* Get all the data in .debug_static_vars */ +extern void +print_static_vars(Dwarf_Debug dbg) +{ + Dwarf_Var *varbuf = NULL; + Dwarf_Signed count = 0; + Dwarf_Signed i = 0; + Dwarf_Off die_off = 0; + Dwarf_Off cu_off = 0; + char *name = 0; + int gvres = 0; + + current_section_id = DEBUG_STATIC_VARS; + + if (!do_print_dwarf) { + return; + } + + printf("\n.debug_static_vars\n"); + gvres = dwarf_get_vars(dbg, &varbuf, &count, &err); + if (gvres == DW_DLV_ERROR) { + print_error(dbg, "dwarf_get_vars", gvres, err); + } else if (gvres == DW_DLV_NO_ENTRY) { + /* no static vars */ + } else { + Dwarf_Unsigned maxoff = get_info_max_offset(dbg); + + for (i = 0; i < count; i++) { + int vnres = 0; + int cures3 = 0; + Dwarf_Off global_cu_off = 0; + + vnres = dwarf_var_name_offsets(varbuf[i], &name, &die_off, + &cu_off, &err); + deal_with_name_offset_err(dbg, + "dwarf_var_name_offsets", + name, die_off, vnres, err); + cures3 = dwarf_var_cu_offset(varbuf[i], + &global_cu_off, &err); + if (cures3 != DW_DLV_OK) { + print_error(dbg, "dwarf_global_cu_offset", cures3, err); + } + + print_pubname_style_entry(dbg, + "static-var", + name, die_off, cu_off, + global_cu_off, maxoff); + + /* print associated die too? */ + } + dwarf_vars_dealloc(dbg, varbuf, count); + } +} /* print_static_vars */ + diff --git a/dwarfdump/print_strings.c b/dwarfdump/print_strings.c new file mode 100644 index 0000000..0cd67b3 --- /dev/null +++ b/dwarfdump/print_strings.c @@ -0,0 +1,80 @@ +/* + Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. + Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved. + Portions Copyright 2008-2011 David Anderson. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + + +$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + +#include "globals.h" +#include "naming.h" +#include "dwconf.h" +#include "esb.h" + +#include "print_sections.h" + +/* print data in .debug_string */ +extern void +print_strings(Dwarf_Debug dbg) +{ + Dwarf_Signed length = 0; + string name; + Dwarf_Off offset = 0; + int sres = 0; + + current_section_id = DEBUG_STR; + printf("\n.debug_string\n"); + while ((sres = dwarf_get_str(dbg, offset, &name, &length, &err)) + == DW_DLV_OK) { + if (display_offsets) { + printf("name at offset 0x%" DW_PR_XZEROS DW_PR_DUx + ", length %4" DW_PR_DSd " is '%s'\n", + (Dwarf_Unsigned)offset, length, name); + } else { + printf("name: length %4" DW_PR_DSd " is '%s'\n", + length, name); + } + offset += length + 1; + } + /* An inability to find the section is not necessarily + a real error, so do not report error unless we've + seen a real record. */ + if(sres == DW_DLV_ERROR && offset != 0) { + print_error(dbg, "dwarf_get_str failure", sres, err); + } +} diff --git a/dwarfdump/print_types.c b/dwarfdump/print_types.c new file mode 100644 index 0000000..f3fddba --- /dev/null +++ b/dwarfdump/print_types.c @@ -0,0 +1,141 @@ +/* + Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. + Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved. + Portions Copyright 2008-2011 David Anderson. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + + +$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + +#include "globals.h" +#include "naming.h" +#include "dwconf.h" +#include "esb.h" + +#include "print_sections.h" +#include "print_frames.h" + +/* get all the data in .debug_types */ +extern void +print_types(Dwarf_Debug dbg, enum type_type_e type_type) +{ + Dwarf_Type *typebuf = NULL; + Dwarf_Signed count = 0; + Dwarf_Signed i = 0; + char *name = NULL; + int gtres = 0; + + char *section_name = NULL; + char *offset_err_name = NULL; + char *section_open_name = NULL; + char *print_name_prefix = NULL; + int (*get_types) (Dwarf_Debug, Dwarf_Type **, Dwarf_Signed *, + Dwarf_Error *) = 0; + int (*get_offset) (Dwarf_Type, char **, Dwarf_Off *, Dwarf_Off *, + Dwarf_Error *) = NULL; + int (*get_cu_offset) (Dwarf_Type, Dwarf_Off *, Dwarf_Error *) = + NULL; + void (*dealloctype) (Dwarf_Debug, Dwarf_Type *, Dwarf_Signed) = + NULL; + + /* Do nothing if in check mode */ + if (!do_print_dwarf) { + return; + } + + + if (type_type == DWARF_PUBTYPES) { + section_name = ".debug_pubtypes"; + offset_err_name = "dwarf_pubtype_name_offsets"; + section_open_name = "dwarf_get_pubtypes"; + print_name_prefix = "pubtype"; + get_types = dwarf_get_pubtypes; + get_offset = dwarf_pubtype_name_offsets; + get_cu_offset = dwarf_pubtype_cu_offset; + dealloctype = dwarf_pubtypes_dealloc; + } else { + /* SGI_TYPENAME */ + section_name = ".debug_typenames"; + offset_err_name = "dwarf_type_name_offsets"; + section_open_name = "dwarf_get_types"; + print_name_prefix = "type"; + get_types = dwarf_get_types; + get_offset = dwarf_type_name_offsets; + get_cu_offset = dwarf_type_cu_offset; + dealloctype = dwarf_types_dealloc; + } + + + + gtres = get_types(dbg, &typebuf, &count, &err); + if (gtres == DW_DLV_ERROR) { + print_error(dbg, section_open_name, gtres, err); + } else if (gtres == DW_DLV_NO_ENTRY) { + /* no types */ + } else { + Dwarf_Unsigned maxoff = get_info_max_offset(dbg); + + /* Before July 2005, the section name was printed + unconditionally, now only prints if non-empty section really + exists. */ + printf("\n%s\n", section_name); + + for (i = 0; i < count; i++) { + int tnres = 0; + int cures3 = 0; + Dwarf_Off die_off = 0; + Dwarf_Off cu_off = 0; + Dwarf_Off global_cu_off = 0; + + tnres = + get_offset(typebuf[i], &name, &die_off, &cu_off, &err); + deal_with_name_offset_err(dbg, offset_err_name, name, + die_off, tnres, err); + cures3 = get_cu_offset(typebuf[i], &global_cu_off, &err); + if (cures3 != DW_DLV_OK) { + print_error(dbg, "dwarf_var_cu_offset", cures3, err); + } + print_pubname_style_entry(dbg, + print_name_prefix, + name, die_off, cu_off, + global_cu_off, maxoff); + + /* print associated die too? */ + } + dealloctype(dbg, typebuf, count); + } +} /* print_types() */ diff --git a/dwarfdump/print_weaknames.c b/dwarfdump/print_weaknames.c new file mode 100644 index 0000000..fd60ea8 --- /dev/null +++ b/dwarfdump/print_weaknames.c @@ -0,0 +1,104 @@ +/* + Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. + Portions Copyright 2009-2011 SN Systems Ltd. All rights reserved. + Portions Copyright 2008-2011 David Anderson. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + + + $Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */ + +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + +#include "globals.h" +#include "naming.h" +#include "dwconf.h" +#include "esb.h" + +#include "print_sections.h" + +/* Get all the data in .debug_weaknames */ +extern void +print_weaknames(Dwarf_Debug dbg) +{ + Dwarf_Weak *weaknamebuf = NULL; + Dwarf_Signed count = 0; + Dwarf_Signed i = 0; + Dwarf_Off die_off = 0; + Dwarf_Off cu_off = 0; + char *name = NULL; + int wkres = 0; + + current_section_id = DEBUG_WEAKNAMES; + + if (!do_print_dwarf) { + return; + } + printf("\n.debug_weaknames\n"); + wkres = dwarf_get_weaks(dbg, &weaknamebuf, &count, &err); + if (wkres == DW_DLV_ERROR) { + print_error(dbg, "dwarf_get_weaks", wkres, err); + } else if (wkres == DW_DLV_NO_ENTRY) { + /* no weaknames */ + } else { + Dwarf_Unsigned maxoff = get_info_max_offset(dbg); + + for (i = 0; i < count; i++) { + int tnres = 0; + int cures3 = 0; + Dwarf_Unsigned global_cu_off = 0; + + tnres = dwarf_weak_name_offsets(weaknamebuf[i], + &name, &die_off, &cu_off, + &err); + deal_with_name_offset_err(dbg, + "dwarf_weak_name_offsets", + name, die_off, tnres, err); + cures3 = dwarf_weak_cu_offset(weaknamebuf[i], + &global_cu_off, &err); + if (cures3 != DW_DLV_OK) { + print_error(dbg, "dwarf_weakname_cu_offset", + cures3, err); + } + print_pubname_style_entry(dbg, + "weakname", + name, die_off, cu_off, + global_cu_off, maxoff); + + /* print associated die too? */ + } + dwarf_weaks_dealloc(dbg, weaknamebuf, count); + } +} /* print_weaknames() */ diff --git a/dwarfdump/strstrnocase.c b/dwarfdump/strstrnocase.c new file mode 100755 index 0000000..082af66 --- /dev/null +++ b/dwarfdump/strstrnocase.c @@ -0,0 +1,118 @@ +/* + Copyright (C) 2009-2010 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. */ + + + +/* +This tries to find the string 'contained' in the +string 'container'. it returns true if found, else false. +The comparisons are independent of case. + +Regrettably there is no generally accepted version that +does this job, though GNU Linux has strcasestr() which +does what we need. Our code here do not behave like +strstr or strcasestr in the case of +an empty 'contained' argument: we return FALSE (this +case is not interesting for dwarfdump). + +There is a public domain stristr(). But given that dwarfdump is GPL, +it would seem (IANAL) that we cannot mix public domain code +into the release. + +The software here is independently written and indeed trivial. + +The POSIX function tolower() is only properly defined on unsigned char, hence +the ugly casts. + +strstrnocase.c + +*/ +#include <ctype.h> +#include <stdio.h> +#include <globals.h> + +boolean +is_strstrnocase(const char * container, const char * contained) +{ + const unsigned char *ct = (const unsigned char *)container; + for( ; *ct; ++ct ) + { + const unsigned char * cntnd = (const unsigned char *)contained; + boolean innerwrong = TRUE; + for( ; *cntnd; ++cntnd,++ct) + { + char lct = tolower(*ct); + char tlc = tolower(*cntnd); + if(lct != tlc) { + innerwrong=TRUE; + break; /* Go to outer loop */ + } + innerwrong=FALSE; + } + if(!innerwrong) { + return TRUE; + } + } + return FALSE; +} + +#ifdef TEST +static void +test(const char *t1, const char *t2,int resexp) +{ + boolean res = is_strstrnocase(t1,t2); + if (res == resexp) { + return; + } + printf("Error,mismatch %s and %s. Expected %d got %d\n", + t1,t2,resexp,res); +} + +int main() +{ + test("aaaaa","a",1); + test("aaaaa","b",0); + test("abaaba","ba",1); + test("abaaxa","x",1); + test("abaabA","Ba",1); + test("a","ab",0); + test("b","c",0); + test("b","",0); + test("","c",0); + test("","",0); + test("aaaaa","aaaaaaaa",0); +} +#endif diff --git a/dwarfdump/tag_attr.c b/dwarfdump/tag_attr.c new file mode 100644 index 0000000..899a357 --- /dev/null +++ b/dwarfdump/tag_attr.c @@ -0,0 +1,286 @@ +/* + Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2009-2010 SN Systems Ltd. All Rights Reserved. + Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + + +$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/tag_attr.c,v 1.8 2005/12/01 17:34:59 davea Exp $ */ +#include <dwarf.h> +#include <stdio.h> +#include <stdlib.h> /* For exit() declaration etc. */ +#include <errno.h> /* For errno declaration. */ +#include <unistd.h> /* For getopt. */ + +#include "globals.h" +#include "libdwarf.h" +#include "common.h" +#include "tag_common.h" + +boolean ellipsis = FALSE; /* So we can use dwarf_names.c */ + +/* Expected input format + +0xffffffff +value of a tag +value of a standard attribute that follows that tag +... +0xffffffff +value of a tag +value of a standard attribute that follows that tag +... +0xffffffff +... + +No blank lines or commentary allowed, no symbols, just numbers. + + +*/ + +unsigned int tag_attr_combination_table[ATTR_TABLE_ROW_MAXIMUM][ATTR_TABLE_COLUMN_MAXIMUM]; + + +static const char *usage[] = { + "Usage: tag_attr_build <options>", + " -i input-table-path", + " -o output-table-path", + " -s (Generate standard attribute table)", + " -e (Generate extended attribute table (common extensions))", + "" +}; + +char *program_name = 0; +char *input_name = 0; +char *output_name = 0; +int standard_flag = FALSE; +int extended_flag = FALSE; + +/* process arguments */ +void +process_args(int argc, char *argv[]) +{ + int c = 0; + boolean usage_error = FALSE; + + program_name = argv[0]; + + while ((c = getopt(argc, argv, "i:o:se")) != EOF) { + switch (c) { + case 'i': + input_name = optarg; + break; + case 'o': + output_name = optarg; + break; + case 'e': + extended_flag = TRUE; + break; + case 's': + standard_flag = TRUE; + break; + default: + usage_error = TRUE; + break; + } + } + + if (usage_error || 1 == optind || optind != argc) { + print_usage_message(argv[0],usage); + exit(FAILED); + } +} + + + +int +main(int argc, char **argv) +{ + int i = 0; + unsigned int num = 0; + int input_eof = 0; + int table_rows = 0; + int table_columns = 0; + int current_row = 0; + FILE * fileInp = 0; + FILE * fileOut = 0; + + print_version_details(argv[0],FALSE); + process_args(argc,argv); + print_args(argc,argv); + + if (!input_name ) { + fprintf(stderr,"Input name required, not supplied.\n"); + print_usage_message(argv[0],usage); + exit(FAILED); + } + fileInp = fopen(input_name,"r"); + if (!fileInp) { + fprintf(stderr,"Invalid input filename, could not open '%s'\n", + input_name); + print_usage_message(argv[0],usage); + exit(FAILED); + } + + + if (!output_name ) { + fprintf(stderr,"Output name required, not supplied.\n"); + print_usage_message(argv[0],usage); + exit(FAILED); + } + fileOut = fopen(output_name,"w"); + if (!fileOut) { + fprintf(stderr,"Invalid output filename, could not open: '%s'\n", + output_name); + print_usage_message(argv[0],usage); + exit(FAILED); + } + if ((standard_flag && extended_flag) || + (!standard_flag && !extended_flag)) { + fprintf(stderr,"Invalid table type\n"); + fprintf(stderr,"Choose -e or -s .\n"); + print_usage_message(argv[0],usage); + exit(FAILED); + } + + + if(standard_flag) { + table_rows = STD_ATTR_TABLE_ROWS; + table_columns = STD_ATTR_TABLE_COLUMNS; + } else { + table_rows = EXT_ATTR_TABLE_ROWS; + table_columns = EXT_ATTR_TABLE_COLS; + } + + input_eof = read_value(&num,fileInp); /* 0xffffffff */ + if (IS_EOF == input_eof) { + bad_line_input("Empty input file"); + } + if (num != MAGIC_TOKEN_VALUE) { + bad_line_input("Expected 0xffffffff"); + } + while (!feof(stdin)) { + unsigned int tag; + int curcol = 0; + + input_eof = read_value(&tag,fileInp); + if (IS_EOF == input_eof) { + /* Reached normal eof */ + break; + } + if(standard_flag) { + if (tag >= table_rows ) { + bad_line_input("tag value exceeds standard table size"); + } + } else { + if(current_row >= table_rows) { + bad_line_input("too many extended table rows."); + } + tag_attr_combination_table[current_row][0] = tag; + } + + input_eof = read_value(&num,fileInp); + if (IS_EOF == input_eof) { + bad_line_input("Not terminated correctly.."); + } + curcol = 1; + while (num != MAGIC_TOKEN_VALUE) { + if(standard_flag) { + unsigned idx = num / BITS_PER_WORD; + unsigned bit = num % BITS_PER_WORD; + + if (idx >= table_columns) { + bad_line_input + ("too many attributes: table incomplete."); + } + tag_attr_combination_table[tag][idx] |= (1 << bit); + } else { + if (curcol >= table_columns) { + bad_line_input("too many attributes: table incomplete."); + } + tag_attr_combination_table[current_row][curcol] = num; + curcol++; + + } + input_eof = read_value(&num,fileInp); + if (IS_EOF == input_eof) { + bad_line_input("Not terminated correctly."); + } + } + ++current_row; + } + fprintf(fileOut,"/* Generated code, do not edit. */\n"); + fprintf(fileOut,"/* Generated on %s %s */\n",__DATE__,__TIME__); + fprintf(fileOut,"\n/* BEGIN FILE */\n\n"); + if (standard_flag) { + fprintf(fileOut,"#define ATTR_TREE_ROW_COUNT %d\n\n",table_rows); + fprintf(fileOut,"#define ATTR_TREE_COLUMN_COUNT %d\n\n",table_columns); + fprintf(fileOut, + "static unsigned int tag_attr_combination_table" + "[ATTR_TREE_ROW_COUNT][ATTR_TREE_COLUMN_COUNT] = {\n"); + } + else { + fprintf(fileOut,"/* Common extensions */\n"); + fprintf(fileOut,"#define ATTR_TREE_EXT_ROW_COUNT %d\n\n",table_rows); + fprintf(fileOut,"#define ATTR_TREE_EXT_COLUMN_COUNT %d\n\n", + table_columns); + fprintf(fileOut, + "static unsigned int tag_attr_combination_ext_table" + "[ATTR_TREE_EXT_ROW_COUNT][ATTR_TREE_EXT_COLUMN_COUNT] = {\n"); + } + + for (i = 0; i < table_rows; i++) { + int j = 0; + const char *name = 0; + if(standard_flag) { + dwarf_get_TAG_name(i,&name); + fprintf(fileOut,"/* %d %-37s*/\n",i,name); + } else { + int k = tag_attr_combination_table[i][0]; + dwarf_get_TAG_name(k,&name); + fprintf(fileOut,"/* %u %-37s*/\n",k,name); + } + fprintf(fileOut," { "); + for(j = 0; j < table_columns; ++j ) { + fprintf(fileOut,"0x%08x,",tag_attr_combination_table[i][j]); + } + fprintf(fileOut,"},\n"); + } + fprintf(fileOut,"};\n"); + fprintf(fileOut,"\n/* END FILE */\n"); + fclose(fileInp); + fclose(fileOut); + return (0); +} +/* A fake so we can use dwarf_names.c */ +void print_error (Dwarf_Debug dbg, string msg,int res, Dwarf_Error err) +{ +} + diff --git a/dwarfdump/tag_attr.list b/dwarfdump/tag_attr.list new file mode 100644 index 0000000..813ae18 --- /dev/null +++ b/dwarfdump/tag_attr.list @@ -0,0 +1,880 @@ +/* + Copyright (C) 2000-2010 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + + $Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/tag_attr.list,v 1.7 2005/12/01 17:34:59 davea Exp $ +*/ +#include <dwarf.h> + +/* + list for semantic check of tag-attr relation. + + 0xffffffff is a "punctuation." The final line of this file + must be 0xffffffff. The next line after each 0xffffffff + (except the final line) is a tag. The lines after this line + before the next 0xffffffff are the attributes that can be given + to the tag." + + For example, + + 0xffffffff + DW_TAG_access_declaration + DW_AT_decl_column + DW_AT_decl_file + DW_AT_decl_line + DW_AT_accessibility + DW_AT_name + DW_AT_sibling + 0xffffffff + + means "only DW_AT_decl_column, DW_AT_decl_file, DW_AT_decl_line, + DW_AT_accessibility, DW_AT_name and DW_AT_sibling can be given to + DW_TAG_access_declaration." + + This file is applied to the preprocessor, thus any C comment and + preprocessor control line is available. +*/ + +0xffffffff +DW_TAG_access_declaration +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_accessibility +DW_AT_name +DW_AT_sibling +0xffffffff +DW_TAG_array_type +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_abstract_origin +DW_AT_accessibility +DW_AT_allocated +DW_AT_associated +DW_AT_bit_stride +DW_AT_byte_size +DW_AT_bit_size /* Allowed in DWARF4 */ +DW_AT_data_location +DW_AT_declaration +DW_AT_description +DW_AT_name +DW_AT_ordering +DW_AT_sibling +DW_AT_specification +DW_AT_start_scope +DW_AT_type +DW_AT_visibility +0xffffffff +DW_TAG_base_type +DW_AT_allocated +DW_AT_associated +DW_AT_binary_scale +DW_AT_bit_offset +DW_AT_bit_size +DW_AT_byte_size +DW_AT_bit_size /* Allowed in DWARF4 */ +DW_AT_data_bit_offset +DW_AT_data_location +DW_AT_decimal_scale +DW_AT_decimal_sign +DW_AT_description +DW_AT_digit_count +DW_AT_encoding +DW_AT_endianity +DW_AT_name +DW_AT_name +DW_AT_picture_string +DW_AT_sibling +DW_AT_small +0xffffffff +DW_TAG_catch_block +DW_AT_abstract_origin +DW_AT_high_pc +DW_AT_low_pc +DW_AT_ranges +DW_AT_segment +DW_AT_sibling +0xffffffff +DW_TAG_class_type +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_abstract_origin +DW_AT_accessibility +DW_AT_allocated +DW_AT_associated +DW_AT_byte_size +DW_AT_bit_size /* Allowed in DWARF4 */ +DW_AT_data_location +DW_AT_declaration +DW_AT_description +DW_AT_name +DW_AT_sibling +DW_AT_signature +DW_AT_specification +DW_AT_start_scope +DW_AT_visibility +0xffffffff +DW_TAG_common_block +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_declaration +DW_AT_location +DW_AT_name +DW_AT_segment +DW_AT_sibling +DW_AT_visibility +0xffffffff +DW_TAG_common_inclusion +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_common_reference +DW_AT_declaration +DW_AT_sibling +DW_AT_visibility +0xffffffff +DW_TAG_compile_unit +DW_AT_base_types +DW_AT_comp_dir +DW_AT_identifier_case +DW_AT_high_pc +DW_AT_language +DW_AT_low_pc +DW_AT_macro_info +DW_AT_main_subprogram +DW_AT_name +DW_AT_producer +DW_AT_ranges +DW_AT_segment +DW_AT_sibling +DW_AT_stmt_list +DW_AT_use_UTF8 +DW_AT_entry_pc +0xffffffff +DW_TAG_condition +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_name +DW_AT_sibling +0xffffffff +DW_TAG_const_type +DW_AT_allocated +DW_AT_associated +DW_AT_data_location +DW_AT_name +DW_AT_sibling +DW_AT_type +0xffffffff +DW_TAG_constant +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_accessibility +DW_AT_const_value +DW_AT_declaration +DW_AT_description +DW_AT_endianity +DW_AT_external +DW_AT_linkage_name +DW_AT_name +DW_AT_sibling +DW_AT_start_scope +DW_AT_type +DW_AT_visibility +0xffffffff +DW_TAG_dwarf_procedure +DW_AT_location +0xffffffff +DW_TAG_entry_point +DW_AT_address_class +DW_AT_description +DW_AT_linkage_name +DW_AT_low_pc +DW_AT_name +DW_AT_return_addr +DW_AT_segment +DW_AT_sibling +DW_AT_static_link +DW_AT_type +0xffffffff +DW_TAG_enumeration_type +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_abstract_origin +DW_AT_accessibility +DW_AT_allocated +DW_AT_associated +DW_AT_bit_stride +DW_AT_byte_size +DW_AT_bit_size /* Allowed in DWARF4 */ +DW_AT_byte_stride +DW_AT_data_location +DW_AT_declaration +DW_AT_description +DW_AT_enum_class +DW_AT_name +DW_AT_sibling +DW_AT_signature +DW_AT_specification +DW_AT_start_scope +DW_AT_type +DW_AT_visibility +0xffffffff +DW_TAG_enumerator +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_const_value +DW_AT_description +DW_AT_name +DW_AT_sibling +0xffffffff +DW_TAG_file_type +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_abstract_origin +DW_AT_allocated +DW_AT_associated +DW_AT_byte_size +DW_AT_bit_size /* Allowed in DWARF4 */ +DW_AT_data_location +DW_AT_description +DW_AT_name +DW_AT_sibling +DW_AT_start_scope +DW_AT_type +DW_AT_visibility +0xffffffff +DW_TAG_formal_parameter +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_abstract_origin +DW_AT_artificial +DW_AT_const_value +DW_AT_default_value +DW_AT_description +DW_AT_endianity +DW_AT_is_optional +DW_AT_location +DW_AT_name +DW_AT_segment +DW_AT_sibling +DW_AT_type +DW_AT_variable_parameter +0xffffffff +DW_TAG_friend +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_abstract_origin +DW_AT_friend +DW_AT_sibling +0xffffffff +DW_TAG_imported_declaration +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_accessibility +DW_AT_description +DW_AT_import +DW_AT_name +DW_AT_sibling +DW_AT_start_scope +0xffffffff +DW_TAG_imported_module +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_import +DW_AT_sibling +DW_AT_start_scope +0xffffffff +DW_TAG_imported_unit +DW_AT_import +0xffffffff +DW_TAG_inheritance +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_accessibility +DW_AT_data_member_location +DW_AT_sibling +DW_AT_type +DW_AT_virtuality +0xffffffff +DW_TAG_inlined_subroutine +DW_AT_abstract_origin +DW_AT_call_column +DW_AT_call_file +DW_AT_call_line +DW_AT_const_expr +DW_AT_entry_pc +DW_AT_high_pc +DW_AT_low_pc +DW_AT_ranges +DW_AT_return_addr +DW_AT_segment +DW_AT_sibling +DW_AT_start_scope +DW_AT_trampoline +0xffffffff +DW_TAG_interface_type +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_accessibility +DW_AT_description +DW_AT_name +DW_AT_sibling +DW_AT_start_scope +0xffffffff +DW_TAG_label +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_abstract_origin +DW_AT_description +DW_AT_low_pc +DW_AT_name +DW_AT_segment +DW_AT_start_scope +DW_AT_sibling +0xffffffff +DW_TAG_lexical_block +DW_AT_abstract_origin +DW_AT_description +DW_AT_high_pc +DW_AT_low_pc +DW_AT_name +DW_AT_ranges +DW_AT_segment +DW_AT_sibling +0xffffffff +DW_TAG_member +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_accessibility +DW_AT_bit_offset +DW_AT_bit_size +DW_AT_byte_size +DW_AT_bit_size /* Allowed in DWARF4 */ +DW_AT_data_bit_offset +DW_AT_data_member_location +DW_AT_declaration +DW_AT_description +DW_AT_mutable +DW_AT_name +DW_AT_sibling +DW_AT_type +DW_AT_visibility +DW_AT_artificial +0xffffffff +DW_TAG_module +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_accessibility +DW_AT_declaration +DW_AT_description +DW_AT_entry_pc +DW_AT_high_pc +DW_AT_low_pc +DW_AT_name +DW_AT_priority +DW_AT_segment +DW_AT_sibling +DW_AT_specification +DW_AT_visibility +0xffffffff +DW_TAG_namelist +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_accessibility +DW_AT_abstract_origin +DW_AT_declaration +DW_AT_name +DW_AT_sibling +DW_AT_visibility +0xffffffff +DW_TAG_namelist_item +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_namelist_item +DW_AT_sibling +0xffffffff +DW_TAG_namespace +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_description +DW_AT_extension +DW_AT_name +DW_AT_sibling +DW_AT_start_scope +0xffffffff +DW_TAG_packed_type +DW_AT_allocated +DW_AT_associated +DW_AT_data_location +DW_AT_name +DW_AT_sibling +DW_AT_type +0xffffffff +DW_TAG_partial_unit +DW_AT_base_types +DW_AT_comp_dir +DW_AT_description +DW_AT_identifier_case +DW_AT_high_pc +DW_AT_language +DW_AT_low_pc +DW_AT_macro_info +DW_AT_main_subprogram +DW_AT_name +DW_AT_producer +DW_AT_ranges +DW_AT_segment +DW_AT_sibling +DW_AT_stmt_list +DW_AT_use_UTF8 +0xffffffff +DW_TAG_pointer_type +DW_AT_address_class +DW_AT_allocated +DW_AT_associated +DW_AT_data_location +DW_AT_name +DW_AT_sibling +DW_AT_specification +DW_AT_type +/* Comment from 1993: + "Though DWARF spec doesn't refer to DW_AT_byte_size, it may well be + given to DW_TAG_pointer_type." + Comment 31 January 2009: + Discussed in the dwarf-workgroup mailing list Jan 5 2009, that + DW_AT_byte_size is allowed. +*/ +DW_AT_byte_size +DW_AT_bit_size /* Allowed in DWARF4 (if DW_AT_byte_size allowed) */ +0xffffffff +DW_TAG_ptr_to_member_type +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_abstract_origin +DW_AT_address_class +DW_AT_allocated +DW_AT_associated +DW_AT_containing_type +DW_AT_data_location +DW_AT_declaration +DW_AT_description +DW_AT_name +DW_AT_sibling +DW_AT_type +DW_AT_use_location +DW_AT_visibility +0xffffffff +DW_TAG_rvalue_reference_type +DW_AT_address_class +DW_AT_allocated +DW_AT_associated +DW_AT_data_location +DW_AT_name +DW_AT_sibling +DW_AT_type +0xffffffff +DW_TAG_reference_type +DW_AT_address_class +DW_AT_allocated +DW_AT_associated +DW_AT_data_location +DW_AT_name +DW_AT_sibling +DW_AT_type +/* Comment from 1993: + "Though DWARF spec doesn't refer to DW_AT_byte_size, it may well be + given to DW_TAG_pointer_type." + Comment 31 January 2009: + Discussed in the dwarf-workgroup mailing list Jan 5 2009, that + DW_AT_byte_size is allowed. +*/ +DW_AT_byte_size +DW_AT_bit_size /* Allowed in DWARF4 */ +0xffffffff +DW_TAG_template_alias +DW_AT_abstract_origin +DW_AT_accessibility +DW_AT_allocated +DW_AT_associated +DW_AT_data_location +DW_AT_declaration +DW_AT_description +DW_AT_name +DW_AT_sibling +DW_AT_signature +DW_AT_start_scope +DW_AT_type +DW_AT_visibility +0xffffffff +DW_TAG_restrict_type +DW_AT_allocated +DW_AT_associated +DW_AT_data_location +DW_AT_name +DW_AT_sibling +DW_AT_type +0xffffffff +DW_TAG_set_type +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_abstract_origin +DW_AT_accessibility +DW_AT_allocated +DW_AT_associated +DW_AT_byte_size +DW_AT_bit_size /* Allowed in DWARF4 */ +DW_AT_data_location +DW_AT_declaration +DW_AT_description +DW_AT_name +DW_AT_start_scope +DW_AT_sibling +DW_AT_type +DW_AT_visibility +0xffffffff +DW_TAG_shared_type +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_count +DW_AT_name +DW_AT_sibling +DW_AT_type +0xffffffff +DW_TAG_string_type +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_abstract_origin +DW_AT_accessibility +DW_AT_allocated +DW_AT_associated +DW_AT_byte_size +DW_AT_bit_size /* Allowed in DWARF4 */ +DW_AT_data_location +DW_AT_declaration +DW_AT_description +DW_AT_name +DW_AT_segment +DW_AT_sibling +DW_AT_start_scope +DW_AT_string_length +DW_AT_visibility +0xffffffff +DW_TAG_structure_type +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_abstract_origin +DW_AT_accessibility +DW_AT_allocated +DW_AT_associated +DW_AT_byte_size +DW_AT_bit_size /* Allowed in DWARF4 */ +DW_AT_containing_type +DW_AT_data_location +DW_AT_declaration +DW_AT_description +DW_AT_name +DW_AT_sibling +DW_AT_signature +DW_AT_specification +DW_AT_start_scope +DW_AT_visibility +0xffffffff +DW_TAG_subprogram +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_abstract_origin +DW_AT_accessibility +DW_AT_address_class +DW_AT_artificial +DW_AT_calling_convention +DW_AT_containing_type +DW_AT_declaration +DW_AT_description +DW_AT_elemental +DW_AT_entry_pc +DW_AT_explicit +DW_AT_external +DW_AT_frame_base +DW_AT_high_pc +DW_AT_inline +DW_AT_linkage_name +DW_AT_low_pc +DW_AT_main_subprogram +DW_AT_name +DW_AT_object_pointer +DW_AT_prototyped +DW_AT_pure +DW_AT_ranges +DW_AT_recursive +DW_AT_return_addr +DW_AT_segment +DW_AT_sibling +DW_AT_specification +DW_AT_start_scope +DW_AT_static_link +DW_AT_trampoline +DW_AT_type +DW_AT_visibility +DW_AT_virtuality +DW_AT_vtable_elem_location +0xffffffff +DW_TAG_subrange_type +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_abstract_origin +DW_AT_accessibility +DW_AT_allocated +DW_AT_associated +DW_AT_bit_stride +DW_AT_byte_size +DW_AT_bit_size /* Allowed in DWARF4 */ +DW_AT_byte_stride +DW_AT_count +DW_AT_data_location +DW_AT_declaration +DW_AT_description +DW_AT_lower_bound +DW_AT_name +DW_AT_sibling +DW_AT_threads_scaled +DW_AT_type +DW_AT_upper_bound +DW_AT_visibility +0xffffffff +DW_TAG_subroutine_type +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_abstract_origin +DW_AT_accessibility +DW_AT_address_class +DW_AT_allocated +DW_AT_associated +DW_AT_data_location +DW_AT_declaration +DW_AT_description +DW_AT_name +DW_AT_prototyped +DW_AT_sibling +DW_AT_start_scope +DW_AT_type +DW_AT_visibility +0xffffffff +DW_TAG_template_type_parameter +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_description +DW_AT_name +DW_AT_sibling +DW_AT_type +0xffffffff +DW_TAG_template_value_parameter +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_const_value +DW_AT_description +DW_AT_name +DW_AT_sibling +DW_AT_type +0xffffffff +DW_TAG_thrown_type +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_allocated +DW_AT_associated +DW_AT_data_location +DW_AT_sibling +DW_AT_type +0xffffffff +DW_TAG_try_block +DW_AT_abstract_origin +DW_AT_high_pc +DW_AT_low_pc +DW_AT_ranges +DW_AT_segment +DW_AT_sibling +0xffffffff +DW_TAG_typedef +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_abstract_origin +DW_AT_accessibility +DW_AT_allocated +DW_AT_associated +DW_AT_data_location +DW_AT_declaration +DW_AT_description +DW_AT_name +DW_AT_sibling +DW_AT_start_scope +DW_AT_type +DW_AT_visibility +0xffffffff +DW_TAG_union_type +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_abstract_origin +DW_AT_accessibility +DW_AT_allocated +DW_AT_associated +DW_AT_byte_size +DW_AT_bit_size /* Allowed in DWARF4 */ +DW_AT_data_location +DW_AT_declaration +DW_AT_description +DW_AT_name +DW_AT_sibling +DW_AT_signature +DW_AT_specification +DW_AT_start_scope +DW_AT_visibility +0xffffffff +DW_TAG_unspecified_parameters +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_abstract_origin +DW_AT_artificial +DW_AT_sibling +0xffffffff +DW_TAG_unspecified_type +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_description +DW_AT_sibling +0xffffffff +DW_TAG_variable +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_abstract_origin +DW_AT_accessibility +DW_AT_byte_size +DW_AT_bit_size /* Allowed in DWARF4 */ +DW_AT_const_expr +DW_AT_const_value +DW_AT_declaration +DW_AT_description +DW_AT_endianity +DW_AT_external +DW_AT_linkage_name +DW_AT_location +DW_AT_name +DW_AT_segment +DW_AT_sibling +DW_AT_specification +DW_AT_start_scope +DW_AT_type +DW_AT_visibility +DW_AT_artificial +0xffffffff +DW_TAG_variant +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_accessibility +DW_AT_abstract_origin +DW_AT_declaration +DW_AT_discr_list +DW_AT_discr_value +DW_AT_sibling +0xffffffff +DW_TAG_variant_part +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_accessibility +DW_AT_abstract_origin +DW_AT_declaration +DW_AT_discr +DW_AT_sibling +DW_AT_type +0xffffffff +DW_TAG_volatile_type +DW_AT_allocated +DW_AT_associated +DW_AT_data_location +DW_AT_name +DW_AT_sibling +DW_AT_type +0xffffffff +DW_TAG_with_stmt +DW_AT_accessibility +DW_AT_address_class +DW_AT_declaration +DW_AT_high_pc +DW_AT_location +DW_AT_low_pc +DW_AT_ranges +DW_AT_segment +DW_AT_sibling +DW_AT_type +DW_AT_visibility +0xffffffff +DW_TAG_type_unit +DW_AT_language +0xffffffff + diff --git a/dwarfdump/tag_attr_ext.list b/dwarfdump/tag_attr_ext.list new file mode 100644 index 0000000..ce6d8b0 --- /dev/null +++ b/dwarfdump/tag_attr_ext.list @@ -0,0 +1,78 @@ +/* + Copyright (C) 2000-2010 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2008-2010 SN Systems Ltd. All Rights Reserved. + Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + + $Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/tag_attr.list,v 1.7 2005/12/01 17:34:59 davea Exp $ +*/ +#include <dwarf.h> + +/* list for semantic check of tag-attr relation. + See tag_attr.list for details. +*/ + +/* Common DWARF extensions */ + +0xffffffff +DW_TAG_member +DW_AT_GNU_guarded_by /* gcc.gnu.org/wiki/ThreadSafetyAnnotationsInDWARF */ +DW_AT_GNU_pt_guarded_by /* gcc.gnu.org/wiki/ThreadSafetyAnnotationsInDWARF */ +DW_AT_GNU_guarded /* gcc.gnu.org/wiki/ThreadSafetyAnnotationsInDWARF */ +DW_AT_GNU_pt_guarded /* gcc.gnu.org/wiki/ThreadSafetyAnnotationsInDWARF */ +0xffffffff +DW_TAG_array_type +DW_AT_GNU_vector +0xffffffff +DW_TAG_subprogram +DW_AT_MIPS_linkage_name /* Used by GNU, SGI-IRIX, and others. */ +DW_AT_MIPS_fde /* SGI-IRIX uses this */ +DW_AT_GNU_locks_excluded /* gcc.gnu.org/wiki/ThreadSafetyAnnotationsInDWARF */ +DW_AT_GNU_exclusive_locks_required +DW_AT_GNU_shared_locks_required +0xffffffff +DW_TAG_variable +DW_AT_MIPS_linkage_name /* Used by GNU, SGI-IRIX, and others. */ +DW_AT_GNU_guarded_by +DW_AT_GNU_pt_guarded_by +DW_AT_GNU_guarded +DW_AT_GNU_pt_guarded +0xffffffff +DW_TAG_GNU_template_template_parameter +DW_AT_decl_column +DW_AT_decl_file +DW_AT_decl_line +DW_AT_name +DW_AT_GNU_template_name +DW_AT_GNU_guarded_by /* GNU changed the name of 0x2108! */ +0xffffffff + diff --git a/dwarfdump/tag_common.c b/dwarfdump/tag_common.c new file mode 100644 index 0000000..28b2d2c --- /dev/null +++ b/dwarfdump/tag_common.c @@ -0,0 +1,145 @@ +/* + Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2009-2010 SN Systems Ltd. All Rights Reserved. + Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/tag_common.c,v 1.8 2008/01/23 09:47:59 davea Exp $ */ + +#include <dwarf.h> +#include <stdio.h> +#include <stdlib.h>/* For exit() declaration etc. */ +#include <errno.h>/* For errno declaration. */ +#include <ctype.h> /* For isspace() declaration */ + +#include "globals.h" +#include "naming.h" +#include "tag_common.h" + +static int linecount = 0; +static char line_in[MAX_LINE_SIZE]; + +void +bad_line_input(char *msg) +{ + fprintf(stderr, + "tag_(tree,attr) table build failed %s, line %d: \"%s\" \n", + msg, linecount, line_in); + exit(FAILED); +} + +void +trim_newline(char *line, int max) +{ + char *end = line + max - 1; + + for (; *line && (line < end); ++line) { + if (*line == '\n') { + /* Found newline, drop it */ + *line = 0; + return; + } + } + return; +} + +/* Detect empty lines (and other lines we do not want to read) */ +boolean +is_skippable_line(char *pLine) +{ + boolean empty = TRUE; + + if(pLine[0] == '#') { + /* Preprocessor lines are of no interest. */ + return TRUE; + } + for (; *pLine && empty; ++pLine) { + empty = isspace(*pLine); + } + return empty; +} + +/* Reads a value from the text table. + Exits with non-zero status + if the table is erroneous in some way. +*/ +int +read_value(unsigned int *outval, FILE*file) +{ + char *res = 0; + unsigned long lval; + char *strout = 0; + boolean bBlankLine = TRUE; + + ++linecount; + *outval = 0; + + while (bBlankLine) { + res = fgets(line_in, sizeof(line_in), file); + if (res == 0) { + if (ferror(file)) { + fprintf(stderr, + "tag_attr: Error reading table, %d lines read\n", + linecount); + exit(FAILED); + } + + if (feof(file)) { + return IS_EOF; + } + + /* Impossible */ + fprintf(stderr, "tag_attr: Impossible error reading table, " + "%d lines read\n", linecount); + exit(FAILED); + } + + bBlankLine = is_skippable_line(line_in); + } + + trim_newline(line_in, sizeof(line_in)); + errno = 0; + lval = strtoul(line_in, &strout, 0); + + if (strout == line_in) { + bad_line_input("bad number input!"); + } + + if (errno != 0) { + int myerr = errno; + + fprintf(stderr, "tag_attr errno %d\n", myerr); + bad_line_input("invalid number on line"); + } + + *outval = (int) lval; + + return NOT_EOF; +} diff --git a/dwarfdump/tag_common.h b/dwarfdump/tag_common.h new file mode 100644 index 0000000..f06d9bd --- /dev/null +++ b/dwarfdump/tag_common.h @@ -0,0 +1,123 @@ +/* + Copyright (C) 2000-2010 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2009-2010 SN Systems Ltd. All Rights Reserved. + Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/tag_common.h,v 1.8 2008/01/23 09:47:59 davea Exp $ */ + +#ifndef tag_common_INCLUDED +#define tag_common_INCLUDED + + + +/* The following is the magic token used to + distinguish real tags/attrs from group-delimiters. + Blank lines have been eliminated by an awk script. +*/ +#define MAGIC_TOKEN_VALUE 0xffffffff + +/* TAG_TREE.LIST Expected input format + +0xffffffff +value of a tag +value of a standard tag that may be a child of that tag +... +0xffffffff +value of a tag +value of a standard tag that may be a child of that tag +... +0xffffffff +... + +No blank lines or commentary allowed, no symbols, just numbers. + +*/ + +/* TAG_ATTR.LIST Expected input format + +0xffffffff +value of a tag +value of a standard attribute that follows that tag +... +0xffffffff +value of a tag +value of a standard attribute that follows that tag +... +0xffffffff +... + +No blank lines or commentary allowed, no symbols, just numbers. + +*/ + +/* We don't need really long lines: the input file is simple. */ +#define MAX_LINE_SIZE 1000 + +/* 1 more than the highest number in the DW_TAG defines, + this is for standard TAGs. Number of rows. */ +#define STD_TAG_TABLE_ROWS 0x44 +/* Enough entries to have a bit for each standard legal tag. */ +#define STD_TAG_TABLE_COLUMNS 7 + +/* TAG tree common extension maximums. */ +#define EXT_TAG_TABLE_ROWS 7 +#define EXT_TAG_TABLE_COLS 7 + +/* The following 2 used in tag_tree.c only. */ +#define TAG_TABLE_ROW_MAXIMUM STD_TAG_TABLE_ROWS +#define TAG_TABLE_COLUMN_MAXIMUM EXT_TAG_TABLE_COLS + +/* Number of attributes columns per tag. The array is bit fields, + BITS_PER_WORD fields per word. Dense and quick to inspect */ +#define COUNT_ATTRIBUTE_STD 7 + +#define STD_ATTR_TABLE_ROWS STD_TAG_TABLE_ROWS +#define STD_ATTR_TABLE_COLUMNS 7 +/* tag/attr tree common extension maximums. */ +#define EXT_ATTR_TABLE_ROWS 7 +#define EXT_ATTR_TABLE_COLS 7 + +/* The following 2 used in tag_attr.c only. */ +#define ATTR_TABLE_ROW_MAXIMUM STD_ATTR_TABLE_ROWS +#define ATTR_TABLE_COLUMN_MAXIMUM EXT_ATTR_TABLE_COLS + +/* Bits per 'int' to mark legal attrs. */ +#define BITS_PER_WORD 32 + +#define IS_EOF 1 +#define NOT_EOF 0 + +extern void bad_line_input(char *msg); +extern void trim_newline(char *line, int max); +extern boolean is_blank_line(char *pLine); +extern int read_value(unsigned int *outval,FILE *f); + +#endif /* tag_common_INCLUDED */ diff --git a/dwarfdump/tag_tree.c b/dwarfdump/tag_tree.c new file mode 100644 index 0000000..b508d06 --- /dev/null +++ b/dwarfdump/tag_tree.c @@ -0,0 +1,290 @@ +/* + Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved. + Portions Copyright 2009-2011 David Anderson. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + + +$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/tag_tree.c,v 1.8 2005/12/01 17:34:59 davea Exp $ */ +#include <dwarf.h> +#include <stdio.h> +#include <stdlib.h> /* For exit() declaration etc. */ +#include <errno.h> /* For errno declaration. */ +#include <unistd.h> /* For getopt. */ + +#include "globals.h" +#include "libdwarf.h" +#include "common.h" +#include "tag_common.h" + +unsigned int tag_tree_combination_table[TAG_TABLE_ROW_MAXIMUM][TAG_TABLE_COLUMN_MAXIMUM]; + +string program_name; + +boolean ellipsis = FALSE; /* So we can use dwarf_names.c */ + +/* Expected input format + +0xffffffff +value of a tag +value of a standard tag that may be a child ofthat tag +... +0xffffffff +value of a tag +value of a standard tag that may be a child ofthat tag +... +0xffffffff +... + +No commentary allowed, no symbols, just numbers. +Blank lines are allowed and are dropped. + +*/ + +static const char *usage[] = { + "Usage: tag_tree_build <options>", + "options:\t-t\tGenerate Tags table", + " -i Input-file-path", + " -o Output-table-path", + " -e (Want Extended table (common extensions))", + " -s (Want Standard table)", + "" +}; + +static char *input_name = 0; +static char *output_name = 0; +int extended_flag = FALSE; +int standard_flag = FALSE; + +static void +process_args(int argc, char *argv[]) +{ + int c = 0; + boolean usage_error = FALSE; + + program_name = argv[0]; + + while ((c = getopt(argc, argv, "i:o:es")) != EOF) { + switch (c) { + case 'i': + input_name = strdup(optarg); + break; + case 'o': + output_name = strdup(optarg); + break; + case 'e': + extended_flag = TRUE; + break; + case 's': + standard_flag = TRUE; + break; + + default: + usage_error = TRUE; + break; + } + } + + if (usage_error || 1 == optind || optind != argc) { + print_usage_message(argv[0],usage); + exit(FAILED); + } +} + + + +int +main(int argc, char **argv) +{ + int i = 0; + unsigned int num = 0; + int input_eof = 0; + int table_rows = 0; + int table_columns = 0; + int current_row = 0; + FILE *fileInp = 0; + FILE *fileOut = 0; + + + print_version_details(argv[0],FALSE); + process_args(argc,argv); + print_args(argc,argv); + + if (!input_name ) { + fprintf(stderr,"Input name required, not supplied.\n"); + print_usage_message(argv[0],usage); + exit(FAILED); + } + fileInp = fopen(input_name,"r"); + if (!fileInp) { + fprintf(stderr,"Invalid input filename, could not open '%s'\n", + input_name); + print_usage_message(argv[0],usage); + exit(FAILED); + } + + + if (!output_name ) { + fprintf(stderr,"Output name required, not supplied.\n"); + print_usage_message(argv[0],usage); + exit(FAILED); + } + fileOut = fopen(output_name,"w"); + if (!fileOut) { + fprintf(stderr,"Invalid output filename, could not open: '%s'\n", + output_name); + print_usage_message(argv[0],usage); + exit(FAILED); + } + if ((standard_flag && extended_flag) || (!standard_flag && !extended_flag)) { + fprintf(stderr,"Invalid table type\n"); + fprintf(stderr,"Choose -e or -s .\n"); + print_usage_message(argv[0],usage); + exit(FAILED); + } + if(standard_flag) { + table_rows = STD_TAG_TABLE_ROWS; + table_columns = STD_TAG_TABLE_COLUMNS; + } else { + table_rows = EXT_TAG_TABLE_ROWS; + table_columns = EXT_TAG_TABLE_COLS; + } + + + + input_eof = read_value(&num,fileInp); /* 0xffffffff */ + if (IS_EOF == input_eof) { + bad_line_input("Empty input file"); + } + if (num != MAGIC_TOKEN_VALUE) { + bad_line_input("Expected 0xffffffff"); + } + + while (!feof(stdin)) { + unsigned int tag = 0; + int nTagLoc = 0; + + input_eof = read_value(&tag,fileInp); + if (IS_EOF == input_eof) { + /* Reached normal eof */ + break; + } + if(standard_flag) { + if (tag >= table_rows ) { + bad_line_input("tag value exceeds standard table size"); + } + } else { + if(current_row >= table_rows) { + bad_line_input("too many extended table rows."); + } + tag_tree_combination_table[current_row][0] = tag; + } + input_eof = read_value(&num,fileInp); + if (IS_EOF == input_eof) { + bad_line_input("Not terminated correctly.."); + } + nTagLoc = 1; + while (num != 0xffffffff) { + if(standard_flag) { + int idx = num / BITS_PER_WORD; + int bit = num % BITS_PER_WORD; + + if (idx >= table_columns) { + fprintf(stderr,"Want column %d, have only %d\n", + idx,table_columns); + bad_line_input("too many TAGs: table incomplete."); + } + tag_tree_combination_table[tag][idx] |= (1 << bit); + } else { + if(nTagLoc >= table_columns) { + printf("Attempting to use colum %d, max is %d\n", + nTagLoc,table_columns); + bad_line_input("too many subTAGs, table incomplete."); + } + tag_tree_combination_table[current_row][nTagLoc] = num; + nTagLoc++; + } + input_eof = read_value(&num,fileInp); + if (IS_EOF == input_eof) { + bad_line_input("Not terminated correctly."); + } + } + ++current_row; /* for extended table */ + } + fprintf(fileOut,"/* Generated code, do not edit. */\n"); + fprintf(fileOut,"/* Generated on %s %s */\n",__DATE__,__TIME__); + fprintf(fileOut,"\n/* BEGIN FILE */\n\n"); + if (standard_flag) { + fprintf(fileOut,"#define TAG_TREE_COLUMN_COUNT %d\n\n",table_columns); + fprintf(fileOut,"#define TAG_TREE_ROW_COUNT %d\n\n",table_rows); + fprintf(fileOut, + "static unsigned int tag_tree_combination_table" + "[TAG_TREE_ROW_COUNT][TAG_TREE_COLUMN_COUNT] = {\n"); + } else { + fprintf(fileOut,"#define TAG_TREE_EXT_COLUMN_COUNT %d\n\n", + table_columns); + fprintf(fileOut,"#define TAG_TREE_EXT_ROW_COUNT %d\n\n",table_rows); + fprintf(fileOut,"/* Common extensions */\n"); + fprintf(fileOut, + "static unsigned int tag_tree_combination_ext_table" + "[TAG_TREE_EXT_ROW_COUNT][TAG_TREE_EXT_COLUMN_COUNT] = {\n"); + } + + for (i = 0; i < table_rows; i++) { + int j = 0; + const char *name = 0; + if (standard_flag) { + dwarf_get_TAG_name(i,&name);; + fprintf(fileOut,"/* %d %-37s*/\n",i, name); + } else { + int k = tag_tree_combination_table[i][0]; + dwarf_get_TAG_name(i,&name);; + fprintf(fileOut,"/* %u %-37s*/\n", k, name); + } + fprintf(fileOut," { "); + for(j = 0; j < table_columns; ++j ) { + fprintf(fileOut,"0x%08x,",tag_tree_combination_table[i][j]); + } + fprintf(fileOut,"},\n"); + + } + fprintf(fileOut,"};\n"); + fprintf(fileOut,"\n/* END FILE */\n"); + fclose(fileInp); + fclose(fileOut); + return (0); +} + +/* A fake so we can use dwarf_names.c */ +void print_error (Dwarf_Debug dbg, string msg,int res, Dwarf_Error err) +{ +} + diff --git a/dwarfdump/tag_tree.list b/dwarfdump/tag_tree.list new file mode 100644 index 0000000..ebad794 --- /dev/null +++ b/dwarfdump/tag_tree.list @@ -0,0 +1,486 @@ +/* + Copyright (C) 2000-2010 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + + $Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/tag_tree.list,v 1.6 2005/12/01 17:34:59 davea Exp $ +*/ +#include <dwarf.h> + +/* + list for semantic check of tag-tree. + + 0xffffffff is a "punctuation." The final line of this file + must be 0xffffffff. The next line after each 0xffffffff + (except the final line) stands for "parent-tag." The lines + after this line before the next 0xffffffff are the tags that + can be children of the "parent-tag." + + For example, + + 0xffffffff + DW_TAG_array_type + DW_TAG_subrange_type + DW_TAG_enumeration_type + 0xffffffff + + means "only DW_TAG_subrange_type and DW_TAG_enumeration_type can + be children of DW_TAG_array_type. + + This file is applied to the preprocessor, thus any C comment and + preprocessor control line is available. +*/ + +0xffffffff +DW_TAG_access_declaration +0xffffffff +DW_TAG_array_type +DW_TAG_subrange_type +DW_TAG_enumeration_type +0xffffffff +DW_TAG_base_type +0xffffffff +DW_TAG_catch_block +DW_TAG_formal_parameter +DW_TAG_unspecified_parameters +DW_TAG_array_type +DW_TAG_class_type +DW_TAG_enumeration_type +DW_TAG_pointer_type +DW_TAG_reference_type +DW_TAG_string_type +DW_TAG_structure_type +DW_TAG_subroutine_type +DW_TAG_typedef +DW_TAG_union_type +DW_TAG_ptr_to_member_type +DW_TAG_set_type +DW_TAG_subrange_type +DW_TAG_base_type +DW_TAG_const_type +DW_TAG_constant +DW_TAG_file_type +DW_TAG_packed_type +DW_TAG_subprogram +DW_TAG_variable +DW_TAG_volatile_type +0xffffffff +DW_TAG_class_type +DW_TAG_member +DW_TAG_inheritance +DW_TAG_access_declaration +DW_TAG_friend +DW_TAG_ptr_to_member_type +DW_TAG_subprogram +DW_TAG_template_type_parameter /* template instantiations */ +DW_TAG_template_value_parameter /* template instantiations */ +DW_TAG_typedef +DW_TAG_base_type +DW_TAG_pointer_type +DW_TAG_union_type +DW_TAG_const_type +DW_TAG_class_type /* Nested classes */ +DW_TAG_structure_type /* Nested structures */ +DW_TAG_enumeration_type /* Nested enums */ +DW_TAG_imported_declaration +DW_TAG_template_alias /* C++ 2010 template alias */ +0xffffffff +DW_TAG_common_block +DW_TAG_variable +0xffffffff +DW_TAG_common_inclusion +0xffffffff +DW_TAG_compile_unit +DW_TAG_array_type +DW_TAG_class_type +DW_TAG_enumeration_type +DW_TAG_imported_declaration +DW_TAG_pointer_type +DW_TAG_reference_type +DW_TAG_string_type +DW_TAG_structure_type +DW_TAG_subroutine_type +DW_TAG_typedef +DW_TAG_union_type +DW_TAG_common_block +DW_TAG_inlined_subroutine +DW_TAG_module +DW_TAG_ptr_to_member_type +DW_TAG_set_type +DW_TAG_subrange_type +DW_TAG_base_type +DW_TAG_const_type +DW_TAG_constant +DW_TAG_file_type +DW_TAG_namelist +DW_TAG_namespace +DW_TAG_packed_type +DW_TAG_subprogram +DW_TAG_variable +DW_TAG_volatile_type +DW_TAG_imported_module +DW_TAG_template_alias /* C++ 2010 template alias */ +0xffffffff +DW_TAG_type_unit +DW_TAG_array_type +DW_TAG_class_type +DW_TAG_enumeration_type +DW_TAG_imported_declaration +DW_TAG_pointer_type +DW_TAG_reference_type +DW_TAG_string_type +DW_TAG_structure_type +DW_TAG_subroutine_type +DW_TAG_typedef +DW_TAG_union_type +DW_TAG_common_block +DW_TAG_inlined_subroutine +DW_TAG_module +DW_TAG_ptr_to_member_type +DW_TAG_set_type +DW_TAG_subrange_type +DW_TAG_base_type +DW_TAG_const_type +DW_TAG_constant +DW_TAG_file_type +DW_TAG_namelist +DW_TAG_namespace +DW_TAG_packed_type +DW_TAG_subprogram +DW_TAG_variable +DW_TAG_volatile_type +DW_TAG_imported_module +DW_TAG_template_alias /* C++ 2010 template alias */ +0xffffffff +DW_TAG_condition /* COBOL */ +DW_TAG_constant +DW_TAG_subrange_type +0xffffffff +DW_TAG_const_type +0xffffffff +DW_TAG_constant +0xffffffff +DW_TAG_dwarf_procedure +0xffffffff +DW_TAG_entry_point +DW_TAG_formal_parameter +DW_TAG_unspecified_parameters +DW_TAG_common_inclusion +0xffffffff +DW_TAG_enumeration_type +DW_TAG_enumerator +0xffffffff +DW_TAG_enumerator +0xffffffff +DW_TAG_file_type +0xffffffff +DW_TAG_formal_parameter +0xffffffff +DW_TAG_friend +0xffffffff +DW_TAG_imported_declaration +0xffffffff +DW_TAG_imported_module +0xffffffff +DW_TAG_imported_unit +0xffffffff +DW_TAG_inheritance +0xffffffff +DW_TAG_inlined_subroutine +DW_TAG_formal_parameter +DW_TAG_unspecified_parameters +DW_TAG_array_type +DW_TAG_class_type +DW_TAG_enumeration_type +DW_TAG_pointer_type +DW_TAG_reference_type +DW_TAG_string_type +DW_TAG_structure_type +DW_TAG_subroutine_type +DW_TAG_lexical_block +DW_TAG_typedef +DW_TAG_union_type +DW_TAG_inlined_subroutine +DW_TAG_ptr_to_member_type +DW_TAG_set_type +DW_TAG_subrange_type +DW_TAG_base_type +DW_TAG_const_type +DW_TAG_constant +DW_TAG_file_type +DW_TAG_namelist +DW_TAG_packed_type +DW_TAG_subprogram +DW_TAG_variable +DW_TAG_volatile_type +0xffffffff +DW_TAG_interface_type +DW_TAG_member +DW_TAG_subprogram +0xffffffff +DW_TAG_label +0xffffffff +DW_TAG_lexical_block +DW_TAG_array_type +DW_TAG_class_type +DW_TAG_enumeration_type +DW_TAG_imported_declaration +DW_TAG_pointer_type +DW_TAG_reference_type +DW_TAG_string_type +DW_TAG_structure_type +DW_TAG_subroutine_type +DW_TAG_typedef +DW_TAG_union_type +DW_TAG_inlined_subroutine +DW_TAG_lexical_block +DW_TAG_module +DW_TAG_ptr_to_member_type +DW_TAG_set_type +DW_TAG_subrange_type +DW_TAG_base_type +DW_TAG_const_type +DW_TAG_constant +DW_TAG_namelist +DW_TAG_packed_type +DW_TAG_subprogram +DW_TAG_variable +DW_TAG_volatile_type +DW_TAG_formal_parameter +0xffffffff +DW_TAG_member +0xffffffff +DW_TAG_module +0xffffffff +DW_TAG_namelist +DW_TAG_namelist_item +0xffffffff +DW_TAG_namelist_item +0xffffffff +DW_TAG_namespace +DW_TAG_array_type +DW_TAG_class_type +DW_TAG_enumeration_type +DW_TAG_imported_declaration +DW_TAG_pointer_type +DW_TAG_reference_type +DW_TAG_string_type +DW_TAG_structure_type +DW_TAG_subroutine_type +DW_TAG_typedef +DW_TAG_union_type +DW_TAG_common_block +DW_TAG_inlined_subroutine +DW_TAG_module +DW_TAG_ptr_to_member_type +DW_TAG_set_type +DW_TAG_subrange_type +DW_TAG_base_type +DW_TAG_const_type +DW_TAG_constant +DW_TAG_namelist +DW_TAG_packed_type +DW_TAG_subprogram +DW_TAG_variable +DW_TAG_volatile_type +DW_TAG_namespace /* Allow a nested namespace */ +DW_TAG_imported_module /* Allow imported module */ +0xffffffff +DW_TAG_packed_type +0xffffffff +DW_TAG_partial_unit +DW_TAG_array_type +DW_TAG_class_type +DW_TAG_enumeration_type +DW_TAG_imported_declaration +DW_TAG_pointer_type +DW_TAG_reference_type +DW_TAG_string_type +DW_TAG_structure_type +DW_TAG_subroutine_type +DW_TAG_typedef +DW_TAG_union_type +DW_TAG_common_block +DW_TAG_inlined_subroutine +DW_TAG_module +DW_TAG_ptr_to_member_type +DW_TAG_set_type +DW_TAG_subrange_type +DW_TAG_base_type +DW_TAG_const_type +DW_TAG_constant +DW_TAG_file_type +DW_TAG_namelist +DW_TAG_packed_type +DW_TAG_subprogram +DW_TAG_variable +DW_TAG_volatile_type +0xffffffff +DW_TAG_pointer_type +DW_TAG_rvalue_reference_type +DW_TAG_reference_type +DW_TAG_restrict_type +DW_TAG_ptr_to_member_type +0xffffffff +DW_TAG_ptr_to_member_type +DW_TAG_rvalue_reference_type +DW_TAG_reference_type +DW_TAG_pointer_type +DW_TAG_restrict_type +0xffffffff +DW_TAG_reference_type +DW_TAG_rvalue_reference_type +DW_TAG_reference_type +DW_TAG_pointer_type +DW_TAG_restrict_type +DW_TAG_ptr_to_member_type +0xffffffff +DW_TAG_rvalue_reference_type +DW_TAG_pointer_type +DW_TAG_restrict_type +DW_TAG_ptr_to_member_type +DW_TAG_reference_type +0xffffffff +DW_TAG_restrict_type +DW_TAG_pointer_type +DW_TAG_ptr_to_member_type +DW_TAG_rvalue_reference_type +0xffffffff +DW_TAG_set_type +0xffffffff +DW_TAG_shared_type +0xffffffff +DW_TAG_string_type +0xffffffff +DW_TAG_structure_type +DW_TAG_member +DW_TAG_inheritance +DW_TAG_access_declaration +DW_TAG_friend +DW_TAG_ptr_to_member_type +DW_TAG_variant_part +DW_TAG_subprogram +DW_TAG_template_type_parameter /* template instantiations */ +DW_TAG_template_value_parameter /* template instantiations */ +DW_TAG_typedef +DW_TAG_base_type +DW_TAG_pointer_type +DW_TAG_union_type +DW_TAG_const_type +DW_TAG_structure_type /* nested structures */ +DW_TAG_enumeration_type /* nested enums */ +DW_TAG_class_type /* nested classes */ +DW_TAG_imported_declaration /* References to namespaces */ +DW_TAG_template_alias /* C++ 2010 template alias */ +0xffffffff +DW_TAG_subprogram +DW_TAG_formal_parameter +DW_TAG_unspecified_parameters +DW_TAG_thrown_type +DW_TAG_template_type_parameter +DW_TAG_template_value_parameter +DW_TAG_common_inclusion +DW_TAG_common_block +DW_TAG_array_type +DW_TAG_class_type +DW_TAG_enumeration_type +DW_TAG_pointer_type +DW_TAG_reference_type +DW_TAG_string_type +DW_TAG_lexical_block +DW_TAG_structure_type +DW_TAG_subroutine_type +DW_TAG_typedef +DW_TAG_union_type +DW_TAG_inlined_subroutine +DW_TAG_ptr_to_member_type +DW_TAG_set_type +DW_TAG_subrange_type +DW_TAG_base_type +DW_TAG_const_type +DW_TAG_constant +DW_TAG_file_type +DW_TAG_namelist +DW_TAG_packed_type +DW_TAG_subprogram +DW_TAG_variable +DW_TAG_volatile_type +DW_TAG_label +DW_TAG_imported_module /* References to namespaces */ +DW_TAG_imported_declaration /* References to namespaces */ +0xffffffff +DW_TAG_subrange_type +0xffffffff +DW_TAG_subroutine_type +DW_TAG_formal_parameter +DW_TAG_unspecified_parameters +0xffffffff +DW_TAG_template_type_parameter +0xffffffff +DW_TAG_template_value_parameter +0xffffffff +DW_TAG_thrown_type +0xffffffff +DW_TAG_try_block +0xffffffff +DW_TAG_typedef +0xffffffff +DW_TAG_union_type +DW_TAG_friend +DW_TAG_member +DW_TAG_class_type /* Nested classes */ +DW_TAG_enumeration_type /* Nested enums */ +DW_TAG_structure_type /* Nested structures */ +DW_TAG_typedef /* Nested typedef */ +DW_TAG_subprogram +DW_TAG_template_type_parameter /* template instantiations */ +DW_TAG_template_value_parameter /* template instantiations */ +0xffffffff +DW_TAG_template_alias +DW_TAG_template_type_parameter +DW_TAG_template_value_parameter +0xffffffff +DW_TAG_unspecified_parameters +0xffffffff +DW_TAG_unspecified_type +0xffffffff +DW_TAG_variable +0xffffffff +DW_TAG_variant +DW_TAG_variant_part +0xffffffff +DW_TAG_variant_part +0xffffffff +DW_TAG_volatile_type +0xffffffff +DW_TAG_with_stmt +0xffffffff diff --git a/dwarfdump/tag_tree_ext.list b/dwarfdump/tag_tree_ext.list new file mode 100644 index 0000000..e671373 --- /dev/null +++ b/dwarfdump/tag_tree_ext.list @@ -0,0 +1,63 @@ +/* + Copyright (C) 2000-2010 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2009-2010 SN Systems Ltd. All rights reserved. + Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2.1 of the GNU Lesser General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, + USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + +$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/tag_attr.list,v 1.7 2005/12/01 17:34:59 davea Exp $ +*/ +#include <dwarf.h> + +/* list for semantic check of tag-tree relation. + See tag_tree.list for details. + +*/ + +/* Common DWARF extensions */ + +0xffffffff +DW_TAG_structure_type +DW_TAG_variable /* GNU gcc usage. */ +0xffffffff +DW_TAG_class_type +DW_TAG_variable /* GNU gcc usage. */ +DW_TAG_GNU_template_template_parameter /* template instantiations */ +0xffffffff +DW_TAG_structure_type +DW_TAG_GNU_template_template_parameter /* template instantiations */ +0xffffffff +DW_TAG_subprogram +DW_TAG_GNU_template_template_parameter /* template instantiations */ +0xffffffff +DW_TAG_union_type +DW_TAG_GNU_template_template_parameter /* template instantiations */ +0xffffffff diff --git a/dwarfdump/testesb.c b/dwarfdump/testesb.c new file mode 100644 index 0000000..c3ea2f0 --- /dev/null +++ b/dwarfdump/testesb.c @@ -0,0 +1,78 @@ +/* testesb.c + test code for esb.h esb.c + + Not part of a compiled dwarfdump. + +*/ + +#include <stdio.h> +#include <string.h> +typedef char *string; + +#include "esb.h" + +void +check(string msg, struct esb_s *data, string v) +{ + string b = esb_get_string(data); + size_t l = 0; + size_t alloc = 0; + + if (strcmp(b, v)) { + fprintf(stderr, "ERROR: %s content error %s != %s\n", msg, b, + v); + } + + l = esb_string_len(data); + + if (l != strlen(v)) { + fprintf(stderr, "ERROR: %s length error %lu != %lu\n", msg, + (unsigned long) l, (unsigned long) strlen(v)); + } + alloc = esb_get_allocated_size(data); + if (l > alloc) { + fprintf(stderr, "ERROR: %s allocation error %lu > %lu\n", msg, + (unsigned long) l, (unsigned long) alloc); + + } + + return; +} + +int +main(void) +{ + struct esb_s data; + + + esb_alloc_size(2); /* small to get all code paths tested. */ + esb_constructor(&data); + + esb_append(&data, "a"); + esb_appendn(&data, "bc", 1); + esb_append(&data, "d"); + esb_append(&data, "e"); + check("test 1", &data, "abde"); + + esb_destructor(&data); + esb_constructor(&data); + + esb_append(&data, "abcdefghij" "0123456789"); + check("test 2", &data, "abcdefghij" "0123456789"); + + esb_destructor(&data); + esb_constructor(&data); + esb_append(&data, "abcdefghij" "0123456789"); + + esb_append(&data, "abcdefghij" "0123456789"); + + esb_append(&data, "abcdefghij" "0123456789"); + + esb_append(&data, "abcdefghij" "0123456789"); + check("test 3", &data, "abcdefghij" + "0123456789" + "abcdefghij" + "0123456789" + "abcdefghij" "0123456789" "abcdefghij" "0123456789"); + return 0; +} diff --git a/dwarfdump/uri.c b/dwarfdump/uri.c new file mode 100644 index 0000000..1353ab8 --- /dev/null +++ b/dwarfdump/uri.c @@ -0,0 +1,493 @@ +/* + Copyright 2011 David Anderson. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + +#include "globals.h" +#include "esb.h" +#include "uri.h" +#include <stdio.h> +#include <ctype.h> + +/* dwarfdump_ctype table. See uritablebuild.c */ +static char dwarfdump_ctype_table[256] = { +0, /* NUL 0x00 */ +0, /* control 0x01 */ +0, /* control 0x02 */ +0, /* control 0x03 */ +0, /* control 0x04 */ +0, /* control 0x05 */ +0, /* control 0x06 */ +0, /* control 0x07 */ +0, /* control 0x08 */ +0, /* whitespace 0x09 */ +0, /* whitespace 0x0a */ +0, /* whitespace 0x0b */ +0, /* whitespace 0x0c */ +0, /* whitespace 0x0d */ +0, /* control 0x0e */ +0, /* control 0x0f */ +0, /* control 0x10 */ +0, /* control 0x11 */ +0, /* control 0x12 */ +0, /* control 0x13 */ +0, /* control 0x14 */ +0, /* control 0x15 */ +0, /* control 0x16 */ +0, /* control 0x17 */ +0, /* control 0x18 */ +0, /* control 0x19 */ +0, /* control 0x1a */ +0, /* control 0x1b */ +0, /* control 0x1c */ +0, /* control 0x1d */ +0, /* control 0x1e */ +0, /* control 0x1f */ +1, /* ' ' 0x20 */ +1, /* '!' 0x21 */ +0, /* '"' 0x22 */ +1, /* '#' 0x23 */ +1, /* '$' 0x24 */ +0, /* '%' 0x25 */ +1, /* '&' 0x26 */ +0, /* ''' 0x27 */ +1, /* '(' 0x28 */ +1, /* ')' 0x29 */ +1, /* '*' 0x2a */ +1, /* '+' 0x2b */ +1, /* ',' 0x2c */ +1, /* '-' 0x2d */ +1, /* '.' 0x2e */ +1, /* '/' 0x2f */ +1, /* '0' 0x30 */ +1, /* '1' 0x31 */ +1, /* '2' 0x32 */ +1, /* '3' 0x33 */ +1, /* '4' 0x34 */ +1, /* '5' 0x35 */ +1, /* '6' 0x36 */ +1, /* '7' 0x37 */ +1, /* '8' 0x38 */ +1, /* '9' 0x39 */ +1, /* ':' 0x3a */ +0, /* ';' 0x3b */ +1, /* '<' 0x3c */ +1, /* '=' 0x3d */ +1, /* '>' 0x3e */ +1, /* '?' 0x3f */ +1, /* '@' 0x40 */ +1, /* 'A' 0x41 */ +1, /* 'B' 0x42 */ +1, /* 'C' 0x43 */ +1, /* 'D' 0x44 */ +1, /* 'E' 0x45 */ +1, /* 'F' 0x46 */ +1, /* 'G' 0x47 */ +1, /* 'H' 0x48 */ +1, /* 'I' 0x49 */ +1, /* 'J' 0x4a */ +1, /* 'K' 0x4b */ +1, /* 'L' 0x4c */ +1, /* 'M' 0x4d */ +1, /* 'N' 0x4e */ +1, /* 'O' 0x4f */ +1, /* 'P' 0x50 */ +1, /* 'Q' 0x51 */ +1, /* 'R' 0x52 */ +1, /* 'S' 0x53 */ +1, /* 'T' 0x54 */ +1, /* 'U' 0x55 */ +1, /* 'V' 0x56 */ +1, /* 'W' 0x57 */ +1, /* 'X' 0x58 */ +1, /* 'Y' 0x59 */ +1, /* 'Z' 0x5a */ +1, /* '[' 0x5b */ +1, /* '\' 0x5c */ +1, /* ']' 0x5d */ +1, /* '^' 0x5e */ +1, /* '_' 0x5f */ +0, /* '`' 0x60 */ +1, /* 'a' 0x61 */ +1, /* 'b' 0x62 */ +1, /* 'c' 0x63 */ +1, /* 'd' 0x64 */ +1, /* 'e' 0x65 */ +1, /* 'f' 0x66 */ +1, /* 'g' 0x67 */ +1, /* 'h' 0x68 */ +1, /* 'i' 0x69 */ +1, /* 'j' 0x6a */ +1, /* 'k' 0x6b */ +1, /* 'l' 0x6c */ +1, /* 'm' 0x6d */ +1, /* 'n' 0x6e */ +1, /* 'o' 0x6f */ +1, /* 'p' 0x70 */ +1, /* 'q' 0x71 */ +1, /* 'r' 0x72 */ +1, /* 's' 0x73 */ +1, /* 't' 0x74 */ +1, /* 'u' 0x75 */ +1, /* 'v' 0x76 */ +1, /* 'w' 0x77 */ +1, /* 'x' 0x78 */ +1, /* 'y' 0x79 */ +1, /* 'z' 0x7a */ +1, /* '{' 0x7b */ +1, /* '|' 0x7c */ +1, /* '}' 0x7d */ +1, /* '~' 0x7e */ +0, /* DEL 0x7f */ +1, /* 0x80 */ +1, /* 0x81 */ +1, /* 0x82 */ +1, /* 0x83 */ +1, /* 0x84 */ +1, /* 0x85 */ +1, /* 0x86 */ +1, /* 0x87 */ +1, /* 0x88 */ +1, /* 0x89 */ +1, /* 0x8a */ +1, /* 0x8b */ +1, /* 0x8c */ +1, /* 0x8d */ +1, /* 0x8e */ +1, /* 0x8f */ +1, /* 0x90 */ +1, /* 0x91 */ +1, /* 0x92 */ +1, /* 0x93 */ +1, /* 0x94 */ +1, /* 0x95 */ +1, /* 0x96 */ +1, /* 0x97 */ +1, /* 0x98 */ +1, /* 0x99 */ +1, /* 0x9a */ +1, /* 0x9b */ +1, /* 0x9c */ +1, /* 0x9d */ +1, /* 0x9e */ +1, /* 0x9f */ +0, /* other: 0xa0 */ +1, /* 0xa1 */ +1, /* 0xa2 */ +1, /* 0xa3 */ +1, /* 0xa4 */ +1, /* 0xa5 */ +1, /* 0xa6 */ +1, /* 0xa7 */ +1, /* 0xa8 */ +1, /* 0xa9 */ +1, /* 0xaa */ +1, /* 0xab */ +1, /* 0xac */ +1, /* 0xad */ +1, /* 0xae */ +1, /* 0xaf */ +1, /* 0xb0 */ +1, /* 0xb1 */ +1, /* 0xb2 */ +1, /* 0xb3 */ +1, /* 0xb4 */ +1, /* 0xb5 */ +1, /* 0xb6 */ +1, /* 0xb7 */ +1, /* 0xb8 */ +1, /* 0xb9 */ +1, /* 0xba */ +1, /* 0xbb */ +1, /* 0xbc */ +1, /* 0xbd */ +1, /* 0xbe */ +1, /* 0xbf */ +1, /* 0xc0 */ +1, /* 0xc1 */ +1, /* 0xc2 */ +1, /* 0xc3 */ +1, /* 0xc4 */ +1, /* 0xc5 */ +1, /* 0xc6 */ +1, /* 0xc7 */ +1, /* 0xc8 */ +1, /* 0xc9 */ +1, /* 0xca */ +1, /* 0xcb */ +1, /* 0xcc */ +1, /* 0xcd */ +1, /* 0xce */ +1, /* 0xcf */ +1, /* 0xd0 */ +1, /* 0xd1 */ +1, /* 0xd2 */ +1, /* 0xd3 */ +1, /* 0xd4 */ +1, /* 0xd5 */ +1, /* 0xd6 */ +1, /* 0xd7 */ +1, /* 0xd8 */ +1, /* 0xd9 */ +1, /* 0xda */ +1, /* 0xdb */ +1, /* 0xdc */ +1, /* 0xdd */ +1, /* 0xde */ +1, /* 0xdf */ +1, /* 0xe0 */ +1, /* 0xe1 */ +1, /* 0xe2 */ +1, /* 0xe3 */ +1, /* 0xe4 */ +1, /* 0xe5 */ +1, /* 0xe6 */ +1, /* 0xe7 */ +1, /* 0xe8 */ +1, /* 0xe9 */ +1, /* 0xea */ +1, /* 0xeb */ +1, /* 0xec */ +1, /* 0xed */ +1, /* 0xee */ +1, /* 0xef */ +1, /* 0xf0 */ +1, /* 0xf1 */ +1, /* 0xf2 */ +1, /* 0xf3 */ +1, /* 0xf4 */ +1, /* 0xf5 */ +1, /* 0xf6 */ +1, /* 0xf7 */ +1, /* 0xf8 */ +1, /* 0xf9 */ +1, /* 0xfa */ +1, /* 0xfb */ +1, /* 0xfc */ +1, /* 0xfd */ +1, /* 0xfe */ +0, /* other: 0xff */ +}; +static char * +xchar(int c, char *buf, int size) +{ + snprintf(buf, size,"%%%02x",c); + return buf; +} + +/* Translate dangerous and some other characters to safe + %xx form. +*/ +void +translate_to_uri(const char * filename, struct esb_s *out) +{ + char buf[8]; + const char *cp = 0; + for(cp = filename ; *cp; ++cp) { + char v[2]; + int c = 0xff & (unsigned char)*cp; + if(dwarfdump_ctype_table[c]) { + v[0] = c; + v[1] = 0; + esb_append(out,v); + } else { + char *b = xchar(c,buf,sizeof(buf)); + esb_append(out,b); + } + } +} + +/* This is not very efficient, but it is seldom called. */ +static char +hexdig(char c) +{ + char ochar = 0; + if(c >= 0 && c <= '9') { + ochar = (c - '0'); + return ochar; + } + if(c >= 'a' && c <= 'f') { + ochar = (c - 'a')+10; + return ochar; + } + if(c >= 'A' && c <= 'F') { + ochar = (c - 'A')+10; + return ochar; + } + // We have an input botch here. + fprintf(stderr,"Translating from uri: " + "A supposed hexadecimal input character is " + "not 0-9 or a-f or A-F, it is (shown as hex here): %x\n",c); + return ochar; +} + +static char tohex(char c1, char c2) +{ + char out = (hexdig(c1) << 4) | hexdig(c2); + return out; +} +static int +hexpairtochar(const char *cp, char*myochar) +{ + char ochar = 0; + int olen = 0; + char c = cp[0]; + if(c) { + char c2 = cp[1]; + if(c2) { + ochar = tohex(c,c2); + olen = 2; + } else { + fprintf(stderr,"Translating from uri: " + "A supposed hexadecimal input character pair " + "runs off the end of the input after 1 hex digit.\n"); + /* botched input. */ + ochar = c; + olen = 1; + } + } else { + /* botched input. */ + fprintf(stderr,"Translating from uri: " + "A supposed hexadecimal input character pair " + "runs off the end of the input.\n"); + ochar = '%'; + olen = 0; + } + *myochar = ochar; + return olen; +} + +void +translate_from_uri(const char * input, struct esb_s* out) +{ + const char *cp = input; + char tempstr[2]; + for(; *cp; ++cp) { + char c = *cp; + if(c == '%') { + int increment = 0; + char c2 = cp[1]; + // hexpairtochar deals with c2 being NUL. + if ( c2 == '%') { + tempstr[0] = c; + tempstr[1] = 0; + esb_append(out,tempstr); + ++cp; + continue; + } + + increment = hexpairtochar(cp+1,&c); + tempstr[0] = c; + tempstr[1] = 0; + esb_append(out,tempstr); + cp +=increment; + continue; + } + tempstr[0] = c; + tempstr[1] = 0; + esb_append(out,tempstr); + } +} + + + + +#ifdef TEST + +unsigned errcnt = 0; + +static void +mytestfrom(const char * in,const char *expected,int testnum) +{ + struct esb_s out; + esb_constructor(&out); + translate_from_uri(in, &out); + if(strcmp(expected, esb_get_string(&out))) { + printf(" Fail test %d expected \"%s\" got \"%s\"\n", + testnum,expected,esb_get_string(&out)); + ++errcnt; + } + esb_destructor(&out); +} + + +static void +mytest(char *in,char *expected,int testnum) +{ + struct esb_s out; + esb_constructor(&out); + translate_to_uri(in, &out); + if(strcmp(expected, esb_get_string(&out))) { + printf(" Fail test %d expected %s got %s\n",testnum,expected,esb_get_string(&out)); + ++errcnt; + } + esb_destructor(&out); +} + + +int +main() +{ + /* We no longer translate space to %20, that + turns out not to help all that much. */ + mytest("aaa","aaa",1); + mytest(" bc"," bc",2); + mytest(";bc","%3bbc",3); + mytest(" bc\n"," bc%0a",4); + mytest(";bc\n","%3bbc%0a",5); + mytest(" bc\r"," bc%0d",6); + mytest(";bc\r","%3bbc%0d",7); + mytest(" \x01"," %01",8); + mytest(";\x01","%3b%01",9); + mytestfrom("abc","abc",10); + mytestfrom("a%20bc","a bc",11); + mytestfrom("a%%20bc","a%20bc",12); + mytestfrom("a%%%20bc","a% bc",13); + mytestfrom("a%%%%20bc","a%%20bc",14); + mytestfrom("a%20","a ",15); + /* The following is mistaken input. */ + mytestfrom("a%2","a2",16); + mytestfrom("a%","a%",17); + mytest("%bc","%25bc",18); + + if(errcnt) { + printf("uri errcount ",errcnt); + } + return errcnt? 1:0; +} +#endif + diff --git a/dwarfdump/uri.h b/dwarfdump/uri.h new file mode 100644 index 0000000..0dfa386 --- /dev/null +++ b/dwarfdump/uri.h @@ -0,0 +1,37 @@ +/* + Copyright 2011 David Anderson. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + + +void translate_to_uri(const char * filename, struct esb_s *out); +void translate_from_uri(const char * input, struct esb_s *out); + diff --git a/dwarfdump/uritablebuild.c b/dwarfdump/uritablebuild.c new file mode 100644 index 0000000..c8c5501 --- /dev/null +++ b/dwarfdump/uritablebuild.c @@ -0,0 +1,146 @@ +/* + Copyright 2011 David Anderson. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + +*/ + +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + +#include <stdio.h> +#include <ctype.h> + +/* Generates a table which identifies a few dangerous characters. + Ones one does not want to appear in output. + + It's a bit arbitrary in that we allow lots of shell-interpreted + characters through, and most characters generally. + + But not control characters or single or double quotes. + The quotes would be particularly problematic for post-processing + dwarfdump output sensibly. + +*/ +static void +print_entry(int c) +{ + char v[2]; + v[0] = c; + v[1] = 0; + if(c == 0) { + printf("0, /* NUL 0x%02x */\n",c); + return; + } + if(isalnum(c) || c == ' ' ) { + /* We let the space character print as space since + lots of files are named that way in Mac and Windows. + */ + printf("1, /* \'%s\' 0x%02x */\n",v,c); + return; + } + if(c == 0x21 || c == 0x23 || c == 0x26) { + /* We let the space character print as space since + lots of files are named that way in Mac and Windows. + */ + printf("1, /* \'%s\' 0x%02x */\n",v,c); + return; + } + if(isspace(c) ) { + /* Other white space translated. */ + printf("0, /* whitespace 0x%02x */\n",c); + return; + } + if(c == 0x7f) { + printf("0, /* DEL 0x%02x */\n",c); + return; + } + if(c >= 0x01 && c <= 0x20 ) { + /* ASCII control characters. */ + printf("0, /* control 0x%02x */\n",c); + return; + } + if(c == '\'' || c == '\"' || c == '%' || c == ';' ) { + printf("0, /* \'%s\' 0x%02x */\n",v,c); + return; + } + if(c >= 0x3a && c <= 0x40 ) { + /* ASCII */ + printf("1, /* \'%s\' 0x%02x */\n",v,c); + return; + } + if(c == 0xa0 || c == 0xff ) { + printf("0, /* other: 0x%02x */\n",c); + return; + } + if(c >= 0x27 && c <= 0x2f ) { + /* ASCII */ + printf("1, /* \'%s\' 0x%02x */\n",v,c); + return; + } + if(c >= 0x5b && c <= 0x5f ) { + /* ASCII */ + printf("1, /* \'%s\' 0x%02x */\n",v,c); + return; + } + if(c >= 0x60 && c <= 0x60 ) { + /* ASCII */ + printf("0, /* \'%s\' 0x%02x */\n",v,c); + return; + } + if(c >= 0x7b && c <= 0x7e ) { + /* ASCII */ + printf("1, /* \'%s\' 0x%02x */\n",v,c); + return; + } + if (c < 0x7f) { + /* ASCII */ + printf("1, /* \'%s\' 0x%02x */\n",v,c); + return; + } + /* We are allowing other iso 8859 characters through unchanged. */ + printf("1, /* 0x%02x */\n",c); +} + + +int +main() +{ + int i = 0; + printf("/* dwarfdump_ctype table */\n"); + printf("char dwarfdump_ctype_table[256] = { \n"); + for ( i = 0 ; i <= 255; ++i) { + print_entry(i); + } + printf("};\n"); +} + |