diff options
author | Richard Henderson <rth@redhat.com> | 1999-05-03 07:29:11 +0000 |
---|---|---|
committer | Richard Henderson <rth@redhat.com> | 1999-05-03 07:29:11 +0000 |
commit | 252b5132c753830d5fd56823373aed85f2a0db63 (patch) | |
tree | 1af963bfd8d3e55167b81def4207f175eaff3a56 /binutils | |
download | gdb-252b5132c753830d5fd56823373aed85f2a0db63.zip gdb-252b5132c753830d5fd56823373aed85f2a0db63.tar.gz gdb-252b5132c753830d5fd56823373aed85f2a0db63.tar.bz2 |
19990502 sourceware importbinu_ss_19990502
Diffstat (limited to 'binutils')
114 files changed, 90535 insertions, 0 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog new file mode 100644 index 0000000..b8a3d27 --- /dev/null +++ b/binutils/ChangeLog @@ -0,0 +1,6404 @@ +1999-04-26 Tom Tromey <tromey@cygnus.com> + + * aclocal.m4, configure: Updated for new version of libtool. + +1999-04-18 Ian Lance Taylor <ian@zembu.com> + + * stabs.c (parse_stab_range_type): Correct parenthesization in + BFD64 case. + + * readelf.c (get_section_type_name): Use correct types in printf + formats. + (process_relocs): Likewise. + (process_dynamic_segment): Likewise. + (process_symbol_table): Likewise. + (process_mips_specific): Likewise. + +Tue Apr 13 21:22:00 1999 Catherine Moore <clm@cygnus.com> + + * dlltool.c (make_one_lib_file): Mark thumb functions as + C_THUMBEXTFUNC. + +1999-04-11 Richard Henderson <rth@cygnus.com> + + * bucomm.h (environ): Declare it, if needed. + (alloca) [C_ALLOCA]: Don't use gcc's builtin or <alloca.h>. + * configure.in (environ): Detect declaration. + * nm.c (main): Don't declare environ. + * configure, config.in: Rebuild. + + * dlltool.c (gen_exp_file): Pad out the .reloc section to a + 32-byte boundary with dummy relocations, to make the BeOS loader + happy. Patch from Bob Manson <manson@charmed.cygnus.com>. + +1999-04-08 Tom Tromey <tromey@cygnus.com> + + * binutils.texi (c++filt): Updated for -j/--java, and hp/edg + formats. + +1999-04-08 Nick Clifton <nickc@cygnus.com> + + * readelf.c: Add ability to decode new constants found in April 25 + 1998 Draft of System V ABI spec. + +1999-04-06 Ian Lance Taylor <ian@zembu.com> + + * bucomm.h (LC_MESSAGES): Never define. + * addr2line.c (main): Don't pass LC_MESSAGES to setlocale if the + system does not define it. + * ar.c (main): Likewise. + * coffdump.c (main): Likewise. + * dlltool.c (main): Likewise. + * nlmconv.c (main): Likewise. + * nm.c (main): Likewise. + * objcopy.c (main): Likewise. + * objdump.c (main): Likewise. + * size.c (main): Likewise. + * srconv.c (main): Likewise. + * strings.c (main): Likewise. + * sysdump.c (main): Likewise. + * windres.c (main): Likewise. + * readelf.c (main): Call locale setting functions. + +1999-04-05 Nick Clifton <nickc@cygnus.com> + + * readelf.c (decode_location_expression): Fix DW_OP_const8{s|u} + decodes. + +1999-04-04 Ian Lance Taylor <ian@zembu.com> + + * rename.c: New file, copied out of objcopy.c with a few changes. + * bucomm.h (set_times, smart_rename): Declare. + * ar.c: Don't include <utime.h>. + (extract_file): Call set_times rather than utime. + (write_archive): Call smart_rename rather than unlink and rename. + * objcopy.c: Don't include <utime.h>. + (simple_copy, smart_rename, set_times): Move to rename.c. + (strip_main): Update smart_rename call for new parameter. + (copy_main): Likewise. + * Makefile.am: Rebuild dependencies. + (CFILES): Add rename.c. + (objcopy_SOURCES, strip_new_SOURCES): Add rename.c. + (ar_SOURCES, ranlib_SOURCES): Add rename.c. + * Makefile.in: Rebuild. + + * Makefile.am: Rebuild dependencies. + (EXTRA_PROGRAMS): Remove backslash which troubles current version + of automake. + * Makefile.in: Rebuild. + + * dllwrap.c (main): Expect correct type in format string. + * resres.c: Include "bfd.h", "bucomm.h", "libiberty.h", and + <time.h>. Don't include <stdio.h> and <errno.h>. + (write_res_file): Remove unused locals e and i. + (read_resource_entry): Remove unused locals rtype and n. + (read_unistring): Remove unused local n. + +1999-04-03 Ian Lance Taylor <ian@zembu.com> + + * arparse.y: Declare yylex. + * objdump.c (disassemble_bytes): Initialize bytes. Add comment + for incorrect use of bytes. + * readelf.c: Change many formats to avoid warnings. + +1999-04-01 Nick Clifton <nickc@cygnus.com> + + * readelf.c (reset_state_machine): New function. Resets the + registers of the source line number state machine. + (process_extended_line_op): Use state machine. + (display_debug_lines): Use state machine. Handle multiple line + number blocks within the same section. + +1999-03-29 Jason Merrill <jason@yorick.cygnus.com> + + * readelf.c (process_extended_line_op): end_sequence also resets + the line number. + (display_debug_lines): advance_line takes a signed operand. + (read_and_display_attr): Print refs as <%x>, addresses as %#x, + others as %d. Handle other location expression attributes. + (display_debug_info): Handle nesting. Always print the offset. + +1999-03-23 Ian Lance Taylor <ian@zembu.com> + + * objcopy.c (filter_symbols): When checking whether to keep a + symbol, check the BFD section symbol for a symbol with + BSF_SECTION_SYM set. + +1999-03-10 Ulrich Drepper <drepper@cygnus.com> + + * readelf.c (process_dynamic_segment): Print new Solaris dynamic + section entries. Correct printing of DT_POSFLAG_1 and DT_FLAGS_1. + +1999-03-10 Nick Clifton <nickc@cygnus.com> + + * readelf.c (request_dump): New function. + Removed arbitary limit on the number of sections that can be + dumped. + +Wed Mar 10 15:10:14 1999 Stan Cox <scox@cygnus.com> + + * dlltool.c (make_one_lib_file): Use %05d to output the stub name so + order in the import library is preserved. + +1999-02-19 Nick Clifton <nickc@cygnus.com> + + * readelf.c: Fix compile time warings. + +1999-02-17 DJ Delorie <dj@cygnus.com> + + * resbin.c (res_to_bin_versioninfo): Instead of entering a value + length of zero in a version info string, enter the appropriate + length. + +Tue Feb 16 16:00:33 1999 Ian Lance Taylor <ian@cygnus.com> + + * configure.in: Require autoconf 2.13. Change AM_PROG_INSTALL to + AC_PROG_INSTALL. Add comments for AC_DEFINE calls. + * acconfig.h: Remove. + * aclocal.m4: Rebuild. + * configure: Rebuild. + * Makefile.in: Rebuild. + * config.in: Rebuild. + +1999-02-02 Nick Clifton <nickc@cygnus.com> + + * readelf.c (read_and_display_attr): Add display of basic type + encodings. + (display_debug_aranges): New function: Display the contents of a + .debug_aranges section. + (display_debug_info): Dump tags found after compunit entry. + + * binutils.texi: Fixed bug in readelf documentation. + +Mon Feb 1 12:38:01 1999 Catherine Moore <clm@cygnus.com> + + * readelf.c (dump_relocations): Handle EM_ARM as REL. + +1999-01-29 Nick Clifton <nickc@cygnus.com> + + * readelf.c (process_symbol_table): Do not produce a histogram of + bucket chains if none were found. + +1999-01-27 Nick Clifton <nickc@cygnus.com> + + * version.c: Add 1999 copyright. + + * binutils.texi (readelf): Document new command line options + --debug-dump and --histogram. + + * readelf.c: Add ability to display contents of some or all of the + Dwarf2 debug sections. {Work only partially completed}. + (display_debug_section): New function. + (display_debug_info): New function. + (display_debug_not_supported): New function. + (display_debug_line): New function. + (display_debug_abbrev): New function. + (process_abbrev_section): New function. + (read_leb128): New function. + (process_extended_line_op): New function. + (get_TAG_name): New function. + (get_AT_name): New function. + (get_FORM_name): New function. + (free_abbrevs): New function. + (add_abbrev): New function. + (add_abbrev_attr): New function. + (read_and_display_attr): New function. + (display_block): New function. + +Thu Jan 14 23:36:11 1999 Jeffrey A Law (law@cygnus.com) + + * coffdump.c (xcalloc): Remove, in libiberty now. + * srconv.c (xcalloc): Likewise. + * sysdump.c (xcalloc): Likewise. + +1999-01-14 Nick Clifton <nickc@cygnus.com> + + * readelf.c (process_section_headers): Omit trailing space at end + of section header contents line. + +Wed Dec 16 17:20:05 1998 Doug Evans <devans@canuck.cygnus.com> + + * aclocal.m4: Regenerate. + +Mon Dec 14 12:55:36 1998 Jim Wilson <wilson@cygnus.com> + + * dllwrap.c: Include bfd.h and bucomm.h. Move getopt.h include + after libiberty.h include. + +Tue Dec 8 16:29:43 1998 Ian Lance Taylor <ian@cygnus.com> + + * objdump.1: Fix typo (-d to -D). From Nokubi Hirotaka + <hnokubi@yyy.or.jp>. + +Sun Dec 6 13:28:09 1998 Ian Lance Taylor <ian@cygnus.com> + + * objdump.c (SFILE): Add size field. + (objdump_sprintf): Merge both versions into one. Increase buffer + size as needed to avoid overflow. + (disassemble_bytes): Change buf from 1000 bytes to 50. Change + initialization and use of sfile to match changes to + objdump_sprintf. + + * strip.1: Fix typo (-V to -v). From Issei Hirayama + <iss@mail.wbs.or.jp>. + +1998-12-03 Ulrich Drepper <drepper@cygnus.com> + + * readelf.c (process_dynamic_segment): Improve output format for + various DT_* values. + +1998-12-02 Ulrich Drepper <drepper@cygnus.com> + + * readelf.c (process_mips_specific): Print .conflict section + content. + + * readelf.c (process_mips_specific): Print l_flags in liblist in + textual form. + +1998-11-30 Nick Clifton <nickc@cygnus.com> + + * ar.c (extract_file): Add some paranoia checks for negatively + sized files. + +Tue Nov 24 09:39:24 1998 Nick Clifton <nickc@cygnus.com> + + * stabs.c (DIR_SEPARATOR): Define as '\\' if WIN32 is defined. + +Tue Nov 17 10:25:26 1998 Nick Clifton <nickc@cygnus.com> + + * Makefile.in: Regenerate. + +Mon Nov 16 19:17:23 1998 Dave Brolley <brolley@cygnus.com> + + * po/binutils.pot: Regenerate. + +Mon Nov 16 10:18:53 1998 Nick Clifton <nickc@cygnus.com> + + * Makefile.am: Regernated dependencies. + * aclocal.m4: Regenerated. + * configure: Regenerated. + +Sat Nov 14 14:50:56 1998 Ian Lance Taylor <ian@cygnus.com> + + * debug.c (debug_name_type): Correct return type from false to + DEBUG_TYPE_NULL. + +Sat Nov 14 14:48:21 1998 Andreas Schwab <schwab@issan.cs.uni-dortmund.de> + + * objdump.c (disassemble_data): Skip over relocs below start + address. + +Tue Nov 10 15:31:52 1998 Nick Clifton <nickc@cygnus.com> + + * Makefile.am: Add dependency of readelf.c on elf/fr30.h + * Makefile.in: Regenerate. + +Wed Nov 4 16:25:55 1998 Nick Clifton <nickc@cygnus.com> + + * readelf.c: Add support for the FR30. + +Mon Nov 2 14:59:33 1998 Geoffrey Noer <noer@cygnus.com> + + * configure.in: detect cygwin* instead of cygwin32* + * configure: regenerate + +Fri Oct 30 15:14:49 1998 Geoffrey Noer <noer@cygnus.com> + + * dllwrap.c: change all references to cygwin32_ to cygwin_, + change Cygwin target def to CYGWIN. + +Wed Oct 28 10:31:19 1998 Nick Clifton <nickc@cygnus.com> + + * objdump.c (disassemble_data): Replace 'unsigned long' with + 'bfd_vma'. + +Tue Oct 27 14:39:00 1998 Nick Clifton <nickc@cygnus.com> + + * objdump.c (disassemble_bytes): Applied this patch from Philip + Blundell <pb@nexus.co.uk>: Make address variables unsigned to + avoid problems when disassembling code at high-bit-set addresses. + +Mon Oct 26 14:07:59 1998 Mumit Khan <khan@xraylith.wisc.edu> + + * dllwrap.c (strhash): New function. + (main): Use it to supply image base if not supplied by user. + (program_version): Up to 0.2.4. + +Mon Oct 26 14:07:59 1998 Mumit Khan <khan@xraylith.wisc.edu> + + * dlltool.c (add_stdcall_alias): New global. + (long_options): Add --add-stdcall-alias option. + (main): Handle it. + (scan_drectve_symbols): Add alias if --add-stdcall-alias is + specified. + (scan_filtered_symbols): Likewise. + (gen_def_file): Output alias for stdcall syms if appropriate. + + * binutils.texi (dlltool): Document --add-stdcall-alias option. + + * dllwrap.c (long_options): Add --add-stdcall-alias option. + (main): Handle it. + + * defparse.y (opt_name): Allow "." in name. + * dlltool.c (def_name): Set dll_name from NAME entry in def file. + (def_library): Set dll_name from LIBRARY entry in def file. + +Mon Oct 26 14:07:59 1998 Mumit Khan <khan@xraylith.wisc.edu> + + * dllwrap.c (long_options): --implib synonym for --output-lib. + (main): Pass --export-all to dlltool only if specified. + (program_version): Up to 0.2.3. + +Mon Oct 26 14:07:59 1998 Mumit Khan <khan@xraylith.wisc.edu> + + * dllwrap.c (mybasename): New function. + (main): Run dlltool to create export definition file and import + library file if necessary. + Change exp_file_name so that it's based on the dll name. + +Sun Oct 25 10:37:45 1998 Mumit Khan <khan@xraylith.wisc.edu> + + * dlltool.c (scan_all_symbols): Fix patch error. + +Fri Oct 16 22:56:20 1998 Felix Lee <flee@cygnus.com> + + * nm.c (display_rel_file): fix "no symbols" messages. + * objdump.c (slurp_symtab): ditto. + * po/POTFILES.in, po/binutils.pot: rebuilt + +Mon Oct 12 14:28:03 1998 Nick Clifton <nickc@cygnus.com> + + * readelf.c (dump_relocations): Rename field from Value to Info to + match name of field in ELF structures. + +Thu Oct 8 15:33:08 1998 Geoffrey Noer <noer@cygnus.com> + + * configure.in: call AC_EXEEXT instead of AM_EXEEXT and + AM_CYGWIN32. + * aclocal.m4: remove local AM_EXEEXT/AM_CYGWIN32 macros. + * configure: regenerate + +Thu Oct 8 15:33:08 1998 Geoffrey Noer <noer@cygnus.com> + + From Mumit Khan <khan@xraylith.wisc.edu>: + * dlltool.c (scan_all_symbols): Don't re-export symbols exported + by other DLLs. + +Thu Oct 8 15:33:08 1998 Geoffrey Noer <noer@cygnus.com> + + * Makefile.am (BUILD_DLLWRAP): Add. + (BUILD_DLLWRAP, DLLWRAP_PROG): Add. + (bin_PROGRAMS): Add dllwrap. + * Makefile.in: regenerate with automake + + From Mumit Khan <khan@xraylith.wisc.edu>: + * dllwrap.c: New file from dllhelpers v0.2.1. + (print_version): New function. + (long_options): Add --version. + (main): Handle. + * dyn-string.h, dyn-string.c: New files from egcs-1.1/gcc. + * configure.in (BUILD_DLLWRAP): Add. + * configure: Regenerate. + +Tue Oct 6 18:20:10 1998 Geoffrey Noer <noer@cygnus.com> + + * Makefile.am (windres_SOURCES): Add resres.c. + (windres_OBJECTS): Add resres.o. + * Makefile.in: regenerate with automake + + From Anders Norlander <anorland@hem2.passagen.se>. + * resres.c: New file. Implementation of read_res_file and + write_res_file functions for windres. + * rcparse.y: Handle CONTROL's with named classes. + * resbin.c: Bug in res_to_bin_dialog and bin_to_res_dialog + when dialog is extended: The version and signature fields should + be reversed (despite what the docs say). Id is 32 bits long in + extended dialogs. + * resrc.c (write_rc_dialog): properly print controls with named + classes. + * windres.c (read_res_file, write_res_file): Remove stubs. + * resres.c (write_res): Rename RT_ACCELERATORS to RT_ACCELERATOR. + +Sun Oct 4 20:34:42 1998 Ian Lance Taylor <ian@cygnus.com> + + From Nokubi Hirotaka <hnokubi@yyy.or.jp>: + * objcopy.1: Fix typo in --remove-leading-char docs. + * objdump.1: Fix formatting in --stabs docs. + +Sat Sep 19 23:33:56 1998 Ian Lance Taylor <ian@cygnus.com> + + * rcparse.y (memflags_move): Correct recursion. + +1998-09-10 Ulrich Drepper <drepper@cygnus.com> + + * readelf.c (process_symbol_table): Print in histogram how many + symbols are covered by the current chain length. + +Sun Sep 6 16:15:47 1998 Nick Clifton <nickc@cygnus.com> + + * readelf.c (process_section_contents): Do not try to dump empty + sections. + +Sat Sep 5 19:17:10 1998 Mumit Khan <khan@xraylith.wisc.edu> + + * dlltool.c (scan_all_symbols): Don't re-export symbols exported + by other DLLs. + +1998-09-02 14:50 Ulrich Drepper <drepper@cygnus.com> + + * readelf.c (process_dynamic_segment): Print DT_* value only if + do_dynamic. + (do_histogram): New variable. + (options): New long option histogram. Set do_histogram if this + option is used. + (usage): Document --histogram. + (parse_args): Handle 0 return value from getopt_long. Enable + do_histogram for -a. + (process_symbol_table): Read hash table also if only do_histogram. + Add code to print hash table histogram. + +1998-08-25 16:45 Ulrich Drepper <drepper@cygnus.com> + + * readelf.c (process_dynamic_segment): Read syminfo section if + available. + (process_syminfo): New function. Print syminfo information. + (process_file): Call process_syminfo and free syminfo data at the end. + +Wed Aug 19 16:19:51 1998 Ian Lance Taylor <ian@cygnus.com> + + * dlltool.c (usage): Add file parameter. Change all callers. + (main): Don't treat '?' as a special case in getopt return. + + * binutils.texi (dlltool): Document new options. Add some uses of + @var. + +Wed Aug 19 16:19:07 1998 Mumit Khan <khan@xraylith.wisc.edu> + + * dlltool.c (gen_def_file): Plug memory leak. Don't print + demangled name if it is NULL. + + Support for exporting all symbols to an output export def file: + * dlltool.c ({export_all_symbols, no_default_excludes, + no_default_excludes, excludes}): New file static variables. + (struct string_list): Type to hold list of symbols to exclude. + (scan_drectve_symbols): Renamed from scan_open_obj_file. + (scan_filtered_symbols): New static function. + (add_excludes): New static function. + (match_exclude): New static function. + (set_default_excludes): New static function. + (filter_symbols): New static function. + (scan_all_symbols): New static function. + (scan_open_obj_file): New static function. + (usage): Document new options. + (long_options): Add new options. + (main): Handle new options. + +1998-07-31 21:24 Ulrich Drepper <drepper@cygnus.com> + + * readelf.c (process_program_headers): Print p_offset value with + six hex digits. + (dynamic_segment_mips_val): Add support for DT_MIPS_FLAGS, + DT_MIPS_IVERSION, and DT_MIPS_TIME_STAMP. + (process_mips_specific): Also print seconds of time stamp. + +Fri Jul 31 10:04:23 1998 Catherine Moore <clm@cygnus.com> + + * readelf.c (dump_relocations): EM_ARM uses rela relocs. + +1998-07-30 16:25 Ulrich Drepper <drepper@cygnus.com> + + * readelf.c (get_dynamic_type): Don't used gettext on the names. + Add new DT_* values from Solaris. Don't print nuemric value in + case of an unknown entry. + (process_dynamic_segment): Handle new DT_* entries. Print numeric + values in decimal, not hex. + +Fri Jul 24 16:28:57 1998 Jeff Holcomb <jeffh@cygnus.com> + + * readelf.c (get_dynamic_type): Remove empty default from switch + statement. + +Fri Jul 24 16:28:12 1998 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.am (install-exec-local): Don't remove the file before + checking whether $(bindir) == $(tooldir)/bin. From Maciej + W. Rozycki <macro@ds2.pg.gda.pl>. + * Makefile.in: Rebuild. + +Fri Jul 24 09:38:59 1998 Nick Clifton <nickc@cygnus.com> + + * objcopy.c: Removed spurious inclusion of elf/internal.h and + elf-bfd.h. + +1998-07-22 Ulrich Drepper <drepper@cygnus.com> + + * readelf.c: Consistantly use elf_ prefix for *_reloc_type + functions. + +Wed Jul 22 16:29:12 1998 Nick Clifton <nickc@cygnus.com> + + * readelf.c (dump_relocations): Add dumps of HPPA and ARC + relocations. + + (process_relocs): Do not abort if no string table can be found. + +1998-07-22 14:58 Ulrich Drepper <drepper@cygnus.com> + + * readelf.c: Remove definition of functions to return relocation + symbol strings. They now get implicitly defined when include the + system specific ELF header. + +1998-07-22 13:51 Ulrich Drepper <drepper@cygnus.com> + + * readelf.c: Before include system specific ELF header define + START_RELOC_NUMBERS, RELOC_NUMBER, and END_RELOC_NUMBERS. For now + used for ppc, mips, and mn10300. + +Wed Jul 22 10:26:32 1998 Nick Clifton <nickc@cygnus.com> + + * readelf.c (dump_relocations): Display number of unrecognised + relocations. + +1998-07-21 13:13 Ulrich Drepper <drepper@cygnus.com> + + * readelf.c: Use symbolic names of relocation entries for the various + architectures. Correct more layout details. + Print names of MIPS specific section types. Print Alpha, ARM, and + MIPS relocation type names. + +1998-07-20 Vladimir N. Makarov <vmakarov@cygnus.com> + + * objcopy.c (filter_symbols): Add code for strip all symbols case. + (copy_objects): Strip all case is now processed also through + filter_symbols. No marking symbols used in relocations when strip + all symbols case. + (copy_section): When strip all symbols case, remove relocations + which are not in keep strip specific list. + (strip_main): Remove guard `strip_specific_list == NULL' for + setting up strip all symbols by default. + +Mon Jul 20 12:51:16 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * addr2line.c (find_address_in_section): Only consider a section + if the pc value is completely contained within it. + (translate_addresses): Don't crash if functionname or filename are + null. + +1998-07-20 07:45 Ulrich Drepper <drepper@cygnus.com> + + * readelf.c (process_symbol_table): Fix little alignment problem + in printed table header. + +1998-07-20 07:14 Ulrich Drepper <drepper@cygnus.com> + + * readelf.c: Correct reading of .dynamic section. + (dynamic_section): Now a global variable. + (process_mips_fpe_exception, process_mips_specific, + process_arch_specific): New functions. + (get_file_header): Call process_arch_specific. + +1998-07-19 15:15 Ulrich Drepper <drepper@cygnus.com> + + * readelf.c: Fix several versioning related bugs. Produce nicer + output. + Add support for processor specific information on MIPS. + +Fri Jul 10 15:57:58 1998 Nick Clifton <nickc@cygnus.com> + + * readelf.c: Switch prototypes from unsigned short to unsigned + int. + +Fri Jul 10 16:17:50 1998 Ian Lance Taylor <ian@cygnus.com> + + From Christian Holland <CHolland@de.lucent.com>: + * ieee.c (parse_ieee): Initialize info.global_vars and + info.global_types. + (parse_ieee_atn): Ignore register lifetime information reportedly + emitted by MRI compiler. + +Thu Jul 9 13:08:01 1998 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.am (MAINTAINERCLEANFILES): Define. + * Makefile.in: Rebuild. + +Tue Jul 7 21:48:54 1998 Jeffrey A Law (law@cygnus.com) + + * readelf.c (byte_get): Use PARAMS in prototype. + (error): Make it work with non-ANSI compilers. + (warn): Likewise. + (get_ver_flags): Don't use an ANSI prototype in the definition. + +Tue Jul 7 13:26:13 1998 Ian Lance Taylor <ian@cygnus.com> + + * objcopy.c (filter_bytes): Set size correctly if the size of the + section is not an even multiple of the interleave. Based on patch + from Brion Stone <Brion.Stone@attws.com>. + +Thu Jul 2 14:01:34 1998 Klaus Kaempf <kkaempf@rmi.de> + + * configure.com: Add vax/vms support. + * makefile.vms-in: Renamed from makefile.vms. Add substitutions + now done by configure.com. + +Wed Jul 1 20:43:52 1998 Ian Lance Taylor <ian@cygnus.com> + + * stabs.c (parse_stab_range_type): Handle 4 and 8 byte signed + integers with real upper bounds. Handle a lower bound one larger + than the upper bound as a signed integer. Handle 8 byte signed + integers. + (stab_demangle_template): Optionally return the demangled name of + the template. + (stab_demangle_qualified): Treat a template name as a tagged + type. + (stab_demangle_fund_type): Likewise. + +Wed Jul 1 16:29:50 1998 Nick Clifton <nickc@cygnus.com> + + * objcopy.c: Minor formatting improvements. + * readelf.c: Minor output formatting improvement. + +Wed Jul 1 14:23:48 1998 Ian Lance Taylor <ian@cygnus.com> + + * rclex.l: Add casts and change types to avoid warnings. + * rcparse.y: Likewise. + * resbin.c: Likewise. + * rescoff.c: Likewise. + * resrc.c: Likewise. + + * Makefile.am: Rebuild dependencies. + (HFILES): Remove readelf.h. + * Makefile.in: Rebuild. + + Based on patches from Andrew Kozin + <Andrew.Kozin@p14.f960.n5020.z2.fidonet.org>: + * winduni.h: New file, from windres.h. + * winduni.c: New file, from windres.c. + * windres.c: Move Unicode functions into winduni.c. + * windres.h: Move Unicode declarations into winduni.h. Include + winduni.h. + (RT_ACCELERATOR): Rename from RT_ACCELERATORS to match Windows + macro. Change all uses. + (RT_PLUGPLAY, RT_VXD): Correct values. + * Makefile.am (HFILES): Add windres.h. + (CFILES): Add winduni.c. + (windres_SOURCES): Add winduni.c. + +Mon Jun 29 17:01:21 1998 Nick Clifton <nickc@cygnus.com> + + * readelf.c: Use BFD Internal and External Elf structures. + * readelf.h: Removed - no longer needed. + * Makefile.in: Remove readelf.c's dependency upon readelf.h. + +1998-06-26 Vladimir N. Makarov <vmakarov@cygnus.com> + + * objcopy.c (strip_main): keep_specific_list == NULL as additional + condition to set up strip all symbols by default. + (copy_archive): don't change archive when error in object files of + the archive. + +Wed Jun 24 17:53:47 1998 Ian Lance Taylor <ian@cygnus.com> + + * stabs.c (parse_number): Sign extend negative values correctly if + bfd_vma is larger than unsigned long. + +Tue Jun 23 14:55:05 1998 Mike Stump <mrs@wrs.com> + + * Makefile.am (install-exec-local): Don't let EXEEXT interfere + with the program transform name. + * Makefile.in: Rebuild. + +Tue Jun 23 11:08:53 1998 Nick Clifton <nickc@cygnus.com> + + * readelf.c: Rewrite to use fopen/fread ratehr than mmap. + + Add --section-headers command line switch, which is an alias for + --sections. + + Incorporate improvemnts made by Andreas Schwab + <schwab@issan.informatik.uni-dortmund.de> including output + formatting and version info display. + + * binutils.texi: Document --section-headers switch to readelf. + +Mon Jun 22 18:28:19 1998 Ian Lance Taylor <ian@cygnus.com> + + * readelf.c: Include bfd.h and bucomm.h before system header + files. + (parse_args): Change type of c from char to int. + +Sun Jun 14 14:26:28 1998 Nick Clifton <nickc@cygnus.com> + + * readelf.c (usage): Write to stdout, not stderr. + +Fri Jun 12 13:33:51 1998 Tom Tromey <tromey@cygnus.com> + + * po/Make-in (all-yes): Depend on .pot file if maintainer mode + enabled. + ($(PACKAGE).pot): Unconditionally depend on POTFILES. + +Fri Jun 12 16:06:15 1998 Michael Meissner <meissner@cygnus.com> + + * readelf.c (get_ppc_rel_type): New PowerPC support. + (dump_relocations): PowerPC uses RELA relocations. + (get_machine_name): Spell PowerPC correctly. + (get_file_type): Change unsigned short parameter to unsigned. + (get_machine_name): Ditto. + (get_machine_data): Return whether big endian or little endian. + (get_machine_flags): Interpret PowerPC, M32R, and MIPS flags. + (process_elf_header): Print endian-ess. Convert all numeric + formats to long or unsigned long. Print out machine specific flag + bits. + (process_section_headers): Increase name by 3 columns and decrease + type by the same so that .gcc_except_table fits in the space. + + * readelf.h: Include elf/ppc.h, elf/mips.h, and elf/m32r.h to get + machine specific flag bits. + +Thu Jun 11 17:54:26 1998 Nick Clifton <nickc@cygnus.com> + + * readelf.c: Remove extraneous #includes. Fix warnings produced + by -Wall when compiling under Linux. + + * Makefile.am (readelf_LDADD): Add $(LIBIBERTY). + +Thu Jun 11 18:30:20 1998 Ian Lance Taylor <ian@cygnus.com> + + * stabs.c (struct stab_handle): Add self_crossref field. + (parse_stab_string): If a tag is a cross reference to itself, + don't define it in the tags list. + (parse_stab_type): Set info->self_crossref. + + * debug.c (struct debug_type_real_list): Define. + (debug_get_real_type): Add list parameter. Change all callers. + Check for circularity to avoid crashing when it occurs. + +Thu Jun 11 14:48:32 1998 Nick Clifton <nickc@cygnus.com> + + * readelf.c: New file: Display contents of ELF format file. + * readelf.h: New file: Header file for readelf.c + * Makefile.am: Add rules to build readelf. + * Makefile.in: Rebuilt. + * binutils.texi: Document readelf. + * NEWS: Mention inclusion of readelf into binutils. + * po/POTFILES.in; Rebuilt. + +Fri Jun 5 18:43:40 1998 Ian Lance Taylor <ian@cygnus.com> + + * objcopy.c (setup_section): Adjust the section size if copy_byte + is >= 0. + (copy_section): Do not call bfd_set_section_size. + +Thu Jun 4 09:12:27 1998 Nick Clifton <nickc@cygnus.com> + + * objcopy.c (copy_usage): Add missing \n\ from help description. + +Wed Jun 3 19:31:33 1998 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.am (YACC): Correct bison -L option. + * Makefile.in: Rebuild. + + * binutils.texi, objdump.1: Document -p/--private-headers. + +Wed Jun 3 12:09:40 1998 Nick Clifton <nickc@cygnus.com> + + * objcopy.c: Add new command line options: --change-section-lma + and --change-section-vma. Rename old command line option + --adjust-section-vma to --change-section-address. Rename + --adjust-vma to --change-addresses and --adjust-start to + --change-start. Provide aliases to support the old versions of + these command line options. + + Change the names of macros and enum elements to upper case to + match the GNU coding standard. + + Replace calls to fprintf (stderr,...) with calls to fatal () or + non_fatal () as appropriate. + + * objcopy.1: Document command line option changes. + * binutils.texi: Document command line option changes. + + * bucomm.h: New exported funtion from bucomm.c: non_fatal(). + * bucomm.c (non_fatal): New exported function. Just like fatal() + except that it returns rather than calling xexit(). + + (bfd_check_format_matches): Call fatal() rather than bfd_fatal(). + + (check_matching_formats): Fix C formating. + + (parse_vma): Call fatal(). + +Mon Jun 1 18:26:40 1998 Ian Lance Taylor <ian@cygnus.com> + + From Yuli Barcohen <yuli.barcohen@telrad.co.il>: + * debug.c (debug_type_samep): Avoid endless loops comparing + function and method parameter types. + +Fri May 22 14:02:42 1998 Ian Lance Taylor <ian@cygnus.com> + + * dlltool.c (dump_iat): Comment out; not used. + (display): Rename from tell. Change all callers. + +Thu May 14 14:00:56 1998 Nick Clifton <nickc@cygnus.com> + + * dlltool.c: Add support for Thumb DLLs. Add support for + interworking between ARM and Thumb programs and DLLs. Tidy the + code. + + * binutils.texi: Document dlltool. + + * configure: Build dlltool for thumb-pe targets. + + * version.c (print_version): Include 1998 in copyright strings. + + * stabs.c (parse_stab): Support Win32 style directory separators. + +Sun May 10 22:34:44 1998 Jeffrey A Law (law@cygnus.com) + + * po/Make-in (install-info): New target. + +Fri May 8 10:33:13 1998 Nick Clifton <nickc@cygnus.com> + + * ar.c (usage): Extend information provided about command line + options. + +Wed May 6 15:28:51 1998 Klaus Kaempf <kkaempf@progis.de> + + * makefile.vms: Run dec c with /nodebug. Pass CC value when + calling make. + +Tue May 5 15:19:00 1998 Nick Clifton <nickc@cygnus.com> + + * configure: Build dlltool for thumb-pe target. + * configure.in: Build dlltool for thumb-pe target. + +Sun May 3 22:04:49 1998 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.am (EXTRA_PROGRAMS): Change $(SRCONV_PROG) to sysconf + sysdump coffdump to avoid extra $(EXEEXT). + * Makefile.in: Rebuild. + +Wed Apr 29 22:22:55 1998 Geoffrey Noer <noer@cygnus.com> + + * configure.in: Stop appending EXEEXT to the end of + SRCONV_PROG (wrong because that variable may contain multiple + programs) + * Makefile.am: instead, add EXEEXTs to each SRCONV_PROG + program + * Makefile.in: regenerate + * configure: regenerate + +Tue Apr 28 19:14:34 1998 Tom Tromey <tromey@cygnus.com> + + * addr2line.c (main): Conditionally call setlocale. + * windres.c (main): Likewise. + * sysdump.c (main): Likewise. + * strings.c (main): Likewise. + * srconv.c (main): Likewise. + * size.c (main): Likewise. + * objdump.c (main): Likewise. + * objcopy.c (main): Likewise. + * nm.c (main): Likewise. + * nlmconv.c (main): Likewise. + * dlltool.c (main): Likewise. + * coffdump.c (main): Likewise. + * ar.c (main): Likewise. + * bucomm.h: Include <locale.h> if HAVE_LOCALE_H. + (LC_MESSAGES): Now can be defined even when ENABLE_NLS. + +Tue Apr 28 10:33:07 1998 Bill Moyer <ttk@cygnus.com> + + Add support for IMPORTS: + * defparse.y (impline): Add IMPORTS syntaxes. + * dlltool.c (ifunctype, iheadtype): New typedefs. + (import_list): New static variable. + (append_import): New static function. + (def_import): Add an entry to import_list. + (generate_idata_ofile): New static function. + (gen_exp_file): Call generate_idata_ofile. + * dlltool.h (def_import): Update declaration. + +Mon Apr 27 16:39:22 1998 Ian Lance Taylor <ian@cygnus.com> + + * configure.in: Change version number to 2.9.4 + * configure: Rebuild. + +Wed Apr 22 16:00:35 1998 Tom Tromey <tromey@cygnus.com> + + * po/Make-in (MKINSTALLDIRS): Don't look in $(top_srcdir). + +Wed Apr 22 00:33:56 1998 Tom Tromey <tromey@scribbles.cygnus.com> + + * Makefile.am (INCLUDES): Search intl dirs for headers; define + LOCALEDIR. + * addr2line.c (main): Call setlocale, bindtextdomain, textdomain. + * ar.c (main): Likewise. + * coffdump.c (main): Likewise. + * dlltool.c (main): Likewise. + * nlmconv.c (main): Likewise. + * nm.c (main): Likewise. + * objcopy.c (main): Likewise. + * objdump.c (main): Likewise. + * size.c (main): Likewise. + * srconv.c (main): Likewise. + * strings.c (main): Likewise. + * sysdump.c (main): Likewise. + * windres.c (main): Likewise. + +Tue Apr 21 22:13:08 1998 Tom Tromey <tromey@scribbles.cygnus.com> + + * Many files: Added gettext invocations around user-visible + strings. + * bucomm.h: Added gettext-related includes and defines. + * acconfig.h (ENABLE_NLS, HAVE_CATGETS, HAVE_GETTEXT, HAVE_STPCPY, + HAVE_LC_MESSAGES): Define. + * configure.in: Call CY_GNU_GETTEXT. Create po/Makefile.in and + po/Makefile. Use AM_PROG_LEX. + * Makefile.am (SUBDIRS): New macro. + (POTFILES): Likewise. + (po/POTFILES.in): New target. + (LDADD): Added INTLLIBS. + (objdump_LDADD): Likewise. + (c__filt_LDADD): Likewise. + (ar_LDADD): Likewise. + (ranlib_LDADD): Likewise. + (dlltool_LDADD): Likewise. + (windres_LDADD): Likewise. + * po/Make-in, po/POTFILES.in, po/binutils.pot: New files. + +Tue Apr 21 16:07:18 1998 Stanislav Brabec <utx@k332.feld.cvut.cz> + + * objcopy.c (preserve_dates): New file static variable. + (smart_rename): If preserve_dates, call set_times when copying. + (strip_main): Remove preserve_dates local variable. + (copy_main): Likewise. + +Tue Apr 7 15:41:15 1998 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.am (DISTSTUFF): Add defparse.h, defparse.c, rclex.c, + rcparse.h, and rcparse.c + * Makefile.in: Rebuild. + +Mon Apr 6 16:24:35 1998 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.am (PROGS): Move $(ADDR2LINE_PROG) to end, so that + Makefile.in doesn't have an empty continuation line. + (bin_PROGRAMS): Likewise. + * Makefile.in: Rebuild. + +Fri Apr 3 14:48:42 1998 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.am (DISTCLEANFILES): Add site.exp and site.bak. + (MOSTLYCLEANFILES): Add binutils.log, binutils.sum, and abcdefgh*. + (mostlyclean-local): New target. + * Makefile.in: Rebuild. + +Wed Apr 1 15:54:16 1998 Ian Lance Taylor <ian@cygnus.com> + + From Zack Weinberg <zack@rabi.phys.columbia.edu> and H.J. Lu + <hjl@gnu.org>: + * ar.c (usage): Mention S modifier. + (main): Add S modifier. + * ar.1, binutils.texi: Document S modifier. + +Wed Apr 1 13:11:23 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * binutils.texi: Use @itemx for a secondary item in a table. + +Tue Mar 31 18:44:13 1998 Ian Lance Taylor <ian@cygnus.com> + + * dep-in.sed: Add rule to remove @OBJDIR@. + * Makefile.am (dep.sed): Substitute for @OBJDIR@. + * Makefile.in: Rebuild. + +Mon Mar 30 12:47:18 1998 Ian Lance Taylor <ian@cygnus.com> + + * configure.in: Set version to 2.9.1. + * configure: Rebuild. + + * Branched binutils 2.9. + + * Makefile.am (DISTCLEANFILES): Remove defparse.h, arparse.h, + rcparse.h, and nlmheader.h. + * Makefile.in: Rebuild. + +Sat Mar 28 17:39:27 1998 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.am (MOSTLYCLEANFILES): Define. + * Makefile.in: Rebuild. + + Fix some gcc -Wall warnings: + * nlmconv.c (main): Add casts to avoid warnings. + (alpha_mangle_relocs): Likewise. + * objdump.c (dump_section_stabs): Likewise. + * size.c (print_sysv_format): Likewise. + * srcconv.c (wr_ob): Likewise. + * wrstabs.c (stab_modify_type): Likewise. + (stab_variable): Likewise. + * nlmconv.c (main): Initialize variables to avoid warnings. + * nm.c (sort_symbols_by_size): Likewise. + * objdump.c (disassemble_bytes): Likewise. + * wrstabs.c (stab_end_class_type): Likewise. + * coffgrok.c (do_sections_p2): Change j to unsigned int. + (do_lines): Change l to unsigned int. + * nlmheader.y (yylex): Change i to unsigned int. + * nm.c (print_symbol): Change j to long. + * size.c (lprint_number): Comment out. + * srconv.c (wr_ob): Change i to bfd_size_type. + * sysdump.c (unit_info_list): Comment out. + (object_body_list, program_structure, debug_list): Likewise. + * sysinfo.y (yyerror): Return value. + +Thu Mar 26 17:06:51 1998 Richard Henderson <rth@cygnus.com> + + * defparse.y (explist): Allow epsilon. + Suggestion from Jonathan-Harris@psion.com. + +Thu Mar 26 16:59:09 1998 Richard Henderson <rth@cygnus.com> + + * coffgrok.c (do_sections_p1): Use the section's lma instead of vma + for the benefit of prom loaders. + +Wed Mar 25 13:05:39 1998 Ian Lance Taylor <ian@cygnus.com> + + Based on patch from H.J. Lu <hjl@gnu.org>: + * Makefile.am (DISTSTUFF): New variable. + (diststuff): New target. + (DISTCLEANFILES): New variable. + * Makefile.in: Rebuild. + +Tue Mar 24 19:33:08 1998 Ian Lance Taylor <ian@cygnus.com> + + * rclex.l: Accept { and } as synonyms for BEGIN and END. + +Fri Mar 20 19:18:08 1998 Ian Lance Taylor <ian@cygnus.com> + + * aclocal.m4, configure: Rebuild with libtool 1.2. + +Tue Feb 24 13:07:50 1998 Doug Evans <devans@canuck.cygnus.com> + + * objdump.c (disassemble_data): Delete "++place" after call to + find_symbol_for_address. Set disasm_info.symbols to array of + symbols at the current address. + +Wed Feb 18 23:39:46 1998 Richard Henderson <rth@cygnus.com> + + * Makefile.am (install-exec-local): Install properly when ln + fails or tooldir == prefix. + +Tue Feb 17 18:40:55 1998 Richard Henderson <rth@cygnus.com> + + * objcopy.c (compare_section_lma): Rename from _vma. + (copy_object): Gap fill based on LMA not VMA. + * binutils.texi: Update and clarify. + * objcopy.1: Likewise. + +Tue Feb 17 20:34:11 1998 Ian Lance Taylor <ian@cygnus.com> + + * dlltool.c (gen_exp_file): Generate _imp__%s as well as __imp_%s, + for Microsoft compatibility. + (make_one_lib_file): Likewise. + + * dlltool.c (make_one_lib_file): Don't add 1 to hint. + +Fri Feb 13 16:37:44 1998 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.am (AUTOMAKE_OPTIONS): Define. + * configure, Makefile.in, aclocal.m4: Rebuild with automake 1.2e. + +Thu Feb 12 14:13:46 1998 Ian Lance Taylor <ian@cygnus.com> + + * deflex.l: Accept '?' in symbol names, for VC++ mangled names. + From Mikey <jeffdb@netzone.com>. + + * addr2line.c (usage): Update bug-gnu-utils address. + * ar.c (usage): Likewise. + * nlmconv.c (show_usage): Likewise. + * nm.c (usage): Likewise. + * objcopy.c (copy_usage): Likewise. + (strip_usage): Likewise. + * objdump.c (usage): Likewise. + * size.c (usage): Likewise. + * strings.c (usage): Likewise. + * windres.c (usage): Likewise. + * binutils.texi (Bug Reporting): Likewise. + +Sat Feb 7 15:36:24 1998 Ian Lance Taylor <ian@cygnus.com> + + * configure, aclocal.m4: Rebuild with new libtool. + +Thu Feb 5 12:21:13 1998 Ian Lance Taylor <ian@cygnus.com> + + * configure, Makefile.in, aclocal.m4: Rebuild with new libtool. + +Fri Jan 30 19:16:28 1998 Doug Evans <devans@canuck.cygnus.com> + + * Makefile.am (CC_FOR_TARGET,nlmcomv.o): Change program_transform_name + to transform. + * Makefile.in: Regenerate. + +Thu Jan 29 16:24:04 1998 Mumit Khan <khan@xraylith.wisc.edu> + + * dlltool.c: Define exit status macros for _WIN32 but not + __CYGWIN32__. + (gen_lib_file): Check for exit status of unlink. + * resrc.c: Define popen and pclose if _WIN32 but not + __CYGWIN32__. + +Wed Jan 28 17:45:46 1998 Ian Lance Taylor <ian@cygnus.com> + + * configure.in: Remove vfork check. + * nlmconv.c: Never include vfork.h. + * aclocal.m4, configure, Makefile.in, config.in: Rebuild. + +Wed Jan 28 17:43:02 1998 J.J. van der Heijden <J.J.vanderHeijden@student.utwente.nl> + + * objcopy.c (copy_archive): Only pass one argument to mkdir if + _WIN32 but not __CYGWIN32__. + (smart_rename): Add code for _WIN32 (not __CYGWIN32__), to cope + with different rename behaviour and lack of chown. + + * configure.in: Check for mingw32 when deciding whether to build + dlltool. + * dlltool.c: Never include vfork.h. + (run): Use pexecute rather than vfork. + (gen_lib_file): Check for errors from bfd_set_archive_head and + bfd_close. Close all the BFDs in the archive before deleting the + temporary files. + +Thu Jan 22 16:22:55 1998 Fred Fish <fnf@cygnus.com> + + * objdump.c (disassemble_bytes): Add flag INSN_HAS_RELOC to tell + disassembly function there is a reloc on this line. + +Wed Jan 14 15:29:43 1998 Richard Henderson <rth@cygnus.com> + + * srconv.c (sh, h8300): Delete variables. + (addrsize, toolname, rnames): New variables. + (writeINT): Use addrsize. + (wr_un): Use toolname. + (wr_hd): Set up addrsize et al properly for h8300[hs]. + (walk_tree_symbol): Zero dsy. Use rnames. + (wr_un, wr_hd, wr_ob, wr_du): Use proper bfd access macros. + * sysdump.c (sh, h8300): Delete variables. + (addrsize): New variable. + (getINT): Use it. + (getone): Initialize it. + (getBITS): Range check on MAX. + +Mon Dec 29 16:58:05 1997 Ian Lance Taylor <ian@cygnus.com> + + From Matthew Bellantoni <matthew@chrysalis.com>: + * ar.c (get_pos_bfd): Add default_posname parameter. Change all + callers. + (replace_members): Default to replacing in the same position. + +Mon Dec 22 11:27:22 1997 Ian Lance Taylor <ian@cygnus.com> + + * rclex.l: Don't permit a comma in a STRING. + * rcparse.y (acc_entry): Warn if an inappropriate modifier is used + with a non VIRTKEY. + (acc_event): For a control character, set VIRTKEY, and force the + character to uppercase. + (acc_options): Don't require a comma separator. + +Tue Dec 9 13:25:42 1997 Michael Meissner <meissner@cygnus.com> + + * size.c (size_number): New function to provide size of field. + ({l,r}print_number): For octal and hex fields, print field using + '0' and '0x' suffixes. Do not include following tab. + (sysv_internal_sizer): Size section name, section size, and vma + address fields. + (sysv_internal_printer): Use calculated sizes for the columns. + (print_sysv_format): Size columns before printing. + (print_berkeley_format): Print tabs between numbers now that + {l,r}print_number doesn't. Print fields right justified. + +Mon Dec 8 11:22:04 1997 Nick Clifton <nickc@cygnus.com> + + * objdump.c (objdump_print_addr_with_sym): Remove call to + disasm_symaddr() as this function no longer exists. + +Tue Dec 2 10:23:50 1997 Nick Clifton <nickc@cygnus.com> + + * objdump.c (objdump_print_addr_with_sym): Call disasm_symaddr() + to allow backend to know which symbol has just been displayed. + +Tue Dec 2 13:06:46 1997 Ian Lance Taylor <ian@cygnus.com> + + * windres.h (ESCAPE_*): Define standard escape sequences. + * rclex.l (handle_quotes): Handle standard escape sequences. Warn + about an unrecognized escape character. + * windres.c (unicode_print): Print standard escape sequences. + * rcparse.y (acc_event): Initialize $$.next. + * resbin.c (bin_to_res_menuitems): Don't set MENUITEM_POPUP or + MENUITEM_ENDMENU in the menu item flags. + (bin_to_res_accelerators): Allocate a structure (the old code + never worked). + (res_to_bin_accelerator): Correct the test for setting ACC_LAST. + (res_to_bin_dialog): Save the extended style rather than saving + the style twice. Remove useless shadowing length variable. Set + the length of control data correctly. + * resrc.c (write_rc_dialog): Don't print the class or menu if the + string length is zero. + +Mon Nov 24 18:52:43 1997 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * stabs.c (parse_stab_argtypes): Don't try to parse the name of a + destructor as mangled argument types. + +Mon Nov 10 17:51:41 1997 Gavin Koch <gavin@cygnus.com> + + * addr2line.c (translate_addresses): Use bfd_scan_vma rather + than strtol to scan addresses. + +Sun Nov 9 11:01:31 1997 Jeffrey A Law (law@cygnus.com) + + * Makefile.am (bin_PROGRAMS): Don't use line continuations here. + +Tue Nov 4 11:56:14 1997 Ian Lance Taylor <ian@cygnus.com> + + * objcopy.c (copy_section): Don't crash if there is no particular + information for a section. + +Mon Nov 3 12:36:19 1997 Ian Lance Taylor <ian@cygnus.com> + + * objcopy.c (parse_flags): Make flag check case insensitive. + Check for `contents' flag. Give an error for unrecognized flags. + (copy_section): If the contents flag was set for a section that + had no contents, zero out the new contents. + * binutils.texi (objcopy): Document contents section flag. + +Sun Nov 2 14:49:56 1997 Ian Lance Taylor <ian@cygnus.com> + + * objcopy.c: Move new struct and variable definitions to top of + file. Remove obsolete add_strip_symbol and is_strip_symbol + declarations. Add prototype declarations for add_specific_symbol + and is_specified_symbol. + +Mon Oct 20 15:31:43 1997 Klaus K"ampf <kkaempf@progis.de> + + * configure.com (HAVE_SBRK): Undefine. + +Tue Oct 14 16:14:35 1997 Nick Clifton <nickc@cygnus.com> + + * objdump.c (objdump_symbol_at_address): New function. Returns + true if a symbol can be found at the address passed in. + (disassemble_data): Set the symbol_at_address_func field to point + to objdump_symbol_at_address. + +Fri Oct 10 14:13:09 1997 Richard Henderson <rth@cygnus.com> + + * objcopy.c, objcopy.1, binutils.texi: "localize" is a better name + than "privatize". Update all references. + +Thu Oct 9 15:57:29 1997 Ian Lance Taylor <ian@cygnus.com> + + * binutils.texi (strip): Remove duplicate --target. From Marty + Leisner <leisner@sdsp.mc.xerox.com>. + + * nm.c (lineno_cache_bfd): New file static variable. + (lineno_cache_rel_bfd): New file static variable. + (display_archive): Clear lineno_cache_bfd and lineno_cache_rel_bfd + when closing a BFD. + (display_file): Likewise. + (print_symbol): Use lineno_cache_bfd and lineno_cache_rel_bfd + instead of cache_bfd and cache_rel_bfd. Make seccount static, and + only set it when setting relocs. + +Wed Oct 8 21:19:11 1997 Richard Henderson <rth@cygnus.com> + + * objcopy.c (keep_specific_list, privatize_specific_list, + weaken_specific_list): New variables. + (keep_symbols): Removed. + (add_specific_symbol): New function from the carcas of + add_strip_symbol. Takes a list as an argument. + (is_specified_symbol): Likewise from is_strip_symbol. + (filter_symbols): Honor the new privatize and weaken lists. + Optimize bfd_asymbol_name handling. + (copy_object, copy_options, copy_usage): Add privatize-symbol & + weaken-symbol options. + + * objcopy.1, binutils.texi: Update docs. + +Sun Oct 5 09:05:44 1997 Frank Ch. Eigler <fche@cygnus.com> + + * objdump.c (disassemble_data): Make "--prefix-addresses" + disassembly adjust to mixed-length instructions. + (objdump_print_addr_with_sym): Add "0x" prefix for hexadecimal + symbol-offsets in disassembly. + +Fri Oct 3 12:04:25 1997 Ian Lance Taylor <ian@cygnus.com> + + * objcopy.c (set_times): New static function, replacing + make_same_dates. + (strip_main): If preserve_dates, stat the input file before + copying it, and call set_times afterward. + (copy_main): Likewise. + + * wrstabs.c (write_stabs_in_sections_debugging_info): Cast p to + char * when calling strcpy and strlen. + +Wed Sep 24 11:34:05 1997 Ian Lance Taylor <ian@cygnus.com> + + * binutils.texi (ar cmdline): Document that q now works like r. + From Marty Leisner <leisner@sdsp.mc.xerox.com>. + + * binutils.texi (size): The object file argument is optional. + From Marty Leisner <leisner@sdsp.mc.xerox.com>. + + * aclocal.m4: Rebuild with new libtool. + * configure: Rebuild. + +Tue Aug 26 17:48:34 1997 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.am (EXEEXT_FOR_BUILD): New variable. Use it in all + references to the sysinfo program. + * configure.in: Rebuild with new bfd/acinclude.m4. + * Makefile.in: Rebuild. + +Fri Aug 8 15:32:49 1997 Ian Lance Taylor <ian@cygnus.com> + + * windres.c: Include <time.h>. + (define_resource): Set a timestamp for the resource. + +Wed Aug 6 13:37:58 1997 Ian Lance Taylor <ian@cygnus.com> + + * configure.in: Define TARGET in header file. + * acconfig.h (TARGET): Add #undef. + * Makefile.am (version.o, bucomm.o): Remove special targets. + * bucomm.c (target): Remove. + * nm.c (program_name): Don't declare. + (target): Make static. + * size.c (target): Make static. + * configure, config.in, Makefile.in: Rebuild. + +Tue Aug 5 00:01:41 1997 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.am (check-DEJAGNU): Export r. + (.dep1): Use $(INCLUDES) rather than $(ALL_CFLAGS). + * Makefile.in: Rebuild. + + * nlmheader.y: Use VERSIONK rather than VERSION. + + * Makefile.am (STRIP_PROG): Change from strip.new to strip-new. + (NM_PROG): Change from nm.new to nm-new. + (TOOL_PROGS, install-exec-local): Adjust accordingly. + * Makefile.in: Rebuild. + +Mon Aug 4 11:47:31 1997 Ian Lance Taylor <ian@cygnus.com> + + * configure.in: Remove AC_ARG_PROGRAM; it's invoked by + AM_INIT_AUTOMAKE. + * configure: Rebuild. + + * Makefile.am (install-exec-local): Create $(tooldir)/bin before + trying to install anything into it. + * Makefile.in: Rebuild. + + * Makefile.am (TOOL_PROGS): Use an explicit $(EXEEXT). + (install-exec-local): When handling $(noinst_PROGRAMS), only use + $(EXEEXT) on the installed file. When handling $(TOOL_PROGS), + handle $(EXEEXT) correctly. + * configure.in: Add an explicit $(EXEEXT) when substituting for + the name of a program to build. + * Makefile.in, configure: Rebuild. + + * aclocal.m4, configure, Makefile.in: Rebuild with new automake + patches. + + * deflex.l, defparse.y: Use VERSIONK rather than VERSION. + * rclex.l, rcparse.y: Likewise. + * Makefile.am (windres_SOURCES): Add $(BULIBS). + * Makefile.in: Rebuild. + +Fri Aug 1 13:08:39 1997 Ian Lance Taylor <ian@cygnus.com> + + * acinclude.m4: Include bfd/acinclude.m4, not bfd/acmacros.m4. + * aclocal.m4, configure: Rebuild with new libtool. + +Thu Jul 31 11:51:35 1997 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.am: New file, based on old Makefile.in. + * acinclude.m4: New file, from old aclocal.m4. + * configure.in: Call AM_INIT_AUTOMAKE and AM_PROG_LIBTOOL. Remove + shared library handling; now handled by libtool. Replace + AC_CONFIG_HEADER with AM_CONFIG_HEADER. Call AC_PROG_YACC, + AC_PROG_LEX, AC_DECL_YYTEST, AM_MAINTAINER_MODE, AM_CYGWIN32, and + AM_EXEEXT. Replace AC_PROG_INSTALL with AM_PROG_INSTALL. Remove + stamp-h handling in AC_OUTPUT. + * acconfig.h: Mention PACKAGE and VERSION. + * stamp-h.in: New file. + * Makefile.in: Now built with automake. + * aclocal.m4: Now built with aclocal. + * config.in, configure: Rebuild. + + From Ton van Overbeek <tvoverbe@wk.estec.esa.nl>: + * rcparse.y (dialog): Default menu and class to be named. + (styles): If FONT is seen, set DS_SETFONT in dialog style. + * resbin.c (res_to_bin_dialog): Correct computation of font + information length. + +Wed Jul 30 11:21:06 1997 Ian Lance Taylor <ian@cygnus.com> + + From Ton van Overbeek <tvoverbe@wk.estec.esa.nl>: + * resbin.c (res_to_bin_menu): Correct computation of menu + vs. menuex length. + * resrc.c (define_stringtable): Add 1 to resource ID. + +Tue Jul 29 11:06:03 1997 Ian Lance Taylor <ian@cygnus.com> + + * resbin.c (bin_to_res_string): Correct adjustment of data and + length. From Ton van Overbeek <tvoverbe@wk.estec.esa.nl>. + +Tue Jul 22 18:01:23 1997 Ian Lance Taylor <ian@cygnus.com> + + * nlmconv.c (link_inputs): Call libiberty pexecute function. + (pexecute) [multiple versions]: Remove. + +Tue Jul 22 16:19:34 1997 Robert Hoehne <robert.hoehne@Mathematik.TU-Chemnitz.DE> + + * bucomm.c (make_tempname): If we might be using a DOS filesystem, + check for a backslash as well as a slash. + +Thu Jun 26 13:53:17 1997 Ian Lance Taylor <ian@cygnus.com> + + * windres.c (main): Quit if we didn't get any resources. + (usage): Fix --yydebug usage message. + * rescoff.c (write_coff_file): Don't free the relocation array + until after we've closed the BFD. + (read_coff_rsrc): Quit rather than try to read standard input. + (write_coff_file): Quit rather than try to write to standard + output. + * rcparse.y: Add a couple of missing semicolons (accepted by bison + but not byacc). + * binutils.texi: Document windres. + +Wed Jun 25 20:57:06 1997 Ian Lance Taylor <ian@cygnus.com> + + * resbin.c: New file. + * rclex.l, rcparse.y, rescoff.c, resrc.c, windres.c, windres.h: + Numerous fixes and improvements. + * Makefile.in: Rebuild dependencies. + (CFILES): Add resbin.c. + (WINDRES_OBJS): Add resbin.o. + +Sun Jun 22 17:29:41 1997 Ian Lance Taylor <ian@cygnus.com> + + First stab at Windows resource compiler: + * windres.h: New file. + * windres.c: New file. + * resrc.c: New file. + * rcparse.y: New file. + * rclex.l: New file. + * rescoff.c: New file. + * configure.in: Define and substitute BUILD_WINDRES. + * configure: Rebuild. + * Makefile.in: Rebuild dependencies. + (WINDRES_PROG): New variable. + (PROGS): Add @BUILD_WINDRES@. + (HFILES): Add dlltool.h and windres.h. + (CFILES): Add windres.c and resrc.c. + (GENERATED_CFILES): Add rcparse.c and rclex.c. + (WINDRES_OBJS): New variable. + $(WINDRES_PROG): New target. + (rcparse.c, rcparse.h, rclex.c): New targets. + +Thu Jun 12 12:27:51 1997 Ian Lance Taylor <ian@cygnus.com> + + * dlltool.c (export_type): Add data field. + (def_exports): Add data parameter. Change all callers. + (dump_def_info): Print data field. + (gen_def_file): Likewise. + (make_one_lib_file): Handle data field by not emitting simple + label and not emitting anything in SEC_TEXT. + (dtab): Print data field. + (process_duplicates): Merge data field. + * dlltool.h (def_exports): Update declaration. + * defparse.y (expline): Accept opt_DATA. Pass it to def_exports. + (opt_DATA): New non-terminal. + +Wed Jun 11 17:15:47 1997 Ian Lance Taylor <ian@cygnus.com> + + * dlltool.h: New file. + * deflex.l: Include dlltool.h and libiberty.h. Don't declare + strdup. Use xstrdup rather than strdup. + * defparse.y: Include bfd.h, bucomm.h, and dlltool.h. + * dlltool.c: Include dlltool.h and time.h. Make a lot of + variables and functions static. Make a lot of char * variables + and parameters const. Add declarations for static functions. Do + some reindenting. Hide more PowerPC stuff inside DLLTOOL_PPC. + +Wed Jun 11 12:05:52 1997 H.J. Lu <hjl@gnu.ai.mit.edu> + + * ar.c (bfd_special_undocumented_glue): Add const. + +Mon May 12 22:09:35 1997 Bob Manson <manson@charmed.cygnus.com> + + * Makefile.in (check): Pass CC_FOR_TARGET and CFLAGS_FOR_TARGET + to runtest. + +Mon May 12 13:14:22 1997 Ian Lance Taylor <ian@cygnus.com> + + * configure.in: Don't clear OPCODES when --enable-commonbfdlib is + used on HP/UX. + * configure: Rebuild. + +Fri Apr 25 14:22:08 1997 H.J. Lu <hjl@gnu.ai.mit.edu> + + * Makefile.in (maintainer-clean realclean): Change *.info* + to binutils.info* to save sysroff.info. + +Tue Apr 15 13:42:22 1997 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.in (INSTALL): Set to @INSTALL@. + (INSTALL_XFORM, INSTALL_XFORM1): Remove. + (install): Depend upon installdirs. Use $(program_transform_name) + directly, rather than using $(INSTALL_XFORM) and + $(INSTALL_XFORM1). + (installdirs): New target. + (install-info): Run mkinstalldirs. + +Mon Apr 14 11:52:39 1997 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.in (INSTALL): Change install.sh to install-sh. + + From Thomas Graichen <graichen@rzpd.de>: + * Makefile.in: Always use $(SHELL) when running move-if-change. + * configure.in: Use ${CONFIG_SHELL} when running $ac_config_sub. + * configure: Rebuild. + +Fri Apr 4 13:28:02 1997 Ian Lance Taylor <ian@cygnus.com> + + * configure.in: Add AC_FUNC_ALLOCA. + * configure, config.in: Rebuild. + * bucomm.h: Add alloca handling, copied from gas/as.h. + * dlltool.c: Add #pragma alloca for AIX to start of file. + * nlmconv.c: Likewise. + + * Makefile.in (distclean): Remove site.exp and site.bak. Remove + everything that clean removes. + +Thu Apr 3 13:18:39 1997 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.in (VERSION): Set to 2.8.1. + + * Branched binutils 2.8. + +Tue Apr 1 16:21:44 1997 Klaus Kaempf <kkaempf@progis.de> + + * configure.com: New file. + * config.h-vms: Remove file. + * makefile.vms: Update for new configure scheme. + +Mon Mar 31 15:30:43 1997 Philippe De Muyter <phdm@info.ucl.ac.be> + + * objcopy.c (make_same_dates): Use statbuf, not buf, if not + HAVE_GOOD_UTIME_H. + +Fri Mar 28 17:57:53 1997 Alan Modra <alan@spri.levels.unisa.edu.au> + + * Makefile.in ($(OBJDUMP_PROG)): Don't link against BFDLIB twice. + * configure.in: Add AC_ARG_ENABLE for commonbfdlib. If it is set, + set OPCODES to empty. + * configure: Rebuild. + +Thu Mar 27 16:03:02 1997 Ian Lance Taylor <ian@cygnus.com> + + Based on patch from Marty Leisner <leisner@sdsp.mc.xerox.com>: + * objcopy.c: Include <utime.h> or <sys/time.h>. + (strip_options): Add "preserve-dates". + (copy_options): Likewise. + (copy_usage): Mention -p and --preserve-dates. + (strip_usage): Likewise. + (make_same_dates): New static function. + (strip_main): Handle -p. + (copy_main): Likewise. + * binutils.texi, strip.1, objcopy.1: Document new option. + + addr2line.c contributed by Ulrich Lauther + <Ulrich.Lauther@zfe.siemens.de>: + * addr2line.c: New file. + * Makefile.in: Rebuild dependencies. + (ADDR2LINE_PROG): New variable. + (MANPAGES): Add addr2line. + (PROGS): Add $(ADDR2LINE_PROG). + (CFILES): Add addr2line.c. + ($(ADDR2LINE_PROG)): New target. + * binutils.texi: Document addr2line. + * addr2line.1: New file. + + * version.c (print_version): Update copyright date. + +Mon Mar 24 10:52:45 1997 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * objdump.c (disassemble_data): Don't exit if a file cannot be + disassembled, instead just return. + +Thu Mar 20 21:16:51 1997 Jeffrey A Law (law@cygnus.com) + + * size.c (usage): Make definition match its prototype. + (display_bfd, lprint_number, rprint_number): Likewise. + (print_berkeley_format, sysv_internal_printer): Likewise. + (print_sysv_format): Likewise. + * nm.c (set_print_radix, set_output_format): Likewise. + * objcopy.c (filter_bytes): Likewise. + +Tue Mar 18 16:39:55 1997 H.J. Lu <hjl@lucon.org> + + * Many files: Add function prototypes. + * ar.c (mri_emul, get_pos_bfd): Make static. + * arlex.l: Include "libiberty.h". Don't declare strdup. Use + xstrdup rather than strdup. + * arparse.y (yyerror): Make argument const. Correct typo. + * arsup.c (strdup): Don't declare. + (ar_save): Use xstrdup rather than strdup. + * filemode.c: Include "bucomm.h". + * nm.c (usage): Make static. + (print_symname): Make format and name const. + * objcopy.c (cat): Remove. + (copy_archive): Make output_target const. Use concat, not cat. + (copy_file, simple_copy, smart_rename): Make arguments const. + * objdump.c (read_section_stabs): Likewise. + (print_section_stabs): Likewise. + (display_target_tables): Don't declare getenv. + * strings.c (strings_object_file): Change file to const. + (print_strings): Change filename to const. + * Makefile.in: Rebuild dependencies. + +Tue Mar 18 11:37:24 1997 Ian Lance Taylor <ian@cygnus.com> + + * configure.in: Add BFD_NEED_DECLARATION(getenv). + * acconfig.h: Add NEED_DECLARATION_GETENV. + * bucomm.h (getenv): Declare if NEED_DECLARATION_GETENV. + * configure, config.in: Rebuild. + * nlmconv.c (getenv): Don't declare. + + * Makefile.in: Rebuild dependencies. + +Sat Mar 15 15:35:56 1997 Ian Lance Taylor <ian@cygnus.com> + + Based on patches from Jamie Lokier <jamie@rebellion.co.uk>: + * objdump.c: Include "demangle.h". + (do_demangle): New static variable. + (usage): Mention -C/--demangle. + (long_options): Add "demangle". + (objdump_print_symname): New static function. + (objdump_print_addr_with_sym): Use objdump_print_symname. + (disassemble_bytes): Likewise. + (dump_reloc_set): Likewise. + (dump_symbols): Demangle symbol name. + (main): Handle -C. + * binutils.texi, objdump.1: Document -C/--demangle. + + * objdump.c (usage): Mention --no-show-raw-insn. + (long_options): Add "no-show-raw-insn". + (disassemble_bytes): Handle --no-show-raw-insn. + * binutils.texi, objdump.1: Document --no-show-raw-insn. + +Wed Mar 12 11:42:00 1997 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * rddbg.c (free_saved_stabs): Set the strings to NULL after being + freed. + +Fri Feb 28 17:18:45 1997 Ian Lance Taylor <ian@cygnus.com> + + * bucomm.c (set_default_bfd_target): New function. + * bucomm.h (set_default_bfd_target): Declare. + * ar.c (main): Call set_default_bfd_target. + * nlmconv.c (main): Likewise. + * nm.c (main): Likewise. + * objcopy.c (main): Likewise. + * objdump.c (main): Likewise. + * size.c (main): Likewise. + * strings.c (main): Likewise. + * Makefile.in (bucomm.o): New target, to define TARGET. + +Tue Feb 25 21:28:38 1997 Ian Lance Taylor <ian@cygnus.com> + + * objdump.c (adjust_section_vma): New static variable. + (usage): Mention --adjust-section-vma. + (OPTION_ADJUST_VMA): Define. + (long_options): Add "addjust-vma". + (display_bfd): If adjust_section_vma is not 0, add it to all the + section addresses. + (main): Handle OPTION_ADJUST_VMA. + * binutils.texi, objdump.1: Document --adjust-vma. + +Fri Feb 14 18:46:47 1997 Ian Lance Taylor <ian@cygnus.com> + + * nm.c (print_symbol): Cache the BFD as well as the symbols and + relocs, and don't try to use the symbols or relocs with a + different BFD. + +Thu Feb 13 21:34:43 1997 Klaus Kaempf (kkaempf@progis.de) + + * config.h-vms: sbrk() is provided on openVMS/Alpha. + * makefile.vms: allow compiling with current gcc snapshot. + +Thu Feb 13 20:14:40 1997 Ian Lance Taylor <ian@cygnus.com> + + * arsup.c, coffgrok.c, dlltool.c, nlmconv.c: Use xmalloc rather + than malloc. + +Wed Feb 12 16:12:02 1997 Ian Lance Taylor <ian@cygnus.com> + + * objdump.c (disassemble_data): Correct VMA argument to + find_symbol_for_address. Improve handling of code with no symbol + followed by code with a symbol. + +Wed Feb 12 12:16:47 1997 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * objdump.c (disassemble_bytes): Make output of raw instructions + work better for non-standard values of bytes_per_chunk and + bytes_per_line. + +Thu Feb 6 14:14:59 1997 Martin M. Hunt <hunt@pizza.cygnus.com> + + * objdump.c (disassemble_bytes): Added code to allow some control + over the way raw instructions are displayed. + +Thu Feb 6 12:36:03 1997 Ian Lance Taylor <ian@cygnus.com> + + * stabs.c (struct bincl_file): Add next_stack field. + (push_bincl): Put the new file on both bincl_list and + bincl_stack. Clear the file_types field. + (pop_bincl): Use the next_stack field when popping the stack. + Don't put the file on bincl_list. + (find_excl): Include the file name when warning about an unfound + N_EXCL. + + * debug.c (debug_type_samep): Don't crash if we are passed NULL. + +Thu Feb 6 11:54:24 1997 Alan Modra <alan@spri.levels.unisa.edu.au> + + * objcopy.1: Add missing space after .B. + +Fri Jan 31 10:33:07 1997 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * objdump.c (disassemble_data): Initialize `aux.require_sec'. + +Wed Jan 29 13:21:21 1997 Ian Lance Taylor <ian@cygnus.com> + + * objdump.c (objdump_print_value): Add skip_zeroes parameter. + Change all callers. + (objdump_print_addr_with_sym): Likewise. Call objdump_print_value + to print address. + (objdump_print_addr): New static function. + (objdump_print_address): Just call objdump_print_addr. + (disassemble_bytes): Print real address, not function offset. + Skip a certain number of leading zeroes. + + * objdump.c (disassemble_zeroes): New static variable. + (usage): Mention --disassemble-zeroes. + (long_options): Add "disassemble-zeroes". + (disassemble_bytes): Check disassemble_zeroes. + +Tue Jan 28 16:47:26 1997 Ian Lance Taylor <ian@cygnus.com> + + * objdump.c (disassemble_bytes): Don't skip zeroes if the + disassembler has told us that we are in a branch delay slot. + +Mon Jan 20 14:24:04 1997 Ian Lance Taylor <ian@cygnus.com> + + * size.c (berkeley_sum): Rewrite. Skip sections which are not + SEC_ALLOC. Count SEC_READONLY sections as text. + +Tue Jan 14 15:14:14 1997 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.in (maintainer-clean realclean): Remove *.info*, not + just *.info. From H.J. Lu <hjl@lucon.org>. + +Tue Dec 31 15:42:54 1996 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.in (ALL_CFLAGS): Add -D_GNU_SOURCE. + +Fri Dec 27 11:19:26 1996 Ian Lance Taylor <ian@cygnus.com> + + * configure.in: Work around bug in AC_FUNC_VFORK in autoconf 2.12. + * configure: Rebuild. + +Thu Dec 19 13:11:20 1996 Ian Lance Taylor <ian@cygnus.com> + + Based on patch from Andrew J Klossner <andrew@pogo.wv.tek.com>: + * objcopy.c (OPTION_WEAKEN): Define. + (copy_options): Add "weaken". + (copy_usage): Mention --weaken. + (weaken): New static variable. + (filter_symbols): Handle weaken. + (copy_object): Call filter_symbols if weaken. + (copy_main): Handle OPTION_WEAKEN. + * binutils.texi, objcopy.1: Document --weaken. + +Wed Dec 18 22:49:13 1996 Stan Shebs <shebs@andros.cygnus.com> + + * mpw-make.sed: Use NewFolderRecursive for installation. + +Sat Dec 7 10:17:25 1996 Jeffrey A Law (law@cygnus.com) + + * Makefile.in (install): Add "else true" clause to cater to + broken "make" on some systems. + +Fri Dec 6 17:21:41 1996 Ian Lance Taylor <ian@cygnus.com> + + * ieee.c (parse_ieee_bb): Always initialize namcopy to avoid gcc + warning about uninitialized variable. + (ieee_read_cxx_class): Likewise, for pf. + (ieee_enum_type): Likewise, for i. + +Tue Nov 26 17:01:25 1996 Ian Lance Taylor <ian@cygnus.com> + + * wrstabs.c (stab_array_type): Add casts when printing + bfd_signed_vma values. + + * configure: Rebuild with autoconf 2.12. + +Mon Nov 25 16:53:18 1996 Ian Lance Taylor <ian@cygnus.com> + + * objdump.c (disassemble_data): Don't crash if there is no + symbol. + +Fri Nov 22 17:29:14 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * ar.c (open_inarch): Don't call bfd_openr with a null name. + +Fri Nov 1 12:08:13 1996 Ian Lance Taylor <ian@cygnus.com> + + * binutils.texi: Add section on reporting bugs. + +Thu Oct 31 18:20:53 1996 Ian Lance Taylor <ian@cygnus.com> + + * stabs.c (struct stab_handle): Add bincl_list field. + (parse_stab): Pass value to push_bincl. Call find_excl for + N_EXCL. + (struct bincl_file): Add hash, file and file_types fields. + (push_bincl): Add hash parameter. Save it in the new hash field. + Save the file number in the new file field. + (pop_bincl): Put the bincl_file on bincl_list, rather than freeing + it. Save the file types in the new file_types field. + (find_excl): New static function. + + * ieee.c (ieee_lineno): Don't compare line number addresses to + info->highaddr (undo part of October 28 patch). + +Tue Oct 29 16:40:22 1996 Ian Lance Taylor <ian@cygnus.com> + + * objdump.c (objdump_print_value): Don't print the empty string + for zero. + +Mon Oct 28 16:58:14 1996 Ian Lance Taylor <ian@cygnus.com> + + * stabs.c (struct stab_handle): Add function_end field. + (start_stab): Initialize function_end. + (finish_stab): Pass info->function_end to debug_end_function. + (parse_stab): If info->function_end is set, use it as the address + which ends a function. + + * ieee.c (ieee_array_type): Remember the correct size. + + * ieee.c (ieee_finish_compilation_unit): Permit coalescing ranges + that are up to 0x1000 bytes apart, not just 64. + (ieee_add_bb11_blocks): Don't bother to emit a BB11 that is less + than 0x100 bytes. + (ieee_lineno): Only emit line numbers that are less than + info->highaddr. + +Fri Oct 25 12:12:17 1996 Ian Lance Taylor <ian@cygnus.com> + + * ieee.c (struct ieee_defined_enum): Add defined field. + (ieee_enum_type): If the enum tag has been seen before but not + defined, reuse the same type index, and define it. + (ieee_tag_type): If this enum has not been defined, add an + undefined entry to the list of enums. + + * objdump.c (disassemble_bytes): Let the disassembler override the + number of bytes printed on a line. + +Thu Oct 24 16:42:10 1996 Ian Lance Taylor <ian@cygnus.com> + + * objdump.c (prefix_addresses): New static variable. + (long_options): Add "prefix-addresses". + (compare_symbols): Sort BSF_FUNCTION symbols before other + symbols. + (find_symbol_for_address): New static function, broken out of + objdump_print_address. + (objdump_print_addr_with_sym): New static function, broken out of + objdump_print_address. + (objdump_print_address): Call new functions. + (disassemble_bytes): New static function, broken out of + disassemble_data. Change disassembly format, unless + prefix_addresses is set. + (disassemble_data): Call disassemble_bytes. Unless + prefix_addresses is set, disassemble in chunks headed by a + symbol. + * binutils.texi, objdump.1: Document --prefix-addresses. + + * rddbg.c (read_section_stabs_debugging_info): Preserve the + backslash when concatenating multiple stabs strings. + +Thu Oct 10 11:36:31 1996 Doug Evans <dje@canuck.cygnus.com> + + * dlltool.c (scan_open_obj_file): Fix loop exit test. + Add missing parameter to def_exports. + +Tue Oct 8 12:06:17 1996 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.in (LEX_OPTIONS): Set to empty string. -I -Cem is the + default for flex, and is not recognized by lex. + +Thu Oct 3 17:41:23 1996 Ian Lance Taylor <ian@cygnus.com> + + * binutils.texi (Target Selection): Document that you can now + specify targets using configuration triplets. + + * ar.c (usage): Declare. Make sure all callers pass an argument. + +Thu Oct 3 15:39:42 1996 Jason Molenda (crash@godzilla.cygnus.co.jp) + + * Makefile.in (clean): Remove config.log. + +Wed Oct 2 15:49:16 1996 Klaus Kaempf <kkaempf@progis.de> + + * makefile.vms: Bump version date. + +Tue Oct 1 15:00:59 1996 Ian Lance Taylor <ian@cygnus.com> + + * version.c (print_version): New function. + * bucomm.h (print_version): Declare. + * ar.c (program_version): Don't declare. + (do_show_version): Remove. + (usage): Add help parameter. Print bug report address. + (main): Set is_ranlib at start. Check for --help and --version. + Call print_version, not do_show_version. + * nlmconv.c (program_version): Don't declare. + (main): Call print_version. + (show_usage): Print bug report address. + * nm.c (program_version, print_version): Don't declare. + (usage): Print bug report address. + (main): Call print_version. + * objcopy.c (program_version): Don't declare. + (copy_usage): Print bug report address. + (strip_usage): Likewise. + (strip_main): Call print_version. + (copy_main): Likewise. + * objdump.c (program_version): Don't declare. + (usage): Print bug report address. + (main): Call print_version. + * size.c (program_version): Don't declare. + (usage): Print bug report address. + (main): Call print_version. + * strings.c (program_version): Don't declare. + (main): Call print_version. + (usage): Print bug report address. + * Makefile.in: Update dependencies. + +Thu Sep 19 14:53:15 1996 Ian Lance Taylor <ian@cygnus.com> + + * ieee.c: Revert Monday's reflocalp patch, and apply this patch + instead: + (write_ieee_debugging_info): Write a dummy type at the end of the + global type block. + +Mon Sep 16 15:30:54 1996 Ian Lance Taylor <ian@cygnus.com> + + * ieee.c (struct ieee_write_type): Add reflocalp field. + (ieee_pointer_type): Set reflocalp after pushing type. + (ieee_function_type): If reflocalp is set, make this type local. + (ieee_range_type, ieee_array_type, ieee_set_type): Likewise. + (ieee_const_type, ieee_volatile_type): Likewise. + (ieee_struct_field, ieee_class_baseclass): Likewise. + + * ieee.c (struct ieee_info): Add global_types field. + (parse_ieee_bb): When starting a BB1, initialize the types field + to the global_types field. + (parse_ieee_be): When ending a BB2, copy the types field to the + global_types field. + +Fri Sep 13 17:32:21 1996 Ian Lance Taylor <ian@cygnus.com> + + * objcopy.c (change_leading_char): New static variable. + (OPTION_CHANGE_LEADING_CHAR): Define. + (copy_options): Add "change-leading-char". + (copy_usage): Mention --change-leading-char. + (filter_symbols): Add obfd parameter. Change all callers. + Implement change_leading_char. + (copy_object): Call filter_symbols if change_leading_char. + (copy_main): Handle OPTION_CHANGE_LEADING_CHAR. + * binutils.texi, objcopy.1: Document --change-leading-char. + +Tue Sep 3 14:05:29 1996 Ian Lance Taylor <ian@cygnus.com> + + * ieee.c (ieee_enum_type): Don't check index into a NULL names + array. + * nm.c (sort_symbols_by_size): Always initialize next. + * rdcoff.c (parse_coff_type): Warn about an incomprehensible + type rather than crashing. + * rddbg.c (read_symbol_stabs_debugging_info): Initialize f. + * stabs.c (parse_stab_members): Set context in all cases. + +Thu Aug 29 16:56:52 1996 Michael Meissner <meissner@tiktok.cygnus.com> + + * configure.in (i[345]86-*-*): Recognize i686 for pentium pro. + * configure: Regenerate. + +Thu Aug 29 11:29:20 1996 Ian Lance Taylor <ian@cygnus.com> + + * objdump.c (L_tmpnam): Never define. + (display_target_list): Use choose_temp_base instead of tmpnam. + (display_info_table): Likewise. + +Tue Aug 27 18:15:01 1996 Ian Lance Taylor <ian@cygnus.com> + + * stabs.c (parse_stab): An N_FUN symbol with an empty string + indicates the end of a function. + +Thu Aug 22 17:08:00 1996 Ian Lance Taylor <ian@cygnus.com> + + * wrstabs.c (struct string_hash_entry): Add next field. + (struct stab_write_handle): Change strings to a pointer to + string_hash_entry. Add last_strings field. Remove strings_alloc + field. + (string_hash_newfunc): Initialize next field. + (stab_write_symbol): Copy string into hash table rather than into + buffer. Keep a list of hash table entries. + (write_stabs_in_sections_debugging_info): Initialize last_string. + Copy strings from list of hash table entries in memory. + (stab_modify_type): If the entry on the stack is a definition, + make a new definition rather than failing an assert. + (stab_array_type): The size is only zero if high is strictly less + than low. + + * ieee.c (struct ieee_info): Add saw_filename field. + (parse_ieee): Initialize saw_filename. + (parse_ieee_bb): Set saw_filename for a BB1 or BB2. In a BB1, + discard the current variables and types. In a BB10, if no + filename has been seen, call debug_set_filename. + (parse_ieee_ty): In case 'g', the type is optional. + + * prdbg.c (pr_fix_visibility): Don't abort on + DEBUG_VISIBILITY_IGNORE. + + * debug.c (debug_name_type): Correct error message. + + * configure.in: Substitute HLDENV. + * configure: Rebuild. + * Makefile.in (HLDENV): New variable. Use it whenever linking a + program. + +Thu Aug 15 19:30:41 1996 Stan Shebs <shebs@andros.cygnus.com> + + * mpw-make.sed: Add symbolic doublequotes around the version + number. + +Thu Aug 8 12:27:52 1996 Klaus Kaempf <kkaempf@progis.de> + + * makefile.vms: Add better support for DEC C compilation. + Add new macros as in Makefile.in. + +Wed Aug 7 14:27:33 1996 Philippe De Muyter <phdm@info.ucl.ac.be> + + * configure.in: Call BFD_NEED_DECLARATION on strstr and sbrk. + * acconfig.h (NEED_DECLARATION_STRSTR): New macro. + (NEED_DECLARATION_SBRK): New macro. + * configure, config.in: Rebuild. + * bucomm.h (strstr): Declare if NEED_DECLARATION_STRSTR. + (sbrk): Declare if HAVE_SBRK and NEED_DECLARATION_SBRK. + + * prdbg.c (pr_end_struct_type): Avoid using a string constant in + assert, for the benefit of broken assert macros. + +Fri Jul 26 14:06:50 1996 Ian Lance Taylor <ian@cygnus.com> + + * objdump.c (disassemble_data): Set disasm_info.flavour from + abfd. + +Tue Jul 23 13:59:54 1996 Ian Lance Taylor <ian@cygnus.com> + + * dlltool.c (secdata): In non DLLTOOL_PPC case, change alignment + of .text section to 2. + +Mon Jul 22 08:46:15 1996 Stu Grossman (grossman@lisa.cygnus.com) + + * objdump.c (dump_section_stabs): Fix test for stabs sections + ending with numbers. This fixes a problem with .stab being + confused with .stab.index. + +Wed Jul 10 13:32:28 1996 Ian Lance Taylor <ian@cygnus.com> + + * stabs.c (stab_demangle_fund_type): Return a void * for a + template, rather than simply aborting. + +Mon Jul 8 15:28:05 1996 Ian Lance Taylor <ian@cygnus.com> + + * ar.c (open_inarch): Add file parameter. Change all callers. If + this is a newly created archive, set the target based on the + file. + * arsup.h (open_inarch): Update declaration. + +Thu Jul 4 12:00:55 1996 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.in (VERSION): Set to cygnus-2.7.1. + + * Released binutils 2.7. + + * rdcoff.c (parse_coff): Get address to pass to debug_end_function + from function size, not value of .ef symbol. From Ning + Mosberger-Tang <ning@AZStarNet.com>. + +Sat Jun 29 21:18:09 1996 Ian Lance Taylor <ian@cygnus.com> + + * objcopy.c (strip_main): Add -o option, and handle it. + (strip_usage): Mention -o. + * binutils.texi, strip.1: Mention -o. + +Mon Jun 24 17:19:02 1996 Jason Molenda (crash@godzilla.cygnus.co.jp) + + * Makefile.in (bindir, libdir, datadir, mandir, infodir, includedir, + INSTALL_PROGRAM, INSTALL_DATA): Use autoconf set values. + (docdir): Removed. + * configure.in (AC_PREREQ): Autoconf 2.5 or higher. + +Mon Jun 24 11:59:13 1996 Ian Lance Taylor <ian@cygnus.com> + + * objdump.c (endian): New static variable. + (usage): Mention -EB/-EL/--endian. + (long_options): Add "endian". + (disassemble_data): If endianness was specified, replace + abfd->xvec with a copy of itself with the given endianness. + (main): Handle -EB/-EL/--endian. + * binutils.texi, objdump.1: Mention -EB/-EL/--endian. + + * objdump.c: Make most variables and functions static. + + * configure.in: On alpha*-*-osf*, link against libbfd.a if not + using shared libraries. + * configure: Rebuild with autoconf 2.10. + +Sun Jun 23 14:47:36 1996 Kim Knuttila <krk@cygnus.com> + + * dlltool.c (secdata): Changed .rdata to .reldata so .reloc will work. + (make_one_lib_file): Removed cruft. (#if 1) + +Wed Jun 19 14:46:38 1996 Ian Lance Taylor <ian@cygnus.com> + + * objdump.c (stabs): Change from struct internal_nlist * to + bfd_byte *. + (print_section_stabs): Fetch stabs information directly, rather + than assuming that struct internal_nlist is the right size. + + * binutils.texi: Document change to binary format: file position + based on load address, not section VMA. + + * bucomm.h: Define SEEK_SET, SEEK_CUR, and SEEK_END if they are + not already defined. + +Tue Jun 18 18:25:00 1996 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.in (DISTSTUFF): Add deflex.c. + +Tue Jun 18 15:03:44 1996 Klaus Kaempf <kkaempf@progis.de> + + * config.h-vms, makefile.vms: New files. + +Mon Jun 17 09:47:31 1996 Ian Lance Taylor <ian@cygnus.com> + + * dlltool.c (make_one_lib_file): Use BFD_RELOC_RVA rather than + BFD_RELOC_32 in IDATA7. + +Wed Jun 12 11:52:06 1996 Ian Lance Taylor <ian@cygnus.com> + + * nm.c (struct get_relocs_info): Define. + (line_numbers): New static variable. + (long_options): Add "line-numbers". + (usage): Mention -l and --line-numbers. + (main): Handle -l. + (print_symbol): Print line numbers if requested. + (get_relocs): New static function. + * binutils.texi, nm.1: Document -l/--line-numbers. + +Tue Jun 11 20:12:15 1996 Ian Lance Taylor <ian@cygnus.com> + + * objdump.c (dump_reloc_set): Add sec parameter. Change all + callers. If with_line_numbers is set, display line numbers of + relocation entries. + * binutils.texi, objdump.1: Document -l with -r. + +Mon Jun 10 23:42:59 1996 Ian Lance Taylor <ian@cygnus.com> + + * ar.c (open_inarch): Report BFD error message if an archive can + not be recognized. List matching formats if the file is + ambiguously recognized. + (ranlib_touch): Likewise. + +Thu Jun 6 13:56:14 1996 Ian Lance Taylor <ian@cygnus.com> + + * README: Add notes on how to build if you don't have ar. + + * Makefile.in: Remove old incorrect setting of CC. + +Tue Jun 4 10:52:49 1996 Tom Tromey <tromey@csk3.cygnus.com> + + * Makefile.in (install): Don't check to see if tooldir exists. + Make $(tooldir) and $(tooldir)/bin. + +Mon Jun 3 17:40:23 1996 Michael Meissner <meissner@tiktok.cygnus.com> + + * strings.c (main): Make main an int function, not void. + +Fri May 31 13:59:24 1996 Ian Lance Taylor <ian@cygnus.com> + + * nm.c (filter_symbols): Check for BSF_WEAK as well as + BSF_GLOBAL. + * objcopy.c (filter_symbols): Likewise. + +Wed May 8 16:57:20 1996 Ian Lance Taylor <ian@cygnus.com> + + * objcopy.c (copy_object): Make clear that it is only a warning + when the output file can not represent the architecture. + +Fri May 3 11:30:17 1996 Ian Lance Taylor <ian@cygnus.com> + + * objdump.c (disassemble_data): Don't refer to bytes past the end + of data. + +Wed Apr 24 14:10:21 1996 Ian Lance Taylor <ian@cygnus.com> + + * rddbg.c (read_symbol_stabs_debugging_info): Move call to + free_saved_stabs outside the loop over the symbols. + +Tue Apr 23 12:56:11 1996 Ian Lance Taylor <ian@cygnus.com> + + * objdump.c (compare_symbols): Sort symbols whose names start with + `.' after other symbols. If no other decision can be made, sort + symbols by name. + +Thu Apr 18 16:02:11 1996 Ian Lance Taylor <ian@cygnus.com> + + * dep-in.sed: Substitute $(BFDDIR) for @BFDDIR@. + * Makefile.in: Rebuild dependencies. + (dep.sed): Substitute $(BFDDIR) for @BFDDIR@. + +Tue Apr 16 13:50:22 1996 Ian Lance Taylor <ian@cygnus.com> + + * rdcoff.c: New file. + * rddbg.c (read_debugging_info): Read COFF symbols if COFF flavour + and no stabs were found. + * budbg.h (parse_coff): Declare. + * Makefile.in: Rebuild dependencies. + (CFILES): Add rdcoff.c. + (DEBUG_OBJS): Add rdcoff.o. + +Mon Apr 15 15:55:01 1996 Doug Evans <dje@canuck.cygnus.com> + + * nlmconv.c (choose_temp_base{,_try}): Delete, in libiberty now. + (link_inputs): Update call to choose_temp_base. + +Mon Apr 8 14:40:05 1996 Ian Lance Taylor <ian@cygnus.com> + + * configure.in: Permit --enable-shared to specify a list of + directories. + * configure: Rebuild. + +Fri Mar 29 16:11:33 1996 Ian Lance Taylor <ian@cygnus.com> + + * objdump.c (dump_section_header): Print the SEC_LINK_ONCE flag + and the SEC_LINK_DUPLICATES field. + +Fri Mar 29 11:35:55 1996 J.T. Conklin (jtc@lisa.cygnus.com) + + * nlmconv.1: Changed to be recognized by catman -w on Solaris. + +Thu Mar 28 14:17:02 1996 Ian Lance Taylor <ian@cygnus.com> + + * wrstabs.c (stab_enum_type): Set buf before using it. + +Fri Mar 22 15:49:08 1996 Ian Lance Taylor <ian@cygnus.com> + + * stabs.c (struct stab_handle): Add field abfd. + (start_stab): Add abfd parameter. + (parse_stab_string): Skip the symbol leading char when searching + for the value of a global symbol. + * budbg.h (start_stab): Update declaration. + * rddbg.c (read_section_stabs_debugging_info): Pass abfd to + start_stab. + (read_symbol_stabs_debugging_info): Likewise. + +Thu Mar 21 12:40:48 1996 Ian Lance Taylor <ian@cygnus.com> + + * wrstabs.c (stab_function_type): Output an empty typedef for an + unused argument, rather than making up a meaningless name. + (stab_variable): Use N_RSYM for a DEBUG_REGISTER variable. + + * ieee.c (struct ieee_info): Add global_vars field. + (parse_ieee_be): When ending the global typedef block, copy the + variables into info->global_vars. + (parse_ieee_atn): Don't require an NN record for a pmisc ATN. + (ieee_read_reference): Search the global variables after the local + variables. + +Wed Mar 20 18:08:19 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * objdump.c (disassemble_data): Make sure sym_name is always set. + (dump_section_header): Always put a space after the section name. + (dump_bfd_header): Terminate output with newline. + +Wed Mar 20 16:35:20 1996 Ian Lance Taylor <ian@cygnus.com> + + * wrstabs.c: New file. + * budbg.h (write_stabs_in_sections_debugging_info): Declare. + * objcopy.c (write_debugging_info): For COFF or ELF, output stabs + in sections. + * Makefile.in: Rebuild dependencies. + (CFILES): Add wrstabs.c. + (WRITE_DEBUG_OBJS): New variable. + ($(OBJCOPY_PROG)): Use $(WRITE_DEBUG_OBJS), not $(DEBUG_OBJS). + ($(STRIP_PROG)): Likewise. + + * stabs.c (parse_stab_members): Make type stub detection more like + gdb. + + * ieee.c (struct ieee_handle): Add fields complex_float_index and + complex_double_index. + (ieee_complex_type): Cache type index in complex_float_index and + complex_double_index, depending upon size. Set size on type stack + to size * 2. + + * ieee.c (ieee_empty_type): Use builtin_unknown, not 0. + (ieee_void_type): Use builtin_void, not 1. + + * ieee.c (parse_ieee_ty): Handle 'V' type code. + (parse_ieee_atn): Don't require two numbers for type 10. + + * ieee.c (parse_ieee_be): Add one to offset at end of function or + block. + + * ieee.c (struct ieee_block): Add field skip. + (parse_ieee_bb): Don't call debug_record_function for __XRYCPP + function, and set skip field. + (parse_ieee_be): Don't call debug_end_function if skip is set. + + * debug.c (struct debug_handle): Add fields current_write_lineno + and current_write_lineno_index. + (debug_write): Initialize current_write_lineno and + current_write_lineno_index for each unit. Call + debug_write_linenos rather than writing out the line numbers + directly. + (debug_write_function): Call debug_write_linenos. + (debug_write_block): Likewise. + (debug_write_linenos): New static function. + + * debug.c (debug_write_type): For DEBUG_KIND_FUNCTION, push return + type before arguments. + +Mon Mar 18 18:05:33 1996 Ian Lance Taylor <ian@cygnus.com> + + * configure.in: Add AC_FUNC_VFORK. + * configure, config.in: Rebuild. + * dlltool.c, nlmconv.c: Include <vfork.h> if HAVE_VFORK_H is + defined. + + * stabs.c (parse_stab_range_type): A complex type is defined as a + subrange of itself with the high bound zero. + * ieee.c (ieee_complex_type): Don't crash on sizes of 12 or 16. + +Tue Mar 12 12:09:43 1996 Ian Lance Taylor <ian@cygnus.com> + + * ieee.c (ieee_write_undefined_tag): Switch to global_types even + if it is not empty. + (ieee_tag_type): For an enum, look through info->enums. + + * configure: Rebuild with autoconf 2.8. + + * debug.c (debug_type_samep): Don't loop endlessly in + DEBUG_KIND_ENUM case. From Eric Baur <ecb@nexen.com>. + +Mon Mar 11 12:35:03 1996 Ian Lance Taylor <ian@cygnus.com> + + * rddbg.c (read_section_stabs_debugging_info): Call save_stab for + each stab entry, call stab_context on an error, and call + free_saved_stabs before rturning. + (read_symbol_stabs_debugging_info): Likewise. + (SAVE_STABS_COUNT): Define. + (struct saved_stab): Define. + (saved_stabs, saved_stabs_index): New static variables. + (save_stab, stab_context, free_saved_stabs): New static functios. + + * objdump.c (stab_name): Remove. + (struct stab_print): Remove. + (stab_print): Remove. + (dump_stabs): Don't initialize stab_name. + (print_section_stabs): Call bfd_get_stab_name rather than using + the stab_name array. + +Tue Feb 27 19:52:01 1996 Ian Lance Taylor <ian@cygnus.com> + + * prdbg.c (pr_int_constant): Initialize info correctly. + (pr_float_constant): Likewise. + +Mon Feb 26 18:11:37 1996 Stan Shebs <shebs@andros.cygnus.com> + + * mpw-make.sed: Update to handle shared library support. + +Sat Feb 24 11:21:49 1996 Alan Modra <alan@spri.levels.unisa.edu.au>: + + * Makefile.in ($(OBJDUMP_PROG)): Search $(BFDLIB) before + $(OPCODES). + +Thu Feb 15 12:44:45 1996 Ian Lance Taylor <ian@cygnus.com> + + * configure.in: Don't tamper with LDFLAGS. Call AC_PROG_CC before + configure.host. + * configure: Rebuild. + + * configure.in: Substitute RPATH_ENVVAR. + * configure: Rebuild. + * Makefile.in (RPATH_ENVVAR): New variable. + (check): Use $(RPATH_ENVVAR) rather than LD_LIBRARY_PATH. + + * objcopy.c (smart_rename): Rather than doing chmod then chown, do + chmod without setuid, then chown, then chmod with setuid. + +Wed Feb 14 16:46:42 1996 Martin Anantharaman <martin@mail.imech.uni-duisburg.de> + + * arsup.c (map_over_list): Reindent. Don't assume that the + function does not delete the BFD. + (ar_addlib_doer): Don't set prev->next if prev is NULL. + +Wed Feb 14 15:12:17 1996 Ian Lance Taylor <ian@cygnus.com> + + * ieee.c (ieee_regno_to_genreg): Convert register numbers for m68k + and i960. + (ieee_genreg_to_regno): Likewise. + +Mon Feb 12 14:19:59 1996 Ian Lance Taylor <ian@cygnus.com> + + * ieee.c: Extensive changes to write code to put types in the + global type block when possible, to output ranges for all memory + occupied by the module, and to improve efficiency. + + * debug.c (struct debug_handle): Remove class_mark field. Add + id_list and compare_list fields. + (struct debug_class_id): Define. + (struct debug_type_compare_list): Define. + (debug_write): Initialize info->id_list + (debug_write_name): Remove reference to info->class_mark. + (debug_write_type): Get id for all structs and classes. Simplify + test for whether struct has already been written. + (debug_write_class_type): Get id for all classes. Simplify test + for whether class has already been written. + (debug_write_block): Don't write out blocks other than the top + level block if they have no local variables. + (debug_set_class_id): New static function. + (debug_type_samep): New static function. + (debug_class_type_samep): New static function. + * prdbg.c (pr_start_struct_type): Always print id. + (pr_start_class_type): Likewise. + (pr_tag_type): Likewise. + + * stabs.c (struct stab_handle): Add syms and symcount fields. + (start_stab): Add syms and symcount parameters. Change all + callers. + (parse_stab_string): Look up global variables in the symbol table + to get the right value. + * budbg.h (start_stab): Update declaration. + * rddbg.c (read_section_stabs_debugging_info): Add syms and + symcount parameters. Change all callers. + + * stabs.c (parse_stab_array_type): If the index type is 0, use + int. + +Wed Feb 7 14:17:45 1996 Ian Lance Taylor <ian@cygnus.com> + + * ieee.c (ieee_start_compilation_unit): Clear modified and + modified_alloc fields of info. + + * configure.in: Check for --enable-shared. Substitute new + variables BFDLIB and OPCODES. + * configure: Rebuild. + * Makefile.in (BFDLIB): Set to @BFDLIB@. + (OPCODES): Set to @OPCODES@. + +Mon Feb 5 16:18:42 1996 Ian Lance Taylor <ian@cygnus.com> + + Support for building bfd and opcodes as shared libraries, based on + patches from Alan Modra <alan@spri.levels.unisa.edu.au>: + * configure.in (HLDFLAGS): New substitution. + * configure: Rebuild. + * Makefile.in (HLDFLAGS): New variable. Make all links use + $(HLDFLAGS) before $(CFLAGS) and $(LDFLAGS). + (BFDLIB_DEP): New variable. Replace all occurrences of $(BFD) as + a dependency with $(BFDLIB_DEP). Remove $(BFD) as a dependency if + there is also a dependency on $(ADDL_DEPS). + (BFDLIB): Rename from BFD; change all uses; set to -L../bfd -lbfd. + (OPCODES_DEP): New variable. Replace all occurrends of $(OPCODES) + as a dependency with $(OPCODES_DEP). + (OPCODES): Set to -L../opcodes -lopcodes. + (ADDL_DEPS): New variable. Replace all occurrences of + $(ADDL_LIBS) as a dependency with $(ADDL_DEPS). + (check): Set LD_LIBRARY_PATH in the environment. + (config.status): Depend upon BFD configure.host and config.bfd. + +Fri Feb 2 17:02:59 1996 Doug Evans <dje@charmed.cygnus.com> + + * objdump.c: #include stdarg.h or varargs.h. + (objdump_print_value): Change FILE* arg to struct disassemble_info*. + All callers updated. Use fprintf_func. + (objdump_print_address): Consistently use fprintf_func. + (objdump_sprintf): New function. + (disassemble_data): Print insn into a buffer, print raw insn ourselves, + then print insn mnemonic. + +Fri Feb 2 16:48:55 1996 Ian Lance Taylor <ian@cygnus.com> + + * configure: Regenerate. + +Thu Feb 1 09:38:18 1996 Steve Chamberlain <sac@slash.cygnus.com> + + * configure.in (i[3-6]86-*-win32): Becomes i[3-6]86-*-cygwin32. + (powerpc*-*-cygwin32): New. + * configure: Regenerated. + +Wed Jan 31 13:22:03 1996 Richard Henderson <rth@tamu.edu> + + * Makefile.in (distclean): Remove $(DEMANGLER_PROG).1. + +Mon Jan 29 17:36:29 1996 Ian Lance Taylor <ian@cygnus.com> + + Based on patches from H J Lu <hjl@zoom.com>: + * objcopy.c (remove_leading_char): New static variable. + (OPTION_REMOVE_LEADING_CHAR): Define. + (copy_usage): Mention --remove-leading-char. + (filter_symbols): If remove_leading_char, and the first character + of a global symbol matches the symbol leading char of the BFD, + remove the first character. + (copy_object): Filter the symbols if remove_leading_char is set. + (copy_main): Handle --remove-leading-char. + * binutils.texi, objcopy.1: Document --remove-leading-char. + +Sat Jan 27 15:40:13 1996 Michael Meissner <meissner@tiktok.cygnus.com> + + * objdump.c (fprintf): Add prototype to avoid compiler warning on + SunOS. + +Fri Jan 26 11:53:42 1996 Ian Lance Taylor <ian@cygnus.com> + + * binutils.texi (nm): Improve documentation on symbol types. + (objdump): Reference the stabs manual from the discussion of the + --stabs option. + +Thu Jan 25 11:21:46 1996 Raymond Jou <rjou@mexican.cygnus.com> + + * mpw-make.sed: Add a "stamps" target. + +Thu Jan 25 13:51:44 1996 Ian Lance Taylor <ian@cygnus.com> + + * objdump.c (dump_headers, dump_section_header): Change objdump -h + output to be simpler and to include section file offsets. + +Wed Jan 24 12:06:05 1996 Ian Lance Taylor <ian@cygnus.com> + + * stabs.c (parse_stab_members): Don't adjust voffset. + + * ieee.c (ieee_read_cxx_class): Don't multiply voffset by 4. + (struct ieee_write_type): Add name field. + (struct ieee_type_class): Remove name field. Change all uses to + use new name field in type instead. + (struct ieee_name_type): Likewise. + (ieee_start_struct_type): Initialize name field of type. + (ieee_start_class_type): Don't initialize classdef entry of tag. + (ieee_class_method_var): Don't adjust voffset. + (ieee_end_class_type): Likewise. + (ieee_tag_type): Initialize new name field of type. + (ieee_typdef): Set name after copying in type information. + + * debug.c (VOFFSET_STATIC_METHOD): Define as -1, not 1. + + * ieee.c (struct ieee_modified_type): Define. + (struct ieee_handle): Add modified and modified_alloc fields. + (ieee_get_modified_info): New static function. + (ieee_pointer_type): Cache type index. + (ieee_const_type): Likewise. + (ieee_volatile_type): Likewise. + + * ieee.c (ieee_define_named_type): When creating a tag for an + anonymous struct, copy the name into memory. + (ieee_tag_type): Likewise. + * debug.c (debug_write_type): Only check and set id field for an + unnamed object. + (debug_write_class_type): Likewise. + + * ieee.c: Various changes to write out types for functions and + references, and to not write out unnecessary function types. + + * ieee.c (struct ieee_var): Remove variable field. Add kind + field, and define some enum constants for it. + (parse_ieee_ty): Set kind field of variable for 'x' and 'X' types. + (parse_ieee_atn): Make an indirect slot for an external variable, + although we otherwise don't record it. Set kind field rather than + variable field of pvar. + (ieee_read_cxx_class): Try to get the type of a static member. + (ieee_read_reference): Check kind field rather than variable + field. + +Tue Jan 23 15:54:18 1996 Ian Lance Taylor <ian@cygnus.com> + + * ieee.c: Various changes to handle reading C++ reference type + information. + + * debug.h (enum debug_var_kind): Add DEBUG_VAR_ILLEGAL. + (enum debug_parm_kind): Add DEBUG_PARM_ILLEGAL. + * debug.c (debug_get_parameter_types): Handle DEBUG_KIND_FUNCTION. + + * ieee.c: Various changes to write out definitions of C++ classes. + + * debug.c (debug_append_filename): Remove. + * debug.h (debug_append_filename): Don't declare. + + * stabs.c (struct stab_handle): Remove last_type field. Add + so_string and so_value fields. + (finish_stab): Call stab_emit_pending_vars before calling + debug_end_function. Don't warn about pending variables. + (parse_stab): Accumulate N_SO strings until a non N_SO symbol is + seen, rather than calling debug_append_filename. Call + stab_emit_pending_vars before calling debug_end_function. Don't + set info->last_type. + +Tue Jan 23 09:53:54 1996 Doug Evans <dje@charmed.cygnus.com> + + * objdump.c (disassemble_data): Handle unknown endianness. + Pass fprintf to INIT_DISASSEMBLE_INFO. + +Mon Jan 22 16:46:43 1996 Doug Evans <dje@charmed.cygnus.com> + + Add new option --show-raw-insn. + * objdump.c (show_raw_insn): New global. + (usage): Update. + (long_options): Update. + (disassemble_data): Set disasm_info.flags if --show-raw-insn. + + * objdump.c (disassemble_data): Set new arch,mach,endian fields in + disasm_info. + +Mon Jan 22 19:29:36 1996 Ian Lance Taylor <ian@cygnus.com> + + * ieee.c: Extensive changes to pass a single info argument around + in the reading routines, rather than several arguments. Add code + to read C++ debugging records. + + * debug.h (debug_get_type_size): Declare. + (debug_get_field_name): Declare. + (debug_get_field_bitpos): Declare. + (debug_get_field_bitsize): Declare. + (debug_get_field_visibility): Declare. + (debug_get_field_physname): Declare. + * debug.c (debug_get_real_type): Handle DEBUG_KIND_TAGGED. + (debug_get_type_size): New function. + (debug_get_field_name): New function. + (debug_get_field_bitpos): New function. + (debug_get_field_bitsize): New function. + (debug_get_field_visibility): New function. + (debug_get_field_physname): New function. + (debug_write_type): Make sure we pass the real kind, not INDIRECT, + to tag_type. Pass the name recursively for INDIRECT. + +Fri Jan 19 12:31:57 1996 Ian Lance Taylor <ian@cygnus.com> + + * debug.h (struct debug_write_fns): Remove ellipsis_type. Add int + and boolean parameters to function_type. Add boolean parameter to + method_type. + (debug_make_ellipsis_type): Don't declare. + (debug_make_function_type): Add debug_type * and boolean + parameters. Change all callers. + (debug_make_method_type): Add boolean parameter. Change all + callers. + (debug_get_parameter_types): Add boolean * parameter. Change all + callers. + (debug_get_target_type): Declare. + * debug.c (struct debug_function_type): Add fields arg_types and + varargs. + (struct debug_method_type): Add field varargs. + (debug_ellipsis_type, ELLIPSIS_P): Remove. + (debug_make_ellipsis_type): Remove. + (debug_make_function_type): Add arg_types and varargs parameters. + (debug_make_method_type): Add varargs parameter. + (debug_get_parameter_types): Add pvarargs parameter. + (debug_get_target_type): New function. + (debug_write_type): In case DEBUG_KIND_FUNCTION, push argument + types and pass count to function_type. In DEBUG_KIND_METHOD, use + a signed int for the count, don't call ellipsis_type, and pass + varargs to method_type. + * stabs.c (struct stab_demangle_info): Add varargs field. + (stab_demangle_argtypes): Add pvarargs parameter. Change all + callers. + (stab_demangle_args): Likewise. + (stab_demangle_type): In case 'F', pick up argument types. + * prdbg.c (pr_ellipsis_type): Remove. + (pr_function_type): Add argcount and varargs parameters. + (pr_method_type): Add varargs parameter. + * ieee.c (ieee_ellipsis_type): Remove. + (ieee_function_type): Add argcount and varargs parameters. + (ieee_method_type): Add varargs parameter. Remove most of + function body, and just call ieee_function_type. + + * stabs.c: Include "demangle.h". Added several new static + functions not listed below to demangle argument types; they are + all called via stab_demangle_argtypes. + (finish_stab): If the kind of an undefined tag is + DEBUG_KIND_ILLEGAL, use DEBUG_KIND_STRUCT instead. Warn if there + are any pending variable. + (parse_stab): Don't close the function when the block depth goes + to zero. Pass value to debug_end_function. + (parse_stab_string): In case 'T', pass the name to + parse_stab_type. + (parse_stab_type): In case 'x', use stab_find_tagged_type. In + case '#', handle functions with variable numbers of arguments. + (parse_stab_struct_type): Add tagname parameter. Change all + callers. + (parse_stab_members): Add tagname and typenums parameters. Change + all callers. If the type of a method is a stub, call + parse_stab_argtypes to demangle the argument types and get the + physical name of the function. + (parse_stab_argtypes): New static function. + (stab_record_variable): For a DEBUG_GLOBAL or DEBUG_STATIC + variable, call debug_record_variable immediately. + (stab_find_tagged_type): New static function. + + * debug.h (enum debug_type_kind): Add DEBUG_KIND_ILLEGAL. + (struct debug_write_fns): Add field ellipsis_type. Add id + parameter to start_struct_type, start_class_type, and tag_type. + (debug_make_ellipsis_type): Declare. + (debug_find_named_type): Declare. + (debug_get_type_kind): Declare. + (debug_get_return_type): Declare. + (debug_get_parameter_types): Declare. + (debug_get_fields): Declare. + (debug_get_field_type): Declare. + * debug.c (struct debug_handle): Add fields class_id and base_id. + (struct debug_class_type): Add field id. + (struct debug_method_variant): Rename argtypes to physname. + Change all uses. + (debug_ellipsis_type): New static variable. + (ELLIPSIS_P): New macro. + (debug_make_ellipsis_type): New function. + (debug_make_method_variant): Rename argtypes to physname. + (debug_make_static_method_variant): Likewise. + (debug_name_type): Always put types in the global namespace. + (debug_find_named_type): New function. + (debug_find_tagged_type): Treat DEBUG_KIND_ILLEGAL specially, + rather than DEBUG_KIND_VOID. + (debug_get_real_type): New static function. + (debug_get_type_kind): New function. + (debug_get_return_type): New function. + (debug_get_parameter_types): New function. + (debug_get_fields): New function. + (debug_get_field_type): New function. + (debug_write): Initialize base_id. + (debug_write_type): Pass new id argument to tag_type. Handle + DEBUG_KIND_ILLEGAL. Use id for DEBUG_KIND_STRUCT and + DEBUG_KIND_UNION. Handle ellipsis for method arguments. + (debug_write_class_type): Don't dereference kclass if it is NULL. + Use id. + * prdbg.c (pr_fns): Add pr_ellipsis_type. + (pr_ellipsis_type): New static function. + (pr_pointer_type): If this is a pointer to an array, parenthesize + it correctly. + (pr_start_struct_type): Add id parameter. + (pr_start_class_type): Likewise. + (pr_tag_type): Likewise. + (pr_fix_visibility): Add the visibility to the top of the stack, + not the second element on the stack. + (pr_struct_field): Pop the stack before calling pr_fix_visibility. + (pr_class_static_member): Likewise. + (pr_class_start_method): Don't push a type, just set the method + name in the type on the top of the stack. + (pr_class_end_method): Don't pop the stack. + (pr_class_method_variant): Rename argtypes parameter to physname. + Append const and volatile rather than prepending them. Add a + space after the physname. + (pr_class_static_method_variant): Likewise. + * ieee.c (ieee_fns): Add ieee_ellipsis_type. + (ieee_define_named_type): Use DEBUG_KIND_ILLEGAL rather than + DEBUG_KIND_VOID. + (write_ieee_debugging_info): Likewise. + (ieee_typdef): Likewise. + (ieee_ellipsis_type): New static function. + (ieee_start_struct_type): Add id parameter. + (ieee_start_class_type): Likewise. + (ieee_tag_type): Likewise. + (ieee_class_method_variant): Rename name to physname. + (ieee_class_static_method_variant): Likewise. + + * Makefile.in (DEBUG_OBJS): Remove prdbg.o. + ($(OBJDUMP_PROG)): Depend upon, and link against, prdbg.o. + +Thu Jan 18 17:35:06 1996 Kim Knuttila <krk@cygnus.com> + + * dlltool.c (make_tail): Changed the order of the sections to avoid + an alignment problem. + +Wed Jan 17 14:23:00 1996 J.T. Conklin <jtc@rtl.cygnus.com> + + * srconv.c (wr_du): Set du.stackfrmt to 0. + (wr_un, wr_sc): Emit all sections, even those with 0 size. + +Tue Jan 16 16:15:49 1996 J.T. Conklin <jtc@rtl.cygnus.com> + + * srconv.c (wr_hd): Space size within segment was being + stored in segment identifier field. + +Tue Jan 16 12:07:25 1996 Stan Shebs <shebs@andros.cygnus.com> + + * mpw-config.in (BUILD_NLMCONV, BUILD_SRCONV, SYSINFO_PROG, + BUILD_DLLTOOL): Put definitions for these into makefile when + configuring, instead of always clearing in mpw-make.sed. + * mpw-make.sed: Edit out any host_alias or target_alias settings, + fix pathname to BFD internal include files, remove dependency + calculation rules. + +Thu Jan 11 17:31:38 1996 Michael Meissner <meissner@tiktok.cygnus.com> + + * objdump.c (dump_section_header): Add new section flags + SEC_{EXCLUDE,SORT_ENTRIES}. + +Thu Jan 11 11:45:34 1996 Ian Lance Taylor <ian@cygnus.com> + + * objcopy.c (filter_symbols): NULL terminate the output symbols. + (copy_object): Allocate space for a possible extra NULL pointer. + + * debug.c (debug_make_undefined_tagged_type): Make sure we are + given a kind of type we can handle. + (debug_write_type): Handle undefined enums and structs. + (debug_write_class_type): Handle undefined classes. + * prdbg.c (pr_enum_type): Handle an undefined enum. + * ieee.c (ieee_enum_type): Likewise. + +Wed Jan 10 15:33:18 1996 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.in: Updated dependencies. + (ALLOCA, MALLOC): Remove variables. + (ADDL_LIBS): Remove $(MALLOC) from definition. + * alloca.c, gmalloc.c: Remove. + +Mon Jan 8 18:02:29 1996 Ian Lance Taylor <ian@cygnus.com> + + * ieee.c: Add global function write_ieee_debugging_info and a + bunch of static functions and structs used to write out IEEE + debugging information. + * budbg.h (write_ieee_debugging_info): Declare. + + * ieee.c (struct ieee_type): Add pslot field. + (enum builtin_types): Define. + (ieee_builtin_type): For a pointer, return a pointer to the named + type. Use enum values rather than numbers. + (ieee_alloc_type): New static function. + (ieee_read_type_index): Use ieee_alloc_type. + (parse_ieee_bb): Likewise. + (parse_ieee_ty): Likewise. Use ieee_builtin_type for array range, + rather than making a new integer type. Store the new type in the + slot, if there is one. + (parse_ieee_atn): Treat ATN10 as defining a register variable. + (ieee_regno_to_genreg): Rename from ieee_regno_to_gen. Change all + callers. + (ieee_genreg_to_regno): New static function. + + * stabs.c (parse_stab_type): Add new typename parameter. Change + all callers. + (parse_stab_range_type): Add new typename parameter. Change all + callers. + + * debug.h (struct debug_write_fns): Add tag parameter to + enum_type, start_struct_type, and start_class_type. + * debug.c (debug_write_type): Pass any tag name to + start_struct_type, debug_write_class_type, and enum_type. If + DEBUG_KIND_TAGGED, pass the name in the recursive call. + (debug_write_class_type): Accept a new tag parameter, and pass it + to start_class_type. + * prdbg.c (pop_type): Don't remove '+' character. + (pr_enum_type): Accept and use tag parameter. + (pr_start_struct_type): Likewise. + (pr_start_class_type): Likewise. + (pr_class_baseclass): Adjust algorithm used to find where to put + the baseclass name. + (pr_tag): Don't bother to insert the tag name. + + * objcopy.c: Include budbg.h. + (convert_debugging): New static variable. + (OPTION_DEBUGGING): Define. + (copy_options): Add "debugging". + (copy_usage): Mention --debugging. + (is_strip_section): Skip debugging sections if convert_debugging. + (setup_section, copy_section): Likewise. + (filter_symbols): Skip debugging symbols if convert_debugging. + (copy_object): If convert_debugging, read and write debugging + information. + (write_debugging_info): New static function. + (copy_main): Handle --debugging. + * Makefile.in (DEBUG_OBJS): New variable. + ($(OBJCOPY_PROG)): Depend upon and link against $(DEBUG_OBJS). + ($(STRIP_PROG)): Likewise. + (OBJDUMP_OBJS): Remove variable. + ($(OBJDUMP_PROG)): Use objdump.o $(DEBUG_OBJS) rather than + $(OBJDUMP_OBJS). + * binutils.texi, objcopy.1: Document --debugging. + +Thu Jan 4 16:31:21 1996 Ian Lance Taylor <ian@cygnus.com> + + * ieee.c: New file with code to read IEEE debugging information. + * budbg.h (parse_ieee): Declare. + * rddbg.c (read_debugging_info): Handle IEEE flavour files. + (read_ieee_debugging_info): New static function. + * Makefile.in: Rebuild dependencies. + (CFILES): Add ieee.c. + (OBJDUMP_OBJS): Add ieee.o. + + * bucomm.h (xrealloc): Change type of first parameter from char * + to PTR. + +Tue Jan 2 17:44:07 1996 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.in: Add targets to automatically rebuild dependencies. + Remove targets which just listed dependencies of .o files. + (DEP): New variable. + (HFILES, GENERATED_HFILES): New variables. + (CFILES, GENERATED_CFILES): New variables. + (underscore.c): Don't do anything, just depend upon stamp-under. + (stamp-under): New target; do what underscore.c used to do. + (nlmconv.o): Depend upon sym.h and ecoff.h. + (.dep, .dep1, dep.sed, dep, dep-in): New targets. + (stage1, stage2, stage3, against, comparison): Remove. + (de-stage1, de-stage2, de-stage3): Remove. + (clean, distclean): Remove stamp-under and dep.sed. + * dep-in.sed: New file. + + Implement generic debugging support. Implement a stabs reader and + a generic printer. + * budbg.h, debug.c, debug.h, prdbg.c, rddbg.c, stabs.c: New files. + * objdump.c: Include "debug.h" and "budbg.h". + (dump_debugging): New global variable. + (usage): Mention --debugging. + (long_options): Add "debugging". + (display_bfd): Handle --debugging. + * Makefile.in (OBJDUMP_OBJS): New variable. + ($(OBJDUMP_PROG)): Use $(OBJDUMP_OBJS). + * binutils.texi, objdump.1: Document --debugging. + +Sat Dec 30 09:59:51 1995 Jeffrey A Law (law@cygnus.com) + + * nm.c ( long_options): Add "--defined-only" option. + (usage): Update for new "--defined-only" option. + (filter_symbols): Handle "--defined-only". + +Fri Dec 29 16:04:56 1995 Ian Lance Taylor <ian@cygnus.com> + + * arparse.y: Include "bucomm.h", not <sysdep.h>. + * nlmheader.y: Don't include "sysdep.h". + +Tue Dec 26 18:23:18 1995 Ian Lance Taylor <ian@cygnus.com> + + * nm.c (print_symdef_entry): Check return value of + bfd_get_elt_at_index. + +Sat Dec 23 11:03:16 1995 Michael Meissner <meissner@tiktok.cgynsu.com> + + * configure.in (DLLTOOL_DEFS): Build dlltool for PowerPC if target + is powerpc*-*-win* in addition to powerpc*-*-*pe*. + +Fri Dec 15 16:30:57 1995 Ian Lance Taylor <ian@cygnus.com> + + * objdump.c (endian_string): New static function. + (display_target_list): Use it. + * nlmconv.c (main): Use new bfd_big_endian macro. + +Fri Dec 15 07:51:34 1995 steve chamberlain <sac@slash.cygnus.com> + + * dlltool.c (fill_ordinals): Start from 1 if no other instructions + given. + +Tue Dec 12 12:05:21 1995 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.in (clean): Remove $(DEMANGLER_PROG).1. From Ronald + F. Guilmette <rfg@monkeys.com>. + +Mon Dec 11 14:33:05 1995 Stan Shebs <shebs@andros.cygnus.com> + + * mac-binutils.r: Fix copyright and version strings. + + * Makefile.in (version): Remove, no longer used. + +Fri Dec 1 14:41:56 1995 Stan Shebs <shebs@andros.cygnus.com> + + * mpw-make.sed (install, install-only): Edit in Mac-specific + install procedure. + +Thu Nov 30 20:26:02 1995 Kim Knuttila <krk@cygnus.com> + + * dlltool.c (ppc_jtab): The binary glue for PowerPC dll linkage, + including the return instruction. + sinfo: added a preferred alignment field. + (secdata): section data for the PowerPC version. + (make_one_lib_file): More symbols, More sections (pdata, rdata) + (make_tail): Use idata$6 instead of idata$7 for ppc. Also added a + NULL idata$3 descriptor (temporary). + +Tue Nov 28 17:23:44 1995 Doug Evans <dje@canuck.cygnus.com> + + * dlltool.c (fill_ordinals): Don't reference d_export_vec if + there are no exported functions. + +Mon Nov 27 13:05:59 1995 Ian Lance Taylor <ian@cygnus.com> + + * configure: Regenerate with autoconf 2.7. + +Wed Nov 22 13:17:15 1995 Ian Lance Taylor <ian@cygnus.com> + + * dlltool.c (fill_ordinals): Start assigning ordinals at 1. + + * Makefile.in (EXPECT): Use $$r, not $${rootme}. + (check): Set r, not rootme. + +Tue Nov 21 18:04:09 1995 Ian Lance Taylor <ian@cygnus.com> + + * configure.in: Use BFD_NEED_DECLARATION. + * acconfig.h: Put NEED_DECLARATION_FPRINTF in @TOP@ section. + * configure, config.in: Rebuild with autoconf 2.6. + +Fri Nov 17 10:34:37 1995 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.in (CC_FOR_TARGET): Use @host@ and @target@, not + $(host_canonical) and $(target_canonical). + +Thu Nov 16 03:39:20 1995 Ken Raeburn <raeburn@cygnus.com> + + Version 2.6 released. + * Makefile.in (VERSION): Update to 2.6. + +Wed Nov 15 12:14:17 1995 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.in (CC_FOR_TARGET): Define. + (check): Pass CC and CFLAGS to runtest. + + * nm.c (display_rel_file): Don't require a DYNAMIC object when + dumping the dynamic symbol table. + + * objdump.c (compare_symbols): Sort global symbols before local + symbols before debugging symbols. + (objdump_print_address): Don't futz around looking for a global + symbol with the same value. + +Tue Nov 14 17:19:11 1995 Ian Lance Taylor <ian@cygnus.com> + + * dlltool.c: Use FOPEN_* macros rather than "r" or "w". + + * dlltool.c (fill_ordinals): Correct memset call. + +Sun Nov 12 12:56:05 1995 Stan Shebs <shebs@andros.cygnus.com> + + * mpw-make.sed (DEMANGLER_PROG): Edit out attempts to do anything + with the man page. + +Fri Nov 10 11:41:22 1995 Ian Lance Taylor <ian@cygnus.com> + + * objcopy.c (setup_section): Copy the section lma independently of + the vma. + +Wed Nov 8 11:33:00 1995 Ian Lance Taylor <ian@cygnus.com> + + * arsup.c (ar_open): Cast malloc return value. + +Tue Nov 7 09:01:26 1995 Kim Knuttila <krk@cygnus.com> + + * configure.in, configure (DLLTOOL_DEFS): Added ppc target. + * dlltool.c (MPPC): Added basic PPC definitions. + +Tue Nov 7 14:02:57 1995 Ian Lance Taylor <ian@cygnus.com> + + * configure.in: Don't treat rs6000-*-lynx* specially. + * configure: Rebuild. + * config/rslynx: Remove. + * Makefile.in: Remove @target_makefile_fragment@. + +Mon Nov 6 15:00:50 1995 Ian Lance Taylor <ian@cygnus.com> + + * bucomm.h: Include <sys/types.h>. + * ar.c: Don't include <sys/types.h> or <stdio.h>. + * bucomm.c, dlltool.c, nlmconv.c, objcopy.c, objdump.c: Likewise. + +Fri Nov 3 12:38:09 1995 Ian Lance Taylor <ian@cygnus.com> + + * objdump.c: Include <sys/types.h>. + + Permit user to override DEMANGLER_PROG from command line. From + Manfred Hollstein <manfred@lts.sel.alcatel.de>. + * Makefile.in ($(DEMANGLER_PROG)): Depend upon + $(DEMANGLER_PROG).1. + (install): Don't depend upon $(DEMANGLER_PROG).1. Only install + $(DEMANGLER_PROG).1 if $(DEMANGLER_PROG) is not empty. + +Wed Nov 1 15:04:57 1995 Manfred Hollstein KS/EF4A 60/1F/110 #40283 <manfred@lts.sel.alcatel.de> + + * Makefile.in (syslex.o): add -I$(srcdir) if compiling in a + separate directory. + +Mon Oct 30 14:24:18 1995 Ian Lance Taylor <ian@cygnus.com> + + * objdump.c (objdump_print_value): New static function. + (objdump_print_address): Use it. If we need the right section for + the symbol, and we can't find it, print an offset from the section + rather than using a symbol from some other section. + +Thu Oct 26 10:23:14 1995 steve chamberlain <sac@slash.cygnus.com> + + * dlltool.c (no_idata4, no_idata5): New. + (arm_jtab): Use correct encoding of jump instruction. + (usage, main, make_head, make_tail): Act on no_idata4, no_idata5. + +Wed Oct 25 12:10:07 1995 Stan Shebs <shebs@andros.cygnus.com> + + * mpw-make.sed: Edit paths to generated y.tab.[ch] files. + +Fri Oct 20 18:40:34 1995 Ian Lance Taylor <ian@cygnus.com> + + * binutils.texi: Change --with-targets to --enable-targets. + +Thu Oct 19 17:47:41 1995 Fred Fish <fnf@cygnus.com> + + * Makefile.in: Remove extraneous tab on otherwise empty line, + which confuses many non-GNU versions of "make". + +Wed Oct 18 16:31:58 1995 steve chamberlain <sac@slash.cygnus.com> + + * dlltool.c (i386_jtab, arm_jtab): New + (gen_lib_file): Rewritten to use bfd. + +Fri Oct 13 16:10:07 1995 Michael Meissner <meissner@tiktok.cygnus.com> + + * Makefile.in (install): Don't give error message if dlltool + wasn't built. + +Fri Oct 13 11:04:37 1995 steve chamberlain <sac@slash.cygnus.com> + + * deflex.l: Allow quoting of IDs. + * defparse.y (%union): string deleted. + (command): DESCRIPTION takes ID. + * dlltool.c (gen_def_file): Quote outgoing name if + necessary. Preserve NONAME. + (gen_lib_file): Run ranlib. + (workout_prefix): Deleted. + (main, usage, long_options): Add --as, --ranlib, --ar options. + +Wed Oct 11 13:36:13 1995 steve chamberlain <sac@slash.cygnus.com> + + * dlltool.c (mtable): HOW_ALIGN_LONG, new. + (d_ord): Deleted. + (d_low_ord, d_high_ord, d_named_funcs): New. + (gen_exp_file): Create noname entries correctly. + (gen_lib_file): Dump exports alphabetically. + (process_duplicates): Count nonamed functions. + (fill_ordinals): Keep track of highest ord too. + (mangle_defs): Create alphabetically ordered list of names. + +Tue Oct 10 09:39:09 1995 steve chamberlain <sac@slash.cygnus.com> + + * Makefile.in (TOOL_PROGS): Include DLLTOOL_PROG. + +Mon Oct 9 13:06:31 1995 steve chamberlain <sac@slash.cygnus.com> + + * dlltool.c (add_underscore): New. + (xlate): Use new name. + (main, usage): Update. + +Fri Oct 6 14:08:51 1995 Ken Raeburn <raeburn@cygnus.com> + + * sysinfo.y: Eliminate unused terminals "[" and "]" and unused + nonterminal "name". One s/r conflict remains. + + Mon Sep 25 22:49:32 1995 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * nm.c (print_symname): Don't try to demangle an empty + name. + * objdump.c (slurp_symtab): Reset symcount if there are + no symbols. + (slurp_dynamic_symtab): Likewise, for dynsymcount. + (disassemble_data): Fix memory leak: free sorted_syms when done. + (display_bfd): Likewise, for syms and dynsyms. + (dump_relocs): Don't print header before possibly generating an + error message. + (dump_dynamic_relocs): Likewise. + + * ar.1, nm.1, objdump.1, size.1, strings.1, strip.1: Fix typos and + formatting bugs. + +Fri Oct 6 12:00:25 1995 Ian Lance Taylor <ian@cygnus.com> + + * ar.c (do_quick_append): Comment out. + (replace_members): Add quick argument. + (main): Don't call do_quick_append. + (open_inarch): Don't call quick_append to create an empty archive. + Instead call bfd_openw/bfd_set_format/bfd_close. + +Thu Oct 5 20:53:08 1995 Ken Raeburn <raeburn@cygnus.com> + + * bucomm.c: Always include time.h. + +Thu Oct 5 17:25:21 1995 Ian Lance Taylor <ian@cygnus.com> + + * objdump.c (compare_symbols): Sort gnu_compiled and gcc2_compiled + symbols after other symbols with the same value. Likewise for + symbols which look like file names. + (objdump_print_address): Always chose the first reasonable symbol + with a given value. + +Tue Oct 3 22:38:55 1995 Ian Lance Taylor <ian@cygnus.com> + + * arsup.c (ar_save): Use rename, not unlink/link/unlink. + +Mon Oct 2 12:10:25 1995 Ian Lance Taylor <ian@cygnus.com> + + * strings.c (main): Exit with zero status if no files are given + and standard input is read. + +Thu Sep 28 20:03:07 1995 Stan Shebs <shebs@andros.cygnus.com> + + * mpw-config.in: Calculate underscore and put into makefile + fragment, generate config.h. + * mpw-make.sed: New file, sed commands to edit Unix makefile + into MPW syntax. + * mpw-make.in: Remove. + * mac-binutils.r: New file, Mac resources. + +Thu Sep 28 15:49:00 1995 steve chamberlain <sac@slash.cygnus.com> + + * dlltool.c: (gen_exp_file): Always emit a .reloc section if + relocatable. + (imp_name_lab): New. + (gen_def_file): New. + (gen_lib_file): Use imp_name_lab. + (main): Initialize imp_name_lab. + +Mon Sep 25 12:05:34 1995 Ian Lance Taylor <ian@cygnus.com> + + * configure.in: Call AC_HEADER_SYS_WAIT. + * configure: Rebuild. + * config.in: Rebuild. + * dlltool.c: Include "libiberty.h" and "bucomm.h". Don't include + <stdio.h>, <stdlib.h>, or <string.h>. Don't include <wait.h>. + Include <sys/types.h>. Use HAVE_SYS_WAIT_H to control whether to + include <sys/wait.h> or define the wait macros by hand. Don't + declare xmalloc. + (gen_lib_file): Don't assume that sprintf returns the number of + characters; use strlen instead. + +Fri Sep 22 17:16:41 1995 Ian Lance Taylor <ian@cygnus.com> + + * objdump.c (disassemble_data): Don't use the old BFD based + disassembler interface. Make info a const pointer. + +Wed Sep 13 18:33:44 1995 Ian Lance Taylor <ian@cygnus.com> + + * objdump.c (start_address): New variable. + (stop_address): New variable. + (usage): Mention --start-address and --stop-address. + (OPTION_START_ADDRESS, OPTION_STOP_ADDRESS): Define. + (long_options): Add "start-address" and "stop-address". + (disassemble_data): Handle start_address and stop_address. + (dump_data, dump_reloc_set): Likewise. + (main): Don't set seenflag for -l. Handle OPTION_START_ADDRESS + and OPTION_STOP_ADDRESS. + * objcopy.c (parse_vma): Move to bucomm.c. + * bucomm.c (parse_vma): New function, moved in from objcopy.c. + * bucomm.h (parse_vma): Declare. + * binutils.texi, objdump.1: Document new objdump options. + +Tue Sep 12 12:37:39 1995 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.in (maintainer-clean): New target. + + * ar.c (replace_members): Don't call write_archive if nothing + changed. + + * objdump.c (disassemble_data): Add casts to avoid gcc warnings. + +Thu Sep 7 12:12:17 1995 Ian Lance Taylor <ian@cygnus.com> + + * config.in: Rename from config.h.in. + * configure.in: Call AC_CONFIG_HEADER with config.h:config.in. + Check for config.h:config.in when creating stamp-h. + * configure: Rebuild. + * Makefile.in (stamp-h): Depend upon config.in rather than + config.h.in. Set CONFIG_HEADERS to config.h:config.in when + calling config.status. + + * Makefile.in (distclean): Remove config.h, stamp-h, and + config.log. + + * nm.c (value_format): Initialize based on BFD64 and + BFD_HOST_64BIT_LONG. + (print_radix): New static variable. + (set_print_radix): Set print_radix. Adjust changes to + value_format. + (print_value): New static function, to print 64 bit octal and + decimal values correctly. + (print_symbol_info_bsd): Check BFD64, not BFD_HOST_64_BIT. Use + print_value. + (print_symbol_info_sysv): Use print_value. + (print_symbol_info_posix): Likewise. + +Wed Sep 6 15:02:55 1995 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.in (*.o): Remove incorrect dependencies on + $(BFDDIR)/hosts/std-host.h. + + * Makefile.in (INSTALL_DATA): Add -m 644. + (INSTALL_XFORM1): Likewise. + (CC_FOR_BUILD): Set to @CC_FOR_BUILD@ rather than $(CC). + (mostlyclean): Remove config.log. + (distclean): Remove config.cache. + + * configure.in: Call BFD_CC_FOR_BUILD and BFD_BINARY_FOPEN. + * configure: Rebuild. + +Tue Sep 5 20:22:42 1995 Ian Lance Taylor <ian@cygnus.com> + + * configure.in: Rewrite to use autoconf. + * aclocal.m4: New file. + * configure: New file, built by autoconf. + * acconfig.h: New file. + * config.h.in: New file, built by autoheader. + * Makefile.in: Various changes for new configure script. Also: + (PROGS): Remove $(SYSINFO_PROG). + (ALL_CFLAGS): Remove $(TDEFINES). + (version.o): Use $(ALL_CFLAGS). + (cplus-dem.o, dlltool.o, nlmconv.o): Likewise. + (sysdump.o): Depend upon bucomm.h and config.h. + (srconv.o, arsup.o, strings.o): Depend upon config.h. + (filemode.o): Don't depend upon ../bfd/sysdep.h. + (bucomm.o): Depend upon config.h, not ../bfd/sysdep.h. + (size.o, objdump.o, nm.o, ar.o, objcopy.o): Likewise. + (nlmheader.o, nlmconv.o): Likewise. + (distclean): Don't remove sysdep.h. + * bucomm.h: Include "ansidecl.h", <stdio.h>, and "config.h". + Include "fopen-same.h" or "fopen-bin.h", based on + USE_BINARY_FOPEN. Include <errno.h>, and declare errno if it is + not a macro. Include <unistd.h>, <string.h>, <strings.h>, + <stdlib.h>, and <fcntl.h> if they are present. Declare strchr, + strrchr, and strstr if no string header file exists. Include + <sys/file.h> if it exists and <fcntl.h> does not. Define + O_RDONLY and O_RDWR if necessary. + * ar.c: Don't include "sysdep.h". Do include <sys/types.h> and + <sys/stat.h>. Use HAVE_GOOD_UTIME_H rather than POSIX_UTIME. Use + HAVE_UTIMES rather than !USE_UTIME. Don't include <errno.h>, and + don't declare errno. + * arsup.c: Don't include <sysdep.h>. + * bucomm.c: Don't include "sysdep.h". Include <stdio.h>, + <sys/types.h>, and <sys/stat.h>. Include <time.h> if it defines + time_t. Define time_t if necessary. + * coffdump.c: Don't include "sysdep.h". + * coffgrok.c, filemode.c, nlmconv.c, size.c: Likewise. + * srconv.c, strings.c: Likewise. + * nm.c: Don't include "sysdep.h". Don't try to define HAVE_SBRK. + * objcopy.c: Don't include "sysdep.h". Include <sys/types.h> and + <sys/stat.h>. + (simple_copy): Use creat rather than assuming that O_CREAT is + defined. + * objdump.c: Don't include "sysdep.h". Use + NEED_DECLARATION_PRINTF rather than !FPRINTF_ALREADY_DECLARED. + * sysdump.c: Include "bfd.h" and "bucomm.h". Don't include + "sysdep.h" or <stdlib.h>. + (dump_symbol_info): Rename from symbol_info. Change all callers. + +Mon Sep 4 14:30:00 1995 Ian Lance Taylor <ian@cygnus.com> + + * configure.in (host_makefile_frag): Don't set. Substitute for + @CC@, @CFLAGS@, @HDEFINES@ and @LDFLAGS@ in Makefile. + * Makefile.in (AR_FLAGS): Set to rc rather than qv. + (CC): Define as @CC@. + (CFLAGS): Set to @CFLAGS@. + (LDFLAGS): Define as @LDFLAGS@. + (ALL_CFLAGS): Use @HDEFINES@ rather than $(HDEFINES). + + * configure.in: Don't bother to call config.bfd for each target. + Just call it for the default target, and use the shell variable to + decide whether underscores are used. + +Thu Aug 31 19:21:48 1995 Jason Molenda (crash@phydeaux.cygnus.com) + + * configure.in: match i[3-6]86-*-win32, not just i386-*-win32. + +Thu Aug 31 16:30:22 1995 steve chamberlain <sac@slash.cygnus.com> + + * dlltool.c (add_indirect): New. + (asm_prefix): New + (gen_exp_file): Timestamp should be 0. Insert prefix when + needed. New code for indirection. + (gen_lib_file): Timestamp should be 0. Insert prefix + when needed. + (usage): Document --add-indirect. + (main): Cope with new option. + + * objdump.c (dump_private_headers): New. + (usage): Document new option. + (long_option): Add private-headers. + (dump_bfd_private_header): New. + (main): Cope with new option. + +Thu Aug 31 04:09:16 1995 Doug Evans <dje@canuck.cygnus.com> + + * dlltool.c (run): Add missing 3rd arg to waitpid. + +Wed Aug 30 11:02:11 1995 steve chamberlain <sac@slash.cygnus.com> + + * Makefile.in (TOOL_PROGS): Include dlltool if needed. + +Tue Aug 29 13:25:21 1995 steve chamberlain <sac@slash.cygnus.com> + + * dlltool.c (rva): Deleted. + (rvaafter, rva_before): Use new assembler pseudo. + (flush_page, gen_exp_file, gen_lib_file): Use new way of RVAing. + (gen_exp_file): Don't generate .edata if no need. + (gen_lib_file): Don't make timestamp. + Put _iname in idata$7. + (workout_prefix): Fix memory initialization bug. + (usage): Tidy up, delete many single char options. + (main): rva option is gone. + +Mon Aug 21 18:41:28 1995 steve chamberlain <sac@slash.cygnus.com> + + * dlltool.c (options): image-base is a synonym for rva. + (gen_lib_file): Put dll name into ibase$7. + +Sun Aug 20 09:59:00 1995 steve chamberlain <sac@slash.cygnus.com> + + Modified to generate archives and objects rather than .s files. + * dlltool.c (run) New function. + (gen_exp_file, gen_lib_file): Use run. + (workout_prefix): New. + (usage): Document new options. + (main): Parse new options. + +Wed Aug 16 16:26:52 1995 steve chamberlain <sac@slash.cygnus.com> + + * dlltool.c (gen_exp_file): Fix RVA handling. + (rva_s, rva_n): Delete. + +Fri Aug 11 18:27:18 1995 Ian Lance Taylor <ian@cygnus.com> + + * nm.c (main): Ignore -e. + +Thu Aug 10 17:35:00 1995 Ken Raeburn <raeburn@cygnus.com> + + * Makefile.in (config.texi): New target. Write out a setting for + texinfo variable VERSION. + (binutils.dvi, binutils.info): Depend on it. + * binutils.texi: Include it, and reference @value{VERSION} instead + of explicitly specifying 2.2(!). + +Thu Aug 10 16:07:53 1995 Ian Lance Taylor <ian@cygnus.com> + + * coffgrok.c (do_type): Handle array dimensions the same way gdb + does. + +Tue Aug 8 17:10:42 1995 steve chamberlain <sac@slash.cygnus.com> + + * dlltool.c (mtable): New fields. + (ASM_RVA_BEFORE, ASM_RVA_AFTER): New. + (flush_page): Use new macros. + +Sat Aug 5 00:16:37 1995 Jeff Law (law@snake.cs.utah.edu) + + * objcopy.c (mark_symbols_used_in_relocations): Handle sections + with no relocations. + * coffgrok.c (do_sections_p1): Likewise. + +Mon Jul 31 12:51:06 1995 Ian Lance Taylor <ian@cygnus.com> + + * strings.c (print_strings): For compatibility with existing + strings programs, print strings which are not terminated with a + null byte or a newline. + * binutils.texi, strings.1: Update documentation accordingly. + + * ar.c (replace_members): For compatibility with existing ar + programs, permit users to add the same file multiple times. + +Tue Jul 25 11:21:53 1995 Ian Lance Taylor <ian@cygnus.com> + + * strings.c (DATA_FLAGS): Remove SEC_DATA. + (main): If no file names are given, scan standard input. + * binutils.texi, strings.1: strings now scans non-data sections by + default. + +Mon Jul 24 13:52:28 1995 J.T. Conklin <jtc@rtl.cygnus.com> + + * srconv.c (wr_hd): Set afl field to 4 for bfd_arch_sh. + (writeINT): When size == -2, use 2 bytes for the h8300 and 4 bytes + for the sh. + + * sysdump.c (fillup): Return size - 1, the last byte is a checksum + and shouldn't be counted. + * sysroff.info (hd): Changed segment identifier from a byte to a 1 + bit field. The sysroff 2.0-01 specification seems to be in error + here. Reduce width of following "spare" field from 4 to 3 bits. + (rl): Changed order and width of first 4 bitfields to correspond + to sysroff specification. + (dln_head, dln_inside, dln_tail): Removed. + +Tue Jul 18 23:00:03 1995 Fred Fish <fnf@cygnus.com> + + * nm.c (sort_symbols_by_size): Enclose expression being casted + in parens so result is casted, not just first operand. Can't + do pointer arithmetic on void* pointers. + +Fri Jul 14 13:42:42 1995 J.T. Conklin <jtc@rtl.cygnus.com> + + * sysdump.c (dh): Changed format of output to be 16 hex digits + followed by 16 ascii characters, similar to Emacs' hexl-mode, + to make it easier to read. + (xcalloc): fix typo. + +Thu Jul 13 15:27:44 1995 J.T. Conklin <jtc@rtl.cygnus.com> + + * srconv.c (wr_tr): Write out handcrafted tr block. + (walk_tree_symbol): Use evallen and evalue instead of + vallen & value because of corresponding changes in + sysroff.info. + + * sysdump.c (sysroff_swap_tr_in, sysroff_print_tr_out): New + functions. + + * sysroff.info (tr): the tr block is a special case --- a block + without contents --- which can't be handled by generated code. + (den, dpp): only first byte is present for DENend, DPPend. + (dsy): describe a conditional portion of block, rename some fields. + (dps): describe a conditional portion of block. + (dfl): removed. + + * sysinfo.y (yyerror): write error message to standard error. + +Thu Jul 13 10:43:59 1995 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.in (DISTSTUFF): Add arparse.h and sysinfo.h. + (mostlyclean): Remove y.output. + (clean): Remove sysroff, sysroff.c, sysroff.h, and sysinfo. + + * nlmconv.c (powerpc_mangle_relocs): Cast memset arg to size_t. + * objcopy.c (copy_object): Likewise. + + * nm.c (HAVE_SBRK): Define execpt on amigados and WINDOWS_NT. + (struct size_sym): Define. + (show_stats): New static variable. + (long_options): Add undocumented option "stats". + (main): Print memory stats if requested. + (sort_bfd, sort_dynamic, sort_x, sort_y): New static variables. + (numeric_forward): Use minisymbols rather than asymbols. + (non_numeric_forward): Likewise. + (size_forward1): Rename from size_forward. Use minisymbols. + (size_forward2): New static function. + (sort_symbols_by_size): Take new arguments dynamic, size, and + symsizep. Use minisymbols. Don't store the size back in the + symbol; store in a newly allocate struct size_sym array. + (display_rel_file): Read minisymbols rather than asymbols. Set + sort_* variables. Call print_size_symbols if sorting by size. + (filter_symbols): Take new arguments dynamic and size. Use + minisymbols. + (print_symbols): Likewise. Call print_symbol for actual printing. + (print_size_symbols): New static function. + (print_symbol): New static function. + +Wed Jul 12 10:43:05 1995 Ian Lance Taylor <ian@cygnus.com> + + * objdump.c (dump_section_stabs): Only print each stabs section + once. + (compare_relocs): Make it clear to gcc that this always returns a + value. + +Wed Jul 12 10:40:23 1995 H.J. Lu <hjl@nynexst.com> + + * objcopy.c (simple_copy): Preserve errno on failure. + (smart_rename): Print error mesage if simple_copy fails. + +Tue Jul 11 13:10:52 1995 J.T. Conklin <jtc@rtl.cygnus.com> + + * sysdump.c: re-indented file. + (module): read blocks sequentially instead of trying to parse + them, as that would require changing the parser recognize the + difference between a DPSstart and DPSend block. + (getone): Add break's between switch blocks as appropriate. + (object_body_list): parse blocks according to sysroff spec. + +Mon Jul 10 12:37:25 1995 J.T. Conklin <jtc@poseidon.cygnus.com> + + * sysroff.info: re-indented file, prior formatting was confusing + because it was indentation did not reflect nesting of conditional + records. Change "space size within segment" record in hd record + from bit to byte. + + * sysinfo.y (cond_it_field): Use xcalloc instead of calloc. + + * srconv.c (wr_cs): Reformatted cs header array, tag each byte + with a comment describing the field. + (wr_unit_info): Use SEEK_SET macro instead of constant 0. + (main): Use FOPEN_WB macro instead of literal "wb". + * sysroff.info: Remove fdl (dfl) field from cs block. Compare + ptr->type with ED_TYPE_CONST instead of constant 2 in ed block. + +Tue Jul 4 14:48:42 1995 Ian Lance Taylor <ian@cygnus.com> + + * nm.c (size_forward): Check yf against yn, not xn. + + * objcopy.c (copy_archive): Record all output BFD's, and close + them before unlinking them and removing the temporary directory, + to avoid NFS problems. + + * ar.c (replace_members): In verbose messages, use 'r' when + replacing a member, and 'a' when adding one. + + * ar.c (ar_truncate): New static variable. + (normalize): Change return type to const char *. Add abfd + argument. Change all callers. If ar_truncate, chop the filename + to abfd->ar_max_namelen. + (main): For the 'f' modifier, set ar_truncate to true. Don't + change quick_append to replace if ar_truncate is true. + (do_quick_append): If ar_truncate, set BFD_TRADITIONAL_FORMAT. + (write_archive): Likewise. + * binutils.texi, ar.1: Document 'f' modifier. + + * objcopy.c (enum strip_action): Define strip_unneeded. + (OPTION_STRIP_UNNEEDED): Define. + (strip_options): Add "strip-unneeded". + (copy_options): Likewise. + (copy_usage): Mention --strip-unneeded. + (strip_usage): Likewise. + (is_strip_section): Strip debugging sections if strip_unneeded. + (filter_symbols): If strip_unneeded, only keep BSF_KEEP symbols. + (copy_object): If strip_all, discard symbols without checking + discard_locals. + (copy_object): Call filter_symbols if strip_unneeded. + (setup_section): Strip debugging sections if strip_unneeded. + (copy_section): Likewise. + (strip_main): Handle OPTION_STRIP_UNNEEDED. + (copy_main): Likewise. + * binutils.texi, objcopy.1, strip.1: Document --strip-unneeded. + +Mon Jul 3 14:16:47 1995 Steve Chamberlain <sac@slash.cygnus.com> + + * configure.in (i386-*-win32): New configuration. + * dlltool.c (killat, xlate, usage, long_options, main): + Understand and cope with -k option. + +Sat Jul 1 12:25:15 1995 Fred Fish <fnf@cygnus.com> + + * ar.c: (extract_file): Change "#if POSIX_UTIME" to + "#ifdef POSIX_UTIME" to match other tests of POSIX_UTIME + and avoid lossage when POSIX_UTIME is not defined at all. + +Wed Jun 28 17:51:24 1995 Steve Chamberlain <sac@slash.cygnus.com> + + * ar.c: (print_contents.c, extract_file, do_quick_append): + Malloc buffers rather than allocate on stack (so it works + on NT). + * deflex.l: Names can have an @ in them. + * dlltool.c: Loads of stuff. Can now generate .imp files which + work with NT .dlls. + +Thu Jun 22 19:10:50 1995 Stan Shebs <shebs@andros.cygnus.com> + + * mpw-make.in (demangle.c.o): Remove. + (arparse.h): Depend on arparse.c instead of arparse.y. + +Wed Jun 21 17:32:45 1995 Ken Raeburn <raeburn@cujo.cygnus.com> + + * Makefile.in (DISTSTUFF): Don't include info here. + (diststuff): Include it here. + (realclean): Remove *.info. + + * objdump.c (compare_relocs): If relocation entries have the same + address, keep them in file order. + +Mon Jun 19 09:06:49 1995 Steve Chamberlain <sac@slash.cygnus.com> + + * dlltool.c: Change names of generated files. .*.s-> -*.s + + * objdump.c (dump_section_stabs): Check for names + which are supersets of selected names. + +Wed Jun 14 19:43:52 1995 Doug Evans <dje@canuck.cygnus.com> + + * dlltool.c (mtable, ARM jump): Must redirect via pc offsetable ptr. + +Wed Jun 14 13:27:22 1995 Steve Chamberlain <sac@slash.cygnus.com> + + * deflex.l, defparse.y, dlltool.c: New files. + * Makefile.in, configure.in: Support for them. + +Mon Jun 12 11:27:54 1995 Steve Chamberlain <sac@slash.cygnus.com> + + * sysdump.c: Include sysdep.h + (main): Open input with FOPEN_RB. + +Fri Jun 9 17:26:11 1995 Michael Meissner <meissner@tiktok.cygnus.com> + + * objdump.c (wide_output): New flag variable. + (usage): Print new -w, --wide options. + (long_options): Add --wide support. + (dump_section_header): If --wide, don't print a newline between + the section's first line and the flags. + (objdump_print_address): Use unsigned comparisons for the binary + search, not signed. + (disassemble_data): If --wide, don't put a \n between the + disassembly output and relocation information. + (main): Support -w option being the same as --wide. + +Thu Jun 1 17:09:27 1995 Ken Raeburn <raeburn@cujo.cygnus.com> + + Sat May 6 08:52:24 1995 H.J. Lu (hjl@nynexst.com) + + * objcopy.c (smart_rename): make it smarter, clean up + if rename () fails. + +Tue May 30 14:24:15 1995 Ken Raeburn <raeburn@cujo.cygnus.com> + + * Makefile.in: Delete lines with lots of #### because four or more + indicate a point for makefile fragment substitution. + +Tue May 9 17:17:05 1995 Michael Meissner <meissner@tiktok.cygnus.com> + + * configure.in: Don't build nlmconv on PowerPC eabi any more, it + is not needed. + +Thu Apr 27 20:21:24 1995 Doug Evans <dje@canuck.cygnus.com> + + * Makefile.in (EXPECT): Define. + (RUNTEST): Use one in source tree if present. + (check): Set `rootme' for $(EXPECT). + +Wed Apr 26 18:26:21 1995 Steve Chamberlain <sac@slash.cygnus.com> + + * srconv.c (main): Add support for -n option which disables + prescan of common symbols. + (wr_ob): If reading past the end of a section, fill with zeros. + +Tue Apr 25 19:14:37 1995 Ken Raeburn <raeburn@cujo.cygnus.com> + + * objdump.c (dump_section_header): Display load address after + virtual memory (run-time) address. + +Wed Apr 19 09:44:06 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * Makefile.in (cplus-dem.o): Pass -DVERSION='"$(VERSION)"' to the + compile. + (DEMANGLER_PROG): No longer uses version.o. + +Mon Apr 10 13:29:49 1995 Stan Shebs <shebs@andros.cygnus.com> + + Merge in support for Mac MPW as a host. + (Old change descriptions retained for informational value.) + + * mpw-config.in (TDEFINES): Define as empty in makefile frag. + + * mpw-config.in: Create mk.tmp, define ARCHDEFS in it. + + * mpw-config.in: New file, MPW configure fragment for binutils. + * mpw-make.in (install-only): New target. + (install): Also depend on install-only. + + * mpw-make.in (cplusfilt): Renamed from c++filt. + (INCLUDES): Add more paths. + + * mpw-make.in: New file, MPW makefile fragment for binutils. + (Normally automatically generated from Makefile.in.) + +Mon Mar 27 11:52:57 1995 Ian Lance Taylor <ian@cygnus.com> + + * ar.c (write_archive): Call make_tempname to get output file + name, rather than using a fixed name based on the input file. + + * objcopy.c (make_tempname): Copy from here... + * bucomm.c (make_tempname): ...to here, and make global. + * bucomm.h (make_tempname): Declare. + +Fri Mar 24 11:47:42 1995 Ian Lance Taylor <ian@cygnus.com> + + * strings.c: Include "bfd.h" before other headers. Include + "sysdep.h". + * bucomm.c (print_arelt_descr): Cast st_uid and st_gid to long, + and print them with %ld. + +Fri Mar 10 13:09:42 1995 Ian Lance Taylor <ian@cygnus.com> + + * objcopy.c (strip_options): Add --keep-symbol. + (copy_options): Likewise. + (copy_usage): Mention --keep-symbol and -K. + (strip_usage): Likewise. + (keep_symbols): New static variable. + (is_strip_symbol): Adjust the return value according to + keep_symbols. + (strip_main): Handle -K. For -N, check that -K was not given. + (copy_main): Likewise. + * binutils.texi, objcopy.1, strip.1: Document -K. + +Mon Mar 6 13:33:47 1995 Stan Shebs <shebs@andros.cygnus.com> + + * objcopy.c (copy_archive): Check result of mkdir. + (copy_main): Cast an xmalloc result. + + * objdump.c (usage): Break long format string into shorter ones. + +Mon Mar 6 13:46:12 1995 Ian Lance Taylor <ian@cygnus.com> + + * bucomm.c (list_supported_targets): New function. + * bucomm.h (list_supported_targets): Declare. + * ar.c (usage): Call list_supported_targets. + * nm.c (usage): Likewise. + * objcopy.c (copy_usage, strip_usage): Likewise. + * objdump.c (usage): Likewise. + * size.c (usage): Likewise. + * strings.c (usage): Likewise. + +Tue Feb 28 15:13:58 1995 Ian Lance Taylor <ian@cygnus.com> + + * bucomm.c (print_arelt_descr): Cast st_size to long before + passing it to fprintf. + +Fri Feb 17 13:36:45 1995 Ian Lance Taylor <ian@cygnus.com> + + * objcopy.c (struct section_list): Add fields remove, set_flags, + and flags. Change adjust from boolean to enum. + (remove_sections): Remove static variable. + (sections_removed): New static variable. + (copy_options): Add --set-section-flags. + (copy_usage): Mention --set-section-flags. + (parse_flags): New static function. + (find_section_list): New static function. + (is_strip_symbol): Change return type from int to boolean. + (is_strip_section): New static function. + (filter_symbols): Call is_strip_section. + (copy_object): When adding sections, check for specified flags or + VMA. Call filter_symbols if any sections are being removed. + (setup_section): Use find_section_list function rather than + looking through remove_sections and adjust_sections. Handle + --set-section-flags. + (copy_section): Use find_section_list rather than looking through + remove_sections. + (strip_main): Use find_section_list instead of adding items to + sections_removed. + (copy_main): Use find_section_list instead of adding items to + sections_removed and adjust_sections. Handle --set-section-flags. + * binutils.texi, objcopy.1: Document --set-section-flags. + +Tue Feb 14 18:03:03 1995 Ian Lance Taylor <ian@cygnus.com> + + * objdump.c (with_source_code): New global variable. + (usage): Mention -S/--source. + (long_options): Add --source. + (prev_functionname, prev_line): New static variables. + (struct print_file_list): Define. + (print_files): New static variable. + (skip_to_line, show_line): New static functions. + (disassemble_data): Call show_line to handle -l and -S. + (main): Handle -S. + * binutils.texi, objdump.1: Document -S/--source. + +Thu Feb 9 16:11:53 1995 Ian Lance Taylor <ian@cygnus.com> + + * objcopy.c (copy_usage): Rename parameter to avoid shadowing. + (strip_usage): Likewise. + + * objcopy.c (struct section_add): Define. + (add_sections): New static variable. + (copy_options): Accept --add-section. + (copy_usage): Mention --add-section. + (copy_object): Add sections from the add_sections list. + (copy_main): Handle --add-section. + * binutils.texi, objcopy.1: Document --add-section. + +Wed Feb 1 15:04:57 1995 Ken Raeburn <raeburn@cujo.cygnus.com> + + * objdump.c (disassemble_data): Pass section offset, not absolute + address, to bfd_find_nearest_line. + + * nlmconv.c (powerpc_mangle_relocs): Don't use const with + reloc_howto_type. + +Thu Jan 26 18:50:06 1995 Ian Lance Taylor <ian@cygnus.com> + + * objdump.c (compare_symbols): Use bfd_asymbol_value (VAR) rather + than VAR->value. + (objdump_print_address): Likewise. + (disassemble_data): Don't change the symbol values. It can + confuse bfd_canonicalize_reloc. + +Thu Jan 26 12:03:56 1995 Michael Meissner <meissner@tiktok.cygnus.com> + + * configure.in: Add support for powerpc-*-ebai. + +Wed Jan 18 10:02:12 1995 Steve Chamberlain <sac@splat> + + * coffdump.c: Include sysdep.h. + (dump_coff_type): Handle coff_secdef_type. + * coffgrok.c : Include sysdep.h. + * srconv.c: Include libiberty.h + (absolute_p, dty_start, dty_end, dump_tree_structure): Remove. + +Wed Jan 18 12:24:14 1995 Ian Lance Taylor <ian@sanguine.cygnus.com> + + * coffdump.c (dump_coff_scope): Cast pointer to unsigned long for + printf. + * coffgrok.c: Include bucomm.h. Don't declare xmalloc. + (push_scope): Declare type of parameter link. + * size.c: Include libiberty.h. + * srconv.c: Include bucomm.h. + (find_base): Declare at top of file. + (wr_hd): Add default case to architecture switch. + (wr_dps_start): Declare type of parameter nest. + (wr_du): Comment out variables used only in commented out blocks. + (wr_dus): Remove unused variable i. + (wr_sc): Remove unused variables myinfo, low, and high. + * strings.c: Include libiberty.h. + * sysdump.c: Include <ctype.h>. + +Tue Dec 20 19:13:44 1994 Ian Lance Taylor <ian@sanguine.cygnus.com> + + * ar.c (main): Ignore 'f' modifier used on HP/UX 9. + +Thu Dec 15 17:34:12 1994 Stan Shebs <shebs@andros.cygnus.com> + + * ar.c, nm.c, objcopy.c, objdump.c: Include progress.h. + * ar.c, nm.c, objcopy.c, objdump.c (main): Add START_PROGRESS + and END_PROGRESS. + * ar.c (map_over_members, open_inarch): Call PROGRESS. + * nm.c (main, display_archive, filter_symbols, print_symbols): + Call PROGRESS. + + * objcopy.c (copy_usage): Break up long usage string. + +Wed Dec 14 15:51:56 1994 Ken Raeburn <raeburn@cujo.cygnus.com> + + * objcopy.c (copy_object): Don't bother setting status after + nonfatal() "call", because it won't return. + +Fri Dec 9 00:22:54 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (powerpc_mangle_relocs): Don't switch a reloc to use + the section symbol if the symbol is undefined. + +Thu Dec 8 14:45:50 1994 Ken Raeburn <raeburn@cujo.cygnus.com> + + * objcopy.c (add_strip_symbol): Cast return value of xmalloc. + +Wed Nov 30 11:05:43 1994 Ian Lance Taylor <ian@rtl.cygnus.com> + + * ar.c (replace_members): Pass current->filename to normalize when + checking for duplicates, because the filename of a newly added + file will not have been normalized yet. + +Thu Nov 17 15:00:13 1994 Ian Lance Taylor <ian@sanguine.cygnus.com> + + * ar.c (main): Don't call do_quick_append if any of the archive + names are longer than 14 characters. + + * objcopy.c (main): Fix is_strip test. From + pirker@eiunix.tuwien.ac.at (Martin Pirker). + +Thu Nov 17 15:37:19 1994 Mark W. Eichin <eichin@cygnus.com> + + * objcopy.c (add_strip_symbol): New function, adds a name to an + explicit list of symbols to strip. + (is_strip_symbol): New function, reports whether the name argument + is in the explicit list. + (filter_symbols): Check against is_strip_symbol above all. + (strip_main): Recognize -N option. If used, don't default to + strip_all. + (copy_main): Recognize -N option. + (strip_usage): Document -N and --strip-symbol options. + (copy_usage): Ditto. + * objcopy.1, strip.1, binutils.texi: Document -N and + --strip-symbol options. + +Tue Nov 8 13:12:54 1994 Ian Lance Taylor <ian@sanguine.cygnus.com> + + * objdump.c (display_target_list, display_info_table): Pass an + array to tmparg, rather than NULL, since some systems can't handle + NULL. + + * objcopy.c (copy_archive): Keep a list of the names of the + temporary files we created. Close each input BFD after we open + its successor. + +Mon Nov 7 15:48:39 1994 Ken Raeburn <raeburn@cujo.cygnus.com> + + * Makefile.in (VERSION): Bump to 2.5.3. + +Thu Nov 3 19:04:34 1994 Ken Raeburn <raeburn@cujo.cygnus.com> + + * Makefile.in (install-info): Install info files from whatever + directory they were found in. + + Patch from DJ Delorie: + * configure.bat: do c++filt -> cxxfilt right + + * sysinfo.y: Include system header files early, so any potential + declaration of abort() occurs before its use. + + * strings.c (strings_file): Try opening the file in binary mode + first. + +Wed Nov 2 15:44:13 1994 Ian Lance Taylor <ian@sanguine.cygnus.com> + + * ar.c (main): Treat ar qs like ar rs. + +Tue Oct 25 16:19:25 1994 Ian Lance Taylor <ian@sanguine.cygnus.com> + + * objcopy.c (gap_fill): Explicitly initialize, for clarity. + (pad_to_set, pad_to): New static variables. + (copy_options): Accept --pad-to. + (copy_usage): Mention --pad-to. + (copy_object): Support --pad-to. + (compare_section_vma): Sort non loadable sections to the front. + Sort sections with the same VMA by size. + (copy_main): Handle --pad-to. + * binutils.texi, objcopy.1: Document --pad-to. + +Thu Oct 20 13:51:31 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objcopy.c (gap_fill_set, gap_fill): New static variables. + (copy_options): Accept --gap-fill. + (copy_usage): Mention --gap-fill. + (copy_object): Support --gap-fill. + (get_sections, compare_section_vma): New static functions. + (copy_main): Handle --gap-fill. + * binutils.texi, objcopy.1: Document --gap-fill. + +Wed Oct 19 14:09:16 1994 Ian Lance Taylor <ian@sanguine.cygnus.com> + + * Makefile.in (check): Add a dummy else clause to the if + statement. + + * objcopy.c (copy_object): Revert yesterday's change. + * binutils.texi, objcopy.1: Remove special mention of --set-start + and `binary' output format. + +Tue Oct 18 11:12:01 1994 Ian Lance Taylor <ian@sanguine.cygnus.com> + + * objcopy.c (copy_object): If the output file format is `binary', + and the start address was not set using --set-start, default the + start address to zero. This hack is because the `binary' output + file format uses the start address to set the virtual address of + the first byte in the file. + * binutils.texi, objcopy.1: Add some notes on generating S-records + and binary files. + + * nm.c (print_symdef_entry): Call print_symname to print the + symbol name, so that --demangle works. + + * Makefile.in (mostlyclean): Remove tmpdir. + + * objcopy.c (struct section_list): Add fields used, adjust, val. + (adjust_start, set_start_set, set_start): New static variables. + (adjust_section_vma, adjust_sections): New static variables. + (copy_options): Add --adjust-start, --adjust-vma, + --adjust-section-vma, --adjust-warnings, --no-adjust-warnings, + --set-start. + (parse_vma): New static function. + (copy_usage): Mention new options. + (copy_object): Handle --set-start and --adjust-start. + (setup_section): Correct type of last argument to PTR. Set used + field if section is removed. Handle --adjust-vma and + --adjust-section-vma. + (copy_section): Correct type of last argument to PTR. + (mark_symbols_used_in_relocations): Likewise. + (strip_main): Clear used field when handling -R. + (copy_main): Handle new options. + * binutils.texi (objcopy): Document new options. + * objcopy.1: Document new options. + +Fri Oct 14 14:38:13 1994 Ian Lance Taylor <ian@sanguine.cygnus.com> + + * configure.in (configdirs): Remove definition--testsuite is no + longer configured. + * Makefile.in (testsuite): Remove target. + (site.exp): New target. + (check): Rewrite. + (clean, distclean): Don't recur into testsuite directory. + +Thu Oct 13 19:24:09 1994 Ken Raeburn <raeburn@cujo.cygnus.com> + + * Makefile.in (VERSION): Updated to 2.5. + * Version 2.5 released. + +Tue Oct 11 15:26:42 1994 Ian Lance Taylor <ian@sanguine.cygnus.com> + + * Makefile.in (sysdump.o): Depends upon sysroff.c. + +Mon Oct 10 13:50:30 1994 J.T. Conklin (jtc@rtl.cygnus.com) + + * nlmconv.c (link_inputs): Pass -Ur flag to ld so that the + ctor/dtor tables needed by C++ programs are built. + +Sun Oct 9 18:04:00 1994 Jim Wilson (wilson@sphagnum.cygnus.com) + + * Makefile.in (srconv.o): Add dependence on sysroff.c. + +Tue Oct 4 12:19:51 1994 Ian Lance Taylor <ian@sanguine.cygnus.com> + + * configure.in: Use ${config_shell} when running config.bfd. + + * Makefile.in (sysroff.h): Split target away from sysroff.c. + (srconv.o, sysdump.o): New targets. + (srconv, sysdump): Don't depend upon sysroff.c. + +Wed Sep 28 13:04:34 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * Makefile.in (arparse.c): Don't ignore errors from mv. + (sysinfo.c): Likewise. Also, depend upon arparse.c, to prevent a + parallel make from trying to build both arparse.c and sysinfo.c + simultaneously. + (nlmheader.c): Similar change. + (arparse.h): Separate target from arparse.c, so that a parallel + make does not try to build both at once. Depend upon arparse.c. + (sysinfo.h): Similar change. + + * objdump.c (disassemble_data): Pass the reloc buffer to free, not + the pointer used to loop over the relocs. + +Sat Sep 24 16:16:57 1994 Stan Shebs (shebs@andros.cygnus.com) + + * objdump.c (disassemble_data): Cast result of xmalloc. + +Wed Sep 21 19:30:35 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * objdump.c (sorted_syms, sorted_symcount): New global variables. + (objdump_print_address): Use sorted_syms and sorted_symcount + instead of syms and symcount. + (disassemble_data): Don't bother to get the relocs before looping + over the sections. Before filtering and sorting the symbol table, + copy it into sorted_syms. + +Fri Sep 16 11:27:39 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * objdump.c (struct objdump_disasm_info): Add field require_sec. + (objdump_print_address): If aux->require_sec, require that the + symbol be in aux->sec even if HAS_RELOC is not set. If we can't + find a smaller symbol in the right section, look for a larger one. + (disassemble_data): Set aux.require_sec around the + objdump_print_address call for the instruction address. + +Thu Sep 15 21:43:17 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * ar.c: Call xexit rather than exit. + (output_filename, output_file, output_bfd): New static variables. + (remove_output): New static function. + (main): Call xatexit (remove_output). Call xexit rather than + returning. + (extract_file): Set output_filename and output_file while output + file is open. + (write_archive): Likewise, but use output_bfd, not output_file. + * arsup.c: Include libiberty.h. Call xexit rather than exit. + * bucomm.c: Likewise. + + * objdump.c (disassemble_all): New global variable. + (usage): Document --disassemble-all. + (long_options): Add disassemble-all as a synonym for -D. + (compare_symbols): Make pointers const. + (compare_relocs): New static function. + (disassemble_data): Rename disassemble to disassemble_fn to avoid + shadowing. If dump_reloc_info, print relocs along with + disassembly. Skip sections which are not SEC_CODE unless + disassemble_all or only is set. + (display_bfd): Don't call dump_relocs if disassemble is set. + (main): Accept and handle -D. + * binutils.texi: Document -D/--disassemble-all. + * objdump.1: Likewise. + +Wed Sep 14 12:19:07 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * objdump.c (disassemble_data): Initialize prevline to 0. Make + prev_function non const. Copy functionname into an malloc buffer + when setting prev_function, instead of assuming that the string + will last forever. + + * nm.c: Include libiberty.h. + (sort_by_size): New static variable. + (long_options): Add --size-sort. + (usage): Mention --size-sort. + (numeric_forward): Make static. Change from void * to PTR. + (numeric_reverse): Likewise. + (non_numeric_forward, non_numeric_reverse): Likewise. + (sorters): Change declaration from void * to PTR. + (size_forward, sort_symbol_by_size): New static functions. + (display_rel_file): Handle sort_by_size. + (filter_symbols): If sort_by_size, discard absolute and undefined + symbols. + * binutils.texi (nm): Document --size-sort. + * nm.1: Document --size-sort. + +Tue Sep 13 21:06:06 1994 Jeff Law (law@snake.cs.utah.edu) + + * objcopy.c (copy_main): Initialize input_filename and + output_filename to NULL. + +Tue Sep 13 14:17:24 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * Makefile.in (version.o): Depend upon Makefile, so that version.o + gets rebuilt when make variable VERSION is changed. + + * objdump.c (dump_section_header): Print the SEC_NEVER_LOAD flag. + +Wed Aug 24 12:40:09 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * configure.in: Change i[34]86 to i[345]86. + +Tue Aug 23 11:00:40 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * ar.c (ranlib_touch): Don't update the archive map if there isn't + one. + +Mon Aug 22 16:02:18 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * ar.c: Include libiberty.h. + (inarch): Remove variable. + (map_over_members): Make static. Add arch argument, and use it + instead of inarch. Change all callers. + (main): Treat --version as -v. Accept -t argument. Accept any + number of archive arguments. Catch and use open_inarch return + value, rather than using inarch. + (open_inarch): Return newly opened BFD, rather than using inarch. + (do_quick_append): Make archive_filename const. + (write_archive): Add iarch argument, and use it instead of inarch. + Change all callers. + (delete_members, move_members, replace_members): Likewise. + (ranlib_only): Don't exit on success. Catch and use open_inarch + return value. + (ranlib_touch): New function. + * arsup.h (map_over_members): Don't declare. + (ar_end, ar_extract): Declare. + (open_inarch): Change return value in declaration to bfd *. + * arsup.c (map_over_list): Make static. Always pass two arguments + to function. Add arch argument, and use it instead of inarch. + Change all callers. + (ar_directory_doer): Make static. Add ignored second argument. + Change all callers. + (ar_directory): Use open_inarch return value rather than inarch. + (ar_addlib_doer): Make static. + (ar_addlib): Use open_inarch return value rather than inarch. + (ar_extract): Remove unused local variable abfd. + +Thu Aug 11 14:55:57 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + Add support for removing named sections to objcopy and strip. + * objcopy.c (struct section_list): Define. + (remove_sections): New static variable. + (strip_options, copy_options): Add remove-section. + (copy_usage, strip_usage): Mention -R and --remove-section. + (setup_section): If section is in remove_sections list, ignore it. + (copy_section): Likewise. + (strip_main, copy_main): Handle -R. + * binutils.texi, objcopy.1, strip.1: Document new options. + +Wed Aug 10 10:19:55 1994 Stan Shebs (shebs@andros.cygnus.com) + + * nlmconv.c (powerpc_mangle_relocs): Rename symvalue to sym_value, + so as not to conflict with the symvalue typedef in bfd.h. + +Mon Aug 1 13:19:09 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * nlmheader.y: Per current NetWare docs, accept a revision number + of 0 and treat a revision number greater than 26 as 0. + +Mon Jul 25 12:58:36 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * objdump.c (objdump_print_address): Correct handling of end of + symbols when looking for next symbol with a different value. + +Fri Jul 22 16:48:34 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * nm.c (numeric_forward): Treat undefined symbols as "less than" + defined symbols with zero values. If numeric values are equal, or + both symbols are undefined, sort alphabetically. Don't assume + that the difference of two bfd_vma values will truncate to "int" + and still have the same sign. + (numeric_reverse): Call numeric_forward and negate the result. + (print_symbol_info_bsd): For undefined symbols, print leading + spaces equivalent to the width of a printed bfd_vma, rather than + assuming that 8 will look right. + +Fri Jul 22 10:36:50 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * coffgrok.c (doit): Zero all fields of new structure. + * srconv.c (sysroff_swap_*_out): Remove redundant trailing arg. + * sysinfo.y: Generate sysroff_swap_*_out without requiring extra + arg. + +Fri Jul 22 10:09:53 1994 J.T. Conklin (jtc@phishhead.cygnus.com) + + * nlmheader.y: Make "stack" and "stacksize" synonyms in the lexer + rather than the parser. + +Thu Jul 21 10:25:09 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * config/mh-alphaosf, config/mh-apollo68v, config/mh-delta88: + Remove; obsolete. + +Sat Jul 16 22:34:39 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * objdump.c (slurp_dynamic_symtab): Try to get the dynamic symbols + even if the bfd is not marked DYNAMIC. ELF executables are not + marked DYNAMIC, but do have dynamic symbols. + +Fri Jul 15 01:41:35 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * coffgrok.c (do_where): Make data with no type 'int'. + (do_define): Keep info on source file of a symbol. + * coffgrok.h (coff_symbol): New field. + * srconv.c (PROGRAM_VERSION): Now 1.3 + (wr_rl): Use external ref number for symbol. + (wr_dus): Only keep one source file per debug unit. + (wr_dln): Always emit line numbers for first source file, + (wr_globals): Emit globals in the du of their owning source file. + +Mon Jul 11 15:59:03 1994 J.T. Conklin (jtc@phishhead.cygnus.com) + + * nlmheader.y: Null terminate var_hdr->threadName. + +Fri Jul 8 17:33:22 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * Makefile.in (syslex.o, sysinfo.o): Permit C source files to be + in $(srcdir), as they will be for FSF releases. + +Wed Jul 6 01:13:14 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (setup_sections): Preserve existing section flags when + copying in flags from a new section. + +Tue Jul 5 15:56:01 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * objcopy.c: Include libiberty.h. + (copy_file): If output_target is NULL, set it to the target of the + input file. + +Wed Jun 29 17:17:14 1994 J.T. Conklin (jtc@phishhead.cygnus.com) + + * nlmconv.c (link_inputs): Fixed memory allocation bug. + +Thu Jun 23 12:52:46 1994 David J. Mackenzie (djm@rtl.cygnus.com) + + * configure.in: Change --with-targets to --enable-targets. + +Tue Jun 21 12:53:21 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * Makefile.in (sysinfo): Does not depend upon $(ADDL_LIBS). + + * nlmconv.c (powerpc_build_stubs): Don't generate the PowerPC + NetWare custom header; no longer needed. + (powerpc_mangle_relocs): Convert relocs against the uninitialized + data section into relocs against the data section. + + * configure.in: Set nlmconv_defs to -DNLMCONV_cputype for all the + netware targets. Write it into Makefile as NLMCONV_DEFS. + * Makefile.in (nlmconv.o): Pass $(NLMCONV_DEFS) to $(CC). + * nlmconv.c: Only compile code for specific CPU types if + NLMCONV_cputype is defined. + + * nlmconv.c (main): Change uses of bfd_abs_section, etc., to use + bfd_abs_section_ptr or bfd_is_abs_section, etc. + (i386_mangle_relocs, alpha_mangle_relocs): Likewise. + (powerpc_build_stubs): Likewise. + * nm.c (filter_symbols, print_symbols): Likewise. + * objcopy.c (filter_symbols): Likewise. + (mark_symbols_used_in_relocations): Likewise. + * objdump.c (remove_useless_symbols, dump_relocs): Likewise. + * size.c (sysv_internal_printer): Likewise. + +Mon Jun 20 16:43:03 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * Makefile.in (MANPAGES): Remove $(DEMANGLER_PROG). + (install): Install it explicitly, from build dir, not srcdir. + +Mon Jun 20 16:29:54 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * objdump.c: Don't include elf/internal.h. + (bfd_elf_find_section): Don't declare. + (read_section_stabs): No special handling for ELF. Always read + using BFD sections. + +Thu Jun 16 17:25:20 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * configure.in: Set UNDERSCORE in Makefile based on result of + invoking config.bfd with a second argument of ``_''. + * Makefile.in (underscore.c): Depend upon Makefile. Don't try to + run $(CC) and $(NM), just use $(UNDERSCORE). Create via temporary + file. + (demangle.o): Remove target. + ($(NM_PROG)): Don't depend upon demangle.o, and don't link against + demangle.o. It's in libiberty anyhow. + (cplus-dem.o): Don't depend upon demangle.o. + * binutils.texi: Mention -n and --no-strip-underscores arguments + to c++filt. + +Wed Jun 15 12:10:31 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nm.c (long_options): Add --no-demangle to turn off --demangle, + and --no-cplus for Linux compatibility. + (usage): Mention --no-demangle. + * binutils.texi: Document --no-demangle. + +Fri Jun 10 15:41:25 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nm.c: HOST_64_BIT was renamed to BFD_HOST_64_BIT. + + * objcopy.c (copy_archive): Make the temporary directory in the + same directory as the output BFD, since we may not have write + permission on the current directory. Set the permissions of the + new directory to 0700, not 0777. + +Mon Jun 6 21:36:43 1994 D. V. Henkel-Wallace (gumby@cygnus.com) + + * configure.in: if this is an rs6000 (and we're not building for + any other bfd targets) then build only nm (collect needs it on + rs6000-lynx). + + * Makefile.in: define TOOL_PROGS which the list of programes to + install in $tooldir -- replaces a hard-coded list. + +Fri Jun 3 10:59:18 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objdump.c (display_target_list): Remove unused local ok. + +Thu May 26 18:05:52 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * config/mh-alphaosf (CFLAGS): Don't specify both -g and -O; + they're not compatible under native cc. Use -O1 instead. + + * Makefile.in (VERSION): Updated to cygnus-2.4.1. + + Changes from binutils-2.4 net release: + + * Makefile.in (MANPAGES): Use $(DEMANGLER_PROG). + ($(DEMANGLER_PROG).1): Build from cxxfilt.man, using sed. + * cxxfilt.man: Renamed from c++filt.1, replaced "c++filt" with + magic token to be replaced by sed. + + Wed May 11 22:32:00 1994 DJ Delorie (dj@ctron.com) + + * configure.bat: update for latest makefile.in + +Fri May 13 23:25:13 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * bucomm.c: Check ANSI_PROTOTYPES rather than __STDC__. + +Tue May 10 18:22:06 1994 Jason Molenda (crash@sendai.cygnus.com) + + * objcopy.c (copy_section): Set section size correctly if using + interleave. + +Sat May 7 16:49:36 1994 Steve Chamberlain (sac@cygnus.com) + + * Makefile.in: Add rule for sysinfo.h + +Fri May 6 12:18:33 1994 Steve Chamberlain (sac@cygnus.com) + + * Makefile.in (SRCONV_PROG): Define. + (PROGS): Use $(SRCONV_PROG) too. + +Thu May 5 19:41:43 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * Makefile.in (DISTSTUFF): Add sysinfo.c, syslex.c, in case + someone configures with `targets=all'. + (distclean): Remove y.*. + (syslex.o): Depend on sysinfo.h. + (sysinfo.c): Rename y.tab.h to sysinfo.h. + (install-info): Don't try to install into $(infodir)/$(srcdir). + * syslex.l: Include sysinfo.h, not y.tab.h. + +Thu May 5 11:50:55 1994 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + * syslex.l (yywrap): Define as function if not defined as a macro. + + * Makefile.in (objdump.o): Deleted special rule. + * configure.in: Don't bother building ARCHDEFS variable for + Makefile. + * objdump.c (ARCH_*): Deleted handling. + (disassemble_data): Call `disassembler' from opcodes library. + +Thu May 5 13:28:42 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * Makefile.in (install): Correct handling of $(tooldir) and + $(bindir) being on different devices. + +Fri Apr 29 09:50:38 1994 Steve Chamberlain (sac@cygnus.com) + + * sysdump.c (h8300, sh): Add declarations. + +Wed Apr 27 11:25:18 1994 Steve Chamberlain (sac@cygnus.com) + + * Makefile.in (syslex, sysinfo): Use CC_FOR_BUILD. + * coffdump.c, coffgroc.c, coffgrog.h, srconv.c, sysdump.c, + sysroff.info: Major changes. + +Tue Apr 26 18:18:24 1994 Stan Shebs (shebs@andros.cygnus.com) + + * objdump.c (print_section_stabs): Indicate the stab header symbol + more clearly, print numbers of unrecognized stab n_type values. + +Tue Apr 26 16:22:55 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (copy_sections): Copy arelent pointers, not arelents. + +Mon Apr 25 16:14:32 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * Makefile.in (distclean): Remove $(PROGS) and underscore.c. + +Fri Apr 22 11:14:19 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (setup_sections): Remove special handling of .reginfo + section. + (copy_sections): Likewise. + (alpha_mangle_relocs): Use bfd_ecoff_get_gp_value rather than the + special ECOFF .reginfo section. + + * objcopy.c (copy_object): Call bfd_copy_private_bfd_data after + copying everything else, to let it fiddle with the file in its + final state. + + * objdump.c: Include libiberty.h. + (display_target_list): If a format fails, just go on to the next + one. Check return value of bfd_set_format. + (display_info_table): Likewise. Don't increment loop variable in + for loop test, since that skips the first element. + (display_target_tables): Rewrite loop for clarity. Ensure that it + always prints at least one element. + + * nlmconv.c (main): Use CyGnUsEx rather than CyGnUsSeCs for + sections header. Rename from cygnus_sections to cygnus_ext. + +Thu Apr 21 12:12:26 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objdump.c (_DUMMY_NAME_): Don't define. + (display_target_list): Use tmpnam to get a file name rather than + using _DUMMY_NAME_. Unlink it when done. + (display_info_table): Likewise. + + * nlmconv.c (secsec): New static variable. + (main): Create .nlmsections section in output BFD. Store + information about it in sections header. + (setup_sections): Allocate space in sections header. + (copy_sections): Copy zero sized sections. Put information about + each section in the sections header. + +Wed Apr 20 14:34:51 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (powerpc_build_stubs): Take new outbfd argument. + Change caller. Create custom header for new PowerPC NetWare + format. + + * Makefile.in (nlmheader.o, nlmconv.o): Update dependencies. + * nlmconv.c: Include bfd.h and libiberty.h with "", not <>. + * nlmheader.y: Include bfd.h with "", not <>. + +Wed Apr 13 10:52:50 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objdump.c: Do an ifdef on __GO32__, not unix. + +Wed Apr 6 21:54:49 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + Added -D (--dynamic) option to nm and -T (--dynamic-syms) and -R + (--dynamic-reloc) arguments to objdump. + * nm.c (dynamic): New static variable. + (long_options): Added "dynamic". + (usage): Mention -D and --dynamic. + (main): Add D to getopt string. Handle -D by setting dynamic. + (display_rel_file): If dynamic is non-zero, read dynamic symbols + rather than normal symbols. + * nm.1: Updated for -D (--dynamic) option. + * objdump.c (dump_dynamic_symtab): New global variable. + (dump_dynamic_reloc_info): New global variable. + (dynsyms, dynsymcount): New global variables. + (usage): Mention -R, -T, --dynamic-syms and --dynamic-reloc. + (long_options): Added "dynamic-reloc" and "dynamic-syms". + (slurp_symtab): If no symbols, return rather than exit. + (slurp_dynamic_symtab): New function. + (display_bfd): Handle dump_dynamic_symtab and + dump_dynamic_reloc_info. + (dump_symbols): Take new dynamic argument, indicating whether to + display dynamic symbols. + (dump_relocs): Move most printing into dump_reloc_set. + (dump_dynamic_relocs): New function. + (dump_reloc_set): New function, extracted from dump_relocs. + (main): Add R and T to getopt string. Handle -T by setting + dump_dynamic_symtab and -R by setting dump_dynamic_reloc_info. + * objdump.1: Updated for -R (--dynamic-reloc) and -T + (--dynamic-syms) options. + * binutils.texi: Updated for new nm and objdump options. + +Wed Mar 30 15:52:40 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + Update for recent BFD changes to symbol and reloc reading. Rename + all uses of get_symtab_upper_bound to bfd_get_symtab_upper_bound. + Also: + * coffgrok.c (symcount): Change to long. + (do_sections_p1): Check for error return from + bfd_get_reloc_upper_bound. Change relcount to long, and check for + error from bfd_canonicalize_reloc. + (coff_grok): Change storage to long. Check for error from + bfd_get_symtab_upper_bound and bfd_canonicalize_symtab. + * nlmconv.c (main): Change symcount, newsymalloc, newsymcount, and + i to long. Check for error from bfd_get_symtab_upper_bound and + bfd_canonicalize_symtab. + (copy_sections): Change reloc_size and reloc_count to long. Check + for error from bfd_get_reloc_upper_bound and + bfd_canonicalize_reloc. + (mangle_relocs, i386_mangle_relocs, alpha_mangle_relocs): Change + reloc_count_ptr argument to long *. Make corresponding changes to + variables loaded from *reloc_count_ptr. + * nm.c (display_rel_file): Change storage and symcount to long. + Check for errors from bfd_get_symtab_upper_bound and + bfd_canonicalize_symtab. + * objcopy.c (filter_symbols): Change symcount, src_count and + dst_count to long. + (copy_object): Change symcount to long. Pass another argument to + fprintf. Check for errors from bfd_get_symtab_upper_bound and + bfd_canonicalize_symtab. + (copy_section): Change relcount to long. Check for errors from + bfd_get_reloc_upper_bound and bfd_canonicalize_reloc. + (mark_symbols_used_in_relocations): Change relcount and i to long. + Check for errors form bfd_get_reloc_upper_bound and + bfd_canonicalize_reloc. + * objdump.c (storage): Remove global variable. + (symcount): Changed to long. + (slurp_symtab): New local variable storage. Check for errors from + bfd_get_symtab_upper_bound and bfd_canonicalize_symtab. + (remove_useless_symbols): Change return value and count to long. + (objdump_print_address): Change min, max, thisplace and i to long. + (disassemble_data): Change i to long. + (dump_symbols): Change count to long. + (dump_relocs): Change relcount to long. Check for errors from + bfd_ret_reloc_upper_bound and bfd_canonicalize_reloc. + (display_info_table): Add casts when passing LONGEST_ARCH for + printf %* argument. + +Tue Mar 29 14:59:04 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nm.c (display_archive): Close each archive element after it has + been displayed. + * objdump.c (display_file): Likewise. + +Mon Mar 28 13:04:08 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * configure.in: Change error message to refer to bfd/config.bfd + rather than bfd/configure.in. + +Sun Mar 27 16:23:39 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * More fixes for object formats which allow multiple sections + with the same name: + * objcopy.c (setup_section): Make a new output section even if + one already exists with the given name. + (copy_section): Use isection->output_section rather than trying + to look the output section up by its (possibly non-unique) name. + + * Makefile.in (install-info): Look for binutils.info in the + current directory, then in $(srcdir). Don't use $<. + +Mon Mar 21 12:55:45 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objdump.c (objdump_print_address): Make static. Declare with + prototype. Change vardiff from int to bfd_signed_vma. Correct + binary search termination condition. When looking for same + section symbol in relocatable file, handle final symbol correctly. + +Sun Mar 20 11:26:36 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * Makefile.in: Avoid bug in hpux sed. + + * objcopy.c: Changes to keep it from stripping symbols used + in output relocations. + (mark_symbols_used_in_relocations): New function. Mark symbols + used in output relocations with BSF_KEEP. + (filter_symbols): Do not strip symbols marked with BSF_KEEP. + (copy_object): Reorder actions. First setup sections, then + build the output symbol table, then copy the section contents. + +Fri Mar 18 10:53:55 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * ar.c (write_archive): Allocate space for the null byte. From + Robert Lipe <robertl@arnet.com>. + +Thu Mar 17 16:20:28 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * Makefile.in: Built nm.new and strip.new to avoid problems with + collect when . is in PATH. + (STRIP_PROG): Change from strip to strip.new. + (NM_PROG): Change from nm to nm.new. + (install): Remove the .new when installing. + +Wed Mar 16 16:27:05 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (powerpc_build_stubs): Set BSF_DYNAMIC flag for each + symbol for which we build a stub. + (powerpc_mangle_relocs): Only reset TOC pointer for a call to a + symbol with BSF_DYNAMIC flag set. + +Tue Mar 15 23:04:13 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * objcopy.c (filter_symbols): Use bfd_is_local_label to determine + if a symbol represents a compiler-generated local label. + (copy_object): Give the BFD backends a chance to copy any private + bfd data from the input BFD to the output BFD. + (setup_section): Give the BFD backends a chance to copy any private + section data from the input section to the output section. + +Mon Mar 14 11:15:58 1994 Jeffrey A. Law (law@snake.cs.utah.edu) + + * objcopy.c (mangle_section): Delete unused function. + (setup_section): Set osection here instead of calling + mangle section to do it. + +Mon Mar 14 12:11:01 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * ar.c (write_archive): Close inarch before unlinking it. + +Fri Mar 11 22:20:48 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (main): For PowerPC, call powerpc_build_stubs and + powerpc_resolve_stubs. Use __GOT0, not __toc_start. Handle it if + the start and end symbols are not in the text section. + (struct powerpc_stub): New struct definition. + (powerpc_stubs, powerpc_stub_insns): New static variables. + (powerpc_initial_got_size): New static variable. + (powerpc_build_stubs): New function. + (powerpc_resolve_stubs): New function. + (powerpc_mangle_relocs): Clear extraneous data in .got section. + Rearrange reloc handling to handle ELF relocs that are not + partial_inplace. Resolve PC relative relocs. + +Wed Mar 9 13:48:11 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * ar.c (move_members): Fix it so that the abi positional modifiers + don't delete all archive members following the insert point. + +Tue Mar 8 13:14:43 1994 Steve Chamberlain (sac@jonny.cygnus.com) + + * coffgrok.[ch]: New files, understand coff objects. + * coffdump.c: Uses coffgrok to dump out the debug info of a coff + file. + * sysroff.info: Description of a SYSROFF object file. + * sysinfo.y, syslex.l: Parse info file, generate a reader, writer, + header files and a printer. + * srconv.c: Uses coffgrok.c and sysroff.info to convert a coff + file to a SYSROFF file. + +Sat Feb 26 13:35:26 1994 Stan Shebs (shebs@andros.cygnus.com) + + * ar.c (do_quick_append): Pad with a genuine character 10, + rather than whatever '\n' might happen to be. + +Tue Feb 22 18:25:52 1994 Ian Lance Taylor (ian@cygnus.com) + + * nlmconv.c (main): Ignore debugging symbols when looking for + special symbols by name. + +Sun Feb 20 18:47:42 1994 Ian Lance Taylor (ian@lisa.cygnus.com) + + * nlmconv.c: Include libiberty.h. + + Support for PowerPC NetWare. + * nlmconv.c (main): For PowerPC NetWare, automatically define the + special symbols __toc_start. + (select_output_format): Handle bfd_arch_powerpc. + (mangle_relocs): Likewise. + (powerpc_mangle_relocs): New function. + +Thu Feb 17 09:28:23 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * ar.c, bucomm.c, nlmconv.c, nm.c, objcopy.c, objdump.c, + size.c: Use bfd_get_error and bfd_set_error and new error names. + +Fri Feb 11 15:54:51 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * objcopy.c (strip_main, copy_main): Add missing 'break' in switch. + +Mon Feb 7 19:45:52 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objdump.c (disassemble_data): Handle bfd_arch_powerpc. + +Sun Feb 6 22:08:20 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * strings.c objdump.c nlmconv.c objcopy.c nm.c ar.c size.c (main): + Call xmalloc_set_program_name. + +Fri Feb 4 10:46:01 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * objcopy.c (filter_bytes): Make MEMHUNK a char *, not PTR, so we + can do arithmetic on it. + +Thu Feb 3 14:06:41 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * objdump.c (dump_section_stabs, read_section_stabs, + print_section_stabs): Functions broken out of dump_stabs_1. + Free the stabs and strings when done with them. + +Wed Feb 2 13:42:23 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * nlmconv.c (main): Use bfd_get_flavour instead of struct member. + * ar.c (print_contents, extract_file), size.c + (print_berkeley_format, print_sysv_format): Use bfd_get_filename and + bfd_my_archive instead of dereferencing the structs directly. + + * ar.c: Use bfd_fatal and bfd_nonfatal instead of bfd_perror and exit. + Indent. Remove DEFUNs. + + * nlmconv.c (main), objcopy.c (copy_file): Print matching formats + if ambiguous match. + * nm.c (display_file, display_archive), size.c (display_bfd): + Eliminate gotos. + Print matching formats if there is an ambiguous match. Use + bfd_nonfatal instead of hardcoded error message if nothing matches. + + * arsup.c, ar.c, objdump.c: Use bfd_get_filename instead of + abfd->filename. + + * nm.c (display_archive): New function, from code in display_file. + (display_rel_file): Renamed from do_one_rel_file. + + * size.c: Indent. + (display_archive): New function from code in display_file. + (display_file): Check bfd_close error return. + + * strings.c (strings_object_file): Check bfd_check_format + error return. + + * strings.c, objdump.c, size.c: Use bfd_nonfatal instead of bfd_perror. + + * bucomm.c: Delete references to exit_handler. It wasn't set + anywhere, and now that we're using the libiberty xmalloc, it + wouldn't always get called before exiting. + (list_matching_formats): Function moved from objdump.c. + * bucomm.h: Declare it. + + * objdump.c (disassemble_data): Move some variable decls closer to + their use. Add some comments. Replace a nested block with a + return. + +Mon Jan 31 18:50:41 1994 Stan Shebs (shebs@andros.cygnus.com) + + * objdump.c (display_target_list, display_info_table): Check that + the bfd of the dummy output file is not null. + +Wed Jan 26 13:13:18 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * objcopy.c (filter_bytes): New function. + (copy_section): Call it. + (copy_options, copy_usage, copy_main): Add --byte option to + activate it. Appropriate the -b option (which was an undocumented + synonym for -F) for it, also. Add --interleave, -i option for + additional control. + (setup_section, copy_section, mangle_section): Renamed with no `s' + on the end. + * objcopy.1, binutils.texi: Document the new options. + + * objdump.c (display_target_tables, display_target_list): + New functions broken out of display_info. + Eliminate some magic constants. Use more meaningful variable names. + (dump_bfd_header): New function broken out of display_bfd. + (dump_section_header): New function broken out of dump_headers. + (remove_useless_symbols): Don't shadow global variable name with + parameter. + (objdump_print_address): Fix backward test. + +Tue Jan 25 19:40:54 1994 Stan Shebs (shebs@andros.cygnus.com) + + * bucomm.c (print_arelt_descr): Change decl of `when' to time_t. + * objdump.h: Removed. + +Mon Jan 24 13:29:02 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * objdump.c (display_file): Remove call to list_matching_formats. + It would never be called. + (list_matching_formats): Take an arg giving the list of matching + formats. + (display_bfd): Pass the arg, and get it filled in by calling + bfd_check_format_matches instead of bfd_check_format. + (display_info, display_info_table): target_vector was renamed to + bfd_target_vector. + + * binutils.texi (objdump): Note some limitations of -h section + address printing. + +Sat Jan 22 16:20:46 1994 Stan Shebs (shebs@andros.cygnus.com) + + * Makefile.in (MALLOC): Set to emptiness by default. + (ALL_CFLAGS): Add and use. + (arparse.h): Make it depend on arparse.y. + * ar.c (libbfd.h): Don't require to be in ../bfd. + * objdump.c (comp): Rename to compare_symbols. + +Fri Jan 21 20:22:30 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * objdump.c (list_matching_formats): If the file format is ambiguous, + print the matching names so the user can choose one. + (display_bfd): Call it. + (display_file): Call it. + +Fri Jan 21 19:17:25 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objdump.c (disassemble_data): Support bfd_arch_rs6000. + +Mon Jan 17 13:57:25 1994 Stan Shebs (shebs@andros.cygnus.com) + + * objdump.c (stab_name): Allocate dynamically. + (stab_print): Use pointers to strings instead of char arrays. + (dump_stabs): Change alloc and init of arrays appropriately. + (dump_stabs_1): Always decide whether to print stab_name or + the stab's type number, if unnamed. + +Fri Jan 14 14:42:48 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objcopy.c (strip_main, copy_main): Don't clobber the input file + if copy_file fails. + + * nlmconv.c (main): Warn about an attempt to use a shared library + with uninitialized data. + + * nlmconv.c (setup_sections): Make sure that we align the + output_offset of each input section appropriately. + +Thu Jan 13 17:32:44 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objdump.c (dump_relocs): Don't crash if section name is NULL. + +Tue Jan 11 19:46:33 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * filemode.c (filemodestring): Commented out; not used. + (mode_string): Use POSIX definitions. + (ftypelet): Likewise. + (rwx): Removed; no longer used. + * bucomm.c: Include bucomm.h. + (bfd_nonfatal, bfd_fatal): Argument is const. + (fatal): Make __STDC__ version. + * bucomm.h (mode_string): Declare. + * Makefile.in (bucomm.o): Depend upon bucomm.h + +Sun Jan 9 12:03:20 1994 Ken Raeburn (raeburn@rtl.cygnus.com) + + * bucomm.c (xmalloc, xrealloc): Deleted. + * bucomm.h (xmalloc, xrealloc): Fix prototypes, to correspond to + libiberty version of functions. + +Thu Jan 6 06:18:15 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * binutils.texi: Add a chapter summarizing the ways to select + aspects of the target for each program. + + * objdump.c (long_options, usage): Add long equivalents for all + remaining short options that lacked them. + * binutils.texi objdump.1: Document them. + + * size.c (usage): Tweak usage message. + * size.1: Add missing `=' in examples. + + * binutils.texi strip.1 objcopy.1 nlmconv.1 objcopy.c nlmconv.c: + Use "--target=bfdname" as the option to select the BFD target, + like nm and size already do. + Reserve "--format=format" for textual output selection options, but + for now keep old option names as obsolete for backward compatibility. + + * strings.c (main, strings_object_file, usage): Add --target option. + * binutils.texi strings.1: Document it. + +Sat Jan 1 13:58:24 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * ar.c (main): Add \n in error message. + +Thu Dec 23 12:23:11 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + gcc -Wall lint: + * ar.c (main): Put parens around assignment used as truth value. + * objcopy.c (strip_main): Remove unused variables. Return 0. + (copy_main): Remove unused variables. Return 0. + * objdump.c (display_bfd): Declare return value as void. + (stab_print): Use "" instead of 0 to initialize array. + (dump_stabs_1): Print vma using printf_vma. + (display_info): Put parens around assignment used as truth value. + * strings.c (print_strings): Cast printf arguments. + + * objcopy.c (copy_main): Use copy_options, not strip_options. + + * nlmheader.y (command): Warn about illegal date values. + +Wed Dec 15 11:18:03 1993 David J. MacKenzie (djm@frosty.eng.umd.edu) + + * bucomm.c bucomm.h: Run through indent. De-ansidecl-ify. + (bfd_nonfatal): New function. + (bfd_fatal): Call it. + + * objcopy.c (smart_rename): Do a copy if the dest file has + multiple hard links. Remove source file on successful copy. + Try to preserve mode and owner on successful rename. + + * objcopy.c: Run through indent. Clean up a bit. + Make global variables static. + Make {input,output}_{target,filename}, show_version local + to various functions. + New global variable `status' for exit status. + (strip_main, copy_main): New functions with code from main. + (nonfatal): New macro. Use it globally instead of bfd_perror and + bfd_fatal. + + (copy_object): Call mangle_sections with bfd_map_over_sections. + (mangle_sections): Adjust for new calling convention. + +Fri Dec 10 11:28:11 1993 Ian Lance Taylor (ian@deneb.cygnus.com) + + * nlmheader.y (command): Accept MAP and FULLMAP without arguments. + * nlmconv.c (main): Change error message for MAP and FULLMAP. + +Thu Dec 9 17:47:19 1993 Ian Lance Taylor (ian@deneb.cygnus.com) + + * nlmconv.c (main): Warn about imported symbols that are not in + the IMPORT list even if the IMPORT keyword is not used. + + * nlmconv.c (debug, unlink_on_exit): New static variables. + (long_options): Add "debug" and "linker". + (main): Handle -d and -l arguments. Make command line input and + output files optional. Parse the command file before opening the + BFD's, which requires storing more information in local variables. + If INPUT names multiple files, link them together. Use OUTPUT for + the output file name if not named on command line. + (show_usage): Changed for new options. + (link_inputs): New function to automatically invoke linker to + handle multiple INPUT files. + (choose_temp_base_try, choose_temp_base, pexecute): New functions, + mostly copied from gcc/gcc.c. + * nlmconv.h (input_files, output_file): Declare. + * nlmheader.y (input_files, output_file): Define. + (command): Support INPUT with a string_list argument. Support + OUTPUT. + (string_list): Renamed from module_list. + * Makefile.in (nlmconv.o): Define LD_NAME based on + program_transform_name. + +Wed Dec 8 10:09:04 1993 Ian Lance Taylor (ian@deneb.cygnus.com) + + * nlmheader.y (nlmheader_identify): New function. Use it to print + the program name just once, instead of with every error message. + +Mon Dec 6 16:11:32 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (long_options): Changed --header-info to --header-file + to match documentation and usage message. + +Sun Dec 5 01:31:01 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * objdump.c (dump_relocs): Avoid dereferencing a NULL sym_ptr_ptr + in a relocation. + +Thu Dec 2 16:00:06 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (main): Change various types from bfd_size_type to + size_t, since they have to be arguments to fread and fwrite. + Change set from char * to unsigned char *. + (select_output_format): Make mach argument unsigned. Handle + bfd_arch_alpha. + (setup_sections): Don't copy the .reginfo section of an ECOFF + file. Call bfd_set_reloc to initialize the relocation fields. + (copy_sections): Don't copy the .reginfo section of an ECOFF file. + Combine all relocs for a section. + (mangle_relocs): Change type of relocs to permit specific + functions to change it. Call alpha_mangle_relocs for alpha, + default_mangle_relocs for other architectures. + (default_mangle_relocs): New function. Adjust the address of all + relocs by the output_offset. + (i386_mangle_relocs): Change type of relocs argument. Cast length + argument to memmove to size_t. + (alpha_mangle_relocs): New function. + +Wed Nov 17 17:38:58 1993 Sean Eric Fagan (sef@cygnus.com) + + * nlmconv.c (select_output_format): Use nlm32-sparc for + bfd_arch_sparc. + +Wed Nov 17 14:41:35 1993 Jeffrey Osier (jeffrey@thepub.cygnus.com) + + * nlmconv.1: added man page + * objcopy.1: fixed format errors + +Wed Nov 17 12:03:41 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * Makefile.in: Use CFLAGS as well as LDFLAGS when linking. + +Wed Nov 17 04:50:55 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * strings.1: Fix typo. + +Mon Nov 15 12:03:20 1993 Ken Raeburn (raeburn@rtl.cygnus.com) + + * Makefile.in (DISTSTUFF): Build "info". + (VERSION): Updated to cygnus-2.3.1; 2.3 has gone out. + +Sun Nov 14 00:27:24 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * objdump.c (dump_stabs): Handle stabs-in-som as implemented + by the new BFD SOM assembler. + +Sat Nov 13 07:14:05 1993 David J. Mackenzie (djm@rtl.cygnus.com) + + * ar.1 c++filt.1 nm.1 objcopy.1 objdump.1 ranlib.1 size.1 + strings.1 strip.1: Replace \(em in NAME section with \- so + makewhatis can grok it. + +Tue Nov 9 15:22:12 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (i386_mangle_relocs): Adjust reloc address by + section output_offset. + +Fri Nov 5 12:11:52 1993 Jeffrey Osier (jeffrey@thepub.cygnus.com) + + * binutils.texi: added nlmconv chapter + +Wed Nov 3 16:10:50 1993 Jeffrey Wheat (cassidy@cygnus.com) + + * Makefile.in: Change RUNTESTFLAGS to RUNTEST_FLAGS + +Wed Nov 3 15:09:23 1993 Ken Raeburn (raeburn@rover.cygnus.com) + + * Makefile.in (distclean): Don't get rid of dvi or info files. + +Tue Nov 2 13:29:59 1993 David J. Mackenzie (djm@rtl.cygnus.com) + + * objcopy.c (S_ISLNK): Define as 0 if there's no S_IFLNK. + +Fri Oct 29 16:02:34 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * binutils.texi: Move objcopy docs into alphabetical order. + + * objdump.c: Use xmalloc instead of malloc. + +Fri Oct 29 11:11:14 1993 Stan Shebs (shebs@rtl.cygnus.com) + + * objdump.c (info): Rename to formats_info. + (dump_stabs_1): Better comments and formatting. + +Thu Oct 28 19:43:16 1993 Stan Shebs (shebs@rtl.cygnus.com) + + * ar.c (main): Always create the archive when quick appending, + even if no input files have been given. + +Wed Oct 27 12:03:06 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (main): Set sharedDebugRecordOffset and + sharedDebugRecordCount fields in extended header. + + * nlmconv.c (main): Force moduleName field to upper case. + +Mon Oct 25 16:45:42 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objcopy.c (main): Give a usage message if there are too many + arguments. + +Mon Oct 25 10:37:08 1993 Ken Raeburn (raeburn@rover.cygnus.com) + + * Makefile.in (install-info): Rewrite to take advantage of VPATH, + so FSF distributions (with info files in $(srcdir)) install + properly. + (DISTSTUFF): Build nlmheader.c too. + +Fri Oct 22 11:43:23 1993 Ken Raeburn (raeburn@rover.cygnus.com) + + * ar.c (program_name): Don't define here. + * objdump.c: Include "bucomm.h". + (xmalloc): Don't declare here. + (program_name): Don't define here. + (program_version): Fixed type in declaration. + * size.c: Include "bucomm.h". + (program_name): Don't declare here. + +Fri Oct 22 14:10:41 1993 Mark Eichin (eichin@cygnus.com) + + * objdump.c (fprintf): hide declaration in FPRINTF_ALREADY_DECLARED + +Fri Oct 1 12:43:00 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (i386_mangle_relocs): Resolve and remove PC relative + relocs against defined symbols in the same section. + +Thu Sep 30 16:46:26 1993 Roland H. Pesch (pesch@fowanton.cygnus.com) + + * Makefile.in (binutils.dvi): use TEXIDIR to find texinfo.tex + +Sat Sep 25 18:09:29 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * objcopy.c (simple_copy, smart_rename): New functions. + (main): Use them. + +Fri Sep 24 15:38:29 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * Makefile.in (clean, distclean): Recurse into testsuite. + +Thu Sep 23 01:05:06 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objcopy.c (setup_sections, copy_sections): If stripping, don't + copy SEC_DEBUGGING sections. + * objdump.c (dump_headers): Print SEC_DEBUGGING flag. + + * objdump.c (usage): Mention --stabs. + + * objcopy.c (copy_object): Copy all applicable file flags. + (copy_file): Don't copy EXEC_P specially here. + +Mon Sep 20 19:28:57 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (main): Adjust data section size to correspond to bss + alignment adjustment. Clear BSF_SECTION_SYM if symbol is moved to + a different section. Use time_t for time variable. + (setup_sections): Only put sections with contents in output NLM. + (i386_mangle_relocs): No symbols are common at this point. Add + casts to avoid warnings. + +Fri Sep 10 11:00:40 1993 Stan Shebs (shebs@rtl.cygnus.com) + + * objdump.c: Made the --stabs option work for stabs-in-coff. + (ELF_STAB_DISPLAY): Removed. + (dump_elf_stabs): Renamed to dump_stabs, changed to run for + any object file format. + (dump_elf_stabs_1): Renamed to dump_stabs_1, added calls to + generic BFD routines for non-ELF case, changed format of message + for no-section-found case. + (display_bfd): Always call dump_stabs if requested. + (dump_data): Call bfd_section_size to get section size. + +Fri Sep 10 08:12:23 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * Makefile.in (install): Don't put strings in tooldir/bin. + +Mon Sep 6 15:39:04 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (total_bss_size): Removed. + (main): Set the bss vma to always follow the data section. Move + symbols into new sections, and adjust values by output_offset. + (setup_sections): Don't copy all sections, but instead point all + text sections to .text, all data sections to .data, and all bss + sections to .bss. + (copy_sections): Adjust accordingly. + +Thu Sep 2 12:34:03 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + Only build nlmconv if configured for a NetWare target. + * configure.in: If we have some *-*-netware* target, or are using + all targets, set BUILD_NLMCONV to $(NLMCONV_PROG) in Makefile. + * Makefile.in (PROGS): Use $(BUILD_NLMCONV) rather than + $(NLMCONV_PROG). + +Tue Aug 31 14:13:35 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * objdump.c (ARCH_all): Define ARCH_hppa too. + (dump_headers): Don't test for SEC_BALIGN if it's not defined by + bfd.h. + +Tue Aug 31 13:29:12 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * nlmconv.c (main): Force creation of .bss section. Set up the + sections before looking at the symbols. Move all common symbols + into .bss section. Automatically define _edata and _end. Only + export symbols in the export list, with multiple prefixes if + necessary. Warn if no version. Always create extended header. + Set date automatically if not already set. + (setup_sections): Count size of bss sections. + (mangle_relocs, i386_mangle_relocs): Accept section argument, and + take reloc_count as a changeable pointer; changed callers. + (i386_mangle_relocs): Remove PC relative relocs within a section, + as they require no adjustment. + * nlmheader.y: Fixed memory allocation throughout: token STRING is + now allocated on the heap, and freed if not needed. Null + terminated copyright message. Accept version with only two + strings. + (symbol_list_opt): New nonterminal, either symbol_list or empty. + (symbol_list): Use left recursion to avoid overflowing parser + stack. + (yylex): Rearranged beginning of line check. Accept quoted + strings using single quotes. End generic argument at comment + character or parentheses. + (string_list_append): Fixed. + (string_list_append1): New function. + + * bucomm.h: The first argument to xrealloc is PTR, not char *. + * bucomm.c (xrealloc): Use PTR rather than char *. + * Makefile.in (objdump.o): Depend upon config.status to notice + --with-targets changes. + (nlmconv.o): Depend upon bucomm.h. + +Tue Aug 17 09:46:01 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * configure.in: Don't pass cpu to config.bfd. + +Thu Aug 12 16:43:04 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * Makefile.in ($(NM_PROG)): Depend on demangle.o. + (demangle.o): New target. + (cplus-dem.o): Depend on it, to force compilation order when doing + parallel compiles. + + * nm.c (print_symbol_info_{bsd,sysv,posix}): Take a bfd arg. + (struct output_fns print_symbol_info): Ditto. + (long_options, usage, main): Add -C --demangle option. + (print_symname): New function, demangling if requested. + (print_symbols, print_symbol_info_{bsd,sysv,posix}): Use it. + +Wed Aug 11 22:57:23 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * Makefile.in: Put CFLAGS last in compilation rules and omit from + linking rules. Use ARCHDEFS to compile objdump.c. + Update dependencies. + * configure.in: Construct ARCHDEFS based on the BFD target makefile + fragments. + * objdump.c: Conditionalize calls to the print_insn_ARCH functions + according to ARCHDEFS. + +Thu Aug 12 08:06:15 1993 Ian Lance Taylor (ian@cygnus.com) + + * ar.c: Removed obsolete and non-functional GNU960 code. + +Wed Aug 11 13:08:26 1993 Ian Lance Taylor (ian@cygnus.com) + + * size.c (berkeley_sum): New function. + (bsssize, datasize, textsize): New global variables. + (bss_section_name, data_section_name, text_section_name): Removed. + (print_berkeley_format): Map berkeley_sum over all the sections, + rather than only reporting sizes of specifically named sections. + * Makefile.in ($(OBJDUMP_PROG)): Removed dependency on size.o. + +Tue Aug 10 10:46:01 1993 Ian Lance Taylor (ian@cygnus.com) + + * nlmconv.c, nlmconv.h, nlmheader.y: New files for program to + convert object files into NetWare Loadable Modules. + * Makefile.in (NLMCONV_PROG): New macro, define to be nlmconv. + (PROGS): Add NLMCONV_PROG. + (nlmheader.c, nlmheader.o, nlmconv.o, $(NLMCONV_PROG)): New + targets. + +Thu Aug 5 15:48:32 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com) + + * Makefile.in: define MAKEOVERRIDES to an empty string + +Wed Aug 4 17:08:08 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * objcopy.c (copy_file): Make failures to process a file nonfatal. + +Mon Aug 2 11:28:23 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * nm.c: Add -B option, like --format=bsd. + +Tue Jul 27 16:29:54 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objcopy.c (copy_file): If the file is neither an object nor an + archive, give an error rather than returning success. + +Mon Jul 19 16:13:40 1993 Ken Raeburn (raeburn@rtl.cygnus.com) + + * objdump.c (objdump_print_address): Prefer non-local symbols over + local ones, and especially discriminate against debugging symbols. + Also, for relocateable files, try to find a symbol in the current + section, instead of picking one from some random section with a + convenient value (read, section offset). + (disassemble_data): Cast argument to malloc to size_t first. + (dump_data): Likewise. + (dump_relocs): If a single section name is specified, show relocs + only for that section. Otherwise, silently omit sections without + relocs. Format table nicely even if values are printed using 16 + digits instead of 8. + +Fri Jul 16 15:19:59 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * nm.c: Changes for final version of POSIX.2. + (print_symbol_filename_{bsd,sysv,posix}): New functions. + (formats): Add an element for a pointer to them. + (print_symbols): Call it. + (print_object_filename_posix, print_archive_member_posix): Produce + output according to new POSIX.2 spec. + + * strings.c (print_strings): Handle STREAM being NULL. + (strings_a_section): Pass a NULL. + (main): Don't open /dev/null. + +Thu Jul 15 12:44:09 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objdump.c (disassemble_data): Handle the m88k. + (display_bfd): Use bfd_errmsg, rather than just claiming that the + bfd is not an object file. + +Mon Jul 12 17:55:34 1993 K. Richard Pixley (rich@cygnus.com) + + * Makefile.in (TAGS): make work again by naming directories + explicitly rather than depending on undefined macros. + (INSTALL_XFORM): correct bad install target. + +Fri Jul 2 16:58:34 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * strings.c: Doc fixes. + +Sun Jun 27 13:35:24 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * Makefile.in: Note dependencies on bucomm.h. + (cplus-dem.o): Link c++filt with version.o. + + * strings.c: Include bucomm.h and add prototypes to other decls. + Remove -h option. + + * bucomm.h: Declare xrealloc. + + * nm.c, objcopy.c, objdump.c, size.c, strings.c (main, usage): Add + --help option. Put "GNU" in the version message. + (usage): Take stream and exit status as args. + (main): Pass new args to usage. + +Fri Jun 25 23:12:12 1993 David J. Mackenzie (djm@thepub.cygnus.com) + + * strings.c, strings.1: New files. + * binutils.texi: Document strings. + * Makefile.in: Add rules for it. + +Fri Jun 25 20:44:43 1993 Ken Raeburn (raeburn@poseidon.cygnus.com) + + * objdump.c: Use size-independent bfd elf section names. + +Sun Jun 20 23:09:06 1993 Ken Raeburn (raeburn@poseidon.cygnus.com) + + * objdump.c (objdump_print_address): Handle wide offsets by + calling sprintf_vma. + +Fri Jun 18 14:29:12 1993 Per Bothner (bothner@deneb.cygnus.com) + + * objdump.c (syms2): Removed unused variable. + * objdump.c (remove_useless_symbols): New function. + * objdump.c (comp): Simplify. + * objdump.c (dis-assemble_data): Make simpler and more + efficient how we filter out useless symbols: Just filter + BEFORE the sort (using remove_useless_symbols). + * objdump.c (objdump_print_address): Simplify. + Change output syntax to match gdb. + +Thu Jun 17 16:53:56 1993 david d `zoo' zuhn (zoo@cygnus.com) + + * Makefile.in: canonicalize install.sh; for use within + this directory (and subdirs) + +Mon Jun 14 12:13:22 1993 david d `zoo' zuhn (zoo at rtl.cygnus.com) + + * Makefile.in (install, install-info): remove parentdir support, + use INSTALL_XFORM; define INSTALL_XFORM + +Thu Jun 10 17:29:21 1993 Per Bothner (bothner@cygnus.com) + + * objcopy.c (copy_object): Fix bad size passed to xmalloc(). + +Mon Jun 7 12:41:12 1993 Per Bothner (bothner@rtl.cygnus.com) + + * Makefile.in (INCLUDES): Add -I../bfd for sysdep.h and bfd.h. + * configure.in: No longer need to configure to get sysdep.h. + * objcopy.c (copy_object): Fix symbol table handling. + +Fri Jun 4 17:20:03 1993 Per Bothner (bothner@cygnus.com) + + * objcopy.c (filter_symbols): Cannot filter the symbols + in place, because that confuses the relocs, so take separate + parameter for output array. + * objcopy.c (sympp): Make two variables: isympp and osympp. + * objcopy.c (copy_object): Allocate separate array (osympp) + for filtered symbols. + +Fri Jun 4 10:51:44 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * Makefile.in: change recursion test to presence of a configured + testsuite directory + +Thu Jun 3 14:05:57 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * Makefile.in (underscore.c): Hack the backquoted command so it + doesn't cause Solaris make to bomb. + +Thu Jun 3 10:40:19 1993 Jeffrey Osier (jeffrey@cygnus.com) + + * Makefile.in: added c++filt and objcopy to MANPAGES variable + +Thu Jun 3 00:32:52 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * Makefile.in: rename LOADLIBES to EXTRALIBS + +Wed Jun 2 18:30:24 1993 Jeffrey Osier (jeffrey@cygnus.com) + + * c++filt.1, objcopy.1: new man pages + +Fri May 28 15:01:24 1993 Per Bothner (bothner@rtl.cygnus.com) + + * Makefile.in (install): Also install ar and ranlib in + $(tooldir)/bin; needed for building libgcc.a. + * objdump.c (objdump_print_address): Fix the check + "coincidental" label matches by dis-allowing undefined + or com symbols. + +Thu May 27 16:58:31 1993 Jeffrey Osier (jeffrey@cygnus.com) + + * biutils.texi: revised c++filt chapter + +Wed May 26 17:24:17 1993 Ian Lance Taylor (ian@cygnus.com) + + * Makefile.in (FLAGS_TO_PASS): Pass down CC and CFLAGS. + +Tue May 25 00:26:47 1993 Ken Raeburn (raeburn@cygnus.com) + + * objdump.c (slurp_symtab): Print warning for bad symbol table. + (bfd_elf32_find_section, Elf32_Internal_Shdr): Updated + declarations and uses. + + * Makefile.in (DISTSTUFF): Don't build binutils.mm. + +Fri May 21 10:51:19 1993 David J. Mackenzie (djm@rtl.cygnus.com) + + * nm.c: Add -f/--format, -P/--portability, -t/--radix options. + Make global variables static. + (main): Make -v like -n, not -V, and make -A like -o, for POSIX.2. + (set_print_radix, set_output_format, + print_{object_filename,archive_filename,archive_member,symbol_info} + {bsd,sysv,posix}): New functions. + (display_file, print_symbols): Call them. + + * ar.c: Improve error messages. + + * nm.c (main): Handle long options that just set a flag. + + * nm.c (main), ar.c (do_show_version), objcopy.c (main), size.c + (main): Exit after printing the version number, per the GNU coding + standards. + +Mon May 17 13:20:25 1993 Per Bothner (bothner@cygnus.com) + + * README, Makefile.in: Minor updates for 2.2. + +Fri May 14 11:12:26 1993 Per Bothner (bothner@cygnus.com) + + * Makefile.in (underscore.c): Automatically generate + (using nm) a file with the variable prepends_underscore. + * Makefile.in (c++filt): Link underscore.o with cplus-dem.o + so that initial underscores get removed iff appropriate. + * binutils.texi: Preliminary documentation for c++filt. + * Makefile.in, binutils.texi: Set to version 2.2. + + * NEWS: Mention copy->objcopy renaming and new c++filt program. + +Wed May 12 12:05:36 1993 Ian Lance Taylor (ian@cygnus.com) + + * Makefile.in (cplus-dem.o, $(DEMANGLER_PROG)): Build the + demangler via cplus-dem.o, rather than directly from the .c file. + + * objcopy.c: Renamed from copy.c, updated comments accordingly. + * Makefile.in, binutils.texi: Renamed copy to objcopy. + * is-strip.c, maybe-strip.c, not-strip.c: Updated comments for + rename of copy to objcopy. + +Mon May 10 17:20:18 1993 Per Bothner (bothner@cygnus.com) + + * binutils.texi (strip, -v option): Fix typo. + +Fri May 7 13:57:50 1993 Ian Lance Taylor (ian@cygnus.com) + + * Makefile.in (RUNTEST): Define. + (FLAGS_TO_PASS): Pass down RUNTEST. + +Tue May 4 10:06:50 1993 Ian Lance Taylor (ian@cygnus.com) + + * Makefile.in (DEMANGLER_PROG): Name it c++filt. + (PROG): Also build and install COPY_PROG. + +Mon May 3 19:11:48 1993 Per Bothner (bothner@cygnus.com) + + * Makefile.in: Change definition of $(tooldir) to match FSF. + +Wed Apr 28 23:41:32 1993 David J. Mackenzie (djm@rtl.cygnus.com) + + * size.c (usage): Add missing options. + (main): Clean up option parser. + + * objdump.c (usage): Add missing options. + (display_file): Print program name before calling + bdf_perror. + + * nm.c (usage): Add missing options. + (main): Clean up option parser. + (display_file): Print program name before calling + bdf_perror. + + * copy.c (copy_usage, strip_usage): Add missing options. + + * ar.c (usage): New function. + (main): Call it. + (open_inarch, do_quick_append): Print program name before calling + bdf_perror. + +Thu Apr 22 15:01:35 1993 Ian Lance Taylor (ian@cygnus.com) + + * nm.c (main): Accept and ignore -A and -B for MIPS compatibility. + +Mon Apr 19 14:06:59 1993 Rob Savoye (rob@cygnus.com) + + * Makefile.in: Added FLAGS_TO_PASS so tests get run on freshly + built binaries if they exist. (otherwise the path) + +Wed Apr 7 22:22:50 1993 Rob Savoye (rob@cygnus.com) + + * Makefile.in: Changed check target to use DejaGnu. + +Thu Apr 1 12:37:13 1993 Jim Kingdon (kingdon@cygnus.com) + + * Makefile.in: Remove am29k-pinsn.c, i960-pinsn.c. + objdump.c: a29k and i960 are `disassemble' not `print'. + + * objdump.c: Rename print_address to objdump_print_address + and change parameters. + (disassemble_data): Use objdump_print_address. + +Wed Mar 31 10:25:29 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + + * objdump.c (disassemble_data): print_insn_sparc is now a + `disassemble' not a `print'. + Makefile.in: Remove sparc-pinsn.c (now in libopcodes.a). + + * objdump.c (disassemble_data): Use new read_memory_func stuff. + +Thu Mar 25 10:38:11 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * objdump.c (fprintf): Declaration of variadic function had better + be a prototype for ANSI C systems. + +Mon Mar 22 23:19:46 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * Makefile.in: rename test-install to install-check + +Fri Mar 19 14:40:08 1993 Steve Chamberlain (sac@thepub.cygnus.com) + + * objdump.c (disassemble_data): Add H8500. + +Fri Mar 19 10:56:51 1993 Jim Kingdon (kingdon@cygnus.com) + + * objdump.c (usage): Mention long options. + +Thu Mar 18 14:22:17 1993 Per Bothner (bothner@rtl.cygnus.com) + + * nm.c: Modify behavior of -o flag for archives to match + BSD4.4 and Sunos 4: Prefix archive name before each line. + + * m68k-pinsn.c: Removed. Subsumed by ../opcodes/m68k-dis.c. + * i386-pinsn.c: Removed. Subsumed by ../opcodes/i386-dis.c. + * Makefile.in: Adjust accordingly. + * objdump.c: Support new-style disassemblers (ones that use + the interface of ../include/dis-asm.h). + +Thu Feb 25 15:57:00 1993 Per Bothner (bothner@rtl.cygnus.com) + + * Makefile.in: When making tar file, remove texinfo/*, + except for texinfo/texinfo.tex. + * ardup.c: Add extern declaration of strdup. + * Makefile.in (testsuite): Add 'else true' since otherwise + Ultrix /bin/sh complains. + +Wed Feb 24 19:44:18 1993 Per Bothner (bothner@rtl.cygnus.com) + + * Makefile.in: Set VERSION to 2.1. + * README, NEWS: Updates. + * nm.c: Add -v as a synonym for -V. + +Tue Feb 23 19:00:50 1993 Mike Werner (mtw@poseidon.cygnus.com) + + * configure.in: added testsuite to configdirs. + * Makefile.in: added support for building testsuite. + +Mon Feb 22 22:52:10 1993 Per Bothner (bothner@rtl.cygnus.com) + + * objdump.c (disassemble_data): Print function names when + given by bfd_find_nearest_line. If not - still print + line numbers. + +Mon Feb 22 07:54:03 1993 Mike Werner (mtw@poseidon.cygnus.com) + + * binutils/testsuite: made modifications to testcases, etc., to allow + them to work properly given the reorganization of deja-gnu and the + relocation of the testcases from deja-gnu to a "tool" subdirectory. + +Mon Feb 22 10:27:24 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + + * objdump.c (dump_data): Free up section contents each time + through the loop. Reported by minyard@bnr.ca. + +Sun Feb 21 10:55:55 1993 Mike Werner (mtw@poseidon.cygnus.com) + + * binutils/testsuite: Initial creation of binutils/testsuite. + Migrated dejagnu testcases and support files for testing nm to + binutils/testsuite from deja-gnu. These files were moved "as is" + with no modifications. This migration is part of a major overhaul + of dejagnu. The modifications to these testcases, etc., which + will allow them to work with the new version of dejagnu will be + made in a future update. + +Fri Feb 12 10:05:20 1993 Fred Fish (fnf@cygnus.com) + + * Makefile.in (LIBIBERTY_SRC_DIR, LIBIBERTY_BIN_DIR): New macros. + * Makefile.in (LIBIBERTY): Use LIBIBERTY_BIN_DIR. + * Makefile.in (DEMANGLER_PROG): New program to build. Add macro + and rule. + * Makefile.in (PROGS): Add DEMANGLER_PROG. + +Tue Jan 26 11:56:33 1993 Ian Lance Taylor (ian@cygnus.com) + + * copy.c, nm.c, objdump.c, size.c: Use new bfd_is_com_section + macro rather than checking for equality to bfd_com_section. + +Fri Jan 8 15:50:05 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objdump.c (disassemble_data): Fix code to find first useless + symbol. + +Thu Jan 7 13:13:31 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * objdump.c (disassemble_data): Use mips_print_insn for MIPS. + Don't core dump if bfd_find_nearest_line returns false. + +Wed Jan 6 17:14:01 1993 Steve Chamberlain (sac@thepub.cygnus.com) + + * objdump.c (disassemble_data): know how to disassemble z8000s + too. + +Wed Jan 6 15:16:27 1993 Per Bothner (bothner@cygnus.com) + + * arsup.h (interactive), bucomm.h (program_name): Prefix + with 'extern', to avoid warnings from some compilers. + +Wed Jan 6 15:14:11 1993 Per Bothner (bothner@rtl.cygnus.com) + + * arparse.y: fix unnecessary shift/reduce + +Tue Dec 22 15:46:56 1992 Per Bothner (bothner@rtl.cygnus.com) + + * Makefile.in: Make check depend on all. + * Makefile.in (distclean): Remove sysdep.h. + * size.c: Use %u format where appropriate. + * objdump.c: Standardize: L_SET -> SEEK_SET. + * objdump.c: Use new macro bfd_asymbol_bfd. + * configure.in: Allow std-host as the default ${mys_host}. + +Thu Dec 17 19:38:19 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * Makefile.in: added dvi target, define and use TEXI2DVI + +Tue Dec 15 18:05:07 1992 Per Bothner (bothner@cygnus.com) + + * Makefile.in (dist): Fix permissions before release. + * size.c: Use bfd_size_type (and long) where appropriate. + * ar.c: Make writing a map the default, to be compatible + with SYSV and Posix.2. Remove some bogus kludges that + handled __.SYMDEF directly. + * NEWS: New file. + +Mon Nov 9 13:36:53 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * Makefile.in: flex no longer needs the -S flag + +Sat Nov 7 15:06:13 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * ar.c (extract_file): utime needs a pointer to a utimbuf + + * Makefile.in: handle -I includes better, adding $(BASEDIR)/bfd to + the list (since some of the bfd/hosts/*.h files include other + files from that directory) + +Fri Nov 6 00:12:51 1992 John Gilmore (gnu@cygnus.com) + + * i960-pinsn.c (MEM_MAX, MEM_SIZ): Set upper bound properly. + +Thu Nov 5 03:37:15 1992 John Gilmore (gnu@cygnus.com) + + Clean up some old BFD ansification macros. + + * arsup.h, bucomm.h, objdump.h: Remove EXFUN from binutils. + It still remains as a local macro in gmalloc.c, which is derived + from some other copy of GNU Malloc somewhere (FIXME). + + * ar.c, objdump.c, size.c: Replace EXFUN with PROTO. Make static + fns really static. + * arsup.h: Declare extract_files. + +Mon Nov 2 12:42:11 1992 Ian Lance Taylor (ian@cygnus.com) + + * ar.c (extract_file): instead of checking USG: if POSIX_UTIME, + use utime and utimbuf structure, otherwise if USE_UTIME use utime + and array of two longs, otherwise use utimes. + +Thu Oct 15 13:57:35 1992 Per Bothner (bothner@cygnus.com) + + * binutils.tex: Document yesterday's changes to strip and copy. + +Wed Oct 14 13:22:14 1992 Per Bothner (bothner@cygnus.com) + + * copy.c: Re-do command-line parsing to use getopt_long(). + Add long option names. Re-think option letters to be more + consistent. + * copy.c: New function filter_symbols() for stripping only + debug-symbols and/or local symbols. Use these to support + the previously-missing options of the old FSF strip. + +Tue Oct 13 01:24:20 1992 John Gilmore (gnu@cygnus.com) + + * configure.in (host): Use ${srcdir}/../bfd/configure.host rather + than repeating a copy of it here. + +Wed Oct 7 12:53:52 1992 Ken Raeburn (raeburn@cygnus.com) + + * copy.c (main): Even if is_strip, accept -d argument indicating + alternate output format. Needed by gdb for Nindy. + + * m68k-pinsn.c (print_insn_arg): Handle new "`" operand type. + +Tue Oct 6 16:33:56 1992 Jeffrey Osier (jeffrey@cygnus.com) + + * binutils.texi: added documentation for "copy" + +Tue Oct 6 14:22:56 1992 Per Bothner (bothner at PersSony) + + * Makefile.in (*clean rules): Some cleaning up. + * Makefile.in (dist): Make diststuff in gprof for a dist. + + * ar.c (do_show_version): New function. + * ar.c (main): Fix so "ar -V" works. + +Thu Oct 1 22:44:45 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * configure.in: now uses the cpu-vendor-os triple instead of + nested cases. + +Fri Sep 25 22:41:08 1992 John Gilmore (gnu@cygnus.com) + + * i960-pinsn.c: Change bzero to memset. + * sparc-pinsn.c: Change index to strchr. + +Mon Sep 21 14:39:56 1992 Ian Lance Taylor (ian@cygnus.com) + + * m68k-pinsn (print_insn_arg, fetch_arg): added support for + operands to memory management instructions, from WRS. + +Tue Sep 15 15:26:38 1992 Ian Lance Taylor (ian@cygnus.com) + + * Makefile.in (install): if $(tooldir) exists, install nm and + strip in $(tooldir)/bin. + +Thu Sep 3 11:57:40 1992 Per Bothner (bothner@rtl.cygnus.com) + + * Makefile.in: Let's call it version 2.0. + +Wed Sep 2 00:25:13 1992 Per Bothner (bothner@rtl.cygnus.com) + + * Makefile.in: Bump to version 0.98. + * TODO, README: Minor updates. + + * Makefile.in: Added mostlyclean, distclean rules, + and cleaned up clean, realclean. + +Sun Aug 30 21:18:59 1992 Ian Lance Taylor (ian@cygnus.com) + + * Makefile.in: map program names through program_transform_name + when installing. + +Sun Aug 30 18:09:03 1992 Per Bothner (bothner@rtl.cygnus.com) + + * Makefile.in: Bump to versions 1.97.90. + * cplus-dem.c: Removed. Was nowhere used - and if some + programs are changed to to demangling should now use the + versions in libiberty. + +Thu Aug 27 12:58:09 1992 Brendan Kehoe (brendan@cygnus.com) + + * configure.in: add we32k + +Mon Aug 24 14:53:42 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * ar.c (map_over_members): if the element of the archive has a + null name, fill it in. + + * nm.c (do_one_rel_file): only warn if a bfd's flags say there + will be symbols and there aren't any. + +Wed Aug 19 11:20:25 1992 Ian Lance Taylor (ian@cygnus.com) + + * m68k-pinsn.c: handle new operand type 'r', introduced for cas2. + +Tue Aug 18 20:45:48 1992 Rob Savoye (rob@cygnus.com) + + * nm.c objdump.c: Added support for a +version (-V) + to print the version number. + + * ar.c, copy.c: Added support for a -V option to print + the version number. + +Tue Aug 18 13:28:44 1992 Ian Lance Taylor (ian@cygnus.com) + + * config/mh-apollo68v: removed -g from CC definition. + + * Makefile.in: always create installation directories. + +Mon Aug 17 18:33:41 1992 Per Bothner (bothner@rtl.cygnus.com) + + * m68k-pinsn.c: Minor fix in style of output (don't use + range to indicate floating point control registers). + +Tue Aug 11 23:42:21 1992 Per Bothner (bothner@cygnus.com) + + * ar.c (main): Don't *always* set the verbose flag! + +Wed Aug 5 11:25:27 1992 Per Bothner (bothner@rtl.cygnus.com) + + * copy.c: When is_strip (because it is invoked as the strip + program), follow traditional argv processing: + 'strip file1 file2' now strips file1 and file2, rather + than stripping file1 (as input), leaving output in file2. + +Mon Jul 27 16:28:08 1992 Per Bothner (bothner@rtl.cygnus.com) + + * objdump.c (display_info, display_info_table): Call + bfd_set_format() on dummy bfd before using it (twice). + * ar.c: Make sure archive is created on command 'r' + even when no elements are inserted. (Clean up and + simplify some non-working related code.) + +Mon Jul 20 02:48:38 1992 D. V. Henkel-Wallace (gumby@cygnus.com) + + * configure.in: hppa support doesn't assume hp OS (from sef). + +Sat Jul 18 14:35:22 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * configure.in: recognize hppa hosts (bsd & hpux), error messages + to stderr, not stdout + +Fri Jul 17 18:39:44 1992 K. Richard Pixley (rich@rtl.cygnus.com) + + * ar.1, binutils.texi, i960-pinsn.c, nm.1, objdump.1, ranlib.1, + size.1, sparc-pinsn.c, strip.1: removed rcsid's. + +Thu Jul 16 16:55:24 1992 K. Richard Pixley (rich@rtl.cygnus.com) + + * Makefile.dos: removed rcsid. + +Thu Jul 16 08:23:07 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * objdump.c (display_bfd): print state of BFD_IS_RELAXABLE too + +Tue Jun 30 20:26:15 1992 D. V. Henkel-Wallace (gumby@cygnus.com) + + * Makefile.in: Add program_suffix (parallel to program_prefix) + +Thu Jun 25 04:52:45 1992 John Gilmore (gnu at cygnus.com) + + * nm.c (sorters): Lint. Remove excess whitespace. + +Wed Jun 24 13:48:07 1992 Per Bothner (bothner@cygnus.com) + + * nm.c (valueof macro): Add missing parentheses. + (Their lack screwed up numeric_forward().) + +Sun Jun 14 10:33:27 1992 John Gilmore (gnu at cygnus.com) + + * objdump.c (dump_elf_stabs): Also dump .stab.index and + .stab.excl sections. + (dump_elf_stabs_1): Split out main body of old dump_elf_stabs. + * objdump.1, binutils.texi: Document new sections dumped. + +Fri Jun 12 22:23:35 1992 John Gilmore (gnu at cygnus.com) + + * size.c, objdump.c, bucomm.c: Lint. + +Thu Jun 11 01:19:06 1992 John Gilmore (gnu at cygnus.com) + + * objdump.c (dump_elf_stabs): New feature: --stabs prints out a + .stab section from an ELF file. Installed under #ifdef + ELF_STAB_DISPLAY so it can be easily disabled, since it requires + bfd-internals header files and such. + * objdump.1, binutils.texi: Update for --stabs. Also fix + objdump's doc to use -- rather than + for long options. + (FIXME: Not yet fixed everywhere in binutils.texinfo.) + +Wed Jun 10 07:53:24 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * objdump.c(display_info), patches from + mohring@informatik.tu-muenchen.de to print the table much more + nicely. + +Thu May 28 13:36:16 1992 Per Bothner (bothner@rtl.cygnus.com) + + * objdump.c: Add another enum->int cast, for the sake of + old compilers (such as PCC). + +Wed May 27 13:01:44 1992 Per Bothner (bothner@rtl.cygnus.com) + + * arlex.l: Don't include <sysdep.h> (unneeded conflicts). + Add declaration of strdup(). + +Fri May 22 13:40:37 1992 Per Bothner (bothner@cygnus.com) + + * Makefile.in: Use srcdir instead of VPATH in ldgram/ldlex + rules, since these are used when building a distribution. + * Makefile.in (arlex.c): Don't re-direct output, since that + leaves a bogus output files if it fails. + + * arlex.l: Make work with lex, for what it's worth. + * Makefile.in: Better lex support. + * Makefile.in (dist): Generate flex and bison outputs + for distribution. + +Thu May 14 17:17:59 1992 K. Richard Pixley (rich@rtl.cygnus.com) + + * Makefile.in: get BISON definition right. + +Fri May 8 07:47:08 1992 K. Richard Pixley (rich@cygnus.com) + + * sanity.sh: default TMPDIR to ".". + +Thu May 7 12:34:50 1992 Roland H. Pesch (pesch@fowanton.cygnus.com) + + * binutils.texi: add doc for ar command language. + +Wed May 6 18:05:36 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * arparse.y: make END call ar_end + * arsup.c (ar_end): added, deletes temp file if archive session + aborted. + + +Wed May 6 11:08:53 1992 K. Richard Pixley (rich@rtl.cygnus.com) + + * Makefile.in: use bison & flex from ../ if they exist. Also, + FLEX->LEX. + + * sanity.sh: remove temporary directory when finished. + +Tue May 5 12:00:58 1992 Per Bothner (bothner@rtl.cygnus.com) + + * Makefile.in: Bump to version 1.97. + * ar.c: Declare errno for machines that need it. + +Mon May 4 23:29:51 1992 John Gilmore (gnu@cygnus.com) + + * objdump.c (display_info): Handle error cases without coredump. + Close the dummy temporary file we open in the loop. + * Makefile.in (arsup.o): Add kludge to build with Sun Make. + +Fri May 1 16:20:23 1992 K. Richard Pixley (rich@cygnus.com) + + * Makefile.in: added test-install target. + + * sanity.sh: new file. + + * Makefile.in: use sanity test on make check. + +Tue Apr 21 13:38:37 1992 K. Richard Pixley (rich@cygnus.com) + + * Makefile.in: rework CFLAGS so that they can be passed on the + command line to make. Remove MINUS_G. Default CFLAGS to -g. + +Wed Apr 15 14:33:07 1992 Steve Chamberlain (sac@thepub.cygnus.com) + + * arsup.c, arsup.h, arparse.y, arlex.l: support for archive + scripting language. + +Fri Mar 6 21:54:53 1992 K. Richard Pixley (rich@cygnus.com) + + * Makefile.in: added check target. + +Thu Mar 5 21:35:49 1992 K. Richard Pixley (rich@cygnus.com) + + * Makefile.in: added clean-info target. + +Tue Mar 3 15:36:37 1992 K. Richard Pixley (rich@rtl.cygnus.com) + + * Makefile.in: remove $(COPY_PROG) from PROGS. It shouldn't be + installed. added tooldir and program_prefix. + +Wed Feb 26 18:04:40 1992 K. Richard Pixley (rich@cygnus.com) + + * Makefile.in, configure.in: removed traces of namesubdir, + -subdirs, $(subdir), $(unsubdir), some rcs triggers. Forced + copyrights to '92, changed some from Cygnus to FSF. + +Sun Feb 16 12:53:02 1992 Per Bothner (bothner at cygnus.com) + + * Makefile.in: Bump version to 1.96, and remove -beta + suffix from distribution name. + * m68k-pinsn.c: New macro COERCE_SIGNED_CHAR to extract + the signed value of a character (even if chars are unsigned). + * sparc-pinsn.c: Add new operand types. + +Thu Feb 6 12:14:19 1992 Steve Chamberlain (sac at rtl.cygnus.com) + + * objdump.c (disassemble_data): don't print a section's contents + if it's not loadable (eg bss) + +Tue Jan 28 11:11:06 1992 Steve Chamberlain (sac at rtl.cygnus.com) + + * m68k-pinsn.c (print_insn_arg): fixed so that -ve branch + displacements don't get printed as large +ve ones. + +Fri Jan 24 14:47:53 1992 Steve Chamberlain (sac at rtl.cygnus.com) + + * copy.c, nm.c, objdump.c, size.c : changed to use the + new reloc scheme. + + +Mon Dec 30 18:34:41 1991 Per Bothner (bothner at cygnus.com) + + * bucomm.c (print_arelt_descr): Tweek the output format + so that 'ar tv' output follows Posix 1003.2/D11. + Output is now also identical to Sun's (except __.SYMDEF). + +Mon Dec 30 06:09:53 1991 John Gilmore (gnu at cygnus.com) + + * Makefile.in: Make `make' output more readable. + +Wed Dec 18 15:04:45 1991 Per Bothner (bothner at cygnus.com) + + * Makefile.in: Bump to version 1.94. + +Wed Dec 11 16:48:09 1991 Steve Chamberlain (sac at cygnus.com) + + * ar.c: added "b" to fopens for dos + * configdj.bat, makefile.dos new files from DJ + +Tue Dec 10 04:07:26 1991 K. Richard Pixley (rich at rtl.cygnus.com) + + * Makefile.in: infodir belongs in datadir. + +Sat Dec 7 17:09:37 1991 Steve Chamberlain (sac at rtl.cygnus.com) + + * bucomm.h: created to hold prototypes of bucomm.c + * objdump.h: created to hold prototyes of objdump.c + * am29k-pinsn.c: include objdump.h + * ar.c: include bucomm.h, get ar.h from the right place and + include libbfd.h + * bucomm.c: defunize bfd_fatal + * copy.c: include bucomm.h, lint. + * i960-pinsn.h: include bucomm.h + * m68k-pinsn.h: lint + * nm.c: include bucomm.h, lint + * objdump.c: lint + * sparc-pinsn.c: include objdump.h + + + +Fri Dec 6 23:02:14 1991 K. Richard Pixley (rich at rtl.cygnus.com) + + * Makefile.in: added standards.text support. install using + INSTALL_PROGRAM and INSTALL_DATA. + + * configure.in: configure now does all of it's work from objdir so + make file existence tests against ${srcdir}. + +Thu Dec 5 22:46:22 1991 K. Richard Pixley (rich at rtl.cygnus.com) + + * Makefile.in: idestdir and ddestdir go away. Added copyrights + and shift gpl to v2. Added ChangeLog if it didn't exist. docdir + and mandir now keyed off datadir by default. + +Wed Dec 4 22:42:03 1991 Per Bothner (bothner at cygnus.com) + + * Makefile.in: Bump to version 1.93. + * Makefile.in: Add make-strip.o:maybe-strip.c dependency + for make versions that provide half-baked VPATH-support (e.g. Sun's). + * size.c: Improvements suggested by + "david d [zoo] zuhn" <zoo@aps1.spa.umn.edu>: + - Don't emit (Berkeley) headers if no files were found. + - Return a non-zero return code on failure. + +Sat Nov 30 21:34:19 1991 Steve Chamberlain (sac at rtl.cygnus.com) + + Changes due to include file renaming: + * am29k-pinsn.c: a29k-opcode.h -> opcode/a29k.h + * sparc-pinsn.c: sparc-opcode.h -> opcode/sparc.h + * m68k-pinsn.c: m68k-opcode.h -> opcode/m68k.h + * nm.c: stab.gnu.h -> aout/stab_gnu.h + +Tue Nov 19 19:20:43 1991 Per Bothner (bothner at cygnus.com) + + * README: Mention MINIMIZE flag for bfd's make. + +Mon Nov 18 12:05:37 1991 Per Bothner (bothner at cygnus.com) + + * README: Various improvements. + +Sun Nov 17 23:40:59 1991 Per Bothner (bothner at cygnus.com) + + * Makefile.in: Bump to version 1.92. + * version.c, Makefile.in: Get version string from Makefile. + * copy.c, is-strip.c, not-strip.c, maybe-strip.c, Makefile.in: + Make the same change that we earlier did for ar/ranlib: + Generate two different binaries for strip and copy and use + a global variable with different values to distinguish + ostrip from copy. (-1 means to use argv[0] to decide, + so you can get the old behavior, but it is no longer the default). + * copy.c (copy_file): Set EXEC_P of output bfd if input is so. + * copy.c (main): If is_strip==-1, compare last 5 chars + of argv[0], not the whole path. + * copy.c (main): Return 0, not 1. + * copy.c (setup_sections): Fix due to change in bfd_make_section + now failing if asked for a duplicate section. + * strip.c, ostrip.c: Removed obsolete files. + * ar.c, not-ranlib.c, maybe-ranlib.c: + Change encoding of is_ranlib variable to be consistent + with is_strip for strip.copy (i.e -1 to means use argv[0]). + +Thu Nov 14 20:11:02 1991 Per Bothner (bothner at cygnus.com) + + * version.c (program_version): Update to version 1.92. + +Tue Nov 12 16:17:53 1991 Per Bothner (bothner at cygnus.com) + + * ar.c (get_pos_bfd): Previous fix was missing a "break". + +Thu Nov 7 08:55:56 1991 Steve Chamberlain (sac at cygnus.com) + + * am29k-pinsn.c: Fixed bug in mtacc, dmac and fmac instruction + encodings. (Thaks to David Wood) + +Sun Nov 3 14:50:23 1991 Per Bothner (bothner at cygnus.com) + + * Makefile.in ($(DIST_NAME).tar.Z), TODO: Various fixes. + * ar.c (get_pos_bfd): Fix to handling of before/after + positioning options. + * bucomm.c (fatal): MISSING_VFPRINTF is no longer an issue, + since libiberty contains vfprintf etc if otherwise missing. + * m68k-pinsn.c (print_insn_arg): Support BB/BW/BL + type operands, as used by branch instructions. + * nm.c: Delegate printing of symbols to BFD, + by using bfd_print_symbol to do the formatting. + +Mon Oct 28 11:20:47 1991 Steve Chamberlain (steve at cygnus.com) + + * ar.c (write_archive.c): added unlink before rename since some + systems can't rename onto an existant file. + +Mon Oct 21 09:47:23 1991 Steve Chamberlain (steve at rtl.cygnus.com) + + * nm.c: now doesn't crash if a symbol with no section and no + SEC_ABS appears. + +Thu Oct 17 15:25:50 1991 Per Bothner (bothner at cygnus.com) + + * Makefile.in, version.c: Bump to version 1.91. + +Wed Oct 16 11:45:36 1991 Per Bothner (bothner at cygnus.com) + + * Makefile.in, ar.c, bucomm.c, copy.c, cplus-dem.c, filemode.c, + i960-pinsn.c, m68k-pinsn.c, nm.c, objdump.c, size.c, sparc-pinsn.c, + * strip.c: Add or update Copyright notice. + * TODO: Add note on 'nm -a'. + * version.c: Update version number to 1.90. + * Makefile.in: Fix making of documentation for dist. + +Tue Oct 15 00:17:17 1991 Per Bothner (bothner at cygnus.com) + + * README: New file. + * Makefile.in: New kludgy rules for making a tarfile. + * Makefile.in: Fix bindir path. + +Mon Oct 14 17:34:29 1991 Roland H. Pesch (pesch at cygnus.com) + + * Makefile.in: add targets binutils.mm, binutils.me + +Fri Oct 11 22:44:21 1991 John Gilmore (gnu at cygnus.com) + + * Makefile.in: Avoid Sun Make VPATH bugs by adding dependencies. + +Fri Oct 11 12:51:33 1991 Roland H. Pesch (pesch at cygnus.com) + + * Makefile.in: add target "binutils.ms" + + * binutils.texinfo: minor restructuring for texi2roff comfort. + +Fri Oct 11 04:12:28 1991 John Gilmore (gnu at cygnus.com) + + Restructure configuration scheme for bfd, binutils, ld. + + * include/sys/h-*.h: Move to bfd/hosts/h-*.h. + * configure.in: Revise to symlink sysdep.h to ../bfd/hosts/h-xxx.h. + Change some config names to match other dirs. + * *.c: Include bfd.h before sysdep.h, so ansidecl and PROTO() + get defined first. + * Makefile.in: Use -I. to get sysdep.h. + +Wed Oct 9 22:42:56 1991 Per Bothner (bothner at cygnus.com) + + * nm.c (print_symbols): Handle NULL name field of symbol. + * Makefile.in: Removed spurious comment. + +Tue Oct 8 16:55:03 1991 Roland H. Pesch (pesch at cygnus.com) + + * binutils.texinfo: minor typos, phrasing, formatting fixes. + +Tue Oct 8 15:13:20 1991 Per Bothner (bothner at cygnus.com) + + * configure.in: Get host file from ../bfd/config, not config. + * config/*: Remove config directory and its files. + +Tue Oct 8 13:58:59 1991 Roland H. Pesch (pesch at cygnus.com) + + * Makefile.in: new targets binutils.dvi, binutils.info + + * binutils.texinfo: remove most remaining FIXME's, delete + references to __.SYMDEF by name + + +Tue Oct 8 10:23:44 1991 Steve Chamberlain (steve at cygnus.com) + + * objdump.c (print_address) Print addresses nicely. + +Mon Oct 7 11:31:05 1991 Per Bothner (bothner at cygnus.com) + + * ar.c, Makefile.in, new files {is,not,maybe}-ranlib.c: + Make two different binaries for ar and ranlib, instead of + distinguishing them at run time using argv[0]. + (Old behavior is still available if you "make ar_with_ranlib", + but it is not the default.) + * ranlib.sh (new): An alternative one-line + shell implementation of ranlib. + +Fri Oct 4 21:49:44 1991 John Gilmore (gnu at cygnus.com) + + * objdump.c: Cope with renames of a few BFD types & enums. + +Fri Oct 4 19:08:09 1991 Roland H. Pesch (pesch at cygnus.com) + + * binutils.texinfo: add new file (rudimentary docn) + +Mon Sep 30 12:30:39 1991 Per Bothner (bothner at cygnus.com) + + * config/hmake-news: Add new file (for Sony NEWSOS3). + * bucomm.c (fatal): Conditionally compile fatal() depending on + MISSING_VFPRINTF, and don't confuse the issue with NO_VARARGS. + * objdump.c (dump_headers): Trivial output format change. + * objdump.c (display_info): Loop over integers, not enums, + to appease old compilers. + +Mon May 20 16:14:07 1991 Steve Chamberlain (steve at cygint.cygnus.com) + + *objdump.c *nm.c *copy.c :hanged some types to work with 64 bit object files + +Thu May 16 16:06:55 1991 Steve Chamberlain (steve at cygint.cygnus.com) + from bother + * objdump.c (print_address): Make disasembled output more + consistent with gdb and as: Add 0x when printing hex. + Don't print extra leading zeros. + Attempt to not print "filename.o". + * objdump.c: Add some enum-to-int casts to accomodate old compilers. + + +Fri May 3 22:21:44 1991 John Gilmore (gnu at cygint.cygnus.com) + + * copy.c: Change =& constructs to = &, since they confuse older + C compilers. + + +Local Variables: +mode: change-log +left-margin: 8 +fill-column: 74 +version-control: never +End: diff --git a/binutils/Makefile.am b/binutils/Makefile.am new file mode 100644 index 0000000..4f3014f --- /dev/null +++ b/binutils/Makefile.am @@ -0,0 +1,495 @@ +## Process this file with automake to generate Makefile.in + +## FIXME: Work around apparent bug in automake. +INTLLIBS = @INTLLIBS@ + +AUTOMAKE_OPTIONS = cygnus dejagnu + +SUBDIRS = po + +tooldir = $(exec_prefix)/$(target_alias) + +## These aren't set by automake, because they appear in +## bfd/acinclude.m4, which is included by binutils/acinclude.m4, and +## thus is not seen by automake. +CC_FOR_BUILD = @CC_FOR_BUILD@ +EXEEXT_FOR_BUILD = @EXEEXT_FOR_BUILD@ + +YACC = `if [ -f ../bison/bison ] ; then echo ../bison/bison -y -L$(srcdir)/../bison/ ; else echo bison -y ; fi` +YFLAGS = -d +LEX = `if [ -f ../flex/flex ] ; then echo ../flex/flex ; else echo flex ; fi` + +# these two are almost the same program +AR_PROG=ar +RANLIB_PROG=ranlib + +# objcopy and strip should be the same program +OBJCOPY_PROG=objcopy +STRIP_PROG=strip-new + +STRINGS_PROG=strings + +READELF_PROG=readelf + +# These should all be the same program too. +SIZE_PROG=size +NM_PROG=nm-new +OBJDUMP_PROG=objdump + +# This is the demangler, as a standalone program. +# Note: This one is used as the installed name too, unlike the above. +DEMANGLER_PROG=c++filt + +ADDR2LINE_PROG=addr2line + +NLMCONV_PROG=nlmconv +DLLTOOL_PROG=dlltool +WINDRES_PROG=windres +DLLWRAP_PROG=dllwrap + +SRCONV_PROG=srconv$(EXEEXT) sysdump$(EXEEXT) coffdump$(EXEEXT) + +man_MANS = ar.1 nm.1 objdump.1 ranlib.1 size.1 strings.1 strip.1 objcopy.1 \ + addr2line.1 nlmconv.1 $(DEMANGLER_PROG).1 + +PROGS = $(SIZE_PROG) $(OBJDUMP_PROG) $(NM_PROG) $(AR_PROG) $(STRINGS_PROG) $(STRIP_PROG) $(RANLIB_PROG) $(DEMANGLER_PROG) $(OBJCOPY_PROG) @BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @BUILD_WINDRES@ $(ADDR2LINE_PROG) $(READELF_PROG) @BUILD_DLLWRAP@ @BUILD_MISC@ + +bin_PROGRAMS = $(SIZE_PROG) $(OBJDUMP_PROG) $(AR_PROG) $(STRINGS_PROG) $(RANLIB_PROG) $(DEMANGLER_PROG) $(OBJCOPY_PROG) @BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @BUILD_WINDRES@ $(ADDR2LINE_PROG) $(READELF_PROG) @BUILD_DLLWRAP@ @BUILD_MISC@ + +## We need a special rule to install the programs which are built with -new +noinst_PROGRAMS = $(NM_PROG) $(STRIP_PROG) + +EXTRA_PROGRAMS = $(NLMCONV_PROG) srconv sysdump coffdump $(DLLTOOL_PROG) $(WINDRES_PROG) $(DLLWRAP_PROG) + +# Stuff that goes in tooldir/ if appropriate +TOOL_PROGS = nm-new strip-new ar ranlib dlltool + +BASEDIR = $(srcdir)/.. +BFDDIR = $(BASEDIR)/bfd +INCDIR = $(BASEDIR)/include + +DEP = mkdep + +INCLUDES = -D_GNU_SOURCE -I. -I$(srcdir) -I../bfd -I$(BFDDIR) -I$(INCDIR) @HDEFINES@ -I$(srcdir)/../intl -I../intl -DLOCALEDIR="\"$(prefix)/share/locale\"" + +HFILES = arsup.h bucomm.h budbg.h coffgrok.h debug.h nlmconv.h dlltool.h \ + windres.h winduni.h dyn-string.h + +GENERATED_HFILES = arparse.h sysroff.h sysinfo.h defparse.h + +CFILES = addr2line.c ar.c arsup.c bucomm.c coffdump.c coffgrok.c debug.c \ + dlltool.c filemode.c ieee.c is-ranlib.c is-strip.c maybe-ranlib.c \ + maybe-strip.c nlmconv.c nm.c not-ranlib.c not-strip.c \ + objcopy.c objdump.c prdbg.c rdcoff.c rddbg.c size.c srconv.c \ + stabs.c strings.c sysdump.c version.c wrstabs.c \ + windres.c resrc.c rescoff.c resbin.c winduni.c readelf.c \ + resres.c dyn-string.c dllwrap.c rename.c + +GENERATED_CFILES = \ + underscore.c arparse.c arlex.c sysroff.c sysinfo.c syslex.c \ + defparse.c deflex.c nlmheader.c rcparse.c rclex.c + +DEBUG_SRCS = rddbg.c debug.c stabs.c ieee.c rdcoff.c +WRITE_DEBUG_SRCS = $(DEBUG_SRCS) wrstabs.c + +# Code shared by all the binutils. +BULIBS = bucomm.c version.c filemode.c + +BFDLIB = ../bfd/libbfd.la + +OPCODES = ../opcodes/libopcodes.la + +LIBIBERTY = ../libiberty/libiberty.a + +POTFILES = $(CFILES) $(DEBUG_SRCS) $(HFILES) +po/POTFILES.in: @MAINT@ Makefile + for file in $(POTFILES); do echo $$file; done | sort > tmp \ + && mv tmp $(srcdir)/po/POTFILES.in + +EXPECT = `if [ -f $$r/../expect/expect ] ; then \ + echo $$r/../expect/expect ; \ + else echo expect ; fi` +RUNTEST = `if [ -f ${srcdir}/../dejagnu/runtest ] ; then \ + echo ${srcdir}/../dejagnu/runtest ; \ + else echo runtest ; fi` + +CC_FOR_TARGET = ` \ + if [ -f $$r/../gcc/xgcc ] ; then \ + if [ -f $$r/../newlib/Makefile ] ; then \ + echo $$r/../gcc/xgcc -B$$r/../gcc/ -idirafter $$r/../newlib/targ-include -idirafter $${srcroot}/../newlib/libc/include -nostdinc; \ + else \ + echo $$r/../gcc/xgcc -B$$r/../gcc/; \ + fi; \ + else \ + if [ "@host@" = "@target@" ] ; then \ + echo $(CC); \ + else \ + echo gcc | sed '$(transform)'; \ + fi; \ + fi` + +check-DEJAGNU: site.exp + srcdir=`cd $(srcdir) && pwd`; export srcdir; \ + r=`pwd`; export r; \ + EXPECT=$(EXPECT); export EXPECT; \ + if [ -f $(top_builddir)/../expect/expect ]; then \ + TCL_LIBRARY=`cd $(top_srcdir)/../tcl/library && pwd`; \ + export TCL_LIBRARY; \ + fi; \ + runtest=$(RUNTEST); \ + if $(SHELL) -c "$$runtest --version" > /dev/null 2>&1; then \ + $$runtest --tool $(DEJATOOL) --srcdir $${srcdir}/testsuite \ + CC_FOR_TARGET="$(CC_FOR_TARGET)" \ + CFLAGS_FOR_TARGET="$(CFLAGS)" $(RUNTESTFLAGS); \ + else echo "WARNING: could not find \`runtest'" 1>&2; :;\ + fi + +installcheck: + /bin/sh $(srcdir)/sanity.sh $(bindir) + +info_TEXINFOS = binutils.texi + +LDADD = $(BFDLIB) $(LIBIBERTY) $(INTLLIBS) + +size_SOURCES = size.c $(BULIBS) + +objcopy_SOURCES = objcopy.c not-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS) + +strings_SOURCES = strings.c $(BULIBS) + +readelf_SOURCES = readelf.c version.c +readelf_LDADD = $(INTLLIBS) $(LIBIBERTY) + +strip_new_SOURCES = objcopy.c is-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS) + +nm_new_SOURCES = nm.c $(BULIBS) + +objdump_SOURCES = objdump.c prdbg.c $(DEBUG_SRCS) $(BULIBS) +objdump_LDADD = $(OPCODES) $(BFDLIB) $(LIBIBERTY) $(INTLLIBS) + +underscore.c: stamp-under ; @true + +stamp-under: Makefile + echo '/*WARNING: This file is automatically generated!*/' >underscore.t + echo "int prepends_underscore = @UNDERSCORE@;" >>underscore.t + $(SHELL) $(srcdir)/../move-if-change underscore.t underscore.c + touch stamp-under + +cplus-dem.o: $(BASEDIR)/libiberty/cplus-dem.c $(INCDIR)/getopt.h + $(COMPILE) -c -DMAIN -DVERSION='"$(VERSION)"' $(BASEDIR)/libiberty/cplus-dem.c + +c__filt_SOURCES = +c__filt_LDADD = cplus-dem.o underscore.o $(LIBIBERTY) $(INTLLIBS) + +ar_SOURCES = arparse.y arlex.l ar.c not-ranlib.c arsup.c rename.c $(BULIBS) +ar_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(INTLLIBS) + +ranlib_SOURCES = ar.c is-ranlib.c arparse.y arlex.l arsup.c rename.c $(BULIBS) +ranlib_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(INTLLIBS) + +addr2line_SOURCES = addr2line.c $(BULIBS) + +# The following is commented out for the convertion to automake. +# This rule creates a single binary that switches between ar and ranlib +# by looking at argv[0]. Use this kludge to save some disk space. +# However, you have to install things by hand. +# (That is after 'make install', replace the installed ranlib by a link to ar.) +# Alternatively, you can install ranlib.sh as ranlib. +# ar_with_ranlib: $(ADDL_DEPS) ar.o maybe-ranlib.o +# $(HLDENV) $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $(AR_PROG) ar.o maybe-ranlib.o $(ADDL_LIBS) $(EXTRALIBS) +# -rm -f $(RANLIB_PROG) +# -ln $(AR_PROG) $(RANLIB_PROG) +# +# objcopy and strip in one binary that uses argv[0] to decide its action. +# +#objcopy_with_strip: $(ADDL_DEPS) objcopy.o maybe-strip.o +# $(HLDENV) $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $(OBJCOPY_PROG) objcopy.o maybe-strip.o $(ADDL_LIBS) $(EXTRALIBS) +# -rm -f $(STRIP_PROG) +# -ln $(OBJCOPY_PROG) $(STRIP_PROG) + +sysroff.c: sysinfo$(EXEEXT_FOR_BUILD) sysroff.info + ./sysinfo$(EXEEXT_FOR_BUILD) -c <$(srcdir)/sysroff.info >sysroff.c + ./sysinfo$(EXEEXT_FOR_BUILD) -i <$(srcdir)/sysroff.info >>sysroff.c + ./sysinfo$(EXEEXT_FOR_BUILD) -g <$(srcdir)/sysroff.info >>sysroff.c + +sysroff.h: sysinfo$(EXEEXT_FOR_BUILD) sysroff.info + ./sysinfo$(EXEEXT_FOR_BUILD) -d <$(srcdir)/sysroff.info >sysroff.h + +sysinfo$(EXEEXT_FOR_BUILD): sysinfo.o syslex.o + $(CC_FOR_BUILD) $(CFLAGS) $(LDFLAGS) -o $@ sysinfo.o syslex.o + +syslex.o: syslex.c sysinfo.h + if [ -r syslex.c ]; then \ + $(CC_FOR_BUILD) -c -I. $(CFLAGS) syslex.c ; \ + else \ + $(CC_FOR_BUILD) -c -I. -I$(srcdir) $(CFLAGS) $(srcdir)/syslex.c ;\ + fi + +sysinfo.o: sysinfo.c + if [ -r sysinfo.c ]; then \ + $(CC_FOR_BUILD) -c -I. $(CFLAGS) sysinfo.c ; \ + else \ + $(CC_FOR_BUILD) -c -I. $(CFLAGS) $(srcdir)/sysinfo.c ; \ + fi + +srconv_SOURCES = srconv.c coffgrok.c $(BULIBS) + +dlltool_SOURCES = dlltool.c defparse.y deflex.l $(BULIBS) +dlltool_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(INTLLIBS) + +dlltool.o:dlltool.c + $(COMPILE) -c $(DLLTOOL_DEFS) $(srcdir)/dlltool.c + +coffdump_SOURCES = coffdump.c coffgrok.c $(BULIBS) + +sysdump_SOURCES = sysdump.c $(BULIBS) + +# coff/sym.h and coff/ecoff.h won't be found by the automatic dependency +# scripts, since they are only included conditionally. +nlmconv.o: nlmconv.c $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h + ldname=`echo ld | sed '$(transform)'`; \ + $(COMPILE) -c -DLD_NAME="\"$${ldname}\"" @NLMCONV_DEFS@ $(srcdir)/nlmconv.c + +nlmconv_SOURCES = nlmconv.c nlmheader.y $(BULIBS) + +windres_SOURCES = windres.c resrc.c rescoff.c resbin.c rcparse.y rclex.l \ + winduni.c resres.c $(BULIBS) +windres_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(INTLLIBS) + +dllwrap_SOURCES = dllwrap.c dyn-string.c +dllwrap_LDADD = $(LIBIBERTY) + + +DISTSTUFF = arparse.c arparse.h arlex.c nlmheader.c sysinfo.c sysinfo.h \ + syslex.c deflex.c defparse.h defparse.c rclex.c rcparse.h rcparse.c + +diststuff: $(DISTSTUFF) info + +DISTCLEANFILES = stamp-under sysinfo underscore.c sysroff.c sysroff.h \ + site.exp site.bak + +# Targets to rebuild dependencies in this Makefile. +# Have to get rid of .dep1 here so that "$?" later includes all of $(CFILES). +.dep: dep.sed $(CFILES) $(HFILES) $(GENERATED_CFILES) $(GENERATED_HFILES) config.h + rm -f .dep1 + $(MAKE) DEP=$(DEP) .dep1 + sed -f dep.sed <.dep1 >.dep + +# This rule really wants a mkdep that runs "gcc -MM". +.dep1: $(CFILES) $(GENERATED_CFILES) + rm -f .dep2 + echo '# DO NOT DELETE THIS LINE -- mkdep uses it.' > .dep2 + $(DEP) -f .dep2 $(INCLUDES) $? + $(SHELL) $(srcdir)/../move-if-change .dep2 .dep1 + +dep.sed: dep-in.sed config.status + objdir=`pwd`; \ + sed <$(srcdir)/dep-in.sed >dep.sed \ + -e 's!@INCDIR@!$(INCDIR)!' \ + -e 's!@BFDDIR@!$(BFDDIR)!' \ + -e 's!@SRCDIR@!$(srcdir)!' \ + -e "s!@OBJDIR@!$${objdir}!" + +dep: .dep + sed -e '/^..DO NOT DELETE THIS LINE/,$$d' < Makefile > tmp-Makefile + cat .dep >> tmp-Makefile + $(SHELL) $(srcdir)/../move-if-change tmp-Makefile Makefile + +dep-in: .dep + sed -e '/^..DO NOT DELETE THIS LINE/,$$d' < $(srcdir)/Makefile.in > tmp-Makefile.in + cat .dep >> tmp-Makefile.in + $(SHELL) $(srcdir)/../move-if-change tmp-Makefile.in $(srcdir)/Makefile.in + +dep-am: .dep + sed -e '/^..DO NOT DELETE THIS LINE/,$$d' < $(srcdir)/Makefile.am > tmp-Makefile.am + cat .dep >> tmp-Makefile.am + $(SHELL) $(srcdir)/../move-if-change tmp-Makefile.am $(srcdir)/Makefile.am + +.PHONY: dep dep-in dep-am + +### +# DOCUMENTATION TARGETS +config.texi: Makefile + rm -f config.texi + echo '@set VERSION $(VERSION)' > config.texi + +binutils.dvi: $(srcdir)/binutils.texi config.texi + +binutils.info: $(srcdir)/binutils.texi config.texi + +MAINTAINERCLEANFILES = config.texi + +$(DEMANGLER_PROG).1: cxxfilt.man Makefile + sed -e 's/@PROGRAM@/$(DEMANGLER_PROG)/' < $(srcdir)/cxxfilt.man \ + > $(DEMANGLER_PROG).1 + +MOSTLYCLEANFILES = sysinfo $(DEMANGLER_PROG).1 binutils.log binutils.sum \ + abcdefgh* +mostlyclean-local: + -rm -rf tmpdir + +CLEANFILES = dep.sed .dep .dep1 + +.PHONY: install-exec-local + +install-exec-local: $(bin_PROGRAMS) $(noinst_PROGRAMS) + @list='$(noinst_PROGRAMS)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(bindir)/`echo $$p|sed -e 's/$(EXEEXT)$$//' -e 's/-new//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \ + $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(bindir)/`echo $$p|sed -e 's/$(EXEEXT)$$//' -e 's/-new//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + else :; fi; \ + done + $(mkinstalldirs) $(tooldir)/bin + for i in $(TOOL_PROGS); do \ + if [ -f $$i$(EXEEXT) ]; then \ + j=`echo $$i | sed -e 's/-new//'`; \ + k=`echo $$j | sed '$(transform)'`; \ + if [ "$(bindir)/$$k$(EXEEXT)" != "$(tooldir)/bin/$$j$(EXEEXT)" ]; then \ + rm -f $(tooldir)/bin/$$j$(EXEEXT); \ + ln $(bindir)/$$k$(EXEEXT) $(tooldir)/bin/$$j$(EXEEXT) >/dev/null 2>/dev/null \ + || $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$i$(EXEEXT) $(tooldir)/bin/$$j$(EXEEXT); \ + fi; \ + else true; \ + fi; \ + done + +# What appears below is generated by a hacked mkdep using gcc -MM. + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. + +addr2line.o: addr2line.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/getopt.h $(INCDIR)/libiberty.h $(INCDIR)/demangle.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h +ar.o: ar.c ../bfd/bfd.h $(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h \ + $(INCDIR)/progress.h bucomm.h config.h $(INCDIR)/fopen-same.h \ + $(INCDIR)/aout/ar.h $(BFDDIR)/libbfd.h arsup.h +arsup.o: arsup.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + arsup.h $(INCDIR)/libiberty.h bucomm.h config.h $(INCDIR)/fopen-same.h +bucomm.o: bucomm.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/libiberty.h bucomm.h config.h $(INCDIR)/fopen-same.h +coffdump.o: coffdump.c coffgrok.h bucomm.h config.h \ + $(INCDIR)/fopen-same.h +coffgrok.o: coffgrok.c bucomm.h config.h $(INCDIR)/fopen-same.h \ + $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \ + coffgrok.h +debug.o: debug.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \ + debug.h +dlltool.o: dlltool.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/libiberty.h bucomm.h config.h $(INCDIR)/fopen-same.h \ + $(INCDIR)/getopt.h $(INCDIR)/demangle.h dlltool.h +filemode.o: filemode.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h +ieee.o: ieee.c ../bfd/bfd.h $(INCDIR)/ansidecl.h $(INCDIR)/ieee.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \ + debug.h budbg.h +is-ranlib.o: is-ranlib.c +is-strip.o: is-strip.c +maybe-ranlib.o: maybe-ranlib.c +maybe-strip.o: maybe-strip.c +nlmconv.o: nlmconv.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/libiberty.h bucomm.h config.h $(INCDIR)/fopen-same.h \ + $(BFDDIR)/libnlm.h $(INCDIR)/nlm/common.h $(INCDIR)/nlm/internal.h \ + $(INCDIR)/nlm/external.h nlmconv.h +nm.o: nm.c ../bfd/bfd.h $(INCDIR)/ansidecl.h $(INCDIR)/progress.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/getopt.h \ + $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def $(INCDIR)/aout/ranlib.h \ + $(INCDIR)/demangle.h $(INCDIR)/libiberty.h +not-ranlib.o: not-ranlib.c +not-strip.o: not-strip.c +objcopy.o: objcopy.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/progress.h bucomm.h config.h $(INCDIR)/fopen-same.h \ + $(INCDIR)/getopt.h $(INCDIR)/libiberty.h budbg.h +objdump.o: objdump.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/getopt.h $(INCDIR)/progress.h bucomm.h config.h \ + $(INCDIR)/fopen-same.h $(INCDIR)/dis-asm.h $(INCDIR)/libiberty.h \ + $(INCDIR)/demangle.h debug.h budbg.h $(INCDIR)/aout/aout64.h +prdbg.o: prdbg.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \ + debug.h budbg.h +rdcoff.o: rdcoff.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/coff/internal.h bucomm.h config.h $(INCDIR)/fopen-same.h \ + $(INCDIR)/libiberty.h $(INCDIR)/demangle.h debug.h \ + budbg.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h +rddbg.o: rddbg.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \ + debug.h budbg.h +size.o: size.c ../bfd/bfd.h $(INCDIR)/ansidecl.h $(INCDIR)/getopt.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h +srconv.o: srconv.c bucomm.h config.h $(INCDIR)/fopen-same.h \ + sysroff.h coffgrok.h $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h \ + $(INCDIR)/bfdlink.h sysroff.c +stabs.o: stabs.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \ + $(INCDIR)/demangle.h debug.h budbg.h $(INCDIR)/aout/aout64.h \ + $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def +strings.o: strings.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h +sysdump.o: sysdump.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h sysroff.h \ + sysroff.c +version.o: version.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h +wrstabs.o: wrstabs.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \ + debug.h budbg.h $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab_gnu.h \ + $(INCDIR)/aout/stab.def +windres.o: windres.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/getopt.h bucomm.h config.h $(INCDIR)/fopen-same.h \ + $(INCDIR)/libiberty.h $(INCDIR)/obstack.h windres.h \ + winduni.h +resrc.o: resrc.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \ + windres.h winduni.h +rescoff.o: rescoff.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \ + windres.h winduni.h $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h \ + $(INCDIR)/bfdlink.h +resbin.o: resbin.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \ + windres.h winduni.h +winduni.o: winduni.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h winduni.h +readelf.o: readelf.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/elf/common.h $(INCDIR)/elf/external.h $(INCDIR)/elf/internal.h \ + $(INCDIR)/elf/dwarf2.h $(INCDIR)/elf/i386.h $(INCDIR)/elf/reloc-macros.h \ + $(INCDIR)/elf/v850.h $(INCDIR)/elf/ppc.h $(INCDIR)/elf/mips.h \ + $(INCDIR)/elf/alpha.h $(INCDIR)/elf/arm.h $(INCDIR)/elf/m68k.h \ + $(INCDIR)/elf/sparc.h $(INCDIR)/elf/m32r.h $(INCDIR)/elf/d10v.h \ + $(INCDIR)/elf/d30v.h $(INCDIR)/elf/sh.h $(INCDIR)/elf/mn10200.h \ + $(INCDIR)/elf/mn10300.h $(INCDIR)/elf/hppa.h $(INCDIR)/elf/arc.h \ + $(INCDIR)/elf/fr30.h bucomm.h config.h $(INCDIR)/fopen-same.h \ + $(INCDIR)/getopt.h +resres.o: resres.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \ + windres.h winduni.h +dyn-string.o: dyn-string.c config.h $(INCDIR)/ansidecl.h \ + dyn-string.h +dllwrap.o: dllwrap.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/libiberty.h bucomm.h config.h $(INCDIR)/fopen-same.h \ + $(INCDIR)/getopt.h dyn-string.h +rename.o: rename.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h +underscore.o: underscore.c +arparse.o: arparse.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h arsup.h +arlex.o: arlex.c $(INCDIR)/libiberty.h arparse.h +sysroff.o: sysroff.c +sysinfo.o: sysinfo.c +syslex.o: syslex.c sysinfo.h +defparse.o: defparse.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h dlltool.h +deflex.o: deflex.c $(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h \ + defparse.h dlltool.h +nlmheader.o: nlmheader.c ../bfd/bfd.h bucomm.h config.h \ + $(INCDIR)/fopen-same.h $(INCDIR)/nlm/common.h $(INCDIR)/nlm/internal.h \ + nlmconv.h +rcparse.o: rcparse.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \ + windres.h winduni.h +rclex.o: rclex.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \ + windres.h winduni.h rcparse.h + +# IF YOU PUT ANYTHING HERE IT WILL GO AWAY diff --git a/binutils/Makefile.in b/binutils/Makefile.in new file mode 100644 index 0000000..c32ae4d --- /dev/null +++ b/binutils/Makefile.in @@ -0,0 +1,1358 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = . + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_alias = @build_alias@ +build_triplet = @build@ +host_alias = @host_alias@ +host_triplet = @host@ +target_alias = @target_alias@ +target_triplet = @target@ +AR = @AR@ +AS = @AS@ +BUILD_DLLTOOL = @BUILD_DLLTOOL@ +BUILD_DLLWRAP = @BUILD_DLLWRAP@ +BUILD_MISC = @BUILD_MISC@ +BUILD_NLMCONV = @BUILD_NLMCONV@ +BUILD_SRCONV = @BUILD_SRCONV@ +BUILD_WINDRES = @BUILD_WINDRES@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +DATADIRNAME = @DATADIRNAME@ +DLLTOOL = @DLLTOOL@ +DLLTOOL_DEFS = @DLLTOOL_DEFS@ +EXEEXT = @EXEEXT@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GT_NO = @GT_NO@ +GT_YES = @GT_YES@ +HDEFINES = @HDEFINES@ +INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@ +INSTOBJEXT = @INSTOBJEXT@ +INTLDEPS = @INTLDEPS@ +INTLOBJS = @INTLOBJS@ +LD = @LD@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +NLMCONV_DEFS = @NLMCONV_DEFS@ +NM = @NM@ +PACKAGE = @PACKAGE@ +POFILES = @POFILES@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +UNDERSCORE = @UNDERSCORE@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +USE_SYMBOL_UNDERSCORE = @USE_SYMBOL_UNDERSCORE@ +VERSION = @VERSION@ +l = @l@ + +INTLLIBS = @INTLLIBS@ + +AUTOMAKE_OPTIONS = cygnus dejagnu + +SUBDIRS = po + +tooldir = $(exec_prefix)/$(target_alias) + +CC_FOR_BUILD = @CC_FOR_BUILD@ +EXEEXT_FOR_BUILD = @EXEEXT_FOR_BUILD@ + +YACC = `if [ -f ../bison/bison ] ; then echo ../bison/bison -y -L$(srcdir)/../bison/ ; else echo bison -y ; fi` +YFLAGS = -d +LEX = `if [ -f ../flex/flex ] ; then echo ../flex/flex ; else echo flex ; fi` + +# these two are almost the same program +AR_PROG = ar +RANLIB_PROG = ranlib + +# objcopy and strip should be the same program +OBJCOPY_PROG = objcopy +STRIP_PROG = strip-new + +STRINGS_PROG = strings + +READELF_PROG = readelf + +# These should all be the same program too. +SIZE_PROG = size +NM_PROG = nm-new +OBJDUMP_PROG = objdump + +# This is the demangler, as a standalone program. +# Note: This one is used as the installed name too, unlike the above. +DEMANGLER_PROG = c++filt + +ADDR2LINE_PROG = addr2line + +NLMCONV_PROG = nlmconv +DLLTOOL_PROG = dlltool +WINDRES_PROG = windres +DLLWRAP_PROG = dllwrap + +SRCONV_PROG = srconv$(EXEEXT) sysdump$(EXEEXT) coffdump$(EXEEXT) + +man_MANS = ar.1 nm.1 objdump.1 ranlib.1 size.1 strings.1 strip.1 objcopy.1 \ + addr2line.1 nlmconv.1 $(DEMANGLER_PROG).1 + + +PROGS = $(SIZE_PROG) $(OBJDUMP_PROG) $(NM_PROG) $(AR_PROG) $(STRINGS_PROG) $(STRIP_PROG) $(RANLIB_PROG) $(DEMANGLER_PROG) $(OBJCOPY_PROG) @BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @BUILD_WINDRES@ $(ADDR2LINE_PROG) $(READELF_PROG) @BUILD_DLLWRAP@ @BUILD_MISC@ + +bin_PROGRAMS = $(SIZE_PROG) $(OBJDUMP_PROG) $(AR_PROG) $(STRINGS_PROG) $(RANLIB_PROG) $(DEMANGLER_PROG) $(OBJCOPY_PROG) @BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @BUILD_WINDRES@ $(ADDR2LINE_PROG) $(READELF_PROG) @BUILD_DLLWRAP@ @BUILD_MISC@ + +noinst_PROGRAMS = $(NM_PROG) $(STRIP_PROG) + +EXTRA_PROGRAMS = $(NLMCONV_PROG) srconv sysdump coffdump $(DLLTOOL_PROG) $(WINDRES_PROG) $(DLLWRAP_PROG) + +# Stuff that goes in tooldir/ if appropriate +TOOL_PROGS = nm-new strip-new ar ranlib dlltool + +BASEDIR = $(srcdir)/.. +BFDDIR = $(BASEDIR)/bfd +INCDIR = $(BASEDIR)/include + +DEP = mkdep + +INCLUDES = -D_GNU_SOURCE -I. -I$(srcdir) -I../bfd -I$(BFDDIR) -I$(INCDIR) @HDEFINES@ -I$(srcdir)/../intl -I../intl -DLOCALEDIR="\"$(prefix)/share/locale\"" + +HFILES = arsup.h bucomm.h budbg.h coffgrok.h debug.h nlmconv.h dlltool.h \ + windres.h winduni.h dyn-string.h + + +GENERATED_HFILES = arparse.h sysroff.h sysinfo.h defparse.h + +CFILES = addr2line.c ar.c arsup.c bucomm.c coffdump.c coffgrok.c debug.c \ + dlltool.c filemode.c ieee.c is-ranlib.c is-strip.c maybe-ranlib.c \ + maybe-strip.c nlmconv.c nm.c not-ranlib.c not-strip.c \ + objcopy.c objdump.c prdbg.c rdcoff.c rddbg.c size.c srconv.c \ + stabs.c strings.c sysdump.c version.c wrstabs.c \ + windres.c resrc.c rescoff.c resbin.c winduni.c readelf.c \ + resres.c dyn-string.c dllwrap.c rename.c + + +GENERATED_CFILES = \ + underscore.c arparse.c arlex.c sysroff.c sysinfo.c syslex.c \ + defparse.c deflex.c nlmheader.c rcparse.c rclex.c + + +DEBUG_SRCS = rddbg.c debug.c stabs.c ieee.c rdcoff.c +WRITE_DEBUG_SRCS = $(DEBUG_SRCS) wrstabs.c + +# Code shared by all the binutils. +BULIBS = bucomm.c version.c filemode.c + +BFDLIB = ../bfd/libbfd.la + +OPCODES = ../opcodes/libopcodes.la + +LIBIBERTY = ../libiberty/libiberty.a + +POTFILES = $(CFILES) $(DEBUG_SRCS) $(HFILES) + +EXPECT = `if [ -f $$r/../expect/expect ] ; then \ + echo $$r/../expect/expect ; \ + else echo expect ; fi` + +RUNTEST = `if [ -f ${srcdir}/../dejagnu/runtest ] ; then \ + echo ${srcdir}/../dejagnu/runtest ; \ + else echo runtest ; fi` + + +CC_FOR_TARGET = ` \ + if [ -f $$r/../gcc/xgcc ] ; then \ + if [ -f $$r/../newlib/Makefile ] ; then \ + echo $$r/../gcc/xgcc -B$$r/../gcc/ -idirafter $$r/../newlib/targ-include -idirafter $${srcroot}/../newlib/libc/include -nostdinc; \ + else \ + echo $$r/../gcc/xgcc -B$$r/../gcc/; \ + fi; \ + else \ + if [ "@host@" = "@target@" ] ; then \ + echo $(CC); \ + else \ + echo gcc | sed '$(transform)'; \ + fi; \ + fi` + + +info_TEXINFOS = binutils.texi + +LDADD = $(BFDLIB) $(LIBIBERTY) $(INTLLIBS) + +size_SOURCES = size.c $(BULIBS) + +objcopy_SOURCES = objcopy.c not-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS) + +strings_SOURCES = strings.c $(BULIBS) + +readelf_SOURCES = readelf.c version.c +readelf_LDADD = $(INTLLIBS) $(LIBIBERTY) + +strip_new_SOURCES = objcopy.c is-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS) + +nm_new_SOURCES = nm.c $(BULIBS) + +objdump_SOURCES = objdump.c prdbg.c $(DEBUG_SRCS) $(BULIBS) +objdump_LDADD = $(OPCODES) $(BFDLIB) $(LIBIBERTY) $(INTLLIBS) + +c__filt_SOURCES = +c__filt_LDADD = cplus-dem.o underscore.o $(LIBIBERTY) $(INTLLIBS) + +ar_SOURCES = arparse.y arlex.l ar.c not-ranlib.c arsup.c rename.c $(BULIBS) +ar_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(INTLLIBS) + +ranlib_SOURCES = ar.c is-ranlib.c arparse.y arlex.l arsup.c rename.c $(BULIBS) +ranlib_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(INTLLIBS) + +addr2line_SOURCES = addr2line.c $(BULIBS) + +srconv_SOURCES = srconv.c coffgrok.c $(BULIBS) + +dlltool_SOURCES = dlltool.c defparse.y deflex.l $(BULIBS) +dlltool_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(INTLLIBS) + +coffdump_SOURCES = coffdump.c coffgrok.c $(BULIBS) + +sysdump_SOURCES = sysdump.c $(BULIBS) + +nlmconv_SOURCES = nlmconv.c nlmheader.y $(BULIBS) + +windres_SOURCES = windres.c resrc.c rescoff.c resbin.c rcparse.y rclex.l \ + winduni.c resres.c $(BULIBS) + +windres_LDADD = $(BFDLIB) $(LIBIBERTY) @LEXLIB@ $(INTLLIBS) + +dllwrap_SOURCES = dllwrap.c dyn-string.c +dllwrap_LDADD = $(LIBIBERTY) + +DISTSTUFF = arparse.c arparse.h arlex.c nlmheader.c sysinfo.c sysinfo.h \ + syslex.c deflex.c defparse.h defparse.c rclex.c rcparse.h rcparse.c + + +DISTCLEANFILES = stamp-under sysinfo underscore.c sysroff.c sysroff.h \ + site.exp site.bak + + +MAINTAINERCLEANFILES = config.texi + +MOSTLYCLEANFILES = sysinfo $(DEMANGLER_PROG).1 binutils.log binutils.sum \ + abcdefgh* + + +CLEANFILES = dep.sed .dep .dep1 +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +bin_PROGRAMS = size$(EXEEXT) objdump$(EXEEXT) ar$(EXEEXT) \ +strings$(EXEEXT) ranlib$(EXEEXT) c++filt$(EXEEXT) objcopy$(EXEEXT) \ +@BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ @BUILD_WINDRES@ \ +addr2line$(EXEEXT) readelf$(EXEEXT) @BUILD_DLLWRAP@ @BUILD_MISC@ +noinst_PROGRAMS = nm-new$(EXEEXT) strip-new$(EXEEXT) +PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I. +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +nlmconv_OBJECTS = nlmconv.o nlmheader.o bucomm.o version.o filemode.o +nlmconv_LDADD = $(LDADD) +nlmconv_DEPENDENCIES = ../bfd/libbfd.la ../libiberty/libiberty.a +nlmconv_LDFLAGS = +srconv_OBJECTS = srconv.o coffgrok.o bucomm.o version.o filemode.o +srconv_LDADD = $(LDADD) +srconv_DEPENDENCIES = ../bfd/libbfd.la ../libiberty/libiberty.a +srconv_LDFLAGS = +sysdump_OBJECTS = sysdump.o bucomm.o version.o filemode.o +sysdump_LDADD = $(LDADD) +sysdump_DEPENDENCIES = ../bfd/libbfd.la ../libiberty/libiberty.a +sysdump_LDFLAGS = +coffdump_OBJECTS = coffdump.o coffgrok.o bucomm.o version.o filemode.o +coffdump_LDADD = $(LDADD) +coffdump_DEPENDENCIES = ../bfd/libbfd.la ../libiberty/libiberty.a +coffdump_LDFLAGS = +dlltool_OBJECTS = dlltool.o defparse.o deflex.o bucomm.o version.o \ +filemode.o +dlltool_DEPENDENCIES = ../bfd/libbfd.la ../libiberty/libiberty.a +dlltool_LDFLAGS = +windres_OBJECTS = windres.o resrc.o rescoff.o resbin.o rcparse.o \ +rclex.o winduni.o resres.o bucomm.o version.o filemode.o +windres_DEPENDENCIES = ../bfd/libbfd.la ../libiberty/libiberty.a +windres_LDFLAGS = +dllwrap_OBJECTS = dllwrap.o dyn-string.o +dllwrap_DEPENDENCIES = ../libiberty/libiberty.a +dllwrap_LDFLAGS = +size_OBJECTS = size.o bucomm.o version.o filemode.o +size_LDADD = $(LDADD) +size_DEPENDENCIES = ../bfd/libbfd.la ../libiberty/libiberty.a +size_LDFLAGS = +objdump_OBJECTS = objdump.o prdbg.o rddbg.o debug.o stabs.o ieee.o \ +rdcoff.o bucomm.o version.o filemode.o +objdump_DEPENDENCIES = ../opcodes/libopcodes.la ../bfd/libbfd.la \ +../libiberty/libiberty.a +objdump_LDFLAGS = +ar_OBJECTS = arparse.o arlex.o ar.o not-ranlib.o arsup.o rename.o \ +bucomm.o version.o filemode.o +ar_DEPENDENCIES = ../bfd/libbfd.la ../libiberty/libiberty.a +ar_LDFLAGS = +strings_OBJECTS = strings.o bucomm.o version.o filemode.o +strings_LDADD = $(LDADD) +strings_DEPENDENCIES = ../bfd/libbfd.la ../libiberty/libiberty.a +strings_LDFLAGS = +ranlib_OBJECTS = ar.o is-ranlib.o arparse.o arlex.o arsup.o rename.o \ +bucomm.o version.o filemode.o +ranlib_DEPENDENCIES = ../bfd/libbfd.la ../libiberty/libiberty.a +ranlib_LDFLAGS = +c__filt_OBJECTS = +c__filt_DEPENDENCIES = cplus-dem.o underscore.o \ +../libiberty/libiberty.a +c__filt_LDFLAGS = +objcopy_OBJECTS = objcopy.o not-strip.o rename.o rddbg.o debug.o \ +stabs.o ieee.o rdcoff.o wrstabs.o bucomm.o version.o filemode.o +objcopy_LDADD = $(LDADD) +objcopy_DEPENDENCIES = ../bfd/libbfd.la ../libiberty/libiberty.a +objcopy_LDFLAGS = +addr2line_OBJECTS = addr2line.o bucomm.o version.o filemode.o +addr2line_LDADD = $(LDADD) +addr2line_DEPENDENCIES = ../bfd/libbfd.la ../libiberty/libiberty.a +addr2line_LDFLAGS = +readelf_OBJECTS = readelf.o version.o +readelf_DEPENDENCIES = ../libiberty/libiberty.a +readelf_LDFLAGS = +nm_new_OBJECTS = nm.o bucomm.o version.o filemode.o +nm_new_LDADD = $(LDADD) +nm_new_DEPENDENCIES = ../bfd/libbfd.la ../libiberty/libiberty.a +nm_new_LDFLAGS = +strip_new_OBJECTS = objcopy.o is-strip.o rename.o rddbg.o debug.o \ +stabs.o ieee.o rdcoff.o wrstabs.o bucomm.o version.o filemode.o +strip_new_LDADD = $(LDADD) +strip_new_DEPENDENCIES = ../bfd/libbfd.la ../libiberty/libiberty.a +strip_new_LDFLAGS = +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LEXLIB = @LEXLIB@ +YLWRAP = $(top_srcdir)/../ylwrap +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +TEXI2DVI = `if test -f $(top_srcdir)/../texinfo/util/texi2dvi; then echo $(top_srcdir)/../texinfo/util/texi2dvi; else echo texi2dvi; fi` +TEXINFO_TEX = $(top_srcdir)/../texinfo/texinfo.tex +INFO_DEPS = binutils.info +DVIS = binutils.dvi +TEXINFOS = binutils.texi +man1dir = $(mandir)/man1 +MANS = $(man_MANS) + +NROFF = nroff +DIST_COMMON = README ./stamp-h.in ChangeLog Makefile.am Makefile.in \ +NEWS acinclude.m4 aclocal.m4 arlex.c arparse.c config.in configure \ +configure.in deflex.c defparse.c nlmheader.c rclex.c rcparse.c + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +SOURCES = $(nlmconv_SOURCES) $(srconv_SOURCES) $(sysdump_SOURCES) $(coffdump_SOURCES) $(dlltool_SOURCES) $(windres_SOURCES) $(dllwrap_SOURCES) $(size_SOURCES) $(objdump_SOURCES) $(ar_SOURCES) $(strings_SOURCES) $(ranlib_SOURCES) $(c__filt_SOURCES) $(objcopy_SOURCES) $(addr2line_SOURCES) $(readelf_SOURCES) $(nm_new_SOURCES) $(strip_new_SOURCES) +OBJECTS = $(nlmconv_OBJECTS) $(srconv_OBJECTS) $(sysdump_OBJECTS) $(coffdump_OBJECTS) $(dlltool_OBJECTS) $(windres_OBJECTS) $(dllwrap_OBJECTS) $(size_OBJECTS) $(objdump_OBJECTS) $(ar_OBJECTS) $(strings_OBJECTS) $(ranlib_OBJECTS) $(c__filt_OBJECTS) $(objcopy_OBJECTS) $(addr2line_OBJECTS) $(readelf_OBJECTS) $(nm_new_OBJECTS) $(strip_new_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .dvi .info .l .lo .o .ps .s .texi .texinfo .txi .y +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --cygnus Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status + +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ configure.in acinclude.m4 + cd $(srcdir) && $(ACLOCAL) + +config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck +$(srcdir)/configure: @MAINTAINER_MODE_TRUE@$(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) + cd $(srcdir) && $(AUTOCONF) + +config.h: stamp-h + @if test ! -f $@; then \ + rm -f stamp-h; \ + $(MAKE) stamp-h; \ + else :; fi +stamp-h: $(srcdir)/config.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES= CONFIG_HEADERS=config.h:config.in \ + $(SHELL) ./config.status + @echo timestamp > stamp-h 2> /dev/null +$(srcdir)/config.in: @MAINTAINER_MODE_TRUE@$(srcdir)/stamp-h.in + @if test ! -f $@; then \ + rm -f $(srcdir)/stamp-h.in; \ + $(MAKE) $(srcdir)/stamp-h.in; \ + else :; fi +$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOHEADER) + @echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null + +mostlyclean-hdr: + +clean-hdr: + +distclean-hdr: + -rm -f config.h + +maintainer-clean-hdr: + +mostlyclean-binPROGRAMS: + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) + +distclean-binPROGRAMS: + +maintainer-clean-binPROGRAMS: + +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(bindir) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \ + $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + list='$(bin_PROGRAMS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + done + +mostlyclean-noinstPROGRAMS: + +clean-noinstPROGRAMS: + -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) + +distclean-noinstPROGRAMS: + +maintainer-clean-noinstPROGRAMS: + +.c.o: + $(COMPILE) -c $< + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +.c.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +.s.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +.S.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + +maintainer-clean-libtool: + +nlmconv$(EXEEXT): $(nlmconv_OBJECTS) $(nlmconv_DEPENDENCIES) + @rm -f nlmconv$(EXEEXT) + $(LINK) $(nlmconv_LDFLAGS) $(nlmconv_OBJECTS) $(nlmconv_LDADD) $(LIBS) + +srconv$(EXEEXT): $(srconv_OBJECTS) $(srconv_DEPENDENCIES) + @rm -f srconv$(EXEEXT) + $(LINK) $(srconv_LDFLAGS) $(srconv_OBJECTS) $(srconv_LDADD) $(LIBS) + +sysdump$(EXEEXT): $(sysdump_OBJECTS) $(sysdump_DEPENDENCIES) + @rm -f sysdump$(EXEEXT) + $(LINK) $(sysdump_LDFLAGS) $(sysdump_OBJECTS) $(sysdump_LDADD) $(LIBS) + +coffdump$(EXEEXT): $(coffdump_OBJECTS) $(coffdump_DEPENDENCIES) + @rm -f coffdump$(EXEEXT) + $(LINK) $(coffdump_LDFLAGS) $(coffdump_OBJECTS) $(coffdump_LDADD) $(LIBS) + +dlltool$(EXEEXT): $(dlltool_OBJECTS) $(dlltool_DEPENDENCIES) + @rm -f dlltool$(EXEEXT) + $(LINK) $(dlltool_LDFLAGS) $(dlltool_OBJECTS) $(dlltool_LDADD) $(LIBS) + +windres$(EXEEXT): $(windres_OBJECTS) $(windres_DEPENDENCIES) + @rm -f windres$(EXEEXT) + $(LINK) $(windres_LDFLAGS) $(windres_OBJECTS) $(windres_LDADD) $(LIBS) + +dllwrap$(EXEEXT): $(dllwrap_OBJECTS) $(dllwrap_DEPENDENCIES) + @rm -f dllwrap$(EXEEXT) + $(LINK) $(dllwrap_LDFLAGS) $(dllwrap_OBJECTS) $(dllwrap_LDADD) $(LIBS) + +size$(EXEEXT): $(size_OBJECTS) $(size_DEPENDENCIES) + @rm -f size$(EXEEXT) + $(LINK) $(size_LDFLAGS) $(size_OBJECTS) $(size_LDADD) $(LIBS) + +objdump$(EXEEXT): $(objdump_OBJECTS) $(objdump_DEPENDENCIES) + @rm -f objdump$(EXEEXT) + $(LINK) $(objdump_LDFLAGS) $(objdump_OBJECTS) $(objdump_LDADD) $(LIBS) + +ar$(EXEEXT): $(ar_OBJECTS) $(ar_DEPENDENCIES) + @rm -f ar$(EXEEXT) + $(LINK) $(ar_LDFLAGS) $(ar_OBJECTS) $(ar_LDADD) $(LIBS) + +strings$(EXEEXT): $(strings_OBJECTS) $(strings_DEPENDENCIES) + @rm -f strings$(EXEEXT) + $(LINK) $(strings_LDFLAGS) $(strings_OBJECTS) $(strings_LDADD) $(LIBS) + +ranlib$(EXEEXT): $(ranlib_OBJECTS) $(ranlib_DEPENDENCIES) + @rm -f ranlib$(EXEEXT) + $(LINK) $(ranlib_LDFLAGS) $(ranlib_OBJECTS) $(ranlib_LDADD) $(LIBS) + +c++filt$(EXEEXT): $(c__filt_OBJECTS) $(c__filt_DEPENDENCIES) + @rm -f c++filt$(EXEEXT) + $(LINK) $(c__filt_LDFLAGS) $(c__filt_OBJECTS) $(c__filt_LDADD) $(LIBS) + +objcopy$(EXEEXT): $(objcopy_OBJECTS) $(objcopy_DEPENDENCIES) + @rm -f objcopy$(EXEEXT) + $(LINK) $(objcopy_LDFLAGS) $(objcopy_OBJECTS) $(objcopy_LDADD) $(LIBS) + +addr2line$(EXEEXT): $(addr2line_OBJECTS) $(addr2line_DEPENDENCIES) + @rm -f addr2line$(EXEEXT) + $(LINK) $(addr2line_LDFLAGS) $(addr2line_OBJECTS) $(addr2line_LDADD) $(LIBS) + +readelf$(EXEEXT): $(readelf_OBJECTS) $(readelf_DEPENDENCIES) + @rm -f readelf$(EXEEXT) + $(LINK) $(readelf_LDFLAGS) $(readelf_OBJECTS) $(readelf_LDADD) $(LIBS) + +nm-new$(EXEEXT): $(nm_new_OBJECTS) $(nm_new_DEPENDENCIES) + @rm -f nm-new$(EXEEXT) + $(LINK) $(nm_new_LDFLAGS) $(nm_new_OBJECTS) $(nm_new_LDADD) $(LIBS) + +strip-new$(EXEEXT): $(strip_new_OBJECTS) $(strip_new_DEPENDENCIES) + @rm -f strip-new$(EXEEXT) + $(LINK) $(strip_new_LDFLAGS) $(strip_new_OBJECTS) $(strip_new_LDADD) $(LIBS) +.l.c: + $(SHELL) $(YLWRAP) "$(LEX)" $< $(LEX_OUTPUT_ROOT).c $@ -- $(AM_LFLAGS) $(LFLAGS) +.y.c: + $(SHELL) $(YLWRAP) "$(YACC)" $< y.tab.c $*.c y.tab.h $*.h -- $(AM_YFLAGS) $(YFLAGS) +arparse.h: arparse.c +defparse.h: defparse.c +nlmheader.h: nlmheader.c +rcparse.h: rcparse.c + + +binutils.info: binutils.texi +binutils.dvi: binutils.texi + + +DVIPS = dvips + +.texi.info: + @rm -f $@ $@-[0-9] $@-[0-9][0-9] + $(MAKEINFO) -I $(srcdir) $< + +.texi.dvi: + TEXINPUTS=$(top_srcdir)/../texinfo/texinfo.tex:$$TEXINPUTS \ + MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $< + +.texi: + @rm -f $@ $@-[0-9] $@-[0-9][0-9] + $(MAKEINFO) -I $(srcdir) $< + +.texinfo.info: + @rm -f $@ $@-[0-9] $@-[0-9][0-9] + $(MAKEINFO) -I $(srcdir) $< + +.texinfo: + @rm -f $@ $@-[0-9] $@-[0-9][0-9] + $(MAKEINFO) -I $(srcdir) $< + +.texinfo.dvi: + TEXINPUTS=$(top_srcdir)/../texinfo/texinfo.tex:$$TEXINPUTS \ + MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $< + +.txi.info: + @rm -f $@ $@-[0-9] $@-[0-9][0-9] + $(MAKEINFO) -I $(srcdir) $< + +.txi.dvi: + TEXINPUTS=$(top_srcdir)/../texinfo/texinfo.tex:$$TEXINPUTS \ + MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $< + +.txi: + @rm -f $@ $@-[0-9] $@-[0-9][0-9] + $(MAKEINFO) -I $(srcdir) $< +.dvi.ps: + $(DVIPS) $< -o $@ + +install-info-am: $(INFO_DEPS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(infodir) + @list='$(INFO_DEPS)'; \ + for file in $$list; do \ + if test -f $$file; then d=.; else d=$(srcdir); fi; \ + for ifile in `cd $$d && echo $$file $$file-[0-9] $$file-[0-9][0-9]`; do \ + if test -f $$d/$$ifile; then \ + echo " $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$ifile"; \ + $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$ifile; \ + else : ; fi; \ + done; \ + done + @$(POST_INSTALL) + @if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then \ + list='$(INFO_DEPS)'; \ + for file in $$list; do \ + echo " install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file";\ + install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file || :;\ + done; \ + else : ; fi + +uninstall-info: + $(PRE_UNINSTALL) + @if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then \ + ii=yes; \ + else ii=; fi; \ + list='$(INFO_DEPS)'; \ + for file in $$list; do \ + test -z "$ii" \ + || install-info --info-dir=$(DESTDIR)$(infodir) --remove $$file; \ + done + @$(NORMAL_UNINSTALL) + list='$(INFO_DEPS)'; \ + for file in $$list; do \ + (cd $(DESTDIR)$(infodir) && rm -f $$file $$file-[0-9] $$file-[0-9][0-9]); \ + done + +dist-info: $(INFO_DEPS) + list='$(INFO_DEPS)'; \ + for base in $$list; do \ + if test -f $$base; then d=.; else d=$(srcdir); fi; \ + for file in `cd $$d && eval echo $$base*`; do \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file; \ + done; \ + done + +mostlyclean-aminfo: + -rm -f binutils.aux binutils.cp binutils.cps binutils.dvi binutils.fn \ + binutils.fns binutils.ky binutils.kys binutils.ps \ + binutils.log binutils.pg binutils.toc binutils.tp \ + binutils.tps binutils.vr binutils.vrs binutils.op binutils.tr \ + binutils.cv binutils.cn + +clean-aminfo: + +distclean-aminfo: + +maintainer-clean-aminfo: + for i in $(INFO_DEPS); do \ + rm -f $$i; \ + if test "`echo $$i-[0-9]*`" != "$$i-[0-9]*"; then \ + rm -f $$i-[0-9]*; \ + fi; \ + done +clean-info: mostlyclean-aminfo + +install-man1: + $(mkinstalldirs) $(DESTDIR)$(man1dir) + @list='$(man1_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst"; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst; \ + done + +uninstall-man1: + @list='$(man1_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f $(DESTDIR)$(man1dir)/$$inst"; \ + rm -f $(DESTDIR)$(man1dir)/$$inst; \ + done +install-man: $(MANS) + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-man1 +uninstall-man: + @$(NORMAL_UNINSTALL) + $(MAKE) $(AM_MAKEFLAGS) uninstall-man1 + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. + +@SET_MAKE@ + +all-recursive install-data-recursive install-exec-recursive \ +installdirs-recursive install-recursive uninstall-recursive install-info-recursive \ +check-recursive installcheck-recursive info-recursive dvi-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ + rev="$$subdir $$rev"; \ + test "$$subdir" = "." && dot_seen=yes; \ + done; \ + test "$$dot_seen" = "no" && rev=". $$rev"; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: tags-recursive $(HEADERS) $(SOURCES) config.in $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)config.in$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.in $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + -rm -rf $(distdir) + GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz + mkdir $(distdir)/=build + mkdir $(distdir)/=inst + dc_install_base=`cd $(distdir)/=inst && pwd`; \ + cd $(distdir)/=build \ + && ../configure --srcdir=.. --prefix=$$dc_install_base \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) dist + -rm -rf $(distdir) + @banner="$(distdir).tar.gz is ready for distribution"; \ + dashes=`echo "$$banner" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + echo "$$dashes" +dist: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +dist-all: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +distdir: $(DISTFILES) + -rm -rf $(distdir) + mkdir $(distdir) + -chmod 777 $(distdir) + @for file in $(DISTFILES); do \ + if test -f $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + cp -pr $$/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + for subdir in $(SUBDIRS); do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + chmod 777 $(distdir)/$$subdir; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-info + +RUNTESTFLAGS = + +DEJATOOL = $(PACKAGE) + +RUNTESTDEFAULTFLAGS = --tool $(DEJATOOL) --srcdir $$srcdir +site.exp: Makefile + @echo 'Making a new site.exp file...' + @test ! -f site.bak || rm -f site.bak + @echo '## these variables are automatically generated by make ##' > $@-t + @echo '# Do not edit here. If you wish to override these values' >> $@-t + @echo '# edit the last section' >> $@-t + @echo 'set tool $(DEJATOOL)' >> $@-t + @echo 'set srcdir $(srcdir)' >> $@-t + @echo 'set objdir' `pwd` >> $@-t + @echo 'set host_alias $(host_alias)' >> $@-t + @echo 'set host_triplet $(host_triplet)' >> $@-t + @echo 'set target_alias $(target_alias)' >> $@-t + @echo 'set target_triplet $(target_triplet)' >> $@-t + @echo 'set build_alias $(build_alias)' >> $@-t + @echo 'set build_triplet $(build_triplet)' >> $@-t + @echo '## All variables above are generated by configure. Do Not Edit ##' >> $@-t + @test ! -f site.exp || sed '1,/^## All variables above are.*##/ d' site.exp >> $@-t + @test ! -f site.exp || mv site.exp site.bak + @mv $@-t site.exp +info-am: $(INFO_DEPS) +info: info-recursive +dvi-am: $(DVIS) +dvi: dvi-recursive +check-am: + $(MAKE) $(AM_MAKEFLAGS) check-DEJAGNU +check: check-recursive +installcheck-am: +installcheck: installcheck-recursive +install-info-am: +install-info: install-info-recursive +all-recursive-am: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +install-exec-am: install-binPROGRAMS install-exec-local +install-exec: install-exec-recursive + +install-data-am: install-man +install-data: install-data-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-recursive +uninstall-am: uninstall-binPROGRAMS uninstall-man +uninstall: uninstall-recursive +all-am: Makefile $(PROGRAMS) $(MANS) config.h +all-redirect: all-recursive-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: installdirs-recursive +installdirs-am: + $(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(mandir)/man1 + + +mostlyclean-generic: + -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + -test -z "arlexldeflexlrclexlarparseharparsecdefparsehdefparsecnlmheaderhnlmheadercrcparsehrcparsec$(MAINTAINERCLEANFILES)" || rm -f arlexl deflexl rclexl arparseh arparsec defparseh defparsec nlmheaderh nlmheaderc rcparseh rcparsec $(MAINTAINERCLEANFILES) +mostlyclean-am: mostlyclean-hdr mostlyclean-binPROGRAMS \ + mostlyclean-noinstPROGRAMS mostlyclean-compile \ + mostlyclean-libtool mostlyclean-aminfo mostlyclean-tags \ + mostlyclean-generic mostlyclean-local + +mostlyclean: mostlyclean-recursive + +clean-am: clean-hdr clean-binPROGRAMS clean-noinstPROGRAMS \ + clean-compile clean-libtool clean-aminfo clean-tags \ + clean-generic mostlyclean-am + +clean: clean-recursive + +distclean-am: distclean-hdr distclean-binPROGRAMS \ + distclean-noinstPROGRAMS distclean-compile \ + distclean-libtool distclean-aminfo distclean-tags \ + distclean-generic clean-am + -rm -f libtool + +distclean: distclean-recursive + -rm -f config.status + +maintainer-clean-am: maintainer-clean-hdr maintainer-clean-binPROGRAMS \ + maintainer-clean-noinstPROGRAMS \ + maintainer-clean-compile maintainer-clean-libtool \ + maintainer-clean-aminfo maintainer-clean-tags \ + maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-recursive + -rm -f config.status + +.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \ +mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \ +maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \ +mostlyclean-noinstPROGRAMS distclean-noinstPROGRAMS \ +clean-noinstPROGRAMS maintainer-clean-noinstPROGRAMS \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile mostlyclean-libtool distclean-libtool \ +clean-libtool maintainer-clean-libtool install-info-am uninstall-info \ +mostlyclean-aminfo distclean-aminfo clean-aminfo \ +maintainer-clean-aminfo install-man1 uninstall-man1 install-man \ +uninstall-man install-data-recursive uninstall-data-recursive \ +install-exec-recursive uninstall-exec-recursive installdirs-recursive \ +uninstalldirs-recursive all-recursive check-recursive \ +installcheck-recursive info-recursive dvi-recursive \ +mostlyclean-recursive distclean-recursive clean-recursive \ +maintainer-clean-recursive tags tags-recursive mostlyclean-tags \ +distclean-tags clean-tags maintainer-clean-tags distdir check-DEJAGNU \ +info-am info dvi-am dvi check check-am installcheck-am installcheck \ +install-info-am install-info all-recursive-am install-exec-local \ +install-exec-am install-exec install-data-am install-data install-am \ +install uninstall-am uninstall all-redirect all-am all installdirs-am \ +installdirs mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + +po/POTFILES.in: @MAINT@ Makefile + for file in $(POTFILES); do echo $$file; done | sort > tmp \ + && mv tmp $(srcdir)/po/POTFILES.in + +check-DEJAGNU: site.exp + srcdir=`cd $(srcdir) && pwd`; export srcdir; \ + r=`pwd`; export r; \ + EXPECT=$(EXPECT); export EXPECT; \ + if [ -f $(top_builddir)/../expect/expect ]; then \ + TCL_LIBRARY=`cd $(top_srcdir)/../tcl/library && pwd`; \ + export TCL_LIBRARY; \ + fi; \ + runtest=$(RUNTEST); \ + if $(SHELL) -c "$$runtest --version" > /dev/null 2>&1; then \ + $$runtest --tool $(DEJATOOL) --srcdir $${srcdir}/testsuite \ + CC_FOR_TARGET="$(CC_FOR_TARGET)" \ + CFLAGS_FOR_TARGET="$(CFLAGS)" $(RUNTESTFLAGS); \ + else echo "WARNING: could not find \`runtest'" 1>&2; :;\ + fi + +installcheck: + /bin/sh $(srcdir)/sanity.sh $(bindir) + +underscore.c: stamp-under ; @true + +stamp-under: Makefile + echo '/*WARNING: This file is automatically generated!*/' >underscore.t + echo "int prepends_underscore = @UNDERSCORE@;" >>underscore.t + $(SHELL) $(srcdir)/../move-if-change underscore.t underscore.c + touch stamp-under + +cplus-dem.o: $(BASEDIR)/libiberty/cplus-dem.c $(INCDIR)/getopt.h + $(COMPILE) -c -DMAIN -DVERSION='"$(VERSION)"' $(BASEDIR)/libiberty/cplus-dem.c + +# The following is commented out for the convertion to automake. +# This rule creates a single binary that switches between ar and ranlib +# by looking at argv[0]. Use this kludge to save some disk space. +# However, you have to install things by hand. +# (That is after 'make install', replace the installed ranlib by a link to ar.) +# Alternatively, you can install ranlib.sh as ranlib. +# ar_with_ranlib: $(ADDL_DEPS) ar.o maybe-ranlib.o +# $(HLDENV) $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $(AR_PROG) ar.o maybe-ranlib.o $(ADDL_LIBS) $(EXTRALIBS) +# -rm -f $(RANLIB_PROG) +# -ln $(AR_PROG) $(RANLIB_PROG) +# +# objcopy and strip in one binary that uses argv[0] to decide its action. +# +#objcopy_with_strip: $(ADDL_DEPS) objcopy.o maybe-strip.o +# $(HLDENV) $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $(OBJCOPY_PROG) objcopy.o maybe-strip.o $(ADDL_LIBS) $(EXTRALIBS) +# -rm -f $(STRIP_PROG) +# -ln $(OBJCOPY_PROG) $(STRIP_PROG) + +sysroff.c: sysinfo$(EXEEXT_FOR_BUILD) sysroff.info + ./sysinfo$(EXEEXT_FOR_BUILD) -c <$(srcdir)/sysroff.info >sysroff.c + ./sysinfo$(EXEEXT_FOR_BUILD) -i <$(srcdir)/sysroff.info >>sysroff.c + ./sysinfo$(EXEEXT_FOR_BUILD) -g <$(srcdir)/sysroff.info >>sysroff.c + +sysroff.h: sysinfo$(EXEEXT_FOR_BUILD) sysroff.info + ./sysinfo$(EXEEXT_FOR_BUILD) -d <$(srcdir)/sysroff.info >sysroff.h + +sysinfo$(EXEEXT_FOR_BUILD): sysinfo.o syslex.o + $(CC_FOR_BUILD) $(CFLAGS) $(LDFLAGS) -o $@ sysinfo.o syslex.o + +syslex.o: syslex.c sysinfo.h + if [ -r syslex.c ]; then \ + $(CC_FOR_BUILD) -c -I. $(CFLAGS) syslex.c ; \ + else \ + $(CC_FOR_BUILD) -c -I. -I$(srcdir) $(CFLAGS) $(srcdir)/syslex.c ;\ + fi + +sysinfo.o: sysinfo.c + if [ -r sysinfo.c ]; then \ + $(CC_FOR_BUILD) -c -I. $(CFLAGS) sysinfo.c ; \ + else \ + $(CC_FOR_BUILD) -c -I. $(CFLAGS) $(srcdir)/sysinfo.c ; \ + fi + +dlltool.o:dlltool.c + $(COMPILE) -c $(DLLTOOL_DEFS) $(srcdir)/dlltool.c + +# coff/sym.h and coff/ecoff.h won't be found by the automatic dependency +# scripts, since they are only included conditionally. +nlmconv.o: nlmconv.c $(INCDIR)/coff/sym.h $(INCDIR)/coff/ecoff.h + ldname=`echo ld | sed '$(transform)'`; \ + $(COMPILE) -c -DLD_NAME="\"$${ldname}\"" @NLMCONV_DEFS@ $(srcdir)/nlmconv.c + + +diststuff: $(DISTSTUFF) info + +# Targets to rebuild dependencies in this Makefile. +# Have to get rid of .dep1 here so that "$?" later includes all of $(CFILES). +.dep: dep.sed $(CFILES) $(HFILES) $(GENERATED_CFILES) $(GENERATED_HFILES) config.h + rm -f .dep1 + $(MAKE) DEP=$(DEP) .dep1 + sed -f dep.sed <.dep1 >.dep + +# This rule really wants a mkdep that runs "gcc -MM". +.dep1: $(CFILES) $(GENERATED_CFILES) + rm -f .dep2 + echo '# DO NOT DELETE THIS LINE -- mkdep uses it.' > .dep2 + $(DEP) -f .dep2 $(INCLUDES) $? + $(SHELL) $(srcdir)/../move-if-change .dep2 .dep1 + +dep.sed: dep-in.sed config.status + objdir=`pwd`; \ + sed <$(srcdir)/dep-in.sed >dep.sed \ + -e 's!@INCDIR@!$(INCDIR)!' \ + -e 's!@BFDDIR@!$(BFDDIR)!' \ + -e 's!@SRCDIR@!$(srcdir)!' \ + -e "s!@OBJDIR@!$${objdir}!" + +dep: .dep + sed -e '/^..DO NOT DELETE THIS LINE/,$$d' < Makefile > tmp-Makefile + cat .dep >> tmp-Makefile + $(SHELL) $(srcdir)/../move-if-change tmp-Makefile Makefile + +dep-in: .dep + sed -e '/^..DO NOT DELETE THIS LINE/,$$d' < $(srcdir)/Makefile.in > tmp-Makefile.in + cat .dep >> tmp-Makefile.in + $(SHELL) $(srcdir)/../move-if-change tmp-Makefile.in $(srcdir)/Makefile.in + +dep-am: .dep + sed -e '/^..DO NOT DELETE THIS LINE/,$$d' < $(srcdir)/Makefile.am > tmp-Makefile.am + cat .dep >> tmp-Makefile.am + $(SHELL) $(srcdir)/../move-if-change tmp-Makefile.am $(srcdir)/Makefile.am + +.PHONY: dep dep-in dep-am + +### +# DOCUMENTATION TARGETS +config.texi: Makefile + rm -f config.texi + echo '@set VERSION $(VERSION)' > config.texi + +binutils.dvi: $(srcdir)/binutils.texi config.texi + +binutils.info: $(srcdir)/binutils.texi config.texi + +$(DEMANGLER_PROG).1: cxxfilt.man Makefile + sed -e 's/@PROGRAM@/$(DEMANGLER_PROG)/' < $(srcdir)/cxxfilt.man \ + > $(DEMANGLER_PROG).1 +mostlyclean-local: + -rm -rf tmpdir + +.PHONY: install-exec-local + +install-exec-local: $(bin_PROGRAMS) $(noinst_PROGRAMS) + @list='$(noinst_PROGRAMS)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(bindir)/`echo $$p|sed -e 's/$(EXEEXT)$$//' -e 's/-new//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \ + $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(bindir)/`echo $$p|sed -e 's/$(EXEEXT)$$//' -e 's/-new//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + else :; fi; \ + done + $(mkinstalldirs) $(tooldir)/bin + for i in $(TOOL_PROGS); do \ + if [ -f $$i$(EXEEXT) ]; then \ + j=`echo $$i | sed -e 's/-new//'`; \ + k=`echo $$j | sed '$(transform)'`; \ + if [ "$(bindir)/$$k$(EXEEXT)" != "$(tooldir)/bin/$$j$(EXEEXT)" ]; then \ + rm -f $(tooldir)/bin/$$j$(EXEEXT); \ + ln $(bindir)/$$k$(EXEEXT) $(tooldir)/bin/$$j$(EXEEXT) >/dev/null 2>/dev/null \ + || $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$i$(EXEEXT) $(tooldir)/bin/$$j$(EXEEXT); \ + fi; \ + else true; \ + fi; \ + done + +# What appears below is generated by a hacked mkdep using gcc -MM. + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. + +addr2line.o: addr2line.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/getopt.h $(INCDIR)/libiberty.h $(INCDIR)/demangle.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h +ar.o: ar.c ../bfd/bfd.h $(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h \ + $(INCDIR)/progress.h bucomm.h config.h $(INCDIR)/fopen-same.h \ + $(INCDIR)/aout/ar.h $(BFDDIR)/libbfd.h arsup.h +arsup.o: arsup.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + arsup.h $(INCDIR)/libiberty.h bucomm.h config.h $(INCDIR)/fopen-same.h +bucomm.o: bucomm.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/libiberty.h bucomm.h config.h $(INCDIR)/fopen-same.h +coffdump.o: coffdump.c coffgrok.h bucomm.h config.h \ + $(INCDIR)/fopen-same.h +coffgrok.o: coffgrok.c bucomm.h config.h $(INCDIR)/fopen-same.h \ + $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h \ + coffgrok.h +debug.o: debug.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \ + debug.h +dlltool.o: dlltool.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/libiberty.h bucomm.h config.h $(INCDIR)/fopen-same.h \ + $(INCDIR)/getopt.h $(INCDIR)/demangle.h dlltool.h +filemode.o: filemode.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h +ieee.o: ieee.c ../bfd/bfd.h $(INCDIR)/ansidecl.h $(INCDIR)/ieee.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \ + debug.h budbg.h +is-ranlib.o: is-ranlib.c +is-strip.o: is-strip.c +maybe-ranlib.o: maybe-ranlib.c +maybe-strip.o: maybe-strip.c +nlmconv.o: nlmconv.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/libiberty.h bucomm.h config.h $(INCDIR)/fopen-same.h \ + $(BFDDIR)/libnlm.h $(INCDIR)/nlm/common.h $(INCDIR)/nlm/internal.h \ + $(INCDIR)/nlm/external.h nlmconv.h +nm.o: nm.c ../bfd/bfd.h $(INCDIR)/ansidecl.h $(INCDIR)/progress.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/getopt.h \ + $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def $(INCDIR)/aout/ranlib.h \ + $(INCDIR)/demangle.h $(INCDIR)/libiberty.h +not-ranlib.o: not-ranlib.c +not-strip.o: not-strip.c +objcopy.o: objcopy.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/progress.h bucomm.h config.h $(INCDIR)/fopen-same.h \ + $(INCDIR)/getopt.h $(INCDIR)/libiberty.h budbg.h +objdump.o: objdump.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/getopt.h $(INCDIR)/progress.h bucomm.h config.h \ + $(INCDIR)/fopen-same.h $(INCDIR)/dis-asm.h $(INCDIR)/libiberty.h \ + $(INCDIR)/demangle.h debug.h budbg.h $(INCDIR)/aout/aout64.h +prdbg.o: prdbg.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \ + debug.h budbg.h +rdcoff.o: rdcoff.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/coff/internal.h bucomm.h config.h $(INCDIR)/fopen-same.h \ + $(INCDIR)/libiberty.h $(INCDIR)/demangle.h debug.h \ + budbg.h $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h +rddbg.o: rddbg.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \ + debug.h budbg.h +size.o: size.c ../bfd/bfd.h $(INCDIR)/ansidecl.h $(INCDIR)/getopt.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h +srconv.o: srconv.c bucomm.h config.h $(INCDIR)/fopen-same.h \ + sysroff.h coffgrok.h $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h \ + $(INCDIR)/bfdlink.h sysroff.c +stabs.o: stabs.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \ + $(INCDIR)/demangle.h debug.h budbg.h $(INCDIR)/aout/aout64.h \ + $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def +strings.o: strings.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h +sysdump.o: sysdump.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h sysroff.h \ + sysroff.c +version.o: version.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h +wrstabs.o: wrstabs.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \ + debug.h budbg.h $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab_gnu.h \ + $(INCDIR)/aout/stab.def +windres.o: windres.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/getopt.h bucomm.h config.h $(INCDIR)/fopen-same.h \ + $(INCDIR)/libiberty.h $(INCDIR)/obstack.h windres.h \ + winduni.h +resrc.o: resrc.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \ + windres.h winduni.h +rescoff.o: rescoff.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \ + windres.h winduni.h $(INCDIR)/coff/internal.h $(BFDDIR)/libcoff.h \ + $(INCDIR)/bfdlink.h +resbin.o: resbin.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \ + windres.h winduni.h +winduni.o: winduni.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h winduni.h +readelf.o: readelf.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/elf/common.h $(INCDIR)/elf/external.h $(INCDIR)/elf/internal.h \ + $(INCDIR)/elf/dwarf2.h $(INCDIR)/elf/i386.h $(INCDIR)/elf/reloc-macros.h \ + $(INCDIR)/elf/v850.h $(INCDIR)/elf/ppc.h $(INCDIR)/elf/mips.h \ + $(INCDIR)/elf/alpha.h $(INCDIR)/elf/arm.h $(INCDIR)/elf/m68k.h \ + $(INCDIR)/elf/sparc.h $(INCDIR)/elf/m32r.h $(INCDIR)/elf/d10v.h \ + $(INCDIR)/elf/d30v.h $(INCDIR)/elf/sh.h $(INCDIR)/elf/mn10200.h \ + $(INCDIR)/elf/mn10300.h $(INCDIR)/elf/hppa.h $(INCDIR)/elf/arc.h \ + $(INCDIR)/elf/fr30.h bucomm.h config.h $(INCDIR)/fopen-same.h \ + $(INCDIR)/getopt.h +resres.o: resres.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \ + windres.h winduni.h +dyn-string.o: dyn-string.c config.h $(INCDIR)/ansidecl.h \ + dyn-string.h +dllwrap.o: dllwrap.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/libiberty.h bucomm.h config.h $(INCDIR)/fopen-same.h \ + $(INCDIR)/getopt.h dyn-string.h +rename.o: rename.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h +underscore.o: underscore.c +arparse.o: arparse.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h arsup.h +arlex.o: arlex.c $(INCDIR)/libiberty.h arparse.h +sysroff.o: sysroff.c +sysinfo.o: sysinfo.c +syslex.o: syslex.c sysinfo.h +defparse.o: defparse.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h dlltool.h +deflex.o: deflex.c $(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h \ + defparse.h dlltool.h +nlmheader.o: nlmheader.c ../bfd/bfd.h bucomm.h config.h \ + $(INCDIR)/fopen-same.h $(INCDIR)/nlm/common.h $(INCDIR)/nlm/internal.h \ + nlmconv.h +rcparse.o: rcparse.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \ + windres.h winduni.h +rclex.o: rclex.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ + bucomm.h config.h $(INCDIR)/fopen-same.h $(INCDIR)/libiberty.h \ + windres.h winduni.h rcparse.h + +# IF YOU PUT ANYTHING HERE IT WILL GO AWAY + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/binutils/NEWS b/binutils/NEWS new file mode 100644 index 0000000..76dcebd --- /dev/null +++ b/binutils/NEWS @@ -0,0 +1,163 @@ +-*- text -*- + +Changes in binutils 2.10: + +* objdump support for -mi386:intel which causes disassembly to be displayed with + intel syntax. + +* New program: readelf. This displays the contents of ELF format files, + regardless of target machine. + +* objcopy now takes --change-section-lma, --change-section-vma, and + --change-section-address options. The old --adjust-section-vma option is + equivalent to --change-section-address. The other --adjust-* options are now + renamed to --change-*, although --adjust-* continues to work. + +* dlltool now supports the IMPORTS command. + +* dlltool now takes --export-all-symbols, --no-export-all-symbols, + --exclude-symbols, and --no-default-excludes options. + +Changes in binutils 2.9: + +* Added windres program, which can be used to manipulate resources in WIN32 + files as used on Windows 95 and Windows NT. + +* The objcopy --gap-fill and --pad-to options operate on the LMA rather than + the VMA of the sections. + +* Added S modifier to ar to not build a symbol table. + +Changes in binutils 2.8: + +* The objdump disassembly format has been changed, and hopefully improved. Use + the new --prefix-addresses option to get the old format. There are also new + --disassemble-zeroes and --no-show-raw-insn options which affect disassembler + output. + +* Formats may now be specified as configuration triplets. For example, + objdump -b i386-pc-linux. The triplets are not passed through config.sub, + so they must be in canonical form. + +* Added new addr2line program. This uses the debugging information to convert + an address into a file name and line number within a program. + +* Added --change-leading-char argument to objcopy. + +* Added --weaken argument to objcopy. + +* objdump --dynamic-reloc now works on ELF executables and shared libraries. + +* Added --adjust-vma option to objdump. + +* Added -C/--demangle option to objdump. + +* Added -p/--preserve-dates option to strip and objcopy. + +Changes in binutils 2.7: + +* Added --enable-shared and --enable-commonbfdlib options to configure. + +* Added --debugging argument to objdump and objcopy. + +* Added --defined-only argument to nm. + +* Added --remove-leading-char argument to objcopy. + +* The objdump --line-numbers option is now meaningful with --reloc. + +* Added --line-numbers option to nm. + +* Added --endian/-EB/-EL option to objdump. + +* Added support for Alpha OpenVMS/AXP. + +Changes in binutils 2.6: + +* Added -N/--strip-symbol and -K/--keep-symbol arguments to strip and objcopy. + +* Added several arguments to objcopy to provide some control over how the new + file is laid out in memory. Also added binary output format to BFD to permit + generating plain binary files. + +* Added --start-address and --stop-address options to objdump. + +* ar and ranlib now work on AIX. The tools are now built by default on AIX. + +Changes in binutils 2.5: + +* Changed objdump -dr to dump the relocs interspersed with the assembly + listing, for a more useful listing of relocateable files. + +* Changed objdump -d/--disassemble to only disassemble SEC_CODE sections. + Added -D/--disassemble-all option to disassemble all sections. + +* Added --size-sort option to nm. + +* strip and objcopy should now be able to handle dynamically linked ELF + executables. + +Changes in binutils 2.4: + +* Support for HP-PA (by Jeff Law), i386 Mach (by David Mackenzie), RS/6000 and + PowerPC (except ar and ranlib; by Ian Taylor). + +* Support for Irix 5. + +* Programs `strip' and `objcopy' will not attempt to write dynamically linked + ELF output files, since BFD currently can't create them properly. + +Changes in binutils 2.3: + +* A new --stabs argument has been added to objdump to dump stabs sections in + ELF and COFF files. + +* A new program, nlmconv, has been added. It can convert object files into + Novell NetWare Loadable Modules. + +* The strings program has been added. + +Changes in binutils 2.2: + +* The 'copy' program has been renamed to 'objcopy', for consistency with + 'objdump', and because 'copy' might more plausibly be used as a synonym for + 'cp'. + +* The new stand-alone program c++filt is a filter that converts encoded + (mangled) C++ assembly-level identifiers to user-level names. (Note: This + may get moved to the gcc distribution.) + +* nm -o on an archive now prefixes each line with the archive name, matching + the output from BSD nm. + +* ar (and ld) can now read (but not write) BSD4.4-style archives. + +* New support for H8500, Z8000, and the Hitach SH. + +* Dis-assembler interface changed to allow sharing with gdb. + +* There is new Elf code, but it is not yet ready for general use. + +* There is the beginnings of a test suite. + +Changes in binutils 2.1: + +* There is now support for writing ECOFF files, so ld and the other utilities + should work on Risc/Ultrix and Irix. Please let us know how well this works. + +* ar now automatically creates a symbol table (a __.SYMDEF member, in the BSD + version), if there are any object files in the archive. So running ranlib is + now redundant (unless the non-standard q command is used). This is required + for Posix.2 conformance. + +* The archive-reading code now reads both BSD-style and SYSV-style archives + independently of the selected target format. This is to encourage people to + switch to SYSV-format, which has a number of advantages. + +* The strip and copy programs now have options to remove debug-symbols only + and/or local symbols only. They now also support long options. + + +Local variables: +fill-column: 79 +End: diff --git a/binutils/README b/binutils/README new file mode 100644 index 0000000..4b2d277 --- /dev/null +++ b/binutils/README @@ -0,0 +1,189 @@ +These are the GNU binutils. These are utilities of use when dealing +with object files. + +The linker (ld) is in a separate directory, which should be ../ld. +Linker-specific notes are in ../ld/README. + +As of version 2.5, the assembler (as) is also included in this package, in +../gas. Assembler-specific notes can be found in ../gas/README. + +Recent changes are in ./NEWS, ../ld/NEWS, and ../gas/NEWS. + +Unpacking and Installation -- quick overview +============================================ + +When you unpack the binutils-2.9.tar.gz file, you'll get a directory +called something like `binutils-2.9', which contains various files and +directories. Most of the files in the top directory are for +information and for configuration. The actual source code is in +subdirectories. + +To build binutils, you can just do: + + cd binutils-2.9 + ./configure [options] + make + make install # copies the programs files into /usr/local/bin + # by default. + +This will configure and build all the libraries as well as the +assembler, the binutils, and the linker. + +If you have GNU make, we recommend building in a different directory: + + mkdir objdir + cd objdir + ../binutils-2.9/configure [options] + make + make install + +This relies on the VPATH feature of GNU make. + +By default, the binutils will be configured to support the system on +which they are built. When doing cross development, use the --target +configure option to specify a different target. + +The --enable-targets option adds support for more binary file formats +besides the default. List them as the argument to --enable-targets, +separated by commas. For example: + + ./configure --enable-targets=sun3,rs6000-aix,decstation + +The name 'all' compiles in support for all valid BFD targets (this was +the default in releases before 2.3): + + ./configure --enable-targets=all + +You can also specify the --enable-shared option when you run +configure. This will build the BFD and opcodes libraries as shared +libraries. You can use arguments with the --enable-shared option to +indicate that only certain libraries should be built shared; for +example, --enable-shared=bfd. The only potential shared libraries in +a binutils release are bfd and opcodes. + +The binutils will be linked against the shared libraries. The build +step will attempt to place the correct library in the runtime search +path for the binaries. However, in some cases, after you install the +binaries, you may have to set an environment variable, normally +LD_LIBRARY_PATH, so that the system can find the installed libbfd +shared library. + +To build under openVMS/AXP, see the file makefile.vms in the top level +directory. + +If you don't have ar +==================== + +If your system does not already have an ar program, the normal +binutils build process will not work. In this case, run configure as +usual. Before running make, run this script: + +#!/bin/sh +MAKE_PROG="${MAKE-make}" +MAKE="${MAKE_PROG} AR=true LINK=true" +export MAKE +${MAKE} $* all-libiberty +${MAKE} $* all-intl +${MAKE} $* all-bfd +cd binutils +MAKE="${MAKE_PROG}" +export MAKE +${MAKE} $* ar_DEPENDENCIES= ar_LDADD='../bfd/*.o `cat ../libiberty/required-list ../libiberty/needed-list | sed -e "s,\([^ ][^ ]*\),../libiberty/\1,g"` `if test -f ../intl/gettext.o; then echo '../intl/*.o'; fi`' ar + +This script will build an ar program in binutils/ar. Move binutils/ar +into a directory on your PATH. After doing this, you can run make as +usual to build the complete binutils distribution. You do not need +the ranlib program in order to build the distribution. + +Porting +======= + +Binutils-2.9 supports many different architectures, but there +are many more not supported, including some that were supported +by earlier versions. We are hoping for volunteers to +improve this situation. + +The major effort in porting binutils to a new host and/or target +architecture involves the BFD library. There is some documentation +in ../bfd/doc. The file ../gdb/doc/gdbint.texinfo (distributed +with gdb-4.x) may also be of help. + +Reporting bugs +============== + +Send bug reports and patches to bug-gnu-utils@gnu.org. Always mention +the version number you are running; this is printed by running any of +the binutils with the --version option. We appreciate reports about +bugs, but we do not promise to fix them. + +VMS +=== + +This section was written by Klaus K"ampf <kkaempf@rmi.de>. It +describes how to build and install the binutils on openVMS (Alpha and +Vax). (The BFD library only supports reading Vax object files.) + +Compiling the release: + +To compile the gnu binary utilities and the gnu assembler, you'll +need DEC C or GNU C for openVMS/Alpha. You'll need *both* compilers +on openVMS/Vax. + +Compiling with either DEC C or GNU C works on openVMS/Alpha only. Some +of the opcodes and binutils files trap a bug in the DEC C optimizer, +so these files must be compiled with /noopt. + +Compiling on openVMS/Vax is a bit complicated, as the bfd library traps +a bug in GNU C and the gnu assembler a bug in (my version of) DEC C. + +I never tried compiling with VAX C. + + +You further need GNU Make Version 3.76 or later. This is available +at ftp.progis.de or any GNU archive site. The makefiles assume that +gmake starts gnu make as a foreign command. + +If you're compiling with DEC C or VAX C, you must run + + $ @setup + +before starting gnu-make. This isn't needed with GNU C. + +On the Alpha you can choose the compiler by editing the toplevel +makefile.vms. Either select CC=cc (for DEC C) or CC=gcc (for GNU C) + + +Installing the release + +Provided that your directory setup conforms to the GNU on openVMS +standard, you already have a concealed deviced named 'GNU_ROOT'. +In this case, a simple + + $ gmake install + +suffices to copy all programs and libraries to the proper directories. + +Define the programs as foreign commands by adding these lines to your +login.com: + + $ gas :== $GNU_ROOT:[bin]as.exe + $ size :== $GNU_ROOT:[bin]size.exe + $ nm :== $GNU_ROOT:[bin]nm.exe + $ objdump :== $GNU_ROOT:[bin]objdump.exe + $ strings :== $GNU_ROOT:[bin]strings.exe + +If you have a different directory setup, copy the binary utilities +([.binutils]size.exe, [.binutils]nm.exe, [.binutils]objdump.exe, +and [.binutils]strings.exe) and the gnu assembler and preprocessor +([.gas]as.exe and [.gas]gasp.exe]) to a directory of your choice +and define all programs as foreign commands. + + +If you're satiesfied with the compilation, you may want to remove +unneeded objects and libraries: + + $ gmake clean + + +If you have any problems or questions about the binutils on VMS, feel +free to mail me at kkaempf@rmi.de. diff --git a/binutils/acinclude.m4 b/binutils/acinclude.m4 new file mode 100644 index 0000000..71b09b9 --- /dev/null +++ b/binutils/acinclude.m4 @@ -0,0 +1 @@ +sinclude(../bfd/acinclude.m4) diff --git a/binutils/aclocal.m4 b/binutils/aclocal.m4 new file mode 100644 index 0000000..88a1565 --- /dev/null +++ b/binutils/aclocal.m4 @@ -0,0 +1,1120 @@ +dnl aclocal.m4 generated automatically by aclocal 1.4 + +dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without +dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A +dnl PARTICULAR PURPOSE. + +sinclude(../bfd/acinclude.m4) + +# Do all the work for Automake. This macro actually does too much -- +# some checks are only needed if your package does certain things. +# But this isn't really a big deal. + +# serial 1 + +dnl Usage: +dnl AM_INIT_AUTOMAKE(package,version, [no-define]) + +AC_DEFUN(AM_INIT_AUTOMAKE, +[AC_REQUIRE([AC_PROG_INSTALL]) +PACKAGE=[$1] +AC_SUBST(PACKAGE) +VERSION=[$2] +AC_SUBST(VERSION) +dnl test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) +fi +ifelse([$3],, +AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) +AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])) +AC_REQUIRE([AM_SANITY_CHECK]) +AC_REQUIRE([AC_ARG_PROGRAM]) +dnl FIXME This is truly gross. +missing_dir=`cd $ac_aux_dir && pwd` +AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir) +AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) +AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir) +AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) +AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) +AC_REQUIRE([AC_PROG_MAKE_SET])]) + +# +# Check to make sure that the build environment is sane. +# + +AC_DEFUN(AM_SANITY_CHECK, +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "[$]*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "[$]*" != "X $srcdir/configure conftestfile" \ + && test "[$]*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "[$]2" = conftestfile + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +rm -f conftest* +AC_MSG_RESULT(yes)]) + +dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY) +dnl The program must properly implement --version. +AC_DEFUN(AM_MISSING_PROG, +[AC_MSG_CHECKING(for working $2) +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if ($2 --version) < /dev/null > /dev/null 2>&1; then + $1=$2 + AC_MSG_RESULT(found) +else + $1="$3/missing $2" + AC_MSG_RESULT(missing) +fi +AC_SUBST($1)]) + + +# serial 35 AC_PROG_LIBTOOL +AC_DEFUN(AC_PROG_LIBTOOL, +[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl + +# Save cache, so that ltconfig can load it +AC_CACHE_SAVE + +# Actually configure libtool. ac_aux_dir is where install-sh is found. +CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \ +LD="$LD" NM="$NM" RANLIB="$RANLIB" LN_S="$LN_S" \ +DLLTOOL="$DLLTOOL" AS="$AS" \ +${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \ +$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $host \ +|| AC_MSG_ERROR([libtool configure failed]) + +# Reload cache, that may have been modified by ltconfig +AC_CACHE_LOAD + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltconfig $ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +# Redirect the config.log output again, so that the ltconfig log is not +# clobbered by the next message. +exec 5>>./config.log +]) + +AC_DEFUN(AC_LIBTOOL_SETUP, +[AC_PREREQ(2.13)dnl +AC_REQUIRE([AC_ENABLE_SHARED])dnl +AC_REQUIRE([AC_ENABLE_STATIC])dnl +AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([AC_PROG_RANLIB])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_LD])dnl +AC_REQUIRE([AC_PROG_NM])dnl +AC_REQUIRE([AC_SYS_NM_PARSE])dnl +AC_REQUIRE([AC_SYS_SYMBOL_UNDERSCORE])dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +dnl + +# Check for any special flags to pass to ltconfig. +libtool_flags="--cache-file=$cache_file" +test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared" +test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static" +test "$enable_fast_install" = no && libtool_flags="$libtool_flags --disable-fast-install" +test "$lt_dlopen" = yes && libtool_flags="$libtool_flags --enable-dlopen" +test "$silent" = yes && libtool_flags="$libtool_flags --silent" +test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc" +test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld" + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case "$host" in +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line __oline__ "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case "`/usr/bin/file conftest.o`" in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; + +*-*-cygwin*) + AC_SYS_LIBTOOL_CYGWIN + ;; + +esac + +# enable the --disable-libtool-lock switch + +AC_ARG_ENABLE(libtool-lock, +[ --disable-libtool-lock force libtool not to do file locking], +need_locks=$enableval, +need_locks=yes) + +if test x"$need_locks" = xno; then + libtool_flags="$libtool_flags --disable-lock" +fi +]) + +# AC_LIBTOOL_DLOPEN - check for dlopen support +AC_DEFUN(AC_LIBTOOL_DLOPEN, [lt_dlopen=yes]) + +# AC_ENABLE_SHARED - implement the --enable-shared flag +# Usage: AC_ENABLE_SHARED[(DEFAULT)] +# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to +# `yes'. +AC_DEFUN(AC_ENABLE_SHARED, +[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE(shared, +changequote(<<, >>)dnl +<< --enable-shared[=PKGS] build shared libraries [default=>>AC_ENABLE_SHARED_DEFAULT], +changequote([, ])dnl +[p=${PACKAGE-default} +case "$enableval" in +yes) enable_shared=yes ;; +no) enable_shared=no ;; +*) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac], +enable_shared=AC_ENABLE_SHARED_DEFAULT)dnl +]) + +# AC_DISABLE_SHARED - set the default shared flag to --disable-shared +AC_DEFUN(AC_DISABLE_SHARED, +[AC_ENABLE_SHARED(no)]) + +# AC_ENABLE_STATIC - implement the --enable-static flag +# Usage: AC_ENABLE_STATIC[(DEFAULT)] +# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to +# `yes'. +AC_DEFUN(AC_ENABLE_STATIC, +[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE(static, +changequote(<<, >>)dnl +<< --enable-static[=PKGS] build static libraries [default=>>AC_ENABLE_STATIC_DEFAULT], +changequote([, ])dnl +[p=${PACKAGE-default} +case "$enableval" in +yes) enable_static=yes ;; +no) enable_static=no ;; +*) + enable_static=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac], +enable_static=AC_ENABLE_STATIC_DEFAULT)dnl +]) + +# AC_DISABLE_STATIC - set the default static flag to --disable-static +AC_DEFUN(AC_DISABLE_STATIC, +[AC_ENABLE_STATIC(no)]) + + +# AC_ENABLE_FAST_INSTALL - implement the --enable-fast-install flag +# Usage: AC_ENABLE_FAST_INSTALL[(DEFAULT)] +# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to +# `yes'. +AC_DEFUN(AC_ENABLE_FAST_INSTALL, +[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE(fast-install, +changequote(<<, >>)dnl +<< --enable-fast-install[=PKGS] optimize for fast installation [default=>>AC_ENABLE_FAST_INSTALL_DEFAULT], +changequote([, ])dnl +[p=${PACKAGE-default} +case "$enableval" in +yes) enable_fast_install=yes ;; +no) enable_fast_install=no ;; +*) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac], +enable_fast_install=AC_ENABLE_FAST_INSTALL_DEFAULT)dnl +]) + +# AC_ENABLE_FAST_INSTALL - set the default to --disable-fast-install +AC_DEFUN(AC_DISABLE_FAST_INSTALL, +[AC_ENABLE_FAST_INSTALL(no)]) + + +# AC_PROG_LD - find the path to the GNU or non-GNU linker +AC_DEFUN(AC_PROG_LD, +[AC_ARG_WITH(gnu-ld, +[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]], +test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no) +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +ac_prog=ld +if test "$ac_cv_prog_gcc" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by GCC]) + ac_prog=`($CC -print-prog-name=ld) 2>&5` + case "$ac_prog" in + # Accept absolute paths. +changequote(,)dnl + /* | [A-Za-z]:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' +changequote([,])dnl + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(ac_cv_path_LD, +[if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog"; then + ac_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then + test "$with_gnu_ld" != no && break + else + test "$with_gnu_ld" != yes && break + fi + fi + done + IFS="$ac_save_ifs" +else + ac_cv_path_LD="$LD" # Let the user override the test with a path. +fi]) +LD="$ac_cv_path_LD" +if test -n "$LD"; then + AC_MSG_RESULT($LD) +else + AC_MSG_RESULT(no) +fi +test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) +AC_SUBST(LD) +AC_PROG_LD_GNU +]) + +AC_DEFUN(AC_PROG_LD_GNU, +[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], ac_cv_prog_gnu_ld, +[# I'd rather use --version here, but apparently some GNU ld's only accept -v. +if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then + ac_cv_prog_gnu_ld=yes +else + ac_cv_prog_gnu_ld=no +fi]) +]) + +# AC_PROG_NM - find the path to a BSD-compatible name lister +AC_DEFUN(AC_PROG_NM, +[AC_MSG_CHECKING([for BSD-compatible nm]) +AC_CACHE_VAL(ac_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + ac_cv_path_NM="$NM" +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/nm; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + ac_cv_path_NM="$ac_dir/nm -B" + break + elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + ac_cv_path_NM="$ac_dir/nm -p" + break + else + ac_cv_path_NM=${ac_cv_path_NM="$ac_dir/nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm +fi]) +NM="$ac_cv_path_NM" +AC_MSG_RESULT([$NM]) +AC_SUBST(NM) +]) + +# AC_SYS_NM_PARSE - Check for command to grab the raw symbol name followed +# by C symbol name from nm. +AC_DEFUN(AC_SYS_NM_PARSE, +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_NM])dnl +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output]) +AC_CACHE_VAL(ac_cv_sys_global_symbol_pipe, +[# These are sane defaults that work on at least a few old systems. +# {They come from Ultrix. What could be older than Ultrix?!! ;)} + +changequote(,)dnl +# Character class describing NM global symbol codes. +ac_symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +ac_sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Transform the above into a raw symbol and a C symbol. +ac_symxfrm='\1 \2\3 \3' + +# Transform an extracted symbol line into a proper C declaration +ac_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'" + +# Define system-specific variables. +case "$host_os" in +aix*) + ac_symcode='[BCDT]' + ;; +cygwin* | mingw*) + ac_symcode='[ABCDGISTW]' + ;; +hpux*) + ac_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^. .* \(.*\)$/extern char \1;/p'" + ;; +irix*) + ac_symcode='[BCDEGRST]' + ;; +solaris*) + ac_symcode='[BDT]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then + ac_symcode='[ABCDGISTW]' +fi +changequote([,])dnl + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + ac_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($ac_symcode\)[ ][ ]*\($ac_symprfx\)$ac_sympat$/$ac_symxfrm/p'" + + # Check to see that the pipe works correctly. + ac_pipe_works=no + rm -f conftest.$ac_ext + cat > conftest.$ac_ext <<EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func;return 0;} +EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + ac_nlist=conftest.nm + + if AC_TRY_EVAL(NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist) && test -s "$ac_nlist"; then + + # Try sorting and uniquifying the output. + if sort "$ac_nlist" | uniq > "$ac_nlist"T; then + mv -f "$ac_nlist"T "$ac_nlist" + else + rm -f "$ac_nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if egrep ' nm_test_var$' "$ac_nlist" >/dev/null; then + if egrep ' nm_test_func$' "$ac_nlist" >/dev/null; then + cat <<EOF > conftest.c +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$ac_global_symbol_to_cdecl"' < "$ac_nlist" >> conftest.c' + + cat <<EOF >> conftest.c +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +changequote(,)dnl +lt_preloaded_symbols[] = +changequote([,])dnl +{ +EOF + sed 's/^. \(.*\) \(.*\)$/ {"\2", (lt_ptr_t) \&\2},/' < "$ac_nlist" >> conftest.c + cat <<\EOF >> conftest.c + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftestm.$ac_objext + ac_save_LIBS="$LIBS" + ac_save_CFLAGS="$CFLAGS" + LIBS="conftestm.$ac_objext" + CFLAGS="$CFLAGS$no_builtin_flag" + if AC_TRY_EVAL(ac_link) && test -s conftest; then + ac_pipe_works=yes + else + echo "configure: failed program was:" >&AC_FD_CC + cat conftest.c >&AC_FD_CC + fi + LIBS="$ac_save_LIBS" + CFLAGS="$ac_save_CFLAGS" + else + echo "cannot find nm_test_func in $ac_nlist" >&AC_FD_CC + fi + else + echo "cannot find nm_test_var in $ac_nlist" >&AC_FD_CC + fi + else + echo "cannot run $ac_cv_sys_global_symbol_pipe" >&AC_FD_CC + fi + else + echo "$progname: failed program was:" >&AC_FD_CC + cat conftest.c >&AC_FD_CC + fi + rm -rf conftest* + + # Do not use the global_symbol_pipe unless it works. + if test "$ac_pipe_works" = yes; then + if test x"$ac_symprfx" = x"_"; then + ac_cv_sys_symbol_underscore=yes + else + ac_cv_sys_symbol_underscore=no + fi + break + else + ac_cv_sys_global_symbol_pipe= + fi +done +]) + +ac_result=yes +if test -z "$ac_cv_sys_global_symbol_pipe"; then + ac_result=no +fi +AC_MSG_RESULT($ac_result) +]) + +# AC_SYS_LIBTOOL_CYGWIN - find tools needed on cygwin +AC_DEFUN(AC_SYS_LIBTOOL_CYGWIN, +[AC_CHECK_TOOL(DLLTOOL, dlltool, false) +AC_CHECK_TOOL(AS, as, false) +]) + +# AC_SYS_SYMBOL_UNDERSCORE - does the compiler prefix global symbols +# with an underscore? +AC_DEFUN(AC_SYS_SYMBOL_UNDERSCORE, +[AC_REQUIRE([AC_PROG_NM])dnl +AC_REQUIRE([AC_SYS_NM_PARSE])dnl +AC_MSG_CHECKING([for _ prefix in compiled symbols]) +AC_CACHE_VAL(ac_cv_sys_symbol_underscore, +[ac_cv_sys_symbol_underscore=no +cat > conftest.$ac_ext <<EOF +void nm_test_func(){} +int main(){nm_test_func;return 0;} +EOF +if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + ac_nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist) && test -s "$ac_nlist"; then + # See whether the symbols have a leading underscore. + if egrep '^. _nm_test_func' "$ac_nlist" >/dev/null; then + ac_cv_sys_symbol_underscore=yes + else + if egrep '^. nm_test_func ' "$ac_nlist" >/dev/null; then + : + else + echo "configure: cannot find nm_test_func in $ac_nlist" >&AC_FD_CC + fi + fi + else + echo "configure: cannot run $ac_cv_sys_global_symbol_pipe" >&AC_FD_CC + fi +else + echo "configure: failed program was:" >&AC_FD_CC + cat conftest.c >&AC_FD_CC +fi +rm -rf conftest* +]) +AC_MSG_RESULT($ac_cv_sys_symbol_underscore) +USE_SYMBOL_UNDERSCORE=${ac_cv_sys_symbol_underscore=no} +AC_SUBST(USE_SYMBOL_UNDERSCORE)dnl +]) + +# AC_CHECK_LIBM - check for math library +AC_DEFUN(AC_CHECK_LIBM, [ +AC_CHECK_LIB(mw, _mwvalidcheckl) +AC_CHECK_LIB(m, cos) +]) + +# AC_LIBLTDL_CONVENIENCE[(dir)] - sets LIBLTDL to the link flags for +# the libltdl convenience library, adds --enable-ltdl-convenience to +# the configure arguments. Note that LIBLTDL is not AC_SUBSTed, nor +# is AC_CONFIG_SUBDIRS called. If DIR is not provided, it is assumed +# to be `${top_builddir}/libltdl'. Make sure you start DIR with +# '${top_builddir}/' (note the single quotes!) if your package is not +# flat, and, if you're not using automake, define top_builddir as +# appropriate in the Makefiles. +AC_DEFUN(AC_LIBLTDL_CONVENIENCE, [ + case "$enable_ltdl_convenience" in + no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; + "") enable_ltdl_convenience=yes + ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; + esac + LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdlc.la +]) + +# AC_LIBLTDL_INSTALLABLE[(dir)] - sets LIBLTDL to the link flags for +# the libltdl installable library, and adds --enable-ltdl-install to +# the configure arguments. Note that LIBLTDL is not AC_SUBSTed, nor +# is AC_CONFIG_SUBDIRS called. If DIR is not provided, it is assumed +# to be `${top_builddir}/libltdl'. Make sure you start DIR with +# '${top_builddir}/' (note the single quotes!) if your package is not +# flat, and, if you're not using automake, define top_builddir as +# appropriate in the Makefiles. +# In the future, this macro may have to be called after AC_PROG_LIBTOOL. +AC_DEFUN(AC_LIBLTDL_INSTALLABLE, [ + AC_CHECK_LIB(ltdl, main, LIBLTDL="-lltdl", [ + case "$enable_ltdl_install" in + no) AC_MSG_WARN([libltdl not installed, but installation disabled]) ;; + "") enable_ltdl_install=yes + ac_configure_args="$ac_configure_args --enable-ltdl-install" ;; + esac + ]) + if test x"$enable_ltdl_install" != x"no"; then + LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdl.la + fi +]) + +dnl old names +AC_DEFUN(AM_PROG_LIBTOOL, [indir([AC_PROG_LIBTOOL])])dnl +AC_DEFUN(AM_ENABLE_SHARED, [indir([AC_ENABLE_SHARED], $@)])dnl +AC_DEFUN(AM_ENABLE_STATIC, [indir([AC_ENABLE_STATIC], $@)])dnl +AC_DEFUN(AM_DISABLE_SHARED, [indir([AC_DISABLE_SHARED], $@)])dnl +AC_DEFUN(AM_DISABLE_STATIC, [indir([AC_DISABLE_STATIC], $@)])dnl +AC_DEFUN(AM_PROG_LD, [indir([AC_PROG_LD])])dnl +AC_DEFUN(AM_PROG_NM, [indir([AC_PROG_NM])])dnl +AC_DEFUN(AM_SYS_NM_PARSE, [indir([AC_SYS_NM_PARSE])])dnl +AC_DEFUN(AM_SYS_SYMBOL_UNDERSCORE, [indir([AC_SYS_SYMBOL_UNDERSCORE])])dnl +AC_DEFUN(AM_SYS_LIBTOOL_CYGWIN, [indir([AC_SYS_LIBTOOL_CYGWIN])])dnl + +# Like AC_CONFIG_HEADER, but automatically create stamp file. + +AC_DEFUN(AM_CONFIG_HEADER, +[AC_PREREQ([2.12]) +AC_CONFIG_HEADER([$1]) +dnl When config.status generates a header, we must update the stamp-h file. +dnl This file resides in the same directory as the config header +dnl that is generated. We must strip everything past the first ":", +dnl and everything past the last "/". +AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl +ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>, +<<test -z "<<$>>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>, +<<am_indx=1 +for am_file in <<$1>>; do + case " <<$>>CONFIG_HEADERS " in + *" <<$>>am_file "*<<)>> + echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx + ;; + esac + am_indx=`expr "<<$>>am_indx" + 1` +done<<>>dnl>>) +changequote([,]))]) + + +dnl AM_PROG_LEX +dnl Look for flex, lex or missing, then run AC_PROG_LEX and AC_DECL_YYTEXT +AC_DEFUN(AM_PROG_LEX, +[missing_dir=ifelse([$1],,`cd $ac_aux_dir && pwd`,$1) +AC_CHECK_PROGS(LEX, flex lex, "$missing_dir/missing flex") +AC_PROG_LEX +AC_DECL_YYTEXT]) + +# This file is derived from `gettext.m4'. The difference is that the +# included macros assume Cygnus-style source and build trees. + +# Macro to add for using GNU gettext. +# Ulrich Drepper <drepper@cygnus.com>, 1995. +# +# This file file be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 3 + +AC_DEFUN(CY_WITH_NLS, + [AC_MSG_CHECKING([whether NLS is requested]) + dnl Default is enabled NLS + AC_ARG_ENABLE(nls, + [ --disable-nls do not use Native Language Support], + USE_NLS=$enableval, USE_NLS=yes) + AC_MSG_RESULT($USE_NLS) + AC_SUBST(USE_NLS) + + USE_INCLUDED_LIBINTL=no + + dnl If we use NLS figure out what method + if test "$USE_NLS" = "yes"; then + AC_DEFINE(ENABLE_NLS, 1, [Define to 1 if NLS is requested]) + AC_MSG_CHECKING([whether included gettext is requested]) + AC_ARG_WITH(included-gettext, + [ --with-included-gettext use the GNU gettext library included here], + nls_cv_force_use_gnu_gettext=$withval, + nls_cv_force_use_gnu_gettext=no) + AC_MSG_RESULT($nls_cv_force_use_gnu_gettext) + + nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" + if test "$nls_cv_force_use_gnu_gettext" != "yes"; then + dnl User does not insist on using GNU NLS library. Figure out what + dnl to use. If gettext or catgets are available (in this order) we + dnl use this. Else we have to fall back to GNU NLS library. + dnl catgets is only used if permitted by option --with-catgets. + nls_cv_header_intl= + nls_cv_header_libgt= + CATOBJEXT=NONE + + AC_CHECK_HEADER(libintl.h, + [AC_CACHE_CHECK([for gettext in libc], gt_cv_func_gettext_libc, + [AC_TRY_LINK([#include <libintl.h>], [return (int) gettext ("")], + gt_cv_func_gettext_libc=yes, gt_cv_func_gettext_libc=no)]) + + if test "$gt_cv_func_gettext_libc" != "yes"; then + AC_CHECK_LIB(intl, bindtextdomain, + [AC_CACHE_CHECK([for gettext in libintl], + gt_cv_func_gettext_libintl, + [AC_TRY_LINK([], [return (int) gettext ("")], + gt_cv_func_gettext_libintl=yes, + gt_cv_func_gettext_libintl=no)])]) + fi + + if test "$gt_cv_func_gettext_libc" = "yes" \ + || test "$gt_cv_func_gettext_libintl" = "yes"; then + AC_DEFINE(HAVE_GETTEXT, 1, + [Define as 1 if you have gettext and don't want to use GNU gettext.]) + AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)dnl + if test "$MSGFMT" != "no"; then + AC_CHECK_FUNCS(dcgettext) + AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) + AC_TRY_LINK(, [extern int _nl_msg_cat_cntr; + return _nl_msg_cat_cntr], + [CATOBJEXT=.gmo + DATADIRNAME=share], + [CATOBJEXT=.mo + DATADIRNAME=lib]) + INSTOBJEXT=.mo + fi + fi + ]) + + dnl In the standard gettext, we would now check for catgets. + dnl However, we never want to use catgets for our releases. + + if test "$CATOBJEXT" = "NONE"; then + dnl Neither gettext nor catgets in included in the C library. + dnl Fall back on GNU gettext library. + nls_cv_use_gnu_gettext=yes + fi + fi + + if test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Mark actions used to generate GNU NLS library. + INTLOBJS="\$(GETTOBJS)" + AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], msgfmt) + AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) + AC_SUBST(MSGFMT) + USE_INCLUDED_LIBINTL=yes + CATOBJEXT=.gmo + INSTOBJEXT=.mo + DATADIRNAME=share + INTLDEPS='$(top_builddir)/../intl/libintl.a' + INTLLIBS=$INTLDEPS + LIBS=`echo $LIBS | sed -e 's/-lintl//'` + nls_cv_header_intl=libintl.h + nls_cv_header_libgt=libgettext.h + fi + + dnl Test whether we really found GNU xgettext. + if test "$XGETTEXT" != ":"; then + dnl If it is no GNU xgettext we define it as : so that the + dnl Makefiles still can work. + if $XGETTEXT --omit-header /dev/null 2> /dev/null; then + : ; + else + AC_MSG_RESULT( + [found xgettext programs is not GNU xgettext; ignore it]) + XGETTEXT=":" + fi + fi + + # We need to process the po/ directory. + POSUB=po + else + DATADIRNAME=share + nls_cv_header_intl=libintl.h + nls_cv_header_libgt=libgettext.h + fi + + # If this is used in GNU gettext we have to set USE_NLS to `yes' + # because some of the sources are only built for this goal. + if test "$PACKAGE" = gettext; then + USE_NLS=yes + USE_INCLUDED_LIBINTL=yes + fi + + dnl These rules are solely for the distribution goal. While doing this + dnl we only have to keep exactly one list of the available catalogs + dnl in configure.in. + for lang in $ALL_LINGUAS; do + GMOFILES="$GMOFILES $lang.gmo" + POFILES="$POFILES $lang.po" + done + + dnl Make all variables we use known to autoconf. + AC_SUBST(USE_INCLUDED_LIBINTL) + AC_SUBST(CATALOGS) + AC_SUBST(CATOBJEXT) + AC_SUBST(DATADIRNAME) + AC_SUBST(GMOFILES) + AC_SUBST(INSTOBJEXT) + AC_SUBST(INTLDEPS) + AC_SUBST(INTLLIBS) + AC_SUBST(INTLOBJS) + AC_SUBST(POFILES) + AC_SUBST(POSUB) + ]) + +AC_DEFUN(CY_GNU_GETTEXT, + [AC_REQUIRE([AC_PROG_MAKE_SET])dnl + AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_PROG_RANLIB])dnl + AC_REQUIRE([AC_ISC_POSIX])dnl + AC_REQUIRE([AC_HEADER_STDC])dnl + AC_REQUIRE([AC_C_CONST])dnl + AC_REQUIRE([AC_C_INLINE])dnl + AC_REQUIRE([AC_TYPE_OFF_T])dnl + AC_REQUIRE([AC_TYPE_SIZE_T])dnl + AC_REQUIRE([AC_FUNC_ALLOCA])dnl + AC_REQUIRE([AC_FUNC_MMAP])dnl + + AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h string.h \ +unistd.h values.h sys/param.h]) + AC_CHECK_FUNCS([getcwd munmap putenv setenv setlocale strchr strcasecmp \ +__argz_count __argz_stringify __argz_next]) + + if test "${ac_cv_func_stpcpy+set}" != "set"; then + AC_CHECK_FUNCS(stpcpy) + fi + if test "${ac_cv_func_stpcpy}" = "yes"; then + AC_DEFINE(HAVE_STPCPY, 1, [Define if you have the stpcpy function]) + fi + + AM_LC_MESSAGES + CY_WITH_NLS + + if test "x$CATOBJEXT" != "x"; then + if test "x$ALL_LINGUAS" = "x"; then + LINGUAS= + else + AC_MSG_CHECKING(for catalogs to be installed) + NEW_LINGUAS= + for lang in ${LINGUAS=$ALL_LINGUAS}; do + case "$ALL_LINGUAS" in + *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;; + esac + done + LINGUAS=$NEW_LINGUAS + AC_MSG_RESULT($LINGUAS) + fi + + dnl Construct list of names of catalog files to be constructed. + if test -n "$LINGUAS"; then + for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done + fi + fi + + dnl The reference to <locale.h> in the installed <libintl.h> file + dnl must be resolved because we cannot expect the users of this + dnl to define HAVE_LOCALE_H. + if test $ac_cv_header_locale_h = yes; then + INCLUDE_LOCALE_H="#include <locale.h>" + else + INCLUDE_LOCALE_H="\ +/* The system does not provide the header <locale.h>. Take care yourself. */" + fi + AC_SUBST(INCLUDE_LOCALE_H) + + dnl Determine which catalog format we have (if any is needed) + dnl For now we know about two different formats: + dnl Linux libc-5 and the normal X/Open format + if test -f $srcdir/po2tbl.sed.in; then + if test "$CATOBJEXT" = ".cat"; then + AC_CHECK_HEADER(linux/version.h, msgformat=linux, msgformat=xopen) + + dnl Transform the SED scripts while copying because some dumb SEDs + dnl cannot handle comments. + sed -e '/^#/d' $srcdir/$msgformat-msg.sed > po2msg.sed + fi + dnl po2tbl.sed is always needed. + sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \ + $srcdir/po2tbl.sed.in > po2tbl.sed + fi + + dnl In the intl/Makefile.in we have a special dependency which makes + dnl only sense for gettext. We comment this out for non-gettext + dnl packages. + if test "$PACKAGE" = "gettext"; then + GT_NO="#NO#" + GT_YES= + else + GT_NO= + GT_YES="#YES#" + fi + AC_SUBST(GT_NO) + AC_SUBST(GT_YES) + + MKINSTALLDIRS="\$(srcdir)/../../mkinstalldirs" + AC_SUBST(MKINSTALLDIRS) + + dnl *** For now the libtool support in intl/Makefile is not for real. + l= + AC_SUBST(l) + + dnl Generate list of files to be processed by xgettext which will + dnl be included in po/Makefile. But only do this if the po directory + dnl exists in srcdir. + if test -d $srcdir/po; then + test -d po || mkdir po + if test "x$srcdir" != "x."; then + if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then + posrcprefix="$srcdir/" + else + posrcprefix="../$srcdir/" + fi + else + posrcprefix="../" + fi + rm -f po/POTFILES + sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ + < $srcdir/po/POTFILES.in > po/POTFILES + fi + ]) + +# Search path for a program which passes the given test. +# Ulrich Drepper <drepper@cygnus.com>, 1996. +# +# This file file be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 1 + +dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, +dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) +AC_DEFUN(AM_PATH_PROG_WITH_TEST, +[# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL(ac_cv_path_$1, +[case "[$]$1" in + /*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in ifelse([$5], , $PATH, [$5]); do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if [$3]; then + ac_cv_path_$1="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" +dnl If no 4th arg is given, leave the cache variable unset, +dnl so AC_PATH_PROGS will keep looking. +ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" +])dnl + ;; +esac])dnl +$1="$ac_cv_path_$1" +if test -n "[$]$1"; then + AC_MSG_RESULT([$]$1) +else + AC_MSG_RESULT(no) +fi +AC_SUBST($1)dnl +]) + +# Check whether LC_MESSAGES is available in <locale.h>. +# Ulrich Drepper <drepper@cygnus.com>, 1995. +# +# This file file be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 1 + +AC_DEFUN(AM_LC_MESSAGES, + [if test $ac_cv_header_locale_h = yes; then + AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES, + [AC_TRY_LINK([#include <locale.h>], [return LC_MESSAGES], + am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)]) + if test $am_cv_val_LC_MESSAGES = yes; then + AC_DEFINE(HAVE_LC_MESSAGES, 1, + [Define if your locale.h file contains LC_MESSAGES.]) + fi + fi]) + +# Add --enable-maintainer-mode option to configure. +# From Jim Meyering + +# serial 1 + +AC_DEFUN(AM_MAINTAINER_MODE, +[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) + dnl maintainer-mode is disabled by default + AC_ARG_ENABLE(maintainer-mode, +[ --enable-maintainer-mode enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer], + USE_MAINTAINER_MODE=$enableval, + USE_MAINTAINER_MODE=no) + AC_MSG_RESULT($USE_MAINTAINER_MODE) + AM_CONDITIONAL(MAINTAINER_MODE, test $USE_MAINTAINER_MODE = yes) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST(MAINT)dnl +] +) + +# Define a conditional. + +AC_DEFUN(AM_CONDITIONAL, +[AC_SUBST($1_TRUE) +AC_SUBST($1_FALSE) +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi]) + diff --git a/binutils/addr2line.1 b/binutils/addr2line.1 new file mode 100644 index 0000000..87ce103 --- /dev/null +++ b/binutils/addr2line.1 @@ -0,0 +1,127 @@ +.\" Copyright (c) 1997 Free Software Foundation +.\" See COPYING for conditions for redistribution +.TH addr2line 1 "27 March 1997" "Cygnus Solutions" "GNU Development Tools" +.de BP +.sp +.ti \-.2i +\(** +.. + +.SH NAME +addr2line \- convert addresses into file names and line numbers + +.SH SYNOPSIS +.hy 0 +.na +.TP +.B addr2line +.RB "[\|" "\-b\ "\c +.I bfdname\c +.RB " | " "\-\-target="\c +.I bfdname\c +\&\|] +.RB "[\|" \-C | \-\-demangle "\|]" +.RB "[\|" "\-e\ "\c +.I filename\c +.RB " | " "\-\-exe="\c +.I filename\c +\&\|] +.RB "[\|" \-f | \-\-functions "\|]" +.RB "[\|" \-s | \-\-basenames "\|]" +.RB "[\|" \-H | \-\-help "\|]" +.RB "[\|" \-V | \-\-version "\|]" +.RB "[\|" addr addr ... "\|]" +.ad b +.hy 1 +.SH DESCRIPTION +\c +.B addr2line +translates program addresses into file names and line numbers. Given +an address and an executable, it uses the debugging information in the +executable to figure out which file name and line number are +associated with a given address. + +The executable to use is specified with the +.B \-e +option. The default is +.B a.out\c +\&. + +.B addr2line +has two modes of operation. + +In the first, hexadecimal addresses are specified on the command line, +and +.B addr2line +displays the file name and line number for each address. + +In the second, +.B addr2line +reads hexadecimal addresses from standard input, and prints the file +name and line number for each address on standard output. In this +mode, +.B addr2line +may be used in a pipe to convert dynamically chosen addresses. + +The format of the output is FILENAME:LINENO. The file name and line +number for each address is printed on a separate line. If the +.B \-f +option is used, then each FILENAME:LINENO line is preceded by a +FUNCTIONNAME line which is the name of the function containing the +address. + +If the file name or function name can not be determined, +.B addr2line +will print two question marks in their place. If the line number can +not be determined, +.B addr2line +will print 0. + +.SH OPTIONS +.TP +.BI "\-b " "bfdname"\c +.TP +.BI "\-\-target=" "bfdname" +Specify the object-code format for the object files to be +\c +.I bfdname\c +\&. + +.TP +.B \-C +.TP +.B \-\-demangle +Decode (\fIdemangle\fP) low-level symbol names into user-level names. +Besides removing any initial underscore prepended by the system, this +makes C++ function names readable. + +.TP +.BI "\-e " "filename"\c +.TP +.BI "\-\-exe=" "filename" +Specify the name of the executable for which addresses should be +translated. The default file is +.B a.out\c +\&. + +.TP +.B \-f +.TP +.B \-\-functions +Display function names as well as file and line number information. + +.TP +.B \-s +.TP +.B \-\-basenames +Display only the base of each file name. + +.SH "SEE ALSO" +.RB "`\|" binutils "\|'" +entry in +.B +info\c +\&; +.I +The GNU Binary Utilities\c +\&, Roland H. Pesch (October 1991). diff --git a/binutils/addr2line.c b/binutils/addr2line.c new file mode 100644 index 0000000..3cee867 --- /dev/null +++ b/binutils/addr2line.c @@ -0,0 +1,335 @@ +/* addr2line.c -- convert addresses to line number and function name + Copyright 1997, 1998, 1999 Free Software Foundation, Inc. + Contributed by Ulrich Lauther <Ulrich.Lauther@zfe.siemens.de> + + This file is part of GNU Binutils. + + 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, 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Derived from objdump.c and nm.c by Ulrich.Lauther@zfe.siemens.de + + Usage: + addr2line [options] addr addr ... + or + addr2line [options] + + both forms write results to stdout, the second form reads addresses + to be converted from stdin. */ + +#include <ctype.h> +#include <string.h> + +#include "bfd.h" +#include "getopt.h" +#include "libiberty.h" +#include "demangle.h" +#include "bucomm.h" + +extern char *program_version; + +static boolean with_functions; /* -f, show function names. */ +static boolean do_demangle; /* -C, demangle names. */ +static boolean base_names; /* -s, strip directory names. */ + +static int naddr; /* Number of addresses to process. */ +static char **addr; /* Hex addresses to process. */ + +static asymbol **syms; /* Symbol table. */ + +static struct option long_options[] = +{ + {"basenames", no_argument, NULL, 's'}, + {"demangle", no_argument, NULL, 'C'}, + {"exe", required_argument, NULL, 'e'}, + {"functions", no_argument, NULL, 'f'}, + {"target", required_argument, NULL, 'b'}, + {"help", no_argument, NULL, 'H'}, + {"version", no_argument, NULL, 'V'}, + {0, no_argument, 0, 0} +}; + +static void usage PARAMS ((FILE *, int)); +static void slurp_symtab PARAMS ((bfd *)); +static void find_address_in_section PARAMS ((bfd *, asection *, PTR)); +static void translate_addresses PARAMS ((bfd *)); +static void process_file PARAMS ((const char *, const char *)); + +/* Print a usage message to STREAM and exit with STATUS. */ + +static void +usage (stream, status) + FILE *stream; + int status; +{ + fprintf (stream, _("\ +Usage: %s [-CfsHV] [-b bfdname] [--target=bfdname]\n\ + [-e executable] [--exe=executable] [--demangle]\n\ + [--basenames] [--functions] [addr addr ...]\n"), + program_name); + list_supported_targets (program_name, stream); + if (status == 0) + fprintf (stream, _("Report bugs to bug-gnu-utils@gnu.org\n")); + exit (status); +} + +/* Read in the symbol table. */ + +static void +slurp_symtab (abfd) + bfd *abfd; +{ + long storage; + long symcount; + + if ((bfd_get_file_flags (abfd) & HAS_SYMS) == 0) + return; + + storage = bfd_get_symtab_upper_bound (abfd); + if (storage < 0) + bfd_fatal (bfd_get_filename (abfd)); + + syms = (asymbol **) xmalloc (storage); + + symcount = bfd_canonicalize_symtab (abfd, syms); + if (symcount < 0) + bfd_fatal (bfd_get_filename (abfd)); +} + +/* These global variables are used to pass information between + translate_addresses and find_address_in_section. */ + +static bfd_vma pc; +static const char *filename; +static const char *functionname; +static unsigned int line; +static boolean found; + +/* Look for an address in a section. This is called via + bfd_map_over_sections. */ + +static void +find_address_in_section (abfd, section, data) + bfd *abfd; + asection *section; + PTR data; +{ + bfd_vma vma; + bfd_size_type size; + + if (found) + return; + + if ((bfd_get_section_flags (abfd, section) & SEC_ALLOC) == 0) + return; + + vma = bfd_get_section_vma (abfd, section); + if (pc < vma) + return; + + size = bfd_get_section_size_before_reloc (section); + if (pc >= vma + size) + return; + + found = bfd_find_nearest_line (abfd, section, syms, pc - vma, + &filename, &functionname, &line); +} + +/* Read hexadecimal addresses from stdin, translate into + file_name:line_number and optionally function name. */ + +static void +translate_addresses (abfd) + bfd *abfd; +{ + int read_stdin = (naddr == 0); + + for (;;) + { + if (read_stdin) + { + char addr_hex[100]; + + if (fgets (addr_hex, sizeof addr_hex, stdin) == NULL) + break; + pc = bfd_scan_vma (addr_hex, NULL, 16); + } + else + { + if (naddr <= 0) + break; + --naddr; + pc = bfd_scan_vma (*addr++, NULL, 16); + } + + found = false; + bfd_map_over_sections (abfd, find_address_in_section, (PTR) NULL); + + if (! found) + { + if (with_functions) + printf ("??\n"); + printf ("??:0\n"); + } + else + { + if (with_functions) + { + if (functionname == NULL || *functionname == '\0') + printf ("??\n"); + else if (! do_demangle) + printf ("%s\n", functionname); + else + { + char *res; + + res = cplus_demangle (functionname, DMGL_ANSI | DMGL_PARAMS); + if (res == NULL) + printf ("%s\n", functionname); + else + { + printf ("%s\n", res); + free (res); + } + } + } + + if (base_names && filename != NULL) + { + char *h; + + h = strrchr (filename, '/'); + if (h != NULL) + filename = h + 1; + } + + printf ("%s:%u\n", filename ? filename : "??", line); + } + + /* fflush() is essential for using this command as a server + child process that reads addresses from a pipe and responds + with line number information, processing one address at a + time. */ + fflush (stdout); + } +} + +/* Process a file. */ + +static void +process_file (filename, target) + const char *filename; + const char *target; +{ + bfd *abfd; + char **matching; + + abfd = bfd_openr (filename, target); + if (abfd == NULL) + bfd_fatal (filename); + + if (bfd_check_format (abfd, bfd_archive)) + fatal (_("%s: can not get addresses from archive"), filename); + + if (! bfd_check_format_matches (abfd, bfd_object, &matching)) + { + bfd_nonfatal (bfd_get_filename (abfd)); + if (bfd_get_error () == bfd_error_file_ambiguously_recognized) + { + list_matching_formats (matching); + free (matching); + } + xexit (1); + } + + slurp_symtab (abfd); + + translate_addresses (abfd); + + if (syms != NULL) + { + free (syms); + syms = NULL; + } + + bfd_close (abfd); +} + +int +main (argc, argv) + int argc; + char **argv; +{ + char *filename; + char *target; + int c; + +#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) + setlocale (LC_MESSAGES, ""); +#endif + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + + program_name = *argv; + xmalloc_set_program_name (program_name); + + bfd_init (); + set_default_bfd_target (); + + filename = NULL; + target = NULL; + while ((c = getopt_long (argc, argv, "b:Ce:sfHV", long_options, (int *) 0)) + != EOF) + { + switch (c) + { + case 0: + break; /* we've been given a long option */ + case 'b': + target = optarg; + break; + case 'C': + do_demangle = true; + break; + case 'e': + filename = optarg; + break; + case 's': + base_names = true; + break; + case 'f': + with_functions = true; + break; + case 'V': + print_version ("addr2line"); + break; + case 'H': + usage (stdout, 0); + break; + default: + usage (stderr, 1); + break; + } + } + + if (filename == NULL) + filename = "a.out"; + + addr = argv + optind; + naddr = argc - optind; + + process_file (filename, target); + + return 0; +} diff --git a/binutils/ar.1 b/binutils/ar.1 new file mode 100644 index 0000000..e4e8cff --- /dev/null +++ b/binutils/ar.1 @@ -0,0 +1,509 @@ +.\" Copyright (c) 1991 Free Software Foundation +.\" See section COPYING for conditions for redistribution +.TH ar 1 "5 November 1991" "cygnus support" "GNU Development Tools" +.de BP +.sp +.ti \-.2i +\(** +.. + +.SH NAME +ar \- create, modify, and extract from archives. + +.SH SYNOPSIS +.hy 0 +.na +.BR ar " [\|" "-" "\|]"\c +.I {dmpqrtx}[abcilosSuvV] \c +[\|\c +.I membername\c +\&\|] \c +.I archive\c +\& \c +.I files\c +\&.\|.\|. + +.ad b +.hy 1 +.SH DESCRIPTION +The GNU \c +.B ar\c +\& program creates, modifies, and extracts from +archives. An \c +.I archive\c +\& is a single file holding a collection of +other files in a structure that makes it possible to retrieve +the original individual files (called \c +.I members\c +\& of the archive). + +The original files' contents, mode (permissions), timestamp, owner, and +group are preserved in the archive, and may be reconstituted on +extraction. + +GNU \c +.B ar\c +\& can maintain archives whose members have names of any +length; however, depending on how \c +.B ar\c +\& is configured on your +system, a limit on member-name length may be imposed (for compatibility +with archive formats maintained with other tools). If it exists, the +limit is often 15 characters (typical of formats related to a.out) or 16 +characters (typical of formats related to coff). + +\c +.B ar\c +\& is considered a binary utility because archives of this sort +are most often used as \c +.I libraries\c +\& holding commonly needed +subroutines. + +\c +.B ar\c +\& will create an index to the symbols defined in relocatable +object modules in the archive when you specify the modifier `\|\c +.B s\c +\|'. +Once created, this index is updated in the archive whenever \c +.B ar\c +\& +makes a change to its contents (save for the `\|\c +.B q\c +\|' update operation). +An archive with such an index speeds up linking to the library, and +allows routines in the library to call each other without regard to +their placement in the archive. + +You may use `\|\c +.B nm \-s\c +\|' or `\|\c +.B nm \-\-print\-armap\c +\|' to list this index +table. If an archive lacks the table, another form of \c +.B ar\c +\& called +\c +.B ranlib\c +\& can be used to add just the table. + +\c +.B ar\c +\& insists on at least two arguments to execute: one +keyletter specifying the \c +.I operation\c +\& (optionally accompanied by other +keyletters specifying \c +.I modifiers\c +\&), and the archive name to act on. + +Most operations can also accept further \c +.I files\c +\& arguments, +specifying particular files to operate on. + +.SH OPTIONS +GNU \c +.B ar\c +\& allows you to mix the operation code \c +.I p\c +\& and modifier +flags \c +.I mod\c +\& in any order, within the first command-line argument. + +If you wish, you may begin the first command-line argument with a +dash. + +The \c +.I p\c +\& keyletter specifies what operation to execute; it may be +any of the following, but you must specify only one of them: + +.TP +.B d +\c +.I Delete\c +\& modules from the archive. Specify the names of modules to +be deleted as \c +.I files\c +\&; the archive is untouched if you +specify no files to delete. + +If you specify the `\|\c +.B v\c +\|' modifier, \c +.B ar\c +\& will list each module +as it is deleted. + +.TP +.B m +Use this operation to \c +.I move\c +\& members in an archive. + +The ordering of members in an archive can make a difference in how +programs are linked using the library, if a symbol is defined in more +than one member. + +If no modifiers are used with \c +.B m\c +\&, any members you name in the +\c +.I files\c +\& arguments are moved to the \c +.I end\c +\& of the archive; +you can use the `\|\c +.B a\c +\|', `\|\c +.B b\c +\|', or `\|\c +.B i\c +\|' modifiers to move them to a +specified place instead. + +.TP +.B p +\c +.I Print\c +\& the specified members of the archive, to the standard +output file. If the `\|\c +.B v\c +\|' modifier is specified, show the member +name before copying its contents to standard output. + +If you specify no \c +.I files\c +\&, all the files in the archive are printed. + +.TP +.B q +\c +.I Quick append\c +\&; add \c +.I files\c +\& to the end of \c +.I archive\c +\&, +without checking for replacement. + +The modifiers `\|\c +.B a\c +\|', `\|\c +.B b\c +\|', and `\|\c +.B i\c +\|' do \c +.I not\c +\& affect this +operation; new members are always placed at the end of the archive. + +The modifier `\|\c +.B v\c +\|' makes \c +.B ar\c +\& list each file as it is appended. + +Since the point of this operation is speed, the archive's symbol table +index is not updated, even if it already existed; you can use `\|\c +.B ar s\c +\|' or +\c +.B ranlib\c +\& explicitly to update the symbol table index. + +However, too many different systems assume quick append rebuilds the +index, so GNU +.B ar +implements `\|\c +.B q\c +\|' as a synonym for `\|\c +.B r\c +\|'. + +.TP +.B r +Insert \c +.I files\c +\& into \c +.I archive\c +\& (with \c +.I replacement\c +\&). This +operation differs from `\|\c +.B q\c +\|' in that any previously existing members +are deleted if their names match those being added. + +If one of the files named in \c +.I files\c +\& doesn't exist, \c +.B ar\c +\& +displays an error message, and leaves undisturbed any existing members +of the archive matching that name. + +By default, new members are added at the end of the file; but you may +use one of the modifiers `\|\c +.B a\c +\|', `\|\c +.B b\c +\|', or `\|\c +.B i\c +\|' to request +placement relative to some existing member. + +The modifier `\|\c +.B v\c +\|' used with this operation elicits a line of +output for each file inserted, along with one of the letters `\|\c +.B a\c +\|' or +`\|\c +.B r\c +\|' to indicate whether the file was appended (no old member +deleted) or replaced. + +.TP +.B t +Display a \c +.I table\c +\& listing the contents of \c +.I archive\c +\&, or those +of the files listed in \c +.I files\c +\& that are present in the +archive. Normally only the member name is shown; if you also want to +see the modes (permissions), timestamp, owner, group, and size, you can +request that by also specifying the `\|\c +.B v\c +\|' modifier. + +If you do not specify any \c +.I files\c +\&, all files in the archive +are listed. + +If there is more than one file with the same name (say, `\|\c +.B fie\c +\|') in +an archive (say `\|\c +.B b.a\c +\|'), `\|\c +.B ar t b.a fie\c +\|' will list only the +first instance; to see them all, you must ask for a complete +listing\(em\&in our example, `\|\c +.B ar t b.a\c +\|'. + +.TP +.B x +\c +.I Extract\c +\& members (named \c +.I files\c +\&) from the archive. You can +use the `\|\c +.B v\c +\|' modifier with this operation, to request that +\c +.B ar\c +\& list each name as it extracts it. + +If you do not specify any \c +.I files\c +\&, all files in the archive +are extracted. + +.PP + +A number of modifiers (\c +.I mod\c +\&) may immediately follow the \c +.I p\c +\& +keyletter, to specify variations on an operation's behavior: + +.TP +.B a +Add new files \c +.I after\c +\& an existing member of the +archive. If you use the modifier \c +.B a\c +\&, the name of an existing archive +member must be present as the \c +.I membername\c +\& argument, before the +\c +.I archive\c +\& specification. + +.TP +.B b +Add new files \c +.I before\c +\& an existing member of the +archive. If you use the modifier \c +.B b\c +\&, the name of an existing archive +member must be present as the \c +.I membername\c +\& argument, before the +\c +.I archive\c +\& specification. (same as `\|\c +.B i\c +\|'). + +.TP +.B c +\c +.I Create\c +\& the archive. The specified \c +.I archive\c +\& is always +created if it didn't exist, when you request an update. But a warning is +issued unless you specify in advance that you expect to create it, by +using this modifier. + +.TP +.B f +Truncate names in the archive. +.B ar +will normally permit file names of any length. This will cause it to +create archives which are not compatible with the native +.B ar +program on some systems. If this is a concern, the +.B f +modifier may be used to truncate file names when putting them in the +archive. + +.TP +.B i +Insert new files \c +.I before\c +\& an existing member of the +archive. If you use the modifier \c +.B i\c +\&, the name of an existing archive +member must be present as the \c +.I membername\c +\& argument, before the +\c +.I archive\c +\& specification. (same as `\|\c +.B b\c +\|'). + +.TP +.B l +This modifier is accepted but not used. + +.TP +.B o +Preserve the \c +.I original\c +\& dates of members when extracting them. If +you do not specify this modifier, files extracted from the archive +will be stamped with the time of extraction. + +.TP +.B s +Write an object-file index into the archive, or update an existing one, +even if no other change is made to the archive. You may use this modifier +flag either with any operation, or alone. Running `\|\c +.B ar s\c +\|' on an +archive is equivalent to running `\|\c +.B ranlib\c +\|' on it. + +.TP +.B S +Do not generate an archive symbol table. This can speed up building a +large library in several steps. The resulting archive can not be used +with the linker. In order to build a symbol table, you must omit the +`\|\c +.B S\c +\|' modifier on the last execution of `\|\c +.B ar\c +\|', or you must run `\|\c +.B ranlib\c +\|' on the archive. + +.TP +.B u +Normally, \c +.B ar r\c +\&.\|.\|. inserts all files +listed into the archive. If you would like to insert \c +.I only\c +\& those +of the files you list that are newer than existing members of the same +names, use this modifier. The `\|\c +.B u\c +\|' modifier is allowed only for the +operation `\|\c +.B r\c +\|' (replace). In particular, the combination `\|\c +.B qu\c +\|' is +not allowed, since checking the timestamps would lose any speed +advantage from the operation `\|\c +.B q\c +\|'. + +.TP +.B v +This modifier requests the \c +.I verbose\c +\& version of an operation. Many +operations display additional information, such as filenames processed, +when the modifier `\|\c +.B v\c +\|' is appended. + +.TP +.B V +This modifier shows the version number of +.BR ar . + +.PP + +.SH "SEE ALSO" +.RB "`\|" binutils "\|'" +entry in +.B +info\c +\&; +.I +The GNU Binary Utilities\c +, Roland H. Pesch (October 1991). +.BR nm ( 1 )\c +\&, +.BR ranlib ( 1 )\c +\&. + +.SH COPYING +Copyright (c) 1991 Free Software Foundation, Inc. +.PP +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. +.PP +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the +entire resulting derived work is distributed under the terms of a +permission notice identical to this one. +.PP +Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be included in +translations approved by the Free Software Foundation instead of in +the original English. diff --git a/binutils/ar.c b/binutils/ar.c new file mode 100644 index 0000000..c951ef7 --- /dev/null +++ b/binutils/ar.c @@ -0,0 +1,1338 @@ +/* ar.c - Archive modify and extract. + Copyright 1991, 92, 93, 94, 95, 96, 97, 98, 1999 + Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* + Bugs: should use getopt the way tar does (complete w/optional -) and + should have long options too. GNU ar used to check file against filesystem + in quick_update and replace operations (would check mtime). Doesn't warn + when name truncated. No way to specify pos_end. Error messages should be + more consistant. +*/ +#include "bfd.h" +#include "libiberty.h" +#include "progress.h" +#include "bucomm.h" +#include "aout/ar.h" +#include "libbfd.h" +#include "arsup.h" +#include <sys/stat.h> + +#ifdef __GO32___ +#define EXT_NAME_LEN 3 /* bufflen of addition to name if it's MS-DOS */ +#else +#define EXT_NAME_LEN 6 /* ditto for *NIX */ +#endif + +#define BUFSIZE 8192 + +/* Kludge declaration from BFD! This is ugly! FIXME! XXX */ + +struct ar_hdr * + bfd_special_undocumented_glue PARAMS ((bfd * abfd, const char *filename)); + +/* Static declarations */ + +static void +mri_emul PARAMS ((void)); + +static const char * +normalize PARAMS ((const char *, bfd *)); + +static void +remove_output PARAMS ((void)); + +static void +map_over_members PARAMS ((bfd *, void (*)(bfd *), char **, int)); + +static void +print_contents PARAMS ((bfd * member)); + +static void +delete_members PARAMS ((bfd *, char **files_to_delete)); + +#if 0 +static void +do_quick_append PARAMS ((const char *archive_filename, + char **files_to_append)); +#endif + +static void +move_members PARAMS ((bfd *, char **files_to_move)); + +static void +replace_members PARAMS ((bfd *, char **files_to_replace, boolean quick)); + +static void +print_descr PARAMS ((bfd * abfd)); + +static void +write_archive PARAMS ((bfd *)); + +static void +ranlib_only PARAMS ((const char *archname)); + +static void +ranlib_touch PARAMS ((const char *archname)); + +static void +usage PARAMS ((int)); + +/** Globals and flags */ + +int mri_mode; + +/* This flag distinguishes between ar and ranlib: + 1 means this is 'ranlib'; 0 means this is 'ar'. + -1 means if we should use argv[0] to decide. */ +extern int is_ranlib; + +/* Nonzero means don't warn about creating the archive file if necessary. */ +int silent_create = 0; + +/* Nonzero means describe each action performed. */ +int verbose = 0; + +/* Nonzero means preserve dates of members when extracting them. */ +int preserve_dates = 0; + +/* Nonzero means don't replace existing members whose dates are more recent + than the corresponding files. */ +int newer_only = 0; + +/* Controls the writing of an archive symbol table (in BSD: a __.SYMDEF + member). -1 means we've been explicitly asked to not write a symbol table; + +1 means we've been explictly asked to write it; + 0 is the default. + Traditionally, the default in BSD has been to not write the table. + However, for POSIX.2 compliance the default is now to write a symbol table + if any of the members are object files. */ +int write_armap = 0; + +/* Nonzero means it's the name of an existing member; position new or moved + files with respect to this one. */ +char *posname = NULL; + +/* Sez how to use `posname': pos_before means position before that member. + pos_after means position after that member. pos_end means always at end. + pos_default means default appropriately. For the latter two, `posname' + should also be zero. */ +enum pos + { + pos_default, pos_before, pos_after, pos_end + } postype = pos_default; + +static bfd ** +get_pos_bfd PARAMS ((bfd **, enum pos, const char *)); + +/* Whether to truncate names of files stored in the archive. */ +static boolean ar_truncate = false; + +int interactive = 0; + +static void +mri_emul () +{ + interactive = isatty (fileno (stdin)); + yyparse (); +} + +/* If COUNT is 0, then FUNCTION is called once on each entry. If nonzero, + COUNT is the length of the FILES chain; FUNCTION is called on each entry + whose name matches one in FILES. */ + +static void +map_over_members (arch, function, files, count) + bfd *arch; + void (*function) PARAMS ((bfd *)); + char **files; + int count; +{ + bfd *head; + + if (count == 0) + { + for (head = arch->next; head; head = head->next) + { + PROGRESS (1); + function (head); + } + return; + } + /* This may appear to be a baroque way of accomplishing what we want. + However we have to iterate over the filenames in order to notice where + a filename is requested but does not exist in the archive. Ditto + mapping over each file each time -- we want to hack multiple + references. */ + + for (; count > 0; files++, count--) + { + boolean found = false; + + for (head = arch->next; head; head = head->next) + { + PROGRESS (1); + if (head->filename == NULL) + { + /* Some archive formats don't get the filenames filled in + until the elements are opened. */ + struct stat buf; + bfd_stat_arch_elt (head, &buf); + } + if ((head->filename != NULL) && + (!strcmp (*files, head->filename))) + { + found = true; + function (head); + } + } + if (!found) + /* xgettext:c-format */ + fprintf (stderr, _("no entry %s in archive\n"), *files); + } +} + +boolean operation_alters_arch = false; + +static void +usage (help) + int help; +{ + FILE *s; + + s = help ? stdout : stderr; + + if (! is_ranlib) + { + /* xgettext:c-format */ + fprintf (s, _("Usage: %s [-]{dmpqrstx}[abcilosSuvV] [member-name] archive-file file...\n"), program_name); + /* xgettext:c-format */ + fprintf (s, _(" %s -M [<mri-script]\n"), program_name); + fprintf (s, _(" commands:\n")); + fprintf (s, _(" d - delete file(s) from the archive\n")); + fprintf (s, _(" m[ab] - move file(s) in the archive\n")); + fprintf (s, _(" p - print file(s) found in the archive\n")); + fprintf (s, _(" q[f] - quick append file(s) to the archive\n")); + fprintf (s, _(" r[ab][f][u] - replace existing or insert new file(s) into the archive\n")); + fprintf (s, _(" t - display contents of archive\n")); + fprintf (s, _(" x[o] - extract file(s) from the archive\n")); + fprintf (s, _(" command specific modifiers:\n")); + fprintf (s, _(" [a] - put file(s) after [member-name]\n")); + fprintf (s, _(" [b] - put file(s) before [member-name] (same as [i])\n")); + fprintf (s, _(" [f] - truncate inserted file names\n")); + fprintf (s, _(" [o] - preserve original dates\n")); + fprintf (s, _(" [u] - only replace files that are newer than current archive contents\n")); + fprintf (s, _(" generic modifiers:\n")); + fprintf (s, _(" [c] - do not warn if the library had to be created\n")); + fprintf (s, _(" [s] - create an archive index (cf. ranlib)\n")); + fprintf (s, _(" [S] - do not build a symbol table\n")); + fprintf (s, _(" [v] - be verbose\n")); + fprintf (s, _(" [V] - display the version number\n")); + } + else + /* xgettext:c-format */ + fprintf (s, _("Usage: %s [-vV] archive\n"), program_name); + + list_supported_targets (program_name, stderr); + + if (help) + fprintf (s, _("Report bugs to bug-gnu-utils@gnu.org\n")); + + xexit (help ? 0 : 1); +} + +/* Normalize a file name specified on the command line into a file + name which we will use in an archive. */ + +static const char * +normalize (file, abfd) + const char *file; + bfd *abfd; +{ + const char *filename; + + filename = strrchr (file, '/'); + if (filename != (char *) NULL) + filename++; + else + filename = file; + + if (ar_truncate + && abfd != NULL + && strlen (filename) > abfd->xvec->ar_max_namelen) + { + char *s; + + /* Space leak. */ + s = (char *) xmalloc (abfd->xvec->ar_max_namelen + 1); + memcpy (s, filename, abfd->xvec->ar_max_namelen); + s[abfd->xvec->ar_max_namelen] = '\0'; + filename = s; + } + + return filename; +} + +/* Remove any output file. This is only called via xatexit. */ + +static char *output_filename = NULL; +static FILE *output_file = NULL; +static bfd *output_bfd = NULL; + +static void +remove_output () +{ + if (output_filename != NULL) + { + if (output_bfd != NULL && output_bfd->iostream != NULL) + fclose ((FILE *) (output_bfd->iostream)); + if (output_file != NULL) + fclose (output_file); + unlink (output_filename); + } +} + +/* The option parsing should be in its own function. + It will be when I have getopt working. */ + +int +main (argc, argv) + int argc; + char **argv; +{ + char *arg_ptr; + char c; + enum + { + none = 0, delete, replace, print_table, + print_files, extract, move, quick_append + } operation = none; + int arg_index; + char **files; + char *inarch_filename; + int show_version; + +#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) + setlocale (LC_MESSAGES, ""); +#endif + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + + program_name = argv[0]; + xmalloc_set_program_name (program_name); + + if (is_ranlib < 0) + { + char *temp; + + temp = strrchr (program_name, '/'); + if (temp == NULL) + temp = program_name; + else + ++temp; + if (strlen (temp) >= 6 + && strcmp (temp + strlen (temp) - 6, "ranlib") == 0) + is_ranlib = 1; + else + is_ranlib = 0; + } + + if (argc > 1 && argv[1][0] == '-') + { + if (strcmp (argv[1], "--help") == 0) + usage (1); + else if (strcmp (argv[1], "--version") == 0) + { + if (is_ranlib) + print_version ("ranlib"); + else + print_version ("ar"); + } + } + + START_PROGRESS (program_name, 0); + + bfd_init (); + set_default_bfd_target (); + + show_version = 0; + + xatexit (remove_output); + + if (is_ranlib) + { + boolean touch = false; + + if (argc < 2 || strcmp (argv[1], "--help") == 0) + usage (0); + if (strcmp (argv[1], "-V") == 0 + || strcmp (argv[1], "-v") == 0 + || strncmp (argv[1], "--v", 3) == 0) + print_version ("ranlib"); + arg_index = 1; + if (strcmp (argv[1], "-t") == 0) + { + ++arg_index; + touch = true; + } + while (arg_index < argc) + { + if (! touch) + ranlib_only (argv[arg_index]); + else + ranlib_touch (argv[arg_index]); + ++arg_index; + } + xexit (0); + } + + if (argc == 2 && strcmp (argv[1], "-M") == 0) + { + mri_emul (); + xexit (0); + } + + if (argc < 2) + usage (0); + + arg_ptr = argv[1]; + + if (*arg_ptr == '-') + ++arg_ptr; /* compatibility */ + + while ((c = *arg_ptr++) != '\0') + { + switch (c) + { + case 'd': + case 'm': + case 'p': + case 'q': + case 'r': + case 't': + case 'x': + if (operation != none) + fatal (_("two different operation options specified")); + switch (c) + { + case 'd': + operation = delete; + operation_alters_arch = true; + break; + case 'm': + operation = move; + operation_alters_arch = true; + break; + case 'p': + operation = print_files; + break; + case 'q': + operation = quick_append; + operation_alters_arch = true; + break; + case 'r': + operation = replace; + operation_alters_arch = true; + break; + case 't': + operation = print_table; + break; + case 'x': + operation = extract; + break; + } + case 'l': + break; + case 'c': + silent_create = 1; + break; + case 'o': + preserve_dates = 1; + break; + case 'V': + show_version = true; + break; + case 's': + write_armap = 1; + break; + case 'S': + write_armap = -1; + break; + case 'u': + newer_only = 1; + break; + case 'v': + verbose = 1; + break; + case 'a': + postype = pos_after; + break; + case 'b': + postype = pos_before; + break; + case 'i': + postype = pos_before; + break; + case 'M': + mri_mode = 1; + break; + case 'f': + ar_truncate = true; + break; + default: + /* xgettext:c-format */ + fprintf (stderr, _("%s: illegal option -- %c\n"), program_name, c); + usage (0); + } + } + + if (show_version) + print_version ("ar"); + + if (argc < 3) + usage (0); + + if (mri_mode) + { + mri_emul (); + } + else + { + bfd *arch; + + /* We can't write an armap when using ar q, so just do ar r + instead. */ + if (operation == quick_append && write_armap) + operation = replace; + + if ((operation == none || operation == print_table) + && write_armap == 1) + { + ranlib_only (argv[2]); + xexit (0); + } + + if (operation == none) + fatal (_("no operation specified")); + + if (newer_only && operation != replace) + fatal (_("`u' is only meaningful with the `r' option.")); + + arg_index = 2; + + if (postype != pos_default) + posname = argv[arg_index++]; + + inarch_filename = argv[arg_index++]; + + files = arg_index < argc ? argv + arg_index : NULL; + +#if 0 + /* We don't use do_quick_append any more. Too many systems + expect ar to always rebuild the symbol table even when q is + used. */ + + /* We can't do a quick append if we need to construct an + extended name table, because do_quick_append won't be able to + rebuild the name table. Unfortunately, at this point we + don't actually know the maximum name length permitted by this + object file format. So, we guess. FIXME. */ + if (operation == quick_append && ! ar_truncate) + { + char **chk; + + for (chk = files; chk != NULL && *chk != '\0'; chk++) + { + if (strlen (normalize (*chk, (bfd *) NULL)) > 14) + { + operation = replace; + break; + } + } + } + + if (operation == quick_append) + { + /* Note that quick appending to a non-existent archive creates it, + even if there are no files to append. */ + do_quick_append (inarch_filename, files); + xexit (0); + } +#endif + + arch = open_inarch (inarch_filename, + files == NULL ? (char *) NULL : files[0]); + + switch (operation) + { + case print_table: + map_over_members (arch, print_descr, files, argc - 3); + break; + + case print_files: + map_over_members (arch, print_contents, files, argc - 3); + break; + + case extract: + map_over_members (arch, extract_file, files, argc - 3); + break; + + case delete: + if (files != NULL) + delete_members (arch, files); + break; + + case move: + if (files != NULL) + move_members (arch, files); + break; + + case replace: + case quick_append: + if (files != NULL || write_armap > 0) + replace_members (arch, files, operation == quick_append); + break; + + /* Shouldn't happen! */ + default: + /* xgettext:c-format */ + fprintf (stderr, _("%s: internal error -- this option not implemented\n"), + program_name); + xexit (1); + } + } + + END_PROGRESS (program_name); + + xexit (0); + return 0; +} + +bfd * +open_inarch (archive_filename, file) + const char *archive_filename; + const char *file; +{ + const char *target; + bfd **last_one; + bfd *next_one; + struct stat sbuf; + bfd *arch; + char **matching; + + bfd_set_error (bfd_error_no_error); + + target = NULL; + + if (stat (archive_filename, &sbuf) != 0) + { +#ifndef __GO32__ + +/* KLUDGE ALERT! Temporary fix until I figger why + * stat() is wrong ... think it's buried in GO32's IDT + * - Jax + */ + if (errno != ENOENT) + bfd_fatal (archive_filename); +#endif + + if (!operation_alters_arch) + { + fprintf (stderr, "%s: ", program_name); + perror (archive_filename); + maybequit (); + return NULL; + } + + /* Try to figure out the target to use for the archive from the + first object on the list. */ + if (file != NULL) + { + bfd *obj; + + obj = bfd_openr (file, NULL); + if (obj != NULL) + { + if (bfd_check_format (obj, bfd_object)) + target = bfd_get_target (obj); + (void) bfd_close (obj); + } + } + + /* Create an empty archive. */ + arch = bfd_openw (archive_filename, target); + if (arch == NULL + || ! bfd_set_format (arch, bfd_archive) + || ! bfd_close (arch)) + bfd_fatal (archive_filename); + } + + arch = bfd_openr (archive_filename, target); + if (arch == NULL) + { + bloser: + bfd_fatal (archive_filename); + } + + if (! bfd_check_format_matches (arch, bfd_archive, &matching)) + { + bfd_nonfatal (archive_filename); + if (bfd_get_error () == bfd_error_file_ambiguously_recognized) + { + list_matching_formats (matching); + free (matching); + } + xexit (1); + } + + last_one = &(arch->next); + /* Read all the contents right away, regardless. */ + for (next_one = bfd_openr_next_archived_file (arch, NULL); + next_one; + next_one = bfd_openr_next_archived_file (arch, next_one)) + { + PROGRESS (1); + *last_one = next_one; + last_one = &next_one->next; + } + *last_one = (bfd *) NULL; + if (bfd_get_error () != bfd_error_no_more_archived_files) + goto bloser; + return arch; +} + +static void +print_contents (abfd) + bfd *abfd; +{ + int ncopied = 0; + char *cbuf = xmalloc (BUFSIZE); + struct stat buf; + long size; + if (bfd_stat_arch_elt (abfd, &buf) != 0) + /* xgettext:c-format */ + fatal (_("internal stat error on %s"), bfd_get_filename (abfd)); + + if (verbose) + /* xgettext:c-format */ + printf (_("\n<member %s>\n\n"), bfd_get_filename (abfd)); + + bfd_seek (abfd, 0, SEEK_SET); + + size = buf.st_size; + while (ncopied < size) + { + + int nread; + int tocopy = size - ncopied; + if (tocopy > BUFSIZE) + tocopy = BUFSIZE; + + nread = bfd_read (cbuf, 1, tocopy, abfd); /* oops -- broke + abstraction! */ + if (nread != tocopy) + /* xgettext:c-format */ + fatal (_("%s is not a valid archive"), + bfd_get_filename (bfd_my_archive (abfd))); + fwrite (cbuf, 1, nread, stdout); + ncopied += tocopy; + } + free (cbuf); +} + +/* Extract a member of the archive into its own file. + + We defer opening the new file until after we have read a BUFSIZ chunk of the + old one, since we know we have just read the archive header for the old + one. Since most members are shorter than BUFSIZ, this means we will read + the old header, read the old data, write a new inode for the new file, and + write the new data, and be done. This 'optimization' is what comes from + sitting next to a bare disk and hearing it every time it seeks. -- Gnu + Gilmore */ + +void +extract_file (abfd) + bfd *abfd; +{ + FILE *ostream; + char *cbuf = xmalloc (BUFSIZE); + int nread, tocopy; + long ncopied = 0; + long size; + struct stat buf; + + if (bfd_stat_arch_elt (abfd, &buf) != 0) + /* xgettext:c-format */ + fatal (_("internal stat error on %s"), bfd_get_filename (abfd)); + size = buf.st_size; + + if (size < 0) + /* xgettext:c-format */ + fatal (_("stat returns negative size for %s"), bfd_get_filename (abfd)); + + if (verbose) + printf ("x - %s\n", bfd_get_filename (abfd)); + + bfd_seek (abfd, 0, SEEK_SET); + + ostream = NULL; + if (size == 0) + { + /* Seems like an abstraction violation, eh? Well it's OK! */ + output_filename = bfd_get_filename (abfd); + + ostream = fopen (bfd_get_filename (abfd), FOPEN_WB); + if (ostream == NULL) + { + perror (bfd_get_filename (abfd)); + xexit (1); + } + + output_file = ostream; + } + else + while (ncopied < size) + { + tocopy = size - ncopied; + if (tocopy > BUFSIZE) + tocopy = BUFSIZE; + + nread = bfd_read (cbuf, 1, tocopy, abfd); + if (nread != tocopy) + /* xgettext:c-format */ + fatal (_("%s is not a valid archive"), + bfd_get_filename (bfd_my_archive (abfd))); + + /* See comment above; this saves disk arm motion */ + if (ostream == NULL) + { + /* Seems like an abstraction violation, eh? Well it's OK! */ + output_filename = bfd_get_filename (abfd); + + ostream = fopen (bfd_get_filename (abfd), FOPEN_WB); + if (ostream == NULL) + { + perror (bfd_get_filename (abfd)); + xexit (1); + } + + output_file = ostream; + } + fwrite (cbuf, 1, nread, ostream); + ncopied += tocopy; + } + + if (ostream != NULL) + fclose (ostream); + + output_file = NULL; + output_filename = NULL; + + chmod (bfd_get_filename (abfd), buf.st_mode); + + if (preserve_dates) + set_times (bfd_get_filename (abfd), &buf); + + free (cbuf); +} + +#if 0 + +/* We don't use this anymore. Too many systems expect ar to rebuild + the symbol table even when q is used. */ + +/* Just do it quickly; don't worry about dups, armap, or anything like that */ + +static void +do_quick_append (archive_filename, files_to_append) + const char *archive_filename; + char **files_to_append; +{ + FILE *ofile, *ifile; + char *buf = xmalloc (BUFSIZE); + long tocopy, thistime; + bfd *temp; + struct stat sbuf; + boolean newfile = false; + bfd_set_error (bfd_error_no_error); + + if (stat (archive_filename, &sbuf) != 0) + { + +#ifndef __GO32__ + +/* KLUDGE ALERT! Temporary fix until I figger why + * stat() is wrong ... think it's buried in GO32's IDT + * - Jax + */ + + if (errno != ENOENT) + bfd_fatal (archive_filename); +#endif + + newfile = true; + } + + ofile = fopen (archive_filename, FOPEN_AUB); + if (ofile == NULL) + { + perror (program_name); + xexit (1); + } + + temp = bfd_openr (archive_filename, NULL); + if (temp == NULL) + { + bfd_fatal (archive_filename); + } + if (newfile == false) + { + if (bfd_check_format (temp, bfd_archive) != true) + /* xgettext:c-format */ + fatal (_("%s is not an archive"), archive_filename); + } + else + { + fwrite (ARMAG, 1, SARMAG, ofile); + if (!silent_create) + /* xgettext:c-format */ + fprintf (stderr, _("%s: creating %s\n"), + program_name, archive_filename); + } + + if (ar_truncate) + temp->flags |= BFD_TRADITIONAL_FORMAT; + + /* assume it's an achive, go straight to the end, sans $200 */ + fseek (ofile, 0, 2); + + for (; files_to_append && *files_to_append; ++files_to_append) + { + struct ar_hdr *hdr = bfd_special_undocumented_glue (temp, *files_to_append); + if (hdr == NULL) + { + bfd_fatal (*files_to_append); + } + + BFD_SEND (temp, _bfd_truncate_arname, (temp, *files_to_append, (char *) hdr)); + + ifile = fopen (*files_to_append, FOPEN_RB); + if (ifile == NULL) + { + bfd_nonfatal (*files_to_append); + } + + if (stat (*files_to_append, &sbuf) != 0) + { + bfd_nonfatal (*files_to_append); + } + + tocopy = sbuf.st_size; + + /* XXX should do error-checking! */ + fwrite (hdr, 1, sizeof (struct ar_hdr), ofile); + + while (tocopy > 0) + { + thistime = tocopy; + if (thistime > BUFSIZE) + thistime = BUFSIZE; + fread (buf, 1, thistime, ifile); + fwrite (buf, 1, thistime, ofile); + tocopy -= thistime; + } + fclose (ifile); + if ((sbuf.st_size % 2) == 1) + putc ('\012', ofile); + } + fclose (ofile); + bfd_close (temp); + free (buf); +} + +#endif /* 0 */ + +static void +write_archive (iarch) + bfd *iarch; +{ + bfd *obfd; + char *old_name, *new_name; + bfd *contents_head = iarch->next; + + old_name = xmalloc (strlen (bfd_get_filename (iarch)) + 1); + strcpy (old_name, bfd_get_filename (iarch)); + new_name = make_tempname (old_name); + + output_filename = new_name; + + obfd = bfd_openw (new_name, bfd_get_target (iarch)); + + if (obfd == NULL) + bfd_fatal (old_name); + + output_bfd = obfd; + + bfd_set_format (obfd, bfd_archive); + + /* Request writing the archive symbol table unless we've + been explicitly requested not to. */ + obfd->has_armap = write_armap >= 0; + + if (ar_truncate) + { + /* This should really use bfd_set_file_flags, but that rejects + archives. */ + obfd->flags |= BFD_TRADITIONAL_FORMAT; + } + + if (bfd_set_archive_head (obfd, contents_head) != true) + bfd_fatal (old_name); + + if (!bfd_close (obfd)) + bfd_fatal (old_name); + + output_bfd = NULL; + output_filename = NULL; + + /* We don't care if this fails; we might be creating the archive. */ + bfd_close (iarch); + + if (smart_rename (new_name, old_name, 0) != 0) + xexit (1); +} + +/* Return a pointer to the pointer to the entry which should be rplacd'd + into when altering. DEFAULT_POS should be how to interpret pos_default, + and should be a pos value. */ + +static bfd ** +get_pos_bfd (contents, default_pos, default_posname) + bfd **contents; + enum pos default_pos; + const char *default_posname; +{ + bfd **after_bfd = contents; + enum pos realpos; + const char *realposname; + + if (postype == pos_default) + { + realpos = default_pos; + realposname = default_posname; + } + else + { + realpos = postype; + realposname = posname; + } + + if (realpos == pos_end) + { + while (*after_bfd) + after_bfd = &((*after_bfd)->next); + } + else + { + for (; *after_bfd; after_bfd = &(*after_bfd)->next) + if (strcmp ((*after_bfd)->filename, realposname) == 0) + { + if (realpos == pos_after) + after_bfd = &(*after_bfd)->next; + break; + } + } + return after_bfd; +} + +static void +delete_members (arch, files_to_delete) + bfd *arch; + char **files_to_delete; +{ + bfd **current_ptr_ptr; + boolean found; + boolean something_changed = false; + for (; *files_to_delete != NULL; ++files_to_delete) + { + /* In a.out systems, the armap is optional. It's also called + __.SYMDEF. So if the user asked to delete it, we should remember + that fact. This isn't quite right for COFF systems (where + __.SYMDEF might be regular member), but it's very unlikely + to be a problem. FIXME */ + + if (!strcmp (*files_to_delete, "__.SYMDEF")) + { + arch->has_armap = false; + write_armap = -1; + continue; + } + + found = false; + current_ptr_ptr = &(arch->next); + while (*current_ptr_ptr) + { + if (strcmp (*files_to_delete, (*current_ptr_ptr)->filename) == 0) + { + found = true; + something_changed = true; + if (verbose) + printf ("d - %s\n", + *files_to_delete); + *current_ptr_ptr = ((*current_ptr_ptr)->next); + goto next_file; + } + else + { + current_ptr_ptr = &((*current_ptr_ptr)->next); + } + } + + if (verbose && found == false) + { + /* xgettext:c-format */ + printf (_("No member named `%s'\n"), *files_to_delete); + } + next_file: + ; + } + + if (something_changed == true) + { + write_archive (arch); + } +} + + +/* Reposition existing members within an archive */ + +static void +move_members (arch, files_to_move) + bfd *arch; + char **files_to_move; +{ + bfd **after_bfd; /* New entries go after this one */ + bfd **current_ptr_ptr; /* cdr pointer into contents */ + + for (; *files_to_move; ++files_to_move) + { + current_ptr_ptr = &(arch->next); + while (*current_ptr_ptr) + { + bfd *current_ptr = *current_ptr_ptr; + if (strcmp (normalize (*files_to_move, arch), + current_ptr->filename) == 0) + { + /* Move this file to the end of the list - first cut from + where it is. */ + bfd *link; + *current_ptr_ptr = current_ptr->next; + + /* Now glue to end */ + after_bfd = get_pos_bfd (&arch->next, pos_end, NULL); + link = *after_bfd; + *after_bfd = current_ptr; + current_ptr->next = link; + + if (verbose) + printf ("m - %s\n", *files_to_move); + + goto next_file; + } + + current_ptr_ptr = &((*current_ptr_ptr)->next); + } + /* xgettext:c-format */ + fprintf (stderr, _("%s: no entry %s in archive %s!\n"), + program_name, *files_to_move, arch->filename); + xexit (1); + next_file:; + } + + write_archive (arch); +} + +/* Ought to default to replacing in place, but this is existing practice! */ + +static void +replace_members (arch, files_to_move, quick) + bfd *arch; + char **files_to_move; + boolean quick; +{ + boolean changed = false; + bfd **after_bfd; /* New entries go after this one */ + bfd *current; + bfd **current_ptr; + bfd *temp; + + while (files_to_move && *files_to_move) + { + if (! quick) + { + current_ptr = &arch->next; + while (*current_ptr) + { + current = *current_ptr; + + /* For compatibility with existing ar programs, we + permit the same file to be added multiple times. */ + if (strcmp (normalize (*files_to_move, arch), + normalize (current->filename, arch)) == 0 + && current->arelt_data != NULL) + { + if (newer_only) + { + struct stat fsbuf, asbuf; + + if (stat (*files_to_move, &fsbuf) != 0) + { + if (errno != ENOENT) + bfd_fatal (*files_to_move); + goto next_file; + } + if (bfd_stat_arch_elt (current, &asbuf) != 0) + /* xgettext:c-format */ + fatal (_("internal stat error on %s"), current->filename); + + if (fsbuf.st_mtime <= asbuf.st_mtime) + goto next_file; + } + + after_bfd = get_pos_bfd (&arch->next, pos_after, + current->filename); + temp = *after_bfd; + + *after_bfd = bfd_openr (*files_to_move, NULL); + if (*after_bfd == (bfd *) NULL) + { + bfd_fatal (*files_to_move); + } + (*after_bfd)->next = temp; + + /* snip out this entry from the chain */ + *current_ptr = (*current_ptr)->next; + + if (verbose) + { + printf ("r - %s\n", *files_to_move); + } + + changed = true; + + goto next_file; + } + current_ptr = &(current->next); + } + } + + /* Add to the end of the archive. */ + + after_bfd = get_pos_bfd (&arch->next, pos_end, NULL); + temp = *after_bfd; + *after_bfd = bfd_openr (*files_to_move, NULL); + if (*after_bfd == (bfd *) NULL) + { + bfd_fatal (*files_to_move); + } + if (verbose) + { + printf ("a - %s\n", *files_to_move); + } + + (*after_bfd)->next = temp; + + changed = true; + + next_file:; + + files_to_move++; + } + + if (changed) + write_archive (arch); +} + +static void +ranlib_only (archname) + const char *archname; +{ + bfd *arch; + + write_armap = 1; + arch = open_inarch (archname, (char *) NULL); + if (arch == NULL) + xexit (1); + write_archive (arch); +} + +/* Update the timestamp of the symbol map of an archive. */ + +static void +ranlib_touch (archname) + const char *archname; +{ +#ifdef __GO32__ + /* I don't think updating works on go32. */ + ranlib_only (archname); +#else + int f; + bfd *arch; + char **matching; + + f = open (archname, O_RDWR, 0); + if (f < 0) + { + bfd_set_error (bfd_error_system_call); + bfd_fatal (archname); + } + + arch = bfd_fdopenr (archname, (const char *) NULL, f); + if (arch == NULL) + bfd_fatal (archname); + if (! bfd_check_format_matches (arch, bfd_archive, &matching)) + { + bfd_nonfatal (archname); + if (bfd_get_error () == bfd_error_file_ambiguously_recognized) + { + list_matching_formats (matching); + free (matching); + } + xexit (1); + } + + if (! bfd_has_map (arch)) + /* xgettext:c-format */ + fatal (_("%s: no archive map to update"), archname); + + bfd_update_armap_timestamp (arch); + + if (! bfd_close (arch)) + bfd_fatal (archname); +#endif +} + +/* Things which are interesting to map over all or some of the files: */ + +static void +print_descr (abfd) + bfd *abfd; +{ + print_arelt_descr (stdout, abfd, verbose); +} diff --git a/binutils/arlex.l b/binutils/arlex.l new file mode 100644 index 0000000..74e13d1 --- /dev/null +++ b/binutils/arlex.l @@ -0,0 +1,83 @@ +%{ +/* arlex.l - Strange script language lexer */ + +/* Copyright (C) 1992, 95, 1997 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +/* Contributed by Steve Chamberlain + sac@cygnus.com + +*/ +#define DONTDECLARE_MALLOC +#include <ansidecl.h> +#include "libiberty.h" +#include "arparse.h" + +int linenumber; +%} +%% + +"ADDLIB" { return ADDLIB; } +"ADDMOD" { return ADDMOD; } +"CLEAR" { return CLEAR; } +"CREATE" { return CREATE; } +"DELETE" { return DELETE; } +"DIRECTORY" { return DIRECTORY; } +"END" { return END; } +"EXTRACT" { return EXTRACT; } +"FULLDIR" { return FULLDIR; } +"HELP" { return HELP; } +"LIST" { return LIST; } +"OPEN" { return OPEN; } +"REPLACE" { return REPLACE; } +"VERBOSE" { return VERBOSE; } +"SAVE" { return SAVE; } +"addlib" { return ADDLIB; } +"addmod" { return ADDMOD; } +"clear" { return CLEAR; } +"create" { return CREATE; } +"delete" { return DELETE; } +"directory" { return DIRECTORY; } +"end" { return END; } +"extract" { return EXTRACT; } +"fulldir" { return FULLDIR; } +"help" { return HELP; } +"list" { return LIST; } +"open" { return OPEN; } +"replace" { return REPLACE; } +"verbose" { return VERBOSE; } +"save" { return SAVE; } +"+\n" { linenumber ++; } +"(" { return '('; } +")" { return ')'; } +"," { return ','; } +[A-Za-z0-9/$:.\-\_]+ { + yylval.name = xstrdup (yytext); + return FILENAME; + } +"*".* { } +";".* { } +" " { } +"\n" { linenumber ++; return NEWLINE; } + +%% +#ifndef yywrap +/* Needed for lex, though not flex. */ +int yywrap() { return 1; } +#endif diff --git a/binutils/arparse.y b/binutils/arparse.y new file mode 100644 index 0000000..d6c7600 --- /dev/null +++ b/binutils/arparse.y @@ -0,0 +1,202 @@ +%{ +/* arparse.y - Stange script language parser */ + +/* Copyright (C) 1992, 93, 95, 97, 98, 1999 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +/* Contributed by Steve Chamberlain + sac@cygnus.com + +*/ +#define DONTDECLARE_MALLOC +#include "bfd.h" +#include "bucomm.h" +#include "arsup.h" +extern int verbose; +extern int yylex PARAMS ((void)); +static int yyerror PARAMS ((const char *)); +%} + +%union { + char *name; +struct list *list ; + +}; + +%token NEWLINE +%token VERBOSE +%token <name> FILENAME +%token ADDLIB +%token LIST +%token ADDMOD +%token CLEAR +%token CREATE +%token DELETE +%token DIRECTORY +%token END +%token EXTRACT +%token FULLDIR +%token HELP +%token QUIT +%token REPLACE +%token SAVE +%token OPEN + +%type <list> modulelist +%type <list> modulename +%type <name> optional_filename +%% + +start: + { prompt(); } session + ; + +session: + session command_line + | + ; + +command_line: + command NEWLINE { prompt(); } + +command: + open_command + | create_command + | verbose_command + | directory_command + | addlib_command + | clear_command + | addmod_command + | save_command + | extract_command + | replace_command + | delete_command + | list_command + | END { ar_end(); return 0; } + | error + | FILENAME { yyerror("foo"); } + | + ; + + +extract_command: + EXTRACT modulename + { ar_extract($2); } + ; + +replace_command: + REPLACE modulename + { ar_replace($2); } + ; + +clear_command: + CLEAR + { ar_clear(); } + ; + +delete_command: + DELETE modulename + { ar_delete($2); } + ; +addmod_command: + ADDMOD modulename + { ar_addmod($2); } + ; + +list_command: + LIST + { ar_list(); } + ; + +save_command: + SAVE + { ar_save(); } + ; + + + +open_command: + OPEN FILENAME + { ar_open($2,0); } + ; + +create_command: + CREATE FILENAME + { ar_open($2,1); } + ; + + +addlib_command: + ADDLIB FILENAME modulelist + { ar_addlib($2,$3); } + ; +directory_command: + DIRECTORY FILENAME modulelist optional_filename + { ar_directory($2, $3, $4); } + ; + + + +optional_filename: + FILENAME + { $$ = $1; } + | { $$ = 0; } + ; + +modulelist: + '(' modulename ')' + { $$ = $2; } + | + { $$ = 0; } + ; + +modulename: + modulename optcomma FILENAME + { struct list *n = (struct list *) malloc(sizeof(struct list)); + n->next = $1; + n->name = $3; + $$ = n; + } + | { $$ = 0; } + ; + + +optcomma: + ',' + | + ; + + +verbose_command: + VERBOSE + { verbose = !verbose; } + ; + + +%% + +static int +yyerror (x) + const char *x; +{ + extern int linenumber; + + printf (_("Syntax error in archive script, line %d\n"), linenumber + 1); + return 0; +} diff --git a/binutils/arsup.c b/binutils/arsup.c new file mode 100644 index 0000000..38fd695 --- /dev/null +++ b/binutils/arsup.c @@ -0,0 +1,456 @@ +/* arsup.c - Archive support for MRI compatibility + Copyright (C) 1992, 93, 94, 95, 96, 1997, 1998 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +/* Contributed by Steve Chamberlain + sac@cygnus.com + +This file looks after requests from arparse.y, to provide the MRI +style librarian command syntax + 1 word LIST + +*/ + +#include "bfd.h" +#include "arsup.h" +#include "libiberty.h" +#include "bucomm.h" + +static void map_over_list + PARAMS ((bfd *, void (*function) (bfd *, bfd *), struct list *)); +static void ar_directory_doer PARAMS ((bfd *, bfd *)); +static void ar_addlib_doer PARAMS ((bfd *, bfd *)); + +extern int verbose; + +static void +map_over_list (arch, function, list) + bfd *arch; + void (*function) PARAMS ((bfd *, bfd *)); + struct list *list; +{ + bfd *head; + + if (list == NULL) + { + bfd *next; + + head = arch->next; + while (head != NULL) + { + next = head->next; + function (head, (bfd *) NULL); + head = next; + } + } + else + { + struct list *ptr; + + /* This may appear to be a baroque way of accomplishing what we + want. however we have to iterate over the filenames in order + to notice where a filename is requested but does not exist in + the archive. Ditto mapping over each file each time -- we + want to hack multiple references. */ + for (ptr = list; ptr; ptr = ptr->next) + { + boolean found = false; + bfd *prev = arch; + + for (head = arch->next; head; head = head->next) + { + if (head->filename != NULL + && strcmp (ptr->name, head->filename) == 0) + { + found = true; + function (head, prev); + } + prev = head; + } + if (! found) + fprintf (stderr, _("No entry %s in archive.\n"), ptr->name); + } + } +} + + +FILE *outfile; + +/*ARGSUSED*/ +static void +ar_directory_doer (abfd, ignore) + bfd *abfd; + bfd *ignore; +{ + print_arelt_descr(outfile, abfd, verbose); +} + +void +ar_directory (ar_name, list, output) + char *ar_name; + struct list *list; + char *output; +{ + bfd *arch; + + arch = open_inarch (ar_name, (char *) NULL); + if (output) + { + outfile = fopen(output,"w"); + if (outfile == 0) + { + outfile = stdout; + fprintf (stderr,_("Can't open file %s\n"), output); + output = 0; + } + } + else + outfile = stdout; + + map_over_list (arch, ar_directory_doer, list); + + bfd_close (arch); + + if (output) + fclose (outfile); +} + +void +DEFUN_VOID(prompt) +{ + extern int interactive; + if (interactive) + { + printf("AR >"); + fflush(stdout); + } +} + +void +maybequit () +{ + if (! interactive) + xexit (9); +} + + +bfd *obfd; +char *real_name ; +void +DEFUN(ar_open,(name, t), + char *name AND + int t) + +{ + char *tname = (char *) xmalloc (strlen (name) + 10); + real_name = name; + sprintf(tname, "%s-tmp", name); + obfd = bfd_openw(tname, NULL); + + if (!obfd) { + fprintf(stderr,_("%s: Can't open output archive %s\n"), program_name, + tname); + + maybequit(); + } + else { + if (!t) { + bfd **ptr; + bfd *element; + bfd *ibfd; + ibfd = bfd_openr(name, NULL); + if (!ibfd) { + fprintf(stderr,_("%s: Can't open input archive %s\n"), + program_name, name); + maybequit(); + return; + } + if (bfd_check_format(ibfd, bfd_archive) != true) { + fprintf(stderr,_("%s: file %s is not an archive\n"), program_name, + name); + maybequit(); + return; + } + ptr = &(obfd->archive_head); + element = bfd_openr_next_archived_file(ibfd, NULL); + + while (element) { + *ptr = element; + ptr = &element->next; + element = bfd_openr_next_archived_file(ibfd, element); + } + } + + bfd_set_format(obfd, bfd_archive); + + obfd->has_armap = 1; + } +} + + +static void +ar_addlib_doer (abfd, prev) + bfd *abfd; + bfd *prev; +{ + /* Add this module to the output bfd */ + if (prev != NULL) + prev->next = abfd->next; + abfd->next = obfd->archive_head; + obfd->archive_head = abfd; +} + +void +ar_addlib (name, list) + char *name; + struct list *list; +{ + if (obfd == NULL) + { + fprintf (stderr, _("%s: no output archive specified yet\n"), program_name); + maybequit (); + } + else + { + bfd *arch; + + arch = open_inarch (name, (char *) NULL); + if (arch != NULL) + map_over_list (arch, ar_addlib_doer, list); + + /* Don't close the bfd, since it will make the elements disasppear */ + } +} + +void +DEFUN(ar_addmod, (list), + struct list *list) +{ + if (!obfd) { + fprintf(stderr, _("%s: no open output archive\n"), program_name); + maybequit(); + } + else + { + while (list) { + bfd *abfd = bfd_openr(list->name, NULL); + if (!abfd) { + fprintf(stderr,_("%s: can't open file %s\n"), program_name, + list->name); + maybequit(); + } + else { + abfd->next = obfd->archive_head; + obfd->archive_head = abfd; + } + list = list->next; + } + } +} + + + +void +DEFUN_VOID(ar_clear) +{ +if (obfd) + obfd->archive_head = 0; +} + +void +DEFUN(ar_delete, (list), + struct list *list) +{ + if (!obfd) { + fprintf(stderr, _("%s: no open output archive\n"), program_name); + maybequit(); + } + else + { + while (list) { + /* Find this name in the archive */ + bfd *member = obfd->archive_head; + bfd **prev = &(obfd->archive_head); + int found = 0; + while (member) { + if (strcmp(member->filename, list->name) == 0) { + *prev = member->next; + found = 1; + } + else { + prev = &(member->next); + } + member = member->next; + } + if (!found) { + fprintf(stderr,_("%s: can't find module file %s\n"), program_name, + list->name); + maybequit(); + } + list = list->next; + } + } +} + + +void +DEFUN_VOID(ar_save) +{ + + if (!obfd) { + fprintf(stderr, _("%s: no open output archive\n"), program_name); + maybequit(); + } + else { + char *ofilename = xstrdup (bfd_get_filename (obfd)); + bfd_close(obfd); + + rename (ofilename, real_name); + obfd = 0; + free(ofilename); + } +} + + + +void +DEFUN(ar_replace, (list), + struct list *list) +{ + if (!obfd) { + fprintf(stderr, _("%s: no open output archive\n"), program_name); + maybequit(); + } + else + { + while (list) { + /* Find this name in the archive */ + bfd *member = obfd->archive_head; + bfd **prev = &(obfd->archive_head); + int found = 0; + while (member) + { + if (strcmp(member->filename, list->name) == 0) + { + /* Found the one to replace */ + bfd *abfd = bfd_openr(list->name, 0); + if (!abfd) + { + fprintf(stderr, _("%s: can't open file %s\n"), program_name, list->name); + maybequit(); + } + else { + *prev = abfd; + abfd->next = member->next; + found = 1; + } + } + else { + prev = &(member->next); + } + member = member->next; + } + if (!found) { + bfd *abfd = bfd_openr(list->name, 0); + fprintf(stderr,_("%s: can't find module file %s\n"), program_name, + list->name); + if (!abfd) + { + fprintf(stderr, _("%s: can't open file %s\n"), program_name, list->name); + maybequit(); + } + else + { + *prev = abfd; + } + } + + list = list->next; + } + } +} + +/* And I added this one */ +void +DEFUN_VOID(ar_list) +{ + if (!obfd) + { + fprintf(stderr, _("%s: no open output archive\n"), program_name); + maybequit(); + } + else { + bfd *abfd; + outfile = stdout; + verbose =1 ; + printf(_("Current open archive is %s\n"), bfd_get_filename (obfd)); + for (abfd = obfd->archive_head; + abfd != (bfd *)NULL; + abfd = abfd->next) + { + ar_directory_doer (abfd, (bfd *) NULL); + } + } +} + + +void +DEFUN_VOID(ar_end) +{ + if (obfd) + { + fclose((FILE *)(obfd->iostream)); + unlink(bfd_get_filename (obfd)); + } +} +void +DEFUN(ar_extract,(list), + struct list *list) +{ + if (!obfd) + { + + fprintf(stderr, _("%s: no open archive\n"), program_name); + maybequit(); + } + else + { + while (list) { + /* Find this name in the archive */ + bfd *member = obfd->archive_head; + int found = 0; + while (member && !found) + { + if (strcmp(member->filename, list->name) == 0) + { + extract_file(member); + found = 1; + } + + member = member->next; + } + if (!found) { + bfd_openr(list->name, 0); + fprintf(stderr,_("%s: can't find module file %s\n"), program_name, + list->name); + + } + list = list->next; + } + } +} diff --git a/binutils/arsup.h b/binutils/arsup.h new file mode 100644 index 0000000..f54a34b --- /dev/null +++ b/binutils/arsup.h @@ -0,0 +1,75 @@ +/* arsup.h - archive support header file + Copyright 1992 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +struct list { + char *name; + struct list *next; +}; + +void +maybequit PARAMS ((void)); + +void +prompt PARAMS ((void)); + +void +ar_clear PARAMS ((void)); + +void +ar_replace PARAMS ((struct list *)); + +void +ar_delete PARAMS ((struct list *)); + +void +ar_save PARAMS ((void)); + +void +ar_list PARAMS ((void)); + +void +ar_open PARAMS ((char *, int)); + +void +ar_directory PARAMS ((char *, struct list *, char *)); + +void +ar_addmod PARAMS ((struct list *)); + +void +ar_addlib PARAMS ((char *, struct list *)); + +void +ar_end PARAMS ((void)); + +void +ar_extract PARAMS ((struct list *)); + +bfd * +open_inarch PARAMS ((const char *archive_filename, const char *)); + +int +yyparse PARAMS ((void)); + +/* Functions from ar.c */ + +void +extract_file PARAMS ((bfd * abfd)); + +extern int interactive; diff --git a/binutils/binutils.texi b/binutils/binutils.texi new file mode 100644 index 0000000..5f7c646 --- /dev/null +++ b/binutils/binutils.texi @@ -0,0 +1,2904 @@ +\input texinfo @c -*- Texinfo -*- +@setfilename binutils.info +@include config.texi + +@ifinfo +@format +START-INFO-DIR-ENTRY +* Binutils: (binutils). The GNU binary utilities "ar", "objcopy", + "objdump", "nm", "nlmconv", "size", "readelf" + "strings", "strip", "ranlib" and "dlltool". +END-INFO-DIR-ENTRY +@end format +@end ifinfo + +@ifinfo +Copyright @copyright{} 1991, 92, 93, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc. + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +@ignore +Permission is granted to process this file through TeX and print the +results, provided the printed document carries a copying permission +notice identical to this one except for the removal of this paragraph +(this paragraph not being relevant to the printed manual). + +@end ignore + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided also that +the entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions. +@end ifinfo + +@synindex ky cp +@c +@c This file documents the GNU binary utilities "ar", "ld", "objcopy", +@c "objdump", "nm", "size", "strings", "strip", "readelf" and "ranlib". +@c +@c Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc. +@c +@c This text may be freely distributed under the terms of the GNU +@c General Public License. +@c + +@setchapternewpage odd +@settitle @sc{gnu} Binary Utilities +@titlepage +@finalout +@title The @sc{gnu} Binary Utilities +@subtitle Version @value{VERSION} +@sp 1 +@subtitle May 1993 +@author Roland H. Pesch +@author Jeffrey M. Osier +@author Cygnus Support +@page + +@tex +{\parskip=0pt \hfill Cygnus Support\par \hfill +\TeX{}info \texinfoversion\par } +@end tex + +@vskip 0pt plus 1filll +Copyright @copyright{} 1991, 92, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc. + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided also that +the entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions. +@end titlepage + +@node Top +@top Introduction + +@cindex version +This brief manual contains preliminary documentation for the @sc{gnu} binary +utilities (collectively version @value{VERSION}): + +@iftex +@table @code +@item ar +Create, modify, and extract from archives + +@item nm +List symbols from object files + +@item objcopy +Copy and translate object files + +@item objdump +Display information from object files + +@item ranlib +Generate index to archive contents + +@item readelf +Display the contents of ELF format files. + +@item size +List file section sizes and total size + +@item strings +List printable strings from files + +@item strip +Discard symbols + +@item c++filt +Demangle encoded C++ symbols + +@item addr2line +Convert addresses into file names and line numbers + +@item nlmconv +Convert object code into a Netware Loadable Module + +@item windres +Manipulate Windows resources + +@item dlltool +Create the files needed to build and use Dynamic Link Libraries +@end table +@end iftex + +@menu +* ar:: Create, modify, and extract from archives +* nm:: List symbols from object files +* objcopy:: Copy and translate object files +* objdump:: Display information from object files +* ranlib:: Generate index to archive contents +* readelf:: Display the contents of ELF format files. +* size:: List section sizes and total size +* strings:: List printable strings from files +* strip:: Discard symbols +* c++filt:: Filter to demangle encoded C++ symbols +* addr2line:: Convert addresses to file and line +* nlmconv:: Converts object code into an NLM +* windres:: Manipulate Windows resources +* dlltool:: Create files needed to build and use DLLs +* Selecting The Target System:: How these utilities determine the target. +* Reporting Bugs:: Reporting Bugs +* Index:: Index +@end menu + +@node ar +@chapter ar + +@kindex ar +@cindex archives +@cindex collections of files +@smallexample +ar [-]@var{p}[@var{mod} [@var{relpos}]] @var{archive} [@var{member}@dots{}] +ar -M [ <mri-script ] +@end smallexample + +The @sc{gnu} @code{ar} program creates, modifies, and extracts from +archives. An @dfn{archive} is a single file holding a collection of +other files in a structure that makes it possible to retrieve +the original individual files (called @dfn{members} of the archive). + +The original files' contents, mode (permissions), timestamp, owner, and +group are preserved in the archive, and can be restored on +extraction. + +@cindex name length +@sc{gnu} @code{ar} can maintain archives whose members have names of any +length; however, depending on how @code{ar} is configured on your +system, a limit on member-name length may be imposed for compatibility +with archive formats maintained with other tools. If it exists, the +limit is often 15 characters (typical of formats related to a.out) or 16 +characters (typical of formats related to coff). + +@cindex libraries +@code{ar} is considered a binary utility because archives of this sort +are most often used as @dfn{libraries} holding commonly needed +subroutines. + +@cindex symbol index +@code{ar} creates an index to the symbols defined in relocatable +object modules in the archive when you specify the modifier @samp{s}. +Once created, this index is updated in the archive whenever @code{ar} +makes a change to its contents (save for the @samp{q} update operation). +An archive with such an index speeds up linking to the library, and +allows routines in the library to call each other without regard to +their placement in the archive. + +You may use @samp{nm -s} or @samp{nm --print-armap} to list this index +table. If an archive lacks the table, another form of @code{ar} called +@code{ranlib} can be used to add just the table. + +@cindex compatibility, @code{ar} +@cindex @code{ar} compatibility +@sc{gnu} @code{ar} is designed to be compatible with two different +facilities. You can control its activity using command-line options, +like the different varieties of @code{ar} on Unix systems; or, if you +specify the single command-line option @samp{-M}, you can control it +with a script supplied via standard input, like the MRI ``librarian'' +program. + +@menu +* ar cmdline:: Controlling @code{ar} on the command line +* ar scripts:: Controlling @code{ar} with a script +@end menu + +@page +@node ar cmdline +@section Controlling @code{ar} on the command line + +@smallexample +ar [-]@var{p}[@var{mod} [@var{relpos}]] @var{archive} [@var{member}@dots{}] +@end smallexample + +@cindex Unix compatibility, @code{ar} +When you use @code{ar} in the Unix style, @code{ar} insists on at least two +arguments to execute: one keyletter specifying the @emph{operation} +(optionally accompanied by other keyletters specifying +@emph{modifiers}), and the archive name to act on. + +Most operations can also accept further @var{member} arguments, +specifying particular files to operate on. + +@sc{gnu} @code{ar} allows you to mix the operation code @var{p} and modifier +flags @var{mod} in any order, within the first command-line argument. + +If you wish, you may begin the first command-line argument with a +dash. + +@cindex operations on archive +The @var{p} keyletter specifies what operation to execute; it may be +any of the following, but you must specify only one of them: + +@table @code +@item d +@cindex deleting from archive +@emph{Delete} modules from the archive. Specify the names of modules to +be deleted as @var{member}@dots{}; the archive is untouched if you +specify no files to delete. + +If you specify the @samp{v} modifier, @code{ar} lists each module +as it is deleted. + +@item m +@cindex moving in archive +Use this operation to @emph{move} members in an archive. + +The ordering of members in an archive can make a difference in how +programs are linked using the library, if a symbol is defined in more +than one member. + +If no modifiers are used with @code{m}, any members you name in the +@var{member} arguments are moved to the @emph{end} of the archive; +you can use the @samp{a}, @samp{b}, or @samp{i} modifiers to move them to a +specified place instead. + +@item p +@cindex printing from archive +@emph{Print} the specified members of the archive, to the standard +output file. If the @samp{v} modifier is specified, show the member +name before copying its contents to standard output. + +If you specify no @var{member} arguments, all the files in the archive are +printed. + +@item q +@cindex quick append to archive +@emph{Quick append}; Historically, add the files @var{member}@dots{} to the end of +@var{archive}, without checking for replacement. + +The modifiers @samp{a}, @samp{b}, and @samp{i} do @emph{not} affect this +operation; new members are always placed at the end of the archive. + +The modifier @samp{v} makes @code{ar} list each file as it is appended. + +Since the point of this operation is speed, the archive's symbol table +index is not updated, even if it already existed; you can use @samp{ar s} or +@code{ranlib} explicitly to update the symbol table index. + +However, too many different systems assume quick append rebuilds the +index, so GNU ar implements @code{q} as a synonym for @code{r}. + +@item r +@cindex replacement in archive +Insert the files @var{member}@dots{} into @var{archive} (with +@emph{replacement}). This operation differs from @samp{q} in that any +previously existing members are deleted if their names match those being +added. + +If one of the files named in @var{member}@dots{} does not exist, @code{ar} +displays an error message, and leaves undisturbed any existing members +of the archive matching that name. + +By default, new members are added at the end of the file; but you may +use one of the modifiers @samp{a}, @samp{b}, or @samp{i} to request +placement relative to some existing member. + +The modifier @samp{v} used with this operation elicits a line of +output for each file inserted, along with one of the letters @samp{a} or +@samp{r} to indicate whether the file was appended (no old member +deleted) or replaced. + +@item t +@cindex contents of archive +Display a @emph{table} listing the contents of @var{archive}, or those +of the files listed in @var{member}@dots{} that are present in the +archive. Normally only the member name is shown; if you also want to +see the modes (permissions), timestamp, owner, group, and size, you can +request that by also specifying the @samp{v} modifier. + +If you do not specify a @var{member}, all files in the archive +are listed. + +@cindex repeated names in archive +@cindex name duplication in archive +If there is more than one file with the same name (say, @samp{fie}) in +an archive (say @samp{b.a}), @samp{ar t b.a fie} lists only the +first instance; to see them all, you must ask for a complete +listing---in our example, @samp{ar t b.a}. +@c WRS only; per Gumby, this is implementation-dependent, and in a more +@c recent case in fact works the other way. + +@item x +@cindex extract from archive +@emph{Extract} members (named @var{member}) from the archive. You can +use the @samp{v} modifier with this operation, to request that +@code{ar} list each name as it extracts it. + +If you do not specify a @var{member}, all files in the archive +are extracted. + +@end table + +A number of modifiers (@var{mod}) may immediately follow the @var{p} +keyletter, to specify variations on an operation's behavior: + +@table @code +@item a +@cindex relative placement in archive +Add new files @emph{after} an existing member of the +archive. If you use the modifier @samp{a}, the name of an existing archive +member must be present as the @var{relpos} argument, before the +@var{archive} specification. + +@item b +Add new files @emph{before} an existing member of the +archive. If you use the modifier @samp{b}, the name of an existing archive +member must be present as the @var{relpos} argument, before the +@var{archive} specification. (same as @samp{i}). + +@item c +@cindex creating archives +@emph{Create} the archive. The specified @var{archive} is always +created if it did not exist, when you request an update. But a warning is +issued unless you specify in advance that you expect to create it, by +using this modifier. + +@item f +Truncate names in the archive. @sc{gnu} @code{ar} will normally permit file +names of any length. This will cause it to create archives which are +not compatible with the native @code{ar} program on some systems. If +this is a concern, the @samp{f} modifier may be used to truncate file +names when putting them in the archive. + +@item i +Insert new files @emph{before} an existing member of the +archive. If you use the modifier @samp{i}, the name of an existing archive +member must be present as the @var{relpos} argument, before the +@var{archive} specification. (same as @samp{b}). + +@item l +This modifier is accepted but not used. +@c whaffor ar l modifier??? presumably compat; with +@c what???---doc@@cygnus.com, 25jan91 + +@item o +@cindex dates in archive +Preserve the @emph{original} dates of members when extracting them. If +you do not specify this modifier, files extracted from the archive +are stamped with the time of extraction. + +@item s +@cindex writing archive index +Write an object-file index into the archive, or update an existing one, +even if no other change is made to the archive. You may use this modifier +flag either with any operation, or alone. Running @samp{ar s} on an +archive is equivalent to running @samp{ranlib} on it. + +@item S +@cindex not writing archive index +Do not generate an archive symbol table. This can speed up building a +large library in several steps. The resulting archive can not be used +with the linker. In order to build a symbol table, you must omit the +@samp{S} modifier on the last execution of @samp{ar}, or you must run +@samp{ranlib} on the archive. + +@item u +@cindex updating an archive +Normally, @samp{ar r}@dots{} inserts all files +listed into the archive. If you would like to insert @emph{only} those +of the files you list that are newer than existing members of the same +names, use this modifier. The @samp{u} modifier is allowed only for the +operation @samp{r} (replace). In particular, the combination @samp{qu} is +not allowed, since checking the timestamps would lose any speed +advantage from the operation @samp{q}. + +@item v +This modifier requests the @emph{verbose} version of an operation. Many +operations display additional information, such as filenames processed, +when the modifier @samp{v} is appended. + +@item V +This modifier shows the version number of @code{ar}. +@end table + +@node ar scripts +@section Controlling @code{ar} with a script + +@smallexample +ar -M [ <@var{script} ] +@end smallexample + +@cindex MRI compatibility, @code{ar} +@cindex scripts, @code{ar} +If you use the single command-line option @samp{-M} with @code{ar}, you +can control its operation with a rudimentary command language. This +form of @code{ar} operates interactively if standard input is coming +directly from a terminal. During interactive use, @code{ar} prompts for +input (the prompt is @samp{AR >}), and continues executing even after +errors. If you redirect standard input to a script file, no prompts are +issued, and @code{ar} abandons execution (with a nonzero exit code) +on any error. + +The @code{ar} command language is @emph{not} designed to be equivalent +to the command-line options; in fact, it provides somewhat less control +over archives. The only purpose of the command language is to ease the +transition to @sc{gnu} @code{ar} for developers who already have scripts +written for the MRI ``librarian'' program. + +The syntax for the @code{ar} command language is straightforward: +@itemize @bullet +@item +commands are recognized in upper or lower case; for example, @code{LIST} +is the same as @code{list}. In the following descriptions, commands are +shown in upper case for clarity. + +@item +a single command may appear on each line; it is the first word on the +line. + +@item +empty lines are allowed, and have no effect. + +@item +comments are allowed; text after either of the characters @samp{*} +or @samp{;} is ignored. + +@item +Whenever you use a list of names as part of the argument to an @code{ar} +command, you can separate the individual names with either commas or +blanks. Commas are shown in the explanations below, for clarity. + +@item +@samp{+} is used as a line continuation character; if @samp{+} appears +at the end of a line, the text on the following line is considered part +of the current command. +@end itemize + +Here are the commands you can use in @code{ar} scripts, or when using +@code{ar} interactively. Three of them have special significance: + +@code{OPEN} or @code{CREATE} specify a @dfn{current archive}, which is +a temporary file required for most of the other commands. + +@code{SAVE} commits the changes so far specified by the script. Prior +to @code{SAVE}, commands affect only the temporary copy of the current +archive. + +@table @code +@item ADDLIB @var{archive} +@itemx ADDLIB @var{archive} (@var{module}, @var{module}, @dots{} @var{module}) +Add all the contents of @var{archive} (or, if specified, each named +@var{module} from @var{archive}) to the current archive. + +Requires prior use of @code{OPEN} or @code{CREATE}. + +@item ADDMOD @var{member}, @var{member}, @dots{} @var{member} +@c FIXME! w/Replacement?? If so, like "ar r @var{archive} @var{names}" +@c else like "ar q..." +Add each named @var{member} as a module in the current archive. + +Requires prior use of @code{OPEN} or @code{CREATE}. + +@item CLEAR +Discard the contents of the current archive, canceling the effect of +any operations since the last @code{SAVE}. May be executed (with no +effect) even if no current archive is specified. + +@item CREATE @var{archive} +Creates an archive, and makes it the current archive (required for many +other commands). The new archive is created with a temporary name; it +is not actually saved as @var{archive} until you use @code{SAVE}. +You can overwrite existing archives; similarly, the contents of any +existing file named @var{archive} will not be destroyed until @code{SAVE}. + +@item DELETE @var{module}, @var{module}, @dots{} @var{module} +Delete each listed @var{module} from the current archive; equivalent to +@samp{ar -d @var{archive} @var{module} @dots{} @var{module}}. + +Requires prior use of @code{OPEN} or @code{CREATE}. + +@item DIRECTORY @var{archive} (@var{module}, @dots{} @var{module}) +@itemx DIRECTORY @var{archive} (@var{module}, @dots{} @var{module}) @var{outputfile} +List each named @var{module} present in @var{archive}. The separate +command @code{VERBOSE} specifies the form of the output: when verbose +output is off, output is like that of @samp{ar -t @var{archive} +@var{module}@dots{}}. When verbose output is on, the listing is like +@samp{ar -tv @var{archive} @var{module}@dots{}}. + +Output normally goes to the standard output stream; however, if you +specify @var{outputfile} as a final argument, @code{ar} directs the +output to that file. + +@item END +Exit from @code{ar}, with a @code{0} exit code to indicate successful +completion. This command does not save the output file; if you have +changed the current archive since the last @code{SAVE} command, those +changes are lost. + +@item EXTRACT @var{module}, @var{module}, @dots{} @var{module} +Extract each named @var{module} from the current archive, writing them +into the current directory as separate files. Equivalent to @samp{ar -x +@var{archive} @var{module}@dots{}}. + +Requires prior use of @code{OPEN} or @code{CREATE}. + +@ignore +@c FIXME Tokens but no commands??? +@item FULLDIR + +@item HELP +@end ignore + +@item LIST +Display full contents of the current archive, in ``verbose'' style +regardless of the state of @code{VERBOSE}. The effect is like @samp{ar +tv @var{archive}}). (This single command is a @sc{gnu} @code{ld} +enhancement, rather than present for MRI compatibility.) + +Requires prior use of @code{OPEN} or @code{CREATE}. + +@item OPEN @var{archive} +Opens an existing archive for use as the current archive (required for +many other commands). Any changes as the result of subsequent commands +will not actually affect @var{archive} until you next use @code{SAVE}. + +@item REPLACE @var{module}, @var{module}, @dots{} @var{module} +In the current archive, replace each existing @var{module} (named in +the @code{REPLACE} arguments) from files in the current working directory. +To execute this command without errors, both the file, and the module in +the current archive, must exist. + +Requires prior use of @code{OPEN} or @code{CREATE}. + +@item VERBOSE +Toggle an internal flag governing the output from @code{DIRECTORY}. +When the flag is on, @code{DIRECTORY} output matches output from +@samp{ar -tv }@dots{}. + +@item SAVE +Commit your changes to the current archive, and actually save it as a +file with the name specified in the last @code{CREATE} or @code{OPEN} +command. + +Requires prior use of @code{OPEN} or @code{CREATE}. + +@end table + +@iftex +@node ld +@chapter ld +@cindex linker +@kindex ld +The @sc{gnu} linker @code{ld} is now described in a separate manual. +@xref{Top,, Overview,, Using LD: the @sc{gnu} linker}. +@end iftex + +@node nm +@chapter nm +@cindex symbols +@kindex nm + +@smallexample +nm [ -a | --debug-syms ] [ -g | --extern-only ] + [ -B ] [ -C | --demangle ] [ -D | --dynamic ] + [ -s | --print-armap ] [ -A | -o | --print-file-name ] + [ -n | -v | --numeric-sort ] [ -p | --no-sort ] + [ -r | --reverse-sort ] [ --size-sort ] [ -u | --undefined-only ] + [ -t @var{radix} | --radix=@var{radix} ] [ -P | --portability ] + [ --target=@var{bfdname} ] [ -f @var{format} | --format=@var{format} ] + [ --defined-only ] [-l | --line-numbers ] + [ --no-demangle ] [ -V | --version ] [ --help ] [ @var{objfile}@dots{} ] +@end smallexample + +@sc{gnu} @code{nm} lists the symbols from object files @var{objfile}@dots{}. +If no object files are listed as arguments, @code{nm} assumes +@file{a.out}. + +For each symbol, @code{nm} shows: + +@itemize @bullet +@item +The symbol value, in the radix selected by options (see below), or +hexadecimal by default. + +@item +The symbol type. At least the following types are used; others are, as +well, depending on the object file format. If lowercase, the symbol is +local; if uppercase, the symbol is global (external). + +@c Some more detail on exactly what these symbol types are used for +@c would be nice. +@table @code +@item A +The symbol's value is absolute, and will not be changed by further +linking. + +@item B +The symbol is in the uninitialized data section (known as BSS). + +@item C +The symbol is common. Common symbols are uninitialized data. When +linking, multiple common symbols may appear with the same name. If the +symbol is defined anywhere, the common symbols are treated as undefined +references. For more details on common symbols, see the discussion of +--warn-common in @ref{Options,,Linker options,ld.info,The GNU linker}. + +@item D +The symbol is in the initialized data section. + +@item G +The symbol is in an initialized data section for small objects. Some +object file formats permit more efficient access to small data objects, +such as a global int variable as opposed to a large global array. + +@item I +The symbol is an indirect reference to another symbol. This is a GNU +extension to the a.out object file format which is rarely used. + +@item N +The symbol is a debugging symbol. + +@item R +The symbol is in a read only data section. + +@item S +The symbol is in an uninitialized data section for small objects. + +@item T +The symbol is in the text (code) section. + +@item U +The symbol is undefined. + +@item W +The symbol is weak. When a weak defined symbol is linked with a normal +defined symbol, the normal defined symbol is used with no error. When a +weak undefined symbol is linked and the symbol is not defined, the value +of the weak symbol becomes zero with no error. + +@item - +The symbol is a stabs symbol in an a.out object file. In this case, the +next values printed are the stabs other field, the stabs desc field, and +the stab type. Stabs symbols are used to hold debugging information; +for more information, see @ref{Top,Stabs,Stabs Overview,stabs.info, The +``stabs'' debug format}. + +@item ? +The symbol type is unknown, or object file format specific. +@end table + +@item +The symbol name. +@end itemize + +The long and short forms of options, shown here as alternatives, are +equivalent. + +@table @code +@item -A +@itemx -o +@itemx --print-file-name +@cindex input file name +@cindex file name +@cindex source file name +Precede each symbol by the name of the input file (or archive element) +in which it was found, rather than identifying the input file once only, +before all of its symbols. + +@item -a +@itemx --debug-syms +@cindex debugging symbols +Display all symbols, even debugger-only symbols; normally these are not +listed. + +@item -B +@cindex @code{nm} format +@cindex @code{nm} compatibility +The same as @samp{--format=bsd} (for compatibility with the MIPS @code{nm}). + +@item -C +@itemx --demangle +@cindex demangling in nm +Decode (@dfn{demangle}) low-level symbol names into user-level names. +Besides removing any initial underscore prepended by the system, this +makes C++ function names readable. @xref{c++filt}, for more information +on demangling. + +@item --no-demangle +Do not demangle low-level symbol names. This is the default. + +@item -D +@itemx --dynamic +@cindex dynamic symbols +Display the dynamic symbols rather than the normal symbols. This is +only meaningful for dynamic objects, such as certain types of shared +libraries. + +@item -f @var{format} +@itemx --format=@var{format} +@cindex @code{nm} format +@cindex @code{nm} compatibility +Use the output format @var{format}, which can be @code{bsd}, +@code{sysv}, or @code{posix}. The default is @code{bsd}. +Only the first character of @var{format} is significant; it can be +either upper or lower case. + +@item -g +@itemx --extern-only +@cindex external symbols +Display only external symbols. + +@item -l +@itemx --line-numbers +@cindex symbol line numbers +For each symbol, use debugging information to try to find a filename and +line number. For a defined symbol, look for the line number of the +address of the symbol. For an undefined symbol, look for the line +number of a relocation entry which refers to the symbol. If line number +information can be found, print it after the other symbol information. + +@item -n +@itemx -v +@itemx --numeric-sort +Sort symbols numerically by their addresses, rather than alphabetically +by their names. + +@item -p +@itemx --no-sort +@cindex sorting symbols +Do not bother to sort the symbols in any order; print them in the order +encountered. + +@item -P +@itemx --portability +Use the POSIX.2 standard output format instead of the default format. +Equivalent to @samp{-f posix}. + +@item -s +@itemx --print-armap +@cindex symbol index, listing +When listing symbols from archive members, include the index: a mapping +(stored in the archive by @code{ar} or @code{ranlib}) of which modules +contain definitions for which names. + +@item -r +@itemx --reverse-sort +Reverse the order of the sort (whether numeric or alphabetic); let the +last come first. + +@item --size-sort +Sort symbols by size. The size is computed as the difference between +the value of the symbol and the value of the symbol with the next higher +value. The size of the symbol is printed, rather than the value. + +@item -t @var{radix} +@itemx --radix=@var{radix} +Use @var{radix} as the radix for printing the symbol values. It must be +@samp{d} for decimal, @samp{o} for octal, or @samp{x} for hexadecimal. + +@item --target=@var{bfdname} +@cindex object code format +Specify an object code format other than your system's default format. +@xref{Target Selection}, for more information. + +@item -u +@itemx --undefined-only +@cindex external symbols +@cindex undefined symbols +Display only undefined symbols (those external to each object file). + +@item --defined-only +@cindex external symbols +@cindex undefined symbols +Display only defined symbols for each object file. + +@item -V +@itemx --version +Show the version number of @code{nm} and exit. + +@item --help +Show a summary of the options to @code{nm} and exit. +@end table + +@node objcopy +@chapter objcopy + +@smallexample +objcopy [ -F @var{bfdname} | --target=@var{bfdname} ] + [ -I @var{bfdname} | --input-target=@var{bfdname} ] + [ -O @var{bfdname} | --output-target=@var{bfdname} ] + [ -S | --strip-all ] [ -g | --strip-debug ] + [ -K @var{symbolname} | --keep-symbol=@var{symbolname} ] + [ -N @var{symbolname} | --strip-symbol=@var{symbolname} ] + [ -L @var{symbolname} | --localize-symbol=@var{symbolname} ] + [ -W @var{symbolname} | --weaken-symbol=@var{symbolname} ] + [ -x | --discard-all ] [ -X | --discard-locals ] + [ -b @var{byte} | --byte=@var{byte} ] + [ -i @var{interleave} | --interleave=@var{interleave} ] + [ -R @var{sectionname} | --remove-section=@var{sectionname} ] + [ -p | --preserve-dates ] [ --debugging ] + [ --gap-fill=@var{val} ] [ --pad-to=@var{address} ] + [ --set-start=@var{val} ] [ --adjust-start=@var{incr} ] + [ --change-addresses=@var{incr} ] + [ --change-section-address=@var{section}@{=,+,-@}@var{val} ] + [ --change-section-lma=@var{section}@{=,+,-@}@var{val} ] + [ --change-section-vma=@var{section}@{=,+,-@}@var{val} ] + [ --change-warnings ] [ --no-change-warnings ] + [ --set-section-flags=@var{section}=@var{flags} ] + [ --add-section=@var{sectionname}=@var{filename} ] + [ --change-leading-char ] [ --remove-leading-char ] + [ --weaken ] + [ -v | --verbose ] [ -V | --version ] [ --help ] + @var{infile} [@var{outfile}] +@end smallexample + +The @sc{gnu} @code{objcopy} utility copies the contents of an object +file to another. @code{objcopy} uses the @sc{gnu} @sc{bfd} Library to +read and write the object files. It can write the destination object +file in a format different from that of the source object file. The +exact behavior of @code{objcopy} is controlled by command-line options. + +@code{objcopy} creates temporary files to do its translations and +deletes them afterward. @code{objcopy} uses @sc{bfd} to do all its +translation work; it has access to all the formats described in @sc{bfd} +and thus is able to recognize most formats without being told +explicitly. @xref{BFD,,BFD,ld.info,Using LD}. + +@code{objcopy} can be used to generate S-records by using an output +target of @samp{srec} (e.g., use @samp{-O srec}). + +@code{objcopy} can be used to generate a raw binary file by using an +output target of @samp{binary} (e.g., use @samp{-O binary}). When +@code{objcopy} generates a raw binary file, it will essentially produce +a memory dump of the contents of the input object file. All symbols and +relocation information will be discarded. The memory dump will start at +the load address of the lowest section copied into the output file. + +When generating an S-record or a raw binary file, it may be helpful to +use @samp{-S} to remove sections containing debugging information. In +some cases @samp{-R} will be useful to remove sections which contain +information which is not needed by the binary file. + +@table @code +@item @var{infile} +@itemx @var{outfile} +The source and output files, respectively. +If you do not specify @var{outfile}, @code{objcopy} creates a +temporary file and destructively renames the result with +the name of @var{infile}. + +@item -I @var{bfdname} +@itemx --input-target=@var{bfdname} +Consider the source file's object format to be @var{bfdname}, rather than +attempting to deduce it. @xref{Target Selection}, for more information. + +@item -O @var{bfdname} +@itemx --output-target=@var{bfdname} +Write the output file using the object format @var{bfdname}. +@xref{Target Selection}, for more information. + +@item -F @var{bfdname} +@itemx --target=@var{bfdname} +Use @var{bfdname} as the object format for both the input and the output +file; i.e., simply transfer data from source to destination with no +translation. @xref{Target Selection}, for more information. + +@item -R @var{sectionname} +@itemx --remove-section=@var{sectionname} +Remove any section named @var{sectionname} from the output file. This +option may be given more than once. Note that using this option +inappropriately may make the output file unusable. + +@item -S +@itemx --strip-all +Do not copy relocation and symbol information from the source file. + +@item -g +@itemx --strip-debug +Do not copy debugging symbols from the source file. + +@item --strip-unneeded +Strip all symbols that are not needed for relocation processing. + +@item -K @var{symbolname} +@itemx --keep-symbol=@var{symbolname} +Copy only symbol @var{symbolname} from the source file. This option may +be given more than once. + +@item -N @var{symbolname} +@itemx --strip-symbol=@var{symbolname} +Do not copy symbol @var{symbolname} from the source file. This option +may be given more than once. + +@item -L @var{symbolname} +@itemx --localize-symbol=@var{symbolname} +Make symbol @var{symbolname} local to the file, so that it is not +visible externally. This option may be given more than once. + +@item -W @var{symbolname} +@itemx --weaken-symbol=@var{symbolname} +Make symbol @var{symbolname} weak. This option may be given more than once. + +@item -x +@itemx --discard-all +Do not copy non-global symbols from the source file. +@c FIXME any reason to prefer "non-global" to "local" here? + +@item -X +@itemx --discard-locals +Do not copy compiler-generated local symbols. +(These usually start with @samp{L} or @samp{.}.) + +@item -b @var{byte} +@itemx --byte=@var{byte} +Keep only every @var{byte}th byte of the input file (header data is not +affected). @var{byte} can be in the range from 0 to @var{interleave}-1, +where @var{interleave} is given by the @samp{-i} or @samp{--interleave} +option, or the default of 4. This option is useful for creating files +to program @sc{rom}. It is typically used with an @code{srec} output +target. + +@item -i @var{interleave} +@itemx --interleave=@var{interleave} +Only copy one out of every @var{interleave} bytes. Select which byte to +copy with the @var{-b} or @samp{--byte} option. The default is 4. +@code{objcopy} ignores this option if you do not specify either @samp{-b} or +@samp{--byte}. + +@item -p +@itemx --preserve-dates +Set the access and modification dates of the output file to be the same +as those of the input file. + +@item --debugging +Convert debugging information, if possible. This is not the default +because only certain debugging formats are supported, and the +conversion process can be time consuming. + +@item --gap-fill @var{val} +Fill gaps between sections with @var{val}. This operation applies to +the @emph{load address} (LMA) of the sections. It is done by increasing +the size of the section with the lower address, and filling in the extra +space created with @var{val}. + +@item --pad-to @var{address} +Pad the output file up to the load address @var{address}. This is +done by increasing the size of the last section. The extra space is +filled in with the value specified by @samp{--gap-fill} (default zero). + +@item --set-start @var{val} +Set the address of the new file to @var{val}. Not all object file +formats support setting the start address. + +@item --change-start @var{incr} +@itemx --adjust-start @var{incr} +@cindex changing start address +Change the start address by adding @var{incr}. Not all object file +formats support setting the start address. + +@item --change-addresses @var{incr} +@itemx --adjust-vma @var{incr} +@cindex changing object addresses +Change the VMA and LMA addresses of all sections, as well as the start +address, by adding @var{incr}. Some object file formats do not permit +section addresses to be changed arbitrarily. Note that this does not +relocate the sections; if the program expects sections to be loaded at a +certain address, and this option is used to change the sections such +that they are loaded at a different address, the program may fail. + +@item --change-section-address @var{section}@{=,+,-@}@var{val} +@itemx --adjust-section-vma @var{section}@{=,+,-@}@var{val} +@cindex changing section address +Set or change both the VMA address and the LMA address of the named +@var{section}. If @samp{=} is used, the section address is set to +@var{val}. Otherwise, @var{val} is added to or subtracted from the +section address. See the comments under @samp{--change-addresses}, +above. If @var{section} does not exist in the input file, a warning will +be issued, unless @samp{--no-change-warnings} is used. + +@item --change-section-lma @var{section}@{=,+,-@}@var{val} +@cindex changing section LMA +Set or change the LMA address of the named @var{section}. The LMA +address is the address where the section will be loaded into memory at +program load time. Normally this is the same as the VMA address, which +is the address of the section at program run time, but on some systems, +especially those where a program is held in ROM, the two can be +different. If @samp{=} is used, the section address is set to +@var{val}. Otherwise, @var{val} is added to or subtracted from the +section address. See the comments under @samp{--change-addresses}, +above. If @var{section} does not exist in the input file, a warning +will be issued, unless @samp{--no-change-warnings} is used. + +@item --change-section-vma @var{section}@{=,+,-@}@var{val} +@cindex changing section VMA +Set or change the VMA address of the named @var{section}. The VMA +address is the address where the section will be located once the +program has started executing. Normally this is the same as the LMA +address, which is the address where the section will be loaded into +memory, but on some systems, especially those where a program is held in +ROM, the two can be different. If @samp{=} is used, the section address +is set to @var{val}. Otherwise, @var{val} is added to or subtracted +from the section address. See the comments under +@samp{--change-addresses}, above. If @var{section} does not exist in +the input file, a warning will be issued, unless +@samp{--no-change-warnings} is used. + +@item --change-warnings +@itemx --adjust-warnings +If @samp{--change-section-address} or @samp{--change-section-lma} or +@samp{--change-section-vma} is used, and the named section does not +exist, issue a warning. This is the default. + +@item --no-change-warnings +@itemx --no-adjust-warnings +Do not issue a warning if @samp{--change-section-address} or +@samp{--adjust-section-lma} or @samp{--adjust-section-vma} is used, even +if the named section does not exist. + +@item --set-section-flags @var{section}=@var{flags} +Set the flags for the named section. The @var{flags} argument is a +comma separated string of flag names. The recognized names are +@samp{alloc}, @samp{contents}, @samp{load}, @samp{readonly}, +@samp{code}, @samp{data}, and @samp{rom}. You can set the +@samp{contents} flag for a section which does not have contents, but it +is not meaningful to clear the @samp{contents} flag of a section which +does have contents--just remove the section instead. Not all flags are +meaningful for all object file formats. + +@item --add-section @var{sectionname}=@var{filename} +Add a new section named @var{sectionname} while copying the file. The +contents of the new section are taken from the file @var{filename}. The +size of the section will be the size of the file. This option only +works on file formats which can support sections with arbitrary names. + +@item --change-leading-char +Some object file formats use special characters at the start of +symbols. The most common such character is underscore, which compilers +often add before every symbol. This option tells @code{objcopy} to +change the leading character of every symbol when it converts between +object file formats. If the object file formats use the same leading +character, this option has no effect. Otherwise, it will add a +character, or remove a character, or change a character, as +appropriate. + +@item --remove-leading-char +If the first character of a global symbol is a special symbol leading +character used by the object file format, remove the character. The +most common symbol leading character is underscore. This option will +remove a leading underscore from all global symbols. This can be useful +if you want to link together objects of different file formats with +different conventions for symbol names. This is different from +@code{--change-leading-char} because it always changes the symbol name +when appropriate, regardless of the object file format of the output +file. + +@item --weaken +Change all global symbols in the file to be weak. This can be useful +when building an object which will be linked against other objects using +the @code{-R} option to the linker. This option is only effective when +using an object file format which supports weak symbols. + +@item -V +@itemx --version +Show the version number of @code{objcopy}. + +@item -v +@itemx --verbose +Verbose output: list all object files modified. In the case of +archives, @samp{objcopy -V} lists all members of the archive. + +@item --help +Show a summary of the options to @code{objcopy}. +@end table + +@node objdump +@chapter objdump + +@cindex object file information +@kindex objdump + +@smallexample +objdump [ -a | --archive-headers ] + [ -b @var{bfdname} | --target=@var{bfdname} ] [ --debugging ] + [ -C | --demangle ] [ -d | --disassemble ] + [ -D | --disassemble-all ] [ --disassemble-zeroes ] + [ -EB | -EL | --endian=@{big | little @} ] + [ -f | --file-headers ] + [ -h | --section-headers | --headers ] [ -i | --info ] + [ -j @var{section} | --section=@var{section} ] + [ -l | --line-numbers ] [ -S | --source ] + [ -m @var{machine} | --architecture=@var{machine} ] + [ -p | --private-headers ] + [ -r | --reloc ] [ -R | --dynamic-reloc ] + [ -s | --full-contents ] [ --stabs ] + [ -t | --syms ] [ -T | --dynamic-syms ] [ -x | --all-headers ] + [ -w | --wide ] [ --start-address=@var{address} ] + [ --stop-address=@var{address} ] + [ --prefix-addresses] [ --[no-]show-raw-insn ] + [ --adjust-vma=@var{offset} ] + [ --version ] [ --help ] + @var{objfile}@dots{} +@end smallexample + +@code{objdump} displays information about one or more object files. +The options control what particular information to display. This +information is mostly useful to programmers who are working on the +compilation tools, as opposed to programmers who just want their +program to compile and work. + +@var{objfile}@dots{} are the object files to be examined. When you +specify archives, @code{objdump} shows information on each of the member +object files. + +The long and short forms of options, shown here as alternatives, are +equivalent. At least one option besides @samp{-l} must be given. + +@table @code +@item -a +@itemx --archive-header +@cindex archive headers +If any of the @var{objfile} files are archives, display the archive +header information (in a format similar to @samp{ls -l}). Besides the +information you could list with @samp{ar tv}, @samp{objdump -a} shows +the object file format of each archive member. + +@item --adjust-vma=@var{offset} +@cindex section addresses in objdump +@cindex VMA in objdump +When dumping information, first add @var{offset} to all the section +addresses. This is useful if the section addresses do not correspond to +the symbol table, which can happen when putting sections at particular +addresses when using a format which can not represent section addresses, +such as a.out. + +@item -b @var{bfdname} +@itemx --target=@var{bfdname} +@cindex object code format +Specify that the object-code format for the object files is +@var{bfdname}. This option may not be necessary; @var{objdump} can +automatically recognize many formats. + +For example, +@example +objdump -b oasys -m vax -h fu.o +@end example +@noindent +displays summary information from the section headers (@samp{-h}) of +@file{fu.o}, which is explicitly identified (@samp{-m}) as a VAX object +file in the format produced by Oasys compilers. You can list the +formats available with the @samp{-i} option. +@xref{Target Selection}, for more information. + +@item -C +@itemx --demangle +@cindex demangling in objdump +Decode (@dfn{demangle}) low-level symbol names into user-level names. +Besides removing any initial underscore prepended by the system, this +makes C++ function names readable. @xref{c++filt}, for more information +on demangling. + +@item --debugging +Display debugging information. This attempts to parse debugging +information stored in the file and print it out using a C like syntax. +Only certain types of debugging information have been implemented. + +@item -d +@itemx --disassemble +@cindex disassembling object code +@cindex machine instructions +Display the assembler mnemonics for the machine instructions from +@var{objfile}. This option only disassembles those sections which are +expected to contain instructions. + +@item -D +@itemx --disassemble-all +Like @samp{-d}, but disassemble the contents of all sections, not just +those expected to contain instructions. + +@item --prefix-addresses +When disassembling, print the complete address on each line. This is +the older disassembly format. + +@item --disassemble-zeroes +Normally the disassembly output will skip blocks of zeroes. This +option directs the disassembler to disassemble those blocks, just like +any other data. + +@item -EB +@itemx -EL +@itemx --endian=@{big|little@} +@cindex endianness +@cindex disassembly endianness +Specify the endianness of the object files. This only affects +disassembly. This can be useful when disassembling a file format which +does not describe endianness information, such as S-records. + +@item -f +@itemx --file-header +@cindex object file header +Display summary information from the overall header of +each of the @var{objfile} files. + +@item -h +@itemx --section-header +@itemx --header +@cindex section headers +Display summary information from the section headers of the +object file. + +File segments may be relocated to nonstandard addresses, for example by +using the @samp{-Ttext}, @samp{-Tdata}, or @samp{-Tbss} options to +@code{ld}. However, some object file formats, such as a.out, do not +store the starting address of the file segments. In those situations, +although @code{ld} relocates the sections correctly, using @samp{objdump +-h} to list the file section headers cannot show the correct addresses. +Instead, it shows the usual addresses, which are implicit for the +target. + +@item --help +Print a summary of the options to @code{objdump} and exit. + +@item -i +@itemx --info +@cindex architectures available +@cindex object formats available +Display a list showing all architectures and object formats available +for specification with @samp{-b} or @samp{-m}. + +@item -j @var{name} +@itemx --section=@var{name} +@cindex section information +Display information only for section @var{name}. + +@item -l +@itemx --line-numbers +@cindex source filenames for object files +Label the display (using debugging information) with the filename and +source line numbers corresponding to the object code or relocs shown. +Only useful with @samp{-d}, @samp{-D}, or @samp{-r}. + +@item -m @var{machine} +@itemx --architecture=@var{machine} +@cindex architecture +@cindex disassembly architecture +Specify the architecture to use when disassembling object files. This +can be useful when disassembling object files which do not describe +architecture information, such as S-records. You can list the available +architectures with the @samp{-i} option. + +@item -p +@itemx --private-headers +Print information that is specific to the object file format. The exact +information printed depends upon the object file format. For some +object file formats, no additional information is printed. + +@item -r +@itemx --reloc +@cindex relocation entries, in object file +Print the relocation entries of the file. If used with @samp{-d} or +@samp{-D}, the relocations are printed interspersed with the +disassembly. + +@item -R +@itemx --dynamic-reloc +@cindex dynamic relocation entries, in object file +Print the dynamic relocation entries of the file. This is only +meaningful for dynamic objects, such as certain types of shared +libraries. + +@item -s +@itemx --full-contents +@cindex sections, full contents +@cindex object file sections +Display the full contents of any sections requested. + +@item -S +@itemx --source +@cindex source disassembly +@cindex disassembly, with source +Display source code intermixed with disassembly, if possible. Implies +@samp{-d}. + +@item --show-raw-insn +When disassembling instructions, print the instruction in hex as well as +in symbolic form. This is the default except when +@code{--prefix-addresses} is used. + +@item --no-show-raw-insn +When disassembling instructions, do not print the instruction bytes. +This is the default when @code{--prefix-addresses} is used. + +@item --stabs +@cindex stab +@cindex .stab +@cindex debug symbols +@cindex ELF object file format +Display the full contents of any sections requested. Display the +contents of the .stab and .stab.index and .stab.excl sections from an +ELF file. This is only useful on systems (such as Solaris 2.0) in which +@code{.stab} debugging symbol-table entries are carried in an ELF +section. In most other file formats, debugging symbol-table entries are +interleaved with linkage symbols, and are visible in the @samp{--syms} +output. For more information on stabs symbols, see @ref{Top,Stabs,Stabs +Overview,stabs.info, The ``stabs'' debug format}. + +@item --start-address=@var{address} +@cindex start-address +Start displaying data at the specified address. This affects the output +of the @code{-d}, @code{-r} and @code{-s} options. + +@item --stop-address=@var{address} +@cindex stop-address +Stop displaying data at the specified address. This affects the output +of the @code{-d}, @code{-r} and @code{-s} options. + +@item -t +@itemx --syms +@cindex symbol table entries, printing +Print the symbol table entries of the file. +This is similar to the information provided by the @samp{nm} program. + +@item -T +@itemx --dynamic-syms +@cindex dynamic symbol table entries, printing +Print the dynamic symbol table entries of the file. This is only +meaningful for dynamic objects, such as certain types of shared +libraries. This is similar to the information provided by the @samp{nm} +program when given the @samp{-D} (@samp{--dynamic}) option. + +@item --version +Print the version number of @code{objdump} and exit. + +@item -x +@itemx --all-header +@cindex all header information, object file +@cindex header information, all +Display all available header information, including the symbol table and +relocation entries. Using @samp{-x} is equivalent to specifying all of +@samp{-a -f -h -r -t}. + +@item -w +@itemx --wide +@cindex wide output, printing +Format some lines for output devices that have more than 80 columns. +@end table + +@node ranlib +@chapter ranlib + +@kindex ranlib +@cindex archive contents +@cindex symbol index + +@smallexample +ranlib [-vV] @var{archive} +@end smallexample + +@code{ranlib} generates an index to the contents of an archive and +stores it in the archive. The index lists each symbol defined by a +member of an archive that is a relocatable object file. + +You may use @samp{nm -s} or @samp{nm --print-armap} to list this index. + +An archive with such an index speeds up linking to the library and +allows routines in the library to call each other without regard to +their placement in the archive. + +The @sc{gnu} @code{ranlib} program is another form of @sc{gnu} @code{ar}; running +@code{ranlib} is completely equivalent to executing @samp{ar -s}. +@xref{ar}. + +@table @code +@item -v +@itemx -V +Show the version number of @code{ranlib}. +@end table + +@node size +@chapter size + +@kindex size +@cindex section sizes + +@smallexample +size [ -A | -B | --format=@var{compatibility} ] + [ --help ] [ -d | -o | -x | --radix=@var{number} ] + [ --target=@var{bfdname} ] [ -V | --version ] + [ @var{objfile}@dots{} ] +@end smallexample + +The @sc{gnu} @code{size} utility lists the section sizes---and the total +size---for each of the object or archive files @var{objfile} in its +argument list. By default, one line of output is generated for each +object file or each module in an archive. + +@var{objfile}@dots{} are the object files to be examined. +If none are specified, the file @code{a.out} will be used. + +The command line options have the following meanings: + +@table @code +@item -A +@itemx -B +@itemx --format=@var{compatibility} +@cindex @code{size} display format +Using one of these options, you can choose whether the output from @sc{gnu} +@code{size} resembles output from System V @code{size} (using @samp{-A}, +or @samp{--format=sysv}), or Berkeley @code{size} (using @samp{-B}, or +@samp{--format=berkeley}). The default is the one-line format similar to +Berkeley's. +@c Bonus for doc-source readers: you can also say --format=strange (or +@c anything else that starts with 's') for sysv, and --format=boring (or +@c anything else that starts with 'b') for Berkeley. + +Here is an example of the Berkeley (default) format of output from +@code{size}: +@smallexample +size --format=Berkeley ranlib size +text data bss dec hex filename +294880 81920 11592 388392 5ed28 ranlib +294880 81920 11888 388688 5ee50 size +@end smallexample + +@noindent +This is the same data, but displayed closer to System V conventions: + +@smallexample +size --format=SysV ranlib size +ranlib : +section size addr +.text 294880 8192 +.data 81920 303104 +.bss 11592 385024 +Total 388392 + + +size : +section size addr +.text 294880 8192 +.data 81920 303104 +.bss 11888 385024 +Total 388688 +@end smallexample + +@item --help +Show a summary of acceptable arguments and options. + +@item -d +@itemx -o +@itemx -x +@itemx --radix=@var{number} +@cindex @code{size} number format +@cindex radix for section sizes +Using one of these options, you can control whether the size of each +section is given in decimal (@samp{-d}, or @samp{--radix=10}); octal +(@samp{-o}, or @samp{--radix=8}); or hexadecimal (@samp{-x}, or +@samp{--radix=16}). In @samp{--radix=@var{number}}, only the three +values (8, 10, 16) are supported. The total size is always given in two +radices; decimal and hexadecimal for @samp{-d} or @samp{-x} output, or +octal and hexadecimal if you're using @samp{-o}. + +@item --target=@var{bfdname} +@cindex object code format +Specify that the object-code format for @var{objfile} is +@var{bfdname}. This option may not be necessary; @code{size} can +automatically recognize many formats. +@xref{Target Selection}, for more information. + +@item -V +@itemx --version +Display the version number of @code{size}. +@end table + +@node strings +@chapter strings +@kindex strings +@cindex listings strings +@cindex printing strings +@cindex strings, printing + +@smallexample +strings [-afov] [-@var{min-len}] [-n @var{min-len}] [-t @var{radix}] [-] + [--all] [--print-file-name] [--bytes=@var{min-len}] + [--radix=@var{radix}] [--target=@var{bfdname}] + [--help] [--version] @var{file}@dots{} +@end smallexample + +For each @var{file} given, @sc{gnu} @code{strings} prints the printable +character sequences that are at least 4 characters long (or the number +given with the options below) and are followed by an unprintable +character. By default, it only prints the strings from the initialized +and loaded sections of object files; for other types of files, it prints +the strings from the whole file. + +@code{strings} is mainly useful for determining the contents of non-text +files. + +@table @code +@item -a +@itemx --all +@itemx - +Do not scan only the initialized and loaded sections of object files; +scan the whole files. + +@item -f +@itemx --print-file-name +Print the name of the file before each string. + +@item --help +Print a summary of the program usage on the standard output and exit. + +@item -@var{min-len} +@itemx -n @var{min-len} +@itemx --bytes=@var{min-len} +Print sequences of characters that are at least @var{min-len} characters +long, instead of the default 4. + +@item -o +Like @samp{-t o}. Some other versions of @code{strings} have @samp{-o} +act like @samp{-t d} instead. Since we can not be compatible with both +ways, we simply chose one. + +@item -t @var{radix} +@itemx --radix=@var{radix} +Print the offset within the file before each string. The single +character argument specifies the radix of the offset---@samp{o} for +octal, @samp{x} for hexadecimal, or @samp{d} for decimal. + +@item --target=@var{bfdname} +@cindex object code format +Specify an object code format other than your system's default format. +@xref{Target Selection}, for more information. + +@item -v +@itemx --version +Print the program version number on the standard output and exit. +@end table + +@node strip +@chapter strip + +@kindex strip +@cindex removing symbols +@cindex discarding symbols +@cindex symbols, discarding + +@smallexample +strip [ -F @var{bfdname} | --target=@var{bfdname} ] + [ -I @var{bfdname} | --input-target=@var{bfdname} ] + [ -O @var{bfdname} | --output-target=@var{bfdname} ] + [ -s | --strip-all ] [ -S | -g | --strip-debug ] + [ -K @var{symbolname} | --keep-symbol=@var{symbolname} ] + [ -N @var{symbolname} | --strip-symbol=@var{symbolname} ] + [ -x | --discard-all ] [ -X | --discard-locals ] + [ -R @var{sectionname} | --remove-section=@var{sectionname} ] + [ -o @var{file} ] [ -p | --preserve-dates ] + [ -v | --verbose ] [ -V | --version ] [ --help ] + @var{objfile}@dots{} +@end smallexample + +@sc{gnu} @code{strip} discards all symbols from object files +@var{objfile}. The list of object files may include archives. +At least one object file must be given. + +@code{strip} modifies the files named in its argument, +rather than writing modified copies under different names. + +@table @code +@item -F @var{bfdname} +@itemx --target=@var{bfdname} +Treat the original @var{objfile} as a file with the object +code format @var{bfdname}, and rewrite it in the same format. +@xref{Target Selection}, for more information. + +@item --help +Show a summary of the options to @code{strip} and exit. + +@item -I @var{bfdname} +@itemx --input-target=@var{bfdname} +Treat the original @var{objfile} as a file with the object +code format @var{bfdname}. +@xref{Target Selection}, for more information. + +@item -O @var{bfdname} +@itemx --output-target=@var{bfdname} +Replace @var{objfile} with a file in the output format @var{bfdname}. +@xref{Target Selection}, for more information. + +@item -R @var{sectionname} +@itemx --remove-section=@var{sectionname} +Remove any section named @var{sectionname} from the output file. This +option may be given more than once. Note that using this option +inappropriately may make the output file unusable. + +@item -s +@itemx --strip-all +Remove all symbols. + +@item -g +@itemx -S +@itemx --strip-debug +Remove debugging symbols only. + +@item --strip-unneeded +Remove all symbols that are not needed for relocation processing. + +@item -K @var{symbolname} +@itemx --keep-symbol=@var{symbolname} +Keep only symbol @var{symbolname} from the source file. This option may +be given more than once. + +@item -N @var{symbolname} +@itemx --strip-symbol=@var{symbolname} +Remove symbol @var{symbolname} from the source file. This option may be +given more than once, and may be combined with strip options other than +@code{-K}. + +@item -o @var{file} +Put the stripped output in @var{file}, rather than replacing the +existing file. When this argument is used, only one @var{objfile} +argument may be specified. + +@item -p +@itemx --preserve-dates +Preserve the access and modification dates of the file. + +@item -x +@itemx --discard-all +Remove non-global symbols. + +@item -X +@itemx --discard-locals +Remove compiler-generated local symbols. +(These usually start with @samp{L} or @samp{.}.) + +@item -V +@itemx --version +Show the version number for @code{strip}. + +@item -v +@itemx --verbose +Verbose output: list all object files modified. In the case of +archives, @samp{strip -v} lists all members of the archive. +@end table + +@node c++filt +@chapter c++filt + +@kindex c++filt +@cindex demangling C++ symbols + +@smallexample +c++filt [ -_ | --strip-underscores ] + [ -j | --java ] + [ -n | --no-strip-underscores ] + [ -s @var{format} | --format=@var{format} ] + [ --help ] [ --version ] [ @var{symbol}@dots{} ] +@end smallexample + +The C++ and Java languages provides function overloading, which means +that you can write many functions with the same name (providing each +takes parameters of different types). All C++ and Java function names +are encoded into a low-level assembly label (this process is known as +@dfn{mangling}). The @code{c++filt} program does the inverse mapping: it +decodes (@dfn{demangles}) low-level names into user-level names so that +the linker can keep these overloaded functions from clashing. + +Every alphanumeric word (consisting of letters, digits, underscores, +dollars, or periods) seen in the input is a potential label. If the +label decodes into a C++ name, the C++ name replaces the low-level +name in the output. + +You can use @code{c++filt} to decipher individual symbols: + +@example +c++filt @var{symbol} +@end example + +If no @var{symbol} arguments are given, @code{c++filt} reads symbol +names from the standard input and writes the demangled names to the +standard output. All results are printed on the standard output. + +@table @code +@item -_ +@itemx --strip-underscores +On some systems, both the C and C++ compilers put an underscore in front +of every name. For example, the C name @code{foo} gets the low-level +name @code{_foo}. This option removes the initial underscore. Whether +@code{c++filt} removes the underscore by default is target dependent. + +@item -j +@itemx --java +Prints demangled names using Java syntax. The default is to use C++ +syntax. + +@item -n +@itemx --no-strip-underscores +Do not remove the initial underscore. + +@item -s @var{format} +@itemx --format=@var{format} +@sc{gnu} @code{nm} can decode three different methods of mangling, used by +different C++ compilers. The argument to this option selects which +method it uses: + +@table @code +@item gnu +the one used by the @sc{gnu} compiler (the default method) +@item lucid +the one used by the Lucid compiler +@item arm +the one specified by the C++ Annotated Reference Manual +@item hp +the one used by the HP compiler +@item edg +the one used by the EDG compiler +@end table + +@item --help +Print a summary of the options to @code{c++filt} and exit. + +@item --version +Print the version number of @code{c++filt} and exit. +@end table + +@quotation +@emph{Warning:} @code{c++filt} is a new utility, and the details of its +user interface are subject to change in future releases. In particular, +a command-line option may be required in the the future to decode a name +passed as an argument on the command line; in other words, + +@example +c++filt @var{symbol} +@end example + +@noindent +may in a future release become + +@example +c++filt @var{option} @var{symbol} +@end example +@end quotation + +@node addr2line +@chapter addr2line + +@kindex addr2line +@cindex address to file name and line number + +@smallexample +addr2line [ -b @var{bfdname} | --target=@var{bfdname} ] + [ -C | --demangle ] + [ -e @var{filename} | --exe=@var{filename} ] + [ -f | --functions ] [ -s | --basename ] + [ -H | --help ] [ -V | --version ] + [ addr addr ... ] +@end smallexample + +@code{addr2line} translates program addresses into file names and line +numbers. Given an address and an executable, it uses the debugging +information in the executable to figure out which file name and line +number are associated with a given address. + +The executable to use is specified with the @code{-e} option. The +default is @file{a.out}. + +@code{addr2line} has two modes of operation. + +In the first, hexadecimal addresses are specified on the command line, +and @code{addr2line} displays the file name and line number for each +address. + +In the second, @code{addr2line} reads hexadecimal addresses from +standard input, and prints the file name and line number for each +address on standard output. In this mode, @code{addr2line} may be used +in a pipe to convert dynamically chosen addresses. + +The format of the output is @samp{FILENAME:LINENO}. The file name and +line number for each address is printed on a separate line. If the +@code{-f} option is used, then each @samp{FILENAME:LINENO} line is +preceded by a @samp{FUNCTIONNAME} line which is the name of the function +containing the address. + +If the file name or function name can not be determined, +@code{addr2line} will print two question marks in their place. If the +line number can not be determined, @code{addr2line} will print 0. + +The long and short forms of options, shown here as alternatives, are +equivalent. + +@table @code +@item -b @var{bfdname} +@itemx --target=@var{bfdname} +@cindex object code format +Specify that the object-code format for the object files is +@var{bfdname}. + +@item -C +@itemx --demangle +@cindex demangling in objdump +Decode (@dfn{demangle}) low-level symbol names into user-level names. +Besides removing any initial underscore prepended by the system, this +makes C++ function names readable. @xref{c++filt}, for more information +on demangling. + +@item -e @var{filename} +@itemx --exe=@var{filename} +Specify the name of the executable for which addresses should be +translated. The default file is @file{a.out}. + +@item -f +@itemx --functions +Display function names as well as file and line number information. + +@item -s +@itemx --basenames +Display only the base of each file name. +@end table + +@node nlmconv +@chapter nlmconv + +@code{nlmconv} converts a relocatable object file into a NetWare +Loadable Module. + +@ignore +@code{nlmconv} currently works with @samp{i386} object +files in @code{coff}, @sc{elf}, or @code{a.out} format, and @sc{SPARC} +object files in @sc{elf}, or @code{a.out} format@footnote{ +@code{nlmconv} should work with any @samp{i386} or @sc{sparc} object +format in the Binary File Descriptor library. It has only been tested +with the above formats.}. +@end ignore + +@quotation +@emph{Warning:} @code{nlmconv} is not always built as part of the binary +utilities, since it is only useful for NLM targets. +@end quotation + +@smallexample +nlmconv [ -I @var{bfdname} | --input-target=@var{bfdname} ] + [ -O @var{bfdname} | --output-target=@var{bfdname} ] + [ -T @var{headerfile} | --header-file=@var{headerfile} ] + [ -d | --debug] [ -l @var{linker} | --linker=@var{linker} ] + [ -h | --help ] [ -V | --version ] + @var{infile} @var{outfile} +@end smallexample + +@code{nlmconv} converts the relocatable @samp{i386} object file +@var{infile} into the NetWare Loadable Module @var{outfile}, optionally +reading @var{headerfile} for NLM header information. For instructions +on writing the NLM command file language used in header files, see the +@samp{linkers} section, @samp{NLMLINK} in particular, of the @cite{NLM +Development and Tools Overview}, which is part of the NLM Software +Developer's Kit (``NLM SDK''), available from Novell, Inc. +@code{nlmconv} uses the @sc{gnu} Binary File Descriptor library to read +@var{infile}; see @ref{BFD,,BFD,ld.info,Using LD}, for +more information. + +@code{nlmconv} can perform a link step. In other words, you can list +more than one object file for input if you list them in the definitions +file (rather than simply specifying one input file on the command line). +In this case, @code{nlmconv} calls the linker for you. + +@table @code +@item -I @var{bfdname} +@itemx --input-target=@var{bfdname} +Object format of the input file. @code{nlmconv} can usually determine +the format of a given file (so no default is necessary). +@xref{Target Selection}, for more information. + +@item -O @var{bfdname} +@itemx --output-target=@var{bfdname} +Object format of the output file. @code{nlmconv} infers the output +format based on the input format, e.g. for a @samp{i386} input file the +output format is @samp{nlm32-i386}. +@xref{Target Selection}, for more information. + +@item -T @var{headerfile} +@itemx --header-file=@var{headerfile} +Reads @var{headerfile} for NLM header information. For instructions on +writing the NLM command file language used in header files, see@ see the +@samp{linkers} section, of the @cite{NLM Development and Tools +Overview}, which is part of the NLM Software Developer's Kit, available +from Novell, Inc. + +@item -d +@itemx --debug +Displays (on standard error) the linker command line used by @code{nlmconv}. + +@item -l @var{linker} +@itemx --linker=@var{linker} +Use @var{linker} for any linking. @var{linker} can be an absolute or a +relative pathname. + +@item -h +@itemx --help +Prints a usage summary. + +@item -V +@itemx --version +Prints the version number for @code{nlmconv}. +@end table + +@node windres +@chapter windres + +@code{windres} may be used to manipulate Windows resources. + +@quotation +@emph{Warning:} @code{windres} is not always built as part of the binary +utilities, since it is only useful for Windows targets. +@end quotation + +@smallexample +windres [options] [input-file] [output-file] +@end smallexample + +@code{windres} reads resources from an input file and copies them into +an output file. Either file may be in one of three formats: + +@table @code +@item rc +A text format read by the Resource Compiler. + +@item res +A binary format generated by the Resource Compiler. + +@item coff +A COFF object or executable. +@end table + +The exact description of these different formats is available in +documentation from Microsoft. + +When @code{windres} converts from the @code{rc} format to the @code{res} +format, it is acting like the Windows Resource Compiler. When +@code{windres} converts from the @code{res} format to the @code{coff} +format, it is acting like the Windows @code{CVTRES} program. + +When @code{windres} generates an @code{rc} file, the output is similar +but not identical to the format expected for the input. When an input +@code{rc} file refers to an external filename, an output @code{rc} file +will instead include the file contents. + +If the input or output format is not specified, @code{windres} will +guess based on the file name, or, for the input file, the file contents. +A file with an extension of @file{.rc} will be treated as an @code{rc} +file, a file with an extension of @file{.res} will be treated as a +@code{res} file, and a file with an extension of @file{.o} or +@file{.exe} will be treated as a @code{coff} file. + +If no output file is specified, @code{windres} will print the resources +in @code{rc} format to standard output. + +The normal use is for you to write an @code{rc} file, use @code{windres} +to convert it to a COFF object file, and then link the COFF file into +your application. This will make the resources described in the +@code{rc} file available to Windows. + +@table @code +@item -i @var{filename} +@itemx --input @var{filename} +The name of the input file. If this option is not used, then +@code{windres} will use the first non-option argument as the input file +name. If there are no non-option arguments, then @code{windres} will +read from standard input. @code{windres} can not read a COFF file from +standard input. + +@item -o @var{filename} +@itemx --output @var{filename} +The name of the output file. If this option is not used, then +@code{windres} will use the first non-option argument, after any used +for the input file name, as the output file name. If there is no +non-option argument, then @code{windres} will write to standard output. +@code{windres} can not write a COFF file to standard output. + +@item -I @var{format} +@itemx --input-format @var{format} +The input format to read. @var{format} may be @samp{res}, @samp{rc}, or +@samp{coff}. If no input format is specified, @code{windres} will +guess, as described above. + +@item -O @var{format} +@itemx --output-format @var{format} +The output format to generate. @var{format} may be @samp{res}, +@samp{rc}, or @samp{coff}. If no output format is specified, +@code{windres} will guess, as described above. + +@item -F @var{target} +@itemx --target @var{target} +Specify the BFD format to use for a COFF file as input or output. This +is a BFD target name; you can use the @code{--help} option to see a list +of supported targets. Normally @code{windres} will use the default +format, which is the first one listed by the @code{--help} option. +@ref{Target Selection}. + +@item --preprocessor @var{program} +When @code{windres} reads an @code{rc} file, it runs it through the C +preprocessor first. This option may be used to specify the preprocessor +to use, including any leading arguments. The default preprocessor +argument is @code{gcc -E -xc-header -DRC_INVOKED}. + +@item --include-dir @var{directory} +Specify an include directory to use when reading an @code{rc} file. +@code{windres} will pass this to the preprocessor as an @code{-I} +option. @code{windres} will also search this directory when looking for +files named in the @code{rc} file. + +@item --define @var{sym[=val]} +Specify a @code{-D} option to pass to the preprocessor when reading an +@code{rc} file. + +@item --language @var{val} +Specify the default language to use when reading an @code{rc} file. +@var{val} should be a hexadecimal language code. The low eight bits are +the language, and the high eight bits are the sublanguage. + +@item --help +Prints a usage summary. + +@item --version +Prints the version number for @code{windres}. + +@item --yydebug +If @code{windres} is compiled with @code{YYDEBUG} defined as @code{1}, +this will turn on parser debugging. +@end table + + +@node dlltool +@chapter Create files needed to build and use DLLs +@cindex DLL +@kindex dlltool + +@code{dlltool} may be used to create the files needed to build and use +dynamic link libraries (DLLs). + +@quotation +@emph{Warning:} @code{dlltool} is not always built as part of the binary +utilities, since it is only useful for those targets which support DLLs. +@end quotation + +@smallexample +dlltool [-d|--input-def @var{def-file-name}] + [-b|--base-file @var{base-file-name}] + [-e|--output-exp @var{exports-file-name}] + [-z|--output-def @var{def-file-name}] + [-l|--output-lib @var{library-file-name}] + [--export-all-symbols] [--no-export-all-symbols] + [--exclude-symbols @var{list}] + [--no-default-excludes] + [-S|--as @var{path-to-assembler}] [-f|--as-flags @var{options}] + [-D|--dllname @var{name}] [-m|--machine @var{machine}] + [-a|--add-indirect] [-U|--add-underscore] [-k|--kill-at] + [-A|--add-stdcall-alias] + [-x|--no-idata4] [-c|--no-idata5] [-i|--interwork] + [-n|--nodelete] [-v|--verbose] [-h|--help] [-V|--version] + [object-file @dots{}] +@end smallexample + +@code{dlltool} reads its inputs, which can come from the @samp{-d} and +@samp{-b} options as well as object files specified on the command +line. It then processes these inputs and if the @samp{-e} option has +been specified it creates a exports file. If the @samp{-l} option +has been specified it creates a library file and if the @samp{-z} option +has been specified it creates a def file. Any or all of the -e, -l +and -z options can be present in one invocation of dlltool. + +When creating a DLL, along with the source for the DLL, it is necessary +to have three other files. @code{dlltool} can help with the creation of +these files. + +The first file is a @samp{.def} file which specifies which functions are +exported from the DLL, which functions the DLL imports, and so on. This +is a text file and can be created by hand, or @code{dlltool} can be used +to create it using the @samp{-z} option. In this case @code{dlltool} +will scan the object files specified on its command line looking for +those functions which have been specially marked as being exported and +put entries for them in the .def file it creates. + +In order to mark a function as being exported from a DLL, it needs to +have an @samp{-export:<name_of_function>} entry in the @samp{.drectve} +section of the object file. This can be done in C by using the +asm() operator: + +@smallexample + asm (".section .drectve"); + asm (".ascii \"-export:my_func\""); + + int my_func (void) @{ @dots{} @} +@end smallexample + +The second file needed for DLL creation is an exports file. This file +is linked with the object files that make up the body of the DLL and it +handles the interface between the DLL and the outside world. This is a +binary file and it can be created by giving the @samp{-e} option to +@code{dlltool} when it is creating or reading in a .def file. + +The third file needed for DLL creation is the library file that programs +will link with in order to access the functions in the DLL. This file +can be created by giving the @samp{-l} option to dlltool when it +is creating or reading in a .def file. + +@code{dlltool} builds the library file by hand, but it builds the +exports file by creating temporary files containing assembler statements +and then assembling these. The @samp{-S} command line option can be +used to specify the path to the assembler that dlltool will use, +and the @samp{-f} option can be used to pass specific flags to that +assembler. The @samp{-n} can be used to prevent dlltool from deleting +these temporary assembler files when it is done, and if @samp{-n} is +specified twice then this will prevent dlltool from deleting the +temporary object files it used to build the library. + +Here is an example of creating a DLL from a source file @samp{dll.c} and +also creating a program (from an object file called @samp{program.o}) +that uses that DLL: + +@smallexample + gcc -c dll.c + dlltool -e exports.o -l dll.lib dll.o + gcc dll.o exports.o -o dll.dll + gcc program.o dll.lib -o program +@end smallexample + +The command line options have the following meanings: + +@table @code + +@item -d @var{filename} +@itemx --input-def @var{filename} +@cindex input .def file +Specifies the name of a .def file to be read in and processed. + +@item -b @var{filename} +@itemx --base-file @var{filename} +@cindex base files +Specifies the name of a base file to be read in and processed. The +contents of this file will be added to the relocation section in the +exports file generated by dlltool. + +@item -e @var{filename} +@itemx --output-exp @var{filename} +Specifies the name of the export file to be created by dlltool. + +@item -z @var{filename} +@itemx --output-def @var{filename} +Specifies the name of the .def file to be created by dlltool. + +@item -l @var{filename} +@itemx --output-lib @var{filename} +Specifies the name of the library file to be created by dlltool. + +@item --export-all-symbols +Treat all global and weak defined symbols found in the input object +files as symbols to be exported. There is a small list of symbols which +are not exported by default; see the @code{--no-default-excludes} +option. You may add to the list of symbols to not export by using the +@code{--exclude-symbols} option. + +@item --no-export-all-symbols +Only export symbols explicitly listed in an input .def file or in +@samp{.drectve} sections in the input object files. This is the default +behaviour. The @samp{.drectve} sections are created by @samp{dllexport} +attributes in the source code. + +@item --exclude-symbols @var{list} +Do not export the symbols in @var{list}. This is a list of symbol names +separated by comma or colon characters. The symbol names should not +contain a leading underscore. This is only meaningful when +@code{--export-all-symbols} is used. + +@item --no-default-excludes +When @code{--export-all-symbols} is used, it will by default avoid +exporting certain special symbols. The current list of symbols to avoid +exporting is @samp{DllMain@@12}, @samp{DllEntryPoint@@0}, +@samp{impure_ptr}. You may use the @code{--no-default-excludes} option +to go ahead and export these special symbols. This is only meaningful +when @code{--export-all-symbols} is used. + +@item -S @var{path} +@itemx --as @var{path} +Specifies the path, including the filename, of the assembler to be used +to create the exports file. + +@item -f @var{switches} +@itemx --as-flags @var{switches} +Specifies any specific command line switches to be passed to the +assembler when building the exports file. This option will work even if +the @samp{-S} option is not used. This option only takes one argument, +and if it occurs more than once on the command line, then later +occurrences will override earlier occurrences. So if it is necessary to +pass multiple switches to the assembler they should be enclosed in +double quotes. + +@item -D @var{name} +@itemx --dll-name @var{name} +Specifies the name to be stored in the .def file as the name of the DLL +when the @samp{-e} option is used. If this option is not present, then +the filename given to the @samp{-e} option will be used as the name of +the DLL. + +@item -m @var{machine} +@itemx -machine @var{machine} +Specifies the type of machine for which the library file should be +built. @code{dlltool} has a built in default type, depending upon how +it was created, but this option can be used to override that. This is +normally only useful when creating DLLs for an ARM processor, when the +contents of the DLL are actually encode using THUMB instructions. + +@item -a +@itemx --add-indirect +Specifies that when @code{dlltool} is creating the exports file it +should add a section which allows the exported functions to be +referenced without using the import library. Whatever the hell that +means! + +@item -U +@itemx --add-underscore +Specifies that when @code{dlltool} is creating the exports file it +should prepend an underscore to the names of the exported functions. + +@item -k +@itemx --kill-at +Specifies that when @code{dlltool} is creating the exports file it +should not append the string @samp{@@ <number>}. These numbers are +called ordinal numbers and they represent another way of accessing the +function in a DLL, other than by name. + +@item -A +@itemx --add-stdcall-alias +Specifies that when @code{dlltool} is creating the exports file it +should add aliases for stdcall symbols without @samp{@@ <number>} +in addition to the symbols with @samp{@@ <number>}. + +@item -x +@itemx --no-idata4 +Specifies that when @code{dlltool} is creating the exports and library +files it should omit the .idata4 section. This is for compatibility +with certain operating systems. + +@item -c +@itemx --no-idata5 +Specifies that when @code{dlltool} is creating the exports and library +files it should omit the .idata5 section. This is for compatibility +with certain operating systems. + +@item -i +@itemx --interwork +Specifies that @code{dlltool} should mark the objects in the library +file and exports file that it produces as supporting interworking +between ARM and THUMB code. + +@item -n +@itemx --nodelete +Makes @code{dlltool} preserve the temporary assembler files it used to +create the exports file. If this option is repeated then dlltool will +also preserve the temporary object files it uses to create the library +file. + +@item -v +@itemx --verbose +Make dlltool describe what it is doing. + +@item -h +@itemx --help +Displays a list of command line options and then exits. + +@item -V +@itemx --version +Displays dlltool's version number and then exits. + +@end table + +@node readelf +@chapter readelf + +@cindex ELF file information +@kindex readelf + +@smallexample +readelf [ -a | --all ] + [ -h | --file-header] + [ -l | --program-headers | --segments] + [ -S | --section-headers | --sections] + [ -e | --headers] + [ -s | --syms | --symbols] + [ -r | --relocs] + [ -d | --dynamic] + [ -V | --version-info] + [ -D | --use-dynamic] + [ -x <number> | --hex-dump=<number>] + [ -w[liapr] | --debug-dump[=info,=line,=abbrev,=pubnames,=ranges]] + [ --histogram] + [ -v | --version] + [ -H | --help] + @var{elffile}@dots{} +@end smallexample + +@code{readelf} displays information about one or more ELF format object +files. The options control what particular information to display. + +@var{elffile}@dots{} are the object files to be examined. At the +moment, @code{readelf} does not support examining archives, nor does it +support examing 64 bit ELF files. + +The long and short forms of options, shown here as alternatives, are +equivalent. At least one option besides @samp{-v} or @samp{-H} must be +given. + +@table @code +@item -a +@itemx --all +Equivalent to specifiying @samp{--file-header}, +@samp{--program-headers}, @samp{--sections}, @samp{--symbols}, +@samp{--relocs}, @samp{--dynamic} and @samp{--version-info}. + +@item -h +@itemx --file-header +@cindex ELF file header information +Displays the information contained in the ELF header at the start of the +file. + +@item -l +@itemx --program-headers +@itemx --segments +@cindex ELF program header information +@cindex ELF segment information +Displays the information contained in the file's segment headers, if it +has any. + +@item -S +@itemx --sections +@itemx --section-headers +@cindex ELF section information +Displays the information contained in the file's section headers, if it +has any. + +@item -s +@itemx --symbols +@itemx --syms +@cindex ELF symbol table information +Displays the entries in symbol table section of the file, if it has one. + +@item -e +@itemx --headers +Display all the headers in the file. Equivalent to @samp{-h -l -S}. + +@item -r +@itemx --relocs +@cindex ELF reloc information +Displays the contents of the file's relocation section, if it ha one. + +@item -d +@itemx --dynamic +@cindex ELF dynamic section information +Displays the contents of the file's dynamic section, if it has one. + +@item -V +@itemx --version-info +@cindex ELF version sections informations +Displays the contents of the version sections in the file, it they +exist. + +@item -D +@itemx --use-dynamic +When displaying symbols, this option makes @code{readelf} use the +symblol table in the file's dynamic section, rather than the one in the +symbols section. + +@item -x <number> +@itemx --hex-dump=<number> +Displays the contents of the indicated section as a hexadecimal dump. + +@item -w[liapr] +@itemx --debug-dump[=line,=info,=abbrev,=pubnames,=ranges] +Displays the contents of the debug sections in the file, if any are +present. If one of the optional letters or words follows the switch +then only data found in those specific sections will be dumped. + +@item --histogram +Display a histogram of bucket list lengths when displaying the contents +of the symbol tables. + +@item -v +@itemx --version +Display the version number of readelf. + +@item -H +@itemx --help +Display the command line options understood by @code{readelf}. + +@end table + + +@node Selecting The Target System +@chapter Selecting the target system + +You can specify three aspects of the target system to the @sc{gnu} +binary file utilities, each in several ways: + +@itemize @bullet +@item +the target + +@item +the architecture + +@item +the linker emulation (which applies to the linker only) +@end itemize + +In the following summaries, the lists of ways to specify values are in +order of decreasing precedence. The ways listed first override those +listed later. + +The commands to list valid values only list the values for which the +programs you are running were configured. If they were configured with +@samp{--enable-targets=all}, the commands list most of the available +values, but a few are left out; not all targets can be configured in at +once because some of them can only be configured @dfn{native} (on hosts +with the same type as the target system). + +@menu +* Target Selection:: +* Architecture Selection:: +* Linker Emulation Selection:: +@end menu + +@node Target Selection +@section Target Selection + +A @dfn{target} is an object file format. A given target may be +supported for multiple architectures (@pxref{Architecture Selection}). +A target selection may also have variations for different operating +systems or architectures. + +The command to list valid target values is @samp{objdump -i} +(the first column of output contains the relevant information). + +Some sample values are: @samp{a.out-hp300bsd}, @samp{ecoff-littlemips}, +@samp{a.out-sunos-big}. + +You can also specify a target using a configuration triplet. This is +the same sort of name that is passed to configure to specify a target. +When you use a configuration triplet as an argument, it must be fully +canonicalized. You can see the canonical version of a triplet by +running the shell script @file{config.sub} which is included with the +sources. + +Some sample configuration triplets are: @samp{m68k-hp-bsd}, +@samp{mips-dec-ultrix}, @samp{sparc-sun-sunos}. + +@subheading @code{objdump} Target + +Ways to specify: + +@enumerate +@item +command line option: @samp{-b} or @samp{--target} + +@item +environment variable @code{GNUTARGET} + +@item +deduced from the input file +@end enumerate + +@subheading @code{objcopy} and @code{strip} Input Target + +Ways to specify: + +@enumerate +@item +command line options: @samp{-I} or @samp{--input-target}, or @samp{-F} or @samp{--target} + +@item +environment variable @code{GNUTARGET} + +@item +deduced from the input file +@end enumerate + +@subheading @code{objcopy} and @code{strip} Output Target + +Ways to specify: + +@enumerate +@item +command line options: @samp{-O} or @samp{--output-target}, or @samp{-F} or @samp{--target} + +@item +the input target (see ``@code{objcopy} and @code{strip} Input Target'' above) + +@item +environment variable @code{GNUTARGET} + +@item +deduced from the input file +@end enumerate + +@subheading @code{nm}, @code{size}, and @code{strings} Target + +Ways to specify: + +@enumerate +@item +command line option: @samp{--target} + +@item +environment variable @code{GNUTARGET} + +@item +deduced from the input file +@end enumerate + +@subheading Linker Input Target + +Ways to specify: + +@enumerate +@item +command line option: @samp{-b} or @samp{--format} +(@pxref{Options,,Options,ld.info,Using LD}) + +@item +script command @code{TARGET} +(@pxref{Option Commands,,Option Commands,ld.info,Using LD}) + +@item +environment variable @code{GNUTARGET} +(@pxref{Environment,,Environment,ld.info,Using LD}) + +@item +the default target of the selected linker emulation +(@pxref{Linker Emulation Selection}) +@end enumerate + +@subheading Linker Output Target + +Ways to specify: + +@enumerate +@item +command line option: @samp{-oformat} +(@pxref{Options,,Options,ld.info,Using LD}) + +@item +script command @code{OUTPUT_FORMAT} +(@pxref{Option Commands,,Option Commands,ld.info,Using LD}) + +@item +the linker input target (see ``Linker Input Target'' above) +@end enumerate + +@node Architecture Selection +@section Architecture selection + +An @dfn{architecture} is a type of @sc{cpu} on which an object file is +to run. Its name may contain a colon, separating the name of the +processor family from the name of the particular @sc{cpu}. + +The command to list valid architecture values is @samp{objdump -i} (the +second column contains the relevant information). + +Sample values: @samp{m68k:68020}, @samp{mips:3000}, @samp{sparc}. + +@subheading @code{objdump} Architecture + +Ways to specify: + +@enumerate +@item +command line option: @samp{-m} or @samp{--architecture} + +@item +deduced from the input file +@end enumerate + +@subheading @code{objcopy}, @code{nm}, @code{size}, @code{strings} Architecture + +Ways to specify: + +@enumerate +@item +deduced from the input file +@end enumerate + +@subheading Linker Input Architecture + +Ways to specify: + +@enumerate +@item +deduced from the input file +@end enumerate + +@subheading Linker Output Architecture + +Ways to specify: + +@enumerate +@item +script command @code{OUTPUT_ARCH} +(@pxref{Option Commands,,Option Commands,ld.info,Using LD}) + +@item +the default architecture from the linker output target +(@pxref{Target Selection}) +@end enumerate + +@node Linker Emulation Selection +@section Linker emulation selection + +A linker @dfn{emulation} is a ``personality'' of the linker, which gives +the linker default values for the other aspects of the target system. +In particular, it consists of + +@itemize @bullet +@item +the linker script + +@item +the target + +@item +several ``hook'' functions that are run at certain stages of the linking +process to do special things that some targets require +@end itemize + +The command to list valid linker emulation values is @samp{ld -V}. + +Sample values: @samp{hp300bsd}, @samp{mipslit}, @samp{sun4}. + +Ways to specify: + +@enumerate +@item +command line option: @samp{-m} +(@pxref{Options,,Options,ld.info,Using LD}) + +@item +environment variable @code{LDEMULATION} + +@item +compiled-in @code{DEFAULT_EMULATION} from @file{Makefile}, +which comes from @code{EMUL} in @file{config/@var{target}.mt} +@end enumerate + +@node Reporting Bugs +@chapter Reporting Bugs +@cindex bugs +@cindex reporting bugs + +Your bug reports play an essential role in making the binary utilities +reliable. + +Reporting a bug may help you by bringing a solution to your problem, or +it may not. But in any case the principal function of a bug report is +to help the entire community by making the next version of the binary +utilities work better. Bug reports are your contribution to their +maintenance. + +In order for a bug report to serve its purpose, you must include the +information that enables us to fix the bug. + +@menu +* Bug Criteria:: Have you found a bug? +* Bug Reporting:: How to report bugs +@end menu + +@node Bug Criteria +@section Have you found a bug? +@cindex bug criteria + +If you are not sure whether you have found a bug, here are some guidelines: + +@itemize @bullet +@cindex fatal signal +@cindex crash +@item +If a binary utility gets a fatal signal, for any input whatever, that is +a bug. Reliable utilities never crash. + +@cindex error on valid input +@item +If a binary utility produces an error message for valid input, that is a +bug. + +@item +If you are an experienced user of binary utilities, your suggestions for +improvement are welcome in any case. +@end itemize + +@node Bug Reporting +@section How to report bugs +@cindex bug reports +@cindex bugs, reporting + +A number of companies and individuals offer support for @sc{gnu} +products. If you obtained the binary utilities from a support +organization, we recommend you contact that organization first. + +You can find contact information for many support companies and +individuals in the file @file{etc/SERVICE} in the @sc{gnu} Emacs +distribution. + +In any event, we also recommend that you send bug reports for the binary +utilities to @samp{bug-gnu-utils@@gnu.org}. + +The fundamental principle of reporting bugs usefully is this: +@strong{report all the facts}. If you are not sure whether to state a +fact or leave it out, state it! + +Often people omit facts because they think they know what causes the +problem and assume that some details do not matter. Thus, you might +assume that the name of a file you use in an example does not matter. +Well, probably it does not, but one cannot be sure. Perhaps the bug is +a stray memory reference which happens to fetch from the location where +that pathname is stored in memory; perhaps, if the pathname were +different, the contents of that location would fool the utility into +doing the right thing despite the bug. Play it safe and give a +specific, complete example. That is the easiest thing for you to do, +and the most helpful. + +Keep in mind that the purpose of a bug report is to enable us to fix the bug if +it is new to us. Therefore, always write your bug reports on the assumption +that the bug has not been reported previously. + +Sometimes people give a few sketchy facts and ask, ``Does this ring a +bell?'' Those bug reports are useless, and we urge everyone to +@emph{refuse to respond to them} except to chide the sender to report +bugs properly. + +To enable us to fix the bug, you should include all these things: + +@itemize @bullet +@item +The version of the utility. Each utility announces it if you start it +with the @samp{--version} argument. + +Without this, we will not know whether there is any point in looking for +the bug in the current version of the binary utilities. + +@item +Any patches you may have applied to the source, including any patches +made to the @code{BFD} library. + +@item +The type of machine you are using, and the operating system name and +version number. + +@item +What compiler (and its version) was used to compile the utilities---e.g. +``@code{gcc-2.7}''. + +@item +The command arguments you gave the utility to observe the bug. To +guarantee you will not omit something important, list them all. A copy +of the Makefile (or the output from make) is sufficient. + +If we were to try to guess the arguments, we would probably guess wrong +and then we might not encounter the bug. + +@item +A complete input file, or set of input files, that will reproduce the +bug. If the utility is reading an object file or files, then it is +generally most helpful to send the actual object files, uuencoded if +necessary to get them through the mail system. Making them available +for anonymous FTP is not as good, but may be the only reasonable choice +for large object files. + +If the source files were produced exclusively using @sc{gnu} programs +(e.g., @code{gcc}, @code{gas}, and/or the @sc{gnu} @code{ld}), then it +may be OK to send the source files rather than the object files. In +this case, be sure to say exactly what version of @code{gcc}, or +whatever, was used to produce the object files. Also say how +@code{gcc}, or whatever, was configured. + +@item +A description of what behavior you observe that you believe is +incorrect. For example, ``It gets a fatal signal.'' + +Of course, if the bug is that the utility gets a fatal signal, then we +will certainly notice it. But if the bug is incorrect output, we might +not notice unless it is glaringly wrong. You might as well not give us +a chance to make a mistake. + +Even if the problem you experience is a fatal signal, you should still +say so explicitly. Suppose something strange is going on, such as, your +copy of the utility is out of synch, or you have encountered a bug in +the C library on your system. (This has happened!) Your copy might +crash and ours would not. If you told us to expect a crash, then when +ours fails to crash, we would know that the bug was not happening for +us. If you had not told us to expect a crash, then we would not be able +to draw any conclusion from our observations. + +@item +If you wish to suggest changes to the source, send us context diffs, as +generated by @code{diff} with the @samp{-u}, @samp{-c}, or @samp{-p} +option. Always send diffs from the old file to the new file. If you +even discuss something in the @code{ld} source, refer to it by context, +not by line number. + +The line numbers in our development sources will not match those in your +sources. Your line numbers would convey no useful information to us. +@end itemize + +Here are some things that are not necessary: + +@itemize @bullet +@item +A description of the envelope of the bug. + +Often people who encounter a bug spend a lot of time investigating +which changes to the input file will make the bug go away and which +changes will not affect it. + +This is often time consuming and not very useful, because the way we +will find the bug is by running a single example under the debugger +with breakpoints, not by pure deduction from a series of examples. +We recommend that you save your time for something else. + +Of course, if you can find a simpler example to report @emph{instead} +of the original one, that is a convenience for us. Errors in the +output will be easier to spot, running under the debugger will take +less time, and so on. + +However, simplification is not vital; if you do not want to do this, +report the bug anyway and send us the entire test case you used. + +@item +A patch for the bug. + +A patch for the bug does help us if it is a good one. But do not omit +the necessary information, such as the test case, on the assumption that +a patch is all we need. We might see problems with your patch and decide +to fix the problem another way, or we might not understand it at all. + +Sometimes with programs as complicated as the binary utilities it is +very hard to construct an example that will make the program follow a +certain path through the code. If you do not send us the example, we +will not be able to construct one, so we will not be able to verify that +the bug is fixed. + +And if we cannot understand what bug you are trying to fix, or why your +patch should be an improvement, we will not install it. A test case will +help us to understand. + +@item +A guess about what the bug is or what it depends on. + +Such guesses are usually wrong. Even we cannot guess right about such +things without first using the debugger to find the facts. +@end itemize + +@node Index +@unnumbered Index + +@printindex cp + +@contents +@bye diff --git a/binutils/bucomm.c b/binutils/bucomm.c new file mode 100644 index 0000000..a5b0054 --- /dev/null +++ b/binutils/bucomm.c @@ -0,0 +1,266 @@ +/* bucomm.c -- Bin Utils COMmon code. + Copyright (C) 1991, 92, 93, 94, 95, 1997, 1998 Free Software Foundation, Inc. + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* We might put this in a library someday so it could be dynamically + loaded, but for now it's not necessary. */ + +#include "bfd.h" +#include "libiberty.h" +#include "bucomm.h" + +#include <sys/stat.h> +#include <time.h> /* ctime, maybe time_t */ + +#ifndef HAVE_TIME_T_IN_TIME_H +#ifndef HAVE_TIME_T_IN_TYPES_H +typedef long time_t; +#endif +#endif + +#ifdef ANSI_PROTOTYPES +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +/* Error reporting */ + +char *program_name; + +void +bfd_nonfatal (string) + CONST char *string; +{ + CONST char *errmsg = bfd_errmsg (bfd_get_error ()); + + if (string) + fprintf (stderr, "%s: %s: %s\n", program_name, string, errmsg); + else + fprintf (stderr, "%s: %s\n", program_name, errmsg); +} + +void +bfd_fatal (string) + CONST char *string; +{ + bfd_nonfatal (string); + xexit (1); +} + +static void +report (format, args) + const char * format; + va_list args; +{ + fprintf (stderr, "%s: ", program_name); + vfprintf (stderr, format, args); + putc ('\n', stderr); +} + +#ifdef ANSI_PROTOTYPES +void +fatal (const char *format, ...) +{ + va_list args; + + va_start (args, format); + report (format, args); + va_end (args); + xexit (1); +} + +void +non_fatal (const char *format, ...) +{ + va_list args; + + va_start (args, format); + report (format, args); + va_end (args); +} +#else +void +fatal (va_alist) + va_dcl +{ + char *Format; + va_list args; + + va_start (args); + Format = va_arg (args, char *); + report (Format, args); + va_end (args); + xexit (1); +} + +void +non_fatal (va_alist) + va_dcl +{ + char *Format; + va_list args; + + va_start (args); + Format = va_arg (args, char *); + report (Format, args); + va_end (args); +} +#endif + +/* Set the default BFD target based on the configured target. Doing + this permits the binutils to be configured for a particular target, + and linked against a shared BFD library which was configured for a + different target. */ + +void +set_default_bfd_target () +{ + /* The macro TARGET is defined by Makefile. */ + const char *target = TARGET; + + if (! bfd_set_default_target (target)) + fatal (_("can't set BFD default target to `%s': %s"), + target, bfd_errmsg (bfd_get_error ())); +} + +/* After a false return from bfd_check_format_matches with + bfd_get_error () == bfd_error_file_ambiguously_recognized, print + the possible matching targets. */ + +void +list_matching_formats (p) + char **p; +{ + fprintf (stderr, _("%s: Matching formats:"), program_name); + while (*p) + fprintf (stderr, " %s", *p++); + fputc ('\n', stderr); +} + +/* List the supported targets. */ + +void +list_supported_targets (name, f) + const char *name; + FILE *f; +{ + extern bfd_target *bfd_target_vector[]; + int t; + + if (name == NULL) + fprintf (f, _("Supported targets:")); + else + fprintf (f, _("%s: supported targets:"), name); + for (t = 0; bfd_target_vector[t] != NULL; t++) + fprintf (f, " %s", bfd_target_vector[t]->name); + fprintf (f, "\n"); +} + +/* Display the archive header for an element as if it were an ls -l listing: + + Mode User\tGroup\tSize\tDate Name */ + +void +print_arelt_descr (file, abfd, verbose) + FILE *file; + bfd *abfd; + boolean verbose; +{ + struct stat buf; + + if (verbose) + { + if (bfd_stat_arch_elt (abfd, &buf) == 0) + { + char modebuf[11]; + char timebuf[40]; + time_t when = buf.st_mtime; + CONST char *ctime_result = (CONST char *) ctime (&when); + + /* POSIX format: skip weekday and seconds from ctime output. */ + sprintf (timebuf, "%.12s %.4s", ctime_result + 4, ctime_result + 20); + + mode_string (buf.st_mode, modebuf); + modebuf[10] = '\0'; + /* POSIX 1003.2/D11 says to skip first character (entry type). */ + fprintf (file, "%s %ld/%ld %6ld %s ", modebuf + 1, + (long) buf.st_uid, (long) buf.st_gid, + (long) buf.st_size, timebuf); + } + } + + fprintf (file, "%s\n", bfd_get_filename (abfd)); +} + +/* Return the name of a temporary file in the same directory as FILENAME. */ + +char * +make_tempname (filename) + char *filename; +{ + static char template[] = "stXXXXXX"; + char *tmpname; + char *slash = strrchr (filename, '/'); + +#if defined (__DJGPP__) || defined (__GO32__) || defined (_WIN32) + if (slash == NULL) + slash = strrchr (filename, '\\'); +#endif + + if (slash != (char *) NULL) + { + char c; + + c = *slash; + *slash = 0; + tmpname = xmalloc (strlen (filename) + sizeof (template) + 1); + strcpy (tmpname, filename); + strcat (tmpname, "/"); + strcat (tmpname, template); + mktemp (tmpname); + *slash = c; + } + else + { + tmpname = xmalloc (sizeof (template)); + strcpy (tmpname, template); + mktemp (tmpname); + } + return tmpname; +} + +/* Parse a string into a VMA, with a fatal error if it can't be + parsed. */ + +bfd_vma +parse_vma (s, arg) + const char *s; + const char *arg; +{ + bfd_vma ret; + const char *end; + + ret = bfd_scan_vma (s, &end, 0); + + if (*end != '\0') + fatal (_("%s: bad number: %s"), arg, s); + + return ret; +} diff --git a/binutils/bucomm.h b/binutils/bucomm.h new file mode 100644 index 0000000..36e6a79 --- /dev/null +++ b/binutils/bucomm.h @@ -0,0 +1,183 @@ +/* bucomm.h -- binutils common include file. + Copyright (C) 1992, 93, 94, 95, 96, 97, 98, 1999 + Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _BUCOMM_H +#define _BUCOMM_H + +#include "ansidecl.h" +#include <stdio.h> +#include <sys/types.h> + +#include "config.h" + +#ifdef USE_BINARY_FOPEN +#include "fopen-bin.h" +#else +#include "fopen-same.h" +#endif + +#include <errno.h> +#ifndef errno +extern int errno; +#endif + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#ifdef HAVE_STRING_H +#include <string.h> +#else +#ifdef HAVE_STRINGS_H +#include <strings.h> +#else +extern char *strchr (); +extern char *strrchr (); +#endif +#endif + +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif + +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#else +#ifdef HAVE_SYS_FILE_H +#include <sys/file.h> +#endif +#endif + +#ifdef NEED_DECLARATION_STRSTR +extern char *strstr (); +#endif + +#ifdef HAVE_SBRK +#ifdef NEED_DECLARATION_SBRK +extern char *sbrk (); +#endif +#endif + +#ifdef NEED_DECLARATION_GETENV +extern char *getenv (); +#endif + +#ifdef NEED_DECLARATION_ENVIRON +extern char **environ; +#endif + +#ifndef O_RDONLY +#define O_RDONLY 0 +#endif + +#ifndef O_RDWR +#define O_RDWR 2 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#if defined(__GNUC__) && !defined(C_ALLOCA) +# undef alloca +# define alloca __builtin_alloca +#else +# if defined(HAVE_ALLOCA_H) && !defined(C_ALLOCA) +# include <alloca.h> +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +# if !defined (__STDC__) && !defined (__hpux) +char *alloca (); +# else +void *alloca (); +# endif /* __STDC__, __hpux */ +# endif /* alloca */ +# endif /* HAVE_ALLOCA_H */ +#endif + +#ifdef HAVE_LOCALE_H +# include <locale.h> +#endif + +#ifdef ENABLE_NLS +# include <libintl.h> +# define _(String) gettext (String) +# ifdef gettext_noop +# define N_(String) gettext_noop (String) +# else +# define N_(String) (String) +# endif +#else +/* Stubs that do something close enough. */ +# define textdomain(String) (String) +# define gettext(String) (String) +# define dgettext(Domain,Message) (Message) +# define dcgettext(Domain,Message,Type) (Message) +# define bindtextdomain(Domain,Directory) (Domain) +# define _(String) (String) +# define N_(String) (String) +#endif + +/* bucomm.c */ +void bfd_nonfatal PARAMS ((CONST char *)); + +void bfd_fatal PARAMS ((CONST char *)); + +void fatal PARAMS ((CONST char *, ...)); + +void non_fatal PARAMS ((CONST char *, ...)); + +void set_default_bfd_target PARAMS ((void)); + +void list_matching_formats PARAMS ((char **p)); + +void list_supported_targets PARAMS ((const char *, FILE *)); + +void print_arelt_descr PARAMS ((FILE *file, bfd *abfd, boolean verbose)); + +char *make_tempname PARAMS ((char *)); + +bfd_vma parse_vma PARAMS ((const char *, const char *)); + +extern char *program_name; + +/* filemode.c */ +void mode_string PARAMS ((unsigned long mode, char *buf)); + +/* version.c */ +extern void print_version PARAMS ((const char *)); + +/* rename.c */ +extern void set_times PARAMS ((const char *, const struct stat *)); + +extern int smart_rename PARAMS ((const char *, const char *, int)); + +/* libiberty */ +PTR xmalloc PARAMS ((size_t)); + +PTR xrealloc PARAMS ((PTR, size_t)); + +#endif /* _BUCOMM_H */ diff --git a/binutils/budbg.h b/binutils/budbg.h new file mode 100644 index 0000000..d8ee889 --- /dev/null +++ b/binutils/budbg.h @@ -0,0 +1,58 @@ +/* budbg.c -- Interfaces to the generic debugging information routines. + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Written by Ian Lance Taylor <ian@cygnus.com>. + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifndef BUDBG_H +#define BUDBG_H + +#include <stdio.h> + +/* Routine used to read generic debugging information. */ + +extern PTR read_debugging_info PARAMS ((bfd *, asymbol **, long)); + +/* Routine used to print generic debugging information. */ + +extern boolean print_debugging_info PARAMS ((FILE *, PTR)); + +/* Routines used to read and write stabs information. */ + +extern PTR start_stab PARAMS ((PTR, bfd *, boolean, asymbol **, long)); + +extern boolean finish_stab PARAMS ((PTR, PTR)); + +extern boolean parse_stab PARAMS ((PTR, PTR, int, int, bfd_vma, const char *)); + +extern boolean write_stabs_in_sections_debugging_info + PARAMS ((bfd *, PTR, bfd_byte **, bfd_size_type *, bfd_byte **, + bfd_size_type *)); + +/* Routines used to read and write IEEE debugging information. */ + +extern boolean parse_ieee + PARAMS ((PTR, bfd *, const bfd_byte *, bfd_size_type)); + +extern boolean write_ieee_debugging_info PARAMS ((bfd *, PTR)); + +/* Routine used to read COFF debugging information. */ + +extern boolean parse_coff PARAMS ((bfd *, asymbol **, long, PTR)); + +#endif diff --git a/binutils/coffdump.c b/binutils/coffdump.c new file mode 100644 index 0000000..dc84d50 --- /dev/null +++ b/binutils/coffdump.c @@ -0,0 +1,541 @@ +/* Coff file dumper. + Copyright (C) 1994, 1998, 1999 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Steve Chamberlain <sac@cygnus.com> + + This module reads a type tree generated by coffgrok and prints + it out so we can test the grokker. +*/ + +#include <bfd.h> +#include <getopt.h> +#include <libiberty.h> + +#include "coffgrok.h" +#include "bucomm.h" + +#define PROGRAM_VERSION "1.0" + +static int atnl; +static void dump_coff_scope (); + +static void +tab (x) +int x; +{ + static int indent; + int i; + + if (atnl) + { + if (x < 0) + { + printf (")"); + indent += x; + + return; + } + else + { + printf ("\n"); + atnl = 0; + } + } + + if (x == -1) + { + for (i = 0; i < indent; i++) + printf (" "); + + indent += x; + printf (")"); + return; + } + + indent += x; + + for (i = 0; i < indent; i++) + printf (" "); + + if (x) + { + printf ("("); + } +} + +static void nl () +{ + atnl = 1; +} + +static void +dump_coff_lines (p) + struct coff_line *p; +{ + int i; + int online = 0; + tab(1); + printf(_("#lines %d "),p->nlines); + for (i = 0; i < p->nlines; i++) + { + printf("(%d 0x%x)", p->lines[i], p->addresses[i]); + online++; + if (online > 6) + { + nl(); + tab(0); + online = 0; + } + } + nl(); + tab(-1); +} + +static void +dump_coff_type (p) + struct coff_type *p; +{ + tab (1); + printf ("size %d ", p->size); + switch (p->type) + { + case coff_secdef_type: + printf ("section definition at %x size %x\n", + p->u.asecdef.address, + p->u.asecdef.size); + nl(); + break; + case coff_pointer_type: + printf ("pointer to"); + nl (); + dump_coff_type (p->u.pointer.points_to); + break; + case coff_array_type: + printf ("array [%d] of", p->u.array.dim); + nl (); + dump_coff_type (p->u.array.array_of); + break; + case coff_function_type: + printf ("function returning"); + nl (); + dump_coff_type (p->u.function.function_returns); + dump_coff_lines (p->u.function.lines); + printf ("arguments"); + nl (); + dump_coff_scope (p->u.function.parameters); + tab (0); + printf ("code"); + nl (); + dump_coff_scope (p->u.function.code); + tab(0); + break; + case coff_structdef_type: + printf ("structure definition"); + nl (); + dump_coff_scope (p->u.astructdef.elements); + break; + case coff_structref_type: + if (!p->u.aenumref.ref) + printf ("structure ref to UNKNOWN struct"); + else + printf ("structure ref to %s", p->u.aenumref.ref->name); + break; + case coff_enumref_type: + printf ("enum ref to %s", p->u.astructref.ref->name); + break; + case coff_enumdef_type: + printf ("enum definition"); + nl (); + dump_coff_scope (p->u.aenumdef.elements); + break; + case coff_basic_type: + switch (p->u.basic) + { + case T_NULL: + printf ("NULL"); + break; + case T_VOID: + printf ("VOID"); + break; + case T_CHAR: + printf ("CHAR"); + break; + case T_SHORT: + printf ("SHORT"); + break; + case T_INT: + printf ("INT "); + break; + case T_LONG: + printf ("LONG"); + break; + case T_FLOAT: + printf ("FLOAT"); + break; + case T_DOUBLE: + printf ("DOUBLE"); + break; + case T_STRUCT: + printf ("STRUCT"); + break; + case T_UNION: + printf ("UNION"); + break; + case T_ENUM: + printf ("ENUM"); + break; + case T_MOE: + printf ("MOE "); + break; + case T_UCHAR: + printf ("UCHAR"); + break; + case T_USHORT: + printf ("USHORT"); + break; + case T_UINT: + printf ("UINT"); + break; + case T_ULONG: + printf ("ULONG"); + break; + case T_LNGDBL: + printf ("LNGDBL"); + break; + default: + abort (); + } + } + nl (); + tab (-1); +} + +static void +dump_coff_where (p) + struct coff_where *p; +{ + tab (1); + switch (p->where) + { + case coff_where_stack: + printf ("Stack offset %x", p->offset); + break; + case coff_where_memory: + printf ("Memory section %s+%x", p->section->name, p->offset); + break; + case coff_where_register: + printf ("Register %d", p->offset); + break; + case coff_where_member_of_struct: + printf ("Struct Member offset %x", p->offset); + break; + case coff_where_member_of_enum: + printf ("Enum Member offset %x", p->offset); + break; + case coff_where_unknown: + printf ("Undefined symbol"); + break; + case coff_where_strtag: + printf ("STRTAG"); + case coff_where_entag: + printf ("ENTAG"); + break; + case coff_where_typedef: + printf ("TYPEDEF"); + break; + default: + abort (); + } + nl (); + tab (-1); +} + +static void +dump_coff_visible (p) + struct coff_visible *p; +{ + tab (1); + switch (p->type) + { + case coff_vis_ext_def: + printf ("coff_vis_ext_def"); + break; + case coff_vis_ext_ref: + printf ("coff_vis_ext_ref"); + break; + case coff_vis_int_def: + printf ("coff_vis_int_def"); + break; + case coff_vis_common: + printf ("coff_vis_common"); + break; + case coff_vis_auto: + printf ("coff_vis_auto"); + break; + case coff_vis_autoparam: + printf ("coff_vis_autoparam"); + break; + case coff_vis_regparam: + printf ("coff_vis_regparam"); + break; + case coff_vis_register: + printf ("coff_vis_register"); + break; + case coff_vis_tag: + printf ("coff_vis_tag"); + break; + case coff_vis_member_of_struct: + printf ("coff_vis_member_of_struct"); + break; + case coff_vis_member_of_enum: + printf ("coff_vis_member_of_enum"); + break; + default: + abort (); + } + nl (); + tab (-1); +} + + +void +dump_coff_symbol (p) + struct coff_symbol *p; +{ + tab (1); + printf ("List of symbols"); + nl (); + while (p) + { + tab (1); + tab (1); + printf ("Symbol %s, tag %d, number %d", p->name, p->tag, p->number); + nl (); + tab (-1); + tab (1); + printf ("Type"); + nl (); + dump_coff_type (p->type); + tab (-1); + tab (1); + printf ("Where"); + dump_coff_where (p->where); + tab (-1); + tab (1); + printf ("Visible"); + dump_coff_visible (p->visible); + tab (-1); + p = p->next; + tab (-1); + } + tab (-1); +} + +static void +dump_coff_scope (p) + struct coff_scope *p; +{ +if (p) { + tab (1); + printf ("List of blocks %lx ",(unsigned long) p); + + if (p->sec) { + printf( " %s %x..%x", p->sec->name,p->offset, p->offset + p->size -1); + } + nl (); + tab (0); + printf ("*****************"); + nl (); + while (p) + { + tab (0); + printf ("vars %d", p->nvars); + nl (); + dump_coff_symbol (p->vars_head); + printf ("blocks"); + nl (); + dump_coff_scope (p->list_head); + nl (); + p = p->next; + } + + tab (0); + printf ("*****************"); + nl (); + tab (-1); +} +} + +static void +dump_coff_sfile (p) + struct coff_sfile *p; +{ + tab (1); + printf ("List of source files"); + nl (); + while (p) + { + tab (0); + printf ("Source file %s", p->name); + nl (); + dump_coff_scope (p->scope); + p = p->next; + } + tab (-1); +} + +static void +dump_coff_section(ptr) +struct coff_section *ptr; +{ + int i; + tab(1); + printf("section %s %d %d address %x size %x number %d nrelocs %d", + ptr->name, ptr->code, ptr->data, ptr->address,ptr->size, ptr->number, ptr->nrelocs); + nl(); + + for (i = 0; i < ptr->nrelocs; i++) + { + tab(0); + printf("(%x %s %x)", + ptr->relocs[i].offset, + ptr->relocs[i].symbol->name, + ptr->relocs[i].addend); + nl(); + } + tab(-1); + +} + +void +coff_dump (ptr) + struct coff_ofile *ptr; +{ + int i; + printf ("Coff dump"); + nl (); + printf ("#souces %d", ptr->nsources); + nl (); + dump_coff_sfile (ptr->source_head); + for (i = 0; i < ptr->nsections; i++) + dump_coff_section(ptr->sections + i); +} + + + +char * program_name; + +static void +show_usage (file, status) + FILE *file; + int status; +{ + fprintf (file, "Usage: %s [-hV] in-file\n", program_name); + exit (status); +} + +static void +show_help () +{ + printf (_("%s: Print a human readable interpretation of a SYSROFF object file\n"), + program_name); + show_usage (stdout, 0); +} + + +int +main (ac, av) + int ac; + char *av[]; +{ + bfd *abfd; + struct coff_ofile *tree; + char **matching; + char *input_file = NULL; + int opt; + static struct option long_options[] = + { + { "help", no_argument, 0, 'h' }, + { "version", no_argument, 0, 'V' }, + { NULL, no_argument, 0, 0 } + }; + +#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) + setlocale (LC_MESSAGES, ""); +#endif + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + + program_name = av[0]; + xmalloc_set_program_name (program_name); + + while ((opt = getopt_long (ac, av, "hV", long_options, + (int *) NULL)) + != EOF) + { + switch (opt) + { + case 'h': + show_help (); + /*NOTREACHED*/ + case 'V': + printf (_("GNU %s version %s\n"), program_name, PROGRAM_VERSION); + exit (0); + /*NOTREACHED*/ + case 0: + break; + default: + show_usage (stderr, 1); + /*NOTREACHED*/ + } + } + + if (optind < ac) + { + input_file = av[optind]; + } + + if (!input_file) + { + fprintf (stderr,_("%s: no input file specified\n"), + program_name); + exit(1); + } + abfd = bfd_openr (input_file, 0); + + if (!abfd) + bfd_fatal (input_file); + + if (! bfd_check_format_matches (abfd, bfd_object, &matching)) + { + bfd_nonfatal (input_file); + if (bfd_get_error () == bfd_error_file_ambiguously_recognized) + { + list_matching_formats (matching); + free (matching); + } + exit (1); + } + + tree = coff_grok (abfd); + + coff_dump(tree); + printf("\n"); + return 0; +} diff --git a/binutils/coffgrok.c b/binutils/coffgrok.c new file mode 100644 index 0000000..8c4e6c9 --- /dev/null +++ b/binutils/coffgrok.c @@ -0,0 +1,737 @@ +/* coffgrok.c + Copyright (C) 1994, 95, 97, 1998 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Steve Chamberlain (sac@cygnus.com) + + This module reads a coff file and builds a really simple type tree + which can be read by other programs. The first application is a + coff->sysroff converter. It can be tested with coffdump.c. + +*/ + +#include <bfd.h> +#include "bucomm.h" + +#include "coff/internal.h" +#include "../bfd/libcoff.h" +#include "coffgrok.h" +int lofile = 1; +static struct coff_scope *top_scope; +static struct coff_scope *file_scope; +static struct coff_ofile *ofile; + +struct coff_symbol *last_function_symbol; +struct coff_type *last_function_type; +struct coff_type *last_struct; +struct coff_type *last_enum; +struct coff_sfile *cur_sfile; + +static struct coff_symbol **tindex; + + +static asymbol **syms; +static long symcount; + +#define N(x) ((x)->_n._n_nptr[1]) + +static struct coff_ptr_struct *rawsyms; +static int rawcount; +static bfd *abfd; +extern char *xcalloc (); +#define PTR_SIZE 4 +#define SHORT_SIZE 2 +#define INT_SIZE 4 +#define LONG_SIZE 4 +#define FLOAT_SIZE 4 +#define DOUBLE_SIZE 8 + +#define INDEXOF(p) ((struct coff_ptr_struct *)(p)-(rawsyms)) + +static struct coff_scope * +empty_scope () +{ + struct coff_scope *l; + l = (struct coff_scope *) (xcalloc (sizeof (struct coff_scope), 1)); + return l; +} + +static struct coff_symbol * +empty_symbol () +{ + return (struct coff_symbol *) (xcalloc (sizeof (struct coff_symbol), 1)); +} + +/*int l;*/ +static void +push_scope (link) + int link; +{ + struct coff_scope *n = empty_scope (); + if (link) + { + if (top_scope) + { + if (top_scope->list_tail) + { + top_scope->list_tail->next = n; + } + else + { + top_scope->list_head = n; + } + top_scope->list_tail = n; + } + } + n->parent = top_scope; + + top_scope = n; +} + +static void +pop_scope () +{ + top_scope = top_scope->parent; +} + +static void +do_sections_p1 (head) + struct coff_ofile *head; +{ + asection *section; + int idx; + struct coff_section *all = (struct coff_section *) (xcalloc (abfd->section_count + 1, + sizeof (struct coff_section))); + head->nsections = abfd->section_count + 1; + head->sections = all; + + for (idx = 0, section = abfd->sections; section; section = section->next, idx++) + { + long relsize; + int i = section->target_index; + arelent **relpp; + long relcount; + + relsize = bfd_get_reloc_upper_bound (abfd, section); + if (relsize < 0) + bfd_fatal (bfd_get_filename (abfd)); + if (relsize == 0) + continue; + relpp = (arelent **) xmalloc (relsize); + relcount = bfd_canonicalize_reloc (abfd, section, relpp, syms); + if (relcount < 0) + bfd_fatal (bfd_get_filename (abfd)); + + head->sections[i].name = (char *) (section->name); + head->sections[i].code = section->flags & SEC_CODE; + head->sections[i].data = section->flags & SEC_DATA; + if (strcmp (section->name, ".bss") == 0) + head->sections[i].data = 1; + head->sections[i].address = section->lma; + head->sections[i].size = section->_raw_size; + head->sections[i].number = idx; + head->sections[i].nrelocs = section->reloc_count; + head->sections[i].relocs = + (struct coff_reloc *) (xcalloc (section->reloc_count, + sizeof (struct coff_reloc))); + head->sections[i].bfd_section = section; + } + head->sections[0].name = "ABSOLUTE"; + head->sections[0].code = 0; + head->sections[0].data = 0; + head->sections[0].address = 0; + head->sections[0].size = 0; + head->sections[0].number = 0; +} + +static void +do_sections_p2 (head) + struct coff_ofile *head; +{ + asection *section; + for (section = abfd->sections; section; section = section->next) + { + unsigned int j; + + for (j = 0; j < section->reloc_count; j++) + { + int idx; + int i = section->target_index; + struct coff_reloc *r = head->sections[i].relocs + j; + arelent *sr = section->relocation + j; + r->offset = sr->address; + r->addend = sr->addend; + idx = ((coff_symbol_type *) (sr->sym_ptr_ptr[0]))->native - rawsyms; + r->symbol = tindex[idx]; + } + } +} + +static struct coff_where * +do_where (i) + int i; +{ + struct internal_syment *sym = &rawsyms[i].u.syment; + struct coff_where *where = + (struct coff_where *) (xmalloc (sizeof (struct coff_where))); + where->offset = sym->n_value; + + if (sym->n_scnum == -1) + sym->n_scnum = 0; + + switch (sym->n_sclass) + { + case C_FIELD: + where->where = coff_where_member_of_struct; + where->offset = sym->n_value / 8; + where->bitoffset = sym->n_value % 8; + where->bitsize = rawsyms[i + 1].u.auxent.x_sym.x_misc.x_lnsz.x_size; + break; + case C_MOE: + where->where = coff_where_member_of_enum; + break; + case C_MOS: + case C_MOU: + where->where = coff_where_member_of_struct; + break; + case C_AUTO: + case C_ARG: + where->where = coff_where_stack; + break; + case C_EXT: + case C_STAT: + case C_EXTDEF: + case C_LABEL: + where->where = coff_where_memory; + where->section = &ofile->sections[sym->n_scnum]; + break; + case C_REG: + case C_REGPARM: + where->where = coff_where_register; + break; + case C_ENTAG: + where->where = coff_where_entag; + break; + case C_STRTAG: + case C_UNTAG: + where->where = coff_where_strtag; + break; + case C_TPDEF: + where->where = coff_where_typedef; + break; + default: + abort (); + break; + } + return where; +} + +static +struct coff_line * +do_lines (i, name) + int i; + char *name; +{ + struct coff_line *res = (struct coff_line *) xcalloc (sizeof (struct coff_line), 1); + asection *s; + unsigned int l; + + /* Find out if this function has any line numbers in the table */ + for (s = abfd->sections; s; s = s->next) + { + for (l = 0; l < s->lineno_count; l++) + { + if (s->lineno[l].line_number == 0) + { + if (rawsyms + i == ((coff_symbol_type *) (&(s->lineno[l].u.sym[0])))->native) + { + /* These lines are for this function - so count them and stick them on */ + int c = 0; + /* Find the linenumber of the top of the function, since coff linenumbers + are relative to the start of the function. */ + int start_line = rawsyms[i + 3].u.auxent.x_sym.x_misc.x_lnsz.x_lnno; + + l++; + for (c = 0; s->lineno[l + c + 1].line_number; c++) + ; + + /* Add two extra records, one for the prologue and one for the epilogue */ + c += 1; + res->nlines = c; + res->lines = (int *) (xcalloc (sizeof (int), c)); + res->addresses = (int *) (xcalloc (sizeof (int), c)); + res->lines[0] = start_line; + res->addresses[0] = rawsyms[i].u.syment.n_value - s->vma; + for (c = 0; s->lineno[l + c + 1].line_number; c++) + { + res->lines[c + 1] = s->lineno[l + c].line_number + start_line - 1; + res->addresses[c + 1] = s->lineno[l + c].u.offset; + } + return res; + } + } + } + } + return res; +} + +static +struct coff_type * +do_type (i) + int i; +{ + struct internal_syment *sym = &rawsyms[i].u.syment; + union internal_auxent *aux = &rawsyms[i + 1].u.auxent; + struct coff_type *res = + (struct coff_type *) xmalloc (sizeof (struct coff_type)); + int type = sym->n_type; + int which_dt = 0; + int dimind = 0; + + res->type = coff_basic_type; + res->u.basic = type & 0xf; + + switch (type & 0xf) + { + case T_NULL: + case T_VOID: + if (sym->n_numaux && sym->n_sclass == C_STAT) + { + /* This is probably a section definition */ + res->type = coff_secdef_type; + res->size = aux->x_scn.x_scnlen; + } + else + { + if (type == 0) + { + /* Don't know what this is, let's make it a simple int */ + res->size = INT_SIZE; + res->u.basic = T_UINT; + } + else + { + /* Else it could be a function or pointer to void */ + res->size = 0; + } + } + break; + + + break; + case T_UCHAR: + case T_CHAR: + res->size = 1; + break; + case T_USHORT: + case T_SHORT: + res->size = SHORT_SIZE; + break; + case T_UINT: + case T_INT: + res->size = INT_SIZE; + break; + case T_ULONG: + case T_LONG: + res->size = LONG_SIZE; + break; + case T_FLOAT: + res->size = FLOAT_SIZE; + break; + case T_DOUBLE: + res->size = DOUBLE_SIZE; + break; + case T_STRUCT: + case T_UNION: + if (sym->n_numaux) + { + if (aux->x_sym.x_tagndx.p) + { + /* Refering to a struct defined elsewhere */ + res->type = coff_structref_type; + res->u.astructref.ref = tindex[INDEXOF (aux->x_sym.x_tagndx.p)]; + res->size = res->u.astructref.ref ? + res->u.astructref.ref->type->size : 0; + } + else + { + /* A definition of a struct */ + last_struct = res; + res->type = coff_structdef_type; + res->u.astructdef.elements = empty_scope (); + res->u.astructdef.idx = 0; + res->u.astructdef.isstruct = (type & 0xf) == T_STRUCT; + res->size = aux->x_sym.x_misc.x_lnsz.x_size; + } + } + else + { + /* No auxents - it's anonynmous */ + res->type = coff_structref_type; + res->u.astructref.ref = 0; + res->size = 0; + } + break; + case T_ENUM: + if (aux->x_sym.x_tagndx.p) + { + /* Refering to a enum defined elsewhere */ + res->type = coff_enumref_type; + res->u.aenumref.ref = tindex[INDEXOF (aux->x_sym.x_tagndx.p)]; + res->size = res->u.aenumref.ref->type->size; + } + else + { + /* A definition of an enum */ + last_enum = res; + res->type = coff_enumdef_type; + res->u.aenumdef.elements = empty_scope (); + res->size = aux->x_sym.x_misc.x_lnsz.x_size; + } + break; + case T_MOE: + break; + } + + for (which_dt = 5; which_dt >= 0; which_dt--) + { + switch ((type >> ((which_dt * 2) + 4)) & 0x3) + { + case 0: + break; + case DT_ARY: + { + struct coff_type *ptr = ((struct coff_type *) + xmalloc (sizeof (struct coff_type))); + int els = (dimind < DIMNUM + ? aux->x_sym.x_fcnary.x_ary.x_dimen[dimind] + : 0); + ++dimind; + ptr->type = coff_array_type; + ptr->size = els * res->size; + ptr->u.array.dim = els; + ptr->u.array.array_of = res; + res = ptr; + break; + } + case DT_PTR: + { + struct coff_type *ptr = + (struct coff_type *) xmalloc (sizeof (struct coff_type)); + ptr->size = PTR_SIZE; + ptr->type = coff_pointer_type; + ptr->u.pointer.points_to = res; + res = ptr; + break; + } + case DT_FCN: + { + struct coff_type *ptr + = (struct coff_type *) xmalloc (sizeof (struct coff_type)); + ptr->size = 0; + ptr->type = coff_function_type; + ptr->u.function.function_returns = res; + ptr->u.function.parameters = empty_scope (); + ptr->u.function.lines = do_lines (i, sym->_n._n_nptr[1]); + ptr->u.function.code = 0; + last_function_type = ptr; + res = ptr; + break; + } + } + } + return res; +} + +static struct coff_visible * +do_visible (i) + int i; +{ + struct internal_syment *sym = &rawsyms[i].u.syment; + struct coff_visible *visible = + (struct coff_visible *) (xmalloc (sizeof (struct coff_visible))); + enum coff_vis_type t; + switch (sym->n_sclass) + { + case C_MOS: + case C_MOU: + case C_FIELD: + t = coff_vis_member_of_struct; + break; + case C_MOE: + t = coff_vis_member_of_enum; + break; + + case C_REGPARM: + t = coff_vis_regparam; + break; + + case C_REG: + t = coff_vis_register; + break; + case C_STRTAG: + case C_UNTAG: + case C_ENTAG: + case C_TPDEF: + t = coff_vis_tag; + break; + case C_AUTOARG: + case C_ARG: + t = coff_vis_autoparam; + break; + case C_AUTO: + + + t = coff_vis_auto; + break; + case C_LABEL: + case C_STAT: + t = coff_vis_int_def; + break; + case C_EXT: + if (sym->n_scnum == N_UNDEF) + { + if (sym->n_value) + t = coff_vis_common; + else + t = coff_vis_ext_ref; + } + else + t = coff_vis_ext_def; + break; + default: + abort (); + break; + + } + visible->type = t; + return visible; +} + +static int +do_define (i, b) + int i; + struct coff_scope *b; +{ + static int symbol_index; + struct internal_syment *sym = &rawsyms[i].u.syment; + + /* Define a symbol and attach to block b */ + struct coff_symbol *s = empty_symbol (); + + s->number = ++symbol_index; + s->name = sym->_n._n_nptr[1]; + s->sfile = cur_sfile; + /* Glue onto the ofile list */ + if (lofile >= 0) + { + if (ofile->symbol_list_tail) + ofile->symbol_list_tail->next_in_ofile_list = s; + else + ofile->symbol_list_head = s; + ofile->symbol_list_tail = s; + /* And the block list */ + } + if (b->vars_tail) + b->vars_tail->next = s; + else + b->vars_head = s; + + b->vars_tail = s; + b->nvars++; + s->type = do_type (i); + s->where = do_where (i); + s->visible = do_visible (i); + + tindex[i] = s; + + /* We remember the lowest address in each section for each source file */ + + if (s->where->where == coff_where_memory + && s->type->type == coff_secdef_type) + { + struct coff_isection *is = cur_sfile->section + s->where->section->number; + + if (!is->init) + { + is->low = s->where->offset; + is->high = s->where->offset + s->type->size; + is->init = 1; + is->parent = s->where->section; + } + + } + + if (s->type->type == coff_function_type) + last_function_symbol = s; + + return i + sym->n_numaux + 1; +} + + +static +struct coff_ofile * +doit () +{ + int i; + int infile = 0; + struct coff_ofile *head = + (struct coff_ofile *) xmalloc (sizeof (struct coff_ofile)); + ofile = head; + head->source_head = 0; + head->source_tail = 0; + head->nsources = 0; + head->symbol_list_tail = 0; + head->symbol_list_head = 0; + do_sections_p1 (head); + push_scope (1); + + for (i = 0; i < rawcount;) + { + struct internal_syment *sym = &rawsyms[i].u.syment; + switch (sym->n_sclass) + { + case C_FILE: + { + /* new source file announced */ + struct coff_sfile *n = + (struct coff_sfile *) xmalloc (sizeof (struct coff_sfile)); + n->section = (struct coff_isection *) xcalloc (sizeof (struct coff_isection), abfd->section_count + 1); + cur_sfile = n; + n->name = sym->_n._n_nptr[1]; + n->next = 0; + + if (infile) + { + pop_scope (); + } + infile = 1; + push_scope (1); + file_scope = n->scope = top_scope; + + if (head->source_tail) + head->source_tail->next = n; + else + head->source_head = n; + head->source_tail = n; + head->nsources++; + i += sym->n_numaux + 1; + } + break; + case C_FCN: + { + char *name = sym->_n._n_nptr[1]; + if (name[1] == 'b') + { + /* Function start */ + push_scope (0); + last_function_type->u.function.code = top_scope; + top_scope->sec = ofile->sections + sym->n_scnum; + top_scope->offset = sym->n_value; + } + else + { + top_scope->size = sym->n_value - top_scope->offset + 1; + pop_scope (); + + } + i += sym->n_numaux + 1; + } + break; + + case C_BLOCK: + { + char *name = sym->_n._n_nptr[1]; + if (name[1] == 'b') + { + /* Block start */ + push_scope (1); + top_scope->sec = ofile->sections + sym->n_scnum; + top_scope->offset = sym->n_value; + + } + else + { + top_scope->size = sym->n_value - top_scope->offset + 1; + pop_scope (); + } + i += sym->n_numaux + 1; + } + break; + case C_REGPARM: + case C_ARG: + i = do_define (i, last_function_symbol->type->u.function.parameters); + break; + case C_MOS: + case C_MOU: + case C_FIELD: + i = do_define (i, last_struct->u.astructdef.elements); + break; + case C_MOE: + i = do_define (i, last_enum->u.aenumdef.elements); + break; + case C_STRTAG: + case C_ENTAG: + case C_UNTAG: + /* Various definition */ + i = do_define (i, top_scope); + break; + case C_EXT: + case C_LABEL: + i = do_define (i, file_scope); + break; + case C_STAT: + case C_TPDEF: + case C_AUTO: + case C_REG: + i = do_define (i, top_scope); + break; + default: + abort (); + case C_EOS: + i += sym->n_numaux + 1; + break; + } + } + do_sections_p2 (head); + return head; +} + +struct coff_ofile * +coff_grok (inabfd) + bfd *inabfd; +{ + long storage; + struct coff_ofile *p; + abfd = inabfd; + storage = bfd_get_symtab_upper_bound (abfd); + + if (storage < 0) + bfd_fatal (abfd->filename); + + syms = (asymbol **) xmalloc (storage); + symcount = bfd_canonicalize_symtab (abfd, syms); + if (symcount < 0) + bfd_fatal (abfd->filename); + rawsyms = obj_raw_syments (abfd); + rawcount = obj_raw_syment_count (abfd);; + tindex = (struct coff_symbol **) (xcalloc (sizeof (struct coff_symbol *), rawcount)); + + p = doit (); + return p; +} diff --git a/binutils/coffgrok.h b/binutils/coffgrok.h new file mode 100644 index 0000000..c0ade42 --- /dev/null +++ b/binutils/coffgrok.h @@ -0,0 +1,206 @@ +#define T_NULL 0 +#define T_VOID 1 /* function argument (only used by compiler) */ +#define T_CHAR 2 /* character */ +#define T_SHORT 3 /* short integer */ +#define T_INT 4 /* integer */ +#define T_LONG 5 /* long integer */ +#define T_FLOAT 6 /* floating point */ +#define T_DOUBLE 7 /* double word */ +#define T_STRUCT 8 /* structure */ +#define T_UNION 9 /* union */ +#define T_ENUM 10 /* enumeration */ +#define T_MOE 11 /* member of enumeration*/ +#define T_UCHAR 12 /* unsigned character */ +#define T_USHORT 13 /* unsigned short */ +#define T_UINT 14 /* unsigned integer */ +#define T_ULONG 15 /* unsigned long */ +#define T_LNGDBL 16 /* long double */ + + + struct coff_reloc + { + int offset; + struct coff_symbol *symbol; + int addend; + }; + + struct coff_section + { + char *name; + int code; + int data; + int address; + int number; /* 0..n, .text = 0 */ + int nrelocs; + int size; + struct coff_reloc *relocs; + struct sec *bfd_section; + }; + +struct coff_ofile +{ + int nsources; + struct coff_sfile *source_head; + struct coff_sfile *source_tail; + int nsections; + struct coff_section *sections; + struct coff_symbol *symbol_list_head; + struct coff_symbol *symbol_list_tail; +}; + +struct coff_isection { + int low; + int high; + int init; + struct coff_section *parent; +}; + +struct coff_sfile +{ + char *name; + struct coff_scope *scope; + struct coff_sfile *next; + + /* Vector which maps where in each output section + the input file has it's data */ + struct coff_isection *section; + +}; + + + struct coff_type +{ + int size; + enum + { + coff_pointer_type, coff_function_type, coff_array_type, coff_structdef_type, coff_basic_type, + coff_structref_type, coff_enumref_type, coff_enumdef_type, coff_secdef_type + } type; + union + { + struct + { + int address; + int size; + } asecdef; + + struct + { + int isstruct; + struct coff_scope *elements; + int idx; + } + astructdef; + struct + { + struct coff_symbol *ref; + } astructref; + + struct + { + struct coff_scope *elements; + int idx; + } aenumdef; + struct + { + struct coff_symbol *ref; + } aenumref; + + struct + { + struct coff_type *points_to; + } pointer; + struct + { + int dim; + struct coff_type *array_of; + } array; + + struct + { + struct coff_type *function_returns; + struct coff_scope *parameters; + struct coff_scope *code; + struct coff_line *lines; + } function; + int basic; /* One of T_VOID.. T_UINT */ + } u; +}; + + + struct coff_line + { + int nlines; + int *lines; + int *addresses; + }; + + + struct coff_scope + { + struct coff_section *sec; /* What section */ + int offset; /* where */ + int size; /* How big */ + struct coff_scope *parent; /* one up */ + + struct coff_scope *next; /*next along */ + + int nvars; + + struct coff_symbol *vars_head; /* symbols */ + struct coff_symbol *vars_tail; + + struct coff_scope *list_head; /* children */ + struct coff_scope *list_tail; + + }; + + + struct coff_visible + { + enum coff_vis_type + { + coff_vis_ext_def, + coff_vis_ext_ref, + coff_vis_int_def, + coff_vis_common, + coff_vis_auto, + coff_vis_register, + coff_vis_tag, + coff_vis_member_of_struct, + coff_vis_member_of_enum, + coff_vis_autoparam, + coff_vis_regparam, + } type; + }; + + struct coff_where + { + enum + { + coff_where_stack, coff_where_memory, coff_where_register, coff_where_unknown, + coff_where_strtag, coff_where_member_of_struct, + coff_where_member_of_enum, coff_where_entag, coff_where_typedef + + } where; + int offset; + int bitoffset; + int bitsize; + struct coff_section *section; + }; + + struct coff_symbol + { + char *name; + int tag; + struct coff_type *type; + struct coff_where *where; + struct coff_visible *visible; + struct coff_symbol *next; + struct coff_symbol *next_in_ofile_list; /* For the ofile list */ + int number; + int er_number; + struct coff_sfile *sfile; + }; + +struct coff_ofile *coff_grok(); diff --git a/binutils/config.in b/binutils/config.in new file mode 100644 index 0000000..38272dd --- /dev/null +++ b/binutils/config.in @@ -0,0 +1,183 @@ +/* config.in. Generated automatically from configure.in by autoheader. */ + +/* Define if using alloca.c. */ +#undef C_ALLOCA + +/* Define to empty if the keyword does not work. */ +#undef const + +/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. + This function is required for alloca.c support on those systems. */ +#undef CRAY_STACKSEG_END + +/* Define if you have alloca, as a function or macro. */ +#undef HAVE_ALLOCA + +/* Define if you have <alloca.h> and it should be used (not on Ultrix). */ +#undef HAVE_ALLOCA_H + +/* Define if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */ +#undef HAVE_SYS_WAIT_H + +/* Define as __inline if that's what the C compiler calls it. */ +#undef inline + +/* Define to `long' if <sys/types.h> doesn't define. */ +#undef off_t + +/* Define if you need to in order for stat and other things to work. */ +#undef _POSIX_SOURCE + +/* Define to `unsigned' if <sys/types.h> doesn't define. */ +#undef size_t + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown + */ +#undef STACK_DIRECTION + +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define if lex declares yytext as a char * by default, not a char[]. */ +#undef YYTEXT_POINTER + +/* Define if you have the __argz_count function. */ +#undef HAVE___ARGZ_COUNT + +/* Define if you have the __argz_next function. */ +#undef HAVE___ARGZ_NEXT + +/* Define if you have the __argz_stringify function. */ +#undef HAVE___ARGZ_STRINGIFY + +/* Define if you have the dcgettext function. */ +#undef HAVE_DCGETTEXT + +/* Define if you have the getcwd function. */ +#undef HAVE_GETCWD + +/* Define if you have the getpagesize function. */ +#undef HAVE_GETPAGESIZE + +/* Define if you have the munmap function. */ +#undef HAVE_MUNMAP + +/* Define if you have the putenv function. */ +#undef HAVE_PUTENV + +/* Define if you have the sbrk function. */ +#undef HAVE_SBRK + +/* Define if you have the setenv function. */ +#undef HAVE_SETENV + +/* Define if you have the setlocale function. */ +#undef HAVE_SETLOCALE + +/* Define if you have the stpcpy function. */ +#undef HAVE_STPCPY + +/* Define if you have the strcasecmp function. */ +#undef HAVE_STRCASECMP + +/* Define if you have the strchr function. */ +#undef HAVE_STRCHR + +/* Define if you have the utimes function. */ +#undef HAVE_UTIMES + +/* Define if you have the <argz.h> header file. */ +#undef HAVE_ARGZ_H + +/* Define if you have the <fcntl.h> header file. */ +#undef HAVE_FCNTL_H + +/* Define if you have the <limits.h> header file. */ +#undef HAVE_LIMITS_H + +/* Define if you have the <locale.h> header file. */ +#undef HAVE_LOCALE_H + +/* Define if you have the <malloc.h> header file. */ +#undef HAVE_MALLOC_H + +/* Define if you have the <nl_types.h> header file. */ +#undef HAVE_NL_TYPES_H + +/* Define if you have the <stdlib.h> header file. */ +#undef HAVE_STDLIB_H + +/* Define if you have the <string.h> header file. */ +#undef HAVE_STRING_H + +/* Define if you have the <strings.h> header file. */ +#undef HAVE_STRINGS_H + +/* Define if you have the <sys/file.h> header file. */ +#undef HAVE_SYS_FILE_H + +/* Define if you have the <sys/param.h> header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* Define if you have the <values.h> header file. */ +#undef HAVE_VALUES_H + +/* Name of package */ +#undef PACKAGE + +/* Version number of package */ +#undef VERSION + +/* Define if you have the stpcpy function */ +#undef HAVE_STPCPY + +/* Define if your locale.h file contains LC_MESSAGES. */ +#undef HAVE_LC_MESSAGES + +/* Define to 1 if NLS is requested */ +#undef ENABLE_NLS + +/* Define as 1 if you have gettext and don't want to use GNU gettext. */ +#undef HAVE_GETTEXT + +/* Is the type time_t defined in <time.h>? */ +#undef HAVE_TIME_T_IN_TIME_H + +/* Is the type time_t defined in <sys/types.h>? */ +#undef HAVE_TIME_T_IN_TYPES_H + +/* Does <utime.h> define struct utimbuf? */ +#undef HAVE_GOOD_UTIME_H + +/* Define if fprintf is not declared in system header files. */ +#undef NEED_DECLARATION_FPRINTF + +/* Define if strstr is not declared in system header files. */ +#undef NEED_DECLARATION_STRSTR + +/* Define if sbrk is not declared in system header files. */ +#undef NEED_DECLARATION_SBRK + +/* Define if getenv is not declared in system header files. */ +#undef NEED_DECLARATION_GETENV + +/* Define if environ is not declared in system header files. */ +#undef NEED_DECLARATION_ENVIRON + +/* Use b modifier when opening binary files? */ +#undef USE_BINARY_FOPEN + +/* Configured target name. */ +#undef TARGET + diff --git a/binutils/configure b/binutils/configure new file mode 100755 index 0000000..594e154 --- /dev/null +++ b/binutils/configure @@ -0,0 +1,5567 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --enable-shared[=PKGS] build shared libraries [default=yes]" +ac_help="$ac_help + --enable-static[=PKGS] build static libraries [default=yes]" +ac_help="$ac_help + --enable-fast-install[=PKGS] optimize for fast installation [default=yes]" +ac_help="$ac_help + --with-gnu-ld assume the C compiler uses GNU ld [default=no]" +ac_help="$ac_help + --disable-libtool-lock force libtool not to do file locking" +ac_help="$ac_help + --enable-targets alternative target configurations" +ac_help="$ac_help + --enable-commonbfdlib build shared BFD/opcodes/libiberty library" +ac_help="$ac_help + --disable-nls do not use Native Language Support" +ac_help="$ac_help + --with-included-gettext use the GNU gettext library included here" +ac_help="$ac_help + --enable-maintainer-mode enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +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=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -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 ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$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" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$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) + # 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 << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$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" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + 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) + 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" ;; + + -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 ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=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" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=ar.c + +# 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 its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + 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 + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +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 + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + + +# Do some error checking and defaulting for the host and target type. +# The inputs are: +# configure --host=HOST --target=TARGET --build=BUILD NONOPT +# +# The rules are: +# 1. You are not allowed to specify --host, --target, and nonopt at the +# same time. +# 2. Host defaults to nonopt. +# 3. If nonopt is not specified, then host defaults to the current host, +# as determined by config.guess. +# 4. Target and build default to nonopt. +# 5. If nonopt is not specified, then target and build default to host. + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +case $host---$target---$nonopt in +NONE---*---* | *---NONE---* | *---*---NONE) ;; +*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;; +esac + + +# Make sure we can run config.sub. +if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then : +else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } +fi + +echo $ac_n "checking host system type""... $ac_c" 1>&6 +echo "configure:594: checking host system type" >&5 + +host_alias=$host +case "$host_alias" in +NONE) + case $nonopt in + NONE) + if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then : + else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } + fi ;; + *) host_alias=$nonopt ;; + esac ;; +esac + +host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias` +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$host" 1>&6 + +echo $ac_n "checking target system type""... $ac_c" 1>&6 +echo "configure:615: checking target system type" >&5 + +target_alias=$target +case "$target_alias" in +NONE) + case $nonopt in + NONE) target_alias=$host_alias ;; + *) target_alias=$nonopt ;; + esac ;; +esac + +target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias` +target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$target" 1>&6 + +echo $ac_n "checking build system type""... $ac_c" 1>&6 +echo "configure:633: checking build system type" >&5 + +build_alias=$build +case "$build_alias" in +NONE) + case $nonopt in + NONE) build_alias=$host_alias ;; + *) build_alias=$nonopt ;; + esac ;; +esac + +build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias` +build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$build" 1>&6 + +test "$host_alias" != "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + + +# 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 +# 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" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:668: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/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 + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +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. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&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_PROGRAM}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 +echo "configure:721: checking whether build environment is sane" >&5 +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "$*" != "X $srcdir/configure conftestfile" \ + && test "$*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + { echo "configure: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" 1>&2; exit 1; } + fi + + test "$2" = conftestfile + ) +then + # Ok. + : +else + { echo "configure: error: newly created file is older than distributed files! +Check your system clock" 1>&2; exit 1; } +fi +rm -f conftest* +echo "$ac_t""yes" 1>&6 +if test "$program_transform_name" = s,x,x,; then + program_transform_name= +else + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed +fi +test "$program_prefix" != NONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + +# sed with no file args requires a program. +test "$program_transform_name" = "" && program_transform_name="s,x,x," + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:778: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + + +PACKAGE=binutils + +VERSION=2.9.4 + +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; } +fi +cat >> confdefs.h <<EOF +#define PACKAGE "$PACKAGE" +EOF + +cat >> confdefs.h <<EOF +#define VERSION "$VERSION" +EOF + + + +missing_dir=`cd $ac_aux_dir && pwd` +echo $ac_n "checking for working aclocal""... $ac_c" 1>&6 +echo "configure:824: checking for working aclocal" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (aclocal --version) < /dev/null > /dev/null 2>&1; then + ACLOCAL=aclocal + echo "$ac_t""found" 1>&6 +else + ACLOCAL="$missing_dir/missing aclocal" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoconf""... $ac_c" 1>&6 +echo "configure:837: checking for working autoconf" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoconf --version) < /dev/null > /dev/null 2>&1; then + AUTOCONF=autoconf + echo "$ac_t""found" 1>&6 +else + AUTOCONF="$missing_dir/missing autoconf" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working automake""... $ac_c" 1>&6 +echo "configure:850: checking for working automake" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (automake --version) < /dev/null > /dev/null 2>&1; then + AUTOMAKE=automake + echo "$ac_t""found" 1>&6 +else + AUTOMAKE="$missing_dir/missing automake" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoheader""... $ac_c" 1>&6 +echo "configure:863: checking for working autoheader" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoheader --version) < /dev/null > /dev/null 2>&1; then + AUTOHEADER=autoheader + echo "$ac_t""found" 1>&6 +else + AUTOHEADER="$missing_dir/missing autoheader" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6 +echo "configure:876: checking for working makeinfo" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (makeinfo --version) < /dev/null > /dev/null 2>&1; then + MAKEINFO=makeinfo + echo "$ac_t""found" 1>&6 +else + MAKEINFO="$missing_dir/missing makeinfo" + echo "$ac_t""missing" 1>&6 +fi + + + +# Check whether --enable-shared or --disable-shared was given. +if test "${enable_shared+set}" = set; then + enableval="$enable_shared" + p=${PACKAGE-default} +case "$enableval" in +yes) enable_shared=yes ;; +no) enable_shared=no ;; +*) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac +else + enable_shared=yes +fi + +# Check whether --enable-static or --disable-static was given. +if test "${enable_static+set}" = set; then + enableval="$enable_static" + p=${PACKAGE-default} +case "$enableval" in +yes) enable_static=yes ;; +no) enable_static=no ;; +*) + enable_static=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac +else + enable_static=yes +fi + +# Check whether --enable-fast-install or --disable-fast-install was given. +if test "${enable_fast_install+set}" = set; then + enableval="$enable_fast_install" + p=${PACKAGE-default} +case "$enableval" in +yes) enable_fast_install=yes ;; +no) enable_fast_install=no ;; +*) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac +else + enable_fast_install=yes +fi + +# Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:962: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:992: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +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 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1022: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_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 $# -gt 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 + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1073: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:1105: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext << EOF + +#line 1116 "configure" +#include "confdefs.h" + +main(){return(0);} +EOF +if { (eval echo configure:1121: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:1147: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:1152: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <<EOF +#ifdef __GNUC__ + yes; +#endif +EOF +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1161: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:1180: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&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 + +# Check whether --with-gnu-ld or --without-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then + withval="$with_gnu_ld" + test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$ac_cv_prog_gcc" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + echo $ac_n "checking for ld used by GCC""... $ac_c" 1>&6 +echo "configure:1223: checking for ld used by GCC" >&5 + ac_prog=`($CC -print-prog-name=ld) 2>&5` + case "$ac_prog" in + # Accept absolute paths. + /* | [A-Za-z]:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + echo $ac_n "checking for GNU ld""... $ac_c" 1>&6 +echo "configure:1247: checking for GNU ld" >&5 +else + echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6 +echo "configure:1250: checking for non-GNU ld" >&5 +fi +if eval "test \"`echo '$''{'ac_cv_path_LD'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog"; then + ac_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then + test "$with_gnu_ld" != no && break + else + test "$with_gnu_ld" != yes && break + fi + fi + done + IFS="$ac_save_ifs" +else + ac_cv_path_LD="$LD" # Let the user override the test with a path. +fi +fi + +LD="$ac_cv_path_LD" +if test -n "$LD"; then + echo "$ac_t""$LD" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi +test -z "$LD" && { echo "configure: error: no acceptable ld found in \$PATH" 1>&2; exit 1; } + +echo $ac_n "checking if the linker ($LD) is GNU ld""... $ac_c" 1>&6 +echo "configure:1286: checking if the linker ($LD) is GNU ld" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gnu_ld'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # I'd rather use --version here, but apparently some GNU ld's only accept -v. +if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then + ac_cv_prog_gnu_ld=yes +else + ac_cv_prog_gnu_ld=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gnu_ld" 1>&6 + + +echo $ac_n "checking for BSD-compatible nm""... $ac_c" 1>&6 +echo "configure:1302: checking for BSD-compatible nm" >&5 +if eval "test \"`echo '$''{'ac_cv_path_NM'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$NM"; then + # Let the user override the test. + ac_cv_path_NM="$NM" +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/nm; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + ac_cv_path_NM="$ac_dir/nm -B" + break + elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + ac_cv_path_NM="$ac_dir/nm -p" + break + else + ac_cv_path_NM=${ac_cv_path_NM="$ac_dir/nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm +fi +fi + +NM="$ac_cv_path_NM" +echo "$ac_t""$NM" 1>&6 + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +echo $ac_n "checking command to parse $NM output""... $ac_c" 1>&6 +echo "configure:1340: checking command to parse $NM output" >&5 +if eval "test \"`echo '$''{'ac_cv_sys_global_symbol_pipe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # These are sane defaults that work on at least a few old systems. +# {They come from Ultrix. What could be older than Ultrix?!! ;)} + +# Character class describing NM global symbol codes. +ac_symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +ac_sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Transform the above into a raw symbol and a C symbol. +ac_symxfrm='\1 \2\3 \3' + +# Transform an extracted symbol line into a proper C declaration +ac_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'" + +# Define system-specific variables. +case "$host_os" in +aix*) + ac_symcode='[BCDT]' + ;; +cygwin* | mingw*) + ac_symcode='[ABCDGISTW]' + ;; +hpux*) + ac_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^. .* \(.*\)$/extern char \1;/p'" + ;; +irix*) + ac_symcode='[BCDEGRST]' + ;; +solaris*) + ac_symcode='[BDT]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then + ac_symcode='[ABCDGISTW]' +fi + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + ac_cv_sys_global_symbol_pipe="sed -n -e 's/^.* \($ac_symcode\) *\($ac_symprfx\)$ac_sympat$/$ac_symxfrm/p'" + + # Check to see that the pipe works correctly. + ac_pipe_works=no + rm -f conftest.$ac_ext + cat > conftest.$ac_ext <<EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func;return 0;} +EOF + + if { (eval echo configure:1403: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + # Now try to grab the symbols. + ac_nlist=conftest.nm + + if { (eval echo configure:1407: \"$NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist\") 1>&5; (eval $NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist) 2>&5; } && test -s "$ac_nlist"; then + + # Try sorting and uniquifying the output. + if sort "$ac_nlist" | uniq > "$ac_nlist"T; then + mv -f "$ac_nlist"T "$ac_nlist" + else + rm -f "$ac_nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if egrep ' nm_test_var$' "$ac_nlist" >/dev/null; then + if egrep ' nm_test_func$' "$ac_nlist" >/dev/null; then + cat <<EOF > conftest.c +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$ac_global_symbol_to_cdecl"' < "$ac_nlist" >> conftest.c' + + cat <<EOF >> conftest.c +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[] = +{ +EOF + sed 's/^. \(.*\) \(.*\)$/ {"\2", (lt_ptr_t) \&\2},/' < "$ac_nlist" >> conftest.c + cat <<\EOF >> conftest.c + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftestm.$ac_objext + ac_save_LIBS="$LIBS" + ac_save_CFLAGS="$CFLAGS" + LIBS="conftestm.$ac_objext" + CFLAGS="$CFLAGS$no_builtin_flag" + if { (eval echo configure:1459: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + ac_pipe_works=yes + else + echo "configure: failed program was:" >&5 + cat conftest.c >&5 + fi + LIBS="$ac_save_LIBS" + CFLAGS="$ac_save_CFLAGS" + else + echo "cannot find nm_test_func in $ac_nlist" >&5 + fi + else + echo "cannot find nm_test_var in $ac_nlist" >&5 + fi + else + echo "cannot run $ac_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.c >&5 + fi + rm -rf conftest* + + # Do not use the global_symbol_pipe unless it works. + if test "$ac_pipe_works" = yes; then + if test x"$ac_symprfx" = x"_"; then + ac_cv_sys_symbol_underscore=yes + else + ac_cv_sys_symbol_underscore=no + fi + break + else + ac_cv_sys_global_symbol_pipe= + fi +done + +fi + + +ac_result=yes +if test -z "$ac_cv_sys_global_symbol_pipe"; then + ac_result=no +fi +echo "$ac_t""$ac_result" 1>&6 + +echo $ac_n "checking for _ prefix in compiled symbols""... $ac_c" 1>&6 +echo "configure:1505: checking for _ prefix in compiled symbols" >&5 +if eval "test \"`echo '$''{'ac_cv_sys_symbol_underscore'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_cv_sys_symbol_underscore=no +cat > conftest.$ac_ext <<EOF +void nm_test_func(){} +int main(){nm_test_func;return 0;} +EOF +if { (eval echo configure:1514: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + # Now try to grab the symbols. + ac_nlist=conftest.nm + if { (eval echo configure:1517: \"$NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist\") 1>&5; (eval $NM conftest.$ac_objext \| $ac_cv_sys_global_symbol_pipe \> $ac_nlist) 2>&5; } && test -s "$ac_nlist"; then + # See whether the symbols have a leading underscore. + if egrep '^. _nm_test_func' "$ac_nlist" >/dev/null; then + ac_cv_sys_symbol_underscore=yes + else + if egrep '^. nm_test_func ' "$ac_nlist" >/dev/null; then + : + else + echo "configure: cannot find nm_test_func in $ac_nlist" >&5 + fi + fi + else + echo "configure: cannot run $ac_cv_sys_global_symbol_pipe" >&5 + fi +else + echo "configure: failed program was:" >&5 + cat conftest.c >&5 +fi +rm -rf conftest* + +fi + +echo "$ac_t""$ac_cv_sys_symbol_underscore" 1>&6 +USE_SYMBOL_UNDERSCORE=${ac_cv_sys_symbol_underscore=no} + +echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 +echo "configure:1543: checking whether ln -s works" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + rm -f conftestdata +if ln -s X conftestdata 2>/dev/null +then + rm -f conftestdata + ac_cv_prog_LN_S="ln -s" +else + ac_cv_prog_LN_S=ln +fi +fi +LN_S="$ac_cv_prog_LN_S" +if test "$ac_cv_prog_LN_S" = "ln -s"; then + echo "$ac_t""yes" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test $host != $build; then + ac_tool_prefix=${host_alias}- +else + ac_tool_prefix= +fi + + +# Check for any special flags to pass to ltconfig. +libtool_flags="--cache-file=$cache_file" +test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared" +test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static" +test "$enable_fast_install" = no && libtool_flags="$libtool_flags --disable-fast-install" +test "$lt_dlopen" = yes && libtool_flags="$libtool_flags --enable-dlopen" +test "$silent" = yes && libtool_flags="$libtool_flags --silent" +test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc" +test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld" + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case "$host" in +*-*-irix6*) + # Find out which ABI we are using. + echo '#line 1585 "configure"' > conftest.$ac_ext + if { (eval echo configure:1586: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + case "`/usr/bin/file conftest.o`" in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + echo $ac_n "checking whether the C compiler needs -belf""... $ac_c" 1>&6 +echo "configure:1607: checking whether the C compiler needs -belf" >&5 +if eval "test \"`echo '$''{'lt_cv_cc_needs_belf'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1612 "configure" +#include "confdefs.h" + +int main() { + +; return 0; } +EOF +if { (eval echo configure:1619: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + lt_cv_cc_needs_belf=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + lt_cv_cc_needs_belf=no +fi +rm -f conftest* +fi + +echo "$ac_t""$lt_cv_cc_needs_belf" 1>&6 + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; + +*-*-cygwin*) + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1642: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_DLLTOOL'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +DLLTOOL="$ac_cv_prog_DLLTOOL" +if test -n "$DLLTOOL"; then + echo "$ac_t""$DLLTOOL" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + +if test -z "$ac_cv_prog_DLLTOOL"; then +if test -n "$ac_tool_prefix"; then + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1674: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_DLLTOOL'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_DLLTOOL="dlltool" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_DLLTOOL" && ac_cv_prog_DLLTOOL="false" +fi +fi +DLLTOOL="$ac_cv_prog_DLLTOOL" +if test -n "$DLLTOOL"; then + echo "$ac_t""$DLLTOOL" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +else + DLLTOOL="false" +fi +fi + +# Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args. +set dummy ${ac_tool_prefix}as; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1709: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_AS'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$AS"; then + ac_cv_prog_AS="$AS" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_AS="${ac_tool_prefix}as" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +AS="$ac_cv_prog_AS" +if test -n "$AS"; then + echo "$ac_t""$AS" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + +if test -z "$ac_cv_prog_AS"; then +if test -n "$ac_tool_prefix"; then + # Extract the first word of "as", so it can be a program name with args. +set dummy as; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1741: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_AS'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$AS"; then + ac_cv_prog_AS="$AS" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_AS="as" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_AS" && ac_cv_prog_AS="false" +fi +fi +AS="$ac_cv_prog_AS" +if test -n "$AS"; then + echo "$ac_t""$AS" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +else + AS="false" +fi +fi + + + ;; + +esac + +# enable the --disable-libtool-lock switch + +# Check whether --enable-libtool-lock or --disable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then + enableval="$enable_libtool_lock" + need_locks=$enableval +else + need_locks=yes +fi + + +if test x"$need_locks" = xno; then + libtool_flags="$libtool_flags --disable-lock" +fi + + +# Save cache, so that ltconfig can load it +cat > confcache <<\EOF +# 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. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# 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. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + + +# Actually configure libtool. ac_aux_dir is where install-sh is found. +CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \ +LD="$LD" NM="$NM" RANLIB="$RANLIB" LN_S="$LN_S" \ +DLLTOOL="$DLLTOOL" AS="$AS" \ +${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \ +$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $host \ +|| { echo "configure: error: libtool configure failed" 1>&2; exit 1; } + +# Reload cache, that may have been modified by ltconfig +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltconfig $ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + +# Redirect the config.log output again, so that the ltconfig log is not +# clobbered by the next message. +exec 5>>./config.log + + +# Check whether --enable-targets or --disable-targets was given. +if test "${enable_targets+set}" = set; then + enableval="$enable_targets" + case "${enableval}" in + yes | "") { echo "configure: error: enable-targets option must specify target names or 'all'" 1>&2; exit 1; } + ;; + no) enable_targets= ;; + *) enable_targets=$enableval ;; +esac +fi +# Check whether --enable-commonbfdlib or --disable-commonbfdlib was given. +if test "${enable_commonbfdlib+set}" = set; then + enableval="$enable_commonbfdlib" + case "${enableval}" in + yes) commonbfdlib=true ;; + no) commonbfdlib=false ;; + *) { echo "configure: error: bad value ${enableval} for BFD commonbfdlib option" 1>&2; exit 1; } ;; +esac +fi + + + + + +if test -z "$target" ; then + { echo "configure: error: Unrecognized target system type; please check config.sub." 1>&2; exit 1; } +fi +if test -z "$host" ; then + { echo "configure: error: Unrecognized host system type; please check config.sub." 1>&2; exit 1; } +fi + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1906: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +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 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1936: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_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 $# -gt 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 + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1987: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:2019: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext << EOF + +#line 2030 "configure" +#include "confdefs.h" + +main(){return(0);} +EOF +if { (eval echo configure:2035: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:2061: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:2066: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <<EOF +#ifdef __GNUC__ + yes; +#endif +EOF +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:2075: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:2094: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&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 + + +for ac_prog in 'bison -y' byacc +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2131: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$YACC"; then + ac_cv_prog_YACC="$YACC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_YACC="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +YACC="$ac_cv_prog_YACC" +if test -n "$YACC"; then + echo "$ac_t""$YACC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$YACC" && break +done +test -n "$YACC" || YACC="yacc" + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:2162: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext <<EOF +#line 2177 "configure" +#include "confdefs.h" +#include <assert.h> +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2183: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext <<EOF +#line 2194 "configure" +#include "confdefs.h" +#include <assert.h> +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2200: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -nologo -E" + cat > conftest.$ac_ext <<EOF +#line 2211 "configure" +#include "confdefs.h" +#include <assert.h> +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2217: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + +missing_dir=`cd $ac_aux_dir && pwd` +for ac_prog in flex lex +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2247: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_LEX'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$LEX"; then + ac_cv_prog_LEX="$LEX" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_LEX="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +LEX="$ac_cv_prog_LEX" +if test -n "$LEX"; then + echo "$ac_t""$LEX" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$LEX" && break +done +test -n "$LEX" || LEX=""$missing_dir/missing flex"" + +# Extract the first word of "flex", so it can be a program name with args. +set dummy flex; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2280: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_LEX'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$LEX"; then + ac_cv_prog_LEX="$LEX" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_LEX="flex" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_LEX" && ac_cv_prog_LEX="lex" +fi +fi +LEX="$ac_cv_prog_LEX" +if test -n "$LEX"; then + echo "$ac_t""$LEX" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$LEXLIB" +then + case "$LEX" in + flex*) ac_lib=fl ;; + *) ac_lib=l ;; + esac + echo $ac_n "checking for yywrap in -l$ac_lib""... $ac_c" 1>&6 +echo "configure:2314: checking for yywrap in -l$ac_lib" >&5 +ac_lib_var=`echo $ac_lib'_'yywrap | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-l$ac_lib $LIBS" +cat > conftest.$ac_ext <<EOF +#line 2322 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char yywrap(); + +int main() { +yywrap() +; return 0; } +EOF +if { (eval echo configure:2333: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + LEXLIB="-l$ac_lib" +else + echo "$ac_t""no" 1>&6 +fi + +fi + +echo $ac_n "checking lex output file root""... $ac_c" 1>&6 +echo "configure:2356: checking lex output file root" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_lex_root'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # The minimal lex program is just a single line: %%. But some broken lexes +# (Solaris, I think it was) want two %% lines, so accommodate them. +echo '%% +%%' | $LEX +if test -f lex.yy.c; then + ac_cv_prog_lex_root=lex.yy +elif test -f lexyy.c; then + ac_cv_prog_lex_root=lexyy +else + { echo "configure: error: cannot find output from $LEX; giving up" 1>&2; exit 1; } +fi +fi + +echo "$ac_t""$ac_cv_prog_lex_root" 1>&6 +LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root + +echo $ac_n "checking whether yytext is a pointer""... $ac_c" 1>&6 +echo "configure:2377: checking whether yytext is a pointer" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_lex_yytext_pointer'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # POSIX says lex can declare yytext either as a pointer or an array; the +# default is implementation-dependent. Figure out which it is, since +# not all implementations provide the %pointer and %array declarations. +ac_cv_prog_lex_yytext_pointer=no +echo 'extern char *yytext;' >>$LEX_OUTPUT_ROOT.c +ac_save_LIBS="$LIBS" +LIBS="$LIBS $LEXLIB" +cat > conftest.$ac_ext <<EOF +#line 2389 "configure" +#include "confdefs.h" +`cat $LEX_OUTPUT_ROOT.c` +int main() { + +; return 0; } +EOF +if { (eval echo configure:2396: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ac_cv_prog_lex_yytext_pointer=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +LIBS="$ac_save_LIBS" +rm -f "${LEX_OUTPUT_ROOT}.c" + +fi + +echo "$ac_t""$ac_cv_prog_lex_yytext_pointer" 1>&6 +if test $ac_cv_prog_lex_yytext_pointer = yes; then + cat >> confdefs.h <<\EOF +#define YYTEXT_POINTER 1 +EOF + +fi + + +ALL_LINGUAS= +echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6 +echo "configure:2420: checking for POSIXized ISC" >&5 +if test -d /etc/conf/kconfig.d && + grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1 +then + echo "$ac_t""yes" 1>&6 + ISC=yes # If later tests want to check for ISC. + cat >> confdefs.h <<\EOF +#define _POSIX_SOURCE 1 +EOF + + if test "$GCC" = yes; then + CC="$CC -posix" + else + CC="$CC -Xp" + fi +else + echo "$ac_t""no" 1>&6 + ISC= +fi + +echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 +echo "configure:2441: checking for ANSI C header files" >&5 +if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2446 "configure" +#include "confdefs.h" +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2454: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + ac_cv_header_stdc=yes +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. +cat > conftest.$ac_ext <<EOF +#line 2471 "configure" +#include "confdefs.h" +#include <string.h> +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + rm -rf conftest* + 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 > conftest.$ac_ext <<EOF +#line 2489 "configure" +#include "confdefs.h" +#include <stdlib.h> +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + rm -rf conftest* + 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 > conftest.$ac_ext <<EOF +#line 2510 "configure" +#include "confdefs.h" +#include <ctype.h> +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#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)) exit(2); +exit (0); } + +EOF +if { (eval echo configure:2521: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_header_stdc=no +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_header_stdc" 1>&6 +if test $ac_cv_header_stdc = yes; then + cat >> confdefs.h <<\EOF +#define STDC_HEADERS 1 +EOF + +fi + +echo $ac_n "checking for working const""... $ac_c" 1>&6 +echo "configure:2545: checking for working const" >&5 +if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2550 "configure" +#include "confdefs.h" + +int main() { + +/* Ultrix mips cc rejects this. */ +typedef int charset[2]; const charset x; +/* SunOS 4.1.1 cc rejects this. */ +char const *const *ccp; +char **p; +/* NEC SVR4.0.2 mips cc rejects this. */ +struct point {int x, y;}; +static struct point const zero = {0,0}; +/* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in an arm + of an if-expression whose if-part is not a constant expression */ +const char *g = "string"; +ccp = &g + (g ? g-g : 0); +/* HPUX 7.0 cc rejects these. */ +++ccp; +p = (char**) ccp; +ccp = (char const *const *) p; +{ /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; +} +{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; +} +{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; +} +{ /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; +} +{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; +} + +; return 0; } +EOF +if { (eval echo configure:2599: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_const=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_c_const=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_c_const" 1>&6 +if test $ac_cv_c_const = no; then + cat >> confdefs.h <<\EOF +#define const +EOF + +fi + +echo $ac_n "checking for inline""... $ac_c" 1>&6 +echo "configure:2620: checking for inline" >&5 +if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat > conftest.$ac_ext <<EOF +#line 2627 "configure" +#include "confdefs.h" + +int main() { +} $ac_kw foo() { +; return 0; } +EOF +if { (eval echo configure:2634: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_inline=$ac_kw; break +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +done + +fi + +echo "$ac_t""$ac_cv_c_inline" 1>&6 +case "$ac_cv_c_inline" in + inline | yes) ;; + no) cat >> confdefs.h <<\EOF +#define inline +EOF + ;; + *) cat >> confdefs.h <<EOF +#define inline $ac_cv_c_inline +EOF + ;; +esac + +echo $ac_n "checking for off_t""... $ac_c" 1>&6 +echo "configure:2660: checking for off_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2665 "configure" +#include "confdefs.h" +#include <sys/types.h> +#if STDC_HEADERS +#include <stdlib.h> +#include <stddef.h> +#endif +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "(^|[^a-zA-Z_0-9])off_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_off_t=yes +else + rm -rf conftest* + ac_cv_type_off_t=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_type_off_t" 1>&6 +if test $ac_cv_type_off_t = no; then + cat >> confdefs.h <<\EOF +#define off_t long +EOF + +fi + +echo $ac_n "checking for size_t""... $ac_c" 1>&6 +echo "configure:2693: checking for size_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2698 "configure" +#include "confdefs.h" +#include <sys/types.h> +#if STDC_HEADERS +#include <stdlib.h> +#include <stddef.h> +#endif +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_size_t=yes +else + rm -rf conftest* + ac_cv_type_size_t=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_type_size_t" 1>&6 +if test $ac_cv_type_size_t = no; then + cat >> confdefs.h <<\EOF +#define size_t unsigned +EOF + +fi + +# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6 +echo "configure:2728: checking for working alloca.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2733 "configure" +#include "confdefs.h" +#include <alloca.h> +int main() { +char *p = alloca(2 * sizeof(int)); +; return 0; } +EOF +if { (eval echo configure:2740: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ac_cv_header_alloca_h=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_alloca_h=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_header_alloca_h" 1>&6 +if test $ac_cv_header_alloca_h = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_ALLOCA_H 1 +EOF + +fi + +echo $ac_n "checking for alloca""... $ac_c" 1>&6 +echo "configure:2761: checking for alloca" >&5 +if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2766 "configure" +#include "confdefs.h" + +#ifdef __GNUC__ +# define alloca __builtin_alloca +#else +# ifdef _MSC_VER +# include <malloc.h> +# define alloca _alloca +# else +# if HAVE_ALLOCA_H +# include <alloca.h> +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +char *alloca (); +# endif +# endif +# endif +# endif +#endif + +int main() { +char *p = (char *) alloca(1); +; return 0; } +EOF +if { (eval echo configure:2794: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ac_cv_func_alloca_works=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_func_alloca_works=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_func_alloca_works" 1>&6 +if test $ac_cv_func_alloca_works = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_ALLOCA 1 +EOF + +fi + +if test $ac_cv_func_alloca_works = no; then + # The SVR3 libPW and SVR4 libucb both contain incompatible functions + # that cause trouble. Some versions do not even contain alloca or + # contain a buggy version. If you still want to use their alloca, + # use ar to extract alloca.o from them instead of compiling alloca.c. + ALLOCA=alloca.${ac_objext} + cat >> confdefs.h <<\EOF +#define C_ALLOCA 1 +EOF + + +echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 +echo "configure:2826: checking whether alloca needs Cray hooks" >&5 +if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2831 "configure" +#include "confdefs.h" +#if defined(CRAY) && ! defined(CRAY2) +webecray +#else +wenotbecray +#endif + +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "webecray" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_os_cray=yes +else + rm -rf conftest* + ac_cv_os_cray=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_os_cray" 1>&6 +if test $ac_cv_os_cray = yes; then +for ac_func in _getb67 GETB67 getb67; do + echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2856: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2861 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2884: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<EOF +#define CRAY_STACKSEG_END $ac_func +EOF + + break +else + echo "$ac_t""no" 1>&6 +fi + +done +fi + +echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 +echo "configure:2911: checking stack direction for C alloca" >&5 +if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_c_stack_direction=0 +else + cat > conftest.$ac_ext <<EOF +#line 2919 "configure" +#include "confdefs.h" +find_stack_direction () +{ + static char *addr = 0; + auto char dummy; + if (addr == 0) + { + addr = &dummy; + return find_stack_direction (); + } + else + return (&dummy > addr) ? 1 : -1; +} +main () +{ + exit (find_stack_direction() < 0); +} +EOF +if { (eval echo configure:2938: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_c_stack_direction=1 +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_c_stack_direction=-1 +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$ac_cv_c_stack_direction" 1>&6 +cat >> confdefs.h <<EOF +#define STACK_DIRECTION $ac_cv_c_stack_direction +EOF + +fi + +for ac_hdr in unistd.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2963: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2968 "configure" +#include "confdefs.h" +#include <$ac_hdr> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2973: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +for ac_func in getpagesize +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:3002: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 3007 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3030: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +echo $ac_n "checking for working mmap""... $ac_c" 1>&6 +echo "configure:3055: checking for working mmap" >&5 +if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_func_mmap_fixed_mapped=no +else + cat > conftest.$ac_ext <<EOF +#line 3063 "configure" +#include "confdefs.h" + +/* Thanks to Mike Haertel and Jim Avera for this test. + Here is a matrix of mmap possibilities: + mmap private not fixed + mmap private fixed at somewhere currently unmapped + mmap private fixed at somewhere already mapped + mmap shared not fixed + mmap shared fixed at somewhere currently unmapped + mmap shared fixed at somewhere already mapped + For private mappings, we should verify that changes cannot be read() + back from the file, nor mmap's back from the file at a different + address. (There have been systems where private was not correctly + implemented like the infamous i386 svr4.0, and systems where the + VM page cache was not coherent with the filesystem buffer cache + like early versions of FreeBSD and possibly contemporary NetBSD.) + For shared mappings, we should conversely verify that changes get + propogated back to all the places they're supposed to be. + + Grep wants private fixed already mapped. + The main things grep needs to know about mmap are: + * does it exist and is it safe to write into the mmap'd area + * how to use it (BSD variants) */ +#include <sys/types.h> +#include <fcntl.h> +#include <sys/mman.h> + +/* This mess was copied from the GNU getpagesize.h. */ +#ifndef HAVE_GETPAGESIZE +# ifdef HAVE_UNISTD_H +# include <unistd.h> +# endif + +/* Assume that all systems that can run configure have sys/param.h. */ +# ifndef HAVE_SYS_PARAM_H +# define HAVE_SYS_PARAM_H 1 +# endif + +# ifdef _SC_PAGESIZE +# define getpagesize() sysconf(_SC_PAGESIZE) +# else /* no _SC_PAGESIZE */ +# ifdef HAVE_SYS_PARAM_H +# include <sys/param.h> +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else /* no EXEC_PAGESIZE */ +# ifdef NBPG +# define getpagesize() NBPG * CLSIZE +# ifndef CLSIZE +# define CLSIZE 1 +# endif /* no CLSIZE */ +# else /* no NBPG */ +# ifdef NBPC +# define getpagesize() NBPC +# else /* no NBPC */ +# ifdef PAGESIZE +# define getpagesize() PAGESIZE +# endif /* PAGESIZE */ +# endif /* no NBPC */ +# endif /* no NBPG */ +# endif /* no EXEC_PAGESIZE */ +# else /* no HAVE_SYS_PARAM_H */ +# define getpagesize() 8192 /* punt totally */ +# endif /* no HAVE_SYS_PARAM_H */ +# endif /* no _SC_PAGESIZE */ + +#endif /* no HAVE_GETPAGESIZE */ + +#ifdef __cplusplus +extern "C" { void *malloc(unsigned); } +#else +char *malloc(); +#endif + +int +main() +{ + char *data, *data2, *data3; + int i, pagesize; + int fd; + + pagesize = getpagesize(); + + /* + * First, make a file with some known garbage in it. + */ + data = malloc(pagesize); + if (!data) + exit(1); + for (i = 0; i < pagesize; ++i) + *(data + i) = rand(); + umask(0); + fd = creat("conftestmmap", 0600); + if (fd < 0) + exit(1); + if (write(fd, data, pagesize) != pagesize) + exit(1); + close(fd); + + /* + * Next, try to mmap the file at a fixed address which + * already has something else allocated at it. If we can, + * also make sure that we see the same garbage. + */ + fd = open("conftestmmap", O_RDWR); + if (fd < 0) + exit(1); + data2 = malloc(2 * pagesize); + if (!data2) + exit(1); + data2 += (pagesize - ((int) data2 & (pagesize - 1))) & (pagesize - 1); + if (data2 != mmap(data2, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED, fd, 0L)) + exit(1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data2 + i)) + exit(1); + + /* + * Finally, make sure that changes to the mapped area + * do not percolate back to the file as seen by read(). + * (This is a bug on some variants of i386 svr4.0.) + */ + for (i = 0; i < pagesize; ++i) + *(data2 + i) = *(data2 + i) + 1; + data3 = malloc(pagesize); + if (!data3) + exit(1); + if (read(fd, data3, pagesize) != pagesize) + exit(1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data3 + i)) + exit(1); + close(fd); + unlink("conftestmmap"); + exit(0); +} + +EOF +if { (eval echo configure:3203: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_func_mmap_fixed_mapped=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_func_mmap_fixed_mapped=no +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$ac_cv_func_mmap_fixed_mapped" 1>&6 +if test $ac_cv_func_mmap_fixed_mapped = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_MMAP 1 +EOF + +fi + + + for ac_hdr in argz.h limits.h locale.h nl_types.h malloc.h string.h \ +unistd.h values.h sys/param.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:3231: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 3236 "configure" +#include "confdefs.h" +#include <$ac_hdr> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:3241: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + + for ac_func in getcwd munmap putenv setenv setlocale strchr strcasecmp \ +__argz_count __argz_stringify __argz_next +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:3271: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 3276 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3299: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + + + if test "${ac_cv_func_stpcpy+set}" != "set"; then + for ac_func in stpcpy +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:3328: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 3333 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3356: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + + fi + if test "${ac_cv_func_stpcpy}" = "yes"; then + cat >> confdefs.h <<\EOF +#define HAVE_STPCPY 1 +EOF + + fi + + if test $ac_cv_header_locale_h = yes; then + echo $ac_n "checking for LC_MESSAGES""... $ac_c" 1>&6 +echo "configure:3390: checking for LC_MESSAGES" >&5 +if eval "test \"`echo '$''{'am_cv_val_LC_MESSAGES'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 3395 "configure" +#include "confdefs.h" +#include <locale.h> +int main() { +return LC_MESSAGES +; return 0; } +EOF +if { (eval echo configure:3402: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + am_cv_val_LC_MESSAGES=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + am_cv_val_LC_MESSAGES=no +fi +rm -f conftest* +fi + +echo "$ac_t""$am_cv_val_LC_MESSAGES" 1>&6 + if test $am_cv_val_LC_MESSAGES = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_LC_MESSAGES 1 +EOF + + fi + fi + echo $ac_n "checking whether NLS is requested""... $ac_c" 1>&6 +echo "configure:3423: checking whether NLS is requested" >&5 + # Check whether --enable-nls or --disable-nls was given. +if test "${enable_nls+set}" = set; then + enableval="$enable_nls" + USE_NLS=$enableval +else + USE_NLS=yes +fi + + echo "$ac_t""$USE_NLS" 1>&6 + + + USE_INCLUDED_LIBINTL=no + + if test "$USE_NLS" = "yes"; then + cat >> confdefs.h <<\EOF +#define ENABLE_NLS 1 +EOF + + echo $ac_n "checking whether included gettext is requested""... $ac_c" 1>&6 +echo "configure:3443: checking whether included gettext is requested" >&5 + # Check whether --with-included-gettext or --without-included-gettext was given. +if test "${with_included_gettext+set}" = set; then + withval="$with_included_gettext" + nls_cv_force_use_gnu_gettext=$withval +else + nls_cv_force_use_gnu_gettext=no +fi + + echo "$ac_t""$nls_cv_force_use_gnu_gettext" 1>&6 + + nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" + if test "$nls_cv_force_use_gnu_gettext" != "yes"; then + nls_cv_header_intl= + nls_cv_header_libgt= + CATOBJEXT=NONE + + ac_safe=`echo "libintl.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for libintl.h""... $ac_c" 1>&6 +echo "configure:3462: checking for libintl.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 3467 "configure" +#include "confdefs.h" +#include <libintl.h> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:3472: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + echo $ac_n "checking for gettext in libc""... $ac_c" 1>&6 +echo "configure:3489: checking for gettext in libc" >&5 +if eval "test \"`echo '$''{'gt_cv_func_gettext_libc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 3494 "configure" +#include "confdefs.h" +#include <libintl.h> +int main() { +return (int) gettext ("") +; return 0; } +EOF +if { (eval echo configure:3501: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + gt_cv_func_gettext_libc=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + gt_cv_func_gettext_libc=no +fi +rm -f conftest* +fi + +echo "$ac_t""$gt_cv_func_gettext_libc" 1>&6 + + if test "$gt_cv_func_gettext_libc" != "yes"; then + echo $ac_n "checking for bindtextdomain in -lintl""... $ac_c" 1>&6 +echo "configure:3517: checking for bindtextdomain in -lintl" >&5 +ac_lib_var=`echo intl'_'bindtextdomain | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lintl $LIBS" +cat > conftest.$ac_ext <<EOF +#line 3525 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char bindtextdomain(); + +int main() { +bindtextdomain() +; return 0; } +EOF +if { (eval echo configure:3536: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + echo $ac_n "checking for gettext in libintl""... $ac_c" 1>&6 +echo "configure:3552: checking for gettext in libintl" >&5 +if eval "test \"`echo '$''{'gt_cv_func_gettext_libintl'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 3557 "configure" +#include "confdefs.h" + +int main() { +return (int) gettext ("") +; return 0; } +EOF +if { (eval echo configure:3564: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + gt_cv_func_gettext_libintl=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + gt_cv_func_gettext_libintl=no +fi +rm -f conftest* +fi + +echo "$ac_t""$gt_cv_func_gettext_libintl" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + fi + + if test "$gt_cv_func_gettext_libc" = "yes" \ + || test "$gt_cv_func_gettext_libintl" = "yes"; then + cat >> confdefs.h <<\EOF +#define HAVE_GETTEXT 1 +EOF + + # Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:3592: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$MSGFMT" in + /*) + ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then + ac_cv_path_MSGFMT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="no" + ;; +esac +fi +MSGFMT="$ac_cv_path_MSGFMT" +if test -n "$MSGFMT"; then + echo "$ac_t""$MSGFMT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + if test "$MSGFMT" != "no"; then + for ac_func in dcgettext +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:3626: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 3631 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3654: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + + # Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:3681: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$GMSGFMT" in + /*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_GMSGFMT="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" + ;; +esac +fi +GMSGFMT="$ac_cv_path_GMSGFMT" +if test -n "$GMSGFMT"; then + echo "$ac_t""$GMSGFMT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + # Extract the first word of "xgettext", so it can be a program name with args. +set dummy xgettext; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:3717: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$XGETTEXT" in + /*) + ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then + ac_cv_path_XGETTEXT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" + ;; +esac +fi +XGETTEXT="$ac_cv_path_XGETTEXT" +if test -n "$XGETTEXT"; then + echo "$ac_t""$XGETTEXT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + cat > conftest.$ac_ext <<EOF +#line 3749 "configure" +#include "confdefs.h" + +int main() { +extern int _nl_msg_cat_cntr; + return _nl_msg_cat_cntr +; return 0; } +EOF +if { (eval echo configure:3757: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + CATOBJEXT=.gmo + DATADIRNAME=share +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CATOBJEXT=.mo + DATADIRNAME=lib +fi +rm -f conftest* + INSTOBJEXT=.mo + fi + fi + +else + echo "$ac_t""no" 1>&6 +fi + + + + if test "$CATOBJEXT" = "NONE"; then + nls_cv_use_gnu_gettext=yes + fi + fi + + if test "$nls_cv_use_gnu_gettext" = "yes"; then + INTLOBJS="\$(GETTOBJS)" + # Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:3789: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$MSGFMT" in + /*) + ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then + ac_cv_path_MSGFMT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="msgfmt" + ;; +esac +fi +MSGFMT="$ac_cv_path_MSGFMT" +if test -n "$MSGFMT"; then + echo "$ac_t""$MSGFMT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + # Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:3823: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$GMSGFMT" in + /*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_GMSGFMT="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" + ;; +esac +fi +GMSGFMT="$ac_cv_path_GMSGFMT" +if test -n "$GMSGFMT"; then + echo "$ac_t""$GMSGFMT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + # Extract the first word of "xgettext", so it can be a program name with args. +set dummy xgettext; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:3859: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$XGETTEXT" in + /*) + ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then + ac_cv_path_XGETTEXT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" + ;; +esac +fi +XGETTEXT="$ac_cv_path_XGETTEXT" +if test -n "$XGETTEXT"; then + echo "$ac_t""$XGETTEXT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + + USE_INCLUDED_LIBINTL=yes + CATOBJEXT=.gmo + INSTOBJEXT=.mo + DATADIRNAME=share + INTLDEPS='$(top_builddir)/../intl/libintl.a' + INTLLIBS=$INTLDEPS + LIBS=`echo $LIBS | sed -e 's/-lintl//'` + nls_cv_header_intl=libintl.h + nls_cv_header_libgt=libgettext.h + fi + + if test "$XGETTEXT" != ":"; then + if $XGETTEXT --omit-header /dev/null 2> /dev/null; then + : ; + else + echo "$ac_t""found xgettext programs is not GNU xgettext; ignore it" 1>&6 + XGETTEXT=":" + fi + fi + + # We need to process the po/ directory. + POSUB=po + else + DATADIRNAME=share + nls_cv_header_intl=libintl.h + nls_cv_header_libgt=libgettext.h + fi + + # If this is used in GNU gettext we have to set USE_NLS to `yes' + # because some of the sources are only built for this goal. + if test "$PACKAGE" = gettext; then + USE_NLS=yes + USE_INCLUDED_LIBINTL=yes + fi + + for lang in $ALL_LINGUAS; do + GMOFILES="$GMOFILES $lang.gmo" + POFILES="$POFILES $lang.po" + done + + + + + + + + + + + + + + + if test "x$CATOBJEXT" != "x"; then + if test "x$ALL_LINGUAS" = "x"; then + LINGUAS= + else + echo $ac_n "checking for catalogs to be installed""... $ac_c" 1>&6 +echo "configure:3949: checking for catalogs to be installed" >&5 + NEW_LINGUAS= + for lang in ${LINGUAS=$ALL_LINGUAS}; do + case "$ALL_LINGUAS" in + *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;; + esac + done + LINGUAS=$NEW_LINGUAS + echo "$ac_t""$LINGUAS" 1>&6 + fi + + if test -n "$LINGUAS"; then + for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done + fi + fi + + if test $ac_cv_header_locale_h = yes; then + INCLUDE_LOCALE_H="#include <locale.h>" + else + INCLUDE_LOCALE_H="\ +/* The system does not provide the header <locale.h>. Take care yourself. */" + fi + + + if test -f $srcdir/po2tbl.sed.in; then + if test "$CATOBJEXT" = ".cat"; then + ac_safe=`echo "linux/version.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for linux/version.h""... $ac_c" 1>&6 +echo "configure:3977: checking for linux/version.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 3982 "configure" +#include "confdefs.h" +#include <linux/version.h> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:3987: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + msgformat=linux +else + echo "$ac_t""no" 1>&6 +msgformat=xopen +fi + + + sed -e '/^#/d' $srcdir/$msgformat-msg.sed > po2msg.sed + fi + sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \ + $srcdir/po2tbl.sed.in > po2tbl.sed + fi + + if test "$PACKAGE" = "gettext"; then + GT_NO="#NO#" + GT_YES= + else + GT_NO= + GT_YES="#YES#" + fi + + + + MKINSTALLDIRS="\$(srcdir)/../../mkinstalldirs" + + + l= + + + if test -d $srcdir/po; then + test -d po || mkdir po + if test "x$srcdir" != "x."; then + if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then + posrcprefix="$srcdir/" + else + posrcprefix="../$srcdir/" + fi + else + posrcprefix="../" + fi + rm -f po/POTFILES + sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ + < $srcdir/po/POTFILES.in > po/POTFILES + fi + + +echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6 +echo "configure:4050: checking whether to enable maintainer-specific portions of Makefiles" >&5 + # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then + enableval="$enable_maintainer_mode" + USE_MAINTAINER_MODE=$enableval +else + USE_MAINTAINER_MODE=no +fi + + echo "$ac_t""$USE_MAINTAINER_MODE" 1>&6 + + +if test $USE_MAINTAINER_MODE = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi + MAINT=$MAINTAINER_MODE_TRUE + + +echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6 +echo "configure:4073: checking for Cygwin environment" >&5 +if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 4078 "configure" +#include "confdefs.h" + +int main() { + +#ifndef __CYGWIN__ +#define __CYGWIN__ __CYGWIN32__ +#endif +return __CYGWIN__; +; return 0; } +EOF +if { (eval echo configure:4089: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_cygwin=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_cygwin=no +fi +rm -f conftest* +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_cygwin" 1>&6 +CYGWIN= +test "$ac_cv_cygwin" = yes && CYGWIN=yes +echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6 +echo "configure:4106: checking for mingw32 environment" >&5 +if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 4111 "configure" +#include "confdefs.h" + +int main() { +return __MINGW32__; +; return 0; } +EOF +if { (eval echo configure:4118: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_mingw32=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_mingw32=no +fi +rm -f conftest* +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_mingw32" 1>&6 +MINGW32= +test "$ac_cv_mingw32" = yes && MINGW32=yes + + +echo $ac_n "checking for executable suffix""... $ac_c" 1>&6 +echo "configure:4137: checking for executable suffix" >&5 +if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$CYGWIN" = yes || test "$MINGW32" = yes; then + ac_cv_exeext=.exe +else + rm -f conftest* + echo 'int main () { return 0; }' > conftest.$ac_ext + ac_cv_exeext= + if { (eval echo configure:4147: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + for file in conftest.*; do + case $file in + *.c | *.o | *.obj | *.ilk | *.pdb) ;; + *) ac_cv_exeext=`echo $file | sed -e s/conftest//` ;; + esac + done + else + { echo "configure: error: installation or configuration problem: compiler cannot create executables." 1>&2; exit 1; } + fi + rm -f conftest* + test x"${ac_cv_exeext}" = x && ac_cv_exeext=no +fi +fi + +EXEEXT="" +test x"${ac_cv_exeext}" != xno && EXEEXT=${ac_cv_exeext} +echo "$ac_t""${ac_cv_exeext}" 1>&6 +ac_exeext=$EXEEXT + + +# host-specific stuff: + +HDEFINES= + +. ${srcdir}/../bfd/configure.host + + +AR=${AR-ar} + +# Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:4180: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +# 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 +# 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" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:4219: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/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 + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +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. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&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_PROGRAM}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + +# Put a plausible default for CC_FOR_BUILD in Makefile. +if test -z "$CC_FOR_BUILD"; then + if test "x$cross_compiling" = "xno"; then + CC_FOR_BUILD='$(CC)' + else + CC_FOR_BUILD=gcc + fi +fi + +# Also set EXEEXT_FOR_BUILD. +if test "x$cross_compiling" = "xno"; then + EXEEXT_FOR_BUILD='$(EXEEXT)' +else + echo $ac_n "checking for build system executable suffix""... $ac_c" 1>&6 +echo "configure:4286: checking for build system executable suffix" >&5 +if eval "test \"`echo '$''{'bfd_cv_build_exeext'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > ac_c_test.c << 'EOF' +int main() { +/* Nothing needed here */ +} +EOF + ${CC_FOR_BUILD} -o ac_c_test am_c_test.c 1>&5 2>&5 + bfd_cv_build_exeext=`echo ac_c_test.* | grep -v ac_c_test.c | sed -e s/ac_c_test//` + rm -f ac_c_test* + test x"${bfd_cv_build_exeext}" = x && bfd_cv_build_exeext=no +fi + +echo "$ac_t""$bfd_cv_build_exeext" 1>&6 + EXEEXT_FOR_BUILD="" + test x"${bfd_cv_build_exeext}" != xno && EXEEXT_FOR_BUILD=${bfd_cv_build_exeext} +fi + + +for ac_hdr in string.h strings.h stdlib.h unistd.h fcntl.h sys/file.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:4311: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 4316 "configure" +#include "confdefs.h" +#include <$ac_hdr> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:4321: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6 +echo "configure:4348: checking for sys/wait.h that is POSIX.1 compatible" >&5 +if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 4353 "configure" +#include "confdefs.h" +#include <sys/types.h> +#include <sys/wait.h> +#ifndef WEXITSTATUS +#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +#endif +#ifndef WIFEXITED +#define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif +int main() { +int s; +wait (&s); +s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; +; return 0; } +EOF +if { (eval echo configure:4369: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_header_sys_wait_h=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_sys_wait_h=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_header_sys_wait_h" 1>&6 +if test $ac_cv_header_sys_wait_h = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_SYS_WAIT_H 1 +EOF + +fi + +# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6 +echo "configure:4392: checking for working alloca.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 4397 "configure" +#include "confdefs.h" +#include <alloca.h> +int main() { +char *p = alloca(2 * sizeof(int)); +; return 0; } +EOF +if { (eval echo configure:4404: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ac_cv_header_alloca_h=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_alloca_h=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_header_alloca_h" 1>&6 +if test $ac_cv_header_alloca_h = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_ALLOCA_H 1 +EOF + +fi + +echo $ac_n "checking for alloca""... $ac_c" 1>&6 +echo "configure:4425: checking for alloca" >&5 +if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 4430 "configure" +#include "confdefs.h" + +#ifdef __GNUC__ +# define alloca __builtin_alloca +#else +# ifdef _MSC_VER +# include <malloc.h> +# define alloca _alloca +# else +# if HAVE_ALLOCA_H +# include <alloca.h> +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +char *alloca (); +# endif +# endif +# endif +# endif +#endif + +int main() { +char *p = (char *) alloca(1); +; return 0; } +EOF +if { (eval echo configure:4458: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ac_cv_func_alloca_works=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_func_alloca_works=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_func_alloca_works" 1>&6 +if test $ac_cv_func_alloca_works = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_ALLOCA 1 +EOF + +fi + +if test $ac_cv_func_alloca_works = no; then + # The SVR3 libPW and SVR4 libucb both contain incompatible functions + # that cause trouble. Some versions do not even contain alloca or + # contain a buggy version. If you still want to use their alloca, + # use ar to extract alloca.o from them instead of compiling alloca.c. + ALLOCA=alloca.${ac_objext} + cat >> confdefs.h <<\EOF +#define C_ALLOCA 1 +EOF + + +echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 +echo "configure:4490: checking whether alloca needs Cray hooks" >&5 +if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 4495 "configure" +#include "confdefs.h" +#if defined(CRAY) && ! defined(CRAY2) +webecray +#else +wenotbecray +#endif + +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "webecray" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_os_cray=yes +else + rm -rf conftest* + ac_cv_os_cray=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_os_cray" 1>&6 +if test $ac_cv_os_cray = yes; then +for ac_func in _getb67 GETB67 getb67; do + echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:4520: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 4525 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:4548: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<EOF +#define CRAY_STACKSEG_END $ac_func +EOF + + break +else + echo "$ac_t""no" 1>&6 +fi + +done +fi + +echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 +echo "configure:4575: checking stack direction for C alloca" >&5 +if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_c_stack_direction=0 +else + cat > conftest.$ac_ext <<EOF +#line 4583 "configure" +#include "confdefs.h" +find_stack_direction () +{ + static char *addr = 0; + auto char dummy; + if (addr == 0) + { + addr = &dummy; + return find_stack_direction (); + } + else + return (&dummy > addr) ? 1 : -1; +} +main () +{ + exit (find_stack_direction() < 0); +} +EOF +if { (eval echo configure:4602: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_c_stack_direction=1 +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_c_stack_direction=-1 +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$ac_cv_c_stack_direction" 1>&6 +cat >> confdefs.h <<EOF +#define STACK_DIRECTION $ac_cv_c_stack_direction +EOF + +fi + +for ac_func in sbrk utimes +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:4626: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 4631 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:4654: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + + +echo $ac_n "checking for time_t in time.h""... $ac_c" 1>&6 +echo "configure:4680: checking for time_t in time.h" >&5 +if eval "test \"`echo '$''{'bu_cv_decl_time_t_time_h'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 4685 "configure" +#include "confdefs.h" +#include <time.h> +int main() { +time_t i; +; return 0; } +EOF +if { (eval echo configure:4692: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + bu_cv_decl_time_t_time_h=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + bu_cv_decl_time_t_time_h=no +fi +rm -f conftest* +fi + +echo "$ac_t""$bu_cv_decl_time_t_time_h" 1>&6 +if test $bu_cv_decl_time_t_time_h = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_TIME_T_IN_TIME_H 1 +EOF + +fi + +echo $ac_n "checking for time_t in sys/types.h""... $ac_c" 1>&6 +echo "configure:4713: checking for time_t in sys/types.h" >&5 +if eval "test \"`echo '$''{'bu_cv_decl_time_t_types_h'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 4718 "configure" +#include "confdefs.h" +#include <sys/types.h> +int main() { +time_t i; +; return 0; } +EOF +if { (eval echo configure:4725: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + bu_cv_decl_time_t_types_h=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + bu_cv_decl_time_t_types_h=no +fi +rm -f conftest* +fi + +echo "$ac_t""$bu_cv_decl_time_t_types_h" 1>&6 +if test $bu_cv_decl_time_t_types_h = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_TIME_T_IN_TYPES_H 1 +EOF + +fi + +# Under Next 3.2 <utime.h> apparently does not define struct utimbuf +# by default. +echo $ac_n "checking for utime.h""... $ac_c" 1>&6 +echo "configure:4748: checking for utime.h" >&5 +if eval "test \"`echo '$''{'bu_cv_header_utime_h'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 4753 "configure" +#include "confdefs.h" +#include <sys/types.h> +#ifdef HAVE_TIME_H +#include <time.h> +#endif +#include <utime.h> +int main() { +struct utimbuf s; +; return 0; } +EOF +if { (eval echo configure:4764: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + bu_cv_header_utime_h=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + bu_cv_header_utime_h=no +fi +rm -f conftest* +fi + +echo "$ac_t""$bu_cv_header_utime_h" 1>&6 +if test $bu_cv_header_utime_h = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_GOOD_UTIME_H 1 +EOF + +fi + +echo $ac_n "checking whether fprintf must be declared""... $ac_c" 1>&6 +echo "configure:4785: checking whether fprintf must be declared" >&5 +if eval "test \"`echo '$''{'bfd_cv_decl_needed_fprintf'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 4790 "configure" +#include "confdefs.h" + +#include <stdio.h> +#ifdef HAVE_STRING_H +#include <string.h> +#else +#ifdef HAVE_STRINGS_H +#include <strings.h> +#endif +#endif +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +int main() { +char *(*pfn) = (char *(*)) fprintf +; return 0; } +EOF +if { (eval echo configure:4811: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + bfd_cv_decl_needed_fprintf=no +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + bfd_cv_decl_needed_fprintf=yes +fi +rm -f conftest* +fi + +echo "$ac_t""$bfd_cv_decl_needed_fprintf" 1>&6 +if test $bfd_cv_decl_needed_fprintf = yes; then + cat >> confdefs.h <<\EOF +#define NEED_DECLARATION_FPRINTF 1 +EOF + +fi + +echo $ac_n "checking whether strstr must be declared""... $ac_c" 1>&6 +echo "configure:4832: checking whether strstr must be declared" >&5 +if eval "test \"`echo '$''{'bfd_cv_decl_needed_strstr'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 4837 "configure" +#include "confdefs.h" + +#include <stdio.h> +#ifdef HAVE_STRING_H +#include <string.h> +#else +#ifdef HAVE_STRINGS_H +#include <strings.h> +#endif +#endif +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +int main() { +char *(*pfn) = (char *(*)) strstr +; return 0; } +EOF +if { (eval echo configure:4858: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + bfd_cv_decl_needed_strstr=no +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + bfd_cv_decl_needed_strstr=yes +fi +rm -f conftest* +fi + +echo "$ac_t""$bfd_cv_decl_needed_strstr" 1>&6 +if test $bfd_cv_decl_needed_strstr = yes; then + cat >> confdefs.h <<\EOF +#define NEED_DECLARATION_STRSTR 1 +EOF + +fi + +echo $ac_n "checking whether sbrk must be declared""... $ac_c" 1>&6 +echo "configure:4879: checking whether sbrk must be declared" >&5 +if eval "test \"`echo '$''{'bfd_cv_decl_needed_sbrk'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 4884 "configure" +#include "confdefs.h" + +#include <stdio.h> +#ifdef HAVE_STRING_H +#include <string.h> +#else +#ifdef HAVE_STRINGS_H +#include <strings.h> +#endif +#endif +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +int main() { +char *(*pfn) = (char *(*)) sbrk +; return 0; } +EOF +if { (eval echo configure:4905: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + bfd_cv_decl_needed_sbrk=no +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + bfd_cv_decl_needed_sbrk=yes +fi +rm -f conftest* +fi + +echo "$ac_t""$bfd_cv_decl_needed_sbrk" 1>&6 +if test $bfd_cv_decl_needed_sbrk = yes; then + cat >> confdefs.h <<\EOF +#define NEED_DECLARATION_SBRK 1 +EOF + +fi + +echo $ac_n "checking whether getenv must be declared""... $ac_c" 1>&6 +echo "configure:4926: checking whether getenv must be declared" >&5 +if eval "test \"`echo '$''{'bfd_cv_decl_needed_getenv'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 4931 "configure" +#include "confdefs.h" + +#include <stdio.h> +#ifdef HAVE_STRING_H +#include <string.h> +#else +#ifdef HAVE_STRINGS_H +#include <strings.h> +#endif +#endif +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +int main() { +char *(*pfn) = (char *(*)) getenv +; return 0; } +EOF +if { (eval echo configure:4952: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + bfd_cv_decl_needed_getenv=no +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + bfd_cv_decl_needed_getenv=yes +fi +rm -f conftest* +fi + +echo "$ac_t""$bfd_cv_decl_needed_getenv" 1>&6 +if test $bfd_cv_decl_needed_getenv = yes; then + cat >> confdefs.h <<\EOF +#define NEED_DECLARATION_GETENV 1 +EOF + +fi + +echo $ac_n "checking whether environ must be declared""... $ac_c" 1>&6 +echo "configure:4973: checking whether environ must be declared" >&5 +if eval "test \"`echo '$''{'bfd_cv_decl_needed_environ'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 4978 "configure" +#include "confdefs.h" + +#include <stdio.h> +#ifdef HAVE_STRING_H +#include <string.h> +#else +#ifdef HAVE_STRINGS_H +#include <strings.h> +#endif +#endif +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +int main() { +char *(*pfn) = (char *(*)) environ +; return 0; } +EOF +if { (eval echo configure:4999: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + bfd_cv_decl_needed_environ=no +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + bfd_cv_decl_needed_environ=yes +fi +rm -f conftest* +fi + +echo "$ac_t""$bfd_cv_decl_needed_environ" 1>&6 +if test $bfd_cv_decl_needed_environ = yes; then + cat >> confdefs.h <<\EOF +#define NEED_DECLARATION_ENVIRON 1 +EOF + +fi + + + +case "${host}" in +*-*-msdos* | *-*-go32* | *-*-mingw32* | *-*-cygwin* | *-*-windows) + cat >> confdefs.h <<\EOF +#define USE_BINARY_FOPEN 1 +EOF + ;; +esac + +# target-specific stuff: + +# Canonicalize the secondary target names. +if test -n "$enable_targets"; then + for targ in `echo $enable_targets | sed 's/,/ /g'` + do + result=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $targ 2>/dev/null` + if test -n "$result"; then + canon_targets="$canon_targets $result" + else + # Allow targets that config.sub doesn't recognize, like "all". + canon_targets="$canon_targets $targ" + fi + done +fi + +all_targets=false +BUILD_NLMCONV= +NLMCONV_DEFS= +BUILD_SRCONV= +BUILD_DLLTOOL= +DLLTOOL_DEFS= +BUILD_WINDRES= +BUILD_DLLWRAP= +BUILD_MISC= + +for targ in $target $canon_targets +do + if test "x$targ" = "xall"; then + all_targets=true + BUILD_NLMCONV='$(NLMCONV_PROG)$(EXEEXT)' + BUILD_SRCONV='$(SRCONV_PROG)' + NLMCONV_DEFS="-DNLMCONV_I386 -DNLMCONV_ALPHA -DNLMCONV_POWERPC -DNLMCONV_SPARC" + else + case $targ in + i[3456]86*-*-netware*) + BUILD_NLMCONV='$(NLMCONV_PROG)$(EXEEXT)' + NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_I386" + ;; + alpha*-*-netware*) + BUILD_NLMCONV='$(NLMCONV_PROG)$(EXEEXT)' + NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_ALPHA" + ;; + powerpc*-*-netware*) + BUILD_NLMCONV='$(NLMCONV_PROG)$(EXEEXT)' + NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_POWERPC" + ;; + sparc*-*-netware*) + BUILD_NLMCONV='$(NLMCONV_PROG)$(EXEEXT)' + NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_SPARC" + ;; + esac + case $targ in + *-*-hms*) BUILD_SRCONV='$(SRCONV_PROG)' ;; + esac + case $targ in + arm-*pe*) + BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)' + DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_ARM" + BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + ;; + thumb-*pe*) + BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)' + DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_ARM" + BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + ;; + i[3-6]86-*pe* | i[3-6]86-*-cygwin* | i[3-6]86-*-mingw32*) + BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)' + DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_I386" + BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)' + ;; + powerpc*-*-*pe* | powerpc*-*-cygwin*) + BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)' + DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_PPC" + BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + ;; + esac + fi +done + + + + + + + + + + +cat >> confdefs.h <<EOF +#define TARGET "${target}" +EOF + + +targ=$target +. $srcdir/../bfd/config.bfd +if test "x$targ_underscore" = "xyes"; then + UNDERSCORE=1 +else + UNDERSCORE=0 +fi + + +trap '' 1 2 15 +cat > confcache <<\EOF +# 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. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# 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. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS <<EOF +#! /bin/sh +# Generated automatically by configure. +# Run this file to recreate the current configuration. +# This directory was configured as follows, +# on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile po/Makefile.in:po/Make-in config.h:config.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS <<EOF + +# Protect against being on the right side of a sed subst in config.status. +sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g; + s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@FFLAGS@%$FFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@host@%$host%g +s%@host_alias@%$host_alias%g +s%@host_cpu@%$host_cpu%g +s%@host_vendor@%$host_vendor%g +s%@host_os@%$host_os%g +s%@target@%$target%g +s%@target_alias@%$target_alias%g +s%@target_cpu@%$target_cpu%g +s%@target_vendor@%$target_vendor%g +s%@target_os@%$target_os%g +s%@build@%$build%g +s%@build_alias@%$build_alias%g +s%@build_cpu@%$build_cpu%g +s%@build_vendor@%$build_vendor%g +s%@build_os@%$build_os%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@PACKAGE@%$PACKAGE%g +s%@VERSION@%$VERSION%g +s%@ACLOCAL@%$ACLOCAL%g +s%@AUTOCONF@%$AUTOCONF%g +s%@AUTOMAKE@%$AUTOMAKE%g +s%@AUTOHEADER@%$AUTOHEADER%g +s%@MAKEINFO@%$MAKEINFO%g +s%@SET_MAKE@%$SET_MAKE%g +s%@RANLIB@%$RANLIB%g +s%@CC@%$CC%g +s%@LD@%$LD%g +s%@NM@%$NM%g +s%@USE_SYMBOL_UNDERSCORE@%$USE_SYMBOL_UNDERSCORE%g +s%@LN_S@%$LN_S%g +s%@DLLTOOL@%$DLLTOOL%g +s%@AS@%$AS%g +s%@LIBTOOL@%$LIBTOOL%g +s%@YACC@%$YACC%g +s%@LEX@%$LEX%g +s%@LEXLIB@%$LEXLIB%g +s%@CPP@%$CPP%g +s%@LEX_OUTPUT_ROOT@%$LEX_OUTPUT_ROOT%g +s%@ALLOCA@%$ALLOCA%g +s%@USE_NLS@%$USE_NLS%g +s%@MSGFMT@%$MSGFMT%g +s%@GMSGFMT@%$GMSGFMT%g +s%@XGETTEXT@%$XGETTEXT%g +s%@USE_INCLUDED_LIBINTL@%$USE_INCLUDED_LIBINTL%g +s%@CATALOGS@%$CATALOGS%g +s%@CATOBJEXT@%$CATOBJEXT%g +s%@DATADIRNAME@%$DATADIRNAME%g +s%@GMOFILES@%$GMOFILES%g +s%@INSTOBJEXT@%$INSTOBJEXT%g +s%@INTLDEPS@%$INTLDEPS%g +s%@INTLLIBS@%$INTLLIBS%g +s%@INTLOBJS@%$INTLOBJS%g +s%@POFILES@%$POFILES%g +s%@POSUB@%$POSUB%g +s%@INCLUDE_LOCALE_H@%$INCLUDE_LOCALE_H%g +s%@GT_NO@%$GT_NO%g +s%@GT_YES@%$GT_YES%g +s%@MKINSTALLDIRS@%$MKINSTALLDIRS%g +s%@l@%$l%g +s%@MAINTAINER_MODE_TRUE@%$MAINTAINER_MODE_TRUE%g +s%@MAINTAINER_MODE_FALSE@%$MAINTAINER_MODE_FALSE%g +s%@MAINT@%$MAINT%g +s%@EXEEXT@%$EXEEXT%g +s%@HDEFINES@%$HDEFINES%g +s%@AR@%$AR%g +s%@CC_FOR_BUILD@%$CC_FOR_BUILD%g +s%@EXEEXT_FOR_BUILD@%$EXEEXT_FOR_BUILD%g +s%@NLMCONV_DEFS@%$NLMCONV_DEFS%g +s%@BUILD_NLMCONV@%$BUILD_NLMCONV%g +s%@BUILD_SRCONV@%$BUILD_SRCONV%g +s%@BUILD_DLLTOOL@%$BUILD_DLLTOOL%g +s%@DLLTOOL_DEFS@%$DLLTOOL_DEFS%g +s%@BUILD_WINDRES@%$BUILD_WINDRES%g +s%@BUILD_DLLWRAP@%$BUILD_DLLWRAP%g +s%@BUILD_MISC@%$BUILD_MISC%g +s%@UNDERSCORE@%$UNDERSCORE%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <<EOF + +CONFIG_FILES=\${CONFIG_FILES-"Makefile po/Makefile.in:po/Make-in"} +EOF +cat >> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <<EOF + CONFIG_HEADERS="config.h:config.in" +EOF +cat >> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #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. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF +cat >> $CONFIG_STATUS <<EOF + + +EOF +cat >> $CONFIG_STATUS <<\EOF +test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h + +case "x$CONFIG_FILES" in +*) sed -e '/POTFILES =/r po/POTFILES' po/Makefile.in > po/Makefile ;; +esac + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + diff --git a/binutils/configure.bat b/binutils/configure.bat new file mode 100755 index 0000000..f7d70f1 --- /dev/null +++ b/binutils/configure.bat @@ -0,0 +1,63 @@ +@echo off
+if "%1" == "h8/300" goto h8300
+
+echo Configuring binutils for go32
+update ../bfd/hosts/go32.h sysdep.h
+goto common
+
+:h8300
+echo Configuring binutils for H8/300
+update ..\bfd\hosts\h-go32.h sysdep.h
+
+:common
+
+echo # Makefile generated by "configure.bat"> Makefile
+
+if exist config.sed del config.sed
+
+sed -n "/^VERSION=/ p" Makefile.in | sed -e "s/^/s^/" -e "s/=/^\"/" -e "s/$/\"^/" > config.sed
+sed -f config.sed version.c > version2.c
+
+if exist config.sed del config.sed
+
+echo "s/version\./version2\./g ">> config.sed
+echo "s/-DVERSION=[^ ]* // ">> config.sed
+
+echo "s/^ \$(srcdir)\/move-if-change/ update/ ">> config.sed
+echo "/^###$/ i\ ">> config.sed
+echo "CC = gcc ">> config.sed
+echo "s/:\([^ ]\)/: \1/g ">> config.sed
+echo "s/^ \ *\.\// go32 / ">> config.sed
+echo "s/`echo \$(srcdir)\///g ">> config.sed
+echo "s/ | sed 's,\^\\\.\/,,'`//g ">> config.sed
+echo "s/^ cd \$(srcdir)[ ]*;// ">> config.sed
+
+echo "/^arparse\.c/ i\ ">> config.sed
+echo "arparse.o: arparse.c\ ">> config.sed
+echo " $(CC) -c $(CFLAGS) $(INCLUDES) $(HDEFINES) $(TDEFINES) arparse.c ">> config.sed
+echo "/\$(BISON)/ c\ ">> config.sed
+echo " bison $(BISONFLAGS) -o $@ arparse.y ">> config.sed
+echo "/y\.tab\./ d ">> config.sed
+
+echo "/^arlex.c/ { ">> config.sed
+echo " i\ ">> config.sed
+echo "arlex.o: arlex.c ">> config.sed
+echo " i\ ">> config.sed
+echo " $(CC) -c $(CFLAGS) $(INCLUDES) $(HDEFINES) $(TDEFINES) arlex.c ">> config.sed
+echo "} ">> config.sed
+echo "/\$(LEX)/ c\ ">> config.sed
+echo " flex $(LEX_OPTIONS) arlex.l ">> config.sed
+echo "s/lex\.yy\./lexyy./g ">> config.sed
+
+echo "s/'"/\\"/g ">> config.sed
+echo "s/"'/\\"/g ">> config.sed
+
+echo "s/c++filt/cxxfilt/g ">> config.sed
+
+sed -e "s/^\"//" -e "s/\"$//" -e "s/[ ]*$//" config.sed > config2.sed
+sed -f config2.sed Makefile.in >> Makefile
+del config.sed
+del config2.sed
+
+echo int prepends_underscore = 1; > underscore.c
+
diff --git a/binutils/configure.com b/binutils/configure.com new file mode 100644 index 0000000..99463d5 --- /dev/null +++ b/binutils/configure.com @@ -0,0 +1,76 @@ +$! +$! This file configures binutils for use with openVMS/Alpha +$! We do not use the configure script, since we do not have /bin/sh +$! to execute it. +$! +$! Written by Klaus K"ampf (kkaempf@rmi.de) +$! +$arch_indx = 1 + ((f$getsyi("CPU").ge.128).and.1) ! vax==1, alpha==2 +$arch = f$element(arch_indx,"|","|VAX|Alpha|") +$! +$! +$! Generate config.h +$! +$ create []config.h +/* config.h. Generated automatically by configure. */ +/* config.in. Generated automatically from configure.in by autoheader. */ +/* Is the type time_t defined in <time.h>? */ +#define HAVE_TIME_T_IN_TIME_H 1 +/* Is the type time_t defined in <sys/types.h>? */ +#define HAVE_TIME_T_IN_TYPES_H 1 +/* Does <utime.h> define struct utimbuf? */ +#define HAVE_GOOD_UTIME_H 1 +/* Whether fprintf must be declared even if <stdio.h> is included. */ +#define NEED_DECLARATION_FPRINTF 1 +/* Whether sbrk must be declared even if <unistd.h> is included. */ +#undef NEED_DECLARATION_SBRK +/* Do we need to use the b modifier when opening binary files? */ +/* #undef USE_BINARY_FOPEN */ +/* Define if you have the sbrk function. */ +/* #undef HAVE_SBRK 1 */ +/* Define if you have the utimes function. */ +#define HAVE_UTIMES 1 +/* Define if you have the <fcntl.h> header file. */ +#define HAVE_FCNTL_H 1 +/* Define if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 +/* Define if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 +/* Define if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 +/* Define if you have the <sys/file.h> header file. */ +#define HAVE_SYS_FILE_H 1 +/* Define if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 +$ write sys$output "Generated `config.h'" +$! +$! +$! Edit VERSION in makefile.vms-in +$! +$ edit/tpu/nojournal/nosection/nodisplay/command=sys$input - + []makefile.vms-in /output=[]makefile.vms +$DECK +! +! Get VERSION from configure.in +! + mfile := CREATE_BUFFER("mfile", "CONFIGURE.IN"); + rang := CREATE_RANGE(BEGINNING_OF(mfile), END_OF(mfile)); + match_pos := SEARCH_QUIETLY('AM_INIT_AUTOMAKE(binutils, ', FORWARD, EXACT, rang); + IF match_pos <> 0 THEN; + POSITION(BEGINNING_OF(match_pos)); + ERASE(match_pos); + vers := CURRENT_LINE-")"; + ELSE; + vers := "unknown"; + ENDIF; + + file := CREATE_BUFFER("file", GET_INFO(COMMAND_LINE, "file_name")); + rang := CREATE_RANGE(BEGINNING_OF(file), END_OF(file)); + match_pos := SEARCH_QUIETLY('@VERSION@', FORWARD, EXACT, rang); + POSITION(BEGINNING_OF(match_pos)); + ERASE(match_pos); + COPY_TEXT(vers); + WRITE_FILE(file, GET_INFO(COMMAND_LINE, "output_file")); + QUIT +$ EOD +$ write sys$output "Created `makefile.vms'" diff --git a/binutils/configure.in b/binutils/configure.in new file mode 100644 index 0000000..298dcd8 --- /dev/null +++ b/binutils/configure.in @@ -0,0 +1,221 @@ +dnl Process this file with autoconf to produce a configure script. +dnl +AC_PREREQ(2.13) +AC_INIT(ar.c) + +AC_CANONICAL_SYSTEM + +AM_INIT_AUTOMAKE(binutils, 2.9.4) + +AM_PROG_LIBTOOL + +AC_ARG_ENABLE(targets, +[ --enable-targets alternative target configurations], +[case "${enableval}" in + yes | "") AC_ERROR(enable-targets option must specify target names or 'all') + ;; + no) enable_targets= ;; + *) enable_targets=$enableval ;; +esac])dnl +AC_ARG_ENABLE(commonbfdlib, +[ --enable-commonbfdlib build shared BFD/opcodes/libiberty library], +[case "${enableval}" in + yes) commonbfdlib=true ;; + no) commonbfdlib=false ;; + *) AC_MSG_ERROR([bad value ${enableval} for BFD commonbfdlib option]) ;; +esac])dnl + +AM_CONFIG_HEADER(config.h:config.in) + +if test -z "$target" ; then + AC_MSG_ERROR(Unrecognized target system type; please check config.sub.) +fi +if test -z "$host" ; then + AC_MSG_ERROR(Unrecognized host system type; please check config.sub.) +fi + +AC_PROG_CC + +AC_PROG_YACC +AM_PROG_LEX + +ALL_LINGUAS= +CY_GNU_GETTEXT + +AM_MAINTAINER_MODE +AC_EXEEXT + +# host-specific stuff: + +HDEFINES= + +. ${srcdir}/../bfd/configure.host + +AC_SUBST(HDEFINES) +AR=${AR-ar} +AC_SUBST(AR) +AC_PROG_RANLIB +AC_PROG_INSTALL + +BFD_CC_FOR_BUILD + +AC_CHECK_HEADERS(string.h strings.h stdlib.h unistd.h fcntl.h sys/file.h) +AC_HEADER_SYS_WAIT +AC_FUNC_ALLOCA +AC_CHECK_FUNCS(sbrk utimes) + +AC_MSG_CHECKING(for time_t in time.h) +AC_CACHE_VAL(bu_cv_decl_time_t_time_h, +[AC_TRY_COMPILE([#include <time.h>], [time_t i;], +bu_cv_decl_time_t_time_h=yes, bu_cv_decl_time_t_time_h=no)]) +AC_MSG_RESULT($bu_cv_decl_time_t_time_h) +if test $bu_cv_decl_time_t_time_h = yes; then + AC_DEFINE([HAVE_TIME_T_IN_TIME_H], 1, + [Is the type time_t defined in <time.h>?]) +fi + +AC_MSG_CHECKING(for time_t in sys/types.h) +AC_CACHE_VAL(bu_cv_decl_time_t_types_h, +[AC_TRY_COMPILE([#include <sys/types.h>], [time_t i;], +bu_cv_decl_time_t_types_h=yes, bu_cv_decl_time_t_types_h=no)]) +AC_MSG_RESULT($bu_cv_decl_time_t_types_h) +if test $bu_cv_decl_time_t_types_h = yes; then + AC_DEFINE([HAVE_TIME_T_IN_TYPES_H], 1, + [Is the type time_t defined in <sys/types.h>?]) +fi + +# Under Next 3.2 <utime.h> apparently does not define struct utimbuf +# by default. +AC_MSG_CHECKING([for utime.h]) +AC_CACHE_VAL(bu_cv_header_utime_h, +[AC_TRY_COMPILE([#include <sys/types.h> +#ifdef HAVE_TIME_H +#include <time.h> +#endif +#include <utime.h>], +[struct utimbuf s;], +bu_cv_header_utime_h=yes, bu_cv_header_utime_h=no)]) +AC_MSG_RESULT($bu_cv_header_utime_h) +if test $bu_cv_header_utime_h = yes; then + AC_DEFINE(HAVE_GOOD_UTIME_H, 1, [Does <utime.h> define struct utimbuf?]) +fi + +BFD_NEED_DECLARATION(fprintf) +BFD_NEED_DECLARATION(strstr) +BFD_NEED_DECLARATION(sbrk) +BFD_NEED_DECLARATION(getenv) +BFD_NEED_DECLARATION(environ) + +BFD_BINARY_FOPEN + +# target-specific stuff: + +# Canonicalize the secondary target names. +if test -n "$enable_targets"; then + for targ in `echo $enable_targets | sed 's/,/ /g'` + do + result=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $targ 2>/dev/null` + if test -n "$result"; then + canon_targets="$canon_targets $result" + else + # Allow targets that config.sub doesn't recognize, like "all". + canon_targets="$canon_targets $targ" + fi + done +fi + +all_targets=false +BUILD_NLMCONV= +NLMCONV_DEFS= +BUILD_SRCONV= +BUILD_DLLTOOL= +DLLTOOL_DEFS= +BUILD_WINDRES= +BUILD_DLLWRAP= +BUILD_MISC= + +for targ in $target $canon_targets +do + if test "x$targ" = "xall"; then + all_targets=true + BUILD_NLMCONV='$(NLMCONV_PROG)$(EXEEXT)' + BUILD_SRCONV='$(SRCONV_PROG)' + NLMCONV_DEFS="-DNLMCONV_I386 -DNLMCONV_ALPHA -DNLMCONV_POWERPC -DNLMCONV_SPARC" + else + case $targ in +changequote(,)dnl + i[3456]86*-*-netware*) +changequote([,])dnl + BUILD_NLMCONV='$(NLMCONV_PROG)$(EXEEXT)' + NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_I386" + ;; + alpha*-*-netware*) + BUILD_NLMCONV='$(NLMCONV_PROG)$(EXEEXT)' + NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_ALPHA" + ;; + powerpc*-*-netware*) + BUILD_NLMCONV='$(NLMCONV_PROG)$(EXEEXT)' + NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_POWERPC" + ;; + sparc*-*-netware*) + BUILD_NLMCONV='$(NLMCONV_PROG)$(EXEEXT)' + NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_SPARC" + ;; + esac + case $targ in + *-*-hms*) BUILD_SRCONV='$(SRCONV_PROG)' ;; + esac + case $targ in + arm-*pe*) + BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)' + DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_ARM" + BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + ;; + thumb-*pe*) + BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)' + DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_ARM" + BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + ;; +changequote(,)dnl + i[3-6]86-*pe* | i[3-6]86-*-cygwin* | i[3-6]86-*-mingw32*) +changequote([,])dnl + BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)' + DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_I386" + BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)' + ;; + powerpc*-*-*pe* | powerpc*-*-cygwin*) + BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)' + DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_PPC" + BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)' + ;; + esac + fi +done + +AC_SUBST(NLMCONV_DEFS) +AC_SUBST(BUILD_NLMCONV) +AC_SUBST(BUILD_SRCONV) +AC_SUBST(BUILD_DLLTOOL) +AC_SUBST(DLLTOOL_DEFS) +AC_SUBST(BUILD_WINDRES) +AC_SUBST(BUILD_DLLWRAP) +AC_SUBST(BUILD_MISC) + +AC_DEFINE_UNQUOTED(TARGET, "${target}", [Configured target name.]) + +targ=$target +. $srcdir/../bfd/config.bfd +if test "x$targ_underscore" = "xyes"; then + UNDERSCORE=1 +else + UNDERSCORE=0 +fi +AC_SUBST(UNDERSCORE) + +AC_OUTPUT(Makefile po/Makefile.in:po/Make-in, +[ +case "x$CONFIG_FILES" in +*) sed -e '/POTFILES =/r po/POTFILES' po/Makefile.in > po/Makefile ;; +esac +]) diff --git a/binutils/cxxfilt.man b/binutils/cxxfilt.man new file mode 100644 index 0000000..a4d5d45 --- /dev/null +++ b/binutils/cxxfilt.man @@ -0,0 +1,114 @@ +.\" Copyright (c) 1991 Free Software Foundation +.\" See section COPYING for conditions for redistribution +.TH @PROGRAM@ 1 "June 1993" "cygnus support" "GNU Development Tools" +.de BP +.sp +.ti \-.2i +\(** +.. + +.SH NAME +@PROGRAM@ \- demangle C++ symbols + +.SH SYNOPSIS +.hy 0 +.na +.TP +.B @PROGRAM@ +.RB "[\|" \-_ | \-\-strip-underscores "\|]" +.RB "[\|" "\-s {gnu,lucid,arm} " | " \-\-format={gnu,lucid,arm}" "\|]" +.RB "[\|" \-\-help "\|]" +.RB "[\|" \-\-version "\|]" +.RB "[\|" symbol "...\|]" +.SH DESCRIPTION +The C++ language provides function overloading, which means that you can +write many functions with the same name (providing each takes parameters +of different types). All C++ function names are encoded into a +low-level assembly label (this process is known as +.I mangling\c +). The +.B @PROGRAM@ +program does the inverse mapping: it decodes (\fIdemangles\fR) +low-level names into user-level names so that the linker can keep +these overloaded functions from clashing. +.PP +Every alphanumeric word (consisting of letters, digits, underscores, +dollars, or periods) seen in the input is a potential label. If the +label decodes into a C++ name, the C++ name replaces the low-level +name in the output. +.PP +You can use +.B @PROGRAM@ +to decipher individual symbols by specifying these symbols on the +command line. +.PP +If no +.B symbol +arguments are given, +.B @PROGRAM@ +reads symbol names from the standard input and writes the demangled +names to the standard output. All results are printed on the standard +output. +.SH OPTIONS +.TP +.B \-_ +.TP +.B \-\-strip\-underscores +On some systems, both the C and C++ compilers put an +underscore in front of every name. For example, the C name +.B foo +gets the low-level name +.BR _foo . +This option removes the leading underscore. + +.TP +.B "\-s {gnu,lucid,arm}" +.TP +.B \-\-format={gnu,lucid,arm} +GNU +.B nm +can decode three different methods of mangling, used by different C++ +compilers. This option selects which method it uses: the one used by +the GNU compiler, the one used by the Lucid compiler, or the one +specified by the C++ Annotated Reference Manual. The default is the +GNU style. + +.TP +.B \-\-help +Print a summary of the options to +.B @PROGRAM@ +and exit. + +.TP +.B \-\-version +Print the version number of +.B @PROGRAM@ +and exit. + +.SH "SEE ALSO" +.RB "`\|" binutils "\|'" +entry in +.B +info\c +\&; +.I +The GNU Binary Utilities\c +\&, Roland H. Pesch (June 1993). + +.SH COPYING +Copyright (c) 1993 Free Software Foundation, Inc. +.PP +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. +.PP +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the +entire resulting derived work is distributed under the terms of a +permission notice identical to this one. +.PP +Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be included in +translations approved by the Free Software Foundation instead of in +the original English. diff --git a/binutils/debug.c b/binutils/debug.c new file mode 100644 index 0000000..173d627 --- /dev/null +++ b/binutils/debug.c @@ -0,0 +1,3568 @@ +/* debug.c -- Handle generic debugging information. + Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc. + Written by Ian Lance Taylor <ian@cygnus.com>. + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* This file implements a generic debugging format. We may eventually + have readers which convert different formats into this generic + format, and writers which write it out. The initial impetus for + this was writing a convertor from stabs to HP IEEE-695 debugging + format. */ + +#include <stdio.h> +#include <assert.h> + +#include "bfd.h" +#include "bucomm.h" +#include "libiberty.h" +#include "debug.h" + +/* Global information we keep for debugging. A pointer to this + structure is the debugging handle passed to all the routines. */ + +struct debug_handle +{ + /* A linked list of compilation units. */ + struct debug_unit *units; + /* The current compilation unit. */ + struct debug_unit *current_unit; + /* The current source file. */ + struct debug_file *current_file; + /* The current function. */ + struct debug_function *current_function; + /* The current block. */ + struct debug_block *current_block; + /* The current line number information for the current unit. */ + struct debug_lineno *current_lineno; + /* Mark. This is used by debug_write. */ + unsigned int mark; + /* A struct/class ID used by debug_write. */ + unsigned int class_id; + /* The base for class_id for this call to debug_write. */ + unsigned int base_id; + /* The current line number in debug_write. */ + struct debug_lineno *current_write_lineno; + unsigned int current_write_lineno_index; + /* A list of classes which have assigned ID's during debug_write. + This is linked through the next_id field of debug_class_type. */ + struct debug_class_id *id_list; + /* A list used to avoid recursion during debug_type_samep. */ + struct debug_type_compare_list *compare_list; +}; + +/* Information we keep for a single compilation unit. */ + +struct debug_unit +{ + /* The next compilation unit. */ + struct debug_unit *next; + /* A list of files included in this compilation unit. The first + file is always the main one, and that is where the main file name + is stored. */ + struct debug_file *files; + /* Line number information for this compilation unit. This is not + stored by function, because assembler code may have line number + information without function information. */ + struct debug_lineno *linenos; +}; + +/* Information kept for a single source file. */ + +struct debug_file +{ + /* The next source file in this compilation unit. */ + struct debug_file *next; + /* The name of the source file. */ + const char *filename; + /* Global functions, variables, types, etc. */ + struct debug_namespace *globals; +}; + +/* A type. */ + +struct debug_type +{ + /* Kind of type. */ + enum debug_type_kind kind; + /* Size of type (0 if not known). */ + unsigned int size; + /* Type which is a pointer to this type. */ + debug_type pointer; + /* Tagged union with additional information about the type. */ + union + { + /* DEBUG_KIND_INDIRECT. */ + struct debug_indirect_type *kindirect; + /* DEBUG_KIND_INT. */ + /* Whether the integer is unsigned. */ + boolean kint; + /* DEBUG_KIND_STRUCT, DEBUG_KIND_UNION, DEBUG_KIND_CLASS, + DEBUG_KIND_UNION_CLASS. */ + struct debug_class_type *kclass; + /* DEBUG_KIND_ENUM. */ + struct debug_enum_type *kenum; + /* DEBUG_KIND_POINTER. */ + struct debug_type *kpointer; + /* DEBUG_KIND_FUNCTION. */ + struct debug_function_type *kfunction; + /* DEBUG_KIND_REFERENCE. */ + struct debug_type *kreference; + /* DEBUG_KIND_RANGE. */ + struct debug_range_type *krange; + /* DEBUG_KIND_ARRAY. */ + struct debug_array_type *karray; + /* DEBUG_KIND_SET. */ + struct debug_set_type *kset; + /* DEBUG_KIND_OFFSET. */ + struct debug_offset_type *koffset; + /* DEBUG_KIND_METHOD. */ + struct debug_method_type *kmethod; + /* DEBUG_KIND_CONST. */ + struct debug_type *kconst; + /* DEBUG_KIND_VOLATILE. */ + struct debug_type *kvolatile; + /* DEBUG_KIND_NAMED, DEBUG_KIND_TAGGED. */ + struct debug_named_type *knamed; + } u; +}; + +/* Information kept for an indirect type. */ + +struct debug_indirect_type +{ + /* Slot where the final type will appear. */ + debug_type *slot; + /* Tag. */ + const char *tag; +}; + +/* Information kept for a struct, union, or class. */ + +struct debug_class_type +{ + /* NULL terminated array of fields. */ + debug_field *fields; + /* A mark field which indicates whether the struct has already been + printed. */ + unsigned int mark; + /* This is used to uniquely identify unnamed structs when printing. */ + unsigned int id; + /* The remaining fields are only used for DEBUG_KIND_CLASS and + DEBUG_KIND_UNION_CLASS. */ + /* NULL terminated array of base classes. */ + debug_baseclass *baseclasses; + /* NULL terminated array of methods. */ + debug_method *methods; + /* The type of the class providing the virtual function table for + this class. This may point to the type itself. */ + debug_type vptrbase; +}; + +/* Information kept for an enum. */ + +struct debug_enum_type +{ + /* NULL terminated array of names. */ + const char **names; + /* Array of corresponding values. */ + bfd_signed_vma *values; +}; + +/* Information kept for a function. FIXME: We should be able to + record the parameter types. */ + +struct debug_function_type +{ + /* Return type. */ + debug_type return_type; + /* NULL terminated array of argument types. */ + debug_type *arg_types; + /* Whether the function takes a variable number of arguments. */ + boolean varargs; +}; + +/* Information kept for a range. */ + +struct debug_range_type +{ + /* Range base type. */ + debug_type type; + /* Lower bound. */ + bfd_signed_vma lower; + /* Upper bound. */ + bfd_signed_vma upper; +}; + +/* Information kept for an array. */ + +struct debug_array_type +{ + /* Element type. */ + debug_type element_type; + /* Range type. */ + debug_type range_type; + /* Lower bound. */ + bfd_signed_vma lower; + /* Upper bound. */ + bfd_signed_vma upper; + /* Whether this array is really a string. */ + boolean stringp; +}; + +/* Information kept for a set. */ + +struct debug_set_type +{ + /* Base type. */ + debug_type type; + /* Whether this set is really a bitstring. */ + boolean bitstringp; +}; + +/* Information kept for an offset type (a based pointer). */ + +struct debug_offset_type +{ + /* The type the pointer is an offset from. */ + debug_type base_type; + /* The type the pointer points to. */ + debug_type target_type; +}; + +/* Information kept for a method type. */ + +struct debug_method_type +{ + /* The return type. */ + debug_type return_type; + /* The object type which this method is for. */ + debug_type domain_type; + /* A NULL terminated array of argument types. */ + debug_type *arg_types; + /* Whether the method takes a variable number of arguments. */ + boolean varargs; +}; + +/* Information kept for a named type. */ + +struct debug_named_type +{ + /* Name. */ + struct debug_name *name; + /* Real type. */ + debug_type type; +}; + +/* A field in a struct or union. */ + +struct debug_field +{ + /* Name of the field. */ + const char *name; + /* Type of the field. */ + struct debug_type *type; + /* Visibility of the field. */ + enum debug_visibility visibility; + /* Whether this is a static member. */ + boolean static_member; + union + { + /* If static_member is false. */ + struct + { + /* Bit position of the field in the struct. */ + unsigned int bitpos; + /* Size of the field in bits. */ + unsigned int bitsize; + } f; + /* If static_member is true. */ + struct + { + const char *physname; + } s; + } u; +}; + +/* A base class for an object. */ + +struct debug_baseclass +{ + /* Type of the base class. */ + struct debug_type *type; + /* Bit position of the base class in the object. */ + unsigned int bitpos; + /* Whether the base class is virtual. */ + boolean virtual; + /* Visibility of the base class. */ + enum debug_visibility visibility; +}; + +/* A method of an object. */ + +struct debug_method +{ + /* The name of the method. */ + const char *name; + /* A NULL terminated array of different types of variants. */ + struct debug_method_variant **variants; +}; + +/* The variants of a method function of an object. These indicate + which method to run. */ + +struct debug_method_variant +{ + /* The physical name of the function. */ + const char *physname; + /* The type of the function. */ + struct debug_type *type; + /* The visibility of the function. */ + enum debug_visibility visibility; + /* Whether the function is const. */ + boolean constp; + /* Whether the function is volatile. */ + boolean volatilep; + /* The offset to the function in the virtual function table. */ + bfd_vma voffset; + /* If voffset is VOFFSET_STATIC_METHOD, this is a static method. */ +#define VOFFSET_STATIC_METHOD ((bfd_vma) -1) + /* Context of a virtual method function. */ + struct debug_type *context; +}; + +/* A variable. This is the information we keep for a variable object. + This has no name; a name is associated with a variable in a + debug_name structure. */ + +struct debug_variable +{ + /* Kind of variable. */ + enum debug_var_kind kind; + /* Type. */ + debug_type type; + /* Value. The interpretation of the value depends upon kind. */ + bfd_vma val; +}; + +/* A function. This has no name; a name is associated with a function + in a debug_name structure. */ + +struct debug_function +{ + /* Return type. */ + debug_type return_type; + /* Parameter information. */ + struct debug_parameter *parameters; + /* Block information. The first structure on the list is the main + block of the function, and describes function local variables. */ + struct debug_block *blocks; +}; + +/* A function parameter. */ + +struct debug_parameter +{ + /* Next parameter. */ + struct debug_parameter *next; + /* Name. */ + const char *name; + /* Type. */ + debug_type type; + /* Kind. */ + enum debug_parm_kind kind; + /* Value (meaning depends upon kind). */ + bfd_vma val; +}; + +/* A typed constant. */ + +struct debug_typed_constant +{ + /* Type. */ + debug_type type; + /* Value. FIXME: We may eventually need to support non-integral + values. */ + bfd_vma val; +}; + +/* Information about a block within a function. */ + +struct debug_block +{ + /* Next block with the same parent. */ + struct debug_block *next; + /* Parent block. */ + struct debug_block *parent; + /* List of child blocks. */ + struct debug_block *children; + /* Start address of the block. */ + bfd_vma start; + /* End address of the block. */ + bfd_vma end; + /* Local variables. */ + struct debug_namespace *locals; +}; + +/* Line number information we keep for a compilation unit. FIXME: + This structure is easy to create, but can be very space + inefficient. */ + +struct debug_lineno +{ + /* More line number information for this block. */ + struct debug_lineno *next; + /* Source file. */ + struct debug_file *file; + /* Line numbers, terminated by a -1 or the end of the array. */ +#define DEBUG_LINENO_COUNT 10 + unsigned long linenos[DEBUG_LINENO_COUNT]; + /* Addresses for the line numbers. */ + bfd_vma addrs[DEBUG_LINENO_COUNT]; +}; + +/* A namespace. This is a mapping from names to objects. FIXME: This + should be implemented as a hash table. */ + +struct debug_namespace +{ + /* List of items in this namespace. */ + struct debug_name *list; + /* Pointer to where the next item in this namespace should go. */ + struct debug_name **tail; +}; + +/* Kinds of objects that appear in a namespace. */ + +enum debug_object_kind +{ + /* A type. */ + DEBUG_OBJECT_TYPE, + /* A tagged type (really a different sort of namespace). */ + DEBUG_OBJECT_TAG, + /* A variable. */ + DEBUG_OBJECT_VARIABLE, + /* A function. */ + DEBUG_OBJECT_FUNCTION, + /* An integer constant. */ + DEBUG_OBJECT_INT_CONSTANT, + /* A floating point constant. */ + DEBUG_OBJECT_FLOAT_CONSTANT, + /* A typed constant. */ + DEBUG_OBJECT_TYPED_CONSTANT +}; + +/* Linkage of an object that appears in a namespace. */ + +enum debug_object_linkage +{ + /* Local variable. */ + DEBUG_LINKAGE_AUTOMATIC, + /* Static--either file static or function static, depending upon the + namespace is. */ + DEBUG_LINKAGE_STATIC, + /* Global. */ + DEBUG_LINKAGE_GLOBAL, + /* No linkage. */ + DEBUG_LINKAGE_NONE +}; + +/* A name in a namespace. */ + +struct debug_name +{ + /* Next name in this namespace. */ + struct debug_name *next; + /* Name. */ + const char *name; + /* Mark. This is used by debug_write. */ + unsigned int mark; + /* Kind of object. */ + enum debug_object_kind kind; + /* Linkage of object. */ + enum debug_object_linkage linkage; + /* Tagged union with additional information about the object. */ + union + { + /* DEBUG_OBJECT_TYPE. */ + struct debug_type *type; + /* DEBUG_OBJECT_TAG. */ + struct debug_type *tag; + /* DEBUG_OBJECT_VARIABLE. */ + struct debug_variable *variable; + /* DEBUG_OBJECT_FUNCTION. */ + struct debug_function *function; + /* DEBUG_OBJECT_INT_CONSTANT. */ + bfd_vma int_constant; + /* DEBUG_OBJECT_FLOAT_CONSTANT. */ + double float_constant; + /* DEBUG_OBJECT_TYPED_CONSTANT. */ + struct debug_typed_constant *typed_constant; + } u; +}; + +/* During debug_write, a linked list of these structures is used to + keep track of ID numbers that have been assigned to classes. */ + +struct debug_class_id +{ + /* Next ID number. */ + struct debug_class_id *next; + /* The type with the ID. */ + struct debug_type *type; + /* The tag; NULL if no tag. */ + const char *tag; +}; + +/* During debug_type_samep, a linked list of these structures is kept + on the stack to avoid infinite recursion. */ + +struct debug_type_compare_list +{ + /* Next type on list. */ + struct debug_type_compare_list *next; + /* The types we are comparing. */ + struct debug_type *t1; + struct debug_type *t2; +}; + +/* During debug_get_real_type, a linked list of these structures is + kept on the stack to avoid infinite recursion. */ + +struct debug_type_real_list +{ + /* Next type on list. */ + struct debug_type_real_list *next; + /* The type we are checking. */ + struct debug_type *t; +}; + +/* Local functions. */ + +static void debug_error PARAMS ((const char *)); +static struct debug_name *debug_add_to_namespace + PARAMS ((struct debug_handle *, struct debug_namespace **, const char *, + enum debug_object_kind, enum debug_object_linkage)); +static struct debug_name *debug_add_to_current_namespace + PARAMS ((struct debug_handle *, const char *, enum debug_object_kind, + enum debug_object_linkage)); +static struct debug_type *debug_make_type + PARAMS ((struct debug_handle *, enum debug_type_kind, unsigned int)); +static struct debug_type *debug_get_real_type + PARAMS ((PTR, debug_type, struct debug_type_real_list *)); +static boolean debug_write_name + PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR, + struct debug_name *)); +static boolean debug_write_type + PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR, + struct debug_type *, struct debug_name *)); +static boolean debug_write_class_type + PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR, + struct debug_type *, const char *)); +static boolean debug_write_function + PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR, + const char *, enum debug_object_linkage, struct debug_function *)); +static boolean debug_write_block + PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR, + struct debug_block *)); +static boolean debug_write_linenos + PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR, + bfd_vma)); +static boolean debug_set_class_id + PARAMS ((struct debug_handle *, const char *, struct debug_type *)); +static boolean debug_type_samep + PARAMS ((struct debug_handle *, struct debug_type *, struct debug_type *)); +static boolean debug_class_type_samep + PARAMS ((struct debug_handle *, struct debug_type *, struct debug_type *)); + +/* Issue an error message. */ + +static void +debug_error (message) + const char *message; +{ + fprintf (stderr, "%s\n", message); +} + +/* Add an object to a namespace. */ + +static struct debug_name * +debug_add_to_namespace (info, nsp, name, kind, linkage) + struct debug_handle *info; + struct debug_namespace **nsp; + const char *name; + enum debug_object_kind kind; + enum debug_object_linkage linkage; +{ + struct debug_name *n; + struct debug_namespace *ns; + + n = (struct debug_name *) xmalloc (sizeof *n); + memset (n, 0, sizeof *n); + + n->name = name; + n->kind = kind; + n->linkage = linkage; + + ns = *nsp; + if (ns == NULL) + { + ns = (struct debug_namespace *) xmalloc (sizeof *ns); + memset (ns, 0, sizeof *ns); + + ns->tail = &ns->list; + + *nsp = ns; + } + + *ns->tail = n; + ns->tail = &n->next; + + return n; +} + +/* Add an object to the current namespace. */ + +static struct debug_name * +debug_add_to_current_namespace (info, name, kind, linkage) + struct debug_handle *info; + const char *name; + enum debug_object_kind kind; + enum debug_object_linkage linkage; +{ + struct debug_namespace **nsp; + + if (info->current_unit == NULL + || info->current_file == NULL) + { + debug_error (_("debug_add_to_current_namespace: no current file")); + return NULL; + } + + if (info->current_block != NULL) + nsp = &info->current_block->locals; + else + nsp = &info->current_file->globals; + + return debug_add_to_namespace (info, nsp, name, kind, linkage); +} + +/* Return a handle for debugging information. */ + +PTR +debug_init () +{ + struct debug_handle *ret; + + ret = (struct debug_handle *) xmalloc (sizeof *ret); + memset (ret, 0, sizeof *ret); + return (PTR) ret; +} + +/* Set the source filename. This implicitly starts a new compilation + unit. */ + +boolean +debug_set_filename (handle, name) + PTR handle; + const char *name; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_file *nfile; + struct debug_unit *nunit; + + if (name == NULL) + name = ""; + + nfile = (struct debug_file *) xmalloc (sizeof *nfile); + memset (nfile, 0, sizeof *nfile); + + nfile->filename = name; + + nunit = (struct debug_unit *) xmalloc (sizeof *nunit); + memset (nunit, 0, sizeof *nunit); + + nunit->files = nfile; + info->current_file = nfile; + + if (info->current_unit != NULL) + info->current_unit->next = nunit; + else + { + assert (info->units == NULL); + info->units = nunit; + } + + info->current_unit = nunit; + + info->current_function = NULL; + info->current_block = NULL; + info->current_lineno = NULL; + + return true; +} + +/* Change source files to the given file name. This is used for + include files in a single compilation unit. */ + +boolean +debug_start_source (handle, name) + PTR handle; + const char *name; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_file *f, **pf; + + if (name == NULL) + name = ""; + + if (info->current_unit == NULL) + { + debug_error (_("debug_start_source: no debug_set_filename call")); + return false; + } + + for (f = info->current_unit->files; f != NULL; f = f->next) + { + if (f->filename[0] == name[0] + && f->filename[1] == name[1] + && strcmp (f->filename, name) == 0) + { + info->current_file = f; + return true; + } + } + + f = (struct debug_file *) xmalloc (sizeof *f); + memset (f, 0, sizeof *f); + + f->filename = name; + + for (pf = &info->current_file->next; + *pf != NULL; + pf = &(*pf)->next) + ; + *pf = f; + + info->current_file = f; + + return true; +} + +/* Record a function definition. This implicitly starts a function + block. The debug_type argument is the type of the return value. + The boolean indicates whether the function is globally visible. + The bfd_vma is the address of the start of the function. Currently + the parameter types are specified by calls to + debug_record_parameter. FIXME: There is no way to specify nested + functions. */ + +boolean +debug_record_function (handle, name, return_type, global, addr) + PTR handle; + const char *name; + debug_type return_type; + boolean global; + bfd_vma addr; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_function *f; + struct debug_block *b; + struct debug_name *n; + + if (name == NULL) + name = ""; + if (return_type == NULL) + return false; + + if (info->current_unit == NULL) + { + debug_error (_("debug_record_function: no debug_set_filename call")); + return false; + } + + f = (struct debug_function *) xmalloc (sizeof *f); + memset (f, 0, sizeof *f); + + f->return_type = return_type; + + b = (struct debug_block *) xmalloc (sizeof *b); + memset (b, 0, sizeof *b); + + b->start = addr; + b->end = (bfd_vma) -1; + + f->blocks = b; + + info->current_function = f; + info->current_block = b; + + /* FIXME: If we could handle nested functions, this would be the + place: we would want to use a different namespace. */ + n = debug_add_to_namespace (info, + &info->current_file->globals, + name, + DEBUG_OBJECT_FUNCTION, + (global + ? DEBUG_LINKAGE_GLOBAL + : DEBUG_LINKAGE_STATIC)); + if (n == NULL) + return false; + + n->u.function = f; + + return true; +} + +/* Record a parameter for the current function. */ + +boolean +debug_record_parameter (handle, name, type, kind, val) + PTR handle; + const char *name; + debug_type type; + enum debug_parm_kind kind; + bfd_vma val; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_parameter *p, **pp; + + if (name == NULL || type == NULL) + return false; + + if (info->current_unit == NULL + || info->current_function == NULL) + { + debug_error (_("debug_record_parameter: no current function")); + return false; + } + + p = (struct debug_parameter *) xmalloc (sizeof *p); + memset (p, 0, sizeof *p); + + p->name = name; + p->type = type; + p->kind = kind; + p->val = val; + + for (pp = &info->current_function->parameters; + *pp != NULL; + pp = &(*pp)->next) + ; + *pp = p; + + return true; +} + +/* End a function. FIXME: This should handle function nesting. */ + +boolean +debug_end_function (handle, addr) + PTR handle; + bfd_vma addr; +{ + struct debug_handle *info = (struct debug_handle *) handle; + + if (info->current_unit == NULL + || info->current_block == NULL + || info->current_function == NULL) + { + debug_error (_("debug_end_function: no current function")); + return false; + } + + if (info->current_block->parent != NULL) + { + debug_error (_("debug_end_function: some blocks were not closed")); + return false; + } + + info->current_block->end = addr; + + info->current_function = NULL; + info->current_block = NULL; + + return true; +} + +/* Start a block in a function. All local information will be + recorded in this block, until the matching call to debug_end_block. + debug_start_block and debug_end_block may be nested. The bfd_vma + argument is the address at which this block starts. */ + +boolean +debug_start_block (handle, addr) + PTR handle; + bfd_vma addr; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_block *b, **pb; + + /* We must always have a current block: debug_record_function sets + one up. */ + if (info->current_unit == NULL + || info->current_block == NULL) + { + debug_error (_("debug_start_block: no current block")); + return false; + } + + b = (struct debug_block *) xmalloc (sizeof *b); + memset (b, 0, sizeof *b); + + b->parent = info->current_block; + b->start = addr; + b->end = (bfd_vma) -1; + + /* This new block is a child of the current block. */ + for (pb = &info->current_block->children; + *pb != NULL; + pb = &(*pb)->next) + ; + *pb = b; + + info->current_block = b; + + return true; +} + +/* Finish a block in a function. This matches the call to + debug_start_block. The argument is the address at which this block + ends. */ + +boolean +debug_end_block (handle, addr) + PTR handle; + bfd_vma addr; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_block *parent; + + if (info->current_unit == NULL + || info->current_block == NULL) + { + debug_error (_("debug_end_block: no current block")); + return false; + } + + parent = info->current_block->parent; + if (parent == NULL) + { + debug_error (_("debug_end_block: attempt to close top level block")); + return false; + } + + info->current_block->end = addr; + + info->current_block = parent; + + return true; +} + +/* Associate a line number in the current source file and function + with a given address. */ + +boolean +debug_record_line (handle, lineno, addr) + PTR handle; + unsigned long lineno; + bfd_vma addr; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_lineno *l; + unsigned int i; + + if (info->current_unit == NULL) + { + debug_error (_("debug_record_line: no current unit")); + return false; + } + + l = info->current_lineno; + if (l != NULL && l->file == info->current_file) + { + for (i = 0; i < DEBUG_LINENO_COUNT; i++) + { + if (l->linenos[i] == (unsigned long) -1) + { + l->linenos[i] = lineno; + l->addrs[i] = addr; + return true; + } + } + } + + /* If we get here, then either 1) there is no current_lineno + structure, which means this is the first line number in this + compilation unit, 2) the current_lineno structure is for a + different file, or 3) the current_lineno structure is full. + Regardless, we want to allocate a new debug_lineno structure, put + it in the right place, and make it the new current_lineno + structure. */ + + l = (struct debug_lineno *) xmalloc (sizeof *l); + memset (l, 0, sizeof *l); + + l->file = info->current_file; + l->linenos[0] = lineno; + l->addrs[0] = addr; + for (i = 1; i < DEBUG_LINENO_COUNT; i++) + l->linenos[i] = (unsigned long) -1; + + if (info->current_lineno != NULL) + info->current_lineno->next = l; + else + info->current_unit->linenos = l; + + info->current_lineno = l; + + return true; +} + +/* Start a named common block. This is a block of variables that may + move in memory. */ + +boolean +debug_start_common_block (handle, name) + PTR handle; + const char *name; +{ + /* FIXME */ + debug_error (_("debug_start_common_block: not implemented")); + return false; +} + +/* End a named common block. */ + +boolean +debug_end_common_block (handle, name) + PTR handle; + const char *name; +{ + /* FIXME */ + debug_error (_("debug_end_common_block: not implemented")); + return false; +} + +/* Record a named integer constant. */ + +boolean +debug_record_int_const (handle, name, val) + PTR handle; + const char *name; + bfd_vma val; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_name *n; + + if (name == NULL) + return false; + + n = debug_add_to_current_namespace (info, name, DEBUG_OBJECT_INT_CONSTANT, + DEBUG_LINKAGE_NONE); + if (n == NULL) + return false; + + n->u.int_constant = val; + + return true; +} + +/* Record a named floating point constant. */ + +boolean +debug_record_float_const (handle, name, val) + PTR handle; + const char *name; + double val; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_name *n; + + if (name == NULL) + return false; + + n = debug_add_to_current_namespace (info, name, DEBUG_OBJECT_FLOAT_CONSTANT, + DEBUG_LINKAGE_NONE); + if (n == NULL) + return false; + + n->u.float_constant = val; + + return true; +} + +/* Record a typed constant with an integral value. */ + +boolean +debug_record_typed_const (handle, name, type, val) + PTR handle; + const char *name; + debug_type type; + bfd_vma val; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_name *n; + struct debug_typed_constant *tc; + + if (name == NULL || type == NULL) + return false; + + n = debug_add_to_current_namespace (info, name, DEBUG_OBJECT_TYPED_CONSTANT, + DEBUG_LINKAGE_NONE); + if (n == NULL) + return false; + + tc = (struct debug_typed_constant *) xmalloc (sizeof *tc); + memset (tc, 0, sizeof *tc); + + tc->type = type; + tc->val = val; + + n->u.typed_constant = tc; + + return true; +} + +/* Record a label. */ + +boolean +debug_record_label (handle, name, type, addr) + PTR handle; + const char *name; + debug_type type; + bfd_vma addr; +{ + /* FIXME. */ + debug_error (_("debug_record_label not implemented")); + return false; +} + +/* Record a variable. */ + +boolean +debug_record_variable (handle, name, type, kind, val) + PTR handle; + const char *name; + debug_type type; + enum debug_var_kind kind; + bfd_vma val; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_namespace **nsp; + enum debug_object_linkage linkage; + struct debug_name *n; + struct debug_variable *v; + + if (name == NULL || type == NULL) + return false; + + if (info->current_unit == NULL + || info->current_file == NULL) + { + debug_error (_("debug_record_variable: no current file")); + return false; + } + + if (kind == DEBUG_GLOBAL || kind == DEBUG_STATIC) + { + nsp = &info->current_file->globals; + if (kind == DEBUG_GLOBAL) + linkage = DEBUG_LINKAGE_GLOBAL; + else + linkage = DEBUG_LINKAGE_STATIC; + } + else + { + if (info->current_block == NULL) + { + debug_error (_("debug_record_variable: no current block")); + return false; + } + nsp = &info->current_block->locals; + linkage = DEBUG_LINKAGE_AUTOMATIC; + } + + n = debug_add_to_namespace (info, nsp, name, DEBUG_OBJECT_VARIABLE, linkage); + if (n == NULL) + return false; + + v = (struct debug_variable *) xmalloc (sizeof *v); + memset (v, 0, sizeof *v); + + v->kind = kind; + v->type = type; + v->val = val; + + n->u.variable = v; + + return true; +} + +/* Make a type with a given kind and size. */ + +/*ARGSUSED*/ +static struct debug_type * +debug_make_type (info, kind, size) + struct debug_handle *info; + enum debug_type_kind kind; + unsigned int size; +{ + struct debug_type *t; + + t = (struct debug_type *) xmalloc (sizeof *t); + memset (t, 0, sizeof *t); + + t->kind = kind; + t->size = size; + + return t; +} + +/* Make an indirect type which may be used as a placeholder for a type + which is referenced before it is defined. */ + +debug_type +debug_make_indirect_type (handle, slot, tag) + PTR handle; + debug_type *slot; + const char *tag; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_type *t; + struct debug_indirect_type *i; + + t = debug_make_type (info, DEBUG_KIND_INDIRECT, 0); + if (t == NULL) + return DEBUG_TYPE_NULL; + + i = (struct debug_indirect_type *) xmalloc (sizeof *i); + memset (i, 0, sizeof *i); + + i->slot = slot; + i->tag = tag; + + t->u.kindirect = i; + + return t; +} + +/* Make a void type. There is only one of these. */ + +debug_type +debug_make_void_type (handle) + PTR handle; +{ + struct debug_handle *info = (struct debug_handle *) handle; + + return debug_make_type (info, DEBUG_KIND_VOID, 0); +} + +/* Make an integer type of a given size. The boolean argument is true + if the integer is unsigned. */ + +debug_type +debug_make_int_type (handle, size, unsignedp) + PTR handle; + unsigned int size; + boolean unsignedp; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_type *t; + + t = debug_make_type (info, DEBUG_KIND_INT, size); + if (t == NULL) + return DEBUG_TYPE_NULL; + + t->u.kint = unsignedp; + + return t; +} + +/* Make a floating point type of a given size. FIXME: On some + platforms, like an Alpha, you probably need to be able to specify + the format. */ + +debug_type +debug_make_float_type (handle, size) + PTR handle; + unsigned int size; +{ + struct debug_handle *info = (struct debug_handle *) handle; + + return debug_make_type (info, DEBUG_KIND_FLOAT, size); +} + +/* Make a boolean type of a given size. */ + +debug_type +debug_make_bool_type (handle, size) + PTR handle; + unsigned int size; +{ + struct debug_handle *info = (struct debug_handle *) handle; + + return debug_make_type (info, DEBUG_KIND_BOOL, size); +} + +/* Make a complex type of a given size. */ + +debug_type +debug_make_complex_type (handle, size) + PTR handle; + unsigned int size; +{ + struct debug_handle *info = (struct debug_handle *) handle; + + return debug_make_type (info, DEBUG_KIND_COMPLEX, size); +} + +/* Make a structure type. The second argument is true for a struct, + false for a union. The third argument is the size of the struct. + The fourth argument is a NULL terminated array of fields. */ + +debug_type +debug_make_struct_type (handle, structp, size, fields) + PTR handle; + boolean structp; + bfd_vma size; + debug_field *fields; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_type *t; + struct debug_class_type *c; + + t = debug_make_type (info, + structp ? DEBUG_KIND_STRUCT : DEBUG_KIND_UNION, + size); + if (t == NULL) + return DEBUG_TYPE_NULL; + + c = (struct debug_class_type *) xmalloc (sizeof *c); + memset (c, 0, sizeof *c); + + c->fields = fields; + + t->u.kclass = c; + + return t; +} + +/* Make an object type. The first three arguments after the handle + are the same as for debug_make_struct_type. The next arguments are + a NULL terminated array of base classes, a NULL terminated array of + methods, the type of the object holding the virtual function table + if it is not this object, and a boolean which is true if this + object has its own virtual function table. */ + +debug_type +debug_make_object_type (handle, structp, size, fields, baseclasses, + methods, vptrbase, ownvptr) + PTR handle; + boolean structp; + bfd_vma size; + debug_field *fields; + debug_baseclass *baseclasses; + debug_method *methods; + debug_type vptrbase; + boolean ownvptr; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_type *t; + struct debug_class_type *c; + + t = debug_make_type (info, + structp ? DEBUG_KIND_CLASS : DEBUG_KIND_UNION_CLASS, + size); + if (t == NULL) + return DEBUG_TYPE_NULL; + + c = (struct debug_class_type *) xmalloc (sizeof *c); + memset (c, 0, sizeof *c); + + c->fields = fields; + c->baseclasses = baseclasses; + c->methods = methods; + if (ownvptr) + c->vptrbase = t; + else + c->vptrbase = vptrbase; + + t->u.kclass = c; + + return t; +} + +/* Make an enumeration type. The arguments are a null terminated + array of strings, and an array of corresponding values. */ + +debug_type +debug_make_enum_type (handle, names, values) + PTR handle; + const char **names; + bfd_signed_vma *values; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_type *t; + struct debug_enum_type *e; + + t = debug_make_type (info, DEBUG_KIND_ENUM, 0); + if (t == NULL) + return DEBUG_TYPE_NULL; + + e = (struct debug_enum_type *) xmalloc (sizeof *e); + memset (e, 0, sizeof *e); + + e->names = names; + e->values = values; + + t->u.kenum = e; + + return t; +} + +/* Make a pointer to a given type. */ + +debug_type +debug_make_pointer_type (handle, type) + PTR handle; + debug_type type; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_type *t; + + if (type == NULL) + return DEBUG_TYPE_NULL; + + if (type->pointer != DEBUG_TYPE_NULL) + return type->pointer; + + t = debug_make_type (info, DEBUG_KIND_POINTER, 0); + if (t == NULL) + return DEBUG_TYPE_NULL; + + t->u.kpointer = type; + + type->pointer = t; + + return t; +} + +/* Make a function returning a given type. FIXME: We should be able + to record the parameter types. */ + +debug_type +debug_make_function_type (handle, type, arg_types, varargs) + PTR handle; + debug_type type; + debug_type *arg_types; + boolean varargs; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_type *t; + struct debug_function_type *f; + + if (type == NULL) + return DEBUG_TYPE_NULL; + + t = debug_make_type (info, DEBUG_KIND_FUNCTION, 0); + if (t == NULL) + return DEBUG_TYPE_NULL; + + f = (struct debug_function_type *) xmalloc (sizeof *f); + memset (f, 0, sizeof *f); + + f->return_type = type; + f->arg_types = arg_types; + f->varargs = varargs; + + t->u.kfunction = f; + + return t; +} + +/* Make a reference to a given type. */ + +debug_type +debug_make_reference_type (handle, type) + PTR handle; + debug_type type; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_type *t; + + if (type == NULL) + return DEBUG_TYPE_NULL; + + t = debug_make_type (info, DEBUG_KIND_REFERENCE, 0); + if (t == NULL) + return DEBUG_TYPE_NULL; + + t->u.kreference = type; + + return t; +} + +/* Make a range of a given type from a lower to an upper bound. */ + +debug_type +debug_make_range_type (handle, type, lower, upper) + PTR handle; + debug_type type; + bfd_signed_vma lower; + bfd_signed_vma upper; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_type *t; + struct debug_range_type *r; + + if (type == NULL) + return DEBUG_TYPE_NULL; + + t = debug_make_type (info, DEBUG_KIND_RANGE, 0); + if (t == NULL) + return DEBUG_TYPE_NULL; + + r = (struct debug_range_type *) xmalloc (sizeof *r); + memset (r, 0, sizeof *r); + + r->type = type; + r->lower = lower; + r->upper = upper; + + t->u.krange = r; + + return t; +} + +/* Make an array type. The second argument is the type of an element + of the array. The third argument is the type of a range of the + array. The fourth and fifth argument are the lower and upper + bounds, respectively. The sixth argument is true if this array is + actually a string, as in C. */ + +debug_type +debug_make_array_type (handle, element_type, range_type, lower, upper, + stringp) + PTR handle; + debug_type element_type; + debug_type range_type; + bfd_signed_vma lower; + bfd_signed_vma upper; + boolean stringp; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_type *t; + struct debug_array_type *a; + + if (element_type == NULL || range_type == NULL) + return DEBUG_TYPE_NULL; + + t = debug_make_type (info, DEBUG_KIND_ARRAY, 0); + if (t == NULL) + return DEBUG_TYPE_NULL; + + a = (struct debug_array_type *) xmalloc (sizeof *a); + memset (a, 0, sizeof *a); + + a->element_type = element_type; + a->range_type = range_type; + a->lower = lower; + a->upper = upper; + a->stringp = stringp; + + t->u.karray = a; + + return t; +} + +/* Make a set of a given type. For example, a Pascal set type. The + boolean argument is true if this set is actually a bitstring, as in + CHILL. */ + +debug_type +debug_make_set_type (handle, type, bitstringp) + PTR handle; + debug_type type; + boolean bitstringp; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_type *t; + struct debug_set_type *s; + + if (type == NULL) + return DEBUG_TYPE_NULL; + + t = debug_make_type (info, DEBUG_KIND_SET, 0); + if (t == NULL) + return DEBUG_TYPE_NULL; + + s = (struct debug_set_type *) xmalloc (sizeof *s); + memset (s, 0, sizeof *s); + + s->type = type; + s->bitstringp = bitstringp; + + t->u.kset = s; + + return t; +} + +/* Make a type for a pointer which is relative to an object. The + second argument is the type of the object to which the pointer is + relative. The third argument is the type that the pointer points + to. */ + +debug_type +debug_make_offset_type (handle, base_type, target_type) + PTR handle; + debug_type base_type; + debug_type target_type; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_type *t; + struct debug_offset_type *o; + + if (base_type == NULL || target_type == NULL) + return DEBUG_TYPE_NULL; + + t = debug_make_type (info, DEBUG_KIND_OFFSET, 0); + if (t == NULL) + return DEBUG_TYPE_NULL; + + o = (struct debug_offset_type *) xmalloc (sizeof *o); + memset (o, 0, sizeof *o); + + o->base_type = base_type; + o->target_type = target_type; + + t->u.koffset = o; + + return t; +} + +/* Make a type for a method function. The second argument is the + return type, the third argument is the domain, and the fourth + argument is a NULL terminated array of argument types. */ + +debug_type +debug_make_method_type (handle, return_type, domain_type, arg_types, varargs) + PTR handle; + debug_type return_type; + debug_type domain_type; + debug_type *arg_types; + boolean varargs; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_type *t; + struct debug_method_type *m; + + if (return_type == NULL) + return DEBUG_TYPE_NULL; + + t = debug_make_type (info, DEBUG_KIND_METHOD, 0); + if (t == NULL) + return DEBUG_TYPE_NULL; + + m = (struct debug_method_type *) xmalloc (sizeof *m); + memset (m, 0, sizeof *m); + + m->return_type = return_type; + m->domain_type = domain_type; + m->arg_types = arg_types; + m->varargs = varargs; + + t->u.kmethod = m; + + return t; +} + +/* Make a const qualified version of a given type. */ + +debug_type +debug_make_const_type (handle, type) + PTR handle; + debug_type type; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_type *t; + + if (type == NULL) + return DEBUG_TYPE_NULL; + + t = debug_make_type (info, DEBUG_KIND_CONST, 0); + if (t == NULL) + return DEBUG_TYPE_NULL; + + t->u.kconst = type; + + return t; +} + +/* Make a volatile qualified version of a given type. */ + +debug_type +debug_make_volatile_type (handle, type) + PTR handle; + debug_type type; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_type *t; + + if (type == NULL) + return DEBUG_TYPE_NULL; + + t = debug_make_type (info, DEBUG_KIND_VOLATILE, 0); + if (t == NULL) + return DEBUG_TYPE_NULL; + + t->u.kvolatile = type; + + return t; +} + +/* Make an undefined tagged type. For example, a struct which has + been mentioned, but not defined. */ + +debug_type +debug_make_undefined_tagged_type (handle, name, kind) + PTR handle; + const char *name; + enum debug_type_kind kind; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_type *t; + + if (name == NULL) + return DEBUG_TYPE_NULL; + + switch (kind) + { + case DEBUG_KIND_STRUCT: + case DEBUG_KIND_UNION: + case DEBUG_KIND_CLASS: + case DEBUG_KIND_UNION_CLASS: + case DEBUG_KIND_ENUM: + break; + + default: + debug_error (_("debug_make_undefined_type: unsupported kind")); + return DEBUG_TYPE_NULL; + } + + t = debug_make_type (info, kind, 0); + if (t == NULL) + return DEBUG_TYPE_NULL; + + return debug_tag_type (handle, name, t); +} + +/* Make a base class for an object. The second argument is the base + class type. The third argument is the bit position of this base + class in the object (always 0 unless doing multiple inheritance). + The fourth argument is whether this is a virtual class. The fifth + argument is the visibility of the base class. */ + +/*ARGSUSED*/ +debug_baseclass +debug_make_baseclass (handle, type, bitpos, virtual, visibility) + PTR handle; + debug_type type; + bfd_vma bitpos; + boolean virtual; + enum debug_visibility visibility; +{ + struct debug_baseclass *b; + + b = (struct debug_baseclass *) xmalloc (sizeof *b); + memset (b, 0, sizeof *b); + + b->type = type; + b->bitpos = bitpos; + b->virtual = virtual; + b->visibility = visibility; + + return b; +} + +/* Make a field for a struct. The second argument is the name. The + third argument is the type of the field. The fourth argument is + the bit position of the field. The fifth argument is the size of + the field (it may be zero). The sixth argument is the visibility + of the field. */ + +/*ARGSUSED*/ +debug_field +debug_make_field (handle, name, type, bitpos, bitsize, visibility) + PTR handle; + const char *name; + debug_type type; + bfd_vma bitpos; + bfd_vma bitsize; + enum debug_visibility visibility; +{ + struct debug_field *f; + + f = (struct debug_field *) xmalloc (sizeof *f); + memset (f, 0, sizeof *f); + + f->name = name; + f->type = type; + f->static_member = false; + f->u.f.bitpos = bitpos; + f->u.f.bitsize = bitsize; + f->visibility = visibility; + + return f; +} + +/* Make a static member of an object. The second argument is the + name. The third argument is the type of the member. The fourth + argument is the physical name of the member (i.e., the name as a + global variable). The fifth argument is the visibility of the + member. */ + +/*ARGSUSED*/ +debug_field +debug_make_static_member (handle, name, type, physname, visibility) + PTR handle; + const char *name; + debug_type type; + const char *physname; + enum debug_visibility visibility; +{ + struct debug_field *f; + + f = (struct debug_field *) xmalloc (sizeof *f); + memset (f, 0, sizeof *f); + + f->name = name; + f->type = type; + f->static_member = true; + f->u.s.physname = physname; + f->visibility = visibility; + + return f; +} + +/* Make a method. The second argument is the name, and the third + argument is a NULL terminated array of method variants. */ + +/*ARGSUSED*/ +debug_method +debug_make_method (handle, name, variants) + PTR handle; + const char *name; + debug_method_variant *variants; +{ + struct debug_method *m; + + m = (struct debug_method *) xmalloc (sizeof *m); + memset (m, 0, sizeof *m); + + m->name = name; + m->variants = variants; + + return m; +} + +/* Make a method argument. The second argument is the real name of + the function. The third argument is the type of the function. The + fourth argument is the visibility. The fifth argument is whether + this is a const function. The sixth argument is whether this is a + volatile function. The seventh argument is the offset in the + virtual function table, if any. The eighth argument is the virtual + function context. FIXME: Are the const and volatile arguments + necessary? Could we just use debug_make_const_type? */ + +/*ARGSUSED*/ +debug_method_variant +debug_make_method_variant (handle, physname, type, visibility, constp, + volatilep, voffset, context) + PTR handle; + const char *physname; + debug_type type; + enum debug_visibility visibility; + boolean constp; + boolean volatilep; + bfd_vma voffset; + debug_type context; +{ + struct debug_method_variant *m; + + m = (struct debug_method_variant *) xmalloc (sizeof *m); + memset (m, 0, sizeof *m); + + m->physname = physname; + m->type = type; + m->visibility = visibility; + m->constp = constp; + m->volatilep = volatilep; + m->voffset = voffset; + m->context = context; + + return m; +} + +/* Make a static method argument. The arguments are the same as for + debug_make_method_variant, except that the last two are omitted + since a static method can not also be virtual. */ + +debug_method_variant +debug_make_static_method_variant (handle, physname, type, visibility, + constp, volatilep) + PTR handle; + const char *physname; + debug_type type; + enum debug_visibility visibility; + boolean constp; + boolean volatilep; +{ + struct debug_method_variant *m; + + m = (struct debug_method_variant *) xmalloc (sizeof *m); + memset (m, 0, sizeof *m); + + m->physname = physname; + m->type = type; + m->visibility = visibility; + m->constp = constp; + m->volatilep = volatilep; + m->voffset = VOFFSET_STATIC_METHOD; + + return m; +} + +/* Name a type. */ + +debug_type +debug_name_type (handle, name, type) + PTR handle; + const char *name; + debug_type type; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_type *t; + struct debug_named_type *n; + struct debug_name *nm; + + if (name == NULL || type == NULL) + return DEBUG_TYPE_NULL; + + if (info->current_unit == NULL + || info->current_file == NULL) + { + debug_error (_("debug_name_type: no current file")); + return DEBUG_TYPE_NULL; + } + + t = debug_make_type (info, DEBUG_KIND_NAMED, 0); + if (t == NULL) + return DEBUG_TYPE_NULL; + + n = (struct debug_named_type *) xmalloc (sizeof *n); + memset (n, 0, sizeof *n); + + n->type = type; + + t->u.knamed = n; + + /* We always add the name to the global namespace. This is probably + wrong in some cases, but it seems to be right for stabs. FIXME. */ + + nm = debug_add_to_namespace (info, &info->current_file->globals, name, + DEBUG_OBJECT_TYPE, DEBUG_LINKAGE_NONE); + if (nm == NULL) + return false; + + nm->u.type = t; + + n->name = nm; + + return t; +} + +/* Tag a type. */ + +debug_type +debug_tag_type (handle, name, type) + PTR handle; + const char *name; + debug_type type; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_type *t; + struct debug_named_type *n; + struct debug_name *nm; + + if (name == NULL || type == NULL) + return DEBUG_TYPE_NULL; + + if (info->current_file == NULL) + { + debug_error (_("debug_tag_type: no current file")); + return DEBUG_TYPE_NULL; + } + + if (type->kind == DEBUG_KIND_TAGGED) + { + if (strcmp (type->u.knamed->name->name, name) == 0) + return type; + debug_error (_("debug_tag_type: extra tag attempted")); + return DEBUG_TYPE_NULL; + } + + t = debug_make_type (info, DEBUG_KIND_TAGGED, 0); + if (t == NULL) + return DEBUG_TYPE_NULL; + + n = (struct debug_named_type *) xmalloc (sizeof *n); + memset (n, 0, sizeof *n); + + n->type = type; + + t->u.knamed = n; + + /* We keep a global namespace of tags for each compilation unit. I + don't know if that is the right thing to do. */ + + nm = debug_add_to_namespace (info, &info->current_file->globals, name, + DEBUG_OBJECT_TAG, DEBUG_LINKAGE_NONE); + if (nm == NULL) + return false; + + nm->u.tag = t; + + n->name = nm; + + return t; +} + +/* Record the size of a given type. */ + +/*ARGSUSED*/ +boolean +debug_record_type_size (handle, type, size) + PTR handle; + debug_type type; + unsigned int size; +{ + if (type->size != 0 && type->size != size) + fprintf (stderr, _("Warning: changing type size from %d to %d\n"), + type->size, size); + + type->size = size; + + return true; +} + +/* Find a named type. */ + +debug_type +debug_find_named_type (handle, name) + PTR handle; + const char *name; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_block *b; + struct debug_file *f; + + /* We only search the current compilation unit. I don't know if + this is right or not. */ + + if (info->current_unit == NULL) + { + debug_error (_("debug_find_named_type: no current compilation unit")); + return DEBUG_TYPE_NULL; + } + + for (b = info->current_block; b != NULL; b = b->parent) + { + if (b->locals != NULL) + { + struct debug_name *n; + + for (n = b->locals->list; n != NULL; n = n->next) + { + if (n->kind == DEBUG_OBJECT_TYPE + && n->name[0] == name[0] + && strcmp (n->name, name) == 0) + return n->u.type; + } + } + } + + for (f = info->current_unit->files; f != NULL; f = f->next) + { + if (f->globals != NULL) + { + struct debug_name *n; + + for (n = f->globals->list; n != NULL; n = n->next) + { + if (n->kind == DEBUG_OBJECT_TYPE + && n->name[0] == name[0] + && strcmp (n->name, name) == 0) + return n->u.type; + } + } + } + + return DEBUG_TYPE_NULL; +} + +/* Find a tagged type. */ + +debug_type +debug_find_tagged_type (handle, name, kind) + PTR handle; + const char *name; + enum debug_type_kind kind; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_unit *u; + + /* We search the globals of all the compilation units. I don't know + if this is correct or not. It would be easy to change. */ + + for (u = info->units; u != NULL; u = u->next) + { + struct debug_file *f; + + for (f = u->files; f != NULL; f = f->next) + { + struct debug_name *n; + + if (f->globals != NULL) + { + for (n = f->globals->list; n != NULL; n = n->next) + { + if (n->kind == DEBUG_OBJECT_TAG + && (kind == DEBUG_KIND_ILLEGAL + || n->u.tag->kind == kind) + && n->name[0] == name[0] + && strcmp (n->name, name) == 0) + return n->u.tag; + } + } + } + } + + return DEBUG_TYPE_NULL; +} + +/* Get a base type. We build a linked list on the stack to avoid + crashing if the type is defined circularly. */ + +static struct debug_type * +debug_get_real_type (handle, type, list) + PTR handle; + debug_type type; + struct debug_type_real_list *list; +{ + struct debug_type_real_list *l; + struct debug_type_real_list rl; + + switch (type->kind) + { + default: + return type; + + case DEBUG_KIND_INDIRECT: + case DEBUG_KIND_NAMED: + case DEBUG_KIND_TAGGED: + break; + } + + for (l = list; l != NULL; l = l->next) + { + if (l->t == type) + { + fprintf (stderr, + _("debug_get_real_type: circular debug information for %s\n"), + debug_get_type_name (handle, type)); + return NULL; + } + } + + rl.next = list; + rl.t = type; + + switch (type->kind) + { + /* The default case is just here to avoid warnings. */ + default: + case DEBUG_KIND_INDIRECT: + if (*type->u.kindirect->slot != NULL) + return debug_get_real_type (handle, *type->u.kindirect->slot, &rl); + return type; + case DEBUG_KIND_NAMED: + case DEBUG_KIND_TAGGED: + return debug_get_real_type (handle, type->u.knamed->type, &rl); + } + /*NOTREACHED*/ +} + +/* Get the kind of a type. */ + +enum debug_type_kind +debug_get_type_kind (handle, type) + PTR handle; + debug_type type; +{ + if (type == NULL) + return DEBUG_KIND_ILLEGAL; + type = debug_get_real_type (handle, type, NULL); + if (type == NULL) + return DEBUG_KIND_ILLEGAL; + return type->kind; +} + +/* Get the name of a type. */ + +const char * +debug_get_type_name (handle, type) + PTR handle; + debug_type type; +{ + if (type->kind == DEBUG_KIND_INDIRECT) + { + if (*type->u.kindirect->slot != NULL) + return debug_get_type_name (handle, *type->u.kindirect->slot); + return type->u.kindirect->tag; + } + if (type->kind == DEBUG_KIND_NAMED + || type->kind == DEBUG_KIND_TAGGED) + return type->u.knamed->name->name; + return NULL; +} + +/* Get the size of a type. */ + +bfd_vma +debug_get_type_size (handle, type) + PTR handle; + debug_type type; +{ + if (type == NULL) + return 0; + + /* We don't call debug_get_real_type, because somebody might have + called debug_record_type_size on a named or indirect type. */ + + if (type->size != 0) + return type->size; + + switch (type->kind) + { + default: + return 0; + case DEBUG_KIND_INDIRECT: + if (*type->u.kindirect->slot != NULL) + return debug_get_type_size (handle, *type->u.kindirect->slot); + return 0; + case DEBUG_KIND_NAMED: + case DEBUG_KIND_TAGGED: + return debug_get_type_size (handle, type->u.knamed->type); + } + /*NOTREACHED*/ +} + +/* Get the return type of a function or method type. */ + +debug_type +debug_get_return_type (handle, type) + PTR handle; + debug_type type; +{ + if (type == NULL) + return DEBUG_TYPE_NULL; + type = debug_get_real_type (handle, type, NULL); + if (type == NULL) + return DEBUG_TYPE_NULL; + switch (type->kind) + { + default: + return DEBUG_TYPE_NULL; + case DEBUG_KIND_FUNCTION: + return type->u.kfunction->return_type; + case DEBUG_KIND_METHOD: + return type->u.kmethod->return_type; + } + /*NOTREACHED*/ +} + +/* Get the parameter types of a function or method type (except that + we don't currently store the parameter types of a function). */ + +const debug_type * +debug_get_parameter_types (handle, type, pvarargs) + PTR handle; + debug_type type; + boolean *pvarargs; +{ + if (type == NULL) + return NULL; + type = debug_get_real_type (handle, type, NULL); + if (type == NULL) + return NULL; + switch (type->kind) + { + default: + return NULL; + case DEBUG_KIND_FUNCTION: + *pvarargs = type->u.kfunction->varargs; + return type->u.kfunction->arg_types; + case DEBUG_KIND_METHOD: + *pvarargs = type->u.kmethod->varargs; + return type->u.kmethod->arg_types; + } + /*NOTREACHED*/ +} + +/* Get the target type of a type. */ + +debug_type +debug_get_target_type (handle, type) + PTR handle; + debug_type type; +{ + if (type == NULL) + return NULL; + type = debug_get_real_type (handle, type, NULL); + if (type == NULL) + return NULL; + switch (type->kind) + { + default: + return NULL; + case DEBUG_KIND_POINTER: + return type->u.kpointer; + case DEBUG_KIND_REFERENCE: + return type->u.kreference; + case DEBUG_KIND_CONST: + return type->u.kconst; + case DEBUG_KIND_VOLATILE: + return type->u.kvolatile; + } + /*NOTREACHED*/ +} + +/* Get the NULL terminated array of fields for a struct, union, or + class. */ + +const debug_field * +debug_get_fields (handle, type) + PTR handle; + debug_type type; +{ + if (type == NULL) + return NULL; + type = debug_get_real_type (handle, type, NULL); + if (type == NULL) + return NULL; + switch (type->kind) + { + default: + return NULL; + case DEBUG_KIND_STRUCT: + case DEBUG_KIND_UNION: + case DEBUG_KIND_CLASS: + case DEBUG_KIND_UNION_CLASS: + return type->u.kclass->fields; + } + /*NOTREACHED*/ +} + +/* Get the type of a field. */ + +/*ARGSUSED*/ +debug_type +debug_get_field_type (handle, field) + PTR handle; + debug_field field; +{ + if (field == NULL) + return NULL; + return field->type; +} + +/* Get the name of a field. */ + +/*ARGSUSED*/ +const char * +debug_get_field_name (handle, field) + PTR handle; + debug_field field; +{ + if (field == NULL) + return NULL; + return field->name; +} + +/* Get the bit position of a field. */ + +/*ARGSUSED*/ +bfd_vma +debug_get_field_bitpos (handle, field) + PTR handle; + debug_field field; +{ + if (field == NULL || field->static_member) + return (bfd_vma) -1; + return field->u.f.bitpos; +} + +/* Get the bit size of a field. */ + +/*ARGSUSED*/ +bfd_vma +debug_get_field_bitsize (handle, field) + PTR handle; + debug_field field; +{ + if (field == NULL || field->static_member) + return (bfd_vma) -1; + return field->u.f.bitsize; +} + +/* Get the visibility of a field. */ + +/*ARGSUSED*/ +enum debug_visibility +debug_get_field_visibility (handle, field) + PTR handle; + debug_field field; +{ + if (field == NULL) + return DEBUG_VISIBILITY_IGNORE; + return field->visibility; +} + +/* Get the physical name of a field. */ + +const char * +debug_get_field_physname (handle, field) + PTR handle; + debug_field field; +{ + if (field == NULL || ! field->static_member) + return NULL; + return field->u.s.physname; +} + +/* Write out the debugging information. This is given a handle to + debugging information, and a set of function pointers to call. */ + +boolean +debug_write (handle, fns, fhandle) + PTR handle; + const struct debug_write_fns *fns; + PTR fhandle; +{ + struct debug_handle *info = (struct debug_handle *) handle; + struct debug_unit *u; + + /* We use a mark to tell whether we have already written out a + particular name. We use an integer, so that we don't have to + clear the mark fields if we happen to write out the same + information more than once. */ + ++info->mark; + + /* The base_id field holds an ID value which will never be used, so + that we can tell whether we have assigned an ID during this call + to debug_write. */ + info->base_id = info->class_id; + + /* We keep a linked list of classes for which was have assigned ID's + during this call to debug_write. */ + info->id_list = NULL; + + for (u = info->units; u != NULL; u = u->next) + { + struct debug_file *f; + boolean first_file; + + info->current_write_lineno = u->linenos; + info->current_write_lineno_index = 0; + + if (! (*fns->start_compilation_unit) (fhandle, u->files->filename)) + return false; + + first_file = true; + for (f = u->files; f != NULL; f = f->next) + { + struct debug_name *n; + + if (first_file) + first_file = false; + else + { + if (! (*fns->start_source) (fhandle, f->filename)) + return false; + } + + if (f->globals != NULL) + { + for (n = f->globals->list; n != NULL; n = n->next) + { + if (! debug_write_name (info, fns, fhandle, n)) + return false; + } + } + } + + /* Output any line number information which hasn't already been + handled. */ + if (! debug_write_linenos (info, fns, fhandle, (bfd_vma) -1)) + return false; + } + + return true; +} + +/* Write out an element in a namespace. */ + +static boolean +debug_write_name (info, fns, fhandle, n) + struct debug_handle *info; + const struct debug_write_fns *fns; + PTR fhandle; + struct debug_name *n; +{ + switch (n->kind) + { + case DEBUG_OBJECT_TYPE: + if (! debug_write_type (info, fns, fhandle, n->u.type, n) + || ! (*fns->typdef) (fhandle, n->name)) + return false; + return true; + case DEBUG_OBJECT_TAG: + if (! debug_write_type (info, fns, fhandle, n->u.tag, n)) + return false; + return (*fns->tag) (fhandle, n->name); + case DEBUG_OBJECT_VARIABLE: + if (! debug_write_type (info, fns, fhandle, n->u.variable->type, + (struct debug_name *) NULL)) + return false; + return (*fns->variable) (fhandle, n->name, n->u.variable->kind, + n->u.variable->val); + case DEBUG_OBJECT_FUNCTION: + return debug_write_function (info, fns, fhandle, n->name, + n->linkage, n->u.function); + case DEBUG_OBJECT_INT_CONSTANT: + return (*fns->int_constant) (fhandle, n->name, n->u.int_constant); + case DEBUG_OBJECT_FLOAT_CONSTANT: + return (*fns->float_constant) (fhandle, n->name, n->u.float_constant); + case DEBUG_OBJECT_TYPED_CONSTANT: + if (! debug_write_type (info, fns, fhandle, n->u.typed_constant->type, + (struct debug_name *) NULL)) + return false; + return (*fns->typed_constant) (fhandle, n->name, + n->u.typed_constant->val); + default: + abort (); + return false; + } + /*NOTREACHED*/ +} + +/* Write out a type. If the type is DEBUG_KIND_NAMED or + DEBUG_KIND_TAGGED, then the name argument is the name for which we + are about to call typedef or tag. If the type is anything else, + then the name argument is a tag from a DEBUG_KIND_TAGGED type which + points to this one. */ + +static boolean +debug_write_type (info, fns, fhandle, type, name) + struct debug_handle *info; + const struct debug_write_fns *fns; + PTR fhandle; + struct debug_type *type; + struct debug_name *name; +{ + unsigned int i; + int is; + const char *tag; + + /* If we have a name for this type, just output it. We only output + typedef names after they have been defined. We output type tags + whenever we are not actually defining them. */ + if ((type->kind == DEBUG_KIND_NAMED + || type->kind == DEBUG_KIND_TAGGED) + && (type->u.knamed->name->mark == info->mark + || (type->kind == DEBUG_KIND_TAGGED + && type->u.knamed->name != name))) + { + if (type->kind == DEBUG_KIND_NAMED) + return (*fns->typedef_type) (fhandle, type->u.knamed->name->name); + else + { + struct debug_type *real; + unsigned int id; + + real = debug_get_real_type ((PTR) info, type, NULL); + if (real == NULL) + return (*fns->empty_type) (fhandle); + id = 0; + if ((real->kind == DEBUG_KIND_STRUCT + || real->kind == DEBUG_KIND_UNION + || real->kind == DEBUG_KIND_CLASS + || real->kind == DEBUG_KIND_UNION_CLASS) + && real->u.kclass != NULL) + { + if (real->u.kclass->id <= info->base_id) + { + if (! debug_set_class_id (info, + type->u.knamed->name->name, + real)) + return false; + } + id = real->u.kclass->id; + } + + return (*fns->tag_type) (fhandle, type->u.knamed->name->name, id, + real->kind); + } + } + + /* Mark the name after we have already looked for a known name, so + that we don't just define a type in terms of itself. We need to + mark the name here so that a struct containing a pointer to + itself will work. */ + if (name != NULL) + name->mark = info->mark; + + tag = NULL; + if (name != NULL + && type->kind != DEBUG_KIND_NAMED + && type->kind != DEBUG_KIND_TAGGED) + { + assert (name->kind == DEBUG_OBJECT_TAG); + tag = name->name; + } + + switch (type->kind) + { + case DEBUG_KIND_ILLEGAL: + debug_error (_("debug_write_type: illegal type encountered")); + return false; + case DEBUG_KIND_INDIRECT: + if (*type->u.kindirect->slot == DEBUG_TYPE_NULL) + return (*fns->empty_type) (fhandle); + return debug_write_type (info, fns, fhandle, *type->u.kindirect->slot, + name); + case DEBUG_KIND_VOID: + return (*fns->void_type) (fhandle); + case DEBUG_KIND_INT: + return (*fns->int_type) (fhandle, type->size, type->u.kint); + case DEBUG_KIND_FLOAT: + return (*fns->float_type) (fhandle, type->size); + case DEBUG_KIND_COMPLEX: + return (*fns->complex_type) (fhandle, type->size); + case DEBUG_KIND_BOOL: + return (*fns->bool_type) (fhandle, type->size); + case DEBUG_KIND_STRUCT: + case DEBUG_KIND_UNION: + if (type->u.kclass != NULL) + { + if (type->u.kclass->id <= info->base_id) + { + if (! debug_set_class_id (info, tag, type)) + return false; + } + + if (info->mark == type->u.kclass->mark) + { + /* We are currently outputting this struct, or we have + already output it. I don't know if this can happen, + but it can happen for a class. */ + assert (type->u.kclass->id > info->base_id); + return (*fns->tag_type) (fhandle, tag, type->u.kclass->id, + type->kind); + } + type->u.kclass->mark = info->mark; + } + + if (! (*fns->start_struct_type) (fhandle, tag, + (type->u.kclass != NULL + ? type->u.kclass->id + : 0), + type->kind == DEBUG_KIND_STRUCT, + type->size)) + return false; + if (type->u.kclass != NULL + && type->u.kclass->fields != NULL) + { + for (i = 0; type->u.kclass->fields[i] != NULL; i++) + { + struct debug_field *f; + + f = type->u.kclass->fields[i]; + if (! debug_write_type (info, fns, fhandle, f->type, + (struct debug_name *) NULL) + || ! (*fns->struct_field) (fhandle, f->name, f->u.f.bitpos, + f->u.f.bitsize, f->visibility)) + return false; + } + } + return (*fns->end_struct_type) (fhandle); + case DEBUG_KIND_CLASS: + case DEBUG_KIND_UNION_CLASS: + return debug_write_class_type (info, fns, fhandle, type, tag); + case DEBUG_KIND_ENUM: + if (type->u.kenum == NULL) + return (*fns->enum_type) (fhandle, tag, (const char **) NULL, + (bfd_signed_vma *) NULL); + return (*fns->enum_type) (fhandle, tag, type->u.kenum->names, + type->u.kenum->values); + case DEBUG_KIND_POINTER: + if (! debug_write_type (info, fns, fhandle, type->u.kpointer, + (struct debug_name *) NULL)) + return false; + return (*fns->pointer_type) (fhandle); + case DEBUG_KIND_FUNCTION: + if (! debug_write_type (info, fns, fhandle, + type->u.kfunction->return_type, + (struct debug_name *) NULL)) + return false; + if (type->u.kfunction->arg_types == NULL) + is = -1; + else + { + for (is = 0; type->u.kfunction->arg_types[is] != NULL; is++) + if (! debug_write_type (info, fns, fhandle, + type->u.kfunction->arg_types[is], + (struct debug_name *) NULL)) + return false; + } + return (*fns->function_type) (fhandle, is, + type->u.kfunction->varargs); + case DEBUG_KIND_REFERENCE: + if (! debug_write_type (info, fns, fhandle, type->u.kreference, + (struct debug_name *) NULL)) + return false; + return (*fns->reference_type) (fhandle); + case DEBUG_KIND_RANGE: + if (! debug_write_type (info, fns, fhandle, type->u.krange->type, + (struct debug_name *) NULL)) + return false; + return (*fns->range_type) (fhandle, type->u.krange->lower, + type->u.krange->upper); + case DEBUG_KIND_ARRAY: + if (! debug_write_type (info, fns, fhandle, type->u.karray->element_type, + (struct debug_name *) NULL) + || ! debug_write_type (info, fns, fhandle, + type->u.karray->range_type, + (struct debug_name *) NULL)) + return false; + return (*fns->array_type) (fhandle, type->u.karray->lower, + type->u.karray->upper, + type->u.karray->stringp); + case DEBUG_KIND_SET: + if (! debug_write_type (info, fns, fhandle, type->u.kset->type, + (struct debug_name *) NULL)) + return false; + return (*fns->set_type) (fhandle, type->u.kset->bitstringp); + case DEBUG_KIND_OFFSET: + if (! debug_write_type (info, fns, fhandle, type->u.koffset->base_type, + (struct debug_name *) NULL) + || ! debug_write_type (info, fns, fhandle, + type->u.koffset->target_type, + (struct debug_name *) NULL)) + return false; + return (*fns->offset_type) (fhandle); + case DEBUG_KIND_METHOD: + if (! debug_write_type (info, fns, fhandle, + type->u.kmethod->return_type, + (struct debug_name *) NULL)) + return false; + if (type->u.kmethod->arg_types == NULL) + is = -1; + else + { + for (is = 0; type->u.kmethod->arg_types[is] != NULL; is++) + if (! debug_write_type (info, fns, fhandle, + type->u.kmethod->arg_types[is], + (struct debug_name *) NULL)) + return false; + } + if (type->u.kmethod->domain_type != NULL) + { + if (! debug_write_type (info, fns, fhandle, + type->u.kmethod->domain_type, + (struct debug_name *) NULL)) + return false; + } + return (*fns->method_type) (fhandle, + type->u.kmethod->domain_type != NULL, + is, + type->u.kmethod->varargs); + case DEBUG_KIND_CONST: + if (! debug_write_type (info, fns, fhandle, type->u.kconst, + (struct debug_name *) NULL)) + return false; + return (*fns->const_type) (fhandle); + case DEBUG_KIND_VOLATILE: + if (! debug_write_type (info, fns, fhandle, type->u.kvolatile, + (struct debug_name *) NULL)) + return false; + return (*fns->volatile_type) (fhandle); + case DEBUG_KIND_NAMED: + return debug_write_type (info, fns, fhandle, type->u.knamed->type, + (struct debug_name *) NULL); + case DEBUG_KIND_TAGGED: + return debug_write_type (info, fns, fhandle, type->u.knamed->type, + type->u.knamed->name); + default: + abort (); + return false; + } +} + +/* Write out a class type. */ + +static boolean +debug_write_class_type (info, fns, fhandle, type, tag) + struct debug_handle *info; + const struct debug_write_fns *fns; + PTR fhandle; + struct debug_type *type; + const char *tag; +{ + unsigned int i; + unsigned int id; + struct debug_type *vptrbase; + + if (type->u.kclass == NULL) + { + id = 0; + vptrbase = NULL; + } + else + { + if (type->u.kclass->id <= info->base_id) + { + if (! debug_set_class_id (info, tag, type)) + return false; + } + + if (info->mark == type->u.kclass->mark) + { + /* We are currently outputting this class, or we have + already output it. This can happen when there are + methods for an anonymous class. */ + assert (type->u.kclass->id > info->base_id); + return (*fns->tag_type) (fhandle, tag, type->u.kclass->id, + type->kind); + } + type->u.kclass->mark = info->mark; + id = type->u.kclass->id; + + vptrbase = type->u.kclass->vptrbase; + if (vptrbase != NULL && vptrbase != type) + { + if (! debug_write_type (info, fns, fhandle, vptrbase, + (struct debug_name *) NULL)) + return false; + } + } + + if (! (*fns->start_class_type) (fhandle, tag, id, + type->kind == DEBUG_KIND_CLASS, + type->size, + vptrbase != NULL, + vptrbase == type)) + return false; + + if (type->u.kclass != NULL) + { + if (type->u.kclass->fields != NULL) + { + for (i = 0; type->u.kclass->fields[i] != NULL; i++) + { + struct debug_field *f; + + f = type->u.kclass->fields[i]; + if (! debug_write_type (info, fns, fhandle, f->type, + (struct debug_name *) NULL)) + return false; + if (f->static_member) + { + if (! (*fns->class_static_member) (fhandle, f->name, + f->u.s.physname, + f->visibility)) + return false; + } + else + { + if (! (*fns->struct_field) (fhandle, f->name, f->u.f.bitpos, + f->u.f.bitsize, f->visibility)) + return false; + } + } + } + + if (type->u.kclass->baseclasses != NULL) + { + for (i = 0; type->u.kclass->baseclasses[i] != NULL; i++) + { + struct debug_baseclass *b; + + b = type->u.kclass->baseclasses[i]; + if (! debug_write_type (info, fns, fhandle, b->type, + (struct debug_name *) NULL)) + return false; + if (! (*fns->class_baseclass) (fhandle, b->bitpos, b->virtual, + b->visibility)) + return false; + } + } + + if (type->u.kclass->methods != NULL) + { + for (i = 0; type->u.kclass->methods[i] != NULL; i++) + { + struct debug_method *m; + unsigned int j; + + m = type->u.kclass->methods[i]; + if (! (*fns->class_start_method) (fhandle, m->name)) + return false; + for (j = 0; m->variants[j] != NULL; j++) + { + struct debug_method_variant *v; + + v = m->variants[j]; + if (v->context != NULL) + { + if (! debug_write_type (info, fns, fhandle, v->context, + (struct debug_name *) NULL)) + return false; + } + if (! debug_write_type (info, fns, fhandle, v->type, + (struct debug_name *) NULL)) + return false; + if (v->voffset != VOFFSET_STATIC_METHOD) + { + if (! (*fns->class_method_variant) (fhandle, v->physname, + v->visibility, + v->constp, + v->volatilep, + v->voffset, + v->context != NULL)) + return false; + } + else + { + if (! (*fns->class_static_method_variant) (fhandle, + v->physname, + v->visibility, + v->constp, + v->volatilep)) + return false; + } + } + if (! (*fns->class_end_method) (fhandle)) + return false; + } + } + } + + return (*fns->end_class_type) (fhandle); +} + +/* Write out information for a function. */ + +static boolean +debug_write_function (info, fns, fhandle, name, linkage, function) + struct debug_handle *info; + const struct debug_write_fns *fns; + PTR fhandle; + const char *name; + enum debug_object_linkage linkage; + struct debug_function *function; +{ + struct debug_parameter *p; + struct debug_block *b; + + if (! debug_write_linenos (info, fns, fhandle, function->blocks->start)) + return false; + + if (! debug_write_type (info, fns, fhandle, function->return_type, + (struct debug_name *) NULL)) + return false; + + if (! (*fns->start_function) (fhandle, name, + linkage == DEBUG_LINKAGE_GLOBAL)) + return false; + + for (p = function->parameters; p != NULL; p = p->next) + { + if (! debug_write_type (info, fns, fhandle, p->type, + (struct debug_name *) NULL) + || ! (*fns->function_parameter) (fhandle, p->name, p->kind, p->val)) + return false; + } + + for (b = function->blocks; b != NULL; b = b->next) + { + if (! debug_write_block (info, fns, fhandle, b)) + return false; + } + + return (*fns->end_function) (fhandle); +} + +/* Write out information for a block. */ + +static boolean +debug_write_block (info, fns, fhandle, block) + struct debug_handle *info; + const struct debug_write_fns *fns; + PTR fhandle; + struct debug_block *block; +{ + struct debug_name *n; + struct debug_block *b; + + if (! debug_write_linenos (info, fns, fhandle, block->start)) + return false; + + /* I can't see any point to writing out a block with no local + variables, so we don't bother, except for the top level block. */ + if (block->locals != NULL || block->parent == NULL) + { + if (! (*fns->start_block) (fhandle, block->start)) + return false; + } + + if (block->locals != NULL) + { + for (n = block->locals->list; n != NULL; n = n->next) + { + if (! debug_write_name (info, fns, fhandle, n)) + return false; + } + } + + for (b = block->children; b != NULL; b = b->next) + { + if (! debug_write_block (info, fns, fhandle, b)) + return false; + } + + if (! debug_write_linenos (info, fns, fhandle, block->end)) + return false; + + if (block->locals != NULL || block->parent == NULL) + { + if (! (*fns->end_block) (fhandle, block->end)) + return false; + } + + return true; +} + +/* Write out line number information up to ADDRESS. */ + +static boolean +debug_write_linenos (info, fns, fhandle, address) + struct debug_handle *info; + const struct debug_write_fns *fns; + PTR fhandle; + bfd_vma address; +{ + while (info->current_write_lineno != NULL) + { + struct debug_lineno *l; + + l = info->current_write_lineno; + + while (info->current_write_lineno_index < DEBUG_LINENO_COUNT) + { + if (l->linenos[info->current_write_lineno_index] + == (unsigned long) -1) + break; + + if (l->addrs[info->current_write_lineno_index] >= address) + return true; + + if (! (*fns->lineno) (fhandle, l->file->filename, + l->linenos[info->current_write_lineno_index], + l->addrs[info->current_write_lineno_index])) + return false; + + ++info->current_write_lineno_index; + } + + info->current_write_lineno = l->next; + info->current_write_lineno_index = 0; + } + + return true; +} + +/* Get the ID number for a class. If during the same call to + debug_write we find a struct with the same definition with the same + name, we use the same ID. This type of things happens because the + same struct will be defined by multiple compilation units. */ + +static boolean +debug_set_class_id (info, tag, type) + struct debug_handle *info; + const char *tag; + struct debug_type *type; +{ + struct debug_class_type *c; + struct debug_class_id *l; + + assert (type->kind == DEBUG_KIND_STRUCT + || type->kind == DEBUG_KIND_UNION + || type->kind == DEBUG_KIND_CLASS + || type->kind == DEBUG_KIND_UNION_CLASS); + + c = type->u.kclass; + + if (c->id > info->base_id) + return true; + + for (l = info->id_list; l != NULL; l = l->next) + { + if (l->type->kind != type->kind) + continue; + + if (tag == NULL) + { + if (l->tag != NULL) + continue; + } + else + { + if (l->tag == NULL + || l->tag[0] != tag[0] + || strcmp (l->tag, tag) != 0) + continue; + } + + if (debug_type_samep (info, l->type, type)) + { + c->id = l->type->u.kclass->id; + return true; + } + } + + /* There are no identical types. Use a new ID, and add it to the + list. */ + ++info->class_id; + c->id = info->class_id; + + l = (struct debug_class_id *) xmalloc (sizeof *l); + memset (l, 0, sizeof *l); + + l->type = type; + l->tag = tag; + + l->next = info->id_list; + info->id_list = l; + + return true; +} + +/* See if two types are the same. At this point, we don't care about + tags and the like. */ + +static boolean +debug_type_samep (info, t1, t2) + struct debug_handle *info; + struct debug_type *t1; + struct debug_type *t2; +{ + struct debug_type_compare_list *l; + struct debug_type_compare_list top; + boolean ret; + + if (t1 == NULL) + return t2 == NULL; + if (t2 == NULL) + return false; + + while (t1->kind == DEBUG_KIND_INDIRECT) + { + t1 = *t1->u.kindirect->slot; + if (t1 == NULL) + return false; + } + while (t2->kind == DEBUG_KIND_INDIRECT) + { + t2 = *t2->u.kindirect->slot; + if (t2 == NULL) + return false; + } + + if (t1 == t2) + return true; + + /* As a special case, permit a typedef to match a tag, since C++ + debugging output will sometimes add a typedef where C debugging + output will not. */ + if (t1->kind == DEBUG_KIND_NAMED + && t2->kind == DEBUG_KIND_TAGGED) + return debug_type_samep (info, t1->u.knamed->type, t2); + else if (t1->kind == DEBUG_KIND_TAGGED + && t2->kind == DEBUG_KIND_NAMED) + return debug_type_samep (info, t1, t2->u.knamed->type); + + if (t1->kind != t2->kind + || t1->size != t2->size) + return false; + + /* Get rid of the trivial cases first. */ + switch (t1->kind) + { + default: + break; + case DEBUG_KIND_VOID: + case DEBUG_KIND_FLOAT: + case DEBUG_KIND_COMPLEX: + case DEBUG_KIND_BOOL: + return true; + case DEBUG_KIND_INT: + return t1->u.kint == t2->u.kint; + } + + /* We have to avoid an infinite recursion. We do this by keeping a + list of types which we are comparing. We just keep the list on + the stack. If we encounter a pair of types we are currently + comparing, we just assume that they are equal. */ + for (l = info->compare_list; l != NULL; l = l->next) + { + if (l->t1 == t1 && l->t2 == t2) + return true; + } + + top.t1 = t1; + top.t2 = t2; + top.next = info->compare_list; + info->compare_list = ⊤ + + switch (t1->kind) + { + default: + abort (); + ret = false; + break; + + case DEBUG_KIND_STRUCT: + case DEBUG_KIND_UNION: + case DEBUG_KIND_CLASS: + case DEBUG_KIND_UNION_CLASS: + if (t1->u.kclass == NULL) + ret = t2->u.kclass == NULL; + else if (t2->u.kclass == NULL) + ret = false; + else if (t1->u.kclass->id > info->base_id + && t1->u.kclass->id == t2->u.kclass->id) + ret = true; + else + ret = debug_class_type_samep (info, t1, t2); + break; + + case DEBUG_KIND_ENUM: + if (t1->u.kenum == NULL) + ret = t2->u.kenum == NULL; + else if (t2->u.kenum == NULL) + ret = false; + else + { + const char **pn1, **pn2; + bfd_signed_vma *pv1, *pv2; + + pn1 = t1->u.kenum->names; + pn2 = t2->u.kenum->names; + pv1 = t1->u.kenum->values; + pv2 = t2->u.kenum->values; + while (*pn1 != NULL && *pn2 != NULL) + { + if (**pn1 != **pn2 + || *pv1 != *pv2 + || strcmp (*pn1, *pn2) != 0) + break; + ++pn1; + ++pn2; + ++pv1; + ++pv2; + } + ret = *pn1 == NULL && *pn2 == NULL; + } + break; + + case DEBUG_KIND_POINTER: + ret = debug_type_samep (info, t1->u.kpointer, t2->u.kpointer); + break; + + case DEBUG_KIND_FUNCTION: + if (t1->u.kfunction->varargs != t2->u.kfunction->varargs + || ! debug_type_samep (info, t1->u.kfunction->return_type, + t2->u.kfunction->return_type) + || ((t1->u.kfunction->arg_types == NULL) + != (t2->u.kfunction->arg_types == NULL))) + ret = false; + else if (t1->u.kfunction->arg_types == NULL) + ret = true; + else + { + struct debug_type **a1, **a2; + + a1 = t1->u.kfunction->arg_types; + a2 = t2->u.kfunction->arg_types; + while (*a1 != NULL && *a2 != NULL) + { + if (! debug_type_samep (info, *a1, *a2)) + break; + ++a1; + ++a2; + } + ret = *a1 == NULL && *a2 == NULL; + } + break; + + case DEBUG_KIND_REFERENCE: + ret = debug_type_samep (info, t1->u.kreference, t2->u.kreference); + break; + + case DEBUG_KIND_RANGE: + ret = (t1->u.krange->lower == t2->u.krange->lower + && t1->u.krange->upper == t2->u.krange->upper + && debug_type_samep (info, t1->u.krange->type, + t2->u.krange->type)); + + case DEBUG_KIND_ARRAY: + ret = (t1->u.karray->lower == t2->u.karray->lower + && t1->u.karray->upper == t2->u.karray->upper + && t1->u.karray->stringp == t2->u.karray->stringp + && debug_type_samep (info, t1->u.karray->element_type, + t2->u.karray->element_type)); + break; + + case DEBUG_KIND_SET: + ret = (t1->u.kset->bitstringp == t2->u.kset->bitstringp + && debug_type_samep (info, t1->u.kset->type, t2->u.kset->type)); + break; + + case DEBUG_KIND_OFFSET: + ret = (debug_type_samep (info, t1->u.koffset->base_type, + t2->u.koffset->base_type) + && debug_type_samep (info, t1->u.koffset->target_type, + t2->u.koffset->target_type)); + break; + + case DEBUG_KIND_METHOD: + if (t1->u.kmethod->varargs != t2->u.kmethod->varargs + || ! debug_type_samep (info, t1->u.kmethod->return_type, + t2->u.kmethod->return_type) + || ! debug_type_samep (info, t1->u.kmethod->domain_type, + t2->u.kmethod->domain_type) + || ((t1->u.kmethod->arg_types == NULL) + != (t2->u.kmethod->arg_types == NULL))) + ret = false; + else if (t1->u.kmethod->arg_types == NULL) + ret = true; + else + { + struct debug_type **a1, **a2; + + a1 = t1->u.kmethod->arg_types; + a2 = t2->u.kmethod->arg_types; + while (*a1 != NULL && *a2 != NULL) + { + if (! debug_type_samep (info, *a1, *a2)) + break; + ++a1; + ++a2; + } + ret = *a1 == NULL && *a2 == NULL; + } + break; + + case DEBUG_KIND_CONST: + ret = debug_type_samep (info, t1->u.kconst, t2->u.kconst); + break; + + case DEBUG_KIND_VOLATILE: + ret = debug_type_samep (info, t1->u.kvolatile, t2->u.kvolatile); + break; + + case DEBUG_KIND_NAMED: + case DEBUG_KIND_TAGGED: + ret = (strcmp (t1->u.knamed->name->name, t2->u.knamed->name->name) == 0 + && debug_type_samep (info, t1->u.knamed->type, + t2->u.knamed->type)); + break; + } + + info->compare_list = top.next; + + return ret; +} + +/* See if two classes are the same. This is a subroutine of + debug_type_samep. */ + +static boolean +debug_class_type_samep (info, t1, t2) + struct debug_handle *info; + struct debug_type *t1; + struct debug_type *t2; +{ + struct debug_class_type *c1, *c2; + + c1 = t1->u.kclass; + c2 = t2->u.kclass; + + if ((c1->fields == NULL) != (c2->fields == NULL) + || (c1->baseclasses == NULL) != (c2->baseclasses == NULL) + || (c1->methods == NULL) != (c2->methods == NULL) + || (c1->vptrbase == NULL) != (c2->vptrbase == NULL)) + return false; + + if (c1->fields != NULL) + { + struct debug_field **pf1, **pf2; + + for (pf1 = c1->fields, pf2 = c2->fields; + *pf1 != NULL && *pf2 != NULL; + pf1++, pf2++) + { + struct debug_field *f1, *f2; + + f1 = *pf1; + f2 = *pf2; + if (f1->name[0] != f2->name[0] + || f1->visibility != f2->visibility + || f1->static_member != f2->static_member) + return false; + if (f1->static_member) + { + if (strcmp (f1->u.s.physname, f2->u.s.physname) != 0) + return false; + } + else + { + if (f1->u.f.bitpos != f2->u.f.bitpos + || f1->u.f.bitsize != f2->u.f.bitsize) + return false; + } + /* We do the checks which require function calls last. We + don't require that the types of fields have the same + names, since that sometimes fails in the presence of + typedefs and we really don't care. */ + if (strcmp (f1->name, f2->name) != 0 + || ! debug_type_samep (info, + debug_get_real_type ((PTR) info, + f1->type, NULL), + debug_get_real_type ((PTR) info, + f2->type, NULL))) + return false; + } + if (*pf1 != NULL || *pf2 != NULL) + return false; + } + + if (c1->vptrbase != NULL) + { + if (! debug_type_samep (info, c1->vptrbase, c2->vptrbase)) + return false; + } + + if (c1->baseclasses != NULL) + { + struct debug_baseclass **pb1, **pb2; + + for (pb1 = c1->baseclasses, pb2 = c2->baseclasses; + *pb1 != NULL && *pb2 != NULL; + ++pb1, ++pb2) + { + struct debug_baseclass *b1, *b2; + + b1 = *pb1; + b2 = *pb2; + if (b1->bitpos != b2->bitpos + || b1->virtual != b2->virtual + || b1->visibility != b2->visibility + || ! debug_type_samep (info, b1->type, b2->type)) + return false; + } + if (*pb1 != NULL || *pb2 != NULL) + return false; + } + + if (c1->methods != NULL) + { + struct debug_method **pm1, **pm2; + + for (pm1 = c1->methods, pm2 = c2->methods; + *pm1 != NULL && *pm2 != NULL; + ++pm1, ++pm2) + { + struct debug_method *m1, *m2; + + m1 = *pm1; + m2 = *pm2; + if (m1->name[0] != m2->name[0] + || strcmp (m1->name, m2->name) != 0 + || (m1->variants == NULL) != (m2->variants == NULL)) + return false; + if (m1->variants == NULL) + { + struct debug_method_variant **pv1, **pv2; + + for (pv1 = m1->variants, pv2 = m2->variants; + *pv1 != NULL && *pv2 != NULL; + ++pv1, ++pv2) + { + struct debug_method_variant *v1, *v2; + + v1 = *pv1; + v2 = *pv2; + if (v1->physname[0] != v2->physname[0] + || v1->visibility != v2->visibility + || v1->constp != v2->constp + || v1->volatilep != v2->volatilep + || v1->voffset != v2->voffset + || (v1->context == NULL) != (v2->context == NULL) + || strcmp (v1->physname, v2->physname) != 0 + || ! debug_type_samep (info, v1->type, v2->type)) + return false; + if (v1->context != NULL) + { + if (! debug_type_samep (info, v1->context, + v2->context)) + return false; + } + } + if (*pv1 != NULL || *pv2 != NULL) + return false; + } + } + if (*pm1 != NULL || *pm2 != NULL) + return false; + } + + return true; +} diff --git a/binutils/debug.h b/binutils/debug.h new file mode 100644 index 0000000..1b890b2 --- /dev/null +++ b/binutils/debug.h @@ -0,0 +1,798 @@ +/* debug.h -- Describe generic debugging information. + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Written by Ian Lance Taylor <ian@cygnus.com>. + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifndef DEBUG_H +#define DEBUG_H + +/* This header file describes a generic debugging information format. + We may eventually have readers which convert different formats into + this generic format, and writers which write it out. The initial + impetus for this was writing a convertor from stabs to HP IEEE-695 + debugging format. */ + +/* Different kinds of types. */ + +enum debug_type_kind +{ + /* Not used. */ + DEBUG_KIND_ILLEGAL, + /* Indirect via a pointer. */ + DEBUG_KIND_INDIRECT, + /* Void. */ + DEBUG_KIND_VOID, + /* Integer. */ + DEBUG_KIND_INT, + /* Floating point. */ + DEBUG_KIND_FLOAT, + /* Complex. */ + DEBUG_KIND_COMPLEX, + /* Boolean. */ + DEBUG_KIND_BOOL, + /* Struct. */ + DEBUG_KIND_STRUCT, + /* Union. */ + DEBUG_KIND_UNION, + /* Class. */ + DEBUG_KIND_CLASS, + /* Union class (can this really happen?). */ + DEBUG_KIND_UNION_CLASS, + /* Enumeration type. */ + DEBUG_KIND_ENUM, + /* Pointer. */ + DEBUG_KIND_POINTER, + /* Function. */ + DEBUG_KIND_FUNCTION, + /* Reference. */ + DEBUG_KIND_REFERENCE, + /* Range. */ + DEBUG_KIND_RANGE, + /* Array. */ + DEBUG_KIND_ARRAY, + /* Set. */ + DEBUG_KIND_SET, + /* Based pointer. */ + DEBUG_KIND_OFFSET, + /* Method. */ + DEBUG_KIND_METHOD, + /* Const qualified type. */ + DEBUG_KIND_CONST, + /* Volatile qualified type. */ + DEBUG_KIND_VOLATILE, + /* Named type. */ + DEBUG_KIND_NAMED, + /* Tagged type. */ + DEBUG_KIND_TAGGED +}; + +/* Different kinds of variables. */ + +enum debug_var_kind +{ + /* Not used. */ + DEBUG_VAR_ILLEGAL, + /* A global variable. */ + DEBUG_GLOBAL, + /* A static variable. */ + DEBUG_STATIC, + /* A local static variable. */ + DEBUG_LOCAL_STATIC, + /* A local variable. */ + DEBUG_LOCAL, + /* A register variable. */ + DEBUG_REGISTER +}; + +/* Different kinds of function parameters. */ + +enum debug_parm_kind +{ + /* Not used. */ + DEBUG_PARM_ILLEGAL, + /* A stack based parameter. */ + DEBUG_PARM_STACK, + /* A register parameter. */ + DEBUG_PARM_REG, + /* A stack based reference parameter. */ + DEBUG_PARM_REFERENCE, + /* A register reference parameter. */ + DEBUG_PARM_REF_REG +}; + +/* Different kinds of visibility. */ + +enum debug_visibility +{ + /* A public field (e.g., a field in a C struct). */ + DEBUG_VISIBILITY_PUBLIC, + /* A protected field. */ + DEBUG_VISIBILITY_PROTECTED, + /* A private field. */ + DEBUG_VISIBILITY_PRIVATE, + /* A field which should be ignored. */ + DEBUG_VISIBILITY_IGNORE +}; + +/* A type. */ + +typedef struct debug_type *debug_type; + +#define DEBUG_TYPE_NULL ((debug_type) NULL) + +/* A field in a struct or union. */ + +typedef struct debug_field *debug_field; + +#define DEBUG_FIELD_NULL ((debug_field) NULL) + +/* A base class for an object. */ + +typedef struct debug_baseclass *debug_baseclass; + +#define DEBUG_BASECLASS_NULL ((debug_baseclass) NULL) + +/* A method of an object. */ + +typedef struct debug_method *debug_method; + +#define DEBUG_METHOD_NULL ((debug_method) NULL) + +/* The arguments to a method function of an object. These indicate + which method to run. */ + +typedef struct debug_method_variant *debug_method_variant; + +#define DEBUG_METHOD_VARIANT_NULL ((debug_method_variant) NULL) + +/* This structure is passed to debug_write. It holds function + pointers that debug_write will call based on the accumulated + debugging information. */ + +struct debug_write_fns +{ + /* This is called at the start of each new compilation unit with the + name of the main file in the new unit. */ + boolean (*start_compilation_unit) PARAMS ((PTR, const char *)); + + /* This is called at the start of each source file within a + compilation unit, before outputting any global information for + that file. The argument is the name of the file. */ + boolean (*start_source) PARAMS ((PTR, const char *)); + + /* Each writer must keep a stack of types. */ + + /* Push an empty type onto the type stack. This type can appear if + there is a reference to a type which is never defined. */ + boolean (*empty_type) PARAMS ((PTR)); + + /* Push a void type onto the type stack. */ + boolean (*void_type) PARAMS ((PTR)); + + /* Push an integer type onto the type stack, given the size and + whether it is unsigned. */ + boolean (*int_type) PARAMS ((PTR, unsigned int, boolean)); + + /* Push a floating type onto the type stack, given the size. */ + boolean (*float_type) PARAMS ((PTR, unsigned int)); + + /* Push a complex type onto the type stack, given the size. */ + boolean (*complex_type) PARAMS ((PTR, unsigned int)); + + /* Push a boolean type onto the type stack, given the size. */ + boolean (*bool_type) PARAMS ((PTR, unsigned int)); + + /* Push an enum type onto the type stack, given the tag, a NULL + terminated array of names and the associated values. If there is + no tag, the tag argument will be NULL. If this is an undefined + enum, the names and values arguments will be NULL. */ + boolean (*enum_type) PARAMS ((PTR, const char *, const char **, + bfd_signed_vma *)); + + /* Pop the top type on the type stack, and push a pointer to that + type onto the type stack. */ + boolean (*pointer_type) PARAMS ((PTR)); + + /* Push a function type onto the type stack. The second argument + indicates the number of argument types that have been pushed onto + the stack. If the number of argument types is passed as -1, then + the argument types of the function are unknown, and no types have + been pushed onto the stack. The third argument is true if the + function takes a variable number of arguments. The return type + of the function is pushed onto the type stack below the argument + types, if any. */ + boolean (*function_type) PARAMS ((PTR, int, boolean)); + + /* Pop the top type on the type stack, and push a reference to that + type onto the type stack. */ + boolean (*reference_type) PARAMS ((PTR)); + + /* Pop the top type on the type stack, and push a range of that type + with the given lower and upper bounds onto the type stack. */ + boolean (*range_type) PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma)); + + /* Push an array type onto the type stack. The top type on the type + stack is the range, and the next type on the type stack is the + element type. These should be popped before the array type is + pushed. The arguments are the lower bound, the upper bound, and + whether the array is a string. */ + boolean (*array_type) PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma, + boolean)); + + /* Pop the top type on the type stack, and push a set of that type + onto the type stack. The argument indicates whether this set is + a bitstring. */ + boolean (*set_type) PARAMS ((PTR, boolean)); + + /* Push an offset type onto the type stack. The top type on the + type stack is the target type, and the next type on the type + stack is the base type. These should be popped before the offset + type is pushed. */ + boolean (*offset_type) PARAMS ((PTR)); + + /* Push a method type onto the type stack. If the second argument + is true, the top type on the stack is the class to which the + method belongs; otherwise, the class must be determined by the + class to which the method is attached. The third argument is the + number of argument types; these are pushed onto the type stack in + reverse order (the first type popped is the last argument to the + method). A value of -1 for the third argument means that no + argument information is available. The fourth argument is true + if the function takes a variable number of arguments. The next + type on the type stack below the domain and the argument types is + the return type of the method. All these types must be popped, + and then the method type must be pushed. */ + boolean (*method_type) PARAMS ((PTR, boolean, int, boolean)); + + /* Pop the top type off the type stack, and push a const qualified + version of that type onto the type stack. */ + boolean (*const_type) PARAMS ((PTR)); + + /* Pop the top type off the type stack, and push a volatile + qualified version of that type onto the type stack. */ + boolean (*volatile_type) PARAMS ((PTR)); + + /* Start building a struct. This is followed by calls to the + struct_field function, and finished by a call to the + end_struct_type function. The second argument is the tag; this + will be NULL if there isn't one. If the second argument is NULL, + the third argument is a constant identifying this struct for use + with tag_type. The fourth argument is true for a struct, false + for a union. The fifth argument is the size. If this is an + undefined struct or union, the size will be 0 and struct_field + will not be called before end_struct_type is called. */ + boolean (*start_struct_type) PARAMS ((PTR, const char *, unsigned int, + boolean, unsigned int)); + + /* Add a field to the struct type currently being built. The type + of the field should be popped off the type stack. The arguments + are the name, the bit position, the bit size (may be zero if the + field is not packed), and the visibility. */ + boolean (*struct_field) PARAMS ((PTR, const char *, bfd_vma, bfd_vma, + enum debug_visibility)); + + /* Finish building a struct, and push it onto the type stack. */ + boolean (*end_struct_type) PARAMS ((PTR)); + + /* Start building a class. This is followed by calls to several + functions: struct_field, class_static_member, class_baseclass, + class_start_method, class_method_variant, + class_static_method_variant, and class_end_method. The class is + finished by a call to end_class_type. The first five arguments + are the same as for start_struct_type. The sixth argument is + true if there is a virtual function table; if there is, the + seventh argument is true if the virtual function table can be + found in the type itself, and is false if the type of the object + holding the virtual function table should be popped from the type + stack. */ + boolean (*start_class_type) PARAMS ((PTR, const char *, unsigned int, + boolean, unsigned int, boolean, + boolean)); + + /* Add a static member to the class currently being built. The + arguments are the field name, the physical name, and the + visibility. The type must be popped off the type stack. */ + boolean (*class_static_member) PARAMS ((PTR, const char *, const char *, + enum debug_visibility)); + + /* Add a baseclass to the class currently being built. The type of + the baseclass must be popped off the type stack. The arguments + are the bit position, whether the class is virtual, and the + visibility. */ + boolean (*class_baseclass) PARAMS ((PTR, bfd_vma, boolean, + enum debug_visibility)); + + /* Start adding a method to the class currently being built. This + is followed by calls to class_method_variant and + class_static_method_variant to describe different variants of the + method which take different arguments. The method is finished + with a call to class_end_method. The argument is the method + name. */ + boolean (*class_start_method) PARAMS ((PTR, const char *)); + + /* Describe a variant to the class method currently being built. + The type of the variant must be popped off the type stack. The + second argument is the physical name of the function. The + following arguments are the visibility, whether the variant is + const, whether the variant is volatile, the offset in the virtual + function table, and whether the context is on the type stack + (below the variant type). */ + boolean (*class_method_variant) PARAMS ((PTR, const char *, + enum debug_visibility, + boolean, boolean, + bfd_vma, boolean)); + + /* Describe a static variant to the class method currently being + built. The arguments are the same as for class_method_variant, + except that the last two arguments are omitted. The type of the + variant must be popped off the type stack. */ + boolean (*class_static_method_variant) PARAMS ((PTR, const char *, + enum debug_visibility, + boolean, boolean)); + + /* Finish describing a class method. */ + boolean (*class_end_method) PARAMS ((PTR)); + + /* Finish describing a class, and push it onto the type stack. */ + boolean (*end_class_type) PARAMS ((PTR)); + + /* Push a type on the stack which was given a name by an earlier + call to typdef. */ + boolean (*typedef_type) PARAMS ((PTR, const char *)); + + /* Push a tagged type on the stack which was defined earlier. If + the second argument is not NULL, the type was defined by a call + to tag. If the second argument is NULL, the type was defined by + a call to start_struct_type or start_class_type with a tag of + NULL and the number of the third argument. Either way, the + fourth argument is the tag kind. Note that this may be called + for a struct (class) being defined, in between the call to + start_struct_type (start_class_type) and the call to + end_struct_type (end_class_type). */ + boolean (*tag_type) PARAMS ((PTR, const char *, unsigned int, + enum debug_type_kind)); + + /* Pop the type stack, and typedef it to the given name. */ + boolean (*typdef) PARAMS ((PTR, const char *)); + + /* Pop the type stack, and declare it as a tagged struct or union or + enum or whatever. The tag passed down here is redundant, since + was also passed when enum_type, start_struct_type, or + start_class_type was called. */ + boolean (*tag) PARAMS ((PTR, const char *)); + + /* This is called to record a named integer constant. */ + boolean (*int_constant) PARAMS ((PTR, const char *, bfd_vma)); + + /* This is called to record a named floating point constant. */ + boolean (*float_constant) PARAMS ((PTR, const char *, double)); + + /* This is called to record a typed integer constant. The type is + popped off the type stack. */ + boolean (*typed_constant) PARAMS ((PTR, const char *, bfd_vma)); + + /* This is called to record a variable. The type is popped off the + type stack. */ + boolean (*variable) PARAMS ((PTR, const char *, enum debug_var_kind, + bfd_vma)); + + /* Start writing out a function. The return type must be popped off + the stack. The boolean is true if the function is global. This + is followed by calls to function_parameter, followed by block + information. */ + boolean (*start_function) PARAMS ((PTR, const char *, boolean)); + + /* Record a function parameter for the current function. The type + must be popped off the stack. */ + boolean (*function_parameter) PARAMS ((PTR, const char *, + enum debug_parm_kind, bfd_vma)); + + /* Start writing out a block. There is at least one top level block + per function. Blocks may be nested. The argument is the + starting address of the block. */ + boolean (*start_block) PARAMS ((PTR, bfd_vma)); + + /* Finish writing out a block. The argument is the ending address + of the block. */ + boolean (*end_block) PARAMS ((PTR, bfd_vma)); + + /* Finish writing out a function. */ + boolean (*end_function) PARAMS ((PTR)); + + /* Record line number information for the current compilation unit. */ + boolean (*lineno) PARAMS ((PTR, const char *, unsigned long, bfd_vma)); +}; + +/* Exported functions. */ + +/* The first argument to most of these functions is a handle. This + handle is returned by the debug_init function. The purpose of the + handle is to permit the debugging routines to not use static + variables, and hence to be reentrant. This would be useful for a + program which wanted to handle two executables simultaneously. */ + +/* Return a debugging handle. */ + +extern PTR debug_init PARAMS ((void)); + +/* Set the source filename. This implicitly starts a new compilation + unit. */ + +extern boolean debug_set_filename PARAMS ((PTR, const char *)); + +/* Change source files to the given file name. This is used for + include files in a single compilation unit. */ + +extern boolean debug_start_source PARAMS ((PTR, const char *)); + +/* Record a function definition. This implicitly starts a function + block. The debug_type argument is the type of the return value. + The boolean indicates whether the function is globally visible. + The bfd_vma is the address of the start of the function. Currently + the parameter types are specified by calls to + debug_record_parameter. */ + +extern boolean debug_record_function + PARAMS ((PTR, const char *, debug_type, boolean, bfd_vma)); + +/* Record a parameter for the current function. */ + +extern boolean debug_record_parameter + PARAMS ((PTR, const char *, debug_type, enum debug_parm_kind, bfd_vma)); + +/* End a function definition. The argument is the address where the + function ends. */ + +extern boolean debug_end_function PARAMS ((PTR, bfd_vma)); + +/* Start a block in a function. All local information will be + recorded in this block, until the matching call to debug_end_block. + debug_start_block and debug_end_block may be nested. The argument + is the address at which this block starts. */ + +extern boolean debug_start_block PARAMS ((PTR, bfd_vma)); + +/* Finish a block in a function. This matches the call to + debug_start_block. The argument is the address at which this block + ends. */ + +extern boolean debug_end_block PARAMS ((PTR, bfd_vma)); + +/* Associate a line number in the current source file with a given + address. */ + +extern boolean debug_record_line PARAMS ((PTR, unsigned long, bfd_vma)); + +/* Start a named common block. This is a block of variables that may + move in memory. */ + +extern boolean debug_start_common_block PARAMS ((PTR, const char *)); + +/* End a named common block. */ + +extern boolean debug_end_common_block PARAMS ((PTR, const char *)); + +/* Record a named integer constant. */ + +extern boolean debug_record_int_const PARAMS ((PTR, const char *, bfd_vma)); + +/* Record a named floating point constant. */ + +extern boolean debug_record_float_const PARAMS ((PTR, const char *, double)); + +/* Record a typed constant with an integral value. */ + +extern boolean debug_record_typed_const + PARAMS ((PTR, const char *, debug_type, bfd_vma)); + +/* Record a label. */ + +extern boolean debug_record_label + PARAMS ((PTR, const char *, debug_type, bfd_vma)); + +/* Record a variable. */ + +extern boolean debug_record_variable + PARAMS ((PTR, const char *, debug_type, enum debug_var_kind, bfd_vma)); + +/* Make an indirect type. The first argument is a pointer to the + location where the real type will be placed. The second argument + is the type tag, if there is one; this may be NULL; the only + purpose of this argument is so that debug_get_type_name can return + something useful. This function may be used when a type is + referenced before it is defined. */ + +extern debug_type debug_make_indirect_type + PARAMS ((PTR, debug_type *, const char *)); + +/* Make a void type. */ + +extern debug_type debug_make_void_type PARAMS ((PTR)); + +/* Make an integer type of a given size. The boolean argument is true + if the integer is unsigned. */ + +extern debug_type debug_make_int_type PARAMS ((PTR, unsigned int, boolean)); + +/* Make a floating point type of a given size. FIXME: On some + platforms, like an Alpha, you probably need to be able to specify + the format. */ + +extern debug_type debug_make_float_type PARAMS ((PTR, unsigned int)); + +/* Make a boolean type of a given size. */ + +extern debug_type debug_make_bool_type PARAMS ((PTR, unsigned int)); + +/* Make a complex type of a given size. */ + +extern debug_type debug_make_complex_type PARAMS ((PTR, unsigned int)); + +/* Make a structure type. The second argument is true for a struct, + false for a union. The third argument is the size of the struct. + The fourth argument is a NULL terminated array of fields. */ + +extern debug_type debug_make_struct_type + PARAMS ((PTR, boolean, bfd_vma, debug_field *)); + +/* Make an object type. The first three arguments after the handle + are the same as for debug_make_struct_type. The next arguments are + a NULL terminated array of base classes, a NULL terminated array of + methods, the type of the object holding the virtual function table + if it is not this object, and a boolean which is true if this + object has its own virtual function table. */ + +extern debug_type debug_make_object_type + PARAMS ((PTR, boolean, bfd_vma, debug_field *, debug_baseclass *, + debug_method *, debug_type, boolean)); + +/* Make an enumeration type. The arguments are a null terminated + array of strings, and an array of corresponding values. */ + +extern debug_type debug_make_enum_type + PARAMS ((PTR, const char **, bfd_signed_vma *)); + +/* Make a pointer to a given type. */ + +extern debug_type debug_make_pointer_type + PARAMS ((PTR, debug_type)); + +/* Make a function type. The second argument is the return type. The + third argument is a NULL terminated array of argument types. The + fourth argument is true if the function takes a variable number of + arguments. If the third argument is NULL, then the argument types + are unknown. */ + +extern debug_type debug_make_function_type + PARAMS ((PTR, debug_type, debug_type *, boolean)); + +/* Make a reference to a given type. */ + +extern debug_type debug_make_reference_type PARAMS ((PTR, debug_type)); + +/* Make a range of a given type from a lower to an upper bound. */ + +extern debug_type debug_make_range_type + PARAMS ((PTR, debug_type, bfd_signed_vma, bfd_signed_vma)); + +/* Make an array type. The second argument is the type of an element + of the array. The third argument is the type of a range of the + array. The fourth and fifth argument are the lower and upper + bounds, respectively (if the bounds are not known, lower should be + 0 and upper should be -1). The sixth argument is true if this + array is actually a string, as in C. */ + +extern debug_type debug_make_array_type + PARAMS ((PTR, debug_type, debug_type, bfd_signed_vma, bfd_signed_vma, + boolean)); + +/* Make a set of a given type. For example, a Pascal set type. The + boolean argument is true if this set is actually a bitstring, as in + CHILL. */ + +extern debug_type debug_make_set_type PARAMS ((PTR, debug_type, boolean)); + +/* Make a type for a pointer which is relative to an object. The + second argument is the type of the object to which the pointer is + relative. The third argument is the type that the pointer points + to. */ + +extern debug_type debug_make_offset_type + PARAMS ((PTR, debug_type, debug_type)); + +/* Make a type for a method function. The second argument is the + return type. The third argument is the domain. The fourth + argument is a NULL terminated array of argument types. The fifth + argument is true if the function takes a variable number of + arguments, in which case the array of argument types indicates the + types of the first arguments. The domain and the argument array + may be NULL, in which case this is a stub method and that + information is not available. Stabs debugging uses this, and gets + the argument types from the mangled name. */ + +extern debug_type debug_make_method_type + PARAMS ((PTR, debug_type, debug_type, debug_type *, boolean)); + +/* Make a const qualified version of a given type. */ + +extern debug_type debug_make_const_type PARAMS ((PTR, debug_type)); + +/* Make a volatile qualified version of a given type. */ + +extern debug_type debug_make_volatile_type PARAMS ((PTR, debug_type)); + +/* Make an undefined tagged type. For example, a struct which has + been mentioned, but not defined. */ + +extern debug_type debug_make_undefined_tagged_type + PARAMS ((PTR, const char *, enum debug_type_kind)); + +/* Make a base class for an object. The second argument is the base + class type. The third argument is the bit position of this base + class in the object. The fourth argument is whether this is a + virtual class. The fifth argument is the visibility of the base + class. */ + +extern debug_baseclass debug_make_baseclass + PARAMS ((PTR, debug_type, bfd_vma, boolean, enum debug_visibility)); + +/* Make a field for a struct. The second argument is the name. The + third argument is the type of the field. The fourth argument is + the bit position of the field. The fifth argument is the size of + the field (it may be zero). The sixth argument is the visibility + of the field. */ + +extern debug_field debug_make_field + PARAMS ((PTR, const char *, debug_type, bfd_vma, bfd_vma, + enum debug_visibility)); + +/* Make a static member of an object. The second argument is the + name. The third argument is the type of the member. The fourth + argument is the physical name of the member (i.e., the name as a + global variable). The fifth argument is the visibility of the + member. */ + +extern debug_field debug_make_static_member + PARAMS ((PTR, const char *, debug_type, const char *, + enum debug_visibility)); + +/* Make a method. The second argument is the name, and the third + argument is a NULL terminated array of method variants. Each + method variant is a method with this name but with different + argument types. */ + +extern debug_method debug_make_method + PARAMS ((PTR, const char *, debug_method_variant *)); + +/* Make a method variant. The second argument is the physical name of + the function. The third argument is the type of the function, + probably constructed by debug_make_method_type. The fourth + argument is the visibility. The fifth argument is whether this is + a const function. The sixth argument is whether this is a volatile + function. The seventh argument is the index in the virtual + function table, if any. The eighth argument is the virtual + function context. */ + +extern debug_method_variant debug_make_method_variant + PARAMS ((PTR, const char *, debug_type, enum debug_visibility, boolean, + boolean, bfd_vma, debug_type)); + +/* Make a static method argument. The arguments are the same as for + debug_make_method_variant, except that the last two are omitted + since a static method can not also be virtual. */ + +extern debug_method_variant debug_make_static_method_variant + PARAMS ((PTR, const char *, debug_type, enum debug_visibility, boolean, + boolean)); + +/* Name a type. This returns a new type with an attached name. */ + +extern debug_type debug_name_type PARAMS ((PTR, const char *, debug_type)); + +/* Give a tag to a type, such as a struct or union. This returns a + new type with an attached tag. */ + +extern debug_type debug_tag_type PARAMS ((PTR, const char *, debug_type)); + +/* Record the size of a given type. */ + +extern boolean debug_record_type_size PARAMS ((PTR, debug_type, unsigned int)); + +/* Find a named type. */ + +extern debug_type debug_find_named_type PARAMS ((PTR, const char *)); + +/* Find a tagged type. */ + +extern debug_type debug_find_tagged_type + PARAMS ((PTR, const char *, enum debug_type_kind)); + +/* Get the kind of a type. */ + +extern enum debug_type_kind debug_get_type_kind PARAMS ((PTR, debug_type)); + +/* Get the name of a type. */ + +extern const char *debug_get_type_name PARAMS ((PTR, debug_type)); + +/* Get the size of a type. */ + +extern bfd_vma debug_get_type_size PARAMS ((PTR, debug_type)); + +/* Get the return type of a function or method type. */ + +extern debug_type debug_get_return_type PARAMS ((PTR, debug_type)); + +/* Get the NULL terminated array of parameter types for a function or + method type (actually, parameter types are not currently stored for + function types). This may be used to determine whether a method + type is a stub method or not. The last argument points to a + boolean which is set to true if the function takes a variable + number of arguments. */ + +extern const debug_type *debug_get_parameter_types PARAMS ((PTR, + debug_type, + boolean *)); + +/* Get the target type of a pointer or reference or const or volatile + type. */ + +extern debug_type debug_get_target_type PARAMS ((PTR, debug_type)); + +/* Get the NULL terminated array of fields for a struct, union, or + class. */ + +extern const debug_field *debug_get_fields PARAMS ((PTR, debug_type)); + +/* Get the type of a field. */ + +extern debug_type debug_get_field_type PARAMS ((PTR, debug_field)); + +/* Get the name of a field. */ + +extern const char *debug_get_field_name PARAMS ((PTR, debug_field)); + +/* Get the bit position of a field within the containing structure. + If the field is a static member, this will return (bfd_vma) -1. */ + +extern bfd_vma debug_get_field_bitpos PARAMS ((PTR, debug_field)); + +/* Get the bit size of a field. If the field is a static member, this + will return (bfd_vma) -1. */ + +extern bfd_vma debug_get_field_bitsize PARAMS ((PTR, debug_field)); + +/* Get the visibility of a field. */ + +extern enum debug_visibility debug_get_field_visibility + PARAMS ((PTR, debug_field)); + +/* Get the physical name of a field, if it is a static member. If the + field is not a static member, this will return NULL. */ + +extern const char *debug_get_field_physname PARAMS ((PTR, debug_field)); + +/* Write out the recorded debugging information. This takes a set of + function pointers which are called to do the actual writing. The + first PTR is the debugging handle. The second PTR is a handle + which is passed to the functions. */ + +extern boolean debug_write PARAMS ((PTR, const struct debug_write_fns *, PTR)); + +#endif /* DEBUG_H */ diff --git a/binutils/deflex.l b/binutils/deflex.l new file mode 100644 index 0000000..e7fa362 --- /dev/null +++ b/binutils/deflex.l @@ -0,0 +1,86 @@ +%{/* deflex.l - Lexer for .def files */ + +/* Copyright (C) 1995, 1997, 1998 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +/* Contributed by Steve Chamberlain + sac@cygnus.com + +*/ +#define DONTDECLARE_MALLOC +#include "libiberty.h" +#include "defparse.h" +#include "dlltool.h" + +int linenumber; + +%} +%% +"NAME" { return NAME;} +"LIBRARY" { return LIBRARY;} +"DESCRIPTION" { return DESCRIPTION;} +"STACKSIZE" { return STACKSIZE;} +"HEAPSIZE" { return HEAPSIZE;} +"CODE" { return CODE;} +"DATA" { return DATA;} +"SECTIONS" { return SECTIONS;} +"EXPORTS" { return EXPORTS;} +"IMPORTS" { return IMPORTS;} +"VERSION" { return VERSIONK;} +"BASE" { return BASE;} +"CONSTANT" { return CONSTANT; } +"NONAME" { return NONAME; } +"READ" { return READ;} +"WRITE" { return WRITE;} +"EXECUTE" { return EXECUTE;} +"SHARED" { return SHARED;} + +[0-9][x0-9A-Fa-f]* { yylval.number = strtol (yytext,0,0); + return NUMBER; } + +[A-Za-z$:\-\_?][A-Za-z0-9/$:\-\_@?]+ { + yylval.id = xstrdup (yytext); + return ID; + } + +"\""[^\"]*"\"" { + yylval.id = xstrdup (yytext+1); + yylval.id[yyleng-2] = 0; + return ID; + } + +"\'"[^\']*"\'" { + yylval.id = xstrdup (yytext+1); + yylval.id[yyleng-2] = 0; + return ID; + } +"*".* { } +";".* { } +" " { } +"\t" { } +"\n" { linenumber ++ ;} +"=" { return '=';} +"." { return '.';} +"@" { return '@';} +"," { return ',';} +%% +#ifndef yywrap +/* Needed for lex, though not flex. */ +int yywrap() { return 1; } +#endif diff --git a/binutils/defparse.y b/binutils/defparse.y new file mode 100644 index 0000000..1cb6360 --- /dev/null +++ b/binutils/defparse.y @@ -0,0 +1,157 @@ +%{ /* defparse.y - parser for .def files */ + +/* Copyright (C) 1995, 1997, 1998 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "bfd.h" +#include "bucomm.h" +#include "dlltool.h" +%} + +%union { + char *id; + int number; +}; + +%token NAME, LIBRARY, DESCRIPTION, STACKSIZE, HEAPSIZE, CODE, DATA +%token SECTIONS, EXPORTS, IMPORTS, VERSIONK, BASE, CONSTANT +%token READ WRITE EXECUTE SHARED NONAME +%token <id> ID +%token <number> NUMBER +%type <number> opt_base opt_ordinal opt_NONAME opt_CONSTANT opt_DATA +%type <number> attr attr_list opt_number +%type <id> opt_name opt_equal_name + +%% + +start: start command + | command + ; + +command: + NAME opt_name opt_base { def_name ($2, $3); } + | LIBRARY opt_name opt_base { def_library ($2, $3); } + | EXPORTS explist + | DESCRIPTION ID { def_description ($2);} + | STACKSIZE NUMBER opt_number { def_stacksize ($2, $3);} + | HEAPSIZE NUMBER opt_number { def_heapsize ($2, $3);} + | CODE attr_list { def_code ($2);} + | DATA attr_list { def_data ($2);} + | SECTIONS seclist + | IMPORTS implist + | VERSIONK NUMBER { def_version ($2,0);} + | VERSIONK NUMBER '.' NUMBER { def_version ($2,$4);} + ; + + +explist: + /* EMPTY */ + | expline + | explist expline + ; + +expline: + ID opt_equal_name opt_ordinal opt_NONAME opt_CONSTANT opt_DATA + { def_exports ($1, $2, $3, $4, $5, $6);} + ; +implist: + implist impline + | impline + ; + +impline: + ID '=' ID '.' ID '.' ID { def_import ($1,$3,$5,$7, 0); } + | ID '=' ID '.' ID '.' NUMBER { def_import ($1,$3,$5, 0,$7); } + | ID '=' ID '.' ID { def_import ($1,$3, 0,$5, 0); } + | ID '=' ID '.' NUMBER { def_import ($1,$3, 0, 0,$5); } + | ID '.' ID '.' ID { def_import ( 0,$1,$3,$5, 0); } + | ID '.' ID '.' NUMBER { def_import ( 0,$1,$3, 0,$5); } + | ID '.' ID { def_import ( 0,$1, 0,$3, 0); } + | ID '.' NUMBER { def_import ( 0,$1, 0, 0,$3); } +; + +seclist: + seclist secline + | secline + ; + +secline: + ID attr_list { def_section ($1,$2);} + ; + +attr_list: + attr_list opt_comma attr + | attr + ; + +opt_comma: + ',' + | + ; +opt_number: ',' NUMBER { $$=$2;} + | { $$=-1;} + ; + +attr: + READ { $$ = 1;} + | WRITE { $$ = 2;} + | EXECUTE { $$=4;} + | SHARED { $$=8;} + ; + +opt_CONSTANT: + CONSTANT {$$=1;} + | {$$=0;} + ; + +opt_NONAME: + NONAME {$$=1;} + | {$$=0;} + ; + +opt_DATA: + DATA { $$ = 1; } + | { $$ = 0; } + ; + +opt_name: ID { $$ =$1; } + | ID '.' ID + { + char *name = xmalloc (strlen ($1) + 1 + strlen ($3) + 1); + sprintf (name, "%s.%s", $1, $3); + $$ = name; + } + | { $$=""; } + ; + +opt_ordinal: + '@' NUMBER { $$=$2;} + | { $$=-1;} + ; + +opt_equal_name: + '=' ID { $$ = $2; } + | { $$ = 0; } + ; + +opt_base: BASE '=' NUMBER { $$= $3;} + | { $$=-1;} + ; + + + diff --git a/binutils/dep-in.sed b/binutils/dep-in.sed new file mode 100644 index 0000000..f61921a --- /dev/null +++ b/binutils/dep-in.sed @@ -0,0 +1,17 @@ +:loop +/\\$/N +/\\$/b loop + +s!@INCDIR@!$(INCDIR)!g +s!@BFDDIR@!$(BFDDIR)!g +s!@SRCDIR@/!!g +s!@OBJDIR@/!!g + +s/\\\n */ /g + +s/ *$// +s/ */ /g +/:$/d + +s/\(.\{50\}[^ ]*\) /\1 \\\ + /g diff --git a/binutils/dlltool.c b/binutils/dlltool.c new file mode 100644 index 0000000..ed5cf5e --- /dev/null +++ b/binutils/dlltool.c @@ -0,0 +1,3199 @@ +/* dlltool.c -- tool to generate stuff for PE style DLLs + Copyright (C) 1995, 96, 97, 98, 1999 Free Software Foundation, Inc. + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + + +/* + This program allows you to build the files necessary to create + DLLs to run on a system which understands PE format image files. + (eg, Windows NT) + + See "Peering Inside the PE: A Tour of the Win32 Portable Executable + File Format", MSJ 1994, Volume 9 for more information. + Also see "Microsoft Portable Executable and Common Object File Format, + Specification 4.1" for more information. + + A DLL contains an export table which contains the information + which the runtime loader needs to tie up references from a + referencing program. + + The export table is generated by this program by reading + in a .DEF file or scanning the .a and .o files which will be in the + DLL. A .o file can contain information in special ".drectve" sections + with export information. + + A DEF file contains any number of the following commands: + + + NAME <name> [ , <base> ] + The result is going to be <name>.EXE + + LIBRARY <name> [ , <base> ] + The result is going to be <name>.DLL + + EXPORTS ( <name1> [ = <name2> ] [ @ <integer> ] [ NONAME ] [CONSTANT] [DATA] ) * + Declares name1 as an exported symbol from the + DLL, with optional ordinal number <integer> + + IMPORTS ( ( <internal-name> = <module-name> . <integer> ) + | ( [ <internal-name> = ] <module-name> . <external-name> )) * + Declares that <external-name> or the exported function whoes ordinal number + is <integer> is to be imported from the file <module-name>. If + <internal-name> is specified then this is the name that the imported + function will be refered to in the body of the DLL. + + DESCRIPTION <string> + Puts <string> into output .exp file in the .rdata section + + [STACKSIZE|HEAPSIZE] <number-reserve> [ , <number-commit> ] + Generates --stack|--heap <number-reserve>,<number-commit> + in the output .drectve section. The linker will + see this and act upon it. + + [CODE|DATA] <attr>+ + SECTIONS ( <sectionname> <attr>+ )* + <attr> = READ | WRITE | EXECUTE | SHARED + Generates --attr <sectionname> <attr> in the output + .drectve section. The linker will see this and act + upon it. + + + A -export:<name> in a .drectve section in an input .o or .a + file to this program is equivalent to a EXPORTS <name> + in a .DEF file. + + + + The program generates output files with the prefix supplied + on the command line, or in the def file, or taken from the first + supplied argument. + + The .exp.s file contains the information necessary to export + the routines in the DLL. The .lib.s file contains the information + necessary to use the DLL's routines from a referencing program. + + + + Example: + + file1.c: + asm (".section .drectve"); + asm (".ascii \"-export:adef\""); + + void adef (char * s) + { + printf ("hello from the dll %s\n", s); + } + + void bdef (char * s) + { + printf ("hello from the dll and the other entry point %s\n", s); + } + + file2.c: + asm (".section .drectve"); + asm (".ascii \"-export:cdef\""); + asm (".ascii \"-export:ddef\""); + + void cdef (char * s) + { + printf ("hello from the dll %s\n", s); + } + + void ddef (char * s) + { + printf ("hello from the dll and the other entry point %s\n", s); + } + + printf() + { + return 9; + } + + main.c + + void main() + { + cdef(); + } + + thedll.def + + LIBRARY thedll + HEAPSIZE 0x40000, 0x2000 + EXPORTS bdef @ 20 + cdef @ 30 NONAME + + SECTIONS donkey READ WRITE + aardvark EXECUTE + + # compile up the parts of the dll + + gcc -c file1.c + gcc -c file2.c + + # put them in a library (you don't have to, you + # could name all the .os on the dlltool line) + + ar qcv thedll.in file1.o file2.o + ranlib thedll.in + + # run this tool over the library and the def file + ./dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a + + # build the dll with the library with file1.o, file2.o and the export table + ld -o thedll.dll thedll.o thedll.in + + # build the mainline + gcc -c themain.c + + # link the executable with the import library + ld -e main -Tthemain.ld -o themain.exe themain.o thedll.a + + */ + +/* .idata section description + + The .idata section is the import table. It is a collection of several + subsections used to keep the pieces for each dll together: .idata$[234567]. + IE: Each dll's .idata$2's are catenated together, each .idata$3's, etc. + + .idata$2 = Import Directory Table + = array of IMAGE_IMPORT_DESCRIPTOR's. + + DWORD Import Lookup Table; - pointer to .idata$4 + DWORD TimeDateStamp; - currently always 0 + DWORD ForwarderChain; - currently always 0 + DWORD Name; - pointer to dll's name + PIMAGE_THUNK_DATA FirstThunk; - pointer to .idata$5 + + .idata$3 = null terminating entry for .idata$2. + + .idata$4 = Import Lookup Table + = array of array of pointers to hint name table. + There is one for each dll being imported from, and each dll's set is + terminated by a trailing NULL. + + .idata$5 = Import Address Table + = array of array of pointers to hint name table. + There is one for each dll being imported from, and each dll's set is + terminated by a trailing NULL. + Initially, this table is identical to the Import Lookup Table. However, + at load time, the loader overwrites the entries with the address of the + function. + + .idata$6 = Hint Name Table + = Array of { short, asciz } entries, one for each imported function. + The `short' is the function's ordinal number. + + .idata$7 = dll name (eg: "kernel32.dll"). (.idata$6 for ppc) +*/ + +/* AIX requires this to be the first thing in the file. */ +#ifndef __GNUC__ +# ifdef _AIX + #pragma alloca +#endif +#endif + +#define show_allnames 0 + +#define PAGE_SIZE 4096 +#define PAGE_MASK (-PAGE_SIZE) +#include "bfd.h" +#include "libiberty.h" +#include "bucomm.h" +#include "getopt.h" +#include "demangle.h" +#include "dlltool.h" + +#include <ctype.h> +#include <time.h> +#ifdef __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +#ifdef DLLTOOL_ARM +#include "coff/arm.h" +#include "coff/internal.h" +#endif + +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#else /* ! HAVE_SYS_WAIT_H */ +#if ! defined (_WIN32) || defined (__CYGWIN32__) +#ifndef WIFEXITED +#define WIFEXITED(w) (((w)&0377) == 0) +#endif +#ifndef WIFSIGNALED +#define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0) +#endif +#ifndef WTERMSIG +#define WTERMSIG(w) ((w) & 0177) +#endif +#ifndef WEXITSTATUS +#define WEXITSTATUS(w) (((w) >> 8) & 0377) +#endif +#else /* defined (_WIN32) && ! defined (__CYGWIN32__) */ +#ifndef WIFEXITED +#define WIFEXITED(w) (((w) & 0xff) == 0) +#endif +#ifndef WIFSIGNALED +#define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f) +#endif +#ifndef WTERMSIG +#define WTERMSIG(w) ((w) & 0x7f) +#endif +#ifndef WEXITSTATUS +#define WEXITSTATUS(w) (((w) & 0xff00) >> 8) +#endif +#endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */ +#endif /* ! HAVE_SYS_WAIT_H */ + +/* ifunc and ihead data structures: ttk@cygnus.com 1997 + + When IMPORT declarations are encountered in a .def file the + function import information is stored in a structure referenced by + the global variable IMPORT_LIST. The structure is a linked list + containing the names of the dll files each function is imported + from and a linked list of functions being imported from that dll + file. This roughly parallels the structure of the .idata section + in the PE object file. + + The contents of .def file are interpreted from within the + process_def_file function. Every time an IMPORT declaration is + encountered, it is broken up into its component parts and passed to + def_import. IMPORT_LIST is initialized to NULL in function main. */ + +typedef struct ifunct +{ + char *name; /* name of function being imported */ + int ord; /* two-byte ordinal value associated with function */ + struct ifunct *next; +} ifunctype; + +typedef struct iheadt +{ + char *dllname; /* name of dll file imported from */ + long nfuncs; /* number of functions in list */ + struct ifunct *funchead; /* first function in list */ + struct ifunct *functail; /* last function in list */ + struct iheadt *next; /* next dll file in list */ +} iheadtype; + +/* Structure containing all import information as defined in .def file + (qv "ihead structure"). */ + +static iheadtype *import_list = NULL; + +static char *as_name = "as"; +static char * as_flags = ""; + +static int no_idata4; +static int no_idata5; +static char *exp_name; +static char *imp_name; +static char *head_label; +static char *imp_name_lab; +static char *dll_name; + +static int add_indirect = 0; +static int add_underscore = 0; +static int dontdeltemps = 0; + +#ifdef DLLTOOL_ARM +static int interwork = 0; +#endif + +/* True if we should export all symbols. Otherwise, we only export + symbols listed in .drectve sections or in the def file. */ +static boolean export_all_symbols; + +/* True if we should exclude the symbols in DEFAULT_EXCLUDES when + exporting all symbols. */ +static boolean do_default_excludes; + +/* Default symbols to exclude when exporting all the symbols. */ +static const char *default_excludes = "DllMain@12,DllEntryPoint@0,impure_ptr"; + +static char *def_file; + +extern char * program_name; + +static int machine; +static int killat; +static int add_stdcall_alias; +static int verbose; +static FILE *output_def; +static FILE *base_file; + +#ifdef DLLTOOL_BEOS +static const char *mname = "beos"; +#endif + +#ifdef DLLTOOL_ARM +static const char *mname = "arm"; +#endif + +#ifdef DLLTOOL_I386 +static const char *mname = "i386"; +#endif + +#ifdef DLLTOOL_PPC +static const char *mname = "ppc"; +#endif + +#define PATHMAX 250 /* What's the right name for this ? */ + +#define TMP_ASM "dc.s" +#define TMP_HEAD_S "dh.s" +#define TMP_HEAD_O "dh.o" +#define TMP_TAIL_S "dt.s" +#define TMP_TAIL_O "dt.o" +#define TMP_STUB "ds" + +/* This bit of assemly does jmp * .... +s set how_jtab_roff to mark where the 32bit abs branch should go */ +static const unsigned char i386_jtab[] = +{ + 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90 +}; + +static const unsigned char arm_jtab[] = +{ + 0x00, 0xc0, 0x9f, 0xe5, + 0x00, 0xf0, 0x9c, 0xe5, + 0, 0, 0, 0 +}; + +static const unsigned char thumb_jtab[] = +{ + 0xc0, 0xb4, + 0x02, 0x4e, + 0x36, 0x68, + 0x01, 0x96, + 0x40, 0xbd, + 0xc0, 0x46, + 0, 0, 0, 0 +}; + +/* This is the glue sequence for PowerPC PE. There is a */ +/* tocrel16-tocdefn reloc against the first instruction. */ +/* We also need a IMGLUE reloc against the glue function */ +/* to restore the toc saved by the third instruction in */ +/* the glue. */ +static const unsigned char ppc_jtab[] = +{ + 0x00, 0x00, 0x62, 0x81, /* lwz r11,0(r2) */ + /* Reloc TOCREL16 __imp_xxx */ + 0x00, 0x00, 0x8B, 0x81, /* lwz r12,0(r11) */ + 0x04, 0x00, 0x41, 0x90, /* stw r2,4(r1) */ + 0xA6, 0x03, 0x89, 0x7D, /* mtctr r12 */ + 0x04, 0x00, 0x4B, 0x80, /* lwz r2,4(r11) */ + 0x20, 0x04, 0x80, 0x4E /* bctr */ +}; + +#ifdef DLLTOOL_PPC +/* the glue instruction, picks up the toc from the stw in */ +/* the above code: "lwz r2,4(r1)" */ +static bfd_vma ppc_glue_insn = 0x80410004; +#endif + +/* The outfile array must be big enough to contain a fully + qualified path name, plus an arbitary series of command + line switches. We hope that PATH_MAX times two will be + enough. */ +static char outfile [PATHMAX * 2]; + +struct mac + { + const char *type; + const char *how_byte; + const char *how_short; + const char *how_long; + const char *how_asciz; + const char *how_comment; + const char *how_jump; + const char *how_global; + const char *how_space; + const char *how_align_short; + const char *how_align_long; + const char *how_bfd_target; + enum bfd_architecture how_bfd_arch; + const unsigned char *how_jtab; + int how_jtab_size; /* size of the jtab entry */ + int how_jtab_roff; /* offset into it for the ind 32 reloc into idata 5 */ + }; + +static const struct mac +mtable[] = +{ + { +#define MARM 0 + "arm", ".byte", ".short", ".long", ".asciz", "@", + "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long", + ".global", ".space", ".align\t2",".align\t4","pe-arm-little", bfd_arch_arm, + arm_jtab, sizeof (arm_jtab), 8 + } + , + { +#define M386 1 + "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-i386",bfd_arch_i386, + i386_jtab, sizeof (i386_jtab), 2 + } + , + { +#define MPPC 2 + "ppc", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-powerpcle",bfd_arch_powerpc, + ppc_jtab, sizeof (ppc_jtab), 0 + } + , + { +#define MTHUMB 3 + "thumb", ".byte", ".short", ".long", ".asciz", "@", + "push\t{r6, r7}\n\tldr\tr6, [pc, #8]\n\tldr\tr6, [r6]\n\tstr\tr6, [sp, #4]\n\tpop\t{r6, pc}\n\tnop", + ".global", ".space", ".align\t2",".align\t4","pe-arm-little", bfd_arch_arm, + thumb_jtab, sizeof (thumb_jtab), 12 + } + , +{ 0} +}; + +typedef struct dlist +{ + char *text; + struct dlist *next; +} +dlist_type; + +typedef struct export + { + const char *name; + const char *internal_name; + int ordinal; + int constant; + int noname; + int data; + int hint; + struct export *next; + } +export_type; + +/* A list of symbols which we should not export. */ + +struct string_list +{ + struct string_list *next; + char *string; +}; + +static struct string_list *excludes; + +static const char *rvaafter PARAMS ((int)); +static const char *rvabefore PARAMS ((int)); +static const char *asm_prefix PARAMS ((int)); +static void append_import PARAMS ((const char *, const char *, int)); +static void run PARAMS ((const char *, char *)); +static void scan_drectve_symbols PARAMS ((bfd *)); +static void scan_filtered_symbols PARAMS ((bfd *, PTR, long, unsigned int)); +static void add_excludes PARAMS ((const char *)); +static boolean match_exclude PARAMS ((const char *)); +static void set_default_excludes PARAMS ((void)); +static long filter_symbols PARAMS ((bfd *, PTR, long, unsigned int)); +static void scan_all_symbols PARAMS ((bfd *)); +static void scan_open_obj_file PARAMS ((bfd *)); +static void scan_obj_file PARAMS ((const char *)); +static void dump_def_info PARAMS ((FILE *)); +static int sfunc PARAMS ((const void *, const void *)); +static void flush_page PARAMS ((FILE *, long *, int, int)); +static void gen_def_file PARAMS ((void)); +static void generate_idata_ofile PARAMS ((FILE *)); +static void gen_exp_file PARAMS ((void)); +static const char *xlate PARAMS ((const char *)); +#if 0 +static void dump_iat PARAMS ((FILE *, export_type *)); +#endif +static char *make_label PARAMS ((const char *, const char *)); +static bfd *make_one_lib_file PARAMS ((export_type *, int)); +static bfd *make_head PARAMS ((void)); +static bfd *make_tail PARAMS ((void)); +static void gen_lib_file PARAMS ((void)); +static int pfunc PARAMS ((const void *, const void *)); +static int nfunc PARAMS ((const void *, const void *)); +static void remove_null_names PARAMS ((export_type **)); +static void dtab PARAMS ((export_type **)); +static void process_duplicates PARAMS ((export_type **)); +static void fill_ordinals PARAMS ((export_type **)); +static int alphafunc PARAMS ((const void *, const void *)); +static void mangle_defs PARAMS ((void)); +static void usage PARAMS ((FILE *, int)); +static void display PARAMS ((const char *, va_list)); +static void inform PARAMS ((const char *, ...)); +static void warn PARAMS ((const char *, ...)); + +static void +display (message, args) + const char * message; + va_list args; +{ + if (program_name != NULL) + fprintf (stderr, "%s: ", program_name); + + vfprintf (stderr, message, args); + + if (message [strlen (message) - 1] != '\n') + fputc ('\n', stderr); +} + + +static void +#ifdef __STDC__ +inform (const char * message, ...) +#else +inform (message, va_alist) + const char * message; + va_dcl +#endif +{ + va_list args; + + if (!verbose) + return; + +#ifdef __STDC__ + va_start (args, message); +#else + va_start (args); +#endif + + display (message, args); + + va_end (args); +} + +static void +#ifdef __STDC__ +warn (const char * message, ...) +#else +warn (message, va_alist) + const char * message; + va_dcl +#endif +{ + va_list args; + +#ifdef __STDC__ + va_start (args, message); +#else + va_start (args); +#endif + + display (message, args); + + va_end (args); +} + +static const char * +rvaafter (machine) + int machine; +{ + switch (machine) + { + case MARM: + case M386: + case MPPC: + case MTHUMB: + break; + default: + /* xgettext:c-format */ + fatal (_("Internal error: Unknown machine type: %d\n"), machine); + break; + } + return ""; +} + +static const char * +rvabefore (machine) + int machine; +{ + switch (machine) + { + case MARM: + case M386: + case MPPC: + case MTHUMB: + return ".rva\t"; + default: + /* xgettext:c-format */ + fatal (_("Internal error: Unknown machine type: %d\n"), machine); + break; + } + return ""; +} + +static const char * +asm_prefix (machine) + int machine; +{ + switch (machine) + { + case MARM: + case MPPC: + case MTHUMB: + break; + case M386: + return "_"; + default: + /* xgettext:c-format */ + fatal (_("Internal error: Unknown machine type: %d\n"), machine); + break; + } + return ""; +} + +#define ASM_BYTE mtable[machine].how_byte +#define ASM_SHORT mtable[machine].how_short +#define ASM_LONG mtable[machine].how_long +#define ASM_TEXT mtable[machine].how_asciz +#define ASM_C mtable[machine].how_comment +#define ASM_JUMP mtable[machine].how_jump +#define ASM_GLOBAL mtable[machine].how_global +#define ASM_SPACE mtable[machine].how_space +#define ASM_ALIGN_SHORT mtable[machine].how_align_short +#define ASM_RVA_BEFORE rvabefore(machine) +#define ASM_RVA_AFTER rvaafter(machine) +#define ASM_PREFIX asm_prefix(machine) +#define ASM_ALIGN_LONG mtable[machine].how_align_long +#define HOW_BFD_TARGET 0 /* always default*/ +#define HOW_BFD_ARCH mtable[machine].how_bfd_arch +#define HOW_JTAB mtable[machine].how_jtab +#define HOW_JTAB_SIZE mtable[machine].how_jtab_size +#define HOW_JTAB_ROFF mtable[machine].how_jtab_roff +static char **oav; + +void +process_def_file (name) + const char *name; +{ + FILE *f = fopen (name, FOPEN_RT); + + if (!f) + /* xgettext:c-format */ + fatal (_("Can't open def file: %s"), name); + + yyin = f; + + /* xgettext:c-format */ + inform (_("Processing def file: %s"), name); + + yyparse (); + + inform (_("Processed def file")); +} + +/**********************************************************************/ + +/* Communications with the parser */ + +static const char *d_name; /* Arg to NAME or LIBRARY */ +static int d_nfuncs; /* Number of functions exported */ +static int d_named_nfuncs; /* Number of named functions exported */ +static int d_low_ord; /* Lowest ordinal index */ +static int d_high_ord; /* Highest ordinal index */ +static export_type *d_exports; /*list of exported functions */ +static export_type **d_exports_lexically; /* vector of exported functions in alpha order */ +static dlist_type *d_list; /* Descriptions */ +static dlist_type *a_list; /* Stuff to go in directives */ + +static int d_is_dll; +static int d_is_exe; + +int +yyerror (err) + const char *err; +{ + /* xgettext:c-format */ + warn (_("Syntax error in def file %s:%d\n"), def_file, linenumber); + + return 0; +} + +void +def_exports (name, internal_name, ordinal, noname, constant, data) + const char *name; + const char *internal_name; + int ordinal; + int noname; + int constant; + int data; +{ + struct export *p = (struct export *) xmalloc (sizeof (*p)); + + p->name = name; + p->internal_name = internal_name ? internal_name : name; + p->ordinal = ordinal; + p->constant = constant; + p->noname = noname; + p->data = data; + p->next = d_exports; + d_exports = p; + d_nfuncs++; +} + +void +def_name (name, base) + const char *name; + int base; +{ + /* xgettext:c-format */ + inform (_("NAME: %s base: %x"), name, base); + + if (d_is_dll) + warn (_("Can't have LIBRARY and NAME\n")); + + d_name = name; + /* if --dllname not provided, use the one in the DEF file. + FIXME: Is this appropriate for executables? */ + if (! dll_name) + dll_name = xstrdup (name); + d_is_exe = 1; +} + +void +def_library (name, base) + const char *name; + int base; +{ + /* xgettext:c-format */ + inform (_("LIBRARY: %s base: %x"), name, base); + + if (d_is_exe) + warn (_("%s: Can't have LIBRARY and NAME\n"), program_name); + + d_name = name; + /* if --dllname not provided, use the one in the DEF file. */ + if (! dll_name) + dll_name = xstrdup (name); + d_is_dll = 1; +} + +void +def_description (desc) + const char *desc; +{ + dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type)); + d->text = xstrdup (desc); + d->next = d_list; + d_list = d; +} + +void +new_directive (dir) + char *dir; +{ + dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type)); + d->text = xstrdup (dir); + d->next = a_list; + a_list = d; +} + +void +def_heapsize (reserve, commit) + int reserve; + int commit; +{ + char b[200]; + if (commit > 0) + sprintf (b, "-heap 0x%x,0x%x ", reserve, commit); + else + sprintf (b, "-heap 0x%x ", reserve); + new_directive (xstrdup (b)); +} + +void +def_stacksize (reserve, commit) + int reserve; + int commit; +{ + char b[200]; + if (commit > 0) + sprintf (b, "-stack 0x%x,0x%x ", reserve, commit); + else + sprintf (b, "-stack 0x%x ", reserve); + new_directive (xstrdup (b)); +} + +/* append_import simply adds the given import definition to the global + import_list. It is used by def_import. */ + +static void +append_import (symbol_name, dll_name, func_ordinal) + const char *symbol_name; + const char *dll_name; + int func_ordinal; +{ + iheadtype **pq; + iheadtype *q; + + for (pq = &import_list; *pq != NULL; pq = &(*pq)->next) + { + if (strcmp ((*pq)->dllname, dll_name) == 0) + { + q = *pq; + q->functail->next = xmalloc (sizeof (ifunctype)); + q->functail = q->functail->next; + q->functail->ord = func_ordinal; + q->functail->name = xstrdup (symbol_name); + q->functail->next = NULL; + q->nfuncs++; + return; + } + } + + q = xmalloc (sizeof (iheadtype)); + q->dllname = xstrdup (dll_name); + q->nfuncs = 1; + q->funchead = xmalloc (sizeof (ifunctype)); + q->functail = q->funchead; + q->next = NULL; + q->functail->name = xstrdup (symbol_name); + q->functail->ord = func_ordinal; + q->functail->next = NULL; + + *pq = q; +} + +/* def_import is called from within defparse.y when an IMPORT + declaration is encountered. Depending on the form of the + declaration, the module name may or may not need ".dll" to be + appended to it, the name of the function may be stored in internal + or entry, and there may or may not be an ordinal value associated + with it. */ + +/* A note regarding the parse modes: + In defparse.y we have to accept import declarations which follow + any one of the following forms: + <func_name_in_app> = <dll_name>.<func_name_in_dll> + <func_name_in_app> = <dll_name>.<number> + <dll_name>.<func_name_in_dll> + <dll_name>.<number> + Furthermore, the dll's name may or may not end with ".dll", which + complicates the parsing a little. Normally the dll's name is + passed to def_import() in the "module" parameter, but when it ends + with ".dll" it gets passed in "module" sans ".dll" and that needs + to be reappended. + + def_import gets five parameters: + APP_NAME - the name of the function in the application, if + present, or NULL if not present. + MODULE - the name of the dll, possibly sans extension (ie, '.dll'). + DLLEXT - the extension of the dll, if present, NULL if not present. + ENTRY - the name of the function in the dll, if present, or NULL. + ORD_VAL - the numerical tag of the function in the dll, if present, + or NULL. Exactly one of <entry> or <ord_val> must be + present (i.e., not NULL). */ + +void +def_import (app_name, module, dllext, entry, ord_val) + const char *app_name; + const char *module; + const char *dllext; + const char *entry; + int ord_val; +{ + const char *application_name; + char *buf; + + if (entry != NULL) + application_name = entry; + else + { + if (app_name != NULL) + application_name = app_name; + else + application_name = ""; + } + + if (dllext != NULL) + { + buf = (char *) alloca (strlen (module) + strlen (dllext) + 2); + sprintf (buf, "%s.%s", module, dllext); + module = buf; + } + + append_import (application_name, module, ord_val); +} + +void +def_version (major, minor) + int major; + int minor; +{ + printf ("VERSION %d.%d\n", major, minor); +} + +void +def_section (name, attr) + const char *name; + int attr; +{ + char buf[200]; + char atts[5]; + char *d = atts; + if (attr & 1) + *d++ = 'R'; + + if (attr & 2) + *d++ = 'W'; + if (attr & 4) + *d++ = 'X'; + if (attr & 8) + *d++ = 'S'; + *d++ = 0; + sprintf (buf, "-attr %s %s", name, atts); + new_directive (xstrdup (buf)); +} + +void +def_code (attr) + int attr; +{ + + def_section ("CODE", attr); +} + +void +def_data (attr) + int attr; +{ + def_section ("DATA", attr); +} + +/**********************************************************************/ + +static void +run (what, args) + const char *what; + char *args; +{ + char *s; + int pid, wait_status; + int i; + const char **argv; + char *errmsg_fmt, *errmsg_arg; + char *temp_base = choose_temp_base (); + + inform ("run: %s %s\n", what, args); + + /* Count the args */ + i = 0; + for (s = args; *s; s++) + if (*s == ' ') + i++; + i++; + argv = alloca (sizeof (char *) * (i + 3)); + i = 0; + argv[i++] = what; + s = args; + while (1) + { + while (*s == ' ') + ++s; + argv[i++] = s; + while (*s != ' ' && *s != 0) + s++; + if (*s == 0) + break; + *s++ = 0; + } + argv[i++] = NULL; + + pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base, + &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH); + + if (pid == -1) + { + inform (strerror (errno)); + + fatal (errmsg_fmt, errmsg_arg); + } + + pid = pwait (pid, & wait_status, 0); + + if (pid == -1) + { + /* xgettext:c-format */ + fatal (_("wait: %s"), strerror (errno)); + } + else if (WIFSIGNALED (wait_status)) + { + /* xgettext:c-format */ + fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status)); + } + else if (WIFEXITED (wait_status)) + { + if (WEXITSTATUS (wait_status) != 0) + /* xgettext:c-format */ + warn (_("%s exited with status %d\n"), + what, WEXITSTATUS (wait_status)); + } + else + abort (); +} + +/* Look for a list of symbols to export in the .drectve section of + ABFD. Pass each one to def_exports. */ + +static void +scan_drectve_symbols (abfd) + bfd *abfd; +{ + asection * s; + int size; + char * buf; + char * p; + char * e; + + /* Look for .drectve's */ + s = bfd_get_section_by_name (abfd, ".drectve"); + + if (s == NULL) + return; + + size = bfd_get_section_size_before_reloc (s); + buf = xmalloc (size); + + bfd_get_section_contents (abfd, s, buf, 0, size); + + /* xgettext:c-format */ + inform (_("Sucking in info from .drective section in %s\n"), + bfd_get_filename (abfd)); + + /* Search for -export: strings */ + p = buf; + e = buf + size; + while (p < e) + { + if (p[0] == '-' + && strncmp (p, "-export:", 8) == 0) + { + char * name; + char * c; + + p += 8; + name = p; + while (p < e && *p != ' ' && *p != '-') + p++; + c = xmalloc (p - name + 1); + memcpy (c, name, p - name); + c[p - name] = 0; + + /* FIXME: The 5th arg is for the `constant' field. + What should it be? Not that it matters since it's not + currently useful. */ + def_exports (c, 0, -1, 0, 0, 0); + + if (add_stdcall_alias && strchr (c, '@')) + { + char *exported_name = xstrdup (c); + char *atsym = strchr (exported_name, '@'); + *atsym = '\0'; + def_exports (exported_name, xstrdup (c), -1, 0, 0, 0); + } + } + else + p++; + } + free (buf); +} + +/* Look through the symbols in MINISYMS, and add each one to list of + symbols to export. */ + +static void +scan_filtered_symbols (abfd, minisyms, symcount, size) + bfd *abfd; + PTR minisyms; + long symcount; + unsigned int size; +{ + asymbol *store; + bfd_byte *from, *fromend; + + store = bfd_make_empty_symbol (abfd); + if (store == NULL) + bfd_fatal (bfd_get_filename (abfd)); + + from = (bfd_byte *) minisyms; + fromend = from + symcount * size; + for (; from < fromend; from += size) + { + asymbol *sym; + const char *symbol_name; + + sym = bfd_minisymbol_to_symbol (abfd, false, from, store); + if (sym == NULL) + bfd_fatal (bfd_get_filename (abfd)); + + symbol_name = bfd_asymbol_name (sym); + if (bfd_get_symbol_leading_char (abfd) == symbol_name[0]) + ++symbol_name; + + def_exports (xstrdup (symbol_name) , 0, -1, 0, 0, 0); + + if (add_stdcall_alias && strchr (symbol_name, '@')) + { + char *exported_name = xstrdup (symbol_name); + char *atsym = strchr (exported_name, '@'); + *atsym = '\0'; + def_exports (exported_name, xstrdup (symbol_name), -1, 0, 0, 0); + } + } +} + +/* Add a list of symbols to exclude. */ + +static void +add_excludes (new_excludes) + const char *new_excludes; +{ + char *local_copy; + char *exclude_string; + + local_copy = xstrdup (new_excludes); + + exclude_string = strtok (local_copy, ",:"); + for (; exclude_string; exclude_string = strtok (NULL, ",:")) + { + struct string_list *new_exclude; + + new_exclude = ((struct string_list *) + xmalloc (sizeof (struct string_list))); + new_exclude->string = (char *) xmalloc (strlen (exclude_string) + 2); + /* FIXME: Is it always right to add a leading underscore? */ + sprintf (new_exclude->string, "_%s", exclude_string); + new_exclude->next = excludes; + excludes = new_exclude; + + /* xgettext:c-format */ + inform (_("Excluding symbol: %s\n"), exclude_string); + } + + free (local_copy); +} + +/* See if STRING is on the list of symbols to exclude. */ + +static boolean +match_exclude (string) + const char *string; +{ + struct string_list *excl_item; + + for (excl_item = excludes; excl_item; excl_item = excl_item->next) + if (strcmp (string, excl_item->string) == 0) + return true; + return false; +} + +/* Add the default list of symbols to exclude. */ + +static void +set_default_excludes (void) +{ + add_excludes (default_excludes); +} + +/* Choose which symbols to export. */ + +static long +filter_symbols (abfd, minisyms, symcount, size) + bfd *abfd; + PTR minisyms; + long symcount; + unsigned int size; +{ + bfd_byte *from, *fromend, *to; + asymbol *store; + + store = bfd_make_empty_symbol (abfd); + if (store == NULL) + bfd_fatal (bfd_get_filename (abfd)); + + from = (bfd_byte *) minisyms; + fromend = from + symcount * size; + to = (bfd_byte *) minisyms; + + for (; from < fromend; from += size) + { + int keep = 0; + asymbol *sym; + + sym = bfd_minisymbol_to_symbol (abfd, false, (const PTR) from, store); + if (sym == NULL) + bfd_fatal (bfd_get_filename (abfd)); + + /* Check for external and defined only symbols. */ + keep = (((sym->flags & BSF_GLOBAL) != 0 + || (sym->flags & BSF_WEAK) != 0 + || bfd_is_com_section (sym->section)) + && ! bfd_is_und_section (sym->section)); + + keep = keep && ! match_exclude (sym->name); + + if (keep) + { + memcpy (to, from, size); + to += size; + } + } + + return (to - (bfd_byte *) minisyms) / size; +} + +/* Export all symbols in ABFD, except for ones we were told not to + export. */ + +static void +scan_all_symbols (abfd) + bfd *abfd; +{ + long symcount; + PTR minisyms; + unsigned int size; + + /* Ignore bfds with an import descriptor table. We assume that any + such BFD contains symbols which are exported from another DLL, + and we don't want to reexport them from here. */ + if (bfd_get_section_by_name (abfd, ".idata$4")) + return; + + if (! (bfd_get_file_flags (abfd) & HAS_SYMS)) + { + /* xgettext:c-format */ + warn (_("%s: no symbols\n"), bfd_get_filename (abfd)); + return; + } + + symcount = bfd_read_minisymbols (abfd, false, &minisyms, &size); + if (symcount < 0) + bfd_fatal (bfd_get_filename (abfd)); + + if (symcount == 0) + { + /* xgettext:c-format */ + warn (_("%s: no symbols\n"), bfd_get_filename (abfd)); + return; + } + + /* Discard the symbols we don't want to export. It's OK to do this + in place; we'll free the storage anyway. */ + + symcount = filter_symbols (abfd, minisyms, symcount, size); + scan_filtered_symbols (abfd, minisyms, symcount, size); + + free (minisyms); +} + +/* Look at the object file to decide which symbols to export. */ + +static void +scan_open_obj_file (abfd) + bfd *abfd; +{ + if (export_all_symbols) + scan_all_symbols (abfd); + else + scan_drectve_symbols (abfd); + + /* FIXME: we ought to read in and block out the base relocations */ + + /* xgettext:c-format */ + inform (_("%s: Done reading %s\n"), bfd_get_filename (abfd)); +} + +static void +scan_obj_file (filename) + const char *filename; +{ + bfd * f = bfd_openr (filename, 0); + + if (!f) + /* xgettext:c-format */ + fatal (_("Unable to open object file: %s"), filename); + + /* xgettext:c-format */ + inform (_("Scanning object file %s"), filename); + + if (bfd_check_format (f, bfd_archive)) + { + bfd *arfile = bfd_openr_next_archived_file (f, 0); + while (arfile) + { + if (bfd_check_format (arfile, bfd_object)) + scan_open_obj_file (arfile); + bfd_close (arfile); + arfile = bfd_openr_next_archived_file (f, arfile); + } + } + else if (bfd_check_format (f, bfd_object)) + { + scan_open_obj_file (f); + } + + bfd_close (f); +} + +/**********************************************************************/ + +static void +dump_def_info (f) + FILE *f; +{ + int i; + export_type *exp; + fprintf (f, "%s ", ASM_C); + for (i = 0; oav[i]; i++) + fprintf (f, "%s ", oav[i]); + fprintf (f, "\n"); + for (i = 0, exp = d_exports; exp; i++, exp = exp->next) + { + fprintf (f, "%s %d = %s %s @ %d %s%s%s\n", + ASM_C, + i, + exp->name, + exp->internal_name, + exp->ordinal, + exp->noname ? "NONAME " : "", + exp->constant ? "CONSTANT" : "", + exp->data ? "DATA" : ""); + } +} + +/* Generate the .exp file */ + +static int +sfunc (a, b) + const void *a; + const void *b; +{ + return *(const long *) a - *(const long *) b; +} + +static void +flush_page (f, need, page_addr, on_page) + FILE *f; + long *need; + int page_addr; + int on_page; +{ + int i; + + /* Flush this page */ + fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n", + ASM_LONG, + page_addr, + ASM_C); + fprintf (f, "\t%s\t0x%x\t%s Size of block\n", + ASM_LONG, + (on_page * 2) + (on_page & 1) * 2 + 8, + ASM_C); + for (i = 0; i < on_page; i++) + { + fprintf (f, "\t%s\t0x%lx\n", ASM_SHORT, (need[i] - page_addr) | 0x3000); + } + /* And padding */ + if (on_page & 1) + fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000); +} + +static void +gen_def_file () +{ + int i; + export_type *exp; + + inform (_("Adding exports to output file")); + + fprintf (output_def, ";"); + for (i = 0; oav[i]; i++) + fprintf (output_def, " %s", oav[i]); + + fprintf (output_def, "\nEXPORTS\n"); + + for (i = 0, exp = d_exports; exp; i++, exp = exp->next) + { + char *quote = strchr (exp->name, '.') ? "\"" : ""; + char *res = cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS); + + if (strcmp (exp->name, exp->internal_name) == 0) + { + + fprintf (output_def, "\t%s%s%s @ %d%s%s ; %s\n", + quote, + exp->name, + quote, + exp->ordinal, + exp->noname ? " NONAME" : "", + exp->data ? " DATA" : "", + res ? res : ""); + } + else + { + char *quote1 = strchr (exp->internal_name, '.') ? "\"" : ""; + /* char *alias = */ + fprintf (output_def, "\t%s%s%s = %s%s%s @ %d%s%s ; %s\n", + quote, + exp->name, + quote, + quote1, + exp->internal_name, + quote1, + exp->ordinal, + exp->noname ? " NONAME" : "", + exp->data ? " DATA" : "", + res ? res : ""); + } + if (res) + free (res); + } + + inform (_("Added exports to output file")); +} + +/* generate_idata_ofile generates the portable assembly source code + for the idata sections. It appends the source code to the end of + the file. */ + +static void +generate_idata_ofile (filvar) + FILE *filvar; +{ + iheadtype *headptr; + ifunctype *funcptr; + int headindex; + int funcindex; + int nheads; + + if (import_list == NULL) + return; + + fprintf (filvar, "%s Import data sections\n", ASM_C); + fprintf (filvar, "\n\t.section\t.idata$2\n"); + fprintf (filvar, "\t%s\tdoi_idata\n", ASM_GLOBAL); + fprintf (filvar, "doi_idata:\n"); + + nheads = 0; + for (headptr = import_list; headptr != NULL; headptr = headptr->next) + { + fprintf (filvar, "\t%slistone%d%s\t%s %s\n", + ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER, + ASM_C, headptr->dllname); + fprintf (filvar, "\t%s\t0\n", ASM_LONG); + fprintf (filvar, "\t%s\t0\n", ASM_LONG); + fprintf (filvar, "\t%sdllname%d%s\n", + ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER); + fprintf (filvar, "\t%slisttwo%d%s\n\n", + ASM_RVA_BEFORE, nheads, ASM_RVA_AFTER); + nheads++; + } + + fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL record at */ + fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* end of idata$2 */ + fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* section */ + fprintf (filvar, "\t%s\t0\n", ASM_LONG); + fprintf (filvar, "\t%s\t0\n", ASM_LONG); + + fprintf (filvar, "\n\t.section\t.idata$4\n"); + headindex = 0; + for (headptr = import_list; headptr != NULL; headptr = headptr->next) + { + fprintf (filvar, "listone%d:\n", headindex); + for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ ) + fprintf (filvar, "\t%sfuncptr%d_%d%s\n", + ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER); + fprintf (filvar,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */ + headindex++; + } + + fprintf (filvar, "\n\t.section\t.idata$5\n"); + headindex = 0; + for (headptr = import_list; headptr != NULL; headptr = headptr->next) + { + fprintf (filvar, "listtwo%d:\n", headindex); + for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ ) + fprintf (filvar, "\t%sfuncptr%d_%d%s\n", + ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER); + fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL terminating list */ + headindex++; + } + + fprintf (filvar, "\n\t.section\t.idata$6\n"); + headindex = 0; + for (headptr = import_list; headptr != NULL; headptr = headptr->next) + { + funcindex = 0; + for (funcptr = headptr->funchead; funcptr != NULL; + funcptr = funcptr->next) + { + fprintf (filvar,"funcptr%d_%d:\n", headindex, funcindex); + fprintf (filvar,"\t%s\t%d\n", ASM_SHORT, + ((funcptr->ord) & 0xFFFF)); + fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT, funcptr->name); + fprintf (filvar,"\t%s\t0\n", ASM_BYTE); + funcindex++; + } + headindex++; + } + + fprintf (filvar, "\n\t.section\t.idata$7\n"); + headindex = 0; + for (headptr = import_list; headptr != NULL; headptr = headptr->next) + { + fprintf (filvar,"dllname%d:\n", headindex); + fprintf (filvar,"\t%s\t\"%s\"\n", ASM_TEXT, headptr->dllname); + fprintf (filvar,"\t%s\t0\n", ASM_BYTE); + headindex++; + } +} + +static void +gen_exp_file () +{ + FILE *f; + int i; + export_type *exp; + dlist_type *dl; + + /* xgettext:c-format */ + inform (_("Generating export file: %s\n"), exp_name); + + f = fopen (TMP_ASM, FOPEN_WT); + if (!f) + /* xgettext:c-format */ + fatal (_("Unable to open temporary assembler file: %s"), TMP_ASM); + + /* xgettext:c-format */ + inform (_("Opened temporary file: %s"), TMP_ASM); + + dump_def_info (f); + + if (d_exports) + { + fprintf (f, "\t.section .edata\n\n"); + fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C); + fprintf (f, "\t%s 0x%lx %s Time and date\n", ASM_LONG, (long) time(0), + ASM_C); + fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C); + fprintf (f, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C); + fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_low_ord, ASM_C); + + + fprintf (f, "\t%s %d %s Number of functions\n", ASM_LONG, d_high_ord - d_low_ord + 1, ASM_C); + fprintf(f,"\t%s named funcs %d, low ord %d, high ord %d\n", + ASM_C, + d_named_nfuncs, d_low_ord, d_high_ord); + fprintf (f, "\t%s %d %s Number of names\n", ASM_LONG, + show_allnames ? d_high_ord - d_low_ord + 1 : d_named_nfuncs, ASM_C); + fprintf (f, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C); + + fprintf (f, "\t%sanames%s %s Address of Name Pointer Table\n", + ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C); + + fprintf (f, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C); + + fprintf (f, "name: %s \"%s\"\n", ASM_TEXT, dll_name); + + + fprintf(f,"%s Export address Table\n", ASM_C); + fprintf(f,"\t%s\n", ASM_ALIGN_LONG); + fprintf (f, "afuncs:\n"); + i = d_low_ord; + + for (exp = d_exports; exp; exp = exp->next) + { + if (exp->ordinal != i) + { +#if 0 + fprintf (f, "\t%s\t%d\t%s %d..%d missing\n", + ASM_SPACE, + (exp->ordinal - i) * 4, + ASM_C, + i, exp->ordinal - 1); + i = exp->ordinal; +#endif + while (i < exp->ordinal) + { + fprintf(f,"\t%s\t0\n", ASM_LONG); + i++; + } + } + fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE, + ASM_PREFIX, + exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal); + i++; + } + + fprintf (f,"%s Export Name Pointer Table\n", ASM_C); + fprintf (f, "anames:\n"); + + for (i = 0; (exp = d_exports_lexically[i]); i++) + { + if (!exp->noname || show_allnames) + fprintf (f, "\t%sn%d%s\n", + ASM_RVA_BEFORE, exp->ordinal, ASM_RVA_AFTER); + } + + fprintf (f,"%s Export Oridinal Table\n", ASM_C); + fprintf (f, "anords:\n"); + for (i = 0; (exp = d_exports_lexically[i]); i++) + { + if (!exp->noname || show_allnames) + fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_low_ord); + } + + fprintf(f,"%s Export Name Table\n", ASM_C); + for (i = 0; (exp = d_exports_lexically[i]); i++) + if (!exp->noname || show_allnames) + fprintf (f, "n%d: %s \"%s\"\n", + exp->ordinal, ASM_TEXT, exp->name); + + if (a_list) + { + fprintf (f, "\t.section .drectve\n"); + for (dl = a_list; dl; dl = dl->next) + { + fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text); + } + } + if (d_list) + { + fprintf (f, "\t.section .rdata\n"); + for (dl = d_list; dl; dl = dl->next) + { + char *p; + int l; + /* We dont output as ascii 'cause there can + be quote characters in the string */ + + l = 0; + for (p = dl->text; *p; p++) + { + if (l == 0) + fprintf (f, "\t%s\t", ASM_BYTE); + else + fprintf (f, ","); + fprintf (f, "%d", *p); + if (p[1] == 0) + { + fprintf (f, ",0\n"); + break; + } + if (++l == 10) + { + fprintf (f, "\n"); + l = 0; + } + } + } + } + } + + + /* Add to the output file a way of getting to the exported names + without using the import library. */ + if (add_indirect) + { + fprintf (f, "\t.section\t.rdata\n"); + for (i = 0, exp = d_exports; exp; i++, exp = exp->next) + if (!exp->noname || show_allnames) + { + /* We use a single underscore for MS compatibility, and a + double underscore for backward compatibility with old + cygwin releases. */ + fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name); + fprintf (f, "\t%s\t_imp__%s\n", ASM_GLOBAL, exp->name); + fprintf (f, "__imp_%s:\n", exp->name); + fprintf (f, "_imp__%s:\n", exp->name); + fprintf (f, "\t%s\t%s\n", ASM_LONG, exp->name); + } + } + + /* Dump the reloc section if a base file is provided */ + if (base_file) + { + int addr; + long need[PAGE_SIZE]; + long page_addr; + int numbytes; + int num_entries; + long *copy; + int j; + int on_page; + fprintf (f, "\t.section\t.init\n"); + fprintf (f, "lab:\n"); + + fseek (base_file, 0, SEEK_END); + numbytes = ftell (base_file); + fseek (base_file, 0, SEEK_SET); + copy = xmalloc (numbytes); + fread (copy, 1, numbytes, base_file); + num_entries = numbytes / sizeof (long); + + + fprintf (f, "\t.section\t.reloc\n"); + if (num_entries) + { + int src; + int dst = 0; + int last = -1; + int totsize = 0; + + qsort (copy, num_entries, sizeof (long), sfunc); + /* Delete duplcates */ + for (src = 0; src < num_entries; src++) + { + if (last != copy[src]) + last = copy[dst++] = copy[src]; + } + num_entries = dst; + addr = copy[0]; + page_addr = addr & PAGE_MASK; /* work out the page addr */ + on_page = 0; + for (j = 0; j < num_entries; j++) + { + totsize += 2; + addr = copy[j]; + if ((addr & PAGE_MASK) != page_addr) + { + totsize += 8 + (on_page & 1)*2; + flush_page (f, need, page_addr, on_page); + on_page = 0; + page_addr = addr & PAGE_MASK; + } + need[on_page++] = addr; + } + + /* Pad the section to an even 32-byte boundary. This will make + the BeOS loader much happier, and shouldn't matter for other + OSes. */ + while ((totsize + 8 + (on_page & 1)*2) % 32 != 0) + { + /* 0x0000 is an absolute relocation that should be ignored. */ + need[on_page++] = 0x0000; + totsize += 2; + } + + flush_page (f, need, page_addr, on_page); + + /* fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/ + } + } + + generate_idata_ofile (f); + + fclose (f); + + /* assemble the file */ + sprintf (outfile, "%s -o %s %s", as_flags, exp_name, TMP_ASM); + +#ifdef DLLTOOL_ARM + if (interwork) + strcat (outfile, " -mthumb-interwork"); +#endif + + run (as_name, outfile); + + if (dontdeltemps == 0) + unlink (TMP_ASM); + + inform (_("Generated exports file")); +} + +static const char * +xlate (name) + const char *name; +{ + if (add_underscore) + { + char *copy = xmalloc (strlen (name) + 2); + copy[0] = '_'; + strcpy (copy + 1, name); + name = copy; + } + + if (killat) + { + char *p; + p = strchr (name, '@'); + if (p) + *p = 0; + } + return name; +} + +/**********************************************************************/ + +#if 0 + +static void +dump_iat (f, exp) + FILE *f; + export_type *exp; +{ + if (exp->noname && !show_allnames ) + { + fprintf (f, "\t%s\t0x%08x\n", + ASM_LONG, + exp->ordinal | 0x80000000); /* hint or orindal ?? */ + } + else + { + fprintf (f, "\t%sID%d%s\n", ASM_RVA_BEFORE, + exp->ordinal, + ASM_RVA_AFTER); + } +} + +#endif + +typedef struct +{ + int id; + const char *name; + int flags; + int align; + asection *sec; + asymbol *sym; + asymbol **sympp; + int size; + unsigned char *data; +} sinfo; + +#ifndef DLLTOOL_PPC + +#define TEXT 0 +#define DATA 1 +#define BSS 2 +#define IDATA7 3 +#define IDATA5 4 +#define IDATA4 5 +#define IDATA6 6 + +#define NSECS 7 + +static sinfo secdata[NSECS] = +{ + { TEXT, ".text", SEC_CODE | SEC_HAS_CONTENTS, 2}, + { DATA, ".data", SEC_DATA, 2}, + { BSS, ".bss", 0, 2}, + { IDATA7, ".idata$7", SEC_HAS_CONTENTS, 2}, + { IDATA5, ".idata$5", SEC_HAS_CONTENTS, 2}, + { IDATA4, ".idata$4", SEC_HAS_CONTENTS, 2}, + { IDATA6, ".idata$6", SEC_HAS_CONTENTS, 1} +}; + +#else + +/* Sections numbered to make the order the same as other PowerPC NT */ +/* compilers. This also keeps funny alignment thingies from happening. */ +#define TEXT 0 +#define PDATA 1 +#define RDATA 2 +#define IDATA5 3 +#define IDATA4 4 +#define IDATA6 5 +#define IDATA7 6 +#define DATA 7 +#define BSS 8 + +#define NSECS 9 + +static sinfo secdata[NSECS] = +{ + { TEXT, ".text", SEC_CODE | SEC_HAS_CONTENTS, 3}, + { PDATA, ".pdata", SEC_HAS_CONTENTS, 2}, + { RDATA, ".reldata", SEC_HAS_CONTENTS, 2}, + { IDATA5, ".idata$5", SEC_HAS_CONTENTS, 2}, + { IDATA4, ".idata$4", SEC_HAS_CONTENTS, 2}, + { IDATA6, ".idata$6", SEC_HAS_CONTENTS, 1}, + { IDATA7, ".idata$7", SEC_HAS_CONTENTS, 2}, + { DATA, ".data", SEC_DATA, 2}, + { BSS, ".bss", 0, 2} +}; + +#endif + +/* +This is what we're trying to make. We generate the imp symbols with +both single and double underscores, for compatibility. + + .text + .global _GetFileVersionInfoSizeW@8 + .global __imp_GetFileVersionInfoSizeW@8 +_GetFileVersionInfoSizeW@8: + jmp * __imp_GetFileVersionInfoSizeW@8 + .section .idata$7 # To force loading of head + .long __version_a_head +# Import Address Table + .section .idata$5 +__imp_GetFileVersionInfoSizeW@8: + .rva ID2 + +# Import Lookup Table + .section .idata$4 + .rva ID2 +# Hint/Name table + .section .idata$6 +ID2: .short 2 + .asciz "GetFileVersionInfoSizeW" + + +For the PowerPC, here's the variation on the above scheme: + +# Rather than a simple "jmp *", the code to get to the dll function +# looks like: + .text + lwz r11,[tocv]__imp_function_name(r2) +# RELOC: 00000000 TOCREL16,TOCDEFN __imp_function_name + lwz r12,0(r11) + stw r2,4(r1) + mtctr r12 + lwz r2,4(r11) + bctr +*/ + +static char * +make_label (prefix, name) + const char *prefix; + const char *name; +{ + int len = strlen (ASM_PREFIX) + strlen (prefix) + strlen (name); + char *copy = xmalloc (len +1 ); + strcpy (copy, ASM_PREFIX); + strcat (copy, prefix); + strcat (copy, name); + return copy; +} + +static bfd * +make_one_lib_file (exp, i) + export_type *exp; + int i; +{ +#if 0 + { + FILE *f; + char *prefix="d"; + sprintf (outfile, "%ss%05d.s", prefix, i); + f = fopen (outfile, FOPEN_WT); + fprintf (f, "\t.text\n"); + fprintf (f, "\t%s\t%s%s\n", ASM_GLOBAL, ASM_PREFIX, exp->name); + fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name); + fprintf (f, "\t%s\t_imp__%s\n", ASM_GLOBAL, exp->name); + fprintf (f, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX, + exp->name, ASM_JUMP, exp->name); + + fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C); + fprintf (f, "\t%s\t%s\n", ASM_LONG, head_label); + + + fprintf (f,"%s Import Address Table\n", ASM_C); + + fprintf (f, "\t.section .idata$5\n"); + fprintf (f, "__imp_%s:\n", exp->name); + fprintf (f, "_imp__%s:\n", exp->name); + + dump_iat (f, exp); + + fprintf (f, "\n%s Import Lookup Table\n", ASM_C); + fprintf (f, "\t.section .idata$4\n"); + + dump_iat (f, exp); + + if(!exp->noname || show_allnames) + { + fprintf (f, "%s Hint/Name table\n", ASM_C); + fprintf (f, "\t.section .idata$6\n"); + fprintf (f, "ID%d:\t%s\t%d\n", exp->ordinal, ASM_SHORT, exp->hint); + fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name)); + } + + fclose (f); + + sprintf (outfile, "%s -o %ss%05d.o %ss%d.s", + as_flags, prefix, i, prefix, i); + +#ifdef DLLTOOL_ARM + if (interwork) + strcat (outfile, " -mthumb-interwork"); +#endif + + run (as_name, outfile); + } +#else /* if 0 */ + { + bfd * abfd; + asymbol * exp_label; + asymbol * iname; + asymbol * iname2; + asymbol * iname_lab; + asymbol ** iname_lab_pp; + asymbol ** iname_pp; +#ifdef DLLTOOL_PPC + asymbol ** fn_pp; + asymbol ** toc_pp; +#define EXTRA 2 +#endif +#ifndef EXTRA +#define EXTRA 0 +#endif + asymbol * ptrs[NSECS + 4 + EXTRA + 1]; + + char * outname = xmalloc (10); + int oidx = 0; + + + sprintf (outname, "%s%05d.o", TMP_STUB, i); + + abfd = bfd_openw (outname, HOW_BFD_TARGET); + + if (!abfd) + /* xgettext:c-format */ + fatal (_("bfd_open failed open stub file: %s"), outname); + + /* xgettext:c-format */ + inform (_("Creating stub file: %s"), outname); + + bfd_set_format (abfd, bfd_object); + bfd_set_arch_mach (abfd, HOW_BFD_ARCH, 0); + +#ifdef DLLTOOL_ARM + if (interwork) + bfd_set_private_flags (abfd, F_INTERWORK); +#endif + + /* First make symbols for the sections */ + for (i = 0; i < NSECS; i++) + { + sinfo *si = secdata + i; + if (si->id != i) + abort(); + si->sec = bfd_make_section_old_way (abfd, si->name); + bfd_set_section_flags (abfd, + si->sec, + si->flags); + + bfd_set_section_alignment(abfd, si->sec, si->align); + si->sec->output_section = si->sec; + si->sym = bfd_make_empty_symbol(abfd); + si->sym->name = si->sec->name; + si->sym->section = si->sec; + si->sym->flags = BSF_LOCAL; + si->sym->value = 0; + ptrs[oidx] = si->sym; + si->sympp = ptrs + oidx; + si->size = 0; + si->data = NULL; + + oidx++; + } + + if (! exp->data) + { + exp_label = bfd_make_empty_symbol (abfd); + exp_label->name = make_label ("", exp->name); + + /* On PowerPC, the function name points to a descriptor in + the rdata section, the first element of which is a + pointer to the code (..function_name), and the second + points to the .toc */ +#ifdef DLLTOOL_PPC + if (machine == MPPC) + exp_label->section = secdata[RDATA].sec; + else +#endif + exp_label->section = secdata[TEXT].sec; + + exp_label->flags = BSF_GLOBAL; + exp_label->value = 0; + +#ifdef DLLTOOL_ARM + if (machine == MTHUMB) + bfd_coff_set_symbol_class (abfd, exp_label, C_THUMBEXTFUNC); +#endif + ptrs[oidx++] = exp_label; + } + + /* Generate imp symbols with one underscore for Microsoft + compatibility, and with two underscores for backward + compatibility with old versions of cygwin. */ + iname = bfd_make_empty_symbol(abfd); + iname->name = make_label ("__imp_", exp->name); + iname->section = secdata[IDATA5].sec; + iname->flags = BSF_GLOBAL; + iname->value = 0; + + iname2 = bfd_make_empty_symbol(abfd); + iname2->name = make_label ("_imp__", exp->name); + iname2->section = secdata[IDATA5].sec; + iname2->flags = BSF_GLOBAL; + iname2->value = 0; + + iname_lab = bfd_make_empty_symbol(abfd); + + iname_lab->name = head_label; + iname_lab->section = (asection *)&bfd_und_section; + iname_lab->flags = 0; + iname_lab->value = 0; + + + iname_pp = ptrs + oidx; + ptrs[oidx++] = iname; + ptrs[oidx++] = iname2; + + iname_lab_pp = ptrs + oidx; + ptrs[oidx++] = iname_lab; + +#ifdef DLLTOOL_PPC + /* The symbol refering to the code (.text) */ + { + asymbol *function_name; + + function_name = bfd_make_empty_symbol(abfd); + function_name->name = make_label ("..", exp->name); + function_name->section = secdata[TEXT].sec; + function_name->flags = BSF_GLOBAL; + function_name->value = 0; + + fn_pp = ptrs + oidx; + ptrs[oidx++] = function_name; + } + + /* The .toc symbol */ + { + asymbol *toc_symbol; /* The .toc symbol */ + + toc_symbol = bfd_make_empty_symbol (abfd); + toc_symbol->name = make_label (".", "toc"); + toc_symbol->section = (asection *)&bfd_und_section; + toc_symbol->flags = BSF_GLOBAL; + toc_symbol->value = 0; + + toc_pp = ptrs + oidx; + ptrs[oidx++] = toc_symbol; + } +#endif + + ptrs[oidx] = 0; + + for (i = 0; i < NSECS; i++) + { + sinfo *si = secdata + i; + asection *sec = si->sec; + arelent *rel; + arelent **rpp; + + switch (i) + { + case TEXT: + if (! exp->data) + { + si->size = HOW_JTAB_SIZE; + si->data = xmalloc (HOW_JTAB_SIZE); + memcpy (si->data, HOW_JTAB, HOW_JTAB_SIZE); + + /* add the reloc into idata$5 */ + rel = xmalloc (sizeof (arelent)); + + rpp = xmalloc (sizeof (arelent *) * 2); + rpp[0] = rel; + rpp[1] = 0; + + rel->address = HOW_JTAB_ROFF; + rel->addend = 0; + + if (machine == MPPC) + { + rel->howto = bfd_reloc_type_lookup (abfd, + BFD_RELOC_16_GOTOFF); + rel->sym_ptr_ptr = iname_pp; + } + else + { + rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); + rel->sym_ptr_ptr = secdata[IDATA5].sympp; + } + sec->orelocation = rpp; + sec->reloc_count = 1; + } + break; + case IDATA4: + case IDATA5: + /* An idata$4 or idata$5 is one word long, and has an + rva to idata$6 */ + + si->data = xmalloc (4); + si->size = 4; + + if (exp->noname) + { + si->data[0] = exp->ordinal ; + si->data[1] = exp->ordinal >> 8; + si->data[2] = exp->ordinal >> 16; + si->data[3] = 0x80; + } + else + { + sec->reloc_count = 1; + memset (si->data, 0, si->size); + rel = xmalloc (sizeof (arelent)); + rpp = xmalloc (sizeof (arelent *) * 2); + rpp[0] = rel; + rpp[1] = 0; + rel->address = 0; + rel->addend = 0; + rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA); + rel->sym_ptr_ptr = secdata[IDATA6].sympp; + sec->orelocation = rpp; + } + + break; + + case IDATA6: + if (!exp->noname) + { + /* This used to add 1 to exp->hint. I don't know + why it did that, and it does not match what I see + in programs compiled with the MS tools. */ + int idx = exp->hint; + si->size = strlen (xlate (exp->name)) + 3; + si->data = xmalloc (si->size); + si->data[0] = idx & 0xff; + si->data[1] = idx >> 8; + strcpy (si->data + 2, xlate (exp->name)); + } + break; + case IDATA7: + si->size = 4; + si->data =xmalloc(4); + memset (si->data, 0, si->size); + rel = xmalloc (sizeof (arelent)); + rpp = xmalloc (sizeof (arelent *) * 2); + rpp[0] = rel; + rel->address = 0; + rel->addend = 0; + rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA); + rel->sym_ptr_ptr = iname_lab_pp; + sec->orelocation = rpp; + sec->reloc_count = 1; + break; + +#ifdef DLLTOOL_PPC + case PDATA: + { + /* The .pdata section is 5 words long. */ + /* Think of it as: */ + /* struct */ + /* { */ + /* bfd_vma BeginAddress, [0x00] */ + /* EndAddress, [0x04] */ + /* ExceptionHandler, [0x08] */ + /* HandlerData, [0x0c] */ + /* PrologEndAddress; [0x10] */ + /* }; */ + + /* So this pdata section setups up this as a glue linkage to + a dll routine. There are a number of house keeping things + we need to do: + + 1. In the name of glue trickery, the ADDR32 relocs for 0, + 4, and 0x10 are set to point to the same place: + "..function_name". + 2. There is one more reloc needed in the pdata section. + The actual glue instruction to restore the toc on + return is saved as the offset in an IMGLUE reloc. + So we need a total of four relocs for this section. + + 3. Lastly, the HandlerData field is set to 0x03, to indicate + that this is a glue routine. + */ + arelent *imglue, *ba_rel, *ea_rel, *pea_rel; + + /* alignment must be set to 2**2 or you get extra stuff */ + bfd_set_section_alignment(abfd, sec, 2); + + si->size = 4 * 5; + si->data =xmalloc(4 * 5); + memset (si->data, 0, si->size); + rpp = xmalloc (sizeof (arelent *) * 5); + rpp[0] = imglue = xmalloc (sizeof (arelent)); + rpp[1] = ba_rel = xmalloc (sizeof (arelent)); + rpp[2] = ea_rel = xmalloc (sizeof (arelent)); + rpp[3] = pea_rel = xmalloc (sizeof (arelent)); + rpp[4] = 0; + + /* stick the toc reload instruction in the glue reloc */ + bfd_put_32(abfd, ppc_glue_insn, (char *) &imglue->address); + + imglue->addend = 0; + imglue->howto = bfd_reloc_type_lookup (abfd, + BFD_RELOC_32_GOTOFF); + imglue->sym_ptr_ptr = fn_pp; + + ba_rel->address = 0; + ba_rel->addend = 0; + ba_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); + ba_rel->sym_ptr_ptr = fn_pp; + + bfd_put_32(abfd, 0x18, si->data + 0x04); + ea_rel->address = 4; + ea_rel->addend = 0; + ea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); + ea_rel->sym_ptr_ptr = fn_pp; + + /* mark it as glue */ + bfd_put_32(abfd, 0x03, si->data + 0x0c); + + /* mark the prolog end address */ + bfd_put_32(abfd, 0x0D, si->data + 0x10); + pea_rel->address = 0x10; + pea_rel->addend = 0; + pea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); + pea_rel->sym_ptr_ptr = fn_pp; + + sec->orelocation = rpp; + sec->reloc_count = 4; + break; + } + case RDATA: + /* Each external function in a PowerPC PE file has a two word + descriptor consisting of: + 1. The address of the code. + 2. The address of the appropriate .toc + We use relocs to build this. + */ + + si->size = 8; + si->data = xmalloc (8); + memset (si->data, 0, si->size); + + rpp = xmalloc (sizeof (arelent *) * 3); + rpp[0] = rel = xmalloc (sizeof (arelent)); + rpp[1] = xmalloc (sizeof (arelent)); + rpp[2] = 0; + + rel->address = 0; + rel->addend = 0; + rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); + rel->sym_ptr_ptr = fn_pp; + + rel = rpp[1]; + + rel->address = 4; + rel->addend = 0; + rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32); + rel->sym_ptr_ptr = toc_pp; + + sec->orelocation = rpp; + sec->reloc_count = 2; + break; +#endif /* DLLTOOL_PPC */ + } + } + + { + bfd_vma vma = 0; + /* Size up all the sections */ + for (i = 0; i < NSECS; i++) + { + sinfo *si = secdata + i; + + bfd_set_section_size (abfd, si->sec, si->size); + bfd_set_section_vma (abfd, si->sec, vma); + +/* vma += si->size;*/ + } + } + /* Write them out */ + for (i = 0; i < NSECS; i++) + { + sinfo *si = secdata + i; + + if (i == IDATA5 && no_idata5) + continue; + + if (i == IDATA4 && no_idata4) + continue; + + bfd_set_section_contents (abfd, si->sec, + si->data, 0, + si->size); + } + + bfd_set_symtab (abfd, ptrs, oidx); + bfd_close (abfd); + abfd = bfd_openr (outname, HOW_BFD_TARGET); + return abfd; + } +#endif +} + +static bfd * +make_head () +{ + FILE * f = fopen (TMP_HEAD_S, FOPEN_WT); + + fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C); + fprintf (f, "\t.section .idata$2\n"); + + fprintf(f,"\t%s\t%s\n", ASM_GLOBAL,head_label); + + fprintf (f, "%s:\n", head_label); + + fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n", + ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C); + + fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C); + fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C); + fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C); + fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C); + fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n", + ASM_RVA_BEFORE, + imp_name_lab, + ASM_RVA_AFTER, + ASM_C); + fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n", + ASM_RVA_BEFORE, + ASM_RVA_AFTER, ASM_C); + + fprintf (f, "%sStuff for compatibility\n", ASM_C); + + if (!no_idata5) + { + fprintf (f, "\t.section\t.idata$5\n"); + fprintf (f, "\t%s\t0\n", ASM_LONG); + fprintf (f, "fthunk:\n"); + } + if (!no_idata4) + { + fprintf (f, "\t.section\t.idata$4\n"); + + fprintf (f, "\t%s\t0\n", ASM_LONG); + fprintf (f, "\t.section .idata$4\n"); + fprintf (f, "hname:\n"); + } + fclose (f); + + sprintf (outfile, "%s -o %s %s", as_flags, TMP_HEAD_O, TMP_HEAD_S); + +#ifdef DLLTOOL_ARM + if (interwork) + strcat (outfile, " -mthumb-interwork"); +#endif + + run (as_name, outfile); + + return bfd_openr (TMP_HEAD_O, HOW_BFD_TARGET); +} + +static bfd * +make_tail () +{ + FILE * f = fopen (TMP_TAIL_S, FOPEN_WT); + + if (!no_idata4) + { + fprintf (f, "\t.section .idata$4\n"); + fprintf (f, "\t%s\t0\n", ASM_LONG); + } + if (!no_idata5) + { + fprintf (f, "\t.section .idata$5\n"); + fprintf (f, "\t%s\t0\n", ASM_LONG); + } + +#ifdef DLLTOOL_PPC + /* Normally, we need to see a null descriptor built in idata$3 to + act as the terminator for the list. The ideal way, I suppose, + would be to mark this section as a comdat type 2 section, so + only one would appear in the final .exe (if our linker supported + comdat, that is) or cause it to be inserted by something else (say + crt0) + */ + + fprintf (f, "\t.section .idata$3\n"); + fprintf (f, "\t%s\t0\n", ASM_LONG); + fprintf (f, "\t%s\t0\n", ASM_LONG); + fprintf (f, "\t%s\t0\n", ASM_LONG); + fprintf (f, "\t%s\t0\n", ASM_LONG); + fprintf (f, "\t%s\t0\n", ASM_LONG); +#endif + +#ifdef DLLTOOL_PPC + /* Other PowerPC NT compilers use idata$6 for the dllname, so I + do too. Original, huh? */ + fprintf (f, "\t.section .idata$6\n"); +#else + fprintf (f, "\t.section .idata$7\n"); +#endif + + fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab); + fprintf (f, "__%s_iname:\t%s\t\"%s\"\n", + imp_name_lab, ASM_TEXT, dll_name); + + fclose (f); + + sprintf (outfile, "%s -o %s %s", as_flags, TMP_TAIL_O, TMP_TAIL_S); + +#ifdef DLLTOOL_ARM + if (interwork) + strcat (outfile, " -mthumb-interwork"); +#endif + + run (as_name, outfile); + + return bfd_openr (TMP_TAIL_O, HOW_BFD_TARGET); +} + +static void +gen_lib_file () +{ + int i; + export_type *exp; + bfd *ar_head; + bfd *ar_tail; + bfd *outarch; + bfd * head = 0; + + unlink (imp_name); + + outarch = bfd_openw (imp_name, HOW_BFD_TARGET); + + if (!outarch) + /* xgettext:c-format */ + fatal (_("Can't open .lib file: %s"), imp_name); + + /* xgettext:c-format */ + inform (_("Creating library file: %s\n"), imp_name); + + bfd_set_format (outarch, bfd_archive); + outarch->has_armap = 1; + + /* Work out a reasonable size of things to put onto one line. */ + + ar_head = make_head (); + ar_tail = make_tail(); + + if (ar_head == NULL || ar_tail == NULL) + return; + + for (i = 0; (exp = d_exports_lexically[i]); i++) + { + bfd *n = make_one_lib_file (exp, i); + n->next = head; + head = n; + } + + /* Now stick them all into the archive */ + + ar_head->next = head; + ar_tail->next = ar_head; + head = ar_tail; + + if (! bfd_set_archive_head (outarch, head)) + bfd_fatal ("bfd_set_archive_head"); + + if (! bfd_close (outarch)) + bfd_fatal (imp_name); + + while (head != NULL) + { + bfd *n = head->next; + bfd_close (head); + head = n; + } + + /* Delete all the temp files */ + + if (dontdeltemps == 0) + { + unlink (TMP_HEAD_O); + unlink (TMP_HEAD_S); + unlink (TMP_TAIL_O); + unlink (TMP_TAIL_S); + } + + if (dontdeltemps < 2) + { + for (i = 0, exp = d_exports; exp; i++, exp = exp->next) + { + sprintf (outfile, "%s%05d.o", TMP_STUB, i); + if (unlink (outfile) < 0) + /* xgettext:c-format */ + warn (_("cannot delete %s: %s\n"), outfile, strerror (errno)); + } + } + + inform (_("Created lib file")); +} + +/**********************************************************************/ + +/* Run through the information gathered from the .o files and the + .def file and work out the best stuff */ +static int +pfunc (a, b) + const void *a; + const void *b; +{ + export_type *ap = *(export_type **) a; + export_type *bp = *(export_type **) b; + if (ap->ordinal == bp->ordinal) + return 0; + + /* unset ordinals go to the bottom */ + if (ap->ordinal == -1) + return 1; + if (bp->ordinal == -1) + return -1; + return (ap->ordinal - bp->ordinal); +} + +static int +nfunc (a, b) + const void *a; + const void *b; +{ + export_type *ap = *(export_type **) a; + export_type *bp = *(export_type **) b; + + return (strcmp (ap->name, bp->name)); +} + +static void +remove_null_names (ptr) + export_type **ptr; +{ + int src; + int dst; + for (dst = src = 0; src < d_nfuncs; src++) + { + if (ptr[src]) + { + ptr[dst] = ptr[src]; + dst++; + } + } + d_nfuncs = dst; +} + +static void +dtab (ptr) + export_type **ptr; +{ +#ifdef SACDEBUG + int i; + for (i = 0; i < d_nfuncs; i++) + { + if (ptr[i]) + { + printf ("%d %s @ %d %s%s%s\n", + i, ptr[i]->name, ptr[i]->ordinal, + ptr[i]->noname ? "NONAME " : "", + ptr[i]->constant ? "CONSTANT" : "", + ptr[i]->data ? "DATA" : ""); + } + else + printf ("empty\n"); + } +#endif +} + +static void +process_duplicates (d_export_vec) + export_type **d_export_vec; +{ + int more = 1; + int i; + while (more) + { + + more = 0; + /* Remove duplicates */ + qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc); + + dtab (d_export_vec); + for (i = 0; i < d_nfuncs - 1; i++) + { + if (strcmp (d_export_vec[i]->name, + d_export_vec[i + 1]->name) == 0) + { + + export_type *a = d_export_vec[i]; + export_type *b = d_export_vec[i + 1]; + + more = 1; + + /* xgettext:c-format */ + inform (_("Warning, ignoring duplicate EXPORT %s %d,%d\n"), + a->name, a->ordinal, b->ordinal); + + if (a->ordinal != -1 + && b->ordinal != -1) + /* xgettext:c-format */ + fatal (_("Error, duplicate EXPORT with oridinals: %s"), + a->name); + + /* Merge attributes */ + b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal; + b->constant |= a->constant; + b->noname |= a->noname; + b->data |= a->data; + d_export_vec[i] = 0; + } + + dtab (d_export_vec); + remove_null_names (d_export_vec); + dtab (d_export_vec); + } + } + + + /* Count the names */ + for (i = 0; i < d_nfuncs; i++) + { + if (!d_export_vec[i]->noname) + d_named_nfuncs++; + } +} + +static void +fill_ordinals (d_export_vec) + export_type **d_export_vec; +{ + int lowest = -1; + int i; + char *ptr; + int size = 65536; + + qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc); + + /* fill in the unset ordinals with ones from our range */ + + ptr = (char *) xmalloc (size); + + memset (ptr, 0, size); + + /* Mark in our large vector all the numbers that are taken */ + for (i = 0; i < d_nfuncs; i++) + { + if (d_export_vec[i]->ordinal != -1) + { + ptr[d_export_vec[i]->ordinal] = 1; + if (lowest == -1 || d_export_vec[i]->ordinal < lowest) + { + lowest = d_export_vec[i]->ordinal; + } + } + } + + /* Start at 1 for compatibility with MS toolchain. */ + if (lowest == -1) + lowest = 1; + + /* Now fill in ordinals where the user wants us to choose. */ + for (i = 0; i < d_nfuncs; i++) + { + if (d_export_vec[i]->ordinal == -1) + { + register int j; + + /* First try within or after any user supplied range. */ + for (j = lowest; j < size; j++) + if (ptr[j] == 0) + { + ptr[j] = 1; + d_export_vec[i]->ordinal = j; + goto done; + } + + /* Then try before the range. */ + for (j = lowest; j >0; j--) + if (ptr[j] == 0) + { + ptr[j] = 1; + d_export_vec[i]->ordinal = j; + goto done; + } + done:; + } + } + + free (ptr); + + /* And resort */ + + qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc); + + /* Work out the lowest and highest ordinal numbers. */ + if (d_nfuncs) + { + if (d_export_vec[0]) + d_low_ord = d_export_vec[0]->ordinal; + if (d_export_vec[d_nfuncs-1]) + d_high_ord = d_export_vec[d_nfuncs-1]->ordinal; + } +} + +static int +alphafunc (av,bv) + const void *av; + const void *bv; +{ + const export_type **a = (const export_type **) av; + const export_type **b = (const export_type **) bv; + + return strcmp ((*a)->name, (*b)->name); +} + +static void +mangle_defs () +{ + /* First work out the minimum ordinal chosen */ + + export_type *exp; + + int i; + int hint = 0; + export_type **d_export_vec + = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs); + + inform (_("Processing definitions")); + + for (i = 0, exp = d_exports; exp; i++, exp = exp->next) + { + d_export_vec[i] = exp; + } + + process_duplicates (d_export_vec); + fill_ordinals (d_export_vec); + + /* Put back the list in the new order */ + d_exports = 0; + for (i = d_nfuncs - 1; i >= 0; i--) + { + d_export_vec[i]->next = d_exports; + d_exports = d_export_vec[i]; + } + + /* Build list in alpha order */ + d_exports_lexically = (export_type **) + xmalloc (sizeof (export_type *) * (d_nfuncs + 1)); + + for (i = 0, exp = d_exports; exp; i++, exp = exp->next) + { + d_exports_lexically[i] = exp; + } + d_exports_lexically[i] = 0; + + qsort (d_exports_lexically, i, sizeof (export_type *), alphafunc); + + /* Fill exp entries with their hint values */ + + for (i = 0; i < d_nfuncs; i++) + { + if (!d_exports_lexically[i]->noname || show_allnames) + d_exports_lexically[i]->hint = hint++; + } + + inform (_("Processed definitions")); +} + +/**********************************************************************/ + +static void +usage (file, status) + FILE *file; + int status; +{ + /* xgetext:c-format */ + fprintf (file, _("Usage %s <options> <object-files>\n"), program_name); + /* xgetext:c-format */ + fprintf (file, _(" -m --machine <machine> Create {arm, i386, ppc, thumb} DLL. [default: %s]\n"), mname); + fprintf (file, _(" -e --output-exp <outname> Generate an export file.\n")); + fprintf (file, _(" -l --output-lib <outname> Generate an interface library.\n")); + fprintf (file, _(" -a --add-indirect Add dll indirects to export file.\n")); + fprintf (file, _(" -D --dllname <name> Name of input dll to put into interface lib.\n")); + fprintf (file, _(" -d --input-def <deffile> Name of .def file to be read in.\n")); + fprintf (file, _(" -z --output-def <deffile> Name of .def file to be created.\n")); + fprintf (file, _(" --export-all-symbols Export all symbols to .def\n")); + fprintf (file, _(" --no-export-all-symbols Only export listed symbols\n")); + fprintf (file, _(" --exclude-symbols <list> Don't export <list>\n")); + fprintf (file, _(" --no-default-excludes Clear default exclude symbols\n")); + fprintf (file, _(" -b --base-file <basefile> Read linker generated base file.\n")); + fprintf (file, _(" -x --no-idata4 Don't generate idata$4 section.\n")); + fprintf (file, _(" -c --no-idata5 Don't generate idata$5 section.\n")); + fprintf (file, _(" -U --add-underscore Add underscores to symbols in interface library.\n")); + fprintf (file, _(" -k --kill-at Kill @<n> from exported names.\n")); + fprintf (file, _(" -A --add-stdcall-alias Add aliases without @<n>.\n")); + fprintf (file, _(" -S --as <name> Use <name> for assembler.\n")); + fprintf (file, _(" -f --as-flags <flags> Pass <flags> to the assembler.\n")); +#ifdef DLLTOOL_ARM + fprintf (file, _(" -i --interwork Support ARM/Thumb interworking.\n")); +#endif + fprintf (file, _(" -n --no-delete Keep temp files (repeat for extra preservation).\n")); + fprintf (file, _(" -v --verbose Be verbose.\n")); + fprintf (file, _(" -V --version Display the program version.\n")); + fprintf (file, _(" -h --help Display this information.\n")); + + exit (status); +} + +#define OPTION_EXPORT_ALL_SYMS 150 +#define OPTION_NO_EXPORT_ALL_SYMS (OPTION_EXPORT_ALL_SYMS + 1) +#define OPTION_EXCLUDE_SYMS (OPTION_NO_EXPORT_ALL_SYMS + 1) +#define OPTION_NO_DEFAULT_EXCLUDES (OPTION_EXCLUDE_SYMS + 1) +#define OPTION_NO_IDATA4 'x' +#define OPTION_NO_IDATA5 'c' + +static const struct option long_options[] = +{ + {"no-delete", no_argument, NULL, 'n'}, + {"dllname", required_argument, NULL, 'D'}, + {"no-idata4", no_argument, NULL, OPTION_NO_IDATA4}, + {"no-idata5", no_argument, NULL, OPTION_NO_IDATA5}, + {"output-exp", required_argument, NULL, 'e'}, + {"output-def", required_argument, NULL, 'z'}, + {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL_SYMS}, + {"no-export-all-symbols", no_argument, NULL, OPTION_NO_EXPORT_ALL_SYMS}, + {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMS}, + {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES}, + {"output-lib", required_argument, NULL, 'l'}, + {"def", required_argument, NULL, 'd'}, /* for compatiblity with older versions */ + {"input-def", required_argument, NULL, 'd'}, + {"add-underscore", no_argument, NULL, 'U'}, + {"kill-at", no_argument, NULL, 'k'}, + {"add-stdcall-alias", no_argument, NULL, 'A'}, + {"verbose", no_argument, NULL, 'v'}, + {"version", no_argument, NULL, 'V'}, + {"help", no_argument, NULL, 'h'}, + {"machine", required_argument, NULL, 'm'}, + {"add-indirect", no_argument, NULL, 'a'}, + {"base-file", required_argument, NULL, 'b'}, + {"as", required_argument, NULL, 'S'}, + {"as-flags", required_argument, NULL, 'f'}, +#ifdef DLLTOOL_ARM + {"interwork", no_argument, NULL, 'i'}, +#endif + {0} +}; + +int +main (ac, av) + int ac; + char **av; +{ + int c; + int i; + char *firstarg = 0; + program_name = av[0]; + oav = av; + +#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) + setlocale (LC_MESSAGES, ""); +#endif + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + + while ((c = getopt_long (ac, av, "xcz:S:aD:l:e:nkAvVb:Uh?m:d:f:i", + long_options, 0)) + != EOF) + { + switch (c) + { + case OPTION_NO_IDATA4: + no_idata4 = 1; + break; + case OPTION_NO_IDATA5: + no_idata5 = 1; + break; + case OPTION_EXPORT_ALL_SYMS: + export_all_symbols = true; + break; + case OPTION_NO_EXPORT_ALL_SYMS: + export_all_symbols = false; + break; + case OPTION_EXCLUDE_SYMS: + add_excludes (optarg); + break; + case OPTION_NO_DEFAULT_EXCLUDES: + do_default_excludes = false; + break; + case 'S': + as_name = optarg; + break; + case 'f': + as_flags = optarg; + break; + + /* ignored for compatibility */ + case 'u': + break; + case 'a': + add_indirect = 1; + break; + case 'z': + output_def = fopen (optarg, FOPEN_WT); + break; + case 'D': + dll_name = optarg; + break; + case 'l': + imp_name = optarg; + break; + case 'e': + exp_name = optarg; + break; + case 'h': + usage (stdout, 0); + break; + case 'm': + mname = optarg; + break; + case 'v': + verbose = 1; + break; + case 'V': + print_version (program_name); + break; +#ifdef DLLTOOL_ARM + case 'i': + interwork = 1; + break; +#endif + case 'y': +#if 0 + /* We don't currently define YYDEBUG when building + defparse.y. */ + yydebug = 1; +#endif + break; + case 'U': + add_underscore = 1; + break; + case 'k': + killat = 1; + break; + case 'A': + add_stdcall_alias = 1; + break; + case 'd': + def_file = optarg; + break; + case 'n': + dontdeltemps++; + break; + case 'b': + base_file = fopen (optarg, FOPEN_RB); + + if (!base_file) + /* xgettext:c-format */ + fatal (_("Unable to open base-file: %s"), optarg); + + break; + default: + usage (stderr, 1); + break; + } + } + + for (i = 0; mtable[i].type; i++) + { + if (strcmp (mtable[i].type, mname) == 0) + break; + } + + if (!mtable[i].type) + /* xgettext:c-format */ + fatal (_("Machine '%s' not supported"), mname); + + machine = i; + +#ifdef DLLTOOL_ARM + /* Always enable interworking for Thumb targets. */ + if (machine == MTHUMB && (! interwork)) + interwork = 1; +#endif + + if (!dll_name && exp_name) + { + int len = strlen (exp_name) + 5; + dll_name = xmalloc (len); + strcpy (dll_name, exp_name); + strcat (dll_name, ".dll"); + } + + /* Don't use the default exclude list if we're reading only the + symbols in the .drectve section. The default excludes are meant + to avoid exporting DLL entry point and Cygwin32 impure_ptr. */ + if (! export_all_symbols) + do_default_excludes = false; + + if (do_default_excludes) + set_default_excludes (); + + if (def_file) + process_def_file (def_file); + + while (optind < ac) + { + if (!firstarg) + firstarg = av[optind]; + scan_obj_file (av[optind]); + optind++; + } + + mangle_defs (); + + if (exp_name) + gen_exp_file (); + + if (imp_name) + { + /* Make imp_name safe for use as a label. */ + char *p; + + imp_name_lab = xstrdup (imp_name); + for (p = imp_name_lab; *p; p++) + { + if (!isalpha ((unsigned char) *p) && !isdigit ((unsigned char) *p)) + *p = '_'; + } + head_label = make_label("_head_", imp_name_lab); + gen_lib_file (); + } + + if (output_def) + gen_def_file (); + + return 0; +} diff --git a/binutils/dlltool.h b/binutils/dlltool.h new file mode 100644 index 0000000..b4167c8 --- /dev/null +++ b/binutils/dlltool.h @@ -0,0 +1,42 @@ +/* dlltool.h -- header file for dlltool + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#include "ansidecl.h" +#include <stdio.h> + +extern void def_code PARAMS ((int)); +extern void def_data PARAMS ((int)); +extern void def_description PARAMS ((const char *)); +extern void def_exports + PARAMS ((const char *, const char *, int, int, int, int)); +extern void def_heapsize PARAMS ((int, int)); +extern void def_import + PARAMS ((const char *, const char *, const char *, const char *, int)); +extern void def_library PARAMS ((const char *, int)); +extern void def_name PARAMS ((const char *, int)); +extern void def_section PARAMS ((const char *, int)); +extern void def_stacksize PARAMS ((int, int)); +extern void def_version PARAMS ((int, int)); +extern int yyparse PARAMS ((void)); +extern int yyerror PARAMS ((const char *)); +extern int yydebug; +extern int yylex PARAMS ((void)); +extern FILE *yyin; +extern int linenumber; diff --git a/binutils/dllwrap.c b/binutils/dllwrap.c new file mode 100644 index 0000000..574611b --- /dev/null +++ b/binutils/dllwrap.c @@ -0,0 +1,1050 @@ +/* dllwrap.c -- wrapper for DLLTOOL and GCC to generate PE style DLLs + Copyright (C) 1998, 1999 Free Software Foundation, Inc. + Contributed by Mumit Khan (khan@xraylith.wisc.edu). + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* AIX requires this to be the first thing in the file. */ +#ifndef __GNUC__ +# ifdef _AIX + #pragma alloca +#endif +#endif + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <errno.h> +#include <string.h> +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include "bfd.h" +#include "libiberty.h" +#include "bucomm.h" +#include "getopt.h" +#include "dyn-string.h" + +#include <ctype.h> +#include <time.h> + +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#else /* ! HAVE_SYS_WAIT_H */ +#if ! defined (_WIN32) || defined (__CYGWIN32__) +#ifndef WIFEXITED +#define WIFEXITED(w) (((w)&0377) == 0) +#endif +#ifndef WIFSIGNALED +#define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0) +#endif +#ifndef WTERMSIG +#define WTERMSIG(w) ((w) & 0177) +#endif +#ifndef WEXITSTATUS +#define WEXITSTATUS(w) (((w) >> 8) & 0377) +#endif +#else /* defined (_WIN32) && ! defined (__CYGWIN32__) */ +#ifndef WIFEXITED +#define WIFEXITED(w) (((w) & 0xff) == 0) +#endif +#ifndef WIFSIGNALED +#define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f) +#endif +#ifndef WTERMSIG +#define WTERMSIG(w) ((w) & 0x7f) +#endif +#ifndef WEXITSTATUS +#define WEXITSTATUS(w) (((w) & 0xff00) >> 8) +#endif +#endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */ +#endif /* ! HAVE_SYS_WAIT_H */ + +static char *program_version = "0.2.4"; +static char *driver_name = "gcc"; +static char *cygwin_driver_flags = + "-Wl,--dll -nostartfiles"; +static char *mingw32_driver_flags = "-mdll"; +static char *generic_driver_flags = "-Wl,--dll"; + +static char *entry_point; + +static char *dlltool_name = "dlltool"; + +static char *target = TARGET; + +typedef enum { + UNKNOWN_TARGET, + CYGWIN_TARGET, + MINGW32_TARGET +} +target_type; + +static target_type which_target = UNKNOWN_TARGET; + +static int dontdeltemps = 0; +static int dry_run = 0; + +static char *program_name; + +static int verbose = 0; + +static char *dll_file_name; +static char *dll_name; +static char *base_file_name; +static char *exp_file_name; +static char *def_file_name; +static int delete_base_file = 1; +static int delete_exp_file = 1; +static int delete_def_file = 1; + +static int run PARAMS ((const char *, char *)); +static void usage PARAMS ((FILE *, int)); +static void delete_temp_files PARAMS ((void)); +static void cleanup_and_exit PARAMS ((int status)); + +/**********************************************************************/ + +static void +delete_temp_files () +{ + if (delete_base_file && base_file_name) + { + if (verbose) + fprintf (stderr, "%s temporary base file %s\n", + dontdeltemps ? "Keeping" : "Deleting", + base_file_name); + if (! dontdeltemps) + { + unlink (base_file_name); + free (base_file_name); + } + } + + if (delete_exp_file && exp_file_name) + { + if (verbose) + fprintf (stderr, "%s temporary exp file %s\n", + dontdeltemps ? "Keeping" : "Deleting", + exp_file_name); + if (! dontdeltemps) + { + unlink (exp_file_name); + free (exp_file_name); + } + } + if (delete_def_file && def_file_name) + { + if (verbose) + fprintf (stderr, "%s temporary def file %s\n", + dontdeltemps ? "Keeping" : "Deleting", + def_file_name); + if (! dontdeltemps) + { + unlink (def_file_name); + free (def_file_name); + } + } +} + +static void +cleanup_and_exit (int status) +{ + delete_temp_files (); + exit (status); +} + +static int +run (what, args) + const char *what; + char *args; +{ + char *s; + int pid, wait_status, retcode; + int i; + const char **argv; + char *errmsg_fmt, *errmsg_arg; + char *temp_base = choose_temp_base (); + int in_quote; + char sep; + + if (verbose || dry_run) + fprintf (stderr, "%s %s\n", what, args); + + /* Count the args */ + i = 0; + for (s = args; *s; s++) + if (*s == ' ') + i++; + i++; + argv = alloca (sizeof (char *) * (i + 3)); + i = 0; + argv[i++] = what; + s = args; + while (1) + { + while (*s == ' ' && *s != 0) + s++; + if (*s == 0) + break; + in_quote = (*s == '\'' || *s == '"'); + sep = (in_quote) ? *s++ : ' '; + argv[i++] = s; + while (*s != sep && *s != 0) + s++; + if (*s == 0) + break; + *s++ = 0; + if (in_quote) + s++; + } + argv[i++] = NULL; + + if (dry_run) + return 0; + + pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base, + &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH); + + if (pid == -1) + { + int errno_val = errno; + + fprintf (stderr, "%s: ", program_name); + fprintf (stderr, errmsg_fmt, errmsg_arg); + fprintf (stderr, ": %s\n", strerror (errno_val)); + return 1; + } + + retcode = 0; + pid = pwait (pid, &wait_status, 0); + if (pid == -1) + { + fprintf (stderr, "%s: wait: %s\n", program_name, strerror (errno)); + retcode = 1; + } + else if (WIFSIGNALED (wait_status)) + { + fprintf (stderr, "%s: subprocess got fatal signal %d\n", + program_name, WTERMSIG (wait_status)); + retcode = 1; + } + else if (WIFEXITED (wait_status)) + { + if (WEXITSTATUS (wait_status) != 0) + { + fprintf (stderr, "%s: %s exited with status %d\n", + program_name, what, WEXITSTATUS (wait_status)); + retcode = 1; + } + } + else + retcode = 1; + + return retcode; +} + +static char * +mybasename (name) + const char *name; +{ + const char *base = name; + + while (*name) + { + if (*name == '/' || *name == '\\') + { + base = name + 1; + } + ++name; + } + return (char *) base; +} + +static int +strhash (const char *str) +{ + const unsigned char *s; + unsigned long hash; + unsigned int c; + unsigned int len; + + hash = 0; + len = 0; + s = (const unsigned char *) str; + while ((c = *s++) != '\0') + { + hash += c + (c << 17); + hash ^= hash >> 2; + ++len; + } + hash += len + (len << 17); + hash ^= hash >> 2; + + return hash; +} + +/**********************************************************************/ + +void +print_version (name) + const char *name; +{ + /* This output is intended to follow the GNU standards document. */ + /* xgettext:c-format */ + printf ("GNU %s %s\n", name, program_version); + printf ("Copyright 1998 Free Software Foundation, Inc.\n"); + printf ("\ +This program is free software; you may redistribute it under the terms of\n\ +the GNU General Public License. This program has absolutely no warranty.\n"); + exit (0); +} + +static void +usage (file, status) + FILE *file; + int status; +{ + fprintf (file, "Usage %s <options> <object-files>\n", program_name); + fprintf (file, " Generic options:\n"); + fprintf (file, " --quiet, -q Work quietly\n"); + fprintf (file, " --verbose, -v Verbose\n"); + fprintf (file, " --version Print dllwrap version\n"); + fprintf (file, " --implib <outname> Synonym for --output-lib\n"); + fprintf (file, " Options for %s:\n", program_name); + fprintf (file, " --driver-name <driver> Defaults to \"gcc\"\n"); + fprintf (file, " --driver-flags <flags> Override default ld flags\n"); + fprintf (file, " --dlltool-name <dlltool> Defaults to \"dlltool\"\n"); + fprintf (file, " --entry <entry> Specify alternate DLL entry point\n"); + fprintf (file, " --image-base <base> Specify image base address\n"); + fprintf (file, " --target <machine> i386-cygwin32 or i386-mingw32\n"); + fprintf (file, " --dry-run Show what needs to be run\n"); + fprintf (file, " Options passed to DLLTOOL:\n"); + fprintf (file, " --machine <machine>\n"); + fprintf (file, " --output-exp <outname> Generate export file.\n"); + fprintf (file, " --output-lib <outname> Generate input library.\n"); + fprintf (file, " --add-indirect Add dll indirects to export file.\n"); + fprintf (file, " --dllname <name> Name of input dll to put into output lib.\n"); + fprintf (file, " --def <deffile> Name input .def file\n"); + fprintf (file, " --output-def <deffile> Name output .def file\n"); + fprintf (file, " --export-all-symbols Export all symbols to .def\n"); + fprintf (file, " --no-export-all-symbols Only export .drectve symbols\n"); + fprintf (file, " --exclude-symbols <list> Exclude <list> from .def\n"); + fprintf (file, " --no-default-excludes Zap default exclude symbols\n"); + fprintf (file, " --base-file <basefile> Read linker generated base file\n"); + fprintf (file, " --no-idata4 Don't generate idata$4 section\n"); + fprintf (file, " --no-idata5 Don't generate idata$5 section\n"); + fprintf (file, " -U Add underscores to .lib\n"); + fprintf (file, " -k Kill @<n> from exported names\n"); + fprintf (file, " --add-stdcall-alias Add aliases without @<n>\n"); + fprintf (file, " --as <name> Use <name> for assembler\n"); + fprintf (file, " --nodelete Keep temp files.\n"); + fprintf (file, " Rest are passed unmodified to the language driver\n"); + fprintf (file, "\n\n"); + exit (status); +} + +#define OPTION_START 149 + +/* GENERIC options. */ +#define OPTION_QUIET (OPTION_START + 1) +#define OPTION_VERBOSE (OPTION_QUIET + 1) +#define OPTION_VERSION (OPTION_VERBOSE + 1) + +/* DLLWRAP options. */ +#define OPTION_DRY_RUN (OPTION_VERSION + 1) +#define OPTION_DRIVER_NAME (OPTION_DRY_RUN + 1) +#define OPTION_DRIVER_FLAGS (OPTION_DRIVER_NAME + 1) +#define OPTION_DLLTOOL_NAME (OPTION_DRIVER_FLAGS + 1) +#define OPTION_ENTRY (OPTION_DLLTOOL_NAME + 1) +#define OPTION_IMAGE_BASE (OPTION_ENTRY + 1) +#define OPTION_TARGET (OPTION_IMAGE_BASE + 1) + +/* DLLTOOL options. */ +#define OPTION_NODELETE (OPTION_TARGET + 1) +#define OPTION_DLLNAME (OPTION_NODELETE + 1) +#define OPTION_NO_IDATA4 (OPTION_DLLNAME + 1) +#define OPTION_NO_IDATA5 (OPTION_NO_IDATA4 + 1) +#define OPTION_OUTPUT_EXP (OPTION_NO_IDATA5 + 1) +#define OPTION_OUTPUT_DEF (OPTION_OUTPUT_EXP + 1) +#define OPTION_EXPORT_ALL_SYMS (OPTION_OUTPUT_DEF + 1) +#define OPTION_NO_EXPORT_ALL_SYMS (OPTION_EXPORT_ALL_SYMS + 1) +#define OPTION_EXCLUDE_SYMS (OPTION_NO_EXPORT_ALL_SYMS + 1) +#define OPTION_NO_DEFAULT_EXCLUDES (OPTION_EXCLUDE_SYMS + 1) +#define OPTION_OUTPUT_LIB (OPTION_NO_DEFAULT_EXCLUDES + 1) +#define OPTION_DEF (OPTION_OUTPUT_LIB + 1) +#define OPTION_ADD_UNDERSCORE (OPTION_DEF + 1) +#define OPTION_KILLAT (OPTION_ADD_UNDERSCORE + 1) +#define OPTION_HELP (OPTION_KILLAT + 1) +#define OPTION_MACHINE (OPTION_HELP + 1) +#define OPTION_ADD_INDIRECT (OPTION_MACHINE + 1) +#define OPTION_BASE_FILE (OPTION_ADD_INDIRECT + 1) +#define OPTION_AS (OPTION_BASE_FILE + 1) + +static const struct option long_options[] = +{ + /* generic options. */ + {"quiet", no_argument, NULL, 'q'}, + {"verbose", no_argument, NULL, 'v'}, + {"version", no_argument, NULL, OPTION_VERSION}, + {"implib", required_argument, NULL, OPTION_OUTPUT_LIB}, + + /* dllwrap options. */ + {"dry-run", no_argument, NULL, OPTION_DRY_RUN}, + {"driver-name", required_argument, NULL, OPTION_DRIVER_NAME}, + {"driver-flags", required_argument, NULL, OPTION_DRIVER_FLAGS}, + {"dlltool-name", required_argument, NULL, OPTION_DLLTOOL_NAME}, + {"entry", required_argument, NULL, 'e'}, + {"image-base", required_argument, NULL, OPTION_IMAGE_BASE}, + {"target", required_argument, NULL, OPTION_TARGET}, + + /* dlltool options. */ + {"no-delete", no_argument, NULL, 'n'}, + {"dllname", required_argument, NULL, OPTION_DLLNAME}, + {"no-idata4", no_argument, NULL, OPTION_NO_IDATA4}, + {"no-idata5", no_argument, NULL, OPTION_NO_IDATA5}, + {"output-exp", required_argument, NULL, OPTION_OUTPUT_EXP}, + {"output-def", required_argument, NULL, OPTION_OUTPUT_DEF}, + {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL_SYMS}, + {"no-export-all-symbols", no_argument, NULL, OPTION_NO_EXPORT_ALL_SYMS}, + {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMS}, + {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES}, + {"output-lib", required_argument, NULL, OPTION_OUTPUT_LIB}, + {"def", required_argument, NULL, OPTION_DEF}, + {"add-underscore", no_argument, NULL, 'U'}, + {"killat", no_argument, NULL, 'k'}, + {"add-stdcall-alias", no_argument, NULL, 'A'}, + {"help", no_argument, NULL, 'h'}, + {"machine", required_argument, NULL, OPTION_MACHINE}, + {"add-indirect", no_argument, NULL, OPTION_ADD_INDIRECT}, + {"base-file", required_argument, NULL, OPTION_BASE_FILE}, + {"as", required_argument, NULL, OPTION_AS}, + {0} +}; + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int i; + + char **saved_argv = 0; + int cmdline_len = 0; + + int export_all = 0; + + int *dlltool_arg_indices; + int *driver_arg_indices; + + char *driver_flags = 0; + char *output_lib_file_name = 0; + + dyn_string_t dlltool_cmdline; + dyn_string_t driver_cmdline; + + int def_file_seen = 0; + + char *image_base_str = 0; + + program_name = argv[0]; + + saved_argv = (char **) xmalloc (argc * sizeof (char*)); + dlltool_arg_indices = (int *) xmalloc (argc * sizeof (int)); + driver_arg_indices = (int *) xmalloc (argc * sizeof (int)); + for (i = 0; i < argc; ++i) + { + size_t len = strlen (argv[i]); + char *arg = (char *) xmalloc (len + 1); + strcpy (arg, argv[i]); + cmdline_len += len; + saved_argv[i] = arg; + dlltool_arg_indices[i] = 0; + driver_arg_indices[i] = 1; + } + cmdline_len++; + + /* We recognize dllwrap and dlltool options, and everything else is + passed onto the language driver (eg., to GCC). We collect options + to dlltool and driver in dlltool_args and driver_args. */ + + opterr = 0; + while ((c = getopt_long_only (argc, argv, "nkAqve:Uho:l:L:I:", + long_options, (int *) 0)) != EOF) + { + int dlltool_arg; + int driver_arg; + int single_word_option_value_pair; + + dlltool_arg = 0; + driver_arg = 1; + single_word_option_value_pair = 0; + + if (c != '?') + { + /* We recognize this option, so it has to be either dllwrap or + dlltool option. Do not pass to driver unless it's one of the + generic options that are passed to all the tools (such as -v) + which are dealt with later. */ + driver_arg = 0; + } + + /* deal with generic and dllwrap options first. */ + switch (c) + { + case 'h': + usage (stdout, 0); + break; + case 'q': + verbose = 0; + break; + case 'v': + verbose = 1; + break; + case OPTION_VERSION: + print_version (program_name); + break; + case 'e': + entry_point = optarg; + break; + case OPTION_IMAGE_BASE: + image_base_str = optarg; + break; + case OPTION_DEF: + def_file_name = optarg; + def_file_seen = 1; + delete_def_file = 0; + break; + case 'n': + dontdeltemps = 1; + dlltool_arg = 1; + break; + case 'o': + dll_file_name = optarg; + break; + case 'I': + case 'l': + case 'L': + driver_arg = 1; + break; + case OPTION_DLLNAME: + dll_name = optarg; + break; + case OPTION_DRY_RUN: + dry_run = 1; + break; + case OPTION_DRIVER_NAME: + driver_name = optarg; + break; + case OPTION_DRIVER_FLAGS: + driver_flags = optarg; + break; + case OPTION_DLLTOOL_NAME: + dlltool_name = optarg; + break; + case OPTION_TARGET: + target = optarg; + break; + case OPTION_BASE_FILE: + base_file_name = optarg; + delete_base_file = 0; + break; + case OPTION_OUTPUT_EXP: + exp_file_name = optarg; + delete_exp_file = 0; + break; + case OPTION_EXPORT_ALL_SYMS: + export_all = 1; + break; + case OPTION_OUTPUT_LIB: + output_lib_file_name = optarg; + break; + case '?': + break; + default: + dlltool_arg = 1; + break; + } + + /* Handle passing through --option=value case. */ + if (optarg + && saved_argv[optind-1][0] == '-' + && saved_argv[optind-1][1] == '-' + && strchr (saved_argv[optind-1], '=')) + single_word_option_value_pair = 1; + + if (dlltool_arg) + { + dlltool_arg_indices[optind-1] = 1; + if (optarg && ! single_word_option_value_pair) + { + dlltool_arg_indices[optind-2] = 1; + } + } + + if (! driver_arg) + { + driver_arg_indices[optind-1] = 0; + if (optarg && ! single_word_option_value_pair) + { + driver_arg_indices[optind-2] = 0; + } + } + } + + /* sanity checks. */ + if (! dll_name && ! dll_file_name) + { + fprintf (stderr, + "%s: Must provide at least one of -o or --dllname options\n", + program_name); + exit (1); + } + else if (! dll_name) + { + dll_name = xstrdup (mybasename (dll_file_name)); + } + else if (! dll_file_name) + { + dll_file_name = xstrdup (dll_name); + } + + if (! def_file_seen) + { + char *fileprefix = choose_temp_base (); + def_file_name = (char *) xmalloc (strlen (fileprefix) + 5); + sprintf (def_file_name, "%s.def", + (dontdeltemps) ? mybasename (fileprefix) : fileprefix); + delete_def_file = 1; + free (fileprefix); + delete_def_file = 1; + fprintf (stderr, "Warning: no export definition file provided\n"); + fprintf (stderr, + "dllwrap will create one, but may not be what you want\n"); + } + + /* set the target platform. */ + if (strstr (target, "cygwin32")) + which_target = CYGWIN_TARGET; + else if (strstr (target, "mingw32")) + which_target = MINGW32_TARGET; + else + which_target = UNKNOWN_TARGET; + + /* re-create the command lines as a string, taking care to quote stuff. */ + dlltool_cmdline = dyn_string_new (cmdline_len); + if (verbose) + { + dyn_string_append (dlltool_cmdline, " -v"); + } + dyn_string_append (dlltool_cmdline, " --dllname "); + dyn_string_append (dlltool_cmdline, dll_name); + + for (i = 1; i < argc; ++i) + { + if (dlltool_arg_indices[i]) + { + char *arg = saved_argv[i]; + int quote = (strchr (arg, ' ') || strchr (arg, '\t')); + dyn_string_append (dlltool_cmdline, + (quote) ? " \"" : " "); + dyn_string_append (dlltool_cmdline, arg); + dyn_string_append (dlltool_cmdline, + (quote) ? "\"" : ""); + } + } + + driver_cmdline = dyn_string_new (cmdline_len); + if (! driver_flags || strlen (driver_flags) == 0) + { + switch (which_target) + { + case CYGWIN_TARGET: + driver_flags = cygwin_driver_flags; + break; + + case MINGW32_TARGET: + driver_flags = mingw32_driver_flags; + break; + + default: + driver_flags = generic_driver_flags; + break; + } + } + dyn_string_append (driver_cmdline, driver_flags); + dyn_string_append (driver_cmdline, " -o "); + dyn_string_append (driver_cmdline, dll_file_name); + + if (! entry_point || strlen (entry_point) == 0) + { + switch (which_target) + { + case CYGWIN_TARGET: + entry_point = "__cygwin_dll_entry@12"; + break; + + case MINGW32_TARGET: + entry_point = "_DllMainCRTStartup@12"; + break; + + default: + entry_point = "_DllMain@12"; + break; + } + } + dyn_string_append (driver_cmdline, " -Wl,-e,"); + dyn_string_append (driver_cmdline, entry_point); + dyn_string_append (dlltool_cmdline, " --exclude-symbol="); + dyn_string_append (dlltool_cmdline, + (entry_point[0] == '_') ? entry_point+1 : entry_point); + + if (! image_base_str || strlen (image_base_str) == 0) + { + char *tmpbuf = (char *) xmalloc (sizeof ("0x12345678") + 1); + unsigned long hash = strhash (dll_file_name); + sprintf (tmpbuf, "0x%.8lX", 0x60000000|((hash<<16)&0xFFC0000)); + image_base_str = tmpbuf; + } + + dyn_string_append (driver_cmdline, " -Wl,--image-base,"); + dyn_string_append (driver_cmdline, image_base_str); + + if (verbose) + { + dyn_string_append (driver_cmdline, " -v"); + } + + for (i = 1; i < argc; ++i) + { + if (driver_arg_indices[i]) + { + char *arg = saved_argv[i]; + int quote = (strchr (arg, ' ') || strchr (arg, '\t')); + dyn_string_append (driver_cmdline, + (quote) ? " \"" : " "); + dyn_string_append (driver_cmdline, arg); + dyn_string_append (driver_cmdline, + (quote) ? "\"" : ""); + } + } + + /* + * Step pre-1. If no --def <EXPORT_DEF> is specified, then create it + * and then pass it on. + */ + + if (! def_file_seen) + { + int i; + dyn_string_t step_pre1; + + step_pre1 = dyn_string_new (1024); + + dyn_string_append (step_pre1, dlltool_cmdline->s); + if (export_all) + { + dyn_string_append (step_pre1, " --export-all --exclude-symbol="); + dyn_string_append (step_pre1, + "_cygwin_dll_entry@12,DllMainCRTStartup@12,DllMain@12,DllEntryPoint@12"); + } + dyn_string_append (step_pre1, " --output-def "); + dyn_string_append (step_pre1, def_file_name); + + for (i = 1; i < argc; ++i) + { + if (driver_arg_indices[i]) + { + char *arg = saved_argv[i]; + size_t len = strlen (arg); + if (len >= 2 && arg[len-2] == '.' + && (arg[len-1] == 'o' || arg[len-1] == 'a')) + { + int quote = (strchr (arg, ' ') || strchr (arg, '\t')); + dyn_string_append (step_pre1, + (quote) ? " \"" : " "); + dyn_string_append (step_pre1, arg); + dyn_string_append (step_pre1, + (quote) ? "\"" : ""); + } + } + } + + if (run (dlltool_name, step_pre1->s)) + cleanup_and_exit (1); + + dyn_string_delete (step_pre1); + } + + dyn_string_append (dlltool_cmdline, " --def "); + dyn_string_append (dlltool_cmdline, def_file_name); + + if (verbose) + { + fprintf (stderr, "DLLTOOL name : %s\n", dlltool_name); + fprintf (stderr, "DLLTOOL options : %s\n", dlltool_cmdline->s); + fprintf (stderr, "DRIVER name : %s\n", driver_name); + fprintf (stderr, "DRIVER options : %s\n", driver_cmdline->s); + } + + /* + * Step 1. Call GCC/LD to create base relocation file. If using GCC, the + * driver command line will look like the following: + * + * % gcc -Wl,--dll --Wl,--base-file,foo.base [rest of command line] + * + * If the user does not specify a base name, create temporary one that + * is deleted at exit. + * + */ + + if (! base_file_name) + { + char *fileprefix = choose_temp_base (); + base_file_name = (char *) xmalloc (strlen (fileprefix) + 6); + sprintf (base_file_name, "%s.base", + (dontdeltemps) ? mybasename (fileprefix) : fileprefix); + delete_base_file = 1; + free (fileprefix); + } + + { + int quote; + + dyn_string_t step1 = dyn_string_new (driver_cmdline->length + + strlen (base_file_name) + + 20); + dyn_string_append (step1, "-Wl,--base-file,"); + quote = (strchr (base_file_name, ' ') + || strchr (base_file_name, '\t')); + dyn_string_append (step1, + (quote) ? "\"" : ""); + dyn_string_append (step1, base_file_name); + dyn_string_append (step1, + (quote) ? "\"" : ""); + if (driver_cmdline->length) + { + dyn_string_append (step1, " "); + dyn_string_append (step1, driver_cmdline->s); + } + + if (run (driver_name, step1->s)) + cleanup_and_exit (1); + + dyn_string_delete (step1); + } + + + + /* + * Step 2. generate the exp file by running dlltool. + * dlltool command line will look like the following: + * + * % dlltool -Wl,--dll --Wl,--base-file,foo.base [rest of command line] + * + * If the user does not specify a base name, create temporary one that + * is deleted at exit. + * + */ + + if (! exp_file_name) + { + char *p = strrchr (dll_name, '.'); + size_t prefix_len = (p) ? p - dll_name : strlen (dll_name); + exp_file_name = (char *) xmalloc (prefix_len + 4 + 1); + strncpy (exp_file_name, dll_name, prefix_len); + exp_file_name[prefix_len] = '\0'; + strcat (exp_file_name, ".exp"); + delete_exp_file = 1; + } + + { + int quote; + dyn_string_t step2 = dyn_string_new (dlltool_cmdline->length + + strlen (base_file_name) + + strlen (exp_file_name) + + 20); + + dyn_string_append (step2, "--base-file "); + quote = (strchr (base_file_name, ' ') + || strchr (base_file_name, '\t')); + dyn_string_append (step2, + (quote) ? "\"" : ""); + dyn_string_append (step2, base_file_name); + dyn_string_append (step2, + (quote) ? "\" " : " "); + + dyn_string_append (step2, "--output-exp "); + quote = (strchr (exp_file_name, ' ') + || strchr (exp_file_name, '\t')); + dyn_string_append (step2, + (quote) ? "\"" : ""); + dyn_string_append (step2, exp_file_name); + dyn_string_append (step2, + (quote) ? "\"" : ""); + + if (dlltool_cmdline->length) + { + dyn_string_append (step2, " "); + dyn_string_append (step2, dlltool_cmdline->s); + } + + if (run (dlltool_name, step2->s)) + cleanup_and_exit (1); + + dyn_string_delete (step2); + } + + /* + * Step 3. Call GCC/LD to again, adding the exp file this time. + * driver command line will look like the following: + * + * % gcc -Wl,--dll --Wl,--base-file,foo.base foo.exp [rest ...] + */ + + { + int quote; + + dyn_string_t step3 = dyn_string_new (driver_cmdline->length + + strlen (exp_file_name) + + strlen (base_file_name) + + 20); + dyn_string_append (step3, "-Wl,--base-file,"); + quote = (strchr (base_file_name, ' ') + || strchr (base_file_name, '\t')); + dyn_string_append (step3, + (quote) ? "\"" : ""); + dyn_string_append (step3, base_file_name); + dyn_string_append (step3, + (quote) ? "\" " : " "); + + quote = (strchr (exp_file_name, ' ') + || strchr (exp_file_name, '\t')); + dyn_string_append (step3, + (quote) ? "\"" : ""); + dyn_string_append (step3, exp_file_name); + dyn_string_append (step3, + (quote) ? "\"" : ""); + + if (driver_cmdline->length) + { + dyn_string_append (step3, " "); + dyn_string_append (step3, driver_cmdline->s); + } + + if (run (driver_name, step3->s)) + cleanup_and_exit (1); + + dyn_string_delete (step3); + } + + + /* + * Step 4. Run DLLTOOL again using the same command line. + */ + + { + int quote; + dyn_string_t step4 = dyn_string_new (dlltool_cmdline->length + + strlen (base_file_name) + + strlen (exp_file_name) + + 20); + + dyn_string_append (step4, "--base-file "); + quote = (strchr (base_file_name, ' ') + || strchr (base_file_name, '\t')); + dyn_string_append (step4, + (quote) ? "\"" : ""); + dyn_string_append (step4, base_file_name); + dyn_string_append (step4, + (quote) ? "\" " : " "); + + dyn_string_append (step4, "--output-exp "); + quote = (strchr (exp_file_name, ' ') + || strchr (exp_file_name, '\t')); + dyn_string_append (step4, + (quote) ? "\"" : ""); + dyn_string_append (step4, exp_file_name); + dyn_string_append (step4, + (quote) ? "\"" : ""); + + if (dlltool_cmdline->length) + { + dyn_string_append (step4, " "); + dyn_string_append (step4, dlltool_cmdline->s); + } + + if (output_lib_file_name) + { + dyn_string_append (step4, " --output-lib "); + dyn_string_append (step4, output_lib_file_name); + } + + if (run (dlltool_name, step4->s)) + cleanup_and_exit (1); + + dyn_string_delete (step4); + } + + + /* + * Step 5. Link it all together and be done with it. + * driver command line will look like the following: + * + * % gcc -Wl,--dll foo.exp [rest ...] + * + */ + + { + int quote; + + dyn_string_t step5 = dyn_string_new (driver_cmdline->length + + strlen (exp_file_name) + + 20); + quote = (strchr (exp_file_name, ' ') + || strchr (exp_file_name, '\t')); + dyn_string_append (step5, + (quote) ? "\"" : ""); + dyn_string_append (step5, exp_file_name); + dyn_string_append (step5, + (quote) ? "\"" : ""); + + if (driver_cmdline->length) + { + dyn_string_append (step5, " "); + dyn_string_append (step5, driver_cmdline->s); + } + + if (run (driver_name, step5->s)) + cleanup_and_exit (1); + + dyn_string_delete (step5); + } + + cleanup_and_exit (0); + + return 0; +} diff --git a/binutils/dyn-string.c b/binutils/dyn-string.c new file mode 100644 index 0000000..a4a3043 --- /dev/null +++ b/binutils/dyn-string.c @@ -0,0 +1,107 @@ +/* An abstract string datatype. + Copyright (C) 1998 Free Software Foundation, Inc. + Contributed by Mark Mitchell (mark@markmitchell.com). + + This file is part of GNU CC. + + GNU CC 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, or (at your option) + any later version. + + GNU CC 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 GNU CC; see the file COPYING. If not, write to the Free + Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* This file lives in at least two places: binutils and gcc. + Don't change one without the other. */ + +#include "config.h" +#ifdef IN_GCC +#include "system.h" +#include "gansidecl.h" +#else +#include "ansidecl.h" +#endif +#include "dyn-string.h" + +extern char *xmalloc (); +extern char *xrealloc (); + +/* Create a new dynamic string capable of holding at least SPACE + characters, including the terminating NUL. If SPACE is 0, it + will be silently increased to 1. */ + +dyn_string_t +dyn_string_new (space) + int space; +{ + dyn_string_t result = (dyn_string_t) xmalloc (sizeof (struct dyn_string)); + + if (space == 0) + /* We need at least one byte in which to store the terminating + NUL. */ + space = 1; + + result->allocated = space; + result->s = (char*) xmalloc (space); + result->length = 0; + result->s[0] = '\0'; + + return result; +} + +/* Free the memory used by DS. */ + +void +dyn_string_delete (ds) + dyn_string_t ds; +{ + free (ds->s); + free (ds); +} + +/* Append the NUL-terminated string S to DS, resizing DS if + necessary. */ + +dyn_string_t +dyn_string_append (ds, s) + dyn_string_t ds; + char *s; +{ + int len = strlen (s); + dyn_string_resize (ds, ds->length + len + 1 /* '\0' */); + strcpy (ds->s + ds->length, s); + ds->length += len; + + return ds; +} + +/* Increase the capacity of DS so that it can hold at least SPACE + characters, including the terminating NUL. This function will not + (at present) reduce the capacity of DS. */ + +dyn_string_t +dyn_string_resize (ds, space) + dyn_string_t ds; + int space; +{ + int new_allocated = ds->allocated; + + while (space > new_allocated) + new_allocated *= 2; + + if (new_allocated != ds->allocated) + { + /* We actually need more space. */ + ds->allocated = new_allocated; + ds->s = (char*) xrealloc (ds->s, ds->allocated); + } + + return ds; +} diff --git a/binutils/dyn-string.h b/binutils/dyn-string.h new file mode 100644 index 0000000..a22bbbf --- /dev/null +++ b/binutils/dyn-string.h @@ -0,0 +1,34 @@ +/* An abstract string datatype. + Copyright (C) 1998 Free Software Foundation, Inc. + Contributed by Mark Mitchell (mark@markmitchell.com). + + This file is part of GNU CC. + + GNU CC 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, or (at your option) + any later version. + + GNU CC 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 GNU CC; see the file COPYING. If not, write to the Free + Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* This file lives in at least two places: binutils and gcc. + Don't change one without the other. */ + +typedef struct dyn_string +{ + int allocated; /* The amount of space allocated for the string. */ + int length; /* The actual length of the string. */ + char *s; /* The string itself, NUL-terminated. */ +}* dyn_string_t; + +extern dyn_string_t dyn_string_new PARAMS((int)); +extern void dyn_string_delete PARAMS((dyn_string_t)); +extern dyn_string_t dyn_string_append PARAMS((dyn_string_t, char*)); +extern dyn_string_t dyn_string_resize PARAMS((dyn_string_t, int)); diff --git a/binutils/filemode.c b/binutils/filemode.c new file mode 100644 index 0000000..58b52ba --- /dev/null +++ b/binutils/filemode.c @@ -0,0 +1,266 @@ +/* filemode.c -- make a string describing file modes + Copyright (C) 1985, 90, 91, 94, 95, 1997 Free Software Foundation, Inc. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#include "bfd.h" +#include "bucomm.h" + +static char ftypelet PARAMS ((unsigned long)); +static void setst PARAMS ((unsigned long, char *)); + +/* filemodestring - fill in string STR with an ls-style ASCII + representation of the st_mode field of file stats block STATP. + 10 characters are stored in STR; no terminating null is added. + The characters stored in STR are: + + 0 File type. 'd' for directory, 'c' for character + special, 'b' for block special, 'm' for multiplex, + 'l' for symbolic link, 's' for socket, 'p' for fifo, + '-' for any other file type + + 1 'r' if the owner may read, '-' otherwise. + + 2 'w' if the owner may write, '-' otherwise. + + 3 'x' if the owner may execute, 's' if the file is + set-user-id, '-' otherwise. + 'S' if the file is set-user-id, but the execute + bit isn't set. + + 4 'r' if group members may read, '-' otherwise. + + 5 'w' if group members may write, '-' otherwise. + + 6 'x' if group members may execute, 's' if the file is + set-group-id, '-' otherwise. + 'S' if it is set-group-id but not executable. + + 7 'r' if any user may read, '-' otherwise. + + 8 'w' if any user may write, '-' otherwise. + + 9 'x' if any user may execute, 't' if the file is "sticky" + (will be retained in swap space after execution), '-' + otherwise. + 'T' if the file is sticky but not executable. */ + +#if 0 + +/* This is not used; only mode_string is used. */ + +void +filemodestring (statp, str) + struct stat *statp; + char *str; +{ + mode_string ((unsigned long) statp->st_mode, str); +} + +#endif + +/* Get definitions for the file permission bits. */ + +#ifndef S_IRWXU +#define S_IRWXU 0700 +#endif +#ifndef S_IRUSR +#define S_IRUSR 0400 +#endif +#ifndef S_IWUSR +#define S_IWUSR 0200 +#endif +#ifndef S_IXUSR +#define S_IXUSR 0100 +#endif + +#ifndef S_IRWXG +#define S_IRWXG 0070 +#endif +#ifndef S_IRGRP +#define S_IRGRP 0040 +#endif +#ifndef S_IWGRP +#define S_IWGRP 0020 +#endif +#ifndef S_IXGRP +#define S_IXGRP 0010 +#endif + +#ifndef S_IRWXO +#define S_IRWXO 0007 +#endif +#ifndef S_IROTH +#define S_IROTH 0004 +#endif +#ifndef S_IWOTH +#define S_IWOTH 0002 +#endif +#ifndef S_IXOTH +#define S_IXOTH 0001 +#endif + +/* Like filemodestring, but only the relevant part of the `struct stat' + is given as an argument. */ + +void +mode_string (mode, str) + unsigned long mode; + char *str; +{ + str[0] = ftypelet ((unsigned long) mode); + str[1] = (mode & S_IRUSR) != 0 ? 'r' : '-'; + str[2] = (mode & S_IWUSR) != 0 ? 'w' : '-'; + str[3] = (mode & S_IXUSR) != 0 ? 'x' : '-'; + str[4] = (mode & S_IRGRP) != 0 ? 'r' : '-'; + str[5] = (mode & S_IWGRP) != 0 ? 'w' : '-'; + str[6] = (mode & S_IXGRP) != 0 ? 'x' : '-'; + str[7] = (mode & S_IROTH) != 0 ? 'r' : '-'; + str[8] = (mode & S_IWOTH) != 0 ? 'w' : '-'; + str[9] = (mode & S_IXOTH) != 0 ? 'x' : '-'; + setst ((unsigned long) mode, str); +} + +/* Return a character indicating the type of file described by + file mode BITS: + 'd' for directories + 'b' for block special files + 'c' for character special files + 'm' for multiplexor files + 'l' for symbolic links + 's' for sockets + 'p' for fifos + '-' for any other file type. */ + +#ifndef S_ISDIR +#ifdef S_IFDIR +#define S_ISDIR(i) (((i) & S_IFMT) == S_IFDIR) +#else /* ! defined (S_IFDIR) */ +#define S_ISDIR(i) (((i) & 0170000) == 040000) +#endif /* ! defined (S_IFDIR) */ +#endif /* ! defined (S_ISDIR) */ + +#ifndef S_ISBLK +#ifdef S_IFBLK +#define S_ISBLK(i) (((i) & S_IFMT) == S_IFBLK) +#else /* ! defined (S_IFBLK) */ +#define S_ISBLK(i) 0 +#endif /* ! defined (S_IFBLK) */ +#endif /* ! defined (S_ISBLK) */ + +#ifndef S_ISCHR +#ifdef S_IFCHR +#define S_ISCHR(i) (((i) & S_IFMT) == S_IFCHR) +#else /* ! defined (S_IFCHR) */ +#define S_ISCHR(i) 0 +#endif /* ! defined (S_IFCHR) */ +#endif /* ! defined (S_ISCHR) */ + +#ifndef S_ISFIFO +#ifdef S_IFIFO +#define S_ISFIFO(i) (((i) & S_IFMT) == S_IFIFO) +#else /* ! defined (S_IFIFO) */ +#define S_ISFIFO(i) 0 +#endif /* ! defined (S_IFIFO) */ +#endif /* ! defined (S_ISFIFO) */ + +#ifndef S_ISSOCK +#ifdef S_IFSOCK +#define S_ISSOCK(i) (((i) & S_IFMT) == S_IFSOCK) +#else /* ! defined (S_IFSOCK) */ +#define S_ISSOCK(i) 0 +#endif /* ! defined (S_IFSOCK) */ +#endif /* ! defined (S_ISSOCK) */ + +#ifndef S_ISLNK +#ifdef S_IFLNK +#define S_ISLNK(i) (((i) & S_IFMT) == S_IFLNK) +#else /* ! defined (S_IFLNK) */ +#define S_ISLNK(i) 0 +#endif /* ! defined (S_IFLNK) */ +#endif /* ! defined (S_ISLNK) */ + +static char +ftypelet (bits) + unsigned long bits; +{ + if (S_ISDIR (bits)) + return 'd'; + if (S_ISLNK (bits)) + return 'l'; + if (S_ISBLK (bits)) + return 'b'; + if (S_ISCHR (bits)) + return 'c'; + if (S_ISSOCK (bits)) + return 's'; + if (S_ISFIFO (bits)) + return 'p'; + +#ifdef S_IFMT +#ifdef S_IFMPC + if ((bits & S_IFMT) == S_IFMPC + || (bits & S_IFMT) == S_IFMPB) + return 'm'; +#endif +#ifdef S_IFNWK + if ((bits & S_IFMT) == S_IFNWK) + return 'n'; +#endif +#endif + + return '-'; +} + +/* Set the 's' and 't' flags in file attributes string CHARS, + according to the file mode BITS. */ + +static void +setst (bits, chars) + unsigned long bits; + char *chars; +{ +#ifdef S_ISUID + if (bits & S_ISUID) + { + if (chars[3] != 'x') + /* Set-uid, but not executable by owner. */ + chars[3] = 'S'; + else + chars[3] = 's'; + } +#endif +#ifdef S_ISGID + if (bits & S_ISGID) + { + if (chars[6] != 'x') + /* Set-gid, but not executable by group. */ + chars[6] = 'S'; + else + chars[6] = 's'; + } +#endif +#ifdef S_ISVTX + if (bits & S_ISVTX) + { + if (chars[9] != 'x') + /* Sticky, but not executable by others. */ + chars[9] = 'T'; + else + chars[9] = 't'; + } +#endif +} diff --git a/binutils/ieee.c b/binutils/ieee.c new file mode 100644 index 0000000..17a5b88 --- /dev/null +++ b/binutils/ieee.c @@ -0,0 +1,7609 @@ +/* ieee.c -- Read and write IEEE-695 debugging information. + Copyright (C) 1996, 1998 Free Software Foundation, Inc. + Written by Ian Lance Taylor <ian@cygnus.com>. + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* This file reads and writes IEEE-695 debugging information. */ + +#include <stdio.h> +#include <assert.h> + +#include "bfd.h" +#include "ieee.h" +#include "bucomm.h" +#include "libiberty.h" +#include "debug.h" +#include "budbg.h" + +/* This structure holds an entry on the block stack. */ + +struct ieee_block +{ + /* The kind of block. */ + int kind; + /* The source file name, for a BB5 block. */ + const char *filename; + /* The index of the function type, for a BB4 or BB6 block. */ + unsigned int fnindx; + /* True if this function is being skipped. */ + boolean skip; +}; + +/* This structure is the block stack. */ + +#define BLOCKSTACK_SIZE (16) + +struct ieee_blockstack +{ + /* The stack pointer. */ + struct ieee_block *bsp; + /* The stack. */ + struct ieee_block stack[BLOCKSTACK_SIZE]; +}; + +/* This structure holds information for a variable. */ + +struct ieee_var +{ + /* Start of name. */ + const char *name; + /* Length of name. */ + unsigned long namlen; + /* Type. */ + debug_type type; + /* Slot if we make an indirect type. */ + debug_type *pslot; + /* Kind of variable or function. */ + enum + { + IEEE_UNKNOWN, + IEEE_EXTERNAL, + IEEE_GLOBAL, + IEEE_STATIC, + IEEE_LOCAL, + IEEE_FUNCTION + } kind; +}; + +/* This structure holds all the variables. */ + +struct ieee_vars +{ + /* Number of slots allocated. */ + unsigned int alloc; + /* Variables. */ + struct ieee_var *vars; +}; + +/* This structure holds information for a type. We need this because + we don't want to represent bitfields as real types. */ + +struct ieee_type +{ + /* Type. */ + debug_type type; + /* Slot if this is type is referenced before it is defined. */ + debug_type *pslot; + /* Slots for arguments if we make indirect types for them. */ + debug_type *arg_slots; + /* If this is a bitfield, this is the size in bits. If this is not + a bitfield, this is zero. */ + unsigned long bitsize; +}; + +/* This structure holds all the type information. */ + +struct ieee_types +{ + /* Number of slots allocated. */ + unsigned int alloc; + /* Types. */ + struct ieee_type *types; + /* Builtin types. */ +#define BUILTIN_TYPE_COUNT (60) + debug_type builtins[BUILTIN_TYPE_COUNT]; +}; + +/* This structure holds a linked last of structs with their tag names, + so that we can convert them to C++ classes if necessary. */ + +struct ieee_tag +{ + /* Next tag. */ + struct ieee_tag *next; + /* This tag name. */ + const char *name; + /* The type of the tag. */ + debug_type type; + /* The tagged type is an indirect type pointing at this slot. */ + debug_type slot; + /* This is an array of slots used when a field type is converted + into a indirect type, in case it needs to be later converted into + a reference type. */ + debug_type *fslots; +}; + +/* This structure holds the information we pass around to the parsing + functions. */ + +struct ieee_info +{ + /* The debugging handle. */ + PTR dhandle; + /* The BFD. */ + bfd *abfd; + /* The start of the bytes to be parsed. */ + const bfd_byte *bytes; + /* The end of the bytes to be parsed. */ + const bfd_byte *pend; + /* The block stack. */ + struct ieee_blockstack blockstack; + /* Whether we have seen a BB1 or BB2. */ + boolean saw_filename; + /* The variables. */ + struct ieee_vars vars; + /* The global variables, after a global typedef block. */ + struct ieee_vars *global_vars; + /* The types. */ + struct ieee_types types; + /* The global types, after a global typedef block. */ + struct ieee_types *global_types; + /* The list of tagged structs. */ + struct ieee_tag *tags; +}; + +/* Basic builtin types, not including the pointers. */ + +enum builtin_types +{ + builtin_unknown = 0, + builtin_void = 1, + builtin_signed_char = 2, + builtin_unsigned_char = 3, + builtin_signed_short_int = 4, + builtin_unsigned_short_int = 5, + builtin_signed_long = 6, + builtin_unsigned_long = 7, + builtin_signed_long_long = 8, + builtin_unsigned_long_long = 9, + builtin_float = 10, + builtin_double = 11, + builtin_long_double = 12, + builtin_long_long_double = 13, + builtin_quoted_string = 14, + builtin_instruction_address = 15, + builtin_int = 16, + builtin_unsigned = 17, + builtin_unsigned_int = 18, + builtin_char = 19, + builtin_long = 20, + builtin_short = 21, + builtin_unsigned_short = 22, + builtin_short_int = 23, + builtin_signed_short = 24, + builtin_bcd_float = 25 +}; + +/* These are the values found in the derivation flags of a 'b' + component record of a 'T' type extension record in a C++ pmisc + record. These are bitmasks. */ + +/* Set for a private base class, clear for a public base class. + Protected base classes are not supported. */ +#define BASEFLAGS_PRIVATE (0x1) +/* Set for a virtual base class. */ +#define BASEFLAGS_VIRTUAL (0x2) +/* Set for a friend class, clear for a base class. */ +#define BASEFLAGS_FRIEND (0x10) + +/* These are the values found in the specs flags of a 'd', 'm', or 'v' + component record of a 'T' type extension record in a C++ pmisc + record. The same flags are used for a 'M' record in a C++ pmisc + record. */ + +/* The lower two bits hold visibility information. */ +#define CXXFLAGS_VISIBILITY (0x3) +/* This value in the lower two bits indicates a public member. */ +#define CXXFLAGS_VISIBILITY_PUBLIC (0x0) +/* This value in the lower two bits indicates a private member. */ +#define CXXFLAGS_VISIBILITY_PRIVATE (0x1) +/* This value in the lower two bits indicates a protected member. */ +#define CXXFLAGS_VISIBILITY_PROTECTED (0x2) +/* Set for a static member. */ +#define CXXFLAGS_STATIC (0x4) +/* Set for a virtual override. */ +#define CXXFLAGS_OVERRIDE (0x8) +/* Set for a friend function. */ +#define CXXFLAGS_FRIEND (0x10) +/* Set for a const function. */ +#define CXXFLAGS_CONST (0x20) +/* Set for a volatile function. */ +#define CXXFLAGS_VOLATILE (0x40) +/* Set for an overloaded function. */ +#define CXXFLAGS_OVERLOADED (0x80) +/* Set for an operator function. */ +#define CXXFLAGS_OPERATOR (0x100) +/* Set for a constructor or destructor. */ +#define CXXFLAGS_CTORDTOR (0x400) +/* Set for a constructor. */ +#define CXXFLAGS_CTOR (0x200) +/* Set for an inline function. */ +#define CXXFLAGS_INLINE (0x800) + +/* Local functions. */ + +static void ieee_error + PARAMS ((struct ieee_info *, const bfd_byte *, const char *)); +static void ieee_eof PARAMS ((struct ieee_info *)); +static char *savestring PARAMS ((const char *, unsigned long)); +static boolean ieee_read_number + PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *)); +static boolean ieee_read_optional_number + PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *, boolean *)); +static boolean ieee_read_id + PARAMS ((struct ieee_info *, const bfd_byte **, const char **, + unsigned long *)); +static boolean ieee_read_optional_id + PARAMS ((struct ieee_info *, const bfd_byte **, const char **, + unsigned long *, boolean *)); +static boolean ieee_read_expression + PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *)); +static debug_type ieee_builtin_type + PARAMS ((struct ieee_info *, const bfd_byte *, unsigned int)); +static boolean ieee_alloc_type + PARAMS ((struct ieee_info *, unsigned int, boolean)); +static boolean ieee_read_type_index + PARAMS ((struct ieee_info *, const bfd_byte **, debug_type *)); +static int ieee_regno_to_genreg PARAMS ((bfd *, int)); +static int ieee_genreg_to_regno PARAMS ((bfd *, int)); +static boolean parse_ieee_bb PARAMS ((struct ieee_info *, const bfd_byte **)); +static boolean parse_ieee_be PARAMS ((struct ieee_info *, const bfd_byte **)); +static boolean parse_ieee_nn PARAMS ((struct ieee_info *, const bfd_byte **)); +static boolean parse_ieee_ty PARAMS ((struct ieee_info *, const bfd_byte **)); +static boolean parse_ieee_atn PARAMS ((struct ieee_info *, const bfd_byte **)); +static boolean ieee_read_cxx_misc + PARAMS ((struct ieee_info *, const bfd_byte **, unsigned long)); +static boolean ieee_read_cxx_class + PARAMS ((struct ieee_info *, const bfd_byte **, unsigned long)); +static boolean ieee_read_cxx_defaults + PARAMS ((struct ieee_info *, const bfd_byte **, unsigned long)); +static boolean ieee_read_reference + PARAMS ((struct ieee_info *, const bfd_byte **)); +static boolean ieee_require_asn + PARAMS ((struct ieee_info *, const bfd_byte **, bfd_vma *)); +static boolean ieee_require_atn65 + PARAMS ((struct ieee_info *, const bfd_byte **, const char **, + unsigned long *)); + +/* Report an error in the IEEE debugging information. */ + +static void +ieee_error (info, p, s) + struct ieee_info *info; + const bfd_byte *p; + const char *s; +{ + if (p != NULL) + fprintf (stderr, "%s: 0x%lx: %s (0x%x)\n", bfd_get_filename (info->abfd), + (unsigned long) (p - info->bytes), s, *p); + else + fprintf (stderr, "%s: %s\n", bfd_get_filename (info->abfd), s); +} + +/* Report an unexpected EOF in the IEEE debugging information. */ + +static void +ieee_eof (info) + struct ieee_info *info; +{ + ieee_error (info, (const bfd_byte *) NULL, + _("unexpected end of debugging information")); +} + +/* Save a string in memory. */ + +static char * +savestring (start, len) + const char *start; + unsigned long len; +{ + char *ret; + + ret = (char *) xmalloc (len + 1); + memcpy (ret, start, len); + ret[len] = '\0'; + return ret; +} + +/* Read a number which must be present in an IEEE file. */ + +static boolean +ieee_read_number (info, pp, pv) + struct ieee_info *info; + const bfd_byte **pp; + bfd_vma *pv; +{ + return ieee_read_optional_number (info, pp, pv, (boolean *) NULL); +} + +/* Read a number in an IEEE file. If ppresent is not NULL, the number + need not be there. */ + +static boolean +ieee_read_optional_number (info, pp, pv, ppresent) + struct ieee_info *info; + const bfd_byte **pp; + bfd_vma *pv; + boolean *ppresent; +{ + ieee_record_enum_type b; + + if (*pp >= info->pend) + { + if (ppresent != NULL) + { + *ppresent = false; + return true; + } + ieee_eof (info); + return false; + } + + b = (ieee_record_enum_type) **pp; + ++*pp; + + if (b <= ieee_number_end_enum) + { + *pv = (bfd_vma) b; + if (ppresent != NULL) + *ppresent = true; + return true; + } + + if (b >= ieee_number_repeat_start_enum && b <= ieee_number_repeat_end_enum) + { + unsigned int i; + + i = (int) b - (int) ieee_number_repeat_start_enum; + if (*pp + i - 1 >= info->pend) + { + ieee_eof (info); + return false; + } + + *pv = 0; + for (; i > 0; i--) + { + *pv <<= 8; + *pv += **pp; + ++*pp; + } + + if (ppresent != NULL) + *ppresent = true; + + return true; + } + + if (ppresent != NULL) + { + --*pp; + *ppresent = false; + return true; + } + + ieee_error (info, *pp - 1, _("invalid number")); + return false; +} + +/* Read a required string from an IEEE file. */ + +static boolean +ieee_read_id (info, pp, pname, pnamlen) + struct ieee_info *info; + const bfd_byte **pp; + const char **pname; + unsigned long *pnamlen; +{ + return ieee_read_optional_id (info, pp, pname, pnamlen, (boolean *) NULL); +} + +/* Read a string from an IEEE file. If ppresent is not NULL, the + string is optional. */ + +static boolean +ieee_read_optional_id (info, pp, pname, pnamlen, ppresent) + struct ieee_info *info; + const bfd_byte **pp; + const char **pname; + unsigned long *pnamlen; + boolean *ppresent; +{ + bfd_byte b; + unsigned long len; + + if (*pp >= info->pend) + { + ieee_eof (info); + return false; + } + + b = **pp; + ++*pp; + + if (b <= 0x7f) + len = b; + else if ((ieee_record_enum_type) b == ieee_extension_length_1_enum) + { + len = **pp; + ++*pp; + } + else if ((ieee_record_enum_type) b == ieee_extension_length_2_enum) + { + len = (**pp << 8) + (*pp)[1]; + *pp += 2; + } + else + { + if (ppresent != NULL) + { + --*pp; + *ppresent = false; + return true; + } + ieee_error (info, *pp - 1, _("invalid string length")); + return false; + } + + if ((unsigned long) (info->pend - *pp) < len) + { + ieee_eof (info); + return false; + } + + *pname = (const char *) *pp; + *pnamlen = len; + *pp += len; + + if (ppresent != NULL) + *ppresent = true; + + return true; +} + +/* Read an expression from an IEEE file. Since this code is only used + to parse debugging information, I haven't bothered to write a full + blown IEEE expression parser. I've only thrown in the things I've + seen in debugging information. This can be easily extended if + necessary. */ + +static boolean +ieee_read_expression (info, pp, pv) + struct ieee_info *info; + const bfd_byte **pp; + bfd_vma *pv; +{ + const bfd_byte *expr_start; +#define EXPR_STACK_SIZE (10) + bfd_vma expr_stack[EXPR_STACK_SIZE]; + bfd_vma *esp; + + expr_start = *pp; + + esp = expr_stack; + + while (1) + { + const bfd_byte *start; + bfd_vma val; + boolean present; + ieee_record_enum_type c; + + start = *pp; + + if (! ieee_read_optional_number (info, pp, &val, &present)) + return false; + + if (present) + { + if (esp - expr_stack >= EXPR_STACK_SIZE) + { + ieee_error (info, start, _("expression stack overflow")); + return false; + } + *esp++ = val; + continue; + } + + c = (ieee_record_enum_type) **pp; + + if (c >= ieee_module_beginning_enum) + break; + + ++*pp; + + if (c == ieee_comma) + break; + + switch (c) + { + default: + ieee_error (info, start, _("unsupported IEEE expression operator")); + break; + + case ieee_variable_R_enum: + { + bfd_vma indx; + asection *s; + + if (! ieee_read_number (info, pp, &indx)) + return false; + for (s = info->abfd->sections; s != NULL; s = s->next) + if ((bfd_vma) s->target_index == indx) + break; + if (s == NULL) + { + ieee_error (info, start, _("unknown section")); + return false; + } + + if (esp - expr_stack >= EXPR_STACK_SIZE) + { + ieee_error (info, start, _("expression stack overflow")); + return false; + } + + *esp++ = bfd_get_section_vma (info->abfd, s); + } + break; + + case ieee_function_plus_enum: + case ieee_function_minus_enum: + { + bfd_vma v1, v2; + + if (esp - expr_stack < 2) + { + ieee_error (info, start, _("expression stack underflow")); + return false; + } + + v1 = *--esp; + v2 = *--esp; + *esp++ = v1 + v2; + } + break; + } + } + + if (esp - 1 != expr_stack) + { + ieee_error (info, expr_start, _("expression stack mismatch")); + return false; + } + + *pv = *--esp; + + return true; +} + +/* Return an IEEE builtin type. */ + +static debug_type +ieee_builtin_type (info, p, indx) + struct ieee_info *info; + const bfd_byte *p; + unsigned int indx; +{ + PTR dhandle; + debug_type type; + const char *name; + + if (indx < BUILTIN_TYPE_COUNT + && info->types.builtins[indx] != DEBUG_TYPE_NULL) + return info->types.builtins[indx]; + + dhandle = info->dhandle; + + if (indx >= 32 && indx < 64) + { + type = debug_make_pointer_type (dhandle, + ieee_builtin_type (info, p, indx - 32)); + assert (indx < BUILTIN_TYPE_COUNT); + info->types.builtins[indx] = type; + return type; + } + + switch ((enum builtin_types) indx) + { + default: + ieee_error (info, p, _("unknown builtin type")); + return NULL; + + case builtin_unknown: + type = debug_make_void_type (dhandle); + name = NULL; + break; + + case builtin_void: + type = debug_make_void_type (dhandle); + name = "void"; + break; + + case builtin_signed_char: + type = debug_make_int_type (dhandle, 1, false); + name = "signed char"; + break; + + case builtin_unsigned_char: + type = debug_make_int_type (dhandle, 1, true); + name = "unsigned char"; + break; + + case builtin_signed_short_int: + type = debug_make_int_type (dhandle, 2, false); + name = "signed short int"; + break; + + case builtin_unsigned_short_int: + type = debug_make_int_type (dhandle, 2, true); + name = "unsigned short int"; + break; + + case builtin_signed_long: + type = debug_make_int_type (dhandle, 4, false); + name = "signed long"; + break; + + case builtin_unsigned_long: + type = debug_make_int_type (dhandle, 4, true); + name = "unsigned long"; + break; + + case builtin_signed_long_long: + type = debug_make_int_type (dhandle, 8, false); + name = "signed long long"; + break; + + case builtin_unsigned_long_long: + type = debug_make_int_type (dhandle, 8, true); + name = "unsigned long long"; + break; + + case builtin_float: + type = debug_make_float_type (dhandle, 4); + name = "float"; + break; + + case builtin_double: + type = debug_make_float_type (dhandle, 8); + name = "double"; + break; + + case builtin_long_double: + /* FIXME: The size for this type should depend upon the + processor. */ + type = debug_make_float_type (dhandle, 12); + name = "long double"; + break; + + case builtin_long_long_double: + type = debug_make_float_type (dhandle, 16); + name = "long long double"; + break; + + case builtin_quoted_string: + type = debug_make_array_type (dhandle, + ieee_builtin_type (info, p, + ((unsigned int) + builtin_char)), + ieee_builtin_type (info, p, + ((unsigned int) + builtin_int)), + 0, -1, true); + name = "QUOTED STRING"; + break; + + case builtin_instruction_address: + /* FIXME: This should be a code address. */ + type = debug_make_int_type (dhandle, 4, true); + name = "instruction address"; + break; + + case builtin_int: + /* FIXME: The size for this type should depend upon the + processor. */ + type = debug_make_int_type (dhandle, 4, false); + name = "int"; + break; + + case builtin_unsigned: + /* FIXME: The size for this type should depend upon the + processor. */ + type = debug_make_int_type (dhandle, 4, true); + name = "unsigned"; + break; + + case builtin_unsigned_int: + /* FIXME: The size for this type should depend upon the + processor. */ + type = debug_make_int_type (dhandle, 4, true); + name = "unsigned int"; + break; + + case builtin_char: + type = debug_make_int_type (dhandle, 1, false); + name = "char"; + break; + + case builtin_long: + type = debug_make_int_type (dhandle, 4, false); + name = "long"; + break; + + case builtin_short: + type = debug_make_int_type (dhandle, 2, false); + name = "short"; + break; + + case builtin_unsigned_short: + type = debug_make_int_type (dhandle, 2, true); + name = "unsigned short"; + break; + + case builtin_short_int: + type = debug_make_int_type (dhandle, 2, false); + name = "short int"; + break; + + case builtin_signed_short: + type = debug_make_int_type (dhandle, 2, false); + name = "signed short"; + break; + + case builtin_bcd_float: + ieee_error (info, p, _("BCD float type not supported")); + return false; + } + + if (name != NULL) + type = debug_name_type (dhandle, name, type); + + assert (indx < BUILTIN_TYPE_COUNT); + + info->types.builtins[indx] = type; + + return type; +} + +/* Allocate more space in the type table. If ref is true, this is a + reference to the type; if it is not already defined, we should set + up an indirect type. */ + +static boolean +ieee_alloc_type (info, indx, ref) + struct ieee_info *info; + unsigned int indx; + boolean ref; +{ + unsigned int nalloc; + register struct ieee_type *t; + struct ieee_type *tend; + + if (indx >= info->types.alloc) + { + nalloc = info->types.alloc; + if (nalloc == 0) + nalloc = 4; + while (indx >= nalloc) + nalloc *= 2; + + info->types.types = ((struct ieee_type *) + xrealloc (info->types.types, + nalloc * sizeof *info->types.types)); + + memset (info->types.types + info->types.alloc, 0, + (nalloc - info->types.alloc) * sizeof *info->types.types); + + tend = info->types.types + nalloc; + for (t = info->types.types + info->types.alloc; t < tend; t++) + t->type = DEBUG_TYPE_NULL; + + info->types.alloc = nalloc; + } + + if (ref) + { + t = info->types.types + indx; + if (t->type == NULL) + { + t->pslot = (debug_type *) xmalloc (sizeof *t->pslot); + *t->pslot = DEBUG_TYPE_NULL; + t->type = debug_make_indirect_type (info->dhandle, t->pslot, + (const char *) NULL); + if (t->type == NULL) + return false; + } + } + + return true; +} + +/* Read a type index and return the corresponding type. */ + +static boolean +ieee_read_type_index (info, pp, ptype) + struct ieee_info *info; + const bfd_byte **pp; + debug_type *ptype; +{ + const bfd_byte *start; + bfd_vma indx; + + start = *pp; + + if (! ieee_read_number (info, pp, &indx)) + return false; + + if (indx < 256) + { + *ptype = ieee_builtin_type (info, start, indx); + if (*ptype == NULL) + return false; + return true; + } + + indx -= 256; + if (! ieee_alloc_type (info, indx, true)) + return false; + + *ptype = info->types.types[indx].type; + + return true; +} + +/* Parse IEEE debugging information for a file. This is passed the + bytes which compose the Debug Information Part of an IEEE file. */ + +boolean +parse_ieee (dhandle, abfd, bytes, len) + PTR dhandle; + bfd *abfd; + const bfd_byte *bytes; + bfd_size_type len; +{ + struct ieee_info info; + unsigned int i; + const bfd_byte *p, *pend; + + info.dhandle = dhandle; + info.abfd = abfd; + info.bytes = bytes; + info.pend = bytes + len; + info.blockstack.bsp = info.blockstack.stack; + info.saw_filename = false; + info.vars.alloc = 0; + info.vars.vars = NULL; + info.global_vars = NULL; + info.types.alloc = 0; + info.types.types = NULL; + info.global_types = NULL; + info.tags = NULL; + for (i = 0; i < BUILTIN_TYPE_COUNT; i++) + info.types.builtins[i] = DEBUG_TYPE_NULL; + + p = bytes; + pend = info.pend; + while (p < pend) + { + const bfd_byte *record_start; + ieee_record_enum_type c; + + record_start = p; + + c = (ieee_record_enum_type) *p++; + + if (c == ieee_at_record_enum) + c = (ieee_record_enum_type) (((unsigned int) c << 8) | *p++); + + if (c <= ieee_number_repeat_end_enum) + { + ieee_error (&info, record_start, _("unexpected number")); + return false; + } + + switch (c) + { + default: + ieee_error (&info, record_start, _("unexpected record type")); + return false; + + case ieee_bb_record_enum: + if (! parse_ieee_bb (&info, &p)) + return false; + break; + + case ieee_be_record_enum: + if (! parse_ieee_be (&info, &p)) + return false; + break; + + case ieee_nn_record: + if (! parse_ieee_nn (&info, &p)) + return false; + break; + + case ieee_ty_record_enum: + if (! parse_ieee_ty (&info, &p)) + return false; + break; + + case ieee_atn_record_enum: + if (! parse_ieee_atn (&info, &p)) + return false; + break; + } + } + + if (info.blockstack.bsp != info.blockstack.stack) + { + ieee_error (&info, (const bfd_byte *) NULL, + _("blocks left on stack at end")); + return false; + } + + return true; +} + +/* Handle an IEEE BB record. */ + +static boolean +parse_ieee_bb (info, pp) + struct ieee_info *info; + const bfd_byte **pp; +{ + const bfd_byte *block_start; + bfd_byte b; + bfd_vma size; + const char *name; + unsigned long namlen; + char *namcopy = NULL; + unsigned int fnindx; + boolean skip; + + block_start = *pp; + + b = **pp; + ++*pp; + + if (! ieee_read_number (info, pp, &size) + || ! ieee_read_id (info, pp, &name, &namlen)) + return false; + + fnindx = (unsigned int) -1; + skip = false; + + switch (b) + { + case 1: + /* BB1: Type definitions local to a module. */ + namcopy = savestring (name, namlen); + if (namcopy == NULL) + return false; + if (! debug_set_filename (info->dhandle, namcopy)) + return false; + info->saw_filename = true; + + /* Discard any variables or types we may have seen before. */ + if (info->vars.vars != NULL) + free (info->vars.vars); + info->vars.vars = NULL; + info->vars.alloc = 0; + if (info->types.types != NULL) + free (info->types.types); + info->types.types = NULL; + info->types.alloc = 0; + + /* Initialize the types to the global types. */ + if (info->global_types != NULL) + { + info->types.alloc = info->global_types->alloc; + info->types.types = ((struct ieee_type *) + xmalloc (info->types.alloc + * sizeof (*info->types.types))); + memcpy (info->types.types, info->global_types->types, + info->types.alloc * sizeof (*info->types.types)); + } + + break; + + case 2: + /* BB2: Global type definitions. The name is supposed to be + empty, but we don't check. */ + if (! debug_set_filename (info->dhandle, "*global*")) + return false; + info->saw_filename = true; + break; + + case 3: + /* BB3: High level module block begin. We don't have to do + anything here. The name is supposed to be the same as for + the BB1, but we don't check. */ + break; + + case 4: + /* BB4: Global function. */ + { + bfd_vma stackspace, typindx, offset; + debug_type return_type; + + if (! ieee_read_number (info, pp, &stackspace) + || ! ieee_read_number (info, pp, &typindx) + || ! ieee_read_expression (info, pp, &offset)) + return false; + + /* We have no way to record the stack space. FIXME. */ + + if (typindx < 256) + { + return_type = ieee_builtin_type (info, block_start, typindx); + if (return_type == DEBUG_TYPE_NULL) + return false; + } + else + { + typindx -= 256; + if (! ieee_alloc_type (info, typindx, true)) + return false; + fnindx = typindx; + return_type = info->types.types[typindx].type; + if (debug_get_type_kind (info->dhandle, return_type) + == DEBUG_KIND_FUNCTION) + return_type = debug_get_return_type (info->dhandle, + return_type); + } + + namcopy = savestring (name, namlen); + if (namcopy == NULL) + return false; + if (! debug_record_function (info->dhandle, namcopy, return_type, + true, offset)) + return false; + } + break; + + case 5: + /* BB5: File name for source line numbers. */ + { + unsigned int i; + + /* We ignore the date and time. FIXME. */ + for (i = 0; i < 6; i++) + { + bfd_vma ignore; + boolean present; + + if (! ieee_read_optional_number (info, pp, &ignore, &present)) + return false; + if (! present) + break; + } + + namcopy = savestring (name, namlen); + if (namcopy == NULL) + return false; + if (! debug_start_source (info->dhandle, namcopy)) + return false; + } + break; + + case 6: + /* BB6: Local function or block. */ + { + bfd_vma stackspace, typindx, offset; + + if (! ieee_read_number (info, pp, &stackspace) + || ! ieee_read_number (info, pp, &typindx) + || ! ieee_read_expression (info, pp, &offset)) + return false; + + /* We have no way to record the stack space. FIXME. */ + + if (namlen == 0) + { + if (! debug_start_block (info->dhandle, offset)) + return false; + /* Change b to indicate that this is a block + rather than a function. */ + b = 0x86; + } + else + { + /* The MRI C++ compiler will output a fake function named + __XRYCPP to hold C++ debugging information. We skip + that function. This is not crucial, but it makes + converting from IEEE to other debug formats work + better. */ + if (strncmp (name, "__XRYCPP", namlen) == 0) + skip = true; + else + { + debug_type return_type; + + if (typindx < 256) + { + return_type = ieee_builtin_type (info, block_start, + typindx); + if (return_type == NULL) + return false; + } + else + { + typindx -= 256; + if (! ieee_alloc_type (info, typindx, true)) + return false; + fnindx = typindx; + return_type = info->types.types[typindx].type; + if (debug_get_type_kind (info->dhandle, return_type) + == DEBUG_KIND_FUNCTION) + return_type = debug_get_return_type (info->dhandle, + return_type); + } + + namcopy = savestring (name, namlen); + if (namcopy == NULL) + return false; + if (! debug_record_function (info->dhandle, namcopy, + return_type, false, offset)) + return false; + } + } + } + break; + + case 10: + /* BB10: Assembler module scope. In the normal case, we + completely ignore all this information. FIXME. */ + { + const char *inam, *vstr; + unsigned long inamlen, vstrlen; + bfd_vma tool_type; + boolean present; + unsigned int i; + + if (! info->saw_filename) + { + namcopy = savestring (name, namlen); + if (namcopy == NULL) + return false; + if (! debug_set_filename (info->dhandle, namcopy)) + return false; + info->saw_filename = true; + } + + if (! ieee_read_id (info, pp, &inam, &inamlen) + || ! ieee_read_number (info, pp, &tool_type) + || ! ieee_read_optional_id (info, pp, &vstr, &vstrlen, &present)) + return false; + for (i = 0; i < 6; i++) + { + bfd_vma ignore; + + if (! ieee_read_optional_number (info, pp, &ignore, &present)) + return false; + if (! present) + break; + } + } + break; + + case 11: + /* BB11: Module section. We completely ignore all this + information. FIXME. */ + { + bfd_vma sectype, secindx, offset, map; + boolean present; + + if (! ieee_read_number (info, pp, §ype) + || ! ieee_read_number (info, pp, &secindx) + || ! ieee_read_expression (info, pp, &offset) + || ! ieee_read_optional_number (info, pp, &map, &present)) + return false; + } + break; + + default: + ieee_error (info, block_start, _("unknown BB type")); + return false; + } + + + /* Push this block on the block stack. */ + + if (info->blockstack.bsp >= info->blockstack.stack + BLOCKSTACK_SIZE) + { + ieee_error (info, (const bfd_byte *) NULL, _("stack overflow")); + return false; + } + + info->blockstack.bsp->kind = b; + if (b == 5) + info->blockstack.bsp->filename = namcopy; + info->blockstack.bsp->fnindx = fnindx; + info->blockstack.bsp->skip = skip; + ++info->blockstack.bsp; + + return true; +} + +/* Handle an IEEE BE record. */ + +static boolean +parse_ieee_be (info, pp) + struct ieee_info *info; + const bfd_byte **pp; +{ + bfd_vma offset; + + if (info->blockstack.bsp <= info->blockstack.stack) + { + ieee_error (info, *pp, _("stack underflow")); + return false; + } + --info->blockstack.bsp; + + switch (info->blockstack.bsp->kind) + { + case 2: + /* When we end the global typedefs block, we copy out the the + contents of info->vars. This is because the variable indices + may be reused in the local blocks. However, we need to + preserve them so that we can locate a function returning a + reference variable whose type is named in the global typedef + block. */ + info->global_vars = ((struct ieee_vars *) + xmalloc (sizeof *info->global_vars)); + info->global_vars->alloc = info->vars.alloc; + info->global_vars->vars = ((struct ieee_var *) + xmalloc (info->vars.alloc + * sizeof (*info->vars.vars))); + memcpy (info->global_vars->vars, info->vars.vars, + info->vars.alloc * sizeof (*info->vars.vars)); + + /* We also copy out the non builtin parts of info->types, since + the types are discarded when we start a new block. */ + info->global_types = ((struct ieee_types *) + xmalloc (sizeof *info->global_types)); + info->global_types->alloc = info->types.alloc; + info->global_types->types = ((struct ieee_type *) + xmalloc (info->types.alloc + * sizeof (*info->types.types))); + memcpy (info->global_types->types, info->types.types, + info->types.alloc * sizeof (*info->types.types)); + memset (info->global_types->builtins, 0, + sizeof (info->global_types->builtins)); + + break; + + case 4: + case 6: + if (! ieee_read_expression (info, pp, &offset)) + return false; + if (! info->blockstack.bsp->skip) + { + if (! debug_end_function (info->dhandle, offset + 1)) + return false; + } + break; + + case 0x86: + /* This is BE6 when BB6 started a block rather than a local + function. */ + if (! ieee_read_expression (info, pp, &offset)) + return false; + if (! debug_end_block (info->dhandle, offset + 1)) + return false; + break; + + case 5: + /* When we end a BB5, we look up the stack for the last BB5, if + there is one, so that we can call debug_start_source. */ + if (info->blockstack.bsp > info->blockstack.stack) + { + struct ieee_block *bl; + + bl = info->blockstack.bsp; + do + { + --bl; + if (bl->kind == 5) + { + if (! debug_start_source (info->dhandle, bl->filename)) + return false; + break; + } + } + while (bl != info->blockstack.stack); + } + break; + + case 11: + if (! ieee_read_expression (info, pp, &offset)) + return false; + /* We just ignore the module size. FIXME. */ + break; + + default: + /* Other block types do not have any trailing information. */ + break; + } + + return true; +} + +/* Parse an NN record. */ + +static boolean +parse_ieee_nn (info, pp) + struct ieee_info *info; + const bfd_byte **pp; +{ + const bfd_byte *nn_start; + bfd_vma varindx; + const char *name; + unsigned long namlen; + + nn_start = *pp; + + if (! ieee_read_number (info, pp, &varindx) + || ! ieee_read_id (info, pp, &name, &namlen)) + return false; + + if (varindx < 32) + { + ieee_error (info, nn_start, _("illegal variable index")); + return false; + } + varindx -= 32; + + if (varindx >= info->vars.alloc) + { + unsigned int alloc; + + alloc = info->vars.alloc; + if (alloc == 0) + alloc = 4; + while (varindx >= alloc) + alloc *= 2; + info->vars.vars = ((struct ieee_var *) + xrealloc (info->vars.vars, + alloc * sizeof *info->vars.vars)); + memset (info->vars.vars + info->vars.alloc, 0, + (alloc - info->vars.alloc) * sizeof *info->vars.vars); + info->vars.alloc = alloc; + } + + info->vars.vars[varindx].name = name; + info->vars.vars[varindx].namlen = namlen; + + return true; +} + +/* Parse a TY record. */ + +static boolean +parse_ieee_ty (info, pp) + struct ieee_info *info; + const bfd_byte **pp; +{ + const bfd_byte *ty_start, *ty_var_start, *ty_code_start; + bfd_vma typeindx, varindx, tc; + PTR dhandle; + boolean tag, typdef; + debug_type *arg_slots; + unsigned long type_bitsize; + debug_type type; + + ty_start = *pp; + + if (! ieee_read_number (info, pp, &typeindx)) + return false; + + if (typeindx < 256) + { + ieee_error (info, ty_start, _("illegal type index")); + return false; + } + + typeindx -= 256; + if (! ieee_alloc_type (info, typeindx, false)) + return false; + + if (**pp != 0xce) + { + ieee_error (info, *pp, _("unknown TY code")); + return false; + } + ++*pp; + + ty_var_start = *pp; + + if (! ieee_read_number (info, pp, &varindx)) + return false; + + if (varindx < 32) + { + ieee_error (info, ty_var_start, _("illegal variable index")); + return false; + } + varindx -= 32; + + if (varindx >= info->vars.alloc || info->vars.vars[varindx].name == NULL) + { + ieee_error (info, ty_var_start, _("undefined variable in TY")); + return false; + } + + ty_code_start = *pp; + + if (! ieee_read_number (info, pp, &tc)) + return false; + + dhandle = info->dhandle; + + tag = false; + typdef = false; + arg_slots = NULL; + type_bitsize = 0; + switch (tc) + { + default: + ieee_error (info, ty_code_start, _("unknown TY code")); + return false; + + case '!': + /* Unknown type, with size. We treat it as int. FIXME. */ + { + bfd_vma size; + + if (! ieee_read_number (info, pp, &size)) + return false; + type = debug_make_int_type (dhandle, size, false); + } + break; + + case 'A': /* Array. */ + case 'a': /* FORTRAN array in column/row order. FIXME: Not + distinguished from normal array. */ + { + debug_type ele_type; + bfd_vma lower, upper; + + if (! ieee_read_type_index (info, pp, &ele_type) + || ! ieee_read_number (info, pp, &lower) + || ! ieee_read_number (info, pp, &upper)) + return false; + type = debug_make_array_type (dhandle, ele_type, + ieee_builtin_type (info, ty_code_start, + ((unsigned int) + builtin_int)), + (bfd_signed_vma) lower, + (bfd_signed_vma) upper, + false); + } + break; + + case 'E': + /* Simple enumeration. */ + { + bfd_vma size; + unsigned int alloc; + const char **names; + unsigned int c; + bfd_signed_vma *vals; + unsigned int i; + + if (! ieee_read_number (info, pp, &size)) + return false; + /* FIXME: we ignore the enumeration size. */ + + alloc = 10; + names = (const char **) xmalloc (alloc * sizeof *names); + memset (names, 0, alloc * sizeof *names); + c = 0; + while (1) + { + const char *name; + unsigned long namlen; + boolean present; + + if (! ieee_read_optional_id (info, pp, &name, &namlen, &present)) + return false; + if (! present) + break; + + if (c + 1 >= alloc) + { + alloc += 10; + names = ((const char **) + xrealloc (names, alloc * sizeof *names)); + } + + names[c] = savestring (name, namlen); + if (names[c] == NULL) + return false; + ++c; + } + + names[c] = NULL; + + vals = (bfd_signed_vma *) xmalloc (c * sizeof *vals); + for (i = 0; i < c; i++) + vals[i] = i; + + type = debug_make_enum_type (dhandle, names, vals); + tag = true; + } + break; + + case 'G': + /* Struct with bit fields. */ + { + bfd_vma size; + unsigned int alloc; + debug_field *fields; + unsigned int c; + + if (! ieee_read_number (info, pp, &size)) + return false; + + alloc = 10; + fields = (debug_field *) xmalloc (alloc * sizeof *fields); + c = 0; + while (1) + { + const char *name; + unsigned long namlen; + boolean present; + debug_type ftype; + bfd_vma bitpos, bitsize; + + if (! ieee_read_optional_id (info, pp, &name, &namlen, &present)) + return false; + if (! present) + break; + if (! ieee_read_type_index (info, pp, &ftype) + || ! ieee_read_number (info, pp, &bitpos) + || ! ieee_read_number (info, pp, &bitsize)) + return false; + + if (c + 1 >= alloc) + { + alloc += 10; + fields = ((debug_field *) + xrealloc (fields, alloc * sizeof *fields)); + } + + fields[c] = debug_make_field (dhandle, savestring (name, namlen), + ftype, bitpos, bitsize, + DEBUG_VISIBILITY_PUBLIC); + if (fields[c] == NULL) + return false; + ++c; + } + + fields[c] = NULL; + + type = debug_make_struct_type (dhandle, true, size, fields); + tag = true; + } + break; + + case 'N': + /* Enumeration. */ + { + unsigned int alloc; + const char **names; + bfd_signed_vma *vals; + unsigned int c; + + alloc = 10; + names = (const char **) xmalloc (alloc * sizeof *names); + vals = (bfd_signed_vma *) xmalloc (alloc * sizeof *names); + c = 0; + while (1) + { + const char *name; + unsigned long namlen; + boolean present; + bfd_vma val; + + if (! ieee_read_optional_id (info, pp, &name, &namlen, &present)) + return false; + if (! present) + break; + if (! ieee_read_number (info, pp, &val)) + return false; + + /* If the length of the name is zero, then the value is + actually the size of the enum. We ignore this + information. FIXME. */ + if (namlen == 0) + continue; + + if (c + 1 >= alloc) + { + alloc += 10; + names = ((const char **) + xrealloc (names, alloc * sizeof *names)); + vals = ((bfd_signed_vma *) + xrealloc (vals, alloc * sizeof *vals)); + } + + names[c] = savestring (name, namlen); + if (names[c] == NULL) + return false; + vals[c] = (bfd_signed_vma) val; + ++c; + } + + names[c] = NULL; + + type = debug_make_enum_type (dhandle, names, vals); + tag = true; + } + break; + + case 'O': /* Small pointer. We don't distinguish small and large + pointers. FIXME. */ + case 'P': /* Large pointer. */ + { + debug_type t; + + if (! ieee_read_type_index (info, pp, &t)) + return false; + type = debug_make_pointer_type (dhandle, t); + } + break; + + case 'R': + /* Range. */ + { + bfd_vma low, high, signedp, size; + + if (! ieee_read_number (info, pp, &low) + || ! ieee_read_number (info, pp, &high) + || ! ieee_read_number (info, pp, &signedp) + || ! ieee_read_number (info, pp, &size)) + return false; + + type = debug_make_range_type (dhandle, + debug_make_int_type (dhandle, size, + ! signedp), + (bfd_signed_vma) low, + (bfd_signed_vma) high); + } + break; + + case 'S': /* Struct. */ + case 'U': /* Union. */ + { + bfd_vma size; + unsigned int alloc; + debug_field *fields; + unsigned int c; + + if (! ieee_read_number (info, pp, &size)) + return false; + + alloc = 10; + fields = (debug_field *) xmalloc (alloc * sizeof *fields); + c = 0; + while (1) + { + const char *name; + unsigned long namlen; + boolean present; + bfd_vma tindx; + bfd_vma offset; + debug_type ftype; + bfd_vma bitsize; + + if (! ieee_read_optional_id (info, pp, &name, &namlen, &present)) + return false; + if (! present) + break; + if (! ieee_read_number (info, pp, &tindx) + || ! ieee_read_number (info, pp, &offset)) + return false; + + if (tindx < 256) + { + ftype = ieee_builtin_type (info, ty_code_start, tindx); + bitsize = 0; + offset *= 8; + } + else + { + struct ieee_type *t; + + tindx -= 256; + if (! ieee_alloc_type (info, tindx, true)) + return false; + t = info->types.types + tindx; + ftype = t->type; + bitsize = t->bitsize; + if (bitsize == 0) + offset *= 8; + } + + if (c + 1 >= alloc) + { + alloc += 10; + fields = ((debug_field *) + xrealloc (fields, alloc * sizeof *fields)); + } + + fields[c] = debug_make_field (dhandle, savestring (name, namlen), + ftype, offset, bitsize, + DEBUG_VISIBILITY_PUBLIC); + if (fields[c] == NULL) + return false; + ++c; + } + + fields[c] = NULL; + + type = debug_make_struct_type (dhandle, tc == 'S', size, fields); + tag = true; + } + break; + + case 'T': + /* Typedef. */ + if (! ieee_read_type_index (info, pp, &type)) + return false; + typdef = true; + break; + + case 'X': + /* Procedure. FIXME: This is an extern declaration, which we + have no way of representing. */ + { + bfd_vma attr; + debug_type rtype; + bfd_vma nargs; + boolean present; + struct ieee_var *pv; + + /* FIXME: We ignore the attribute and the argument names. */ + + if (! ieee_read_number (info, pp, &attr) + || ! ieee_read_type_index (info, pp, &rtype) + || ! ieee_read_number (info, pp, &nargs)) + return false; + do + { + const char *name; + unsigned long namlen; + + if (! ieee_read_optional_id (info, pp, &name, &namlen, &present)) + return false; + } + while (present); + + pv = info->vars.vars + varindx; + pv->kind = IEEE_EXTERNAL; + if (pv->namlen > 0 + && debug_get_type_kind (dhandle, rtype) == DEBUG_KIND_POINTER) + { + /* Set up the return type as an indirect type pointing to + the variable slot, so that we can change it to a + reference later if appropriate. */ + pv->pslot = (debug_type *) xmalloc (sizeof *pv->pslot); + *pv->pslot = rtype; + rtype = debug_make_indirect_type (dhandle, pv->pslot, + (const char *) NULL); + } + + type = debug_make_function_type (dhandle, rtype, (debug_type *) NULL, + false); + } + break; + + case 'V': + /* Void. This is not documented, but the MRI compiler emits it. */ + type = debug_make_void_type (dhandle); + break; + + case 'Z': + /* Array with 0 lower bound. */ + { + debug_type etype; + bfd_vma high; + + if (! ieee_read_type_index (info, pp, &etype) + || ! ieee_read_number (info, pp, &high)) + return false; + + type = debug_make_array_type (dhandle, etype, + ieee_builtin_type (info, ty_code_start, + ((unsigned int) + builtin_int)), + 0, (bfd_signed_vma) high, false); + } + break; + + case 'c': /* Complex. */ + case 'd': /* Double complex. */ + { + const char *name; + unsigned long namlen; + + /* FIXME: I don't know what the name means. */ + + if (! ieee_read_id (info, pp, &name, &namlen)) + return false; + + type = debug_make_complex_type (dhandle, tc == 'c' ? 4 : 8); + } + break; + + case 'f': + /* Pascal file name. FIXME. */ + ieee_error (info, ty_code_start, _("Pascal file name not supported")); + return false; + + case 'g': + /* Bitfield type. */ + { + bfd_vma signedp, bitsize, dummy; + const bfd_byte *hold; + boolean present; + + if (! ieee_read_number (info, pp, &signedp) + || ! ieee_read_number (info, pp, &bitsize)) + return false; + + /* I think the documentation says that there is a type index, + but some actual files do not have one. */ + hold = *pp; + if (! ieee_read_optional_number (info, pp, &dummy, &present)) + return false; + if (! present) + { + /* FIXME: This is just a guess. */ + type = debug_make_int_type (dhandle, 4, + signedp ? false : true); + } + else + { + *pp = hold; + if (! ieee_read_type_index (info, pp, &type)) + return false; + } + type_bitsize = bitsize; + } + break; + + case 'n': + /* Qualifier. */ + { + bfd_vma kind; + debug_type t; + + if (! ieee_read_number (info, pp, &kind) + || ! ieee_read_type_index (info, pp, &t)) + return false; + + switch (kind) + { + default: + ieee_error (info, ty_start, _("unsupported qualifer")); + return false; + + case 1: + type = debug_make_const_type (dhandle, t); + break; + + case 2: + type = debug_make_volatile_type (dhandle, t); + break; + } + } + break; + + case 's': + /* Set. */ + { + bfd_vma size; + debug_type etype; + + if (! ieee_read_number (info, pp, &size) + || ! ieee_read_type_index (info, pp, &etype)) + return false; + + /* FIXME: We ignore the size. */ + + type = debug_make_set_type (dhandle, etype, false); + } + break; + + case 'x': + /* Procedure with compiler dependencies. */ + { + struct ieee_var *pv; + bfd_vma attr, frame_type, push_mask, nargs, level, father; + debug_type rtype; + debug_type *arg_types; + boolean varargs; + boolean present; + + /* FIXME: We ignore some of this information. */ + + pv = info->vars.vars + varindx; + + if (! ieee_read_number (info, pp, &attr) + || ! ieee_read_number (info, pp, &frame_type) + || ! ieee_read_number (info, pp, &push_mask) + || ! ieee_read_type_index (info, pp, &rtype) + || ! ieee_read_number (info, pp, &nargs)) + return false; + if (nargs == (bfd_vma) -1) + { + arg_types = NULL; + varargs = false; + } + else + { + unsigned int i; + + arg_types = ((debug_type *) + xmalloc ((nargs + 1) * sizeof *arg_types)); + for (i = 0; i < nargs; i++) + if (! ieee_read_type_index (info, pp, arg_types + i)) + return false; + + /* If the last type is pointer to void, this is really a + varargs function. */ + varargs = false; + if (nargs > 0) + { + debug_type last; + + last = arg_types[nargs - 1]; + if (debug_get_type_kind (dhandle, last) == DEBUG_KIND_POINTER + && (debug_get_type_kind (dhandle, + debug_get_target_type (dhandle, + last)) + == DEBUG_KIND_VOID)) + { + --nargs; + varargs = true; + } + } + + /* If there are any pointer arguments, turn them into + indirect types in case we later need to convert them to + reference types. */ + for (i = 0; i < nargs; i++) + { + if (debug_get_type_kind (dhandle, arg_types[i]) + == DEBUG_KIND_POINTER) + { + if (arg_slots == NULL) + { + arg_slots = ((debug_type *) + xmalloc (nargs * sizeof *arg_slots)); + memset (arg_slots, 0, nargs * sizeof *arg_slots); + } + arg_slots[i] = arg_types[i]; + arg_types[i] = + debug_make_indirect_type (dhandle, + arg_slots + i, + (const char *) NULL); + } + } + + arg_types[nargs] = DEBUG_TYPE_NULL; + } + if (! ieee_read_number (info, pp, &level) + || ! ieee_read_optional_number (info, pp, &father, &present)) + return false; + + /* We can't distinguish between a global function and a static + function. */ + pv->kind = IEEE_FUNCTION; + + if (pv->namlen > 0 + && debug_get_type_kind (dhandle, rtype) == DEBUG_KIND_POINTER) + { + /* Set up the return type as an indirect type pointing to + the variable slot, so that we can change it to a + reference later if appropriate. */ + pv->pslot = (debug_type *) xmalloc (sizeof *pv->pslot); + *pv->pslot = rtype; + rtype = debug_make_indirect_type (dhandle, pv->pslot, + (const char *) NULL); + } + + type = debug_make_function_type (dhandle, rtype, arg_types, varargs); + } + break; + } + + /* Record the type in the table. */ + + if (type == DEBUG_TYPE_NULL) + return false; + + info->vars.vars[varindx].type = type; + + if ((tag || typdef) + && info->vars.vars[varindx].namlen > 0) + { + const char *name; + + name = savestring (info->vars.vars[varindx].name, + info->vars.vars[varindx].namlen); + if (typdef) + type = debug_name_type (dhandle, name, type); + else if (tc == 'E' || tc == 'N') + type = debug_tag_type (dhandle, name, type); + else + { + struct ieee_tag *it; + + /* We must allocate all struct tags as indirect types, so + that if we later see a definition of the tag as a C++ + record we can update the indirect slot and automatically + change all the existing references. */ + it = (struct ieee_tag *) xmalloc (sizeof *it); + memset (it, 0, sizeof *it); + it->next = info->tags; + info->tags = it; + it->name = name; + it->slot = type; + + type = debug_make_indirect_type (dhandle, &it->slot, name); + type = debug_tag_type (dhandle, name, type); + + it->type = type; + } + if (type == NULL) + return false; + } + + info->types.types[typeindx].type = type; + info->types.types[typeindx].arg_slots = arg_slots; + info->types.types[typeindx].bitsize = type_bitsize; + + /* We may have already allocated type as an indirect type pointing + to slot. It does no harm to replace the indirect type with the + real type. Filling in slot as well handles the indirect types + which are already hanging around. */ + if (info->types.types[typeindx].pslot != NULL) + *info->types.types[typeindx].pslot = type; + + return true; +} + +/* Parse an ATN record. */ + +static boolean +parse_ieee_atn (info, pp) + struct ieee_info *info; + const bfd_byte **pp; +{ + const bfd_byte *atn_start, *atn_code_start; + bfd_vma varindx; + struct ieee_var *pvar; + debug_type type; + bfd_vma atn_code; + PTR dhandle; + bfd_vma v, v2, v3, v4, v5; + const char *name; + unsigned long namlen; + char *namcopy; + boolean present; + int blocktype; + + atn_start = *pp; + + if (! ieee_read_number (info, pp, &varindx) + || ! ieee_read_type_index (info, pp, &type)) + return false; + + atn_code_start = *pp; + + if (! ieee_read_number (info, pp, &atn_code)) + return false; + + if (varindx == 0) + { + pvar = NULL; + name = ""; + namlen = 0; + } + else if (varindx < 32) + { + /* The MRI compiler reportedly sometimes emits variable lifetime + information for a register. We just ignore it. */ + if (atn_code == 9) + return ieee_read_number (info, pp, &v); + + ieee_error (info, atn_start, _("illegal variable index")); + return false; + } + else + { + varindx -= 32; + if (varindx >= info->vars.alloc + || info->vars.vars[varindx].name == NULL) + { + /* The MRI compiler or linker sometimes omits the NN record + for a pmisc record. */ + if (atn_code == 62) + { + if (varindx >= info->vars.alloc) + { + unsigned int alloc; + + alloc = info->vars.alloc; + if (alloc == 0) + alloc = 4; + while (varindx >= alloc) + alloc *= 2; + info->vars.vars = ((struct ieee_var *) + xrealloc (info->vars.vars, + (alloc + * sizeof *info->vars.vars))); + memset (info->vars.vars + info->vars.alloc, 0, + ((alloc - info->vars.alloc) + * sizeof *info->vars.vars)); + info->vars.alloc = alloc; + } + + pvar = info->vars.vars + varindx; + pvar->name = ""; + pvar->namlen = 0; + } + else + { + ieee_error (info, atn_start, _("undefined variable in ATN")); + return false; + } + } + + pvar = info->vars.vars + varindx; + + pvar->type = type; + + name = pvar->name; + namlen = pvar->namlen; + } + + dhandle = info->dhandle; + + /* If we are going to call debug_record_variable with a pointer + type, change the type to an indirect type so that we can later + change it to a reference type if we encounter a C++ pmisc 'R' + record. */ + if (pvar != NULL + && type != DEBUG_TYPE_NULL + && debug_get_type_kind (dhandle, type) == DEBUG_KIND_POINTER) + { + switch (atn_code) + { + case 1: + case 2: + case 3: + case 5: + case 8: + case 10: + pvar->pslot = (debug_type *) xmalloc (sizeof *pvar->pslot); + *pvar->pslot = type; + type = debug_make_indirect_type (dhandle, pvar->pslot, + (const char *) NULL); + pvar->type = type; + break; + } + } + + switch (atn_code) + { + default: + ieee_error (info, atn_code_start, _("unknown ATN type")); + return false; + + case 1: + /* Automatic variable. */ + if (! ieee_read_number (info, pp, &v)) + return false; + namcopy = savestring (name, namlen); + if (type == NULL) + type = debug_make_void_type (dhandle); + if (pvar != NULL) + pvar->kind = IEEE_LOCAL; + return debug_record_variable (dhandle, namcopy, type, DEBUG_LOCAL, v); + + case 2: + /* Register variable. */ + if (! ieee_read_number (info, pp, &v)) + return false; + namcopy = savestring (name, namlen); + if (type == NULL) + type = debug_make_void_type (dhandle); + if (pvar != NULL) + pvar->kind = IEEE_LOCAL; + return debug_record_variable (dhandle, namcopy, type, DEBUG_REGISTER, + ieee_regno_to_genreg (info->abfd, v)); + + case 3: + /* Static variable. */ + if (! ieee_require_asn (info, pp, &v)) + return false; + namcopy = savestring (name, namlen); + if (type == NULL) + type = debug_make_void_type (dhandle); + if (info->blockstack.bsp <= info->blockstack.stack) + blocktype = 0; + else + blocktype = info->blockstack.bsp[-1].kind; + if (pvar != NULL) + { + if (blocktype == 4 || blocktype == 6) + pvar->kind = IEEE_LOCAL; + else + pvar->kind = IEEE_STATIC; + } + return debug_record_variable (dhandle, namcopy, type, + (blocktype == 4 || blocktype == 6 + ? DEBUG_LOCAL_STATIC + : DEBUG_STATIC), + v); + + case 4: + /* External function. We don't currently record these. FIXME. */ + if (pvar != NULL) + pvar->kind = IEEE_EXTERNAL; + return true; + + case 5: + /* External variable. We don't currently record these. FIXME. */ + if (pvar != NULL) + pvar->kind = IEEE_EXTERNAL; + return true; + + case 7: + if (! ieee_read_number (info, pp, &v) + || ! ieee_read_number (info, pp, &v2) + || ! ieee_read_optional_number (info, pp, &v3, &present)) + return false; + if (present) + { + if (! ieee_read_optional_number (info, pp, &v4, &present)) + return false; + } + + /* We just ignore the two optional fields in v3 and v4, since + they are not defined. */ + + if (! ieee_require_asn (info, pp, &v3)) + return false; + + /* We have no way to record the column number. FIXME. */ + + return debug_record_line (dhandle, v, v3); + + case 8: + /* Global variable. */ + if (! ieee_require_asn (info, pp, &v)) + return false; + namcopy = savestring (name, namlen); + if (type == NULL) + type = debug_make_void_type (dhandle); + if (pvar != NULL) + pvar->kind = IEEE_GLOBAL; + return debug_record_variable (dhandle, namcopy, type, DEBUG_GLOBAL, v); + + case 9: + /* Variable lifetime information. */ + if (! ieee_read_number (info, pp, &v)) + return false; + + /* We have no way to record this information. FIXME. */ + return true; + + case 10: + /* Locked register. The spec says that there are two required + fields, but at least on occasion the MRI compiler only emits + one. */ + if (! ieee_read_number (info, pp, &v) + || ! ieee_read_optional_number (info, pp, &v2, &present)) + return false; + + /* I think this means a variable that is both in a register and + a frame slot. We ignore the frame slot. FIXME. */ + + namcopy = savestring (name, namlen); + if (type == NULL) + type = debug_make_void_type (dhandle); + if (pvar != NULL) + pvar->kind = IEEE_LOCAL; + return debug_record_variable (dhandle, namcopy, type, DEBUG_REGISTER, v); + + case 11: + /* Reserved for FORTRAN common. */ + ieee_error (info, atn_code_start, _("unsupported ATN11")); + + /* Return true to keep going. */ + return true; + + case 12: + /* Based variable. */ + v3 = 0; + v4 = 0x80; + v5 = 0; + if (! ieee_read_number (info, pp, &v) + || ! ieee_read_number (info, pp, &v2) + || ! ieee_read_optional_number (info, pp, &v3, &present)) + return false; + if (present) + { + if (! ieee_read_optional_number (info, pp, &v4, &present)) + return false; + if (present) + { + if (! ieee_read_optional_number (info, pp, &v5, &present)) + return false; + } + } + + /* We have no way to record this information. FIXME. */ + + ieee_error (info, atn_code_start, _("unsupported ATN12")); + + /* Return true to keep going. */ + return true; + + case 16: + /* Constant. The description of this that I have is ambiguous, + so I'm not going to try to implement it. */ + if (! ieee_read_number (info, pp, &v) + || ! ieee_read_optional_number (info, pp, &v2, &present)) + return false; + if (present) + { + if (! ieee_read_optional_number (info, pp, &v2, &present)) + return false; + if (present) + { + if (! ieee_read_optional_id (info, pp, &name, &namlen, &present)) + return false; + } + } + + if ((ieee_record_enum_type) **pp == ieee_e2_first_byte_enum) + { + if (! ieee_require_asn (info, pp, &v3)) + return false; + } + + return true; + + case 19: + /* Static variable from assembler. */ + v2 = 0; + if (! ieee_read_number (info, pp, &v) + || ! ieee_read_optional_number (info, pp, &v2, &present) + || ! ieee_require_asn (info, pp, &v3)) + return false; + namcopy = savestring (name, namlen); + /* We don't really handle this correctly. FIXME. */ + return debug_record_variable (dhandle, namcopy, + debug_make_void_type (dhandle), + v2 != 0 ? DEBUG_GLOBAL : DEBUG_STATIC, + v3); + + case 62: + /* Procedure miscellaneous information. */ + case 63: + /* Variable miscellaneous information. */ + case 64: + /* Module miscellaneous information. */ + if (! ieee_read_number (info, pp, &v) + || ! ieee_read_number (info, pp, &v2) + || ! ieee_read_optional_id (info, pp, &name, &namlen, &present)) + return false; + + if (atn_code == 62 && v == 80) + { + if (present) + { + ieee_error (info, atn_code_start, + _("unexpected string in C++ misc")); + return false; + } + return ieee_read_cxx_misc (info, pp, v2); + } + + /* We just ignore all of this stuff. FIXME. */ + + for (; v2 > 0; --v2) + { + switch ((ieee_record_enum_type) **pp) + { + default: + ieee_error (info, *pp, _("bad misc record")); + return false; + + case ieee_at_record_enum: + if (! ieee_require_atn65 (info, pp, &name, &namlen)) + return false; + break; + + case ieee_e2_first_byte_enum: + if (! ieee_require_asn (info, pp, &v3)) + return false; + break; + } + } + + return true; + } + + /*NOTREACHED*/ +} + +/* Handle C++ debugging miscellaneous records. This is called for + procedure miscellaneous records of type 80. */ + +static boolean +ieee_read_cxx_misc (info, pp, count) + struct ieee_info *info; + const bfd_byte **pp; + unsigned long count; +{ + const bfd_byte *start; + bfd_vma category; + + start = *pp; + + /* Get the category of C++ misc record. */ + if (! ieee_require_asn (info, pp, &category)) + return false; + --count; + + switch (category) + { + default: + ieee_error (info, start, _("unrecognized C++ misc record")); + return false; + + case 'T': + if (! ieee_read_cxx_class (info, pp, count)) + return false; + break; + + case 'M': + { + bfd_vma flags; + const char *name; + unsigned long namlen; + + /* The IEEE spec indicates that the 'M' record only has a + flags field. The MRI compiler also emits the name of the + function. */ + + if (! ieee_require_asn (info, pp, &flags)) + return false; + if (*pp < info->pend + && (ieee_record_enum_type) **pp == ieee_at_record_enum) + { + if (! ieee_require_atn65 (info, pp, &name, &namlen)) + return false; + } + + /* This is emitted for method functions, but I don't think we + care very much. It might help if it told us useful + information like the class with which this function is + associated, but it doesn't, so it isn't helpful. */ + } + break; + + case 'B': + if (! ieee_read_cxx_defaults (info, pp, count)) + return false; + break; + + case 'z': + { + const char *name, *mangled, *class; + unsigned long namlen, mangledlen, classlen; + bfd_vma control; + + /* Pointer to member. */ + + if (! ieee_require_atn65 (info, pp, &name, &namlen) + || ! ieee_require_atn65 (info, pp, &mangled, &mangledlen) + || ! ieee_require_atn65 (info, pp, &class, &classlen) + || ! ieee_require_asn (info, pp, &control)) + return false; + + /* FIXME: We should now track down name and change its type. */ + } + break; + + case 'R': + if (! ieee_read_reference (info, pp)) + return false; + break; + } + + return true; +} + +/* Read a C++ class definition. This is a pmisc type 80 record of + category 'T'. */ + +static boolean +ieee_read_cxx_class (info, pp, count) + struct ieee_info *info; + const bfd_byte **pp; + unsigned long count; +{ + const bfd_byte *start; + bfd_vma class; + const char *tag; + unsigned long taglen; + struct ieee_tag *it; + PTR dhandle; + debug_field *fields; + unsigned int field_count, field_alloc; + debug_baseclass *baseclasses; + unsigned int baseclasses_count, baseclasses_alloc; + const debug_field *structfields; + struct ieee_method + { + const char *name; + unsigned long namlen; + debug_method_variant *variants; + unsigned count; + unsigned int alloc; + } *methods; + unsigned int methods_count, methods_alloc; + debug_type vptrbase; + boolean ownvptr; + debug_method *dmethods; + + start = *pp; + + if (! ieee_require_asn (info, pp, &class)) + return false; + --count; + + if (! ieee_require_atn65 (info, pp, &tag, &taglen)) + return false; + --count; + + /* Find the C struct with this name. */ + for (it = info->tags; it != NULL; it = it->next) + if (it->name[0] == tag[0] + && strncmp (it->name, tag, taglen) == 0 + && strlen (it->name) == taglen) + break; + if (it == NULL) + { + ieee_error (info, start, _("undefined C++ object")); + return false; + } + + dhandle = info->dhandle; + + fields = NULL; + field_count = 0; + field_alloc = 0; + baseclasses = NULL; + baseclasses_count = 0; + baseclasses_alloc = 0; + methods = NULL; + methods_count = 0; + methods_alloc = 0; + vptrbase = DEBUG_TYPE_NULL; + ownvptr = false; + + structfields = debug_get_fields (dhandle, it->type); + + while (count > 0) + { + bfd_vma id; + const bfd_byte *spec_start; + + spec_start = *pp; + + if (! ieee_require_asn (info, pp, &id)) + return false; + --count; + + switch (id) + { + default: + ieee_error (info, spec_start, _("unrecognized C++ object spec")); + return false; + + case 'b': + { + bfd_vma flags, cinline; + const char *basename, *fieldname; + unsigned long baselen, fieldlen; + char *basecopy; + debug_type basetype; + bfd_vma bitpos; + boolean virtualp; + enum debug_visibility visibility; + debug_baseclass baseclass; + + /* This represents a base or friend class. */ + + if (! ieee_require_asn (info, pp, &flags) + || ! ieee_require_atn65 (info, pp, &basename, &baselen) + || ! ieee_require_asn (info, pp, &cinline) + || ! ieee_require_atn65 (info, pp, &fieldname, &fieldlen)) + return false; + count -= 4; + + /* We have no way of recording friend information, so we + just ignore it. */ + if ((flags & BASEFLAGS_FRIEND) != 0) + break; + + /* I assume that either all of the members of the + baseclass are included in the object, starting at the + beginning of the object, or that none of them are + included. */ + + if ((fieldlen == 0) == (cinline == 0)) + { + ieee_error (info, start, _("unsupported C++ object type")); + return false; + } + + basecopy = savestring (basename, baselen); + basetype = debug_find_tagged_type (dhandle, basecopy, + DEBUG_KIND_ILLEGAL); + free (basecopy); + if (basetype == DEBUG_TYPE_NULL) + { + ieee_error (info, start, _("C++ base class not defined")); + return false; + } + + if (fieldlen == 0) + bitpos = 0; + else + { + const debug_field *pf; + + if (structfields == NULL) + { + ieee_error (info, start, _("C++ object has no fields")); + return false; + } + + for (pf = structfields; *pf != DEBUG_FIELD_NULL; pf++) + { + const char *fname; + + fname = debug_get_field_name (dhandle, *pf); + if (fname == NULL) + return false; + if (fname[0] == fieldname[0] + && strncmp (fname, fieldname, fieldlen) == 0 + && strlen (fname) == fieldlen) + break; + } + if (*pf == DEBUG_FIELD_NULL) + { + ieee_error (info, start, + _("C++ base class not found in container")); + return false; + } + + bitpos = debug_get_field_bitpos (dhandle, *pf); + } + + if ((flags & BASEFLAGS_VIRTUAL) != 0) + virtualp = true; + else + virtualp = false; + if ((flags & BASEFLAGS_PRIVATE) != 0) + visibility = DEBUG_VISIBILITY_PRIVATE; + else + visibility = DEBUG_VISIBILITY_PUBLIC; + + baseclass = debug_make_baseclass (dhandle, basetype, bitpos, + virtualp, visibility); + if (baseclass == DEBUG_BASECLASS_NULL) + return false; + + if (baseclasses_count + 1 >= baseclasses_alloc) + { + baseclasses_alloc += 10; + baseclasses = ((debug_baseclass *) + xrealloc (baseclasses, + (baseclasses_alloc + * sizeof *baseclasses))); + } + + baseclasses[baseclasses_count] = baseclass; + ++baseclasses_count; + baseclasses[baseclasses_count] = DEBUG_BASECLASS_NULL; + } + break; + + case 'd': + { + bfd_vma flags; + const char *fieldname, *mangledname; + unsigned long fieldlen, mangledlen; + char *fieldcopy; + boolean staticp; + debug_type ftype; + const debug_field *pf = NULL; + enum debug_visibility visibility; + debug_field field; + + /* This represents a data member. */ + + if (! ieee_require_asn (info, pp, &flags) + || ! ieee_require_atn65 (info, pp, &fieldname, &fieldlen) + || ! ieee_require_atn65 (info, pp, &mangledname, &mangledlen)) + return false; + count -= 3; + + fieldcopy = savestring (fieldname, fieldlen); + + staticp = (flags & CXXFLAGS_STATIC) != 0 ? true : false; + + if (staticp) + { + struct ieee_var *pv, *pvend; + + /* See if we can find a definition for this variable. */ + pv = info->vars.vars; + pvend = pv + info->vars.alloc; + for (; pv < pvend; pv++) + if (pv->namlen == mangledlen + && strncmp (pv->name, mangledname, mangledlen) == 0) + break; + if (pv < pvend) + ftype = pv->type; + else + { + /* This can happen if the variable is never used. */ + ftype = ieee_builtin_type (info, start, + (unsigned int) builtin_void); + } + } + else + { + unsigned int findx; + + if (structfields == NULL) + { + ieee_error (info, start, _("C++ object has no fields")); + return false; + } + + for (pf = structfields, findx = 0; + *pf != DEBUG_FIELD_NULL; + pf++, findx++) + { + const char *fname; + + fname = debug_get_field_name (dhandle, *pf); + if (fname == NULL) + return false; + if (fname[0] == mangledname[0] + && strncmp (fname, mangledname, mangledlen) == 0 + && strlen (fname) == mangledlen) + break; + } + if (*pf == DEBUG_FIELD_NULL) + { + ieee_error (info, start, + _("C++ data member not found in container")); + return false; + } + + ftype = debug_get_field_type (dhandle, *pf); + + if (debug_get_type_kind (dhandle, ftype) == DEBUG_KIND_POINTER) + { + /* We might need to convert this field into a + reference type later on, so make it an indirect + type. */ + if (it->fslots == NULL) + { + unsigned int fcnt; + const debug_field *pfcnt; + + fcnt = 0; + for (pfcnt = structfields; + *pfcnt != DEBUG_FIELD_NULL; + pfcnt++) + ++fcnt; + it->fslots = ((debug_type *) + xmalloc (fcnt * sizeof *it->fslots)); + memset (it->fslots, 0, + fcnt * sizeof *it->fslots); + } + + if (ftype == DEBUG_TYPE_NULL) + return false; + it->fslots[findx] = ftype; + ftype = debug_make_indirect_type (dhandle, + it->fslots + findx, + (const char *) NULL); + } + } + if (ftype == DEBUG_TYPE_NULL) + return false; + + switch (flags & CXXFLAGS_VISIBILITY) + { + default: + ieee_error (info, start, _("unknown C++ visibility")); + return false; + + case CXXFLAGS_VISIBILITY_PUBLIC: + visibility = DEBUG_VISIBILITY_PUBLIC; + break; + + case CXXFLAGS_VISIBILITY_PRIVATE: + visibility = DEBUG_VISIBILITY_PRIVATE; + break; + + case CXXFLAGS_VISIBILITY_PROTECTED: + visibility = DEBUG_VISIBILITY_PROTECTED; + break; + } + + if (staticp) + { + char *mangledcopy; + + mangledcopy = savestring (mangledname, mangledlen); + + field = debug_make_static_member (dhandle, fieldcopy, + ftype, mangledcopy, + visibility); + } + else + { + bfd_vma bitpos, bitsize; + + bitpos = debug_get_field_bitpos (dhandle, *pf); + bitsize = debug_get_field_bitsize (dhandle, *pf); + if (bitpos == (bfd_vma) -1 || bitsize == (bfd_vma) -1) + { + ieee_error (info, start, _("bad C++ field bit pos or size")); + return false; + } + field = debug_make_field (dhandle, fieldcopy, ftype, bitpos, + bitsize, visibility); + } + + if (field == DEBUG_FIELD_NULL) + return false; + + if (field_count + 1 >= field_alloc) + { + field_alloc += 10; + fields = ((debug_field *) + xrealloc (fields, field_alloc * sizeof *fields)); + } + + fields[field_count] = field; + ++field_count; + fields[field_count] = DEBUG_FIELD_NULL; + } + break; + + case 'm': + case 'v': + { + bfd_vma flags, voffset, control; + const char *name, *mangled; + unsigned long namlen, mangledlen; + struct ieee_var *pv, *pvend; + debug_type type; + enum debug_visibility visibility; + boolean constp, volatilep; + char *mangledcopy; + debug_method_variant mv; + struct ieee_method *meth; + unsigned int im; + + if (! ieee_require_asn (info, pp, &flags) + || ! ieee_require_atn65 (info, pp, &name, &namlen) + || ! ieee_require_atn65 (info, pp, &mangled, &mangledlen)) + return false; + count -= 3; + if (id != 'v') + voffset = 0; + else + { + if (! ieee_require_asn (info, pp, &voffset)) + return false; + --count; + } + if (! ieee_require_asn (info, pp, &control)) + return false; + --count; + + /* We just ignore the control information. */ + + /* We have no way to represent friend information, so we + just ignore it. */ + if ((flags & CXXFLAGS_FRIEND) != 0) + break; + + /* We should already have seen a type for the function. */ + pv = info->vars.vars; + pvend = pv + info->vars.alloc; + for (; pv < pvend; pv++) + if (pv->namlen == mangledlen + && strncmp (pv->name, mangled, mangledlen) == 0) + break; + + if (pv >= pvend) + { + /* We won't have type information for this function if + it is not included in this file. We don't try to + handle this case. FIXME. */ + type = (debug_make_function_type + (dhandle, + ieee_builtin_type (info, start, + (unsigned int) builtin_void), + (debug_type *) NULL, + false)); + } + else + { + debug_type return_type; + const debug_type *arg_types; + boolean varargs; + + if (debug_get_type_kind (dhandle, pv->type) + != DEBUG_KIND_FUNCTION) + { + ieee_error (info, start, + _("bad type for C++ method function")); + return false; + } + + return_type = debug_get_return_type (dhandle, pv->type); + arg_types = debug_get_parameter_types (dhandle, pv->type, + &varargs); + if (return_type == DEBUG_TYPE_NULL || arg_types == NULL) + { + ieee_error (info, start, + _("no type information for C++ method function")); + return false; + } + + type = debug_make_method_type (dhandle, return_type, it->type, + (debug_type *) arg_types, + varargs); + } + if (type == DEBUG_TYPE_NULL) + return false; + + switch (flags & CXXFLAGS_VISIBILITY) + { + default: + ieee_error (info, start, _("unknown C++ visibility")); + return false; + + case CXXFLAGS_VISIBILITY_PUBLIC: + visibility = DEBUG_VISIBILITY_PUBLIC; + break; + + case CXXFLAGS_VISIBILITY_PRIVATE: + visibility = DEBUG_VISIBILITY_PRIVATE; + break; + + case CXXFLAGS_VISIBILITY_PROTECTED: + visibility = DEBUG_VISIBILITY_PROTECTED; + break; + } + + constp = (flags & CXXFLAGS_CONST) != 0 ? true : false; + volatilep = (flags & CXXFLAGS_VOLATILE) != 0 ? true : false; + + mangledcopy = savestring (mangled, mangledlen); + + if ((flags & CXXFLAGS_STATIC) != 0) + { + if (id == 'v') + { + ieee_error (info, start, _("C++ static virtual method")); + return false; + } + mv = debug_make_static_method_variant (dhandle, mangledcopy, + type, visibility, + constp, volatilep); + } + else + { + debug_type vcontext; + + if (id != 'v') + vcontext = DEBUG_TYPE_NULL; + else + { + /* FIXME: How can we calculate this correctly? */ + vcontext = it->type; + } + mv = debug_make_method_variant (dhandle, mangledcopy, type, + visibility, constp, + volatilep, voffset, + vcontext); + } + if (mv == DEBUG_METHOD_VARIANT_NULL) + return false; + + for (meth = methods, im = 0; im < methods_count; meth++, im++) + if (meth->namlen == namlen + && strncmp (meth->name, name, namlen) == 0) + break; + if (im >= methods_count) + { + if (methods_count >= methods_alloc) + { + methods_alloc += 10; + methods = ((struct ieee_method *) + xrealloc (methods, + methods_alloc * sizeof *methods)); + } + methods[methods_count].name = name; + methods[methods_count].namlen = namlen; + methods[methods_count].variants = NULL; + methods[methods_count].count = 0; + methods[methods_count].alloc = 0; + meth = methods + methods_count; + ++methods_count; + } + + if (meth->count + 1 >= meth->alloc) + { + meth->alloc += 10; + meth->variants = ((debug_method_variant *) + xrealloc (meth->variants, + (meth->alloc + * sizeof *meth->variants))); + } + + meth->variants[meth->count] = mv; + ++meth->count; + meth->variants[meth->count] = DEBUG_METHOD_VARIANT_NULL; + } + break; + + case 'o': + { + bfd_vma spec; + + /* We have no way to store this information, so we just + ignore it. */ + if (! ieee_require_asn (info, pp, &spec)) + return false; + --count; + if ((spec & 4) != 0) + { + const char *filename; + unsigned long filenamlen; + bfd_vma lineno; + + if (! ieee_require_atn65 (info, pp, &filename, &filenamlen) + || ! ieee_require_asn (info, pp, &lineno)) + return false; + count -= 2; + } + else if ((spec & 8) != 0) + { + const char *mangled; + unsigned long mangledlen; + + if (! ieee_require_atn65 (info, pp, &mangled, &mangledlen)) + return false; + --count; + } + else + { + ieee_error (info, start, + _("unrecognized C++ object overhead spec")); + return false; + } + } + break; + + case 'z': + { + const char *vname, *basename; + unsigned long vnamelen, baselen; + bfd_vma vsize, control; + + /* A virtual table pointer. */ + + if (! ieee_require_atn65 (info, pp, &vname, &vnamelen) + || ! ieee_require_asn (info, pp, &vsize) + || ! ieee_require_atn65 (info, pp, &basename, &baselen) + || ! ieee_require_asn (info, pp, &control)) + return false; + count -= 4; + + /* We just ignore the control number. We don't care what + the virtual table name is. We have no way to store the + virtual table size, and I don't think we care anyhow. */ + + /* FIXME: We can't handle multiple virtual table pointers. */ + + if (baselen == 0) + ownvptr = true; + else + { + char *basecopy; + + basecopy = savestring (basename, baselen); + vptrbase = debug_find_tagged_type (dhandle, basecopy, + DEBUG_KIND_ILLEGAL); + free (basecopy); + if (vptrbase == DEBUG_TYPE_NULL) + { + ieee_error (info, start, _("undefined C++ vtable")); + return false; + } + } + } + break; + } + } + + /* Now that we have seen all the method variants, we can call + debug_make_method for each one. */ + + if (methods_count == 0) + dmethods = NULL; + else + { + unsigned int i; + + dmethods = ((debug_method *) + xmalloc ((methods_count + 1) * sizeof *dmethods)); + for (i = 0; i < methods_count; i++) + { + char *namcopy; + + namcopy = savestring (methods[i].name, methods[i].namlen); + dmethods[i] = debug_make_method (dhandle, namcopy, + methods[i].variants); + if (dmethods[i] == DEBUG_METHOD_NULL) + return false; + } + dmethods[i] = DEBUG_METHOD_NULL; + free (methods); + } + + /* The struct type was created as an indirect type pointing at + it->slot. We update it->slot to automatically update all + references to this struct. */ + it->slot = debug_make_object_type (dhandle, + class != 'u', + debug_get_type_size (dhandle, + it->slot), + fields, baseclasses, dmethods, + vptrbase, ownvptr); + if (it->slot == DEBUG_TYPE_NULL) + return false; + + return true; +} + +/* Read C++ default argument value and reference type information. */ + +static boolean +ieee_read_cxx_defaults (info, pp, count) + struct ieee_info *info; + const bfd_byte **pp; + unsigned long count; +{ + const bfd_byte *start; + const char *fnname; + unsigned long fnlen; + bfd_vma defcount; + + start = *pp; + + /* Giving the function name before the argument count is an addendum + to the spec. The function name is demangled, though, so this + record must always refer to the current function. */ + + if (info->blockstack.bsp <= info->blockstack.stack + || info->blockstack.bsp[-1].fnindx == (unsigned int) -1) + { + ieee_error (info, start, _("C++ default values not in a function")); + return false; + } + + if (! ieee_require_atn65 (info, pp, &fnname, &fnlen) + || ! ieee_require_asn (info, pp, &defcount)) + return false; + count -= 2; + + while (defcount-- > 0) + { + bfd_vma type, val; + const char *strval; + unsigned long strvallen; + + if (! ieee_require_asn (info, pp, &type)) + return false; + --count; + + switch (type) + { + case 0: + case 4: + break; + + case 1: + case 2: + if (! ieee_require_asn (info, pp, &val)) + return false; + --count; + break; + + case 3: + case 7: + if (! ieee_require_atn65 (info, pp, &strval, &strvallen)) + return false; + --count; + break; + + default: + ieee_error (info, start, _("unrecognized C++ default type")); + return false; + } + + /* We have no way to record the default argument values, so we + just ignore them. FIXME. */ + } + + /* Any remaining arguments are indices of parameters that are really + reference type. */ + if (count > 0) + { + PTR dhandle; + debug_type *arg_slots; + + dhandle = info->dhandle; + arg_slots = info->types.types[info->blockstack.bsp[-1].fnindx].arg_slots; + while (count-- > 0) + { + bfd_vma indx; + debug_type target; + + if (! ieee_require_asn (info, pp, &indx)) + return false; + /* The index is 1 based. */ + --indx; + if (arg_slots == NULL + || arg_slots[indx] == DEBUG_TYPE_NULL + || (debug_get_type_kind (dhandle, arg_slots[indx]) + != DEBUG_KIND_POINTER)) + { + ieee_error (info, start, _("reference parameter is not a pointer")); + return false; + } + + target = debug_get_target_type (dhandle, arg_slots[indx]); + arg_slots[indx] = debug_make_reference_type (dhandle, target); + if (arg_slots[indx] == DEBUG_TYPE_NULL) + return false; + } + } + + return true; +} + +/* Read a C++ reference definition. */ + +static boolean +ieee_read_reference (info, pp) + struct ieee_info *info; + const bfd_byte **pp; +{ + const bfd_byte *start; + bfd_vma flags; + const char *class, *name; + unsigned long classlen, namlen; + debug_type *pslot; + debug_type target; + + start = *pp; + + if (! ieee_require_asn (info, pp, &flags)) + return false; + + /* Giving the class name before the member name is in an addendum to + the spec. */ + if (flags == 3) + { + if (! ieee_require_atn65 (info, pp, &class, &classlen)) + return false; + } + + if (! ieee_require_atn65 (info, pp, &name, &namlen)) + return false; + + pslot = NULL; + if (flags != 3) + { + int pass; + + /* We search from the last variable indices to the first in + hopes of finding local variables correctly. We search the + local variables on the first pass, and the global variables + on the second. FIXME: This probably won't work in all cases. + On the other hand, I don't know what will. */ + for (pass = 0; pass < 2; pass++) + { + struct ieee_vars *vars; + int i; + struct ieee_var *pv = NULL; + + if (pass == 0) + vars = &info->vars; + else + { + vars = info->global_vars; + if (vars == NULL) + break; + } + + for (i = (int) vars->alloc - 1; i >= 0; i--) + { + boolean found; + + pv = vars->vars + i; + + if (pv->pslot == NULL + || pv->namlen != namlen + || strncmp (pv->name, name, namlen) != 0) + continue; + + found = false; + switch (flags) + { + default: + ieee_error (info, start, + _("unrecognized C++ reference type")); + return false; + + case 0: + /* Global variable or function. */ + if (pv->kind == IEEE_GLOBAL + || pv->kind == IEEE_EXTERNAL + || pv->kind == IEEE_FUNCTION) + found = true; + break; + + case 1: + /* Global static variable or function. */ + if (pv->kind == IEEE_STATIC + || pv->kind == IEEE_FUNCTION) + found = true; + break; + + case 2: + /* Local variable. */ + if (pv->kind == IEEE_LOCAL) + found = true; + break; + } + + if (found) + break; + } + + if (i >= 0) + { + pslot = pv->pslot; + break; + } + } + } + else + { + struct ieee_tag *it; + + for (it = info->tags; it != NULL; it = it->next) + { + if (it->name[0] == class[0] + && strncmp (it->name, class, classlen) == 0 + && strlen (it->name) == classlen) + { + if (it->fslots != NULL) + { + const debug_field *pf; + unsigned int findx; + + pf = debug_get_fields (info->dhandle, it->type); + if (pf == NULL) + { + ieee_error (info, start, + "C++ reference in class with no fields"); + return false; + } + + for (findx = 0; *pf != DEBUG_FIELD_NULL; pf++, findx++) + { + const char *fname; + + fname = debug_get_field_name (info->dhandle, *pf); + if (fname == NULL) + return false; + if (strncmp (fname, name, namlen) == 0 + && strlen (fname) == namlen) + { + pslot = it->fslots + findx; + break; + } + } + } + + break; + } + } + } + + if (pslot == NULL) + { + ieee_error (info, start, _("C++ reference not found")); + return false; + } + + /* We allocated the type of the object as an indirect type pointing + to *pslot, which we can now update to be a reference type. */ + if (debug_get_type_kind (info->dhandle, *pslot) != DEBUG_KIND_POINTER) + { + ieee_error (info, start, _("C++ reference is not pointer")); + return false; + } + + target = debug_get_target_type (info->dhandle, *pslot); + *pslot = debug_make_reference_type (info->dhandle, target); + if (*pslot == DEBUG_TYPE_NULL) + return false; + + return true; +} + +/* Require an ASN record. */ + +static boolean +ieee_require_asn (info, pp, pv) + struct ieee_info *info; + const bfd_byte **pp; + bfd_vma *pv; +{ + const bfd_byte *start; + ieee_record_enum_type c; + bfd_vma varindx; + + start = *pp; + + c = (ieee_record_enum_type) **pp; + if (c != ieee_e2_first_byte_enum) + { + ieee_error (info, start, _("missing required ASN")); + return false; + } + ++*pp; + + c = (ieee_record_enum_type) (((unsigned int) c << 8) | **pp); + if (c != ieee_asn_record_enum) + { + ieee_error (info, start, _("missing required ASN")); + return false; + } + ++*pp; + + /* Just ignore the variable index. */ + if (! ieee_read_number (info, pp, &varindx)) + return false; + + return ieee_read_expression (info, pp, pv); +} + +/* Require an ATN65 record. */ + +static boolean +ieee_require_atn65 (info, pp, pname, pnamlen) + struct ieee_info *info; + const bfd_byte **pp; + const char **pname; + unsigned long *pnamlen; +{ + const bfd_byte *start; + ieee_record_enum_type c; + bfd_vma name_indx, type_indx, atn_code; + + start = *pp; + + c = (ieee_record_enum_type) **pp; + if (c != ieee_at_record_enum) + { + ieee_error (info, start, _("missing required ATN65")); + return false; + } + ++*pp; + + c = (ieee_record_enum_type) (((unsigned int) c << 8) | **pp); + if (c != ieee_atn_record_enum) + { + ieee_error (info, start, _("missing required ATN65")); + return false; + } + ++*pp; + + if (! ieee_read_number (info, pp, &name_indx) + || ! ieee_read_number (info, pp, &type_indx) + || ! ieee_read_number (info, pp, &atn_code)) + return false; + + /* Just ignore name_indx. */ + + if (type_indx != 0 || atn_code != 65) + { + ieee_error (info, start, _("bad ATN65 record")); + return false; + } + + return ieee_read_id (info, pp, pname, pnamlen); +} + +/* Convert a register number in IEEE debugging information into a + generic register number. */ + +static int +ieee_regno_to_genreg (abfd, r) + bfd *abfd; + int r; +{ + switch (bfd_get_arch (abfd)) + { + case bfd_arch_m68k: + /* For some reasons stabs adds 2 to the floating point register + numbers. */ + if (r >= 16) + r += 2; + break; + + case bfd_arch_i960: + /* Stabs uses 0 to 15 for r0 to r15, 16 to 31 for g0 to g15, and + 32 to 35 for fp0 to fp3. */ + --r; + break; + + default: + break; + } + + return r; +} + +/* Convert a generic register number to an IEEE specific one. */ + +static int +ieee_genreg_to_regno (abfd, r) + bfd *abfd; + int r; +{ + switch (bfd_get_arch (abfd)) + { + case bfd_arch_m68k: + /* For some reason stabs add 2 to the floating point register + numbers. */ + if (r >= 18) + r -= 2; + break; + + case bfd_arch_i960: + /* Stabs uses 0 to 15 for r0 to r15, 16 to 31 for g0 to g15, and + 32 to 35 for fp0 to fp3. */ + ++r; + break; + + default: + break; + } + + return r; +} + +/* These routines build IEEE debugging information out of the generic + debugging information. */ + +/* We build the IEEE debugging information byte by byte. Rather than + waste time copying data around, we use a linked list of buffers to + hold the data. */ + +#define IEEE_BUFSIZE (490) + +struct ieee_buf +{ + /* Next buffer. */ + struct ieee_buf *next; + /* Number of data bytes in this buffer. */ + unsigned int c; + /* Bytes. */ + bfd_byte buf[IEEE_BUFSIZE]; +}; + +/* A list of buffers. */ + +struct ieee_buflist +{ + /* Head of list. */ + struct ieee_buf *head; + /* Tail--last buffer on list. */ + struct ieee_buf *tail; +}; + +/* In order to generate the BB11 blocks required by the HP emulator, + we keep track of ranges of addresses which correspond to a given + compilation unit. */ + +struct ieee_range +{ + /* Next range. */ + struct ieee_range *next; + /* Low address. */ + bfd_vma low; + /* High address. */ + bfd_vma high; +}; + +/* This structure holds information for a class on the type stack. */ + +struct ieee_type_class +{ + /* The name index in the debugging information. */ + unsigned int indx; + /* The pmisc records for the class. */ + struct ieee_buflist pmiscbuf; + /* The number of pmisc records. */ + unsigned int pmisccount; + /* The name of the class holding the virtual table, if not this + class. */ + const char *vclass; + /* Whether this class holds its own virtual table. */ + boolean ownvptr; + /* The largest virtual table offset seen so far. */ + bfd_vma voffset; + /* The current method. */ + const char *method; + /* Additional pmisc records used to record fields of reference type. */ + struct ieee_buflist refs; +}; + +/* This is how we store types for the writing routines. Most types + are simply represented by a type index. */ + +struct ieee_write_type +{ + /* Type index. */ + unsigned int indx; + /* The size of the type, if known. */ + unsigned int size; + /* The name of the type, if any. */ + const char *name; + /* If this is a function or method type, we build the type here, and + only add it to the output buffers if we need it. */ + struct ieee_buflist fndef; + /* If this is a struct, this is where the struct definition is + built. */ + struct ieee_buflist strdef; + /* If this is a class, this is where the class information is built. */ + struct ieee_type_class *classdef; + /* Whether the type is unsigned. */ + unsigned int unsignedp : 1; + /* Whether this is a reference type. */ + unsigned int referencep : 1; + /* Whether this is in the local type block. */ + unsigned int localp : 1; + /* Whether this is a duplicate struct definition which we are + ignoring. */ + unsigned int ignorep : 1; +}; + +/* This is the type stack used by the debug writing routines. FIXME: + We could generate more efficient output if we remembered when we + have output a particular type before. */ + +struct ieee_type_stack +{ + /* Next entry on stack. */ + struct ieee_type_stack *next; + /* Type information. */ + struct ieee_write_type type; +}; + +/* This is a list of associations between a name and some types. + These are used for typedefs and tags. */ + +struct ieee_name_type +{ + /* Next type for this name. */ + struct ieee_name_type *next; + /* ID number. For a typedef, this is the index of the type to which + this name is typedefed. */ + unsigned int id; + /* Type. */ + struct ieee_write_type type; + /* If this is a tag which has not yet been defined, this is the + kind. If the tag has been defined, this is DEBUG_KIND_ILLEGAL. */ + enum debug_type_kind kind; +}; + +/* We use a hash table to associate names and types. */ + +struct ieee_name_type_hash_table +{ + struct bfd_hash_table root; +}; + +struct ieee_name_type_hash_entry +{ + struct bfd_hash_entry root; + /* Information for this name. */ + struct ieee_name_type *types; +}; + +/* This is a list of enums. */ + +struct ieee_defined_enum +{ + /* Next enum. */ + struct ieee_defined_enum *next; + /* Type index. */ + unsigned int indx; + /* Whether this enum has been defined. */ + boolean defined; + /* Tag. */ + const char *tag; + /* Names. */ + const char **names; + /* Values. */ + bfd_signed_vma *vals; +}; + +/* We keep a list of modified versions of types, so that we don't + output them more than once. */ + +struct ieee_modified_type +{ + /* Pointer to this type. */ + unsigned int pointer; + /* Function with unknown arguments returning this type. */ + unsigned int function; + /* Const version of this type. */ + unsigned int const_qualified; + /* Volatile version of this type. */ + unsigned int volatile_qualified; + /* List of arrays of this type of various bounds. */ + struct ieee_modified_array_type *arrays; +}; + +/* A list of arrays bounds. */ + +struct ieee_modified_array_type +{ + /* Next array bounds. */ + struct ieee_modified_array_type *next; + /* Type index with these bounds. */ + unsigned int indx; + /* Low bound. */ + bfd_signed_vma low; + /* High bound. */ + bfd_signed_vma high; +}; + +/* This is a list of pending function parameter information. We don't + output them until we see the first block. */ + +struct ieee_pending_parm +{ + /* Next pending parameter. */ + struct ieee_pending_parm *next; + /* Name. */ + const char *name; + /* Type index. */ + unsigned int type; + /* Whether the type is a reference. */ + boolean referencep; + /* Kind. */ + enum debug_parm_kind kind; + /* Value. */ + bfd_vma val; +}; + +/* This is the handle passed down by debug_write. */ + +struct ieee_handle +{ + /* BFD we are writing to. */ + bfd *abfd; + /* Whether we got an error in a subroutine called via traverse or + map_over_sections. */ + boolean error; + /* Current data buffer list. */ + struct ieee_buflist *current; + /* Current data buffer. */ + struct ieee_buf *curbuf; + /* Filename of current compilation unit. */ + const char *filename; + /* Module name of current compilation unit. */ + const char *modname; + /* List of buffer for global types. */ + struct ieee_buflist global_types; + /* List of finished data buffers. */ + struct ieee_buflist data; + /* List of buffers for typedefs in the current compilation unit. */ + struct ieee_buflist types; + /* List of buffers for variables and functions in the current + compilation unit. */ + struct ieee_buflist vars; + /* List of buffers for C++ class definitions in the current + compilation unit. */ + struct ieee_buflist cxx; + /* List of buffers for line numbers in the current compilation unit. */ + struct ieee_buflist linenos; + /* Ranges for the current compilation unit. */ + struct ieee_range *ranges; + /* Ranges for all debugging information. */ + struct ieee_range *global_ranges; + /* Nested pending ranges. */ + struct ieee_range *pending_ranges; + /* Type stack. */ + struct ieee_type_stack *type_stack; + /* Next unallocated type index. */ + unsigned int type_indx; + /* Next unallocated name index. */ + unsigned int name_indx; + /* Typedefs. */ + struct ieee_name_type_hash_table typedefs; + /* Tags. */ + struct ieee_name_type_hash_table tags; + /* Enums. */ + struct ieee_defined_enum *enums; + /* Modified versions of types. */ + struct ieee_modified_type *modified; + /* Number of entries allocated in modified. */ + unsigned int modified_alloc; + /* 4 byte complex type. */ + unsigned int complex_float_index; + /* 8 byte complex type. */ + unsigned int complex_double_index; + /* The depth of block nesting. This is 0 outside a function, and 1 + just after start_function is called. */ + unsigned int block_depth; + /* The name of the current function. */ + const char *fnname; + /* List of buffers for the type of the function we are currently + writing out. */ + struct ieee_buflist fntype; + /* List of buffers for the parameters of the function we are + currently writing out. */ + struct ieee_buflist fnargs; + /* Number of arguments written to fnargs. */ + unsigned int fnargcount; + /* Pending function parameters. */ + struct ieee_pending_parm *pending_parms; + /* Current line number filename. */ + const char *lineno_filename; + /* Line number name index. */ + unsigned int lineno_name_indx; + /* Filename of pending line number. */ + const char *pending_lineno_filename; + /* Pending line number. */ + unsigned long pending_lineno; + /* Address of pending line number. */ + bfd_vma pending_lineno_addr; + /* Highest address seen at end of procedure. */ + bfd_vma highaddr; +}; + +static boolean ieee_init_buffer + PARAMS ((struct ieee_handle *, struct ieee_buflist *)); +static boolean ieee_change_buffer + PARAMS ((struct ieee_handle *, struct ieee_buflist *)); +static boolean ieee_append_buffer + PARAMS ((struct ieee_handle *, struct ieee_buflist *, + struct ieee_buflist *)); +static boolean ieee_real_write_byte PARAMS ((struct ieee_handle *, int)); +static boolean ieee_write_2bytes PARAMS ((struct ieee_handle *, int)); +static boolean ieee_write_number PARAMS ((struct ieee_handle *, bfd_vma)); +static boolean ieee_write_id PARAMS ((struct ieee_handle *, const char *)); +static boolean ieee_write_asn + PARAMS ((struct ieee_handle *, unsigned int, bfd_vma)); +static boolean ieee_write_atn65 + PARAMS ((struct ieee_handle *, unsigned int, const char *)); +static boolean ieee_push_type + PARAMS ((struct ieee_handle *, unsigned int, unsigned int, boolean, + boolean)); +static unsigned int ieee_pop_type PARAMS ((struct ieee_handle *)); +static void ieee_pop_unused_type PARAMS ((struct ieee_handle *)); +static unsigned int ieee_pop_type_used + PARAMS ((struct ieee_handle *, boolean)); +static boolean ieee_add_range + PARAMS ((struct ieee_handle *, boolean, bfd_vma, bfd_vma)); +static boolean ieee_start_range PARAMS ((struct ieee_handle *, bfd_vma)); +static boolean ieee_end_range PARAMS ((struct ieee_handle *, bfd_vma)); +static boolean ieee_define_type + PARAMS ((struct ieee_handle *, unsigned int, boolean, boolean)); +static boolean ieee_define_named_type + PARAMS ((struct ieee_handle *, const char *, unsigned int, unsigned int, + boolean, boolean, struct ieee_buflist *)); +static struct ieee_modified_type *ieee_get_modified_info + PARAMS ((struct ieee_handle *, unsigned int)); +static struct bfd_hash_entry *ieee_name_type_newfunc + PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); +static boolean ieee_write_undefined_tag + PARAMS ((struct ieee_name_type_hash_entry *, PTR)); +static boolean ieee_finish_compilation_unit PARAMS ((struct ieee_handle *)); +static void ieee_add_bb11_blocks PARAMS ((bfd *, asection *, PTR)); +static boolean ieee_add_bb11 + PARAMS ((struct ieee_handle *, asection *, bfd_vma, bfd_vma)); +static boolean ieee_output_pending_parms PARAMS ((struct ieee_handle *)); +static unsigned int ieee_vis_to_flags PARAMS ((enum debug_visibility)); +static boolean ieee_class_method_var + PARAMS ((struct ieee_handle *, const char *, enum debug_visibility, boolean, + boolean, boolean, bfd_vma, boolean)); + +static boolean ieee_start_compilation_unit PARAMS ((PTR, const char *)); +static boolean ieee_start_source PARAMS ((PTR, const char *)); +static boolean ieee_empty_type PARAMS ((PTR)); +static boolean ieee_void_type PARAMS ((PTR)); +static boolean ieee_int_type PARAMS ((PTR, unsigned int, boolean)); +static boolean ieee_float_type PARAMS ((PTR, unsigned int)); +static boolean ieee_complex_type PARAMS ((PTR, unsigned int)); +static boolean ieee_bool_type PARAMS ((PTR, unsigned int)); +static boolean ieee_enum_type + PARAMS ((PTR, const char *, const char **, bfd_signed_vma *)); +static boolean ieee_pointer_type PARAMS ((PTR)); +static boolean ieee_function_type PARAMS ((PTR, int, boolean)); +static boolean ieee_reference_type PARAMS ((PTR)); +static boolean ieee_range_type PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma)); +static boolean ieee_array_type + PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma, boolean)); +static boolean ieee_set_type PARAMS ((PTR, boolean)); +static boolean ieee_offset_type PARAMS ((PTR)); +static boolean ieee_method_type PARAMS ((PTR, boolean, int, boolean)); +static boolean ieee_const_type PARAMS ((PTR)); +static boolean ieee_volatile_type PARAMS ((PTR)); +static boolean ieee_start_struct_type + PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int)); +static boolean ieee_struct_field + PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility)); +static boolean ieee_end_struct_type PARAMS ((PTR)); +static boolean ieee_start_class_type + PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int, boolean, + boolean)); +static boolean ieee_class_static_member + PARAMS ((PTR, const char *, const char *, enum debug_visibility)); +static boolean ieee_class_baseclass + PARAMS ((PTR, bfd_vma, boolean, enum debug_visibility)); +static boolean ieee_class_start_method PARAMS ((PTR, const char *)); +static boolean ieee_class_method_variant + PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean, + bfd_vma, boolean)); +static boolean ieee_class_static_method_variant + PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean)); +static boolean ieee_class_end_method PARAMS ((PTR)); +static boolean ieee_end_class_type PARAMS ((PTR)); +static boolean ieee_typedef_type PARAMS ((PTR, const char *)); +static boolean ieee_tag_type + PARAMS ((PTR, const char *, unsigned int, enum debug_type_kind)); +static boolean ieee_typdef PARAMS ((PTR, const char *)); +static boolean ieee_tag PARAMS ((PTR, const char *)); +static boolean ieee_int_constant PARAMS ((PTR, const char *, bfd_vma)); +static boolean ieee_float_constant PARAMS ((PTR, const char *, double)); +static boolean ieee_typed_constant PARAMS ((PTR, const char *, bfd_vma)); +static boolean ieee_variable + PARAMS ((PTR, const char *, enum debug_var_kind, bfd_vma)); +static boolean ieee_start_function PARAMS ((PTR, const char *, boolean)); +static boolean ieee_function_parameter + PARAMS ((PTR, const char *, enum debug_parm_kind, bfd_vma)); +static boolean ieee_start_block PARAMS ((PTR, bfd_vma)); +static boolean ieee_end_block PARAMS ((PTR, bfd_vma)); +static boolean ieee_end_function PARAMS ((PTR)); +static boolean ieee_lineno + PARAMS ((PTR, const char *, unsigned long, bfd_vma)); + +static const struct debug_write_fns ieee_fns = +{ + ieee_start_compilation_unit, + ieee_start_source, + ieee_empty_type, + ieee_void_type, + ieee_int_type, + ieee_float_type, + ieee_complex_type, + ieee_bool_type, + ieee_enum_type, + ieee_pointer_type, + ieee_function_type, + ieee_reference_type, + ieee_range_type, + ieee_array_type, + ieee_set_type, + ieee_offset_type, + ieee_method_type, + ieee_const_type, + ieee_volatile_type, + ieee_start_struct_type, + ieee_struct_field, + ieee_end_struct_type, + ieee_start_class_type, + ieee_class_static_member, + ieee_class_baseclass, + ieee_class_start_method, + ieee_class_method_variant, + ieee_class_static_method_variant, + ieee_class_end_method, + ieee_end_class_type, + ieee_typedef_type, + ieee_tag_type, + ieee_typdef, + ieee_tag, + ieee_int_constant, + ieee_float_constant, + ieee_typed_constant, + ieee_variable, + ieee_start_function, + ieee_function_parameter, + ieee_start_block, + ieee_end_block, + ieee_end_function, + ieee_lineno +}; + +/* Initialize a buffer to be empty. */ + +/*ARGSUSED*/ +static boolean +ieee_init_buffer (info, buflist) + struct ieee_handle *info; + struct ieee_buflist *buflist; +{ + buflist->head = NULL; + buflist->tail = NULL; + return true; +} + +/* See whether a buffer list has any data. */ + +#define ieee_buffer_emptyp(buflist) ((buflist)->head == NULL) + +/* Change the current buffer to a specified buffer chain. */ + +static boolean +ieee_change_buffer (info, buflist) + struct ieee_handle *info; + struct ieee_buflist *buflist; +{ + if (buflist->head == NULL) + { + struct ieee_buf *buf; + + buf = (struct ieee_buf *) xmalloc (sizeof *buf); + buf->next = NULL; + buf->c = 0; + buflist->head = buf; + buflist->tail = buf; + } + + info->current = buflist; + info->curbuf = buflist->tail; + + return true; +} + +/* Append a buffer chain. */ + +/*ARGSUSED*/ +static boolean +ieee_append_buffer (info, mainbuf, newbuf) + struct ieee_handle *info; + struct ieee_buflist *mainbuf; + struct ieee_buflist *newbuf; +{ + if (newbuf->head != NULL) + { + if (mainbuf->head == NULL) + mainbuf->head = newbuf->head; + else + mainbuf->tail->next = newbuf->head; + mainbuf->tail = newbuf->tail; + } + return true; +} + +/* Write a byte into the buffer. We use a macro for speed and a + function for the complex cases. */ + +#define ieee_write_byte(info, b) \ + ((info)->curbuf->c < IEEE_BUFSIZE \ + ? ((info)->curbuf->buf[(info)->curbuf->c++] = (b), true) \ + : ieee_real_write_byte ((info), (b))) + +static boolean +ieee_real_write_byte (info, b) + struct ieee_handle *info; + int b; +{ + if (info->curbuf->c >= IEEE_BUFSIZE) + { + struct ieee_buf *n; + + n = (struct ieee_buf *) xmalloc (sizeof *n); + n->next = NULL; + n->c = 0; + if (info->current->head == NULL) + info->current->head = n; + else + info->current->tail->next = n; + info->current->tail = n; + info->curbuf = n; + } + + info->curbuf->buf[info->curbuf->c] = b; + ++info->curbuf->c; + + return true; +} + +/* Write out two bytes. */ + +static boolean +ieee_write_2bytes (info, i) + struct ieee_handle *info; + int i; +{ + return (ieee_write_byte (info, i >> 8) + && ieee_write_byte (info, i & 0xff)); +} + +/* Write out an integer. */ + +static boolean +ieee_write_number (info, v) + struct ieee_handle *info; + bfd_vma v; +{ + bfd_vma t; + bfd_byte ab[20]; + bfd_byte *p; + unsigned int c; + + if (v <= (bfd_vma) ieee_number_end_enum) + return ieee_write_byte (info, (int) v); + + t = v; + p = ab + sizeof ab; + while (t != 0) + { + *--p = t & 0xff; + t >>= 8; + } + c = (ab + 20) - p; + + if (c > (unsigned int) (ieee_number_repeat_end_enum + - ieee_number_repeat_start_enum)) + { + fprintf (stderr, _("IEEE numeric overflow: 0x")); + fprintf_vma (stderr, v); + fprintf (stderr, "\n"); + return false; + } + + if (! ieee_write_byte (info, (int) ieee_number_repeat_start_enum + c)) + return false; + for (; c > 0; --c, ++p) + { + if (! ieee_write_byte (info, *p)) + return false; + } + + return true; +} + +/* Write out a string. */ + +static boolean +ieee_write_id (info, s) + struct ieee_handle *info; + const char *s; +{ + unsigned int len; + + len = strlen (s); + if (len <= 0x7f) + { + if (! ieee_write_byte (info, len)) + return false; + } + else if (len <= 0xff) + { + if (! ieee_write_byte (info, (int) ieee_extension_length_1_enum) + || ! ieee_write_byte (info, len)) + return false; + } + else if (len <= 0xffff) + { + if (! ieee_write_byte (info, (int) ieee_extension_length_2_enum) + || ! ieee_write_2bytes (info, len)) + return false; + } + else + { + fprintf (stderr, _("IEEE string length overflow: %u\n"), len); + return false; + } + + for (; *s != '\0'; s++) + if (! ieee_write_byte (info, *s)) + return false; + + return true; +} + +/* Write out an ASN record. */ + +static boolean +ieee_write_asn (info, indx, val) + struct ieee_handle *info; + unsigned int indx; + bfd_vma val; +{ + return (ieee_write_2bytes (info, (int) ieee_asn_record_enum) + && ieee_write_number (info, indx) + && ieee_write_number (info, val)); +} + +/* Write out an ATN65 record. */ + +static boolean +ieee_write_atn65 (info, indx, s) + struct ieee_handle *info; + unsigned int indx; + const char *s; +{ + return (ieee_write_2bytes (info, (int) ieee_atn_record_enum) + && ieee_write_number (info, indx) + && ieee_write_number (info, 0) + && ieee_write_number (info, 65) + && ieee_write_id (info, s)); +} + +/* Push a type index onto the type stack. */ + +static boolean +ieee_push_type (info, indx, size, unsignedp, localp) + struct ieee_handle *info; + unsigned int indx; + unsigned int size; + boolean unsignedp; + boolean localp; +{ + struct ieee_type_stack *ts; + + ts = (struct ieee_type_stack *) xmalloc (sizeof *ts); + memset (ts, 0, sizeof *ts); + + ts->type.indx = indx; + ts->type.size = size; + ts->type.unsignedp = unsignedp; + ts->type.localp = localp; + + ts->next = info->type_stack; + info->type_stack = ts; + + return true; +} + +/* Pop a type index off the type stack. */ + +static unsigned int +ieee_pop_type (info) + struct ieee_handle *info; +{ + return ieee_pop_type_used (info, true); +} + +/* Pop an unused type index off the type stack. */ + +static void +ieee_pop_unused_type (info) + struct ieee_handle *info; +{ + (void) ieee_pop_type_used (info, false); +} + +/* Pop a used or unused type index off the type stack. */ + +static unsigned int +ieee_pop_type_used (info, used) + struct ieee_handle *info; + boolean used; +{ + struct ieee_type_stack *ts; + unsigned int ret; + + ts = info->type_stack; + assert (ts != NULL); + + /* If this is a function type, and we need it, we need to append the + actual definition to the typedef block now. */ + if (used && ! ieee_buffer_emptyp (&ts->type.fndef)) + { + struct ieee_buflist *buflist; + + if (ts->type.localp) + { + /* Make sure we have started the types block. */ + if (ieee_buffer_emptyp (&info->types)) + { + if (! ieee_change_buffer (info, &info->types) + || ! ieee_write_byte (info, (int) ieee_bb_record_enum) + || ! ieee_write_byte (info, 1) + || ! ieee_write_number (info, 0) + || ! ieee_write_id (info, info->modname)) + return false; + } + buflist = &info->types; + } + else + { + /* Make sure we started the global type block. */ + if (ieee_buffer_emptyp (&info->global_types)) + { + if (! ieee_change_buffer (info, &info->global_types) + || ! ieee_write_byte (info, (int) ieee_bb_record_enum) + || ! ieee_write_byte (info, 2) + || ! ieee_write_number (info, 0) + || ! ieee_write_id (info, "")) + return false; + } + buflist = &info->global_types; + } + + if (! ieee_append_buffer (info, buflist, &ts->type.fndef)) + return false; + } + + ret = ts->type.indx; + info->type_stack = ts->next; + free (ts); + return ret; +} + +/* Add a range of bytes included in the current compilation unit. */ + +static boolean +ieee_add_range (info, global, low, high) + struct ieee_handle *info; + boolean global; + bfd_vma low; + bfd_vma high; +{ + struct ieee_range **plist, *r, **pr; + + if (low == (bfd_vma) -1 || high == (bfd_vma) -1 || low == high) + return true; + + if (global) + plist = &info->global_ranges; + else + plist = &info->ranges; + + for (r = *plist; r != NULL; r = r->next) + { + if (high >= r->low && low <= r->high) + { + /* The new range overlaps r. */ + if (low < r->low) + r->low = low; + if (high > r->high) + r->high = high; + pr = &r->next; + while (*pr != NULL && (*pr)->low <= r->high) + { + struct ieee_range *n; + + if ((*pr)->high > r->high) + r->high = (*pr)->high; + n = (*pr)->next; + free (*pr); + *pr = n; + } + return true; + } + } + + r = (struct ieee_range *) xmalloc (sizeof *r); + memset (r, 0, sizeof *r); + + r->low = low; + r->high = high; + + /* Store the ranges sorted by address. */ + for (pr = plist; *pr != NULL; pr = &(*pr)->next) + if ((*pr)->low > high) + break; + r->next = *pr; + *pr = r; + + return true; +} + +/* Start a new range for which we only have the low address. */ + +static boolean +ieee_start_range (info, low) + struct ieee_handle *info; + bfd_vma low; +{ + struct ieee_range *r; + + r = (struct ieee_range *) xmalloc (sizeof *r); + memset (r, 0, sizeof *r); + r->low = low; + r->next = info->pending_ranges; + info->pending_ranges = r; + return true; +} + +/* Finish a range started by ieee_start_range. */ + +static boolean +ieee_end_range (info, high) + struct ieee_handle *info; + bfd_vma high; +{ + struct ieee_range *r; + bfd_vma low; + + assert (info->pending_ranges != NULL); + r = info->pending_ranges; + low = r->low; + info->pending_ranges = r->next; + free (r); + return ieee_add_range (info, false, low, high); +} + +/* Start defining a type. */ + +static boolean +ieee_define_type (info, size, unsignedp, localp) + struct ieee_handle *info; + unsigned int size; + boolean unsignedp; + boolean localp; +{ + return ieee_define_named_type (info, (const char *) NULL, + (unsigned int) -1, size, unsignedp, + localp, (struct ieee_buflist *) NULL); +} + +/* Start defining a named type. */ + +static boolean +ieee_define_named_type (info, name, indx, size, unsignedp, localp, buflist) + struct ieee_handle *info; + const char *name; + unsigned int indx; + unsigned int size; + boolean unsignedp; + boolean localp; + struct ieee_buflist *buflist; +{ + unsigned int type_indx; + unsigned int name_indx; + + if (indx != (unsigned int) -1) + type_indx = indx; + else + { + type_indx = info->type_indx; + ++info->type_indx; + } + + name_indx = info->name_indx; + ++info->name_indx; + + if (name == NULL) + name = ""; + + /* If we were given a buffer, use it; otherwise, use either the + local or the global type information, and make sure that the type + block is started. */ + if (buflist != NULL) + { + if (! ieee_change_buffer (info, buflist)) + return false; + } + else if (localp) + { + if (! ieee_buffer_emptyp (&info->types)) + { + if (! ieee_change_buffer (info, &info->types)) + return false; + } + else + { + if (! ieee_change_buffer (info, &info->types) + || ! ieee_write_byte (info, (int) ieee_bb_record_enum) + || ! ieee_write_byte (info, 1) + || ! ieee_write_number (info, 0) + || ! ieee_write_id (info, info->modname)) + return false; + } + } + else + { + if (! ieee_buffer_emptyp (&info->global_types)) + { + if (! ieee_change_buffer (info, &info->global_types)) + return false; + } + else + { + if (! ieee_change_buffer (info, &info->global_types) + || ! ieee_write_byte (info, (int) ieee_bb_record_enum) + || ! ieee_write_byte (info, 2) + || ! ieee_write_number (info, 0) + || ! ieee_write_id (info, "")) + return false; + } + } + + /* Push the new type on the type stack, write out an NN record, and + write out the start of a TY record. The caller will then finish + the TY record. */ + if (! ieee_push_type (info, type_indx, size, unsignedp, localp)) + return false; + + return (ieee_write_byte (info, (int) ieee_nn_record) + && ieee_write_number (info, name_indx) + && ieee_write_id (info, name) + && ieee_write_byte (info, (int) ieee_ty_record_enum) + && ieee_write_number (info, type_indx) + && ieee_write_byte (info, 0xce) + && ieee_write_number (info, name_indx)); +} + +/* Get an entry to the list of modified versions of a type. */ + +static struct ieee_modified_type * +ieee_get_modified_info (info, indx) + struct ieee_handle *info; + unsigned int indx; +{ + if (indx >= info->modified_alloc) + { + unsigned int nalloc; + + nalloc = info->modified_alloc; + if (nalloc == 0) + nalloc = 16; + while (indx >= nalloc) + nalloc *= 2; + info->modified = ((struct ieee_modified_type *) + xrealloc (info->modified, + nalloc * sizeof *info->modified)); + memset (info->modified + info->modified_alloc, 0, + (nalloc - info->modified_alloc) * sizeof *info->modified); + info->modified_alloc = nalloc; + } + + return info->modified + indx; +} + +/* Routines for the hash table mapping names to types. */ + +/* Initialize an entry in the hash table. */ + +static struct bfd_hash_entry * +ieee_name_type_newfunc (entry, table, string) + struct bfd_hash_entry *entry; + struct bfd_hash_table *table; + const char *string; +{ + struct ieee_name_type_hash_entry *ret = + (struct ieee_name_type_hash_entry *) entry; + + /* Allocate the structure if it has not already been allocated by a + subclass. */ + if (ret == NULL) + ret = ((struct ieee_name_type_hash_entry *) + bfd_hash_allocate (table, sizeof *ret)); + if (ret == NULL) + return NULL; + + /* Call the allocation method of the superclass. */ + ret = ((struct ieee_name_type_hash_entry *) + bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); + if (ret) + { + /* Set local fields. */ + ret->types = NULL; + } + + return (struct bfd_hash_entry *) ret; +} + +/* Look up an entry in the hash table. */ + +#define ieee_name_type_hash_lookup(table, string, create, copy) \ + ((struct ieee_name_type_hash_entry *) \ + bfd_hash_lookup (&(table)->root, (string), (create), (copy))) + +/* Traverse the hash table. */ + +#define ieee_name_type_hash_traverse(table, func, info) \ + (bfd_hash_traverse \ + (&(table)->root, \ + (boolean (*) PARAMS ((struct bfd_hash_entry *, PTR))) (func), \ + (info))) + +/* The general routine to write out IEEE debugging information. */ + +boolean +write_ieee_debugging_info (abfd, dhandle) + bfd *abfd; + PTR dhandle; +{ + struct ieee_handle info; + asection *s; + const char *err; + struct ieee_buf *b; + + memset (&info, 0, sizeof info); + info.abfd = abfd; + info.type_indx = 256; + info.name_indx = 32; + + if (! bfd_hash_table_init (&info.typedefs.root, ieee_name_type_newfunc) + || ! bfd_hash_table_init (&info.tags.root, ieee_name_type_newfunc)) + return false; + + if (! ieee_init_buffer (&info, &info.global_types) + || ! ieee_init_buffer (&info, &info.data) + || ! ieee_init_buffer (&info, &info.types) + || ! ieee_init_buffer (&info, &info.vars) + || ! ieee_init_buffer (&info, &info.cxx) + || ! ieee_init_buffer (&info, &info.linenos) + || ! ieee_init_buffer (&info, &info.fntype) + || ! ieee_init_buffer (&info, &info.fnargs)) + return false; + + if (! debug_write (dhandle, &ieee_fns, (PTR) &info)) + return false; + + if (info.filename != NULL) + { + if (! ieee_finish_compilation_unit (&info)) + return false; + } + + /* Put any undefined tags in the global typedef information. */ + info.error = false; + ieee_name_type_hash_traverse (&info.tags, + ieee_write_undefined_tag, + (PTR) &info); + if (info.error) + return false; + + /* Prepend the global typedef information to the other data. */ + if (! ieee_buffer_emptyp (&info.global_types)) + { + /* The HP debugger seems to have a bug in which it ignores the + last entry in the global types, so we add a dummy entry. */ + if (! ieee_change_buffer (&info, &info.global_types) + || ! ieee_write_byte (&info, (int) ieee_nn_record) + || ! ieee_write_number (&info, info.name_indx) + || ! ieee_write_id (&info, "") + || ! ieee_write_byte (&info, (int) ieee_ty_record_enum) + || ! ieee_write_number (&info, info.type_indx) + || ! ieee_write_byte (&info, 0xce) + || ! ieee_write_number (&info, info.name_indx) + || ! ieee_write_number (&info, 'P') + || ! ieee_write_number (&info, (int) builtin_void + 32) + || ! ieee_write_byte (&info, (int) ieee_be_record_enum)) + return false; + + if (! ieee_append_buffer (&info, &info.global_types, &info.data)) + return false; + info.data = info.global_types; + } + + /* Make sure that we have declare BB11 blocks for each range in the + file. They are added to info->vars. */ + info.error = false; + if (! ieee_init_buffer (&info, &info.vars)) + return false; + bfd_map_over_sections (abfd, ieee_add_bb11_blocks, (PTR) &info); + if (info.error) + return false; + if (! ieee_buffer_emptyp (&info.vars)) + { + if (! ieee_change_buffer (&info, &info.vars) + || ! ieee_write_byte (&info, (int) ieee_be_record_enum)) + return false; + + if (! ieee_append_buffer (&info, &info.data, &info.vars)) + return false; + } + + /* Now all the data is in info.data. Write it out to the BFD. We + normally would need to worry about whether all the other sections + are set up yet, but the IEEE backend will handle this particular + case correctly regardless. */ + if (ieee_buffer_emptyp (&info.data)) + { + /* There is no debugging information. */ + return true; + } + err = NULL; + s = bfd_make_section (abfd, ".debug"); + if (s == NULL) + err = "bfd_make_section"; + if (err == NULL) + { + if (! bfd_set_section_flags (abfd, s, SEC_DEBUGGING | SEC_HAS_CONTENTS)) + err = "bfd_set_section_flags"; + } + if (err == NULL) + { + bfd_size_type size; + + size = 0; + for (b = info.data.head; b != NULL; b = b->next) + size += b->c; + if (! bfd_set_section_size (abfd, s, size)) + err = "bfd_set_section_size"; + } + if (err == NULL) + { + file_ptr offset; + + offset = 0; + for (b = info.data.head; b != NULL; b = b->next) + { + if (! bfd_set_section_contents (abfd, s, b->buf, offset, b->c)) + { + err = "bfd_set_section_contents"; + break; + } + offset += b->c; + } + } + + if (err != NULL) + { + fprintf (stderr, "%s: %s: %s\n", bfd_get_filename (abfd), err, + bfd_errmsg (bfd_get_error ())); + return false; + } + + bfd_hash_table_free (&info.typedefs.root); + bfd_hash_table_free (&info.tags.root); + + return true; +} + +/* Write out information for an undefined tag. This is called via + ieee_name_type_hash_traverse. */ + +static boolean +ieee_write_undefined_tag (h, p) + struct ieee_name_type_hash_entry *h; + PTR p; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + struct ieee_name_type *nt; + + for (nt = h->types; nt != NULL; nt = nt->next) + { + unsigned int name_indx; + char code; + + if (nt->kind == DEBUG_KIND_ILLEGAL) + continue; + + if (ieee_buffer_emptyp (&info->global_types)) + { + if (! ieee_change_buffer (info, &info->global_types) + || ! ieee_write_byte (info, (int) ieee_bb_record_enum) + || ! ieee_write_byte (info, 2) + || ! ieee_write_number (info, 0) + || ! ieee_write_id (info, "")) + { + info->error = true; + return false; + } + } + else + { + if (! ieee_change_buffer (info, &info->global_types)) + { + info->error = true; + return false; + } + } + + name_indx = info->name_indx; + ++info->name_indx; + if (! ieee_write_byte (info, (int) ieee_nn_record) + || ! ieee_write_number (info, name_indx) + || ! ieee_write_id (info, nt->type.name) + || ! ieee_write_byte (info, (int) ieee_ty_record_enum) + || ! ieee_write_number (info, nt->type.indx) + || ! ieee_write_byte (info, 0xce) + || ! ieee_write_number (info, name_indx)) + { + info->error = true; + return false; + } + + switch (nt->kind) + { + default: + abort (); + info->error = true; + return false; + case DEBUG_KIND_STRUCT: + case DEBUG_KIND_CLASS: + code = 'S'; + break; + case DEBUG_KIND_UNION: + case DEBUG_KIND_UNION_CLASS: + code = 'U'; + break; + case DEBUG_KIND_ENUM: + code = 'E'; + break; + } + if (! ieee_write_number (info, code) + || ! ieee_write_number (info, 0)) + { + info->error = true; + return false; + } + } + + return true; +} + +/* Start writing out information for a compilation unit. */ + +static boolean +ieee_start_compilation_unit (p, filename) + PTR p; + const char *filename; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + const char *modname; + char *c, *s; + unsigned int nindx; + + if (info->filename != NULL) + { + if (! ieee_finish_compilation_unit (info)) + return false; + } + + info->filename = filename; + modname = strrchr (filename, '/'); + if (modname != NULL) + ++modname; + else + { + modname = strrchr (filename, '\\'); + if (modname != NULL) + ++modname; + else + modname = filename; + } + c = xstrdup (modname); + s = strrchr (c, '.'); + if (s != NULL) + *s = '\0'; + info->modname = c; + + if (! ieee_init_buffer (info, &info->types) + || ! ieee_init_buffer (info, &info->vars) + || ! ieee_init_buffer (info, &info->cxx) + || ! ieee_init_buffer (info, &info->linenos)) + return false; + info->ranges = NULL; + + /* Always include a BB1 and a BB3 block. That is what the output of + the MRI linker seems to look like. */ + if (! ieee_change_buffer (info, &info->types) + || ! ieee_write_byte (info, (int) ieee_bb_record_enum) + || ! ieee_write_byte (info, 1) + || ! ieee_write_number (info, 0) + || ! ieee_write_id (info, info->modname)) + return false; + + nindx = info->name_indx; + ++info->name_indx; + if (! ieee_change_buffer (info, &info->vars) + || ! ieee_write_byte (info, (int) ieee_bb_record_enum) + || ! ieee_write_byte (info, 3) + || ! ieee_write_number (info, 0) + || ! ieee_write_id (info, info->modname)) + return false; + + return true; +} + +/* Finish up a compilation unit. */ + +static boolean +ieee_finish_compilation_unit (info) + struct ieee_handle *info; +{ + struct ieee_range *r; + + if (! ieee_buffer_emptyp (&info->types)) + { + if (! ieee_change_buffer (info, &info->types) + || ! ieee_write_byte (info, (int) ieee_be_record_enum)) + return false; + } + + if (! ieee_buffer_emptyp (&info->cxx)) + { + /* Append any C++ information to the global function and + variable information. */ + assert (! ieee_buffer_emptyp (&info->vars)); + if (! ieee_change_buffer (info, &info->vars)) + return false; + + /* We put the pmisc records in a dummy procedure, just as the + MRI compiler does. */ + if (! ieee_write_byte (info, (int) ieee_bb_record_enum) + || ! ieee_write_byte (info, 6) + || ! ieee_write_number (info, 0) + || ! ieee_write_id (info, "__XRYCPP") + || ! ieee_write_number (info, 0) + || ! ieee_write_number (info, 0) + || ! ieee_write_number (info, info->highaddr - 1) + || ! ieee_append_buffer (info, &info->vars, &info->cxx) + || ! ieee_change_buffer (info, &info->vars) + || ! ieee_write_byte (info, (int) ieee_be_record_enum) + || ! ieee_write_number (info, info->highaddr - 1)) + return false; + } + + if (! ieee_buffer_emptyp (&info->vars)) + { + if (! ieee_change_buffer (info, &info->vars) + || ! ieee_write_byte (info, (int) ieee_be_record_enum)) + return false; + } + + if (info->pending_lineno_filename != NULL) + { + /* Force out the pending line number. */ + if (! ieee_lineno ((PTR) info, (const char *) NULL, 0, (bfd_vma) -1)) + return false; + } + if (! ieee_buffer_emptyp (&info->linenos)) + { + if (! ieee_change_buffer (info, &info->linenos) + || ! ieee_write_byte (info, (int) ieee_be_record_enum)) + return false; + if (strcmp (info->filename, info->lineno_filename) != 0) + { + /* We were not in the main file. We just closed the + included line number block, and now we must close the + main line number block. */ + if (! ieee_write_byte (info, (int) ieee_be_record_enum)) + return false; + } + } + + if (! ieee_append_buffer (info, &info->data, &info->types) + || ! ieee_append_buffer (info, &info->data, &info->vars) + || ! ieee_append_buffer (info, &info->data, &info->linenos)) + return false; + + /* Build BB10/BB11 blocks based on the ranges we recorded. */ + if (! ieee_change_buffer (info, &info->data)) + return false; + + if (! ieee_write_byte (info, (int) ieee_bb_record_enum) + || ! ieee_write_byte (info, 10) + || ! ieee_write_number (info, 0) + || ! ieee_write_id (info, info->modname) + || ! ieee_write_id (info, "") + || ! ieee_write_number (info, 0) + || ! ieee_write_id (info, "GNU objcopy")) + return false; + + for (r = info->ranges; r != NULL; r = r->next) + { + bfd_vma low, high; + asection *s; + int kind; + + low = r->low; + high = r->high; + + /* Find the section corresponding to this range. */ + for (s = info->abfd->sections; s != NULL; s = s->next) + { + if (bfd_get_section_vma (info->abfd, s) <= low + && high <= (bfd_get_section_vma (info->abfd, s) + + bfd_section_size (info->abfd, s))) + break; + } + + if (s == NULL) + { + /* Just ignore this range. */ + continue; + } + + /* Coalesce ranges if it seems reasonable. */ + while (r->next != NULL + && high + 0x1000 >= r->next->low + && (r->next->high + <= (bfd_get_section_vma (info->abfd, s) + + bfd_section_size (info->abfd, s)))) + { + r = r->next; + high = r->high; + } + + if ((s->flags & SEC_CODE) != 0) + kind = 1; + else if ((s->flags & SEC_READONLY) != 0) + kind = 3; + else + kind = 2; + + if (! ieee_write_byte (info, (int) ieee_bb_record_enum) + || ! ieee_write_byte (info, 11) + || ! ieee_write_number (info, 0) + || ! ieee_write_id (info, "") + || ! ieee_write_number (info, kind) + || ! ieee_write_number (info, s->index + IEEE_SECTION_NUMBER_BASE) + || ! ieee_write_number (info, low) + || ! ieee_write_byte (info, (int) ieee_be_record_enum) + || ! ieee_write_number (info, high - low)) + return false; + + /* Add this range to the list of global ranges. */ + if (! ieee_add_range (info, true, low, high)) + return false; + } + + if (! ieee_write_byte (info, (int) ieee_be_record_enum)) + return false; + + return true; +} + +/* Add BB11 blocks describing each range that we have not already + described. */ + +static void +ieee_add_bb11_blocks (abfd, sec, data) + bfd *abfd; + asection *sec; + PTR data; +{ + struct ieee_handle *info = (struct ieee_handle *) data; + bfd_vma low, high; + struct ieee_range *r; + + low = bfd_get_section_vma (abfd, sec); + high = low + bfd_section_size (abfd, sec); + + /* Find the first range at or after this section. The ranges are + sorted by address. */ + for (r = info->global_ranges; r != NULL; r = r->next) + if (r->high > low) + break; + + while (low < high) + { + if (r == NULL || r->low >= high) + { + if (! ieee_add_bb11 (info, sec, low, high)) + info->error = true; + return; + } + + if (low < r->low + && r->low - low > 0x100) + { + if (! ieee_add_bb11 (info, sec, low, r->low)) + { + info->error = true; + return; + } + } + low = r->high; + + r = r->next; + } +} + +/* Add a single BB11 block for a range. We add it to info->vars. */ + +static boolean +ieee_add_bb11 (info, sec, low, high) + struct ieee_handle *info; + asection *sec; + bfd_vma low; + bfd_vma high; +{ + int kind; + + if (! ieee_buffer_emptyp (&info->vars)) + { + if (! ieee_change_buffer (info, &info->vars)) + return false; + } + else + { + const char *filename, *modname; + char *c, *s; + + /* Start the enclosing BB10 block. */ + filename = bfd_get_filename (info->abfd); + modname = strrchr (filename, '/'); + if (modname != NULL) + ++modname; + else + { + modname = strrchr (filename, '\\'); + if (modname != NULL) + ++modname; + else + modname = filename; + } + c = xstrdup (modname); + s = strrchr (c, '.'); + if (s != NULL) + *s = '\0'; + + if (! ieee_change_buffer (info, &info->vars) + || ! ieee_write_byte (info, (int) ieee_bb_record_enum) + || ! ieee_write_byte (info, 10) + || ! ieee_write_number (info, 0) + || ! ieee_write_id (info, c) + || ! ieee_write_id (info, "") + || ! ieee_write_number (info, 0) + || ! ieee_write_id (info, "GNU objcopy")) + return false; + + free (c); + } + + if ((sec->flags & SEC_CODE) != 0) + kind = 1; + else if ((sec->flags & SEC_READONLY) != 0) + kind = 3; + else + kind = 2; + + if (! ieee_write_byte (info, (int) ieee_bb_record_enum) + || ! ieee_write_byte (info, 11) + || ! ieee_write_number (info, 0) + || ! ieee_write_id (info, "") + || ! ieee_write_number (info, kind) + || ! ieee_write_number (info, sec->index + IEEE_SECTION_NUMBER_BASE) + || ! ieee_write_number (info, low) + || ! ieee_write_byte (info, (int) ieee_be_record_enum) + || ! ieee_write_number (info, high - low)) + return false; + + return true; +} + +/* Start recording information from a particular source file. This is + used to record which file defined which types, variables, etc. It + is not used for line numbers, since the lineno entry point passes + down the file name anyhow. IEEE debugging information doesn't seem + to store this information anywhere. */ + +/*ARGSUSED*/ +static boolean +ieee_start_source (p, filename) + PTR p; + const char *filename; +{ + return true; +} + +/* Make an empty type. */ + +static boolean +ieee_empty_type (p) + PTR p; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + + return ieee_push_type (info, (int) builtin_unknown, 0, false, false); +} + +/* Make a void type. */ + +static boolean +ieee_void_type (p) + PTR p; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + + return ieee_push_type (info, (int) builtin_void, 0, false, false); +} + +/* Make an integer type. */ + +static boolean +ieee_int_type (p, size, unsignedp) + PTR p; + unsigned int size; + boolean unsignedp; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + unsigned int indx; + + switch (size) + { + case 1: + indx = (int) builtin_signed_char; + break; + case 2: + indx = (int) builtin_signed_short_int; + break; + case 4: + indx = (int) builtin_signed_long; + break; + case 8: + indx = (int) builtin_signed_long_long; + break; + default: + fprintf (stderr, _("IEEE unsupported integer type size %u\n"), size); + return false; + } + + if (unsignedp) + ++indx; + + return ieee_push_type (info, indx, size, unsignedp, false); +} + +/* Make a floating point type. */ + +static boolean +ieee_float_type (p, size) + PTR p; + unsigned int size; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + unsigned int indx; + + switch (size) + { + case 4: + indx = (int) builtin_float; + break; + case 8: + indx = (int) builtin_double; + break; + case 12: + /* FIXME: This size really depends upon the processor. */ + indx = (int) builtin_long_double; + break; + case 16: + indx = (int) builtin_long_long_double; + break; + default: + fprintf (stderr, _("IEEE unsupported float type size %u\n"), size); + return false; + } + + return ieee_push_type (info, indx, size, false, false); +} + +/* Make a complex type. */ + +static boolean +ieee_complex_type (p, size) + PTR p; + unsigned int size; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + char code; + + switch (size) + { + case 4: + if (info->complex_float_index != 0) + return ieee_push_type (info, info->complex_float_index, size * 2, + false, false); + code = 'c'; + break; + case 12: + case 16: + /* These cases can be output by gcc -gstabs. Outputting the + wrong type is better than crashing. */ + case 8: + if (info->complex_double_index != 0) + return ieee_push_type (info, info->complex_double_index, size * 2, + false, false); + code = 'd'; + break; + default: + fprintf (stderr, _("IEEE unsupported complex type size %u\n"), size); + return false; + } + + /* FIXME: I don't know what the string is for. */ + if (! ieee_define_type (info, size * 2, false, false) + || ! ieee_write_number (info, code) + || ! ieee_write_id (info, "")) + return false; + + if (size == 4) + info->complex_float_index = info->type_stack->type.indx; + else + info->complex_double_index = info->type_stack->type.indx; + + return true; +} + +/* Make a boolean type. IEEE doesn't support these, so we just make + an integer type instead. */ + +static boolean +ieee_bool_type (p, size) + PTR p; + unsigned int size; +{ + return ieee_int_type (p, size, true); +} + +/* Make an enumeration. */ + +static boolean +ieee_enum_type (p, tag, names, vals) + PTR p; + const char *tag; + const char **names; + bfd_signed_vma *vals; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + struct ieee_defined_enum *e; + boolean localp, simple; + unsigned int indx; + int i = 0; + + localp = false; + indx = (unsigned int) -1; + for (e = info->enums; e != NULL; e = e->next) + { + if (tag == NULL) + { + if (e->tag != NULL) + continue; + } + else + { + if (e->tag == NULL + || tag[0] != e->tag[0] + || strcmp (tag, e->tag) != 0) + continue; + } + + if (! e->defined) + { + /* This enum tag has been seen but not defined. */ + indx = e->indx; + break; + } + + if (names != NULL && e->names != NULL) + { + for (i = 0; names[i] != NULL && e->names[i] != NULL; i++) + { + if (names[i][0] != e->names[i][0] + || vals[i] != e->vals[i] + || strcmp (names[i], e->names[i]) != 0) + break; + } + } + + if ((names == NULL && e->names == NULL) + || (names != NULL + && e->names != NULL + && names[i] == NULL + && e->names[i] == NULL)) + { + /* We've seen this enum before. */ + return ieee_push_type (info, e->indx, 0, true, false); + } + + if (tag != NULL) + { + /* We've already seen an enum of the same name, so we must make + sure to output this one locally. */ + localp = true; + break; + } + } + + /* If this is a simple enumeration, in which the values start at 0 + and always increment by 1, we can use type E. Otherwise we must + use type N. */ + + simple = true; + if (names != NULL) + { + for (i = 0; names[i] != NULL; i++) + { + if (vals[i] != i) + { + simple = false; + break; + } + } + } + + if (! ieee_define_named_type (info, tag, indx, 0, true, localp, + (struct ieee_buflist *) NULL) + || ! ieee_write_number (info, simple ? 'E' : 'N')) + return false; + if (simple) + { + /* FIXME: This is supposed to be the enumeration size, but we + don't store that. */ + if (! ieee_write_number (info, 4)) + return false; + } + if (names != NULL) + { + for (i = 0; names[i] != NULL; i++) + { + if (! ieee_write_id (info, names[i])) + return false; + if (! simple) + { + if (! ieee_write_number (info, vals[i])) + return false; + } + } + } + + if (! localp) + { + if (indx == (unsigned int) -1) + { + e = (struct ieee_defined_enum *) xmalloc (sizeof *e); + memset (e, 0, sizeof *e); + e->indx = info->type_stack->type.indx; + e->tag = tag; + + e->next = info->enums; + info->enums = e; + } + + e->names = names; + e->vals = vals; + e->defined = true; + } + + return true; +} + +/* Make a pointer type. */ + +static boolean +ieee_pointer_type (p) + PTR p; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + boolean localp; + unsigned int indx; + struct ieee_modified_type *m = NULL; + + localp = info->type_stack->type.localp; + indx = ieee_pop_type (info); + + /* A pointer to a simple builtin type can be obtained by adding 32. + FIXME: Will this be a short pointer, and will that matter? */ + if (indx < 32) + return ieee_push_type (info, indx + 32, 0, true, false); + + if (! localp) + { + m = ieee_get_modified_info (p, indx); + if (m == NULL) + return false; + + /* FIXME: The size should depend upon the architecture. */ + if (m->pointer > 0) + return ieee_push_type (info, m->pointer, 4, true, false); + } + + if (! ieee_define_type (info, 4, true, localp) + || ! ieee_write_number (info, 'P') + || ! ieee_write_number (info, indx)) + return false; + + if (! localp) + m->pointer = info->type_stack->type.indx; + + return true; +} + +/* Make a function type. This will be called for a method, but we + don't want to actually add it to the type table in that case. We + handle this by defining the type in a private buffer, and only + adding that buffer to the typedef block if we are going to use it. */ + +static boolean +ieee_function_type (p, argcount, varargs) + PTR p; + int argcount; + boolean varargs; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + boolean localp; + unsigned int *args = NULL; + int i; + unsigned int retindx; + struct ieee_buflist fndef; + struct ieee_modified_type *m; + + localp = false; + + if (argcount > 0) + { + args = (unsigned int *) xmalloc (argcount * sizeof *args); + for (i = argcount - 1; i >= 0; i--) + { + if (info->type_stack->type.localp) + localp = true; + args[i] = ieee_pop_type (info); + } + } + else if (argcount < 0) + varargs = false; + + if (info->type_stack->type.localp) + localp = true; + retindx = ieee_pop_type (info); + + m = NULL; + if (argcount < 0 && ! localp) + { + m = ieee_get_modified_info (p, retindx); + if (m == NULL) + return false; + + if (m->function > 0) + return ieee_push_type (info, m->function, 0, true, false); + } + + /* An attribute of 0x41 means that the frame and push mask are + unknown. */ + if (! ieee_init_buffer (info, &fndef) + || ! ieee_define_named_type (info, (const char *) NULL, + (unsigned int) -1, 0, true, localp, + &fndef) + || ! ieee_write_number (info, 'x') + || ! ieee_write_number (info, 0x41) + || ! ieee_write_number (info, 0) + || ! ieee_write_number (info, 0) + || ! ieee_write_number (info, retindx) + || ! ieee_write_number (info, (bfd_vma) argcount + (varargs ? 1 : 0))) + return false; + if (argcount > 0) + { + for (i = 0; i < argcount; i++) + if (! ieee_write_number (info, args[i])) + return false; + free (args); + } + if (varargs) + { + /* A varargs function is represented by writing out the last + argument as type void *, although this makes little sense. */ + if (! ieee_write_number (info, (bfd_vma) builtin_void + 32)) + return false; + } + + if (! ieee_write_number (info, 0)) + return false; + + /* We wrote the information into fndef, in case we don't need it. + It will be appended to info->types by ieee_pop_type. */ + info->type_stack->type.fndef = fndef; + + if (m != NULL) + m->function = info->type_stack->type.indx; + + return true; +} + +/* Make a reference type. */ + +static boolean +ieee_reference_type (p) + PTR p; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + + /* IEEE appears to record a normal pointer type, and then use a + pmisc record to indicate that it is really a reference. */ + + if (! ieee_pointer_type (p)) + return false; + info->type_stack->type.referencep = true; + return true; +} + +/* Make a range type. */ + +static boolean +ieee_range_type (p, low, high) + PTR p; + bfd_signed_vma low; + bfd_signed_vma high; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + unsigned int size; + boolean unsignedp, localp; + + size = info->type_stack->type.size; + unsignedp = info->type_stack->type.unsignedp; + localp = info->type_stack->type.localp; + ieee_pop_unused_type (info); + return (ieee_define_type (info, size, unsignedp, localp) + && ieee_write_number (info, 'R') + && ieee_write_number (info, (bfd_vma) low) + && ieee_write_number (info, (bfd_vma) high) + && ieee_write_number (info, unsignedp ? 0 : 1) + && ieee_write_number (info, size)); +} + +/* Make an array type. */ + +/*ARGSUSED*/ +static boolean +ieee_array_type (p, low, high, stringp) + PTR p; + bfd_signed_vma low; + bfd_signed_vma high; + boolean stringp; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + unsigned int eleindx; + boolean localp; + unsigned int size; + struct ieee_modified_type *m = NULL; + struct ieee_modified_array_type *a; + + /* IEEE does not store the range, so we just ignore it. */ + ieee_pop_unused_type (info); + localp = info->type_stack->type.localp; + size = info->type_stack->type.size; + eleindx = ieee_pop_type (info); + + /* If we don't know the range, treat the size as exactly one + element. */ + if (low < high) + size *= (high - low) + 1; + + if (! localp) + { + m = ieee_get_modified_info (info, eleindx); + if (m == NULL) + return false; + + for (a = m->arrays; a != NULL; a = a->next) + { + if (a->low == low && a->high == high) + return ieee_push_type (info, a->indx, size, false, false); + } + } + + if (! ieee_define_type (info, size, false, localp) + || ! ieee_write_number (info, low == 0 ? 'Z' : 'C') + || ! ieee_write_number (info, eleindx)) + return false; + if (low != 0) + { + if (! ieee_write_number (info, low)) + return false; + } + + if (! ieee_write_number (info, high + 1)) + return false; + + if (! localp) + { + a = (struct ieee_modified_array_type *) xmalloc (sizeof *a); + memset (a, 0, sizeof *a); + + a->indx = info->type_stack->type.indx; + a->low = low; + a->high = high; + + a->next = m->arrays; + m->arrays = a; + } + + return true; +} + +/* Make a set type. */ + +static boolean +ieee_set_type (p, bitstringp) + PTR p; + boolean bitstringp; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + boolean localp; + unsigned int eleindx; + + localp = info->type_stack->type.localp; + eleindx = ieee_pop_type (info); + + /* FIXME: We don't know the size, so we just use 4. */ + + return (ieee_define_type (info, 0, true, localp) + && ieee_write_number (info, 's') + && ieee_write_number (info, 4) + && ieee_write_number (info, eleindx)); +} + +/* Make an offset type. */ + +static boolean +ieee_offset_type (p) + PTR p; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + unsigned int targetindx, baseindx; + + targetindx = ieee_pop_type (info); + baseindx = ieee_pop_type (info); + + /* FIXME: The MRI C++ compiler does not appear to generate any + useful type information about an offset type. It just records a + pointer to member as an integer. The MRI/HP IEEE spec does + describe a pmisc record which can be used for a pointer to + member. Unfortunately, it does not describe the target type, + which seems pretty important. I'm going to punt this for now. */ + + return ieee_int_type (p, 4, true); +} + +/* Make a method type. */ + +static boolean +ieee_method_type (p, domain, argcount, varargs) + PTR p; + boolean domain; + int argcount; + boolean varargs; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + + /* FIXME: The MRI/HP IEEE spec defines a pmisc record to use for a + method, but the definition is incomplete. We just output an 'x' + type. */ + + if (domain) + ieee_pop_unused_type (info); + + return ieee_function_type (p, argcount, varargs); +} + +/* Make a const qualified type. */ + +static boolean +ieee_const_type (p) + PTR p; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + unsigned int size; + boolean unsignedp, localp; + unsigned int indx; + struct ieee_modified_type *m = NULL; + + size = info->type_stack->type.size; + unsignedp = info->type_stack->type.unsignedp; + localp = info->type_stack->type.localp; + indx = ieee_pop_type (info); + + if (! localp) + { + m = ieee_get_modified_info (info, indx); + if (m == NULL) + return false; + + if (m->const_qualified > 0) + return ieee_push_type (info, m->const_qualified, size, unsignedp, + false); + } + + if (! ieee_define_type (info, size, unsignedp, localp) + || ! ieee_write_number (info, 'n') + || ! ieee_write_number (info, 1) + || ! ieee_write_number (info, indx)) + return false; + + if (! localp) + m->const_qualified = info->type_stack->type.indx; + + return true; +} + +/* Make a volatile qualified type. */ + +static boolean +ieee_volatile_type (p) + PTR p; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + unsigned int size; + boolean unsignedp, localp; + unsigned int indx; + struct ieee_modified_type *m = NULL; + + size = info->type_stack->type.size; + unsignedp = info->type_stack->type.unsignedp; + localp = info->type_stack->type.localp; + indx = ieee_pop_type (info); + + if (! localp) + { + m = ieee_get_modified_info (info, indx); + if (m == NULL) + return false; + + if (m->volatile_qualified > 0) + return ieee_push_type (info, m->volatile_qualified, size, unsignedp, + false); + } + + if (! ieee_define_type (info, size, unsignedp, localp) + || ! ieee_write_number (info, 'n') + || ! ieee_write_number (info, 2) + || ! ieee_write_number (info, indx)) + return false; + + if (! localp) + m->volatile_qualified = info->type_stack->type.indx; + + return true; +} + +/* Convert an enum debug_visibility into a CXXFLAGS value. */ + +static unsigned int +ieee_vis_to_flags (visibility) + enum debug_visibility visibility; +{ + switch (visibility) + { + default: + abort (); + case DEBUG_VISIBILITY_PUBLIC: + return CXXFLAGS_VISIBILITY_PUBLIC; + case DEBUG_VISIBILITY_PRIVATE: + return CXXFLAGS_VISIBILITY_PRIVATE; + case DEBUG_VISIBILITY_PROTECTED: + return CXXFLAGS_VISIBILITY_PROTECTED; + } + /*NOTREACHED*/ +} + +/* Start defining a struct type. We build it in the strdef field on + the stack, to avoid confusing type definitions required by the + fields with the struct type itself. */ + +static boolean +ieee_start_struct_type (p, tag, id, structp, size) + PTR p; + const char *tag; + unsigned int id; + boolean structp; + unsigned int size; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + boolean localp, ignorep; + boolean copy; + char ab[20]; + const char *look; + struct ieee_name_type_hash_entry *h; + struct ieee_name_type *nt, *ntlook; + struct ieee_buflist strdef; + + localp = false; + ignorep = false; + + /* We need to create a tag for internal use even if we don't want + one for external use. This will let us refer to an anonymous + struct. */ + if (tag != NULL) + { + look = tag; + copy = false; + } + else + { + sprintf (ab, "__anon%u", id); + look = ab; + copy = true; + } + + /* If we already have references to the tag, we must use the + existing type index. */ + h = ieee_name_type_hash_lookup (&info->tags, look, true, copy); + if (h == NULL) + return false; + + nt = NULL; + for (ntlook = h->types; ntlook != NULL; ntlook = ntlook->next) + { + if (ntlook->id == id) + nt = ntlook; + else if (! ntlook->type.localp) + { + /* We are creating a duplicate definition of a globally + defined tag. Force it to be local to avoid + confusion. */ + localp = true; + } + } + + if (nt != NULL) + { + assert (localp == nt->type.localp); + if (nt->kind == DEBUG_KIND_ILLEGAL && ! localp) + { + /* We've already seen a global definition of the type. + Ignore this new definition. */ + ignorep = true; + } + } + else + { + nt = (struct ieee_name_type *) xmalloc (sizeof *nt); + memset (nt, 0, sizeof *nt); + nt->id = id; + nt->type.name = h->root.string; + nt->next = h->types; + h->types = nt; + nt->type.indx = info->type_indx; + ++info->type_indx; + } + + nt->kind = DEBUG_KIND_ILLEGAL; + + if (! ieee_init_buffer (info, &strdef) + || ! ieee_define_named_type (info, tag, nt->type.indx, size, true, + localp, &strdef) + || ! ieee_write_number (info, structp ? 'S' : 'U') + || ! ieee_write_number (info, size)) + return false; + + if (! ignorep) + { + const char *hold; + + /* We never want nt->type.name to be NULL. We want the rest of + the type to be the object set up on the type stack; it will + have a NULL name if tag is NULL. */ + hold = nt->type.name; + nt->type = info->type_stack->type; + nt->type.name = hold; + } + + info->type_stack->type.name = tag; + info->type_stack->type.strdef = strdef; + info->type_stack->type.ignorep = ignorep; + + return true; +} + +/* Add a field to a struct. */ + +static boolean +ieee_struct_field (p, name, bitpos, bitsize, visibility) + PTR p; + const char *name; + bfd_vma bitpos; + bfd_vma bitsize; + enum debug_visibility visibility; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + unsigned int size; + boolean unsignedp; + boolean referencep; + boolean localp; + unsigned int indx; + bfd_vma offset; + + assert (info->type_stack != NULL + && info->type_stack->next != NULL + && ! ieee_buffer_emptyp (&info->type_stack->next->type.strdef)); + + /* If we are ignoring this struct definition, just pop and ignore + the type. */ + if (info->type_stack->next->type.ignorep) + { + ieee_pop_unused_type (info); + return true; + } + + size = info->type_stack->type.size; + unsignedp = info->type_stack->type.unsignedp; + referencep = info->type_stack->type.referencep; + localp = info->type_stack->type.localp; + indx = ieee_pop_type (info); + + if (localp) + info->type_stack->type.localp = true; + + if (info->type_stack->type.classdef != NULL) + { + unsigned int flags; + unsigned int nindx; + + /* This is a class. We must add a description of this field to + the class records we are building. */ + + flags = ieee_vis_to_flags (visibility); + nindx = info->type_stack->type.classdef->indx; + if (! ieee_change_buffer (info, + &info->type_stack->type.classdef->pmiscbuf) + || ! ieee_write_asn (info, nindx, 'd') + || ! ieee_write_asn (info, nindx, flags) + || ! ieee_write_atn65 (info, nindx, name) + || ! ieee_write_atn65 (info, nindx, name)) + return false; + info->type_stack->type.classdef->pmisccount += 4; + + if (referencep) + { + unsigned int nindx; + + /* We need to output a record recording that this field is + really of reference type. We put this on the refs field + of classdef, so that it can be appended to the C++ + records after the class is defined. */ + + nindx = info->name_indx; + ++info->name_indx; + + if (! ieee_change_buffer (info, + &info->type_stack->type.classdef->refs) + || ! ieee_write_byte (info, (int) ieee_nn_record) + || ! ieee_write_number (info, nindx) + || ! ieee_write_id (info, "") + || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum) + || ! ieee_write_number (info, nindx) + || ! ieee_write_number (info, 0) + || ! ieee_write_number (info, 62) + || ! ieee_write_number (info, 80) + || ! ieee_write_number (info, 4) + || ! ieee_write_asn (info, nindx, 'R') + || ! ieee_write_asn (info, nindx, 3) + || ! ieee_write_atn65 (info, nindx, info->type_stack->type.name) + || ! ieee_write_atn65 (info, nindx, name)) + return false; + } + } + + /* If the bitsize doesn't match the expected size, we need to output + a bitfield type. */ + if (size == 0 || bitsize == 0 || bitsize == size * 8) + offset = bitpos / 8; + else + { + if (! ieee_define_type (info, 0, unsignedp, + info->type_stack->type.localp) + || ! ieee_write_number (info, 'g') + || ! ieee_write_number (info, unsignedp ? 0 : 1) + || ! ieee_write_number (info, bitsize) + || ! ieee_write_number (info, indx)) + return false; + indx = ieee_pop_type (info); + offset = bitpos; + } + + /* Switch to the struct we are building in order to output this + field definition. */ + return (ieee_change_buffer (info, &info->type_stack->type.strdef) + && ieee_write_id (info, name) + && ieee_write_number (info, indx) + && ieee_write_number (info, offset)); +} + +/* Finish up a struct type. */ + +static boolean +ieee_end_struct_type (p) + PTR p; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + struct ieee_buflist *pb; + + assert (info->type_stack != NULL + && ! ieee_buffer_emptyp (&info->type_stack->type.strdef)); + + /* If we were ignoring this struct definition because it was a + duplicate defintion, just through away whatever bytes we have + accumulated. Leave the type on the stack. */ + if (info->type_stack->type.ignorep) + return true; + + /* If this is not a duplicate definition of this tag, then localp + will be false, and we can put it in the global type block. + FIXME: We should avoid outputting duplicate definitions which are + the same. */ + if (! info->type_stack->type.localp) + { + /* Make sure we have started the global type block. */ + if (ieee_buffer_emptyp (&info->global_types)) + { + if (! ieee_change_buffer (info, &info->global_types) + || ! ieee_write_byte (info, (int) ieee_bb_record_enum) + || ! ieee_write_byte (info, 2) + || ! ieee_write_number (info, 0) + || ! ieee_write_id (info, "")) + return false; + } + pb = &info->global_types; + } + else + { + /* Make sure we have started the types block. */ + if (ieee_buffer_emptyp (&info->types)) + { + if (! ieee_change_buffer (info, &info->types) + || ! ieee_write_byte (info, (int) ieee_bb_record_enum) + || ! ieee_write_byte (info, 1) + || ! ieee_write_number (info, 0) + || ! ieee_write_id (info, info->modname)) + return false; + } + pb = &info->types; + } + + /* Append the struct definition to the types. */ + if (! ieee_append_buffer (info, pb, &info->type_stack->type.strdef) + || ! ieee_init_buffer (info, &info->type_stack->type.strdef)) + return false; + + /* Leave the struct on the type stack. */ + + return true; +} + +/* Start a class type. */ + +static boolean +ieee_start_class_type (p, tag, id, structp, size, vptr, ownvptr) + PTR p; + const char *tag; + unsigned int id; + boolean structp; + unsigned int size; + boolean vptr; + boolean ownvptr; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + const char *vclass; + struct ieee_buflist pmiscbuf; + unsigned int indx; + struct ieee_type_class *classdef; + + /* A C++ class is output as a C++ struct along with a set of pmisc + records describing the class. */ + + /* We need to have a name so that we can associate the struct and + the class. */ + if (tag == NULL) + { + char *t; + + t = (char *) xmalloc (20); + sprintf (t, "__anon%u", id); + tag = t; + } + + /* We can't write out the virtual table information until we have + finished the class, because we don't know the virtual table size. + We get the size from the largest voffset we see. */ + vclass = NULL; + if (vptr && ! ownvptr) + { + vclass = info->type_stack->type.name; + assert (vclass != NULL); + /* We don't call ieee_pop_unused_type, since the class should + get defined. */ + (void) ieee_pop_type (info); + } + + if (! ieee_start_struct_type (p, tag, id, structp, size)) + return false; + + indx = info->name_indx; + ++info->name_indx; + + /* We write out pmisc records into the classdef field. We will + write out the pmisc start after we know the number of records we + need. */ + if (! ieee_init_buffer (info, &pmiscbuf) + || ! ieee_change_buffer (info, &pmiscbuf) + || ! ieee_write_asn (info, indx, 'T') + || ! ieee_write_asn (info, indx, structp ? 'o' : 'u') + || ! ieee_write_atn65 (info, indx, tag)) + return false; + + classdef = (struct ieee_type_class *) xmalloc (sizeof *classdef); + memset (classdef, 0, sizeof *classdef); + + classdef->indx = indx; + classdef->pmiscbuf = pmiscbuf; + classdef->pmisccount = 3; + classdef->vclass = vclass; + classdef->ownvptr = ownvptr; + + info->type_stack->type.classdef = classdef; + + return true; +} + +/* Add a static member to a class. */ + +static boolean +ieee_class_static_member (p, name, physname, visibility) + PTR p; + const char *name; + const char *physname; + enum debug_visibility visibility; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + unsigned int flags; + unsigned int nindx; + + /* We don't care about the type. Hopefully there will be a call to + ieee_variable declaring the physical name and the type, since + that is where an IEEE consumer must get the type. */ + ieee_pop_unused_type (info); + + assert (info->type_stack != NULL + && info->type_stack->type.classdef != NULL); + + flags = ieee_vis_to_flags (visibility); + flags |= CXXFLAGS_STATIC; + + nindx = info->type_stack->type.classdef->indx; + + if (! ieee_change_buffer (info, &info->type_stack->type.classdef->pmiscbuf) + || ! ieee_write_asn (info, nindx, 'd') + || ! ieee_write_asn (info, nindx, flags) + || ! ieee_write_atn65 (info, nindx, name) + || ! ieee_write_atn65 (info, nindx, physname)) + return false; + info->type_stack->type.classdef->pmisccount += 4; + + return true; +} + +/* Add a base class to a class. */ + +static boolean +ieee_class_baseclass (p, bitpos, virtual, visibility) + PTR p; + bfd_vma bitpos; + boolean virtual; + enum debug_visibility visibility; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + const char *bname; + boolean localp; + unsigned int bindx; + char *fname; + unsigned int flags; + unsigned int nindx; + + assert (info->type_stack != NULL + && info->type_stack->type.name != NULL + && info->type_stack->next != NULL + && info->type_stack->next->type.classdef != NULL + && ! ieee_buffer_emptyp (&info->type_stack->next->type.strdef)); + + bname = info->type_stack->type.name; + localp = info->type_stack->type.localp; + bindx = ieee_pop_type (info); + + /* We are currently defining both a struct and a class. We must + write out a field definition in the struct which holds the base + class. The stabs debugging reader will create a field named + _vb$CLASS for a virtual base class, so we just use that. FIXME: + we should not depend upon a detail of stabs debugging. */ + if (virtual) + { + fname = (char *) xmalloc (strlen (bname) + sizeof "_vb$"); + sprintf (fname, "_vb$%s", bname); + flags = BASEFLAGS_VIRTUAL; + } + else + { + if (localp) + info->type_stack->type.localp = true; + + fname = (char *) xmalloc (strlen (bname) + sizeof "_b$"); + sprintf (fname, "_b$%s", bname); + + if (! ieee_change_buffer (info, &info->type_stack->type.strdef) + || ! ieee_write_id (info, fname) + || ! ieee_write_number (info, bindx) + || ! ieee_write_number (info, bitpos / 8)) + return false; + flags = 0; + } + + if (visibility == DEBUG_VISIBILITY_PRIVATE) + flags |= BASEFLAGS_PRIVATE; + + nindx = info->type_stack->type.classdef->indx; + + if (! ieee_change_buffer (info, &info->type_stack->type.classdef->pmiscbuf) + || ! ieee_write_asn (info, nindx, 'b') + || ! ieee_write_asn (info, nindx, flags) + || ! ieee_write_atn65 (info, nindx, bname) + || ! ieee_write_asn (info, nindx, 0) + || ! ieee_write_atn65 (info, nindx, fname)) + return false; + info->type_stack->type.classdef->pmisccount += 5; + + free (fname); + + return true; +} + +/* Start building a method for a class. */ + +static boolean +ieee_class_start_method (p, name) + PTR p; + const char *name; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + + assert (info->type_stack != NULL + && info->type_stack->type.classdef != NULL + && info->type_stack->type.classdef->method == NULL); + + info->type_stack->type.classdef->method = name; + + return true; +} + +/* Define a new method variant, either static or not. */ + +static boolean +ieee_class_method_var (info, physname, visibility, staticp, constp, + volatilep, voffset, context) + struct ieee_handle *info; + const char *physname; + enum debug_visibility visibility; + boolean staticp; + boolean constp; + boolean volatilep; + bfd_vma voffset; + boolean context; +{ + unsigned int flags; + unsigned int nindx; + boolean virtual; + + /* We don't need the type of the method. An IEEE consumer which + wants the type must track down the function by the physical name + and get the type from that. */ + ieee_pop_unused_type (info); + + /* We don't use the context. FIXME: We probably ought to use it to + adjust the voffset somehow, but I don't really know how. */ + if (context) + ieee_pop_unused_type (info); + + assert (info->type_stack != NULL + && info->type_stack->type.classdef != NULL + && info->type_stack->type.classdef->method != NULL); + + flags = ieee_vis_to_flags (visibility); + + /* FIXME: We never set CXXFLAGS_OVERRIDE, CXXFLAGS_OPERATOR, + CXXFLAGS_CTORDTOR, CXXFLAGS_CTOR, or CXXFLAGS_INLINE. */ + + if (staticp) + flags |= CXXFLAGS_STATIC; + if (constp) + flags |= CXXFLAGS_CONST; + if (volatilep) + flags |= CXXFLAGS_VOLATILE; + + nindx = info->type_stack->type.classdef->indx; + + virtual = context || voffset > 0; + + if (! ieee_change_buffer (info, + &info->type_stack->type.classdef->pmiscbuf) + || ! ieee_write_asn (info, nindx, virtual ? 'v' : 'm') + || ! ieee_write_asn (info, nindx, flags) + || ! ieee_write_atn65 (info, nindx, + info->type_stack->type.classdef->method) + || ! ieee_write_atn65 (info, nindx, physname)) + return false; + + if (virtual) + { + if (voffset > info->type_stack->type.classdef->voffset) + info->type_stack->type.classdef->voffset = voffset; + if (! ieee_write_asn (info, nindx, voffset)) + return false; + ++info->type_stack->type.classdef->pmisccount; + } + + if (! ieee_write_asn (info, nindx, 0)) + return false; + + info->type_stack->type.classdef->pmisccount += 5; + + return true; +} + +/* Define a new method variant. */ + +static boolean +ieee_class_method_variant (p, physname, visibility, constp, volatilep, + voffset, context) + PTR p; + const char *physname; + enum debug_visibility visibility; + boolean constp; + boolean volatilep; + bfd_vma voffset; + boolean context; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + + return ieee_class_method_var (info, physname, visibility, false, constp, + volatilep, voffset, context); +} + +/* Define a new static method variant. */ + +static boolean +ieee_class_static_method_variant (p, physname, visibility, constp, volatilep) + PTR p; + const char *physname; + enum debug_visibility visibility; + boolean constp; + boolean volatilep; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + + return ieee_class_method_var (info, physname, visibility, true, constp, + volatilep, 0, false); +} + +/* Finish up a method. */ + +static boolean +ieee_class_end_method (p) + PTR p; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + + assert (info->type_stack != NULL + && info->type_stack->type.classdef != NULL + && info->type_stack->type.classdef->method != NULL); + + info->type_stack->type.classdef->method = NULL; + + return true; +} + +/* Finish up a class. */ + +static boolean +ieee_end_class_type (p) + PTR p; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + unsigned int nindx; + + assert (info->type_stack != NULL + && info->type_stack->type.classdef != NULL); + + /* If we were ignoring this class definition because it was a + duplicate definition, just through away whatever bytes we have + accumulated. Leave the type on the stack. */ + if (info->type_stack->type.ignorep) + return true; + + nindx = info->type_stack->type.classdef->indx; + + /* If we have a virtual table, we can write out the information now. */ + if (info->type_stack->type.classdef->vclass != NULL + || info->type_stack->type.classdef->ownvptr) + { + if (! ieee_change_buffer (info, + &info->type_stack->type.classdef->pmiscbuf) + || ! ieee_write_asn (info, nindx, 'z') + || ! ieee_write_atn65 (info, nindx, "") + || ! ieee_write_asn (info, nindx, + info->type_stack->type.classdef->voffset)) + return false; + if (info->type_stack->type.classdef->ownvptr) + { + if (! ieee_write_atn65 (info, nindx, "")) + return false; + } + else + { + if (! ieee_write_atn65 (info, nindx, + info->type_stack->type.classdef->vclass)) + return false; + } + if (! ieee_write_asn (info, nindx, 0)) + return false; + info->type_stack->type.classdef->pmisccount += 5; + } + + /* Now that we know the number of pmisc records, we can write out + the atn62 which starts the pmisc records, and append them to the + C++ buffers. */ + + if (! ieee_change_buffer (info, &info->cxx) + || ! ieee_write_byte (info, (int) ieee_nn_record) + || ! ieee_write_number (info, nindx) + || ! ieee_write_id (info, "") + || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum) + || ! ieee_write_number (info, nindx) + || ! ieee_write_number (info, 0) + || ! ieee_write_number (info, 62) + || ! ieee_write_number (info, 80) + || ! ieee_write_number (info, + info->type_stack->type.classdef->pmisccount)) + return false; + + if (! ieee_append_buffer (info, &info->cxx, + &info->type_stack->type.classdef->pmiscbuf)) + return false; + if (! ieee_buffer_emptyp (&info->type_stack->type.classdef->refs)) + { + if (! ieee_append_buffer (info, &info->cxx, + &info->type_stack->type.classdef->refs)) + return false; + } + + return ieee_end_struct_type (p); +} + +/* Push a previously seen typedef onto the type stack. */ + +static boolean +ieee_typedef_type (p, name) + PTR p; + const char *name; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + struct ieee_name_type_hash_entry *h; + struct ieee_name_type *nt; + + h = ieee_name_type_hash_lookup (&info->typedefs, name, false, false); + + /* h should never be NULL, since that would imply that the generic + debugging code has asked for a typedef which it has not yet + defined. */ + assert (h != NULL); + + /* We always use the most recently defined type for this name, which + will be the first one on the list. */ + + nt = h->types; + if (! ieee_push_type (info, nt->type.indx, nt->type.size, + nt->type.unsignedp, nt->type.localp)) + return false; + + /* Copy over any other type information we may have. */ + info->type_stack->type = nt->type; + + return true; +} + +/* Push a tagged type onto the type stack. */ + +static boolean +ieee_tag_type (p, name, id, kind) + PTR p; + const char *name; + unsigned int id; + enum debug_type_kind kind; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + boolean localp; + boolean copy; + char ab[20]; + struct ieee_name_type_hash_entry *h; + struct ieee_name_type *nt; + + if (kind == DEBUG_KIND_ENUM) + { + struct ieee_defined_enum *e; + + if (name == NULL) + abort (); + for (e = info->enums; e != NULL; e = e->next) + if (e->tag != NULL && strcmp (e->tag, name) == 0) + return ieee_push_type (info, e->indx, 0, true, false); + + e = (struct ieee_defined_enum *) xmalloc (sizeof *e); + memset (e, 0, sizeof *e); + + e->indx = info->type_indx; + ++info->type_indx; + e->tag = name; + e->defined = false; + + e->next = info->enums; + info->enums = e; + + return ieee_push_type (info, e->indx, 0, true, false); + } + + localp = false; + + copy = false; + if (name == NULL) + { + sprintf (ab, "__anon%u", id); + name = ab; + copy = true; + } + + h = ieee_name_type_hash_lookup (&info->tags, name, true, copy); + if (h == NULL) + return false; + + for (nt = h->types; nt != NULL; nt = nt->next) + { + if (nt->id == id) + { + if (! ieee_push_type (info, nt->type.indx, nt->type.size, + nt->type.unsignedp, nt->type.localp)) + return false; + /* Copy over any other type information we may have. */ + info->type_stack->type = nt->type; + return true; + } + + if (! nt->type.localp) + { + /* This is a duplicate of a global type, so it must be + local. */ + localp = true; + } + } + + nt = (struct ieee_name_type *) xmalloc (sizeof *nt); + memset (nt, 0, sizeof *nt); + + nt->id = id; + nt->type.name = h->root.string; + nt->type.indx = info->type_indx; + nt->type.localp = localp; + ++info->type_indx; + nt->kind = kind; + + nt->next = h->types; + h->types = nt; + + if (! ieee_push_type (info, nt->type.indx, 0, false, localp)) + return false; + + info->type_stack->type.name = h->root.string; + + return true; +} + +/* Output a typedef. */ + +static boolean +ieee_typdef (p, name) + PTR p; + const char *name; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + struct ieee_write_type type; + unsigned int indx; + boolean found; + boolean localp; + struct ieee_name_type_hash_entry *h; + struct ieee_name_type *nt; + + type = info->type_stack->type; + indx = type.indx; + + /* If this is a simple builtin type using a builtin name, we don't + want to output the typedef itself. We also want to change the + type index to correspond to the name being used. We recognize + names used in stabs debugging output even if they don't exactly + correspond to the names used for the IEEE builtin types. */ + found = false; + if (indx <= (unsigned int) builtin_bcd_float) + { + switch ((enum builtin_types) indx) + { + default: + break; + + case builtin_void: + if (strcmp (name, "void") == 0) + found = true; + break; + + case builtin_signed_char: + case builtin_char: + if (strcmp (name, "signed char") == 0) + { + indx = (unsigned int) builtin_signed_char; + found = true; + } + else if (strcmp (name, "char") == 0) + { + indx = (unsigned int) builtin_char; + found = true; + } + break; + + case builtin_unsigned_char: + if (strcmp (name, "unsigned char") == 0) + found = true; + break; + + case builtin_signed_short_int: + case builtin_short: + case builtin_short_int: + case builtin_signed_short: + if (strcmp (name, "signed short int") == 0) + { + indx = (unsigned int) builtin_signed_short_int; + found = true; + } + else if (strcmp (name, "short") == 0) + { + indx = (unsigned int) builtin_short; + found = true; + } + else if (strcmp (name, "short int") == 0) + { + indx = (unsigned int) builtin_short_int; + found = true; + } + else if (strcmp (name, "signed short") == 0) + { + indx = (unsigned int) builtin_signed_short; + found = true; + } + break; + + case builtin_unsigned_short_int: + case builtin_unsigned_short: + if (strcmp (name, "unsigned short int") == 0 + || strcmp (name, "short unsigned int") == 0) + { + indx = builtin_unsigned_short_int; + found = true; + } + else if (strcmp (name, "unsigned short") == 0) + { + indx = builtin_unsigned_short; + found = true; + } + break; + + case builtin_signed_long: + case builtin_int: /* FIXME: Size depends upon architecture. */ + case builtin_long: + if (strcmp (name, "signed long") == 0) + { + indx = builtin_signed_long; + found = true; + } + else if (strcmp (name, "int") == 0) + { + indx = builtin_int; + found = true; + } + else if (strcmp (name, "long") == 0 + || strcmp (name, "long int") == 0) + { + indx = builtin_long; + found = true; + } + break; + + case builtin_unsigned_long: + case builtin_unsigned: /* FIXME: Size depends upon architecture. */ + case builtin_unsigned_int: /* FIXME: Like builtin_unsigned. */ + if (strcmp (name, "unsigned long") == 0 + || strcmp (name, "long unsigned int") == 0) + { + indx = builtin_unsigned_long; + found = true; + } + else if (strcmp (name, "unsigned") == 0) + { + indx = builtin_unsigned; + found = true; + } + else if (strcmp (name, "unsigned int") == 0) + { + indx = builtin_unsigned_int; + found = true; + } + break; + + case builtin_signed_long_long: + if (strcmp (name, "signed long long") == 0 + || strcmp (name, "long long int") == 0) + found = true; + break; + + case builtin_unsigned_long_long: + if (strcmp (name, "unsigned long long") == 0 + || strcmp (name, "long long unsigned int") == 0) + found = true; + break; + + case builtin_float: + if (strcmp (name, "float") == 0) + found = true; + break; + + case builtin_double: + if (strcmp (name, "double") == 0) + found = true; + break; + + case builtin_long_double: + if (strcmp (name, "long double") == 0) + found = true; + break; + + case builtin_long_long_double: + if (strcmp (name, "long long double") == 0) + found = true; + break; + } + + if (found) + type.indx = indx; + } + + h = ieee_name_type_hash_lookup (&info->typedefs, name, true, false); + if (h == NULL) + return false; + + /* See if we have already defined this type with this name. */ + localp = type.localp; + for (nt = h->types; nt != NULL; nt = nt->next) + { + if (nt->id == indx) + { + /* If this is a global definition, then we don't need to + do anything here. */ + if (! nt->type.localp) + { + ieee_pop_unused_type (info); + return true; + } + } + else + { + /* This is a duplicate definition, so make this one local. */ + localp = true; + } + } + + /* We need to add a new typedef for this type. */ + + nt = (struct ieee_name_type *) xmalloc (sizeof *nt); + memset (nt, 0, sizeof *nt); + nt->id = indx; + nt->type = type; + nt->type.name = name; + nt->type.localp = localp; + nt->kind = DEBUG_KIND_ILLEGAL; + + nt->next = h->types; + h->types = nt; + + if (found) + { + /* This is one of the builtin typedefs, so we don't need to + actually define it. */ + ieee_pop_unused_type (info); + return true; + } + + indx = ieee_pop_type (info); + + if (! ieee_define_named_type (info, name, (unsigned int) -1, type.size, + type.unsignedp, localp, + (struct ieee_buflist *) NULL) + || ! ieee_write_number (info, 'T') + || ! ieee_write_number (info, indx)) + return false; + + /* Remove the type we just added to the type stack. This should not + be ieee_pop_unused_type, since the type is used, we just don't + need it now. */ + (void) ieee_pop_type (info); + + return true; +} + +/* Output a tag for a type. We don't have to do anything here. */ + +static boolean +ieee_tag (p, name) + PTR p; + const char *name; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + + /* This should not be ieee_pop_unused_type, since we want the type + to be defined. */ + (void) ieee_pop_type (info); + return true; +} + +/* Output an integer constant. */ + +static boolean +ieee_int_constant (p, name, val) + PTR p; + const char *name; + bfd_vma val; +{ + /* FIXME. */ + return true; +} + +/* Output a floating point constant. */ + +static boolean +ieee_float_constant (p, name, val) + PTR p; + const char *name; + double val; +{ + /* FIXME. */ + return true; +} + +/* Output a typed constant. */ + +static boolean +ieee_typed_constant (p, name, val) + PTR p; + const char *name; + bfd_vma val; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + + /* FIXME. */ + ieee_pop_unused_type (info); + return true; +} + +/* Output a variable. */ + +static boolean +ieee_variable (p, name, kind, val) + PTR p; + const char *name; + enum debug_var_kind kind; + bfd_vma val; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + unsigned int name_indx; + unsigned int size; + boolean referencep; + unsigned int type_indx; + boolean asn; + int refflag; + + size = info->type_stack->type.size; + referencep = info->type_stack->type.referencep; + type_indx = ieee_pop_type (info); + + assert (! ieee_buffer_emptyp (&info->vars)); + if (! ieee_change_buffer (info, &info->vars)) + return false; + + name_indx = info->name_indx; + ++info->name_indx; + + /* Write out an NN and an ATN record for this variable. */ + if (! ieee_write_byte (info, (int) ieee_nn_record) + || ! ieee_write_number (info, name_indx) + || ! ieee_write_id (info, name) + || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum) + || ! ieee_write_number (info, name_indx) + || ! ieee_write_number (info, type_indx)) + return false; + switch (kind) + { + default: + abort (); + return false; + case DEBUG_GLOBAL: + if (! ieee_write_number (info, 8) + || ! ieee_add_range (info, false, val, val + size)) + return false; + refflag = 0; + asn = true; + break; + case DEBUG_STATIC: + if (! ieee_write_number (info, 3) + || ! ieee_add_range (info, false, val, val + size)) + return false; + refflag = 1; + asn = true; + break; + case DEBUG_LOCAL_STATIC: + if (! ieee_write_number (info, 3) + || ! ieee_add_range (info, false, val, val + size)) + return false; + refflag = 2; + asn = true; + break; + case DEBUG_LOCAL: + if (! ieee_write_number (info, 1) + || ! ieee_write_number (info, val)) + return false; + refflag = 2; + asn = false; + break; + case DEBUG_REGISTER: + if (! ieee_write_number (info, 2) + || ! ieee_write_number (info, + ieee_genreg_to_regno (info->abfd, val))) + return false; + refflag = 2; + asn = false; + break; + } + + if (asn) + { + if (! ieee_write_asn (info, name_indx, val)) + return false; + } + + /* If this is really a reference type, then we just output it with + pointer type, and must now output a C++ record indicating that it + is really reference type. */ + if (referencep) + { + unsigned int nindx; + + nindx = info->name_indx; + ++info->name_indx; + + /* If this is a global variable, we want to output the misc + record in the C++ misc record block. Otherwise, we want to + output it just after the variable definition, which is where + the current buffer is. */ + if (refflag != 2) + { + if (! ieee_change_buffer (info, &info->cxx)) + return false; + } + + if (! ieee_write_byte (info, (int) ieee_nn_record) + || ! ieee_write_number (info, nindx) + || ! ieee_write_id (info, "") + || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum) + || ! ieee_write_number (info, nindx) + || ! ieee_write_number (info, 0) + || ! ieee_write_number (info, 62) + || ! ieee_write_number (info, 80) + || ! ieee_write_number (info, 3) + || ! ieee_write_asn (info, nindx, 'R') + || ! ieee_write_asn (info, nindx, refflag) + || ! ieee_write_atn65 (info, nindx, name)) + return false; + } + + return true; +} + +/* Start outputting information for a function. */ + +static boolean +ieee_start_function (p, name, global) + PTR p; + const char *name; + boolean global; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + boolean referencep; + unsigned int retindx, typeindx; + + referencep = info->type_stack->type.referencep; + retindx = ieee_pop_type (info); + + /* Besides recording a BB4 or BB6 block, we record the type of the + function in the BB1 typedef block. We can't write out the full + type until we have seen all the parameters, so we accumulate it + in info->fntype and info->fnargs. */ + if (! ieee_buffer_emptyp (&info->fntype)) + { + /* FIXME: This might happen someday if we support nested + functions. */ + abort (); + } + + info->fnname = name; + + /* An attribute of 0x40 means that the push mask is unknown. */ + if (! ieee_define_named_type (info, name, (unsigned int) -1, 0, false, true, + &info->fntype) + || ! ieee_write_number (info, 'x') + || ! ieee_write_number (info, 0x40) + || ! ieee_write_number (info, 0) + || ! ieee_write_number (info, 0) + || ! ieee_write_number (info, retindx)) + return false; + + typeindx = ieee_pop_type (info); + + if (! ieee_init_buffer (info, &info->fnargs)) + return false; + info->fnargcount = 0; + + /* If the function return value is actually a reference type, we + must add a record indicating that. */ + if (referencep) + { + unsigned int nindx; + + nindx = info->name_indx; + ++info->name_indx; + if (! ieee_change_buffer (info, &info->cxx) + || ! ieee_write_byte (info, (int) ieee_nn_record) + || ! ieee_write_number (info, nindx) + || ! ieee_write_id (info, "") + || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum) + || ! ieee_write_number (info, nindx) + || ! ieee_write_number (info, 0) + || ! ieee_write_number (info, 62) + || ! ieee_write_number (info, 80) + || ! ieee_write_number (info, 3) + || ! ieee_write_asn (info, nindx, 'R') + || ! ieee_write_asn (info, nindx, global ? 0 : 1) + || ! ieee_write_atn65 (info, nindx, name)) + return false; + } + + assert (! ieee_buffer_emptyp (&info->vars)); + if (! ieee_change_buffer (info, &info->vars)) + return false; + + /* The address is written out as the first block. */ + + ++info->block_depth; + + return (ieee_write_byte (info, (int) ieee_bb_record_enum) + && ieee_write_byte (info, global ? 4 : 6) + && ieee_write_number (info, 0) + && ieee_write_id (info, name) + && ieee_write_number (info, 0) + && ieee_write_number (info, typeindx)); +} + +/* Add a function parameter. This will normally be called before the + first block, so we postpone them until we see the block. */ + +static boolean +ieee_function_parameter (p, name, kind, val) + PTR p; + const char *name; + enum debug_parm_kind kind; + bfd_vma val; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + struct ieee_pending_parm *m, **pm; + + assert (info->block_depth == 1); + + m = (struct ieee_pending_parm *) xmalloc (sizeof *m); + memset (m, 0, sizeof *m); + + m->next = NULL; + m->name = name; + m->referencep = info->type_stack->type.referencep; + m->type = ieee_pop_type (info); + m->kind = kind; + m->val = val; + + for (pm = &info->pending_parms; *pm != NULL; pm = &(*pm)->next) + ; + *pm = m; + + /* Add the type to the fnargs list. */ + if (! ieee_change_buffer (info, &info->fnargs) + || ! ieee_write_number (info, m->type)) + return false; + ++info->fnargcount; + + return true; +} + +/* Output pending function parameters. */ + +static boolean +ieee_output_pending_parms (info) + struct ieee_handle *info; +{ + struct ieee_pending_parm *m; + unsigned int refcount; + + refcount = 0; + for (m = info->pending_parms; m != NULL; m = m->next) + { + enum debug_var_kind vkind; + + switch (m->kind) + { + default: + abort (); + return false; + case DEBUG_PARM_STACK: + case DEBUG_PARM_REFERENCE: + vkind = DEBUG_LOCAL; + break; + case DEBUG_PARM_REG: + case DEBUG_PARM_REF_REG: + vkind = DEBUG_REGISTER; + break; + } + + if (! ieee_push_type (info, m->type, 0, false, false)) + return false; + info->type_stack->type.referencep = m->referencep; + if (m->referencep) + ++refcount; + if (! ieee_variable ((PTR) info, m->name, vkind, m->val)) + return false; + } + + /* If there are any reference parameters, we need to output a + miscellaneous record indicating them. */ + if (refcount > 0) + { + unsigned int nindx, varindx; + + /* FIXME: The MRI compiler outputs the demangled function name + here, but we are outputting the mangled name. */ + nindx = info->name_indx; + ++info->name_indx; + if (! ieee_change_buffer (info, &info->vars) + || ! ieee_write_byte (info, (int) ieee_nn_record) + || ! ieee_write_number (info, nindx) + || ! ieee_write_id (info, "") + || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum) + || ! ieee_write_number (info, nindx) + || ! ieee_write_number (info, 0) + || ! ieee_write_number (info, 62) + || ! ieee_write_number (info, 80) + || ! ieee_write_number (info, refcount + 3) + || ! ieee_write_asn (info, nindx, 'B') + || ! ieee_write_atn65 (info, nindx, info->fnname) + || ! ieee_write_asn (info, nindx, 0)) + return false; + for (m = info->pending_parms, varindx = 1; + m != NULL; + m = m->next, varindx++) + { + if (m->referencep) + { + if (! ieee_write_asn (info, nindx, varindx)) + return false; + } + } + } + + m = info->pending_parms; + while (m != NULL) + { + struct ieee_pending_parm *next; + + next = m->next; + free (m); + m = next; + } + + info->pending_parms = NULL; + + return true; +} + +/* Start a block. If this is the first block, we output the address + to finish the BB4 or BB6, and then output the function parameters. */ + +static boolean +ieee_start_block (p, addr) + PTR p; + bfd_vma addr; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + + if (! ieee_change_buffer (info, &info->vars)) + return false; + + if (info->block_depth == 1) + { + if (! ieee_write_number (info, addr) + || ! ieee_output_pending_parms (info)) + return false; + } + else + { + if (! ieee_write_byte (info, (int) ieee_bb_record_enum) + || ! ieee_write_byte (info, 6) + || ! ieee_write_number (info, 0) + || ! ieee_write_id (info, "") + || ! ieee_write_number (info, 0) + || ! ieee_write_number (info, 0) + || ! ieee_write_number (info, addr)) + return false; + } + + if (! ieee_start_range (info, addr)) + return false; + + ++info->block_depth; + + return true; +} + +/* End a block. */ + +static boolean +ieee_end_block (p, addr) + PTR p; + bfd_vma addr; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + + /* The address we are given is the end of the block, but IEEE seems + to want to the address of the last byte in the block, so we + subtract one. */ + if (! ieee_change_buffer (info, &info->vars) + || ! ieee_write_byte (info, (int) ieee_be_record_enum) + || ! ieee_write_number (info, addr - 1)) + return false; + + if (! ieee_end_range (info, addr)) + return false; + + --info->block_depth; + + if (addr > info->highaddr) + info->highaddr = addr; + + return true; +} + +/* End a function. */ + +static boolean +ieee_end_function (p) + PTR p; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + + assert (info->block_depth == 1); + + --info->block_depth; + + /* Now we can finish up fntype, and add it to the typdef section. + At this point, fntype is the 'x' type up to the argument count, + and fnargs is the argument types. We must add the argument + count, and we must add the level. FIXME: We don't record varargs + functions correctly. In fact, stabs debugging does not give us + enough information to do so. */ + if (! ieee_change_buffer (info, &info->fntype) + || ! ieee_write_number (info, info->fnargcount) + || ! ieee_change_buffer (info, &info->fnargs) + || ! ieee_write_number (info, 0)) + return false; + + /* Make sure the typdef block has been started. */ + if (ieee_buffer_emptyp (&info->types)) + { + if (! ieee_change_buffer (info, &info->types) + || ! ieee_write_byte (info, (int) ieee_bb_record_enum) + || ! ieee_write_byte (info, 1) + || ! ieee_write_number (info, 0) + || ! ieee_write_id (info, info->modname)) + return false; + } + + if (! ieee_append_buffer (info, &info->types, &info->fntype) + || ! ieee_append_buffer (info, &info->types, &info->fnargs)) + return false; + + info->fnname = NULL; + if (! ieee_init_buffer (info, &info->fntype) + || ! ieee_init_buffer (info, &info->fnargs)) + return false; + info->fnargcount = 0; + + return true; +} + +/* Record line number information. */ + +static boolean +ieee_lineno (p, filename, lineno, addr) + PTR p; + const char *filename; + unsigned long lineno; + bfd_vma addr; +{ + struct ieee_handle *info = (struct ieee_handle *) p; + + assert (info->filename != NULL); + + /* The HP simulator seems to get confused when more than one line is + listed for the same address, at least if they are in different + files. We handle this by always listing the last line for a + given address, since that seems to be the one that gdb uses. */ + if (info->pending_lineno_filename != NULL + && addr != info->pending_lineno_addr) + { + /* Make sure we have a line number block. */ + if (! ieee_buffer_emptyp (&info->linenos)) + { + if (! ieee_change_buffer (info, &info->linenos)) + return false; + } + else + { + info->lineno_name_indx = info->name_indx; + ++info->name_indx; + if (! ieee_change_buffer (info, &info->linenos) + || ! ieee_write_byte (info, (int) ieee_bb_record_enum) + || ! ieee_write_byte (info, 5) + || ! ieee_write_number (info, 0) + || ! ieee_write_id (info, info->filename) + || ! ieee_write_byte (info, (int) ieee_nn_record) + || ! ieee_write_number (info, info->lineno_name_indx) + || ! ieee_write_id (info, "")) + return false; + info->lineno_filename = info->filename; + } + + if (strcmp (info->pending_lineno_filename, info->lineno_filename) != 0) + { + if (strcmp (info->filename, info->lineno_filename) != 0) + { + /* We were not in the main file. Close the block for the + included file. */ + if (! ieee_write_byte (info, (int) ieee_be_record_enum)) + return false; + if (strcmp (info->filename, info->pending_lineno_filename) == 0) + { + /* We need a new NN record, and we aren't about to + output one. */ + info->lineno_name_indx = info->name_indx; + ++info->name_indx; + if (! ieee_write_byte (info, (int) ieee_nn_record) + || ! ieee_write_number (info, info->lineno_name_indx) + || ! ieee_write_id (info, "")) + return false; + } + } + if (strcmp (info->filename, info->pending_lineno_filename) != 0) + { + /* We are not changing to the main file. Open a block for + the new included file. */ + info->lineno_name_indx = info->name_indx; + ++info->name_indx; + if (! ieee_write_byte (info, (int) ieee_bb_record_enum) + || ! ieee_write_byte (info, 5) + || ! ieee_write_number (info, 0) + || ! ieee_write_id (info, info->pending_lineno_filename) + || ! ieee_write_byte (info, (int) ieee_nn_record) + || ! ieee_write_number (info, info->lineno_name_indx) + || ! ieee_write_id (info, "")) + return false; + } + info->lineno_filename = info->pending_lineno_filename; + } + + if (! ieee_write_2bytes (info, (int) ieee_atn_record_enum) + || ! ieee_write_number (info, info->lineno_name_indx) + || ! ieee_write_number (info, 0) + || ! ieee_write_number (info, 7) + || ! ieee_write_number (info, info->pending_lineno) + || ! ieee_write_number (info, 0) + || ! ieee_write_asn (info, info->lineno_name_indx, + info->pending_lineno_addr)) + return false; + } + + info->pending_lineno_filename = filename; + info->pending_lineno = lineno; + info->pending_lineno_addr = addr; + + return true; +} diff --git a/binutils/is-ranlib.c b/binutils/is-ranlib.c new file mode 100644 index 0000000..fde72a4 --- /dev/null +++ b/binutils/is-ranlib.c @@ -0,0 +1,3 @@ +/* Linked with ar.o to flag that this program is 'ranlib' (not 'ar'). */ + +int is_ranlib = 1; diff --git a/binutils/is-strip.c b/binutils/is-strip.c new file mode 100644 index 0000000..215341a --- /dev/null +++ b/binutils/is-strip.c @@ -0,0 +1,4 @@ +/* Linked with objcopy.o to flag that this program is 'strip' (not + 'objcopy'). */ + +int is_strip = 1; diff --git a/binutils/mac-binutils.r b/binutils/mac-binutils.r new file mode 100644 index 0000000..7b1a303 --- /dev/null +++ b/binutils/mac-binutils.r @@ -0,0 +1,42 @@ +/* Resources for GNU binutils. */ + +#include "SysTypes.r" + +/* Version resources. */ + +resource 'vers' (1) { + 0, + 0, + 0, + 0, + verUs, + VERSION_STRING, + VERSION_STRING " (C) 1986-95 FSF, Inc." +}; + +resource 'vers' (2, purgeable) { + 0, + 0, + 0, + 0, + verUs, + VERSION_STRING, + "binutils " VERSION_STRING " for MPW" +}; + +#ifdef WANT_CFRG + +#include "CodeFragmentTypes.r" + +resource 'cfrg' (0) { + { + kPowerPC, + kFullLib, + kNoVersionNum, kNoVersionNum, + 0,0, + kIsApp, kOnDiskFlat, kZeroOffset, kWholeFork, + PROG_NAME + } +}; + +#endif /* WANT_CFRG */ diff --git a/binutils/makefile.vms-in b/binutils/makefile.vms-in new file mode 100644 index 0000000..a809d1b --- /dev/null +++ b/binutils/makefile.vms-in @@ -0,0 +1,98 @@ +# +# Makefile for binutils under openVMS (Alpha and Vax) +# +# For use with gnu-make for vms +# +# Created by Klaus K"ampf, kkaempf@rmi.de +# +# + +# Distribution version, filled in by configure.com +VERSION=@VERSION@ + +ifeq ($(ARCH),ALPHA) +TARGET=""vms-alpha"" +else +TARGET=""vms-vax"" +endif + +ifeq ($(CC),gcc) +CFLAGS=/include=([],[-.include],[-.bfd])$(DEFS) +DEFS=/define=("TARGET=$(TARGET)") +LIBS=,gnu_cc_library:libgcc/lib,sys$$library:vaxcrtl.olb/lib,gnu_cc_library:crt0.obj +else +CFLAGS=/noopt/debug/include=([],[-.include],[-.bfd])$(DEFS)\ +/warnings=disable=(missingreturn,implicitfunc,longextern) +DEFS=/define=("TARGET=$(TARGET)","const=","unlink=remove") +LIBS=,sys$$library:vaxcrtl.olb/lib +endif + +BFDLIB = [-.bfd]libbfd.olb/lib +BFDLIB_DEP = [-.bfd]libbfd.olb +LIBIBERTY_DEP = [-.libiberty]libiberty.olb +LIBIBERTY = [-.libiberty]libiberty.olb/lib +OPCODES_DEP = [-.opcodes]libopcodes.olb +OPCODES = [-.opcodes]libopcodes.olb/lib + +DEBUG_OBJS = rddbg.obj,debug.obj,stabs.obj,ieee.obj,rdcoff.obj + +WRITE_DEBUG_OBJS = $(DEBUG_OBJS),wrstabs.obj + +BULIBS = []bucomm.obj,version.obj,filemode.obj + +ADDL_DEPS = $(BULIBS),$(BFDLIB_DEP),$(LIBIBERTY_DEP) +ADDL_LIBS = $(BULIBS),$(BFDLIB),$(LIBIBERTY) + +SIZEOBJS = $(ADDL_DEPS),size.obj + +STRINGSOBJS = $(ADDL_DEPS),strings.obj + +NMOBJS = $(ADDL_DEPS),nm.obj + +OBJDUMPOBJS = $(ADDL_DEPS),objdump.obj,prdbg.obj,$(DEBUG_OBJS),$(OPCODES_DEP) + +all: config.h size.exe strings.exe objdump.exe nm.exe + +size.exe: $(SIZEOBJS) + link/exe=$@ size.obj,$(ADDL_LIBS)$(LIBS) + +strings.exe: $(STRINGSOBJS) + link/exe=$@ strings.obj,$(ADDL_LIBS)$(LIBS) + +nm.exe: $(NMOBJS) + link/exe=$@ nm.obj,$(ADDL_LIBS)$(LIBS) + +objdump.exe: $(OBJDUMPOBJS) + link/exe=$@ objdump.obj,prdbg.obj,$(DEBUG_OBJS),$(BFDLIB),$(OPCODES),$(ADDL_LIBS)$(LIBS) + + +version.obj: version.c + $(CC) $(CFLAGS)/define=(VERSION="""$(VERSION)""") $< + +config.h: + $$ @configure + $(MAKE) -f makefile.vms "CC=$(CC)" + +[-.bfd]libbfd.olb: + $(CD) [-.bfd] + $(MAKE) -f makefile.vms "CC=$(CC)" + $(CD) [-.binutils] + +[-.libiberty]libiberty.olb: + $(CD) [-.libiberty] + $(MAKE) -f makefile.vms "CC=$(CC)" + $(CD) [-.binutils] + +[-.opcodes]libopcodes.olb: + $(CD) [-.opcodes] + $(MAKE) -f makefile.vms "CC=$(CC)" + $(CD) [-.binutils] + +clean: + $$ purge + $(RM) *.obj; + $(RM) *.exe; + +distclean: clean + $(RM) config.h; + $(RM) makefile.vms; diff --git a/binutils/maybe-ranlib.c b/binutils/maybe-ranlib.c new file mode 100644 index 0000000..f37bc0f --- /dev/null +++ b/binutils/maybe-ranlib.c @@ -0,0 +1,4 @@ +/* Linked with ar.o to flag that this program decides at runtime + (using argv[0] if it is is 'ar' or 'ranlib'. */ + +int is_ranlib = -1; diff --git a/binutils/maybe-strip.c b/binutils/maybe-strip.c new file mode 100644 index 0000000..6467c99 --- /dev/null +++ b/binutils/maybe-strip.c @@ -0,0 +1,4 @@ +/* Linked with objcopy.o to flag that this program decides at runtime + (using argv[0] if it is is 'strip' or 'objcopy'. */ + +int is_strip = -1; diff --git a/binutils/mpw-config.in b/binutils/mpw-config.in new file mode 100644 index 0000000..21a067d --- /dev/null +++ b/binutils/mpw-config.in @@ -0,0 +1,27 @@ +# Configuration fragment for binutils. + +Set target_arch `echo {target_canonical} | sed -e 's/-.*-.*//'` + +# (should canonicalize arch name) */ + +Set archname ARCH_{target_arch} + +Set underscore 0 + +If "{target_canonical}" =~ /sh-hitachi-hms/ + Set underscore 1 +End If + +Echo '# From mpw-config.in' > "{o}"mk.tmp +Echo "ARCHDEFS = -d" {archname} >> "{o}"mk.tmp +Echo "UNDERSCORE = " {underscore} >> "{o}"mk.tmp +Echo "BUILD_NLMCONV = " >> "{o}"mk.tmp +Echo "BUILD_SRCONV = " >> "{o}"mk.tmp +Echo "SYSINFO_PROG = " >> "{o}"mk.tmp +Echo "BUILD_DLLTOOL = " >> "{o}"mk.tmp +Echo '# End from mpw-config.in' >> "{o}"mk.tmp + +Echo '/* config.h. Generated by mpw-configure. */' > "{o}"config.new +Echo '#include "mpw.h"' >> "{o}"config.new + +MoveIfChange "{o}"config.new "{o}"config.h diff --git a/binutils/mpw-make.sed b/binutils/mpw-make.sed new file mode 100644 index 0000000..03abffe --- /dev/null +++ b/binutils/mpw-make.sed @@ -0,0 +1,115 @@ +# Sed commands to finish translating the binutils Unix makefile into MPW syntax. + +# Add a rule. +/^#### .*/a\ +\ +"{o}"underscore.c.o \\Option-f "{o}"underscore.c\ + +# Comment out any alias settings. +/^host_alias =/s/^/#/ +/^target_alias =/s/^/#/ + +# Whack out unused host define bits. +/HDEFINES/s/@HDEFINES@// + +# Don't build specialized tools. +/BUILD_NLMCONV/s/@BUILD_NLMCONV@// +/BUILD_SRCONV/s/@BUILD_SRCONV@// +/BUILD_DLLTOOL/s/@BUILD_DLLTOOL@// + +/UNDERSCORE/s/@UNDERSCORE@/{UNDERSCORE}/ + +# Don't need this. +/@HLDFLAGS@/s/@HLDFLAGS@// + +# Point at the libraries directly. +/@BFDLIB@/s/@BFDLIB@/::bfd:libbfd.o/ +/@OPCODES@/s/@OPCODES@/::opcodes:libopcodes.o/ + +# Whack out target makefile fragment. +/target_makefile_fragment/s/target_makefile_fragment@// + +# Fix and add to the include paths. +/^INCLUDES = .*$/s/$/ -i "{INCDIR}":mpw: -i ::extra-include:/ +/BFDDIR/s/-i {BFDDIR} /-i "{BFDDIR}": / +/INCDIR/s/-i {INCDIR} /-i "{INCDIR}": / + +# Use byacc instead of bison (for now anyway). +/BISON/s/^BISON =.*$/BISON = byacc/ +#/BISONFLAGS/s/^BISONFLAGS =.*$/BISONFLAGS = / + +# Embed the version in symbolic doublequotes that will expand to +# the right thing for each compiler. +/VERSION/s/'"{VERSION}"'/{dq}{VERSION}{dq}/ + +# '+' is a special char to MPW, don't use it ever. +/c++filt/s/c++filt/cplusfilt/ + +# All of the binutils use the same Rez file, change names to refer to it. +/^{[A-Z]*_PROG}/s/$/ "{s}"mac-binutils.r/ +/{[A-Z]*_PROG}\.r/s/{[A-Z]*_PROG}\.r/mac-binutils.r/ + +# There are auto-generated references to BFD .h files that are not +# in the objdir (like bfd.h) but are in the source dir. +/::bfd:lib/s/::bfd:lib\([a-z]*\)\.h/{BFDDIR}:lib\1.h/g + +# Fix the locations of generated files. +/config/s/"{s}"config\.h/"{o}"config.h/g +/config/s/^config\.h/"{o}"config\.h/ +/underscore/s/"{s}"underscore\.c/"{o}"underscore.c/g +/underscore/s/^underscore\.c/"{o}"underscore\.c/ + +# Fix paths to generated source files. +/lex.yy.c/s/"{s}"lex\.yy\.c/"{o}"lex.yy.c/g +/lex.yy.c/s/^lex\.yy\.c/"{o}"lex.yy.c/ +/arlex.c/s/"{s}"arlex\.c/"{o}"arlex.c/g +/arlex.c/s/^arlex\.c/"{o}"arlex.c/ +/y.tab.c/s/"{s}"y\.tab\.c/"{o}"y.tab.c/g +/y.tab.c/s/^y\.tab\.c/"{o}"y.tab.c/ +/arparse.c/s/"{s}"arparse\.c/"{o}"arparse.c/g +/arparse.c/s/^arparse\.c/"{o}"arparse.c/ +/y.tab.h/s/"{s}"y\.tab\.h/"{o}"y.tab.h/g +/y.tab.h/s/^y\.tab\.h/"{o}"y.tab.h/ +/arparse.h/s/"{s}"arparse\.h/"{o}"arparse.h/g +/arparse.h/s/^arparse\.h/"{o}"arparse.h/ + +/"{s}"{INCDIR}/s/"{s}"{INCDIR}/"{INCDIR}"/g + +# The generated lexer may include an ifdef for older Mac compilers that +# needs to work with newer compilers also. +/lex.yy.c/s/Rename -y \([^ ]*\) \([^ ]*\)$/sed -e 's,ifdef macintosh,if defined(macintosh) || defined(__MWERKS__),' \1 > \2/ + +# Fix an over-eagerness. +/echo.*WARNING.*This file/s/'.*'/' '/ + +# Add a "stamps" target. +$a\ +stamps \\Option-f stamp-under\ + +/^install \\Option-f /,/^$/c\ +install \\Option-f all install-only\ +\ +install-only \\Option-f\ + NewFolderRecursive "{bindir}"\ + # Need to copy all the tools\ + For prog in {PROGS}\ + Set progname `echo {prog} | sed -e 's/.new//'`\ + Duplicate -y :{prog} "{bindir}"{progname}\ + End For\ + + +/true/s/ ; @true$// + +# dot files are trouble, remove them and their actions. +/^\.dep/,/^$/d + +# Remove un-useful targets. +/^Makefile \\Option-f/,/^$/d +/^"{o}"config.h \\Option-f/,/^$/d +/^config.status \\Option-f/,/^$/d + +# Don't try to make the demangler's man page, it's useless. +/^{DEMANGLER_PROG}\.1 \\Option-f/,/^$/d +# Don't depend on it either. +/{DEMANGLER_PROG}/s/ {DEMANGLER_PROG}\.1// + diff --git a/binutils/nlmconv.1 b/binutils/nlmconv.1 new file mode 100644 index 0000000..cbc3aed --- /dev/null +++ b/binutils/nlmconv.1 @@ -0,0 +1,110 @@ +.\" Copyright (c) 1991, 1996 Free Software Foundation +.\" See section COPYING for conditions for redistribution +.TH nlmconv 1 "March 1996" "cygnus support" "GNU Development Tools" +.de BP +.sp +.ti \-.2i +\(** +.. + +.SH NAME +nlmconv \- converts object code into an NLM + +.SH SYNOPSIS +.hy 0 +.na +.TP +.B nlmconv +.RB "[\|" \-I\ \fIbfdname\fB\ |\ \-\-input\-target=\fIbfdname\fR "\|]" +.RB "[\|" \-O\ \fIbfdname\fB\ |\ \-\-output\-target=\fIbfdname\fR "\|]" +.RB "[\|" \-T\ \fIheaderfile\fB\ |\ \-\-header\-file=\fIheaderfile\fR "\|]" +.RB "[\|" \-V\ |\ \-\-version\fR "\|]" +.RB "[\|" \-\-help\fR "\|]" +.B infile +.B outfile +.SH DESCRIPTION +.B nlmconv +converts the relocatable object file +.B infile +into the NetWare Loadable Module +.BR outfile , +optionally reading +.I headerfile +for NLM header information. For instructions on writing the NLM +command file language used in header files, see +.IR "The NetWare Tool Maker Specification Manual" , +available from Novell, Inc. +.B nlmconv +currently works with i386 object files in +.BR COFF , +.BR ELF , +or +.B a.out +format, and with SPARC object files in +.B ELF +or +.B a.out +format. +.br +.B nlmconv +uses the GNU Binary File Descriptor library to read +.IR infile . +.SH OPTIONS +.TP +.B \-I \fIbfdname\fR, \fB\-\-input\-target=\fIbfdname +Consider the source file's object format to be +.IR bfdname , +rather than attempting to deduce it. +.TP +.B \-O \fIbfdname\fR, \fB\-\-output\-target=\fIbfdname +Write the output file using the object format +.IR bfdname . +.B nlmconv +infers the output format based on the input format, e.g. for an i386 +input file the output format is +.IR nlm32\-i386 . +.TP +.B \-T \fIheaderfile\fR, \fB\-\-header\-file=\fIheaderfile +Reads +.I headerfile +for NLM header information. For instructions on writing the NLM +command file language used in header files, see +.IR "The NetWare Tool Maker Specification Manual" , +available from Novell, Inc. +.TP +.B \-V\fR, \fB\-\-version +Show the version number of +.B nlmconv +and exit. +.TP +.B \-h\fR, \fB\-\-help +Show a summary of the options to +.B nlmconv +and exit. +.SH "SEE ALSO" +.RB "`\|" binutils "\|'" +entry in +.B +info\c +\&; +.I +The GNU Binary Utilities\c +\&, Roland H. Pesch (June 1993). + +.SH COPYING +Copyright (c) 1993 Free Software Foundation, Inc. +.PP +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. +.PP +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the +entire resulting derived work is distributed under the terms of a +permission notice identical to this one. +.PP +Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be included in +translations approved by the Free Software Foundation instead of in +the original English. diff --git a/binutils/nlmconv.c b/binutils/nlmconv.c new file mode 100644 index 0000000..f1c8b6c --- /dev/null +++ b/binutils/nlmconv.c @@ -0,0 +1,2212 @@ +/* nlmconv.c -- NLM conversion program + Copyright (C) 1993, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Ian Lance Taylor <ian@cygnus.com>. + + This program can be used to convert any appropriate object file + into a NetWare Loadable Module (an NLM). It will accept a linker + specification file which is identical to that accepted by the + NetWare linker, NLMLINK. */ + +/* AIX requires this to be the first thing in the file. */ +#ifndef __GNUC__ +# ifdef _AIX + #pragma alloca +#endif +#endif + +#include "bfd.h" +#include "libiberty.h" +#include "bucomm.h" + +#include <ansidecl.h> +#include <time.h> +#include <ctype.h> +#include <sys/stat.h> +#include <sys/file.h> +#include <assert.h> +#include <getopt.h> + +/* Internal BFD NLM header. */ +#include "libnlm.h" +#include "nlmconv.h" + +#ifdef NLMCONV_ALPHA +#include "coff/sym.h" +#include "coff/ecoff.h" +#endif + +/* If strerror is just a macro, we want to use the one from libiberty + since it will handle undefined values. */ +#undef strerror +extern char *strerror (); + +#ifndef localtime +extern struct tm *localtime (); +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +#ifndef R_OK +#define R_OK 4 +#define W_OK 2 +#define X_OK 1 +#endif + +/* Global variables. */ + +/* The name used to invoke the program. */ +char *program_name; + +/* Local variables. */ + +/* Whether to print out debugging information (currently just controls + whether it prints the linker command if there is one). */ +static int debug; + +/* The symbol table. */ +static asymbol **symbols; + +/* A section we create in the output file to hold pointers to where + the sections of the input file end up. We will put a pointer to + this section in the NLM header. These is an entry for each input + section. The format is + null terminated section name + zeroes to adjust to 4 byte boundary + 4 byte section data file pointer + 4 byte section size + We don't need a version number. The way we find this information + is by finding a stamp in the NLM header information. If we need to + change the format of this information, we can simply change the + stamp. */ +static asection *secsec; + +/* A temporary file name to be unlinked on exit. Actually, for most + errors, we leave it around. It's not clear whether that is helpful + or not. */ +static char *unlink_on_exit; + +/* The list of long options. */ +static struct option long_options[] = +{ + { "debug", no_argument, 0, 'd' }, + { "header-file", required_argument, 0, 'T' }, + { "help", no_argument, 0, 'h' }, + { "input-target", required_argument, 0, 'I' }, + { "input-format", required_argument, 0, 'I' }, /* Obsolete */ + { "linker", required_argument, 0, 'l' }, + { "output-target", required_argument, 0, 'O' }, + { "output-format", required_argument, 0, 'O' }, /* Obsolete */ + { "version", no_argument, 0, 'V' }, + { NULL, no_argument, 0, 0 } +}; + +/* Local routines. */ + +static void show_help PARAMS ((void)); +static void show_usage PARAMS ((FILE *, int)); +static const char *select_output_format PARAMS ((enum bfd_architecture, + unsigned long, boolean)); +static void setup_sections PARAMS ((bfd *, asection *, PTR)); +static void copy_sections PARAMS ((bfd *, asection *, PTR)); +static void mangle_relocs PARAMS ((bfd *, asection *, arelent ***, + long *, char *, + bfd_size_type)); +static void default_mangle_relocs PARAMS ((bfd *, asection *, arelent ***, + long *, char *, + bfd_size_type)); +static char *link_inputs PARAMS ((struct string_list *, char *)); + +#ifdef NLMCONV_I386 +static void i386_mangle_relocs PARAMS ((bfd *, asection *, arelent ***, + long *, char *, + bfd_size_type)); +#endif + +#ifdef NLMCONV_ALPHA +static void alpha_mangle_relocs PARAMS ((bfd *, asection *, arelent ***, + long *, char *, + bfd_size_type)); +#endif + +#ifdef NLMCONV_POWERPC +static void powerpc_build_stubs PARAMS ((bfd *, bfd *, asymbol ***, long *)); +static void powerpc_resolve_stubs PARAMS ((bfd *, bfd *)); +static void powerpc_mangle_relocs PARAMS ((bfd *, asection *, arelent ***, + long *, char *, + bfd_size_type)); +#endif + +/* The main routine. */ + +int +main (argc, argv) + int argc; + char **argv; +{ + int opt; + char *input_file = NULL; + const char *input_format = NULL; + const char *output_format = NULL; + const char *header_file = NULL; + char *ld_arg = NULL; + Nlm_Internal_Fixed_Header fixed_hdr_struct; + Nlm_Internal_Variable_Header var_hdr_struct; + Nlm_Internal_Version_Header version_hdr_struct; + Nlm_Internal_Copyright_Header copyright_hdr_struct; + Nlm_Internal_Extended_Header extended_hdr_struct; + bfd *inbfd; + bfd *outbfd; + asymbol **newsyms, **outsyms; + long symcount, newsymalloc, newsymcount; + long symsize; + asection *text_sec, *bss_sec, *data_sec; + bfd_vma vma; + bfd_size_type align; + asymbol *endsym; + long i; + char inlead, outlead; + boolean gotstart, gotexit, gotcheck; + struct stat st; + FILE *custom_data = NULL; + FILE *help_data = NULL; + FILE *message_data = NULL; + FILE *rpc_data = NULL; + FILE *shared_data = NULL; + size_t custom_size = 0; + size_t help_size = 0; + size_t message_size = 0; + size_t module_size = 0; + size_t rpc_size = 0; + asection *custom_section = NULL; + asection *help_section = NULL; + asection *message_section = NULL; + asection *module_section = NULL; + asection *rpc_section = NULL; + asection *shared_section = NULL; + bfd *sharedbfd; + size_t shared_offset = 0; + size_t shared_size = 0; + Nlm_Internal_Fixed_Header sharedhdr; + int len; + char *modname; + char **matching; + +#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) + setlocale (LC_MESSAGES, ""); +#endif + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + + program_name = argv[0]; + xmalloc_set_program_name (program_name); + + bfd_init (); + set_default_bfd_target (); + + while ((opt = getopt_long (argc, argv, "dhI:l:O:T:V", long_options, + (int *) NULL)) + != EOF) + { + switch (opt) + { + case 'd': + debug = 1; + break; + case 'h': + show_help (); + /*NOTREACHED*/ + case 'I': + input_format = optarg; + break; + case 'l': + ld_arg = optarg; + break; + case 'O': + output_format = optarg; + break; + case 'T': + header_file = optarg; + break; + case 'V': + print_version ("nlmconv"); + /*NOTREACHED*/ + case 0: + break; + default: + show_usage (stderr, 1); + /*NOTREACHED*/ + } + } + + /* The input and output files may be named on the command line. */ + output_file = NULL; + if (optind < argc) + { + input_file = argv[optind]; + ++optind; + if (optind < argc) + { + output_file = argv[optind]; + ++optind; + if (optind < argc) + show_usage (stderr, 1); + if (strcmp (input_file, output_file) == 0) + { + fprintf (stderr, + _("%s: input and output files must be different\n"), + program_name); + exit (1); + } + } + } + + /* Initialize the header information to default values. */ + fixed_hdr = &fixed_hdr_struct; + memset ((PTR) &fixed_hdr_struct, 0, sizeof fixed_hdr_struct); + var_hdr = &var_hdr_struct; + memset ((PTR) &var_hdr_struct, 0, sizeof var_hdr_struct); + version_hdr = &version_hdr_struct; + memset ((PTR) &version_hdr_struct, 0, sizeof version_hdr_struct); + copyright_hdr = ©right_hdr_struct; + memset ((PTR) ©right_hdr_struct, 0, sizeof copyright_hdr_struct); + extended_hdr = &extended_hdr_struct; + memset ((PTR) &extended_hdr_struct, 0, sizeof extended_hdr_struct); + check_procedure = NULL; + custom_file = NULL; + debug_info = false; + exit_procedure = "_Stop"; + export_symbols = NULL; + map_file = NULL; + full_map = false; + help_file = NULL; + import_symbols = NULL; + message_file = NULL; + modules = NULL; + sharelib_file = NULL; + start_procedure = "_Prelude"; + verbose = false; + rpc_file = NULL; + + parse_errors = 0; + + /* Parse the header file (if there is one). */ + if (header_file != NULL) + { + if (! nlmlex_file (header_file) + || yyparse () != 0 + || parse_errors != 0) + exit (1); + } + + if (input_files != NULL) + { + if (input_file != NULL) + { + fprintf (stderr, + _("%s: input file named both on command line and with INPUT\n"), + program_name); + exit (1); + } + if (input_files->next == NULL) + input_file = input_files->string; + else + input_file = link_inputs (input_files, ld_arg); + } + else if (input_file == NULL) + { + fprintf (stderr, _("%s: no input file\n"), program_name); + show_usage (stderr, 1); + } + + inbfd = bfd_openr (input_file, input_format); + if (inbfd == NULL) + bfd_fatal (input_file); + + if (! bfd_check_format_matches (inbfd, bfd_object, &matching)) + { + bfd_nonfatal (input_file); + if (bfd_get_error () == bfd_error_file_ambiguously_recognized) + { + list_matching_formats (matching); + free (matching); + } + exit (1); + } + + if (output_format == NULL) + output_format = select_output_format (bfd_get_arch (inbfd), + bfd_get_mach (inbfd), + bfd_big_endian (inbfd)); + + assert (output_format != NULL); + + /* Use the output file named on the command line if it exists. + Otherwise use the file named in the OUTPUT statement. */ + if (output_file == NULL) + { + fprintf (stderr, _("%s: no name for output file\n"), + program_name); + show_usage (stderr, 1); + } + + outbfd = bfd_openw (output_file, output_format); + if (outbfd == NULL) + bfd_fatal (output_file); + if (! bfd_set_format (outbfd, bfd_object)) + bfd_fatal (output_file); + + assert (bfd_get_flavour (outbfd) == bfd_target_nlm_flavour); + + if (bfd_arch_get_compatible (inbfd, outbfd) == NULL) + fprintf (stderr, + _("%s: warning:input and output formats are not compatible\n"), + program_name); + + /* Move the values read from the command file into outbfd. */ + *nlm_fixed_header (outbfd) = fixed_hdr_struct; + *nlm_variable_header (outbfd) = var_hdr_struct; + *nlm_version_header (outbfd) = version_hdr_struct; + *nlm_copyright_header (outbfd) = copyright_hdr_struct; + *nlm_extended_header (outbfd) = extended_hdr_struct; + + /* Start copying the input BFD to the output BFD. */ + if (! bfd_set_file_flags (outbfd, bfd_get_file_flags (inbfd))) + bfd_fatal (bfd_get_filename (outbfd)); + + symsize = bfd_get_symtab_upper_bound (inbfd); + if (symsize < 0) + bfd_fatal (input_file); + symbols = (asymbol **) xmalloc (symsize); + symcount = bfd_canonicalize_symtab (inbfd, symbols); + if (symcount < 0) + bfd_fatal (input_file); + + /* Make sure we have a .bss section. */ + bss_sec = bfd_get_section_by_name (outbfd, NLM_UNINITIALIZED_DATA_NAME); + if (bss_sec == NULL) + { + bss_sec = bfd_make_section (outbfd, NLM_UNINITIALIZED_DATA_NAME); + if (bss_sec == NULL + || ! bfd_set_section_flags (outbfd, bss_sec, SEC_ALLOC) + || ! bfd_set_section_alignment (outbfd, bss_sec, 1)) + bfd_fatal (_("make .bss section")); + } + + /* We store the original section names in the .nlmsections section, + so that programs which understand it can resurrect the original + sections from the NLM. We will put a pointer to .nlmsections in + the NLM header area. */ + secsec = bfd_make_section (outbfd, ".nlmsections"); + if (secsec == NULL) + bfd_fatal (_("make .nlmsections section")); + if (! bfd_set_section_flags (outbfd, secsec, SEC_HAS_CONTENTS)) + bfd_fatal (_("set .nlmsections flags")); + +#ifdef NLMCONV_POWERPC + /* For PowerPC NetWare we need to build stubs for calls to undefined + symbols. Because each stub requires an entry in the TOC section + which must be at the same location as other entries in the TOC + section, we must do this before determining where the TOC section + goes in setup_sections. */ + if (bfd_get_arch (inbfd) == bfd_arch_powerpc) + powerpc_build_stubs (inbfd, outbfd, &symbols, &symcount); +#endif + + /* Set up the sections. */ + bfd_map_over_sections (inbfd, setup_sections, (PTR) outbfd); + + text_sec = bfd_get_section_by_name (outbfd, NLM_CODE_NAME); + + /* The .bss section immediately follows the .data section. */ + data_sec = bfd_get_section_by_name (outbfd, NLM_INITIALIZED_DATA_NAME); + if (data_sec != NULL) + { + bfd_size_type add; + + vma = bfd_get_section_size_before_reloc (data_sec); + align = 1 << bss_sec->alignment_power; + add = ((vma + align - 1) &~ (align - 1)) - vma; + vma += add; + if (! bfd_set_section_vma (outbfd, bss_sec, vma)) + bfd_fatal (_("set .bss vma")); + if (add != 0) + { + bfd_size_type data_size; + + data_size = bfd_get_section_size_before_reloc (data_sec); + if (! bfd_set_section_size (outbfd, data_sec, data_size + add)) + bfd_fatal (_("set .data size")); + } + } + + /* Adjust symbol information. */ + inlead = bfd_get_symbol_leading_char (inbfd); + outlead = bfd_get_symbol_leading_char (outbfd); + gotstart = false; + gotexit = false; + gotcheck = false; + newsymalloc = 10; + newsyms = (asymbol **) xmalloc (newsymalloc * sizeof (asymbol *)); + newsymcount = 0; + endsym = NULL; + for (i = 0; i < symcount; i++) + { + register asymbol *sym; + + sym = symbols[i]; + + /* Add or remove a leading underscore. */ + if (inlead != outlead) + { + if (inlead != '\0') + { + if (bfd_asymbol_name (sym)[0] == inlead) + { + if (outlead == '\0') + ++sym->name; + else + { + char *new; + + new = xmalloc (strlen (bfd_asymbol_name (sym)) + 1); + new[0] = outlead; + strcpy (new + 1, bfd_asymbol_name (sym) + 1); + sym->name = new; + } + } + } + else + { + char *new; + + new = xmalloc (strlen (bfd_asymbol_name (sym)) + 2); + new[0] = outlead; + strcpy (new + 1, bfd_asymbol_name (sym)); + sym->name = new; + } + } + + /* NLM's have an uninitialized data section, but they do not + have a common section in the Unix sense. Move all common + symbols into the .bss section, and mark them as exported. */ + if (bfd_is_com_section (bfd_get_section (sym))) + { + bfd_vma size; + + sym->section = bss_sec; + size = sym->value; + sym->value = bss_sec->_raw_size; + bss_sec->_raw_size += size; + align = 1 << bss_sec->alignment_power; + bss_sec->_raw_size = (bss_sec->_raw_size + align - 1) &~ (align - 1); + sym->flags |= BSF_EXPORT | BSF_GLOBAL; + } + else if (bfd_get_section (sym)->output_section != NULL) + { + /* Move the symbol into the output section. */ + sym->value += bfd_get_section (sym)->output_offset; + sym->section = bfd_get_section (sym)->output_section; + /* This is no longer a section symbol. */ + sym->flags &=~ BSF_SECTION_SYM; + } + + /* Force _edata and _end to be defined. This would normally be + done by the linker, but the manipulation of the common + symbols will confuse it. */ + if ((sym->flags & BSF_DEBUGGING) == 0 + && bfd_asymbol_name (sym)[0] == '_' + && bfd_is_und_section (bfd_get_section (sym))) + { + if (strcmp (bfd_asymbol_name (sym), "_edata") == 0) + { + sym->section = bss_sec; + sym->value = 0; + } + if (strcmp (bfd_asymbol_name (sym), "_end") == 0) + { + sym->section = bss_sec; + endsym = sym; + } + +#ifdef NLMCONV_POWERPC + /* For PowerPC NetWare, we define __GOT0. This is the start + of the .got section. */ + if (bfd_get_arch (inbfd) == bfd_arch_powerpc + && strcmp (bfd_asymbol_name (sym), "__GOT0") == 0) + { + asection *got_sec; + + got_sec = bfd_get_section_by_name (inbfd, ".got"); + assert (got_sec != (asection *) NULL); + sym->value = got_sec->output_offset; + sym->section = got_sec->output_section; + } +#endif + } + + /* If this is a global symbol, check the export list. */ + if ((sym->flags & (BSF_EXPORT | BSF_GLOBAL)) != 0) + { + register struct string_list *l; + int found_simple; + + /* Unfortunately, a symbol can appear multiple times on the + export list, with and without prefixes. */ + found_simple = 0; + for (l = export_symbols; l != NULL; l = l->next) + { + if (strcmp (l->string, bfd_asymbol_name (sym)) == 0) + found_simple = 1; + else + { + char *zbase; + + zbase = strchr (l->string, '@'); + if (zbase != NULL + && strcmp (zbase + 1, bfd_asymbol_name (sym)) == 0) + { + /* We must add a symbol with this prefix. */ + if (newsymcount >= newsymalloc) + { + newsymalloc += 10; + newsyms = ((asymbol **) + xrealloc ((PTR) newsyms, + (newsymalloc + * sizeof (asymbol *)))); + } + newsyms[newsymcount] = + (asymbol *) xmalloc (sizeof (asymbol)); + *newsyms[newsymcount] = *sym; + newsyms[newsymcount]->name = l->string; + ++newsymcount; + } + } + } + if (! found_simple) + { + /* The unmodified symbol is actually not exported at + all. */ + sym->flags &=~ (BSF_GLOBAL | BSF_EXPORT); + sym->flags |= BSF_LOCAL; + } + } + + /* If it's an undefined symbol, see if it's on the import list. + Change the prefix if necessary. */ + if (bfd_is_und_section (bfd_get_section (sym))) + { + register struct string_list *l; + + for (l = import_symbols; l != NULL; l = l->next) + { + if (strcmp (l->string, bfd_asymbol_name (sym)) == 0) + break; + else + { + char *zbase; + + zbase = strchr (l->string, '@'); + if (zbase != NULL + && strcmp (zbase + 1, bfd_asymbol_name (sym)) == 0) + { + sym->name = l->string; + break; + } + } + } + if (l == NULL) + fprintf (stderr, + _("%s: warning: symbol %s imported but not in import list\n"), + program_name, bfd_asymbol_name (sym)); + } + + /* See if it's one of the special named symbols. */ + if ((sym->flags & BSF_DEBUGGING) == 0) + { + bfd_vma val; + + /* FIXME: If these symbols are not in the .text section, we + add the .text section size to the value. This may not be + correct for all targets. I'm not sure how this should + really be handled. */ + if (strcmp (bfd_asymbol_name (sym), start_procedure) == 0) + { + val = bfd_asymbol_value (sym); + if (bfd_get_section (sym) == data_sec + && text_sec != (asection *) NULL) + val += bfd_section_size (outbfd, text_sec); + if (! bfd_set_start_address (outbfd, val)) + bfd_fatal (_("set start address")); + gotstart = true; + } + if (strcmp (bfd_asymbol_name (sym), exit_procedure) == 0) + { + val = bfd_asymbol_value (sym); + if (bfd_get_section (sym) == data_sec + && text_sec != (asection *) NULL) + val += bfd_section_size (outbfd, text_sec); + nlm_fixed_header (outbfd)->exitProcedureOffset = val; + gotexit = true; + } + if (check_procedure != NULL + && strcmp (bfd_asymbol_name (sym), check_procedure) == 0) + { + val = bfd_asymbol_value (sym); + if (bfd_get_section (sym) == data_sec + && text_sec != (asection *) NULL) + val += bfd_section_size (outbfd, text_sec); + nlm_fixed_header (outbfd)->checkUnloadProcedureOffset = val; + gotcheck = true; + } + } + } + + if (endsym != NULL) + { + endsym->value = bfd_get_section_size_before_reloc (bss_sec); + + /* FIXME: If any relocs referring to _end use inplace addends, + then I think they need to be updated. This is handled by + i386_mangle_relocs. Is it needed for any other object + formats? */ + } + + if (newsymcount == 0) + outsyms = symbols; + else + { + outsyms = (asymbol **) xmalloc ((symcount + newsymcount + 1) + * sizeof (asymbol *)); + memcpy (outsyms, symbols, symcount * sizeof (asymbol *)); + memcpy (outsyms + symcount, newsyms, newsymcount * sizeof (asymbol *)); + outsyms[symcount + newsymcount] = NULL; + } + + bfd_set_symtab (outbfd, outsyms, symcount + newsymcount); + + if (! gotstart) + fprintf (stderr, _("%s: warning: START procedure %s not defined\n"), + program_name, start_procedure); + if (! gotexit) + fprintf (stderr, _("%s: warning: EXIT procedure %s not defined\n"), + program_name, exit_procedure); + if (check_procedure != NULL + && ! gotcheck) + fprintf (stderr, _("%s: warning: CHECK procedure %s not defined\n"), + program_name, check_procedure); + + /* Add additional sections required for the header information. */ + if (custom_file != NULL) + { + custom_data = fopen (custom_file, "r"); + if (custom_data == NULL + || fstat (fileno (custom_data), &st) < 0) + { + fprintf (stderr, "%s:%s: %s\n", program_name, custom_file, + strerror (errno)); + custom_file = NULL; + } + else + { + custom_size = st.st_size; + custom_section = bfd_make_section (outbfd, ".nlmcustom"); + if (custom_section == NULL + || ! bfd_set_section_size (outbfd, custom_section, custom_size) + || ! bfd_set_section_flags (outbfd, custom_section, + SEC_HAS_CONTENTS)) + bfd_fatal (_("custom section")); + } + } + if (help_file != NULL) + { + help_data = fopen (help_file, "r"); + if (help_data == NULL + || fstat (fileno (help_data), &st) < 0) + { + fprintf (stderr, "%s:%s: %s\n", program_name, help_file, + strerror (errno)); + help_file = NULL; + } + else + { + help_size = st.st_size; + help_section = bfd_make_section (outbfd, ".nlmhelp"); + if (help_section == NULL + || ! bfd_set_section_size (outbfd, help_section, help_size) + || ! bfd_set_section_flags (outbfd, help_section, + SEC_HAS_CONTENTS)) + bfd_fatal (_("help section")); + strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8); + } + } + if (message_file != NULL) + { + message_data = fopen (message_file, "r"); + if (message_data == NULL + || fstat (fileno (message_data), &st) < 0) + { + fprintf (stderr, "%s:%s: %s\n", program_name, message_file, + strerror (errno)); + message_file = NULL; + } + else + { + message_size = st.st_size; + message_section = bfd_make_section (outbfd, ".nlmmessages"); + if (message_section == NULL + || ! bfd_set_section_size (outbfd, message_section, message_size) + || ! bfd_set_section_flags (outbfd, message_section, + SEC_HAS_CONTENTS)) + bfd_fatal (_("message section")); + strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8); + } + } + if (modules != NULL) + { + struct string_list *l; + + module_size = 0; + for (l = modules; l != NULL; l = l->next) + module_size += strlen (l->string) + 1; + module_section = bfd_make_section (outbfd, ".nlmmodules"); + if (module_section == NULL + || ! bfd_set_section_size (outbfd, module_section, module_size) + || ! bfd_set_section_flags (outbfd, module_section, + SEC_HAS_CONTENTS)) + bfd_fatal (_("module section")); + } + if (rpc_file != NULL) + { + rpc_data = fopen (rpc_file, "r"); + if (rpc_data == NULL + || fstat (fileno (rpc_data), &st) < 0) + { + fprintf (stderr, "%s:%s: %s\n", program_name, rpc_file, + strerror (errno)); + rpc_file = NULL; + } + else + { + rpc_size = st.st_size; + rpc_section = bfd_make_section (outbfd, ".nlmrpc"); + if (rpc_section == NULL + || ! bfd_set_section_size (outbfd, rpc_section, rpc_size) + || ! bfd_set_section_flags (outbfd, rpc_section, + SEC_HAS_CONTENTS)) + bfd_fatal (_("rpc section")); + strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8); + } + } + if (sharelib_file != NULL) + { + sharedbfd = bfd_openr (sharelib_file, output_format); + if (sharedbfd == NULL + || ! bfd_check_format (sharedbfd, bfd_object)) + { + fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file, + bfd_errmsg (bfd_get_error ())); + sharelib_file = NULL; + } + else + { + sharedhdr = *nlm_fixed_header (sharedbfd); + bfd_close (sharedbfd); + shared_data = fopen (sharelib_file, "r"); + if (shared_data == NULL + || (fstat (fileno (shared_data), &st) < 0)) + { + fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file, + strerror (errno)); + sharelib_file = NULL; + } + else + { + /* If we were clever, we could just copy out the + sections of the shared library which we actually + need. However, we would have to figure out the sizes + of the external and public information, and that can + not be done without reading through them. */ + if (sharedhdr.uninitializedDataSize > 0) + { + /* There is no place to record this information. */ + fprintf (stderr, + _("%s:%s: warning: shared libraries can not have uninitialized data\n"), + program_name, sharelib_file); + } + shared_offset = st.st_size; + if (shared_offset > (size_t) sharedhdr.codeImageOffset) + shared_offset = sharedhdr.codeImageOffset; + if (shared_offset > (size_t) sharedhdr.dataImageOffset) + shared_offset = sharedhdr.dataImageOffset; + if (shared_offset > (size_t) sharedhdr.relocationFixupOffset) + shared_offset = sharedhdr.relocationFixupOffset; + if (shared_offset > (size_t) sharedhdr.externalReferencesOffset) + shared_offset = sharedhdr.externalReferencesOffset; + if (shared_offset > (size_t) sharedhdr.publicsOffset) + shared_offset = sharedhdr.publicsOffset; + shared_size = st.st_size - shared_offset; + shared_section = bfd_make_section (outbfd, ".nlmshared"); + if (shared_section == NULL + || ! bfd_set_section_size (outbfd, shared_section, + shared_size) + || ! bfd_set_section_flags (outbfd, shared_section, + SEC_HAS_CONTENTS)) + bfd_fatal (_("shared section")); + strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8); + } + } + } + + /* Check whether a version was given. */ + if (strncmp (version_hdr->stamp, "VeRsIoN#", 8) != 0) + fprintf (stderr, _("%s: warning: No version number given\n"), + program_name); + + /* At least for now, always create an extended header, because that + is what NLMLINK does. */ + strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8); + + strncpy (nlm_cygnus_ext_header (outbfd)->stamp, "CyGnUsEx", 8); + + /* If the date was not given, force it in. */ + if (nlm_version_header (outbfd)->month == 0 + && nlm_version_header (outbfd)->day == 0 + && nlm_version_header (outbfd)->year == 0) + { + time_t now; + struct tm *ptm; + + time (&now); + ptm = localtime (&now); + nlm_version_header (outbfd)->month = ptm->tm_mon + 1; + nlm_version_header (outbfd)->day = ptm->tm_mday; + nlm_version_header (outbfd)->year = ptm->tm_year + 1900; + strncpy (version_hdr->stamp, "VeRsIoN#", 8); + } + +#ifdef NLMCONV_POWERPC + /* Resolve the stubs we build for PowerPC NetWare. */ + if (bfd_get_arch (inbfd) == bfd_arch_powerpc) + powerpc_resolve_stubs (inbfd, outbfd); +#endif + + /* Copy over the sections. */ + bfd_map_over_sections (inbfd, copy_sections, (PTR) outbfd); + + /* Finish up the header information. */ + if (custom_file != NULL) + { + PTR data; + + data = xmalloc (custom_size); + if (fread (data, 1, custom_size, custom_data) != custom_size) + fprintf (stderr, _("%s:%s: read: %s\n"), program_name, custom_file, + strerror (errno)); + else + { + if (! bfd_set_section_contents (outbfd, custom_section, data, + (file_ptr) 0, custom_size)) + bfd_fatal (_("custom section")); + nlm_fixed_header (outbfd)->customDataOffset = + custom_section->filepos; + nlm_fixed_header (outbfd)->customDataSize = custom_size; + } + free (data); + } + if (! debug_info) + { + /* As a special hack, the backend recognizes a debugInfoOffset + of -1 to mean that it should not output any debugging + information. This can not be handling by fiddling with the + symbol table because exported symbols appear in both the + export information and the debugging information. */ + nlm_fixed_header (outbfd)->debugInfoOffset = (file_ptr) -1; + } + if (map_file != NULL) + fprintf (stderr, + _("%s: warning: MAP and FULLMAP are not supported; try ld -M\n"), + program_name); + if (help_file != NULL) + { + PTR data; + + data = xmalloc (help_size); + if (fread (data, 1, help_size, help_data) != help_size) + fprintf (stderr, _("%s:%s: read: %s\n"), program_name, help_file, + strerror (errno)); + else + { + if (! bfd_set_section_contents (outbfd, help_section, data, + (file_ptr) 0, help_size)) + bfd_fatal (_("help section")); + nlm_extended_header (outbfd)->helpFileOffset = + help_section->filepos; + nlm_extended_header (outbfd)->helpFileLength = help_size; + } + free (data); + } + if (message_file != NULL) + { + PTR data; + + data = xmalloc (message_size); + if (fread (data, 1, message_size, message_data) != message_size) + fprintf (stderr, _("%s:%s: read: %s\n"), program_name, message_file, + strerror (errno)); + else + { + if (! bfd_set_section_contents (outbfd, message_section, data, + (file_ptr) 0, message_size)) + bfd_fatal (_("message section")); + nlm_extended_header (outbfd)->messageFileOffset = + message_section->filepos; + nlm_extended_header (outbfd)->messageFileLength = message_size; + + /* FIXME: Are these offsets correct on all platforms? Are + they 32 bits on all platforms? What endianness? */ + nlm_extended_header (outbfd)->languageID = + bfd_h_get_32 (outbfd, (bfd_byte *) data + 106); + nlm_extended_header (outbfd)->messageCount = + bfd_h_get_32 (outbfd, (bfd_byte *) data + 110); + } + free (data); + } + if (modules != NULL) + { + PTR data; + unsigned char *set; + struct string_list *l; + bfd_size_type c; + + data = xmalloc (module_size); + c = 0; + set = (unsigned char *) data; + for (l = modules; l != NULL; l = l->next) + { + *set = strlen (l->string); + strncpy (set + 1, l->string, *set); + set += *set + 1; + ++c; + } + if (! bfd_set_section_contents (outbfd, module_section, data, + (file_ptr) 0, module_size)) + bfd_fatal (_("module section")); + nlm_fixed_header (outbfd)->moduleDependencyOffset = + module_section->filepos; + nlm_fixed_header (outbfd)->numberOfModuleDependencies = c; + } + if (rpc_file != NULL) + { + PTR data; + + data = xmalloc (rpc_size); + if (fread (data, 1, rpc_size, rpc_data) != rpc_size) + fprintf (stderr, _("%s:%s: read: %s\n"), program_name, rpc_file, + strerror (errno)); + else + { + if (! bfd_set_section_contents (outbfd, rpc_section, data, + (file_ptr) 0, rpc_size)) + bfd_fatal (_("rpc section")); + nlm_extended_header (outbfd)->RPCDataOffset = + rpc_section->filepos; + nlm_extended_header (outbfd)->RPCDataLength = rpc_size; + } + free (data); + } + if (sharelib_file != NULL) + { + PTR data; + + data = xmalloc (shared_size); + if (fseek (shared_data, shared_offset, SEEK_SET) != 0 + || fread (data, 1, shared_size, shared_data) != shared_size) + fprintf (stderr, _("%s:%s: read: %s\n"), program_name, sharelib_file, + strerror (errno)); + else + { + if (! bfd_set_section_contents (outbfd, shared_section, data, + (file_ptr) 0, shared_size)) + bfd_fatal (_("shared section")); + } + nlm_extended_header (outbfd)->sharedCodeOffset = + sharedhdr.codeImageOffset - shared_offset + shared_section->filepos; + nlm_extended_header (outbfd)->sharedCodeLength = + sharedhdr.codeImageSize; + nlm_extended_header (outbfd)->sharedDataOffset = + sharedhdr.dataImageOffset - shared_offset + shared_section->filepos; + nlm_extended_header (outbfd)->sharedDataLength = + sharedhdr.dataImageSize; + nlm_extended_header (outbfd)->sharedRelocationFixupOffset = + (sharedhdr.relocationFixupOffset + - shared_offset + + shared_section->filepos); + nlm_extended_header (outbfd)->sharedRelocationFixupCount = + sharedhdr.numberOfRelocationFixups; + nlm_extended_header (outbfd)->sharedExternalReferenceOffset = + (sharedhdr.externalReferencesOffset + - shared_offset + + shared_section->filepos); + nlm_extended_header (outbfd)->sharedExternalReferenceCount = + sharedhdr.numberOfExternalReferences; + nlm_extended_header (outbfd)->sharedPublicsOffset = + sharedhdr.publicsOffset - shared_offset + shared_section->filepos; + nlm_extended_header (outbfd)->sharedPublicsCount = + sharedhdr.numberOfPublics; + nlm_extended_header (outbfd)->sharedDebugRecordOffset = + sharedhdr.debugInfoOffset - shared_offset + shared_section->filepos; + nlm_extended_header (outbfd)->sharedDebugRecordCount = + sharedhdr.numberOfDebugRecords; + nlm_extended_header (outbfd)->SharedInitializationOffset = + sharedhdr.codeStartOffset; + nlm_extended_header (outbfd)->SharedExitProcedureOffset = + sharedhdr.exitProcedureOffset; + free (data); + } + len = strlen (output_file); + if (len > NLM_MODULE_NAME_SIZE - 2) + len = NLM_MODULE_NAME_SIZE - 2; + nlm_fixed_header (outbfd)->moduleName[0] = len; + + strncpy (nlm_fixed_header (outbfd)->moduleName + 1, output_file, + NLM_MODULE_NAME_SIZE - 2); + nlm_fixed_header (outbfd)->moduleName[NLM_MODULE_NAME_SIZE - 1] = '\0'; + for (modname = nlm_fixed_header (outbfd)->moduleName; + *modname != '\0'; + modname++) + if (islower ((unsigned char) *modname)) + *modname = toupper (*modname); + + strncpy (nlm_variable_header (outbfd)->oldThreadName, " LONG", + NLM_OLD_THREAD_NAME_LENGTH); + + nlm_cygnus_ext_header (outbfd)->offset = secsec->filepos; + nlm_cygnus_ext_header (outbfd)->length = bfd_section_size (outbfd, secsec); + + if (! bfd_close (outbfd)) + bfd_fatal (output_file); + if (! bfd_close (inbfd)) + bfd_fatal (input_file); + + if (unlink_on_exit != NULL) + unlink (unlink_on_exit); + + return 0; +} + +/* Display a help message and exit. */ + +static void +show_help () +{ + printf (_("%s: Convert an object file into a NetWare Loadable Module\n"), + program_name); + show_usage (stdout, 0); +} + +/* Show a usage message and exit. */ + +static void +show_usage (file, status) + FILE *file; + int status; +{ + fprintf (file, _("\ +Usage: %s [-dhV] [-I bfdname] [-O bfdname] [-T header-file] [-l linker]\n\ + [--input-target=bfdname] [--output-target=bfdname]\n\ + [--header-file=file] [--linker=linker] [--debug]\n\ + [--help] [--version]\n\ + [in-file [out-file]]\n"), + program_name); + if (status == 0) + fprintf (file, _("Report bugs to bug-gnu-utils@gnu.org\n")); + exit (status); +} + +/* Select the output format based on the input architecture, machine, + and endianness. This chooses the appropriate NLM target. */ + +static const char * +select_output_format (arch, mach, bigendian) + enum bfd_architecture arch; + unsigned long mach; + boolean bigendian; +{ + switch (arch) + { +#ifdef NLMCONV_I386 + case bfd_arch_i386: + return "nlm32-i386"; +#endif +#ifdef NLMCONV_SPARC + case bfd_arch_sparc: + return "nlm32-sparc"; +#endif +#ifdef NLMCONV_ALPHA + case bfd_arch_alpha: + return "nlm32-alpha"; +#endif +#ifdef NLMCONV_POWERPC + case bfd_arch_powerpc: + return "nlm32-powerpc"; +#endif + default: + fprintf (stderr, _("%s: support not compiled in for %s\n"), + program_name, bfd_printable_arch_mach (arch, mach)); + exit (1); + /* Avoid warning. */ + return NULL; + } + /*NOTREACHED*/ +} + +/* The BFD sections are copied in two passes. This function selects + the output section for each input section, and sets up the section + name, size, etc. */ + +static void +setup_sections (inbfd, insec, data_ptr) + bfd *inbfd; + asection *insec; + PTR data_ptr; +{ + bfd *outbfd = (bfd *) data_ptr; + flagword f; + const char *outname; + asection *outsec; + bfd_vma offset; + bfd_size_type align; + bfd_size_type add; + bfd_size_type secsecsize; + + f = bfd_get_section_flags (inbfd, insec); + if (f & SEC_CODE) + outname = NLM_CODE_NAME; + else if ((f & SEC_LOAD) && (f & SEC_HAS_CONTENTS)) + outname = NLM_INITIALIZED_DATA_NAME; + else if (f & SEC_ALLOC) + outname = NLM_UNINITIALIZED_DATA_NAME; + else + outname = bfd_section_name (inbfd, insec); + + outsec = bfd_get_section_by_name (outbfd, outname); + if (outsec == NULL) + { + outsec = bfd_make_section (outbfd, outname); + if (outsec == NULL) + bfd_fatal (_("make section")); + } + + insec->output_section = outsec; + + offset = bfd_section_size (outbfd, outsec); + align = 1 << bfd_section_alignment (inbfd, insec); + add = ((offset + align - 1) &~ (align - 1)) - offset; + insec->output_offset = offset + add; + + if (! bfd_set_section_size (outbfd, outsec, + (bfd_section_size (outbfd, outsec) + + bfd_section_size (inbfd, insec) + + add))) + bfd_fatal (_("set section size")); + + if ((bfd_section_alignment (inbfd, insec) + > bfd_section_alignment (outbfd, outsec)) + && ! bfd_set_section_alignment (outbfd, outsec, + bfd_section_alignment (inbfd, insec))) + bfd_fatal (_("set section alignment")); + + if (! bfd_set_section_flags (outbfd, outsec, + f | bfd_get_section_flags (outbfd, outsec))) + bfd_fatal (_("set section flags")); + + bfd_set_reloc (outbfd, outsec, (arelent **) NULL, 0); + + /* For each input section we allocate space for an entry in + .nlmsections. */ + secsecsize = bfd_section_size (outbfd, secsec); + secsecsize += strlen (bfd_section_name (inbfd, insec)) + 1; + secsecsize = (secsecsize + 3) &~ 3; + secsecsize += 8; + if (! bfd_set_section_size (outbfd, secsec, secsecsize)) + bfd_fatal (_("set .nlmsections size")); +} + +/* Copy the section contents. */ + +static void +copy_sections (inbfd, insec, data_ptr) + bfd *inbfd; + asection *insec; + PTR data_ptr; +{ + static bfd_size_type secsecoff = 0; + bfd *outbfd = (bfd *) data_ptr; + const char *inname; + asection *outsec; + bfd_size_type size; + PTR contents; + long reloc_size; + bfd_byte buf[4]; + bfd_size_type add; + + inname = bfd_section_name (inbfd, insec); + + outsec = insec->output_section; + assert (outsec != NULL); + + size = bfd_get_section_size_before_reloc (insec); + + /* FIXME: Why are these necessary? */ + insec->_cooked_size = insec->_raw_size; + insec->reloc_done = true; + + if ((bfd_get_section_flags (inbfd, insec) & SEC_HAS_CONTENTS) == 0) + contents = NULL; + else + { + contents = xmalloc (size); + if (! bfd_get_section_contents (inbfd, insec, contents, + (file_ptr) 0, size)) + bfd_fatal (bfd_get_filename (inbfd)); + } + + reloc_size = bfd_get_reloc_upper_bound (inbfd, insec); + if (reloc_size < 0) + bfd_fatal (bfd_get_filename (inbfd)); + if (reloc_size != 0) + { + arelent **relocs; + long reloc_count; + + relocs = (arelent **) xmalloc (reloc_size); + reloc_count = bfd_canonicalize_reloc (inbfd, insec, relocs, symbols); + if (reloc_count < 0) + bfd_fatal (bfd_get_filename (inbfd)); + mangle_relocs (outbfd, insec, &relocs, &reloc_count, (char *) contents, + size); + + /* FIXME: refers to internal BFD fields. */ + if (outsec->orelocation != (arelent **) NULL) + { + bfd_size_type total_count; + arelent **combined; + + total_count = reloc_count + outsec->reloc_count; + combined = (arelent **) xmalloc (total_count * sizeof (arelent *)); + memcpy (combined, outsec->orelocation, + outsec->reloc_count * sizeof (arelent *)); + memcpy (combined + outsec->reloc_count, relocs, + (size_t) (reloc_count * sizeof (arelent *))); + free (outsec->orelocation); + reloc_count = total_count; + relocs = combined; + } + + bfd_set_reloc (outbfd, outsec, relocs, reloc_count); + } + + if (contents != NULL) + { + if (! bfd_set_section_contents (outbfd, outsec, contents, + insec->output_offset, size)) + bfd_fatal (bfd_get_filename (outbfd)); + free (contents); + } + + /* Add this section to .nlmsections. */ + if (! bfd_set_section_contents (outbfd, secsec, (PTR) inname, secsecoff, + strlen (inname) + 1)) + bfd_fatal (_("set .nlmsection contents")); + secsecoff += strlen (inname) + 1; + + add = ((secsecoff + 3) &~ 3) - secsecoff; + if (add != 0) + { + bfd_h_put_32 (outbfd, (bfd_vma) 0, buf); + if (! bfd_set_section_contents (outbfd, secsec, buf, secsecoff, add)) + bfd_fatal (_("set .nlmsection contents")); + secsecoff += add; + } + + if (contents != NULL) + bfd_h_put_32 (outbfd, (bfd_vma) outsec->filepos, buf); + else + bfd_h_put_32 (outbfd, (bfd_vma) 0, buf); + if (! bfd_set_section_contents (outbfd, secsec, buf, secsecoff, 4)) + bfd_fatal (_("set .nlmsection contents")); + secsecoff += 4; + + bfd_h_put_32 (outbfd, (bfd_vma) size, buf); + if (! bfd_set_section_contents (outbfd, secsec, buf, secsecoff, 4)) + bfd_fatal (_("set .nlmsection contents")); + secsecoff += 4; +} + +/* Some, perhaps all, NetWare targets require changing the relocs used + by the input formats. */ + +static void +mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents, + contents_size) + bfd *outbfd; + asection *insec; + arelent ***relocs_ptr; + long *reloc_count_ptr; + char *contents; + bfd_size_type contents_size; +{ + switch (bfd_get_arch (outbfd)) + { +#ifdef NLMCONV_I386 + case bfd_arch_i386: + i386_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, + contents, contents_size); + break; +#endif +#ifdef NLMCONV_ALPHA + case bfd_arch_alpha: + alpha_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, + contents, contents_size); + break; +#endif +#ifdef NLMCONV_POWERPC + case bfd_arch_powerpc: + powerpc_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, + contents, contents_size); + break; +#endif + default: + default_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, + contents, contents_size); + break; + } +} + +/* By default all we need to do for relocs is change the address by + the output_offset. */ + +/*ARGSUSED*/ +static void +default_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents, + contents_size) + bfd *outbfd; + asection *insec; + arelent ***relocs_ptr; + long *reloc_count_ptr; + char *contents; + bfd_size_type contents_size; +{ + if (insec->output_offset != 0) + { + long reloc_count; + register arelent **relocs; + register long i; + + reloc_count = *reloc_count_ptr; + relocs = *relocs_ptr; + for (i = 0; i < reloc_count; i++, relocs++) + (*relocs)->address += insec->output_offset; + } +} + +#ifdef NLMCONV_I386 + +/* NetWare on the i386 supports a restricted set of relocs, which are + different from those used on other i386 targets. This routine + converts the relocs. It is, obviously, very target dependent. At + the moment, the nlm32-i386 backend performs similar translations; + however, it is more reliable and efficient to do them here. */ + +static reloc_howto_type nlm_i386_pcrel_howto = + HOWTO (1, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + true, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + 0, /* special_function */ + "DISP32", /* name */ + true, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + true); /* pcrel_offset */ + +static void +i386_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents, + contents_size) + bfd *outbfd; + asection *insec; + arelent ***relocs_ptr; + long *reloc_count_ptr; + char *contents; + bfd_size_type contents_size; +{ + long reloc_count, i; + arelent **relocs; + + reloc_count = *reloc_count_ptr; + relocs = *relocs_ptr; + for (i = 0; i < reloc_count; i++) + { + arelent *rel; + asymbol *sym; + bfd_size_type address; + bfd_vma addend; + + rel = *relocs++; + sym = *rel->sym_ptr_ptr; + + /* We're moving the relocs from the input section to the output + section, so we must adjust the address accordingly. */ + address = rel->address; + rel->address += insec->output_offset; + + /* Note that no serious harm will ensue if we fail to change a + reloc. The backend will fail when writing out the reloc. */ + + /* Make sure this reloc is within the data we have. We use only + 4 byte relocs here, so we insist on having 4 bytes. */ + if (address + 4 > contents_size) + continue; + + /* A PC relative reloc entirely within a single section is + completely unnecessary. This can be generated by ld -r. */ + if (sym == insec->symbol + && rel->howto != NULL + && rel->howto->pc_relative + && ! rel->howto->pcrel_offset) + { + --*reloc_count_ptr; + --relocs; + memmove (relocs, relocs + 1, + (size_t) ((reloc_count - i) * sizeof (arelent *))); + continue; + } + + /* Get the amount the relocation will add in. */ + addend = rel->addend + sym->value; + + /* NetWare doesn't support PC relative relocs against defined + symbols, so we have to eliminate them by doing the relocation + now. We can only do this if the reloc is within a single + section. */ + if (rel->howto != NULL + && rel->howto->pc_relative + && bfd_get_section (sym) == insec->output_section) + { + bfd_vma val; + + if (rel->howto->pcrel_offset) + addend -= address; + + val = bfd_get_32 (outbfd, (bfd_byte *) contents + address); + val += addend; + bfd_put_32 (outbfd, val, (bfd_byte *) contents + address); + + --*reloc_count_ptr; + --relocs; + memmove (relocs, relocs + 1, + (size_t) ((reloc_count - i) * sizeof (arelent *))); + continue; + } + + /* NetWare doesn't support reloc addends, so we get rid of them + here by simply adding them into the object data. We handle + the symbol value, if any, the same way. */ + if (addend != 0 + && rel->howto != NULL + && rel->howto->rightshift == 0 + && rel->howto->size == 2 + && rel->howto->bitsize == 32 + && rel->howto->bitpos == 0 + && rel->howto->src_mask == 0xffffffff + && rel->howto->dst_mask == 0xffffffff) + { + bfd_vma val; + + val = bfd_get_32 (outbfd, (bfd_byte *) contents + address); + val += addend; + bfd_put_32 (outbfd, val, (bfd_byte *) contents + address); + + /* Adjust the reloc for the changes we just made. */ + rel->addend = 0; + if (! bfd_is_und_section (bfd_get_section (sym))) + rel->sym_ptr_ptr = bfd_get_section (sym)->symbol_ptr_ptr; + } + + /* NetWare uses a reloc with pcrel_offset set. We adjust + pc_relative relocs accordingly. We are going to change the + howto field, so we can only do this if the current one is + compatible. We should check that special_function is NULL + here, but at the moment coff-i386 uses a special_function + which does not affect what we are doing here. */ + if (rel->howto != NULL + && rel->howto->pc_relative + && ! rel->howto->pcrel_offset + && rel->howto->rightshift == 0 + && rel->howto->size == 2 + && rel->howto->bitsize == 32 + && rel->howto->bitpos == 0 + && rel->howto->src_mask == 0xffffffff + && rel->howto->dst_mask == 0xffffffff) + { + bfd_vma val; + + /* When pcrel_offset is not set, it means that the negative + of the address of the memory location is stored in the + memory location. We must add it back in. */ + val = bfd_get_32 (outbfd, (bfd_byte *) contents + address); + val += address; + bfd_put_32 (outbfd, val, (bfd_byte *) contents + address); + + /* We must change to a new howto. */ + rel->howto = &nlm_i386_pcrel_howto; + } + } +} + +#endif /* NLMCONV_I386 */ + +#ifdef NLMCONV_ALPHA + +/* On the Alpha the first reloc for every section must be a special + relocs which hold the GP address. Also, the first reloc in the + file must be a special reloc which holds the address of the .lita + section. */ + +static reloc_howto_type nlm32_alpha_nw_howto = + HOWTO (ALPHA_R_NW_RELOC, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + 0, /* special_function */ + "NW_RELOC", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false); /* pcrel_offset */ + +/*ARGSUSED*/ +static void +alpha_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents, + contents_size) + bfd *outbfd; + asection *insec; + register arelent ***relocs_ptr; + long *reloc_count_ptr; + char *contents; + bfd_size_type contents_size; +{ + long old_reloc_count; + arelent **old_relocs; + register arelent **relocs; + + old_reloc_count = *reloc_count_ptr; + old_relocs = *relocs_ptr; + relocs = (arelent **) xmalloc ((old_reloc_count + 3) * sizeof (arelent *)); + *relocs_ptr = relocs; + + if (nlm_alpha_backend_data (outbfd)->lita_address == 0) + { + bfd *inbfd; + asection *lita_section; + + inbfd = insec->owner; + lita_section = bfd_get_section_by_name (inbfd, _LITA); + if (lita_section != (asection *) NULL) + { + nlm_alpha_backend_data (outbfd)->lita_address = + bfd_get_section_vma (inbfd, lita_section); + nlm_alpha_backend_data (outbfd)->lita_size = + bfd_section_size (inbfd, lita_section); + } + else + { + /* Avoid outputting this reloc again. */ + nlm_alpha_backend_data (outbfd)->lita_address = 4; + } + + *relocs = (arelent *) xmalloc (sizeof (arelent)); + (*relocs)->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; + (*relocs)->address = nlm_alpha_backend_data (outbfd)->lita_address; + (*relocs)->addend = nlm_alpha_backend_data (outbfd)->lita_size + 1; + (*relocs)->howto = &nlm32_alpha_nw_howto; + ++relocs; + ++(*reloc_count_ptr); + } + + /* Get the GP value from bfd. */ + if (nlm_alpha_backend_data (outbfd)->gp == 0) + nlm_alpha_backend_data (outbfd)->gp = + bfd_ecoff_get_gp_value (insec->owner); + + *relocs = (arelent *) xmalloc (sizeof (arelent)); + (*relocs)->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; + (*relocs)->address = nlm_alpha_backend_data (outbfd)->gp; + (*relocs)->addend = 0; + (*relocs)->howto = &nlm32_alpha_nw_howto; + ++relocs; + ++(*reloc_count_ptr); + + memcpy ((PTR) relocs, (PTR) old_relocs, + (size_t) old_reloc_count * sizeof (arelent *)); + relocs[old_reloc_count] = (arelent *) NULL; + + free (old_relocs); + + if (insec->output_offset != 0) + { + register bfd_size_type i; + + for (i = 0; i < (bfd_size_type) old_reloc_count; i++, relocs++) + (*relocs)->address += insec->output_offset; + } +} + +#endif /* NLMCONV_ALPHA */ + +#ifdef NLMCONV_POWERPC + +/* We keep a linked list of stubs which we must build. Because BFD + requires us to know the sizes of all sections before we can set the + contents of any, we must figure out which stubs we want to build + before we can actually build any of them. */ + +struct powerpc_stub +{ + /* Next stub in linked list. */ + struct powerpc_stub *next; + + /* Symbol whose value is the start of the stub. This is a symbol + whose name begins with `.'. */ + asymbol *start; + + /* Symbol we are going to create a reloc against. This is a symbol + with the same name as START but without the leading `.'. */ + asymbol *reloc; + + /* The TOC index for this stub. This is the index into the TOC + section at which the reloc is created. */ + unsigned int toc_index; +}; + +/* The linked list of stubs. */ + +static struct powerpc_stub *powerpc_stubs; + +/* This is what a stub looks like. The first instruction will get + adjusted with the correct TOC index. */ + +static unsigned long powerpc_stub_insns[] = +{ + 0x81820000, /* lwz r12,0(r2) */ + 0x90410014, /* stw r2,20(r1) */ + 0x800c0000, /* lwz r0,0(r12) */ + 0x804c0004, /* lwz r2,r(r12) */ + 0x7c0903a6, /* mtctr r0 */ + 0x4e800420, /* bctr */ + 0, /* Traceback table. */ + 0xc8000, + 0 +}; + +#define POWERPC_STUB_INSN_COUNT \ + (sizeof powerpc_stub_insns / sizeof powerpc_stub_insns[0]) + +#define POWERPC_STUB_SIZE (4 * POWERPC_STUB_INSN_COUNT) + +/* Each stub uses a four byte TOC entry. */ +#define POWERPC_STUB_TOC_ENTRY_SIZE (4) + +/* The original size of the .got section. */ +static bfd_size_type powerpc_initial_got_size; + +/* Look for all undefined symbols beginning with `.', and prepare to + build a stub for each one. */ + +static void +powerpc_build_stubs (inbfd, outbfd, symbols_ptr, symcount_ptr) + bfd *inbfd; + bfd *outbfd; + asymbol ***symbols_ptr; + long *symcount_ptr; +{ + asection *stub_sec; + asection *got_sec; + unsigned int got_base; + long i; + long symcount; + long stubcount; + + /* Make a section to hold stubs. We don't set SEC_HAS_CONTENTS for + the section to prevent copy_sections from reading from it. */ + stub_sec = bfd_make_section (inbfd, ".stubs"); + if (stub_sec == (asection *) NULL + || ! bfd_set_section_flags (inbfd, stub_sec, + (SEC_CODE + | SEC_RELOC + | SEC_ALLOC + | SEC_LOAD)) + || ! bfd_set_section_alignment (inbfd, stub_sec, 2)) + bfd_fatal (".stubs"); + + /* Get the TOC section, which is named .got. */ + got_sec = bfd_get_section_by_name (inbfd, ".got"); + if (got_sec == (asection *) NULL) + { + got_sec = bfd_make_section (inbfd, ".got"); + if (got_sec == (asection *) NULL + || ! bfd_set_section_flags (inbfd, got_sec, + (SEC_DATA + | SEC_RELOC + | SEC_ALLOC + | SEC_LOAD + | SEC_HAS_CONTENTS)) + || ! bfd_set_section_alignment (inbfd, got_sec, 2)) + bfd_fatal (".got"); + } + + powerpc_initial_got_size = bfd_section_size (inbfd, got_sec); + got_base = powerpc_initial_got_size; + got_base = (got_base + 3) &~ 3; + + stubcount = 0; + + symcount = *symcount_ptr; + for (i = 0; i < symcount; i++) + { + asymbol *sym; + asymbol *newsym; + char *newname; + struct powerpc_stub *item; + + sym = (*symbols_ptr)[i]; + + /* We must make a stub for every undefined symbol whose name + starts with '.'. */ + if (bfd_asymbol_name (sym)[0] != '.' + || ! bfd_is_und_section (bfd_get_section (sym))) + continue; + + /* Make a new undefined symbol with the same name but without + the leading `.'. */ + newsym = (asymbol *) xmalloc (sizeof (asymbol)); + *newsym = *sym; + newname = (char *) xmalloc (strlen (bfd_asymbol_name (sym))); + strcpy (newname, bfd_asymbol_name (sym) + 1); + newsym->name = newname; + + /* Define the `.' symbol to be in the stub section. */ + sym->section = stub_sec; + sym->value = stubcount * POWERPC_STUB_SIZE; + /* We set the BSF_DYNAMIC flag here so that we can check it when + we are mangling relocs. FIXME: This is a hack. */ + sym->flags = BSF_LOCAL | BSF_DYNAMIC; + + /* Add this stub to the linked list. */ + item = (struct powerpc_stub *) xmalloc (sizeof (struct powerpc_stub)); + item->start = sym; + item->reloc = newsym; + item->toc_index = got_base + stubcount * POWERPC_STUB_TOC_ENTRY_SIZE; + + item->next = powerpc_stubs; + powerpc_stubs = item; + + ++stubcount; + } + + if (stubcount > 0) + { + asymbol **s; + struct powerpc_stub *l; + + /* Add the new symbols we just created to the symbol table. */ + *symbols_ptr = (asymbol **) xrealloc ((char *) *symbols_ptr, + ((symcount + stubcount) + * sizeof (asymbol))); + *symcount_ptr += stubcount; + s = &(*symbols_ptr)[symcount]; + for (l = powerpc_stubs; l != (struct powerpc_stub *) NULL; l = l->next) + *s++ = l->reloc; + + /* Set the size of the .stubs section and increase the size of + the .got section. */ + if (! bfd_set_section_size (inbfd, stub_sec, + stubcount * POWERPC_STUB_SIZE) + || ! bfd_set_section_size (inbfd, got_sec, + (got_base + + (stubcount + * POWERPC_STUB_TOC_ENTRY_SIZE)))) + bfd_fatal (_("stub section sizes")); + } +} + +/* Resolve all the stubs for PowerPC NetWare. We fill in the contents + of the output section, and create new relocs in the TOC. */ + +static void +powerpc_resolve_stubs (inbfd, outbfd) + bfd *inbfd; + bfd *outbfd; +{ + bfd_byte buf[POWERPC_STUB_SIZE]; + unsigned int i; + unsigned int stubcount; + arelent **relocs; + asection *got_sec; + arelent **r; + struct powerpc_stub *l; + + if (powerpc_stubs == (struct powerpc_stub *) NULL) + return; + + for (i = 0; i < POWERPC_STUB_INSN_COUNT; i++) + bfd_put_32 (outbfd, (bfd_vma) powerpc_stub_insns[i], buf + i * 4); + + got_sec = bfd_get_section_by_name (inbfd, ".got"); + assert (got_sec != (asection *) NULL); + assert (got_sec->output_section->orelocation == (arelent **) NULL); + + stubcount = 0; + for (l = powerpc_stubs; l != (struct powerpc_stub *) NULL; l = l->next) + ++stubcount; + relocs = (arelent **) xmalloc (stubcount * sizeof (arelent *)); + + r = relocs; + for (l = powerpc_stubs; l != (struct powerpc_stub *) NULL; l = l->next) + { + arelent *reloc; + + /* Adjust the first instruction to use the right TOC index. */ + bfd_put_32 (outbfd, (bfd_vma) powerpc_stub_insns[0] + l->toc_index, buf); + + /* Write this stub out. */ + if (! bfd_set_section_contents (outbfd, + bfd_get_section (l->start), + buf, + l->start->value, + POWERPC_STUB_SIZE)) + bfd_fatal (_("writing stub")); + + /* Create a new reloc for the TOC entry. */ + reloc = (arelent *) xmalloc (sizeof (arelent)); + reloc->sym_ptr_ptr = &l->reloc; + reloc->address = l->toc_index + got_sec->output_offset; + reloc->addend = 0; + reloc->howto = bfd_reloc_type_lookup (inbfd, BFD_RELOC_32); + + *r++ = reloc; + } + + bfd_set_reloc (outbfd, got_sec->output_section, relocs, stubcount); +} + +/* Adjust relocation entries for PowerPC NetWare. We do not output + TOC relocations. The object code already contains the offset from + the TOC pointer. When the function is called, the TOC register, + r2, will be set to the correct TOC value, so there is no need for + any further reloc. */ + +/*ARGSUSED*/ +static void +powerpc_mangle_relocs (outbfd, insec, relocs_ptr, reloc_count_ptr, contents, + contents_size) + bfd *outbfd; + asection *insec; + register arelent ***relocs_ptr; + long *reloc_count_ptr; + char *contents; + bfd_size_type contents_size; +{ + reloc_howto_type *toc_howto; + long reloc_count; + register arelent **relocs; + register long i; + + toc_howto = bfd_reloc_type_lookup (insec->owner, BFD_RELOC_PPC_TOC16); + if (toc_howto == (reloc_howto_type *) NULL) + abort (); + + /* If this is the .got section, clear out all the contents beyond + the initial size. We must do this here because copy_sections is + going to write out whatever we return in the contents field. */ + if (strcmp (bfd_get_section_name (insec->owner, insec), ".got") == 0) + memset (contents + powerpc_initial_got_size, 0, + (size_t) (bfd_get_section_size_after_reloc (insec) + - powerpc_initial_got_size)); + + reloc_count = *reloc_count_ptr; + relocs = *relocs_ptr; + for (i = 0; i < reloc_count; i++) + { + arelent *rel; + asymbol *sym; + bfd_vma sym_value; + + rel = *relocs++; + sym = *rel->sym_ptr_ptr; + + /* Convert any relocs against the .bss section into relocs + against the .data section. */ + if (strcmp (bfd_get_section_name (outbfd, bfd_get_section (sym)), + NLM_UNINITIALIZED_DATA_NAME) == 0) + { + asection *datasec; + + datasec = bfd_get_section_by_name (outbfd, + NLM_INITIALIZED_DATA_NAME); + if (datasec != NULL) + { + rel->addend += (bfd_get_section_vma (outbfd, + bfd_get_section (sym)) + + sym->value); + rel->sym_ptr_ptr = datasec->symbol_ptr_ptr; + sym = *rel->sym_ptr_ptr; + } + } + + /* We must be able to resolve all PC relative relocs at this + point. If we get a branch to an undefined symbol we build a + stub, since NetWare will resolve undefined symbols into a + pointer to a function descriptor. */ + if (rel->howto->pc_relative) + { + /* This check for whether a symbol is in the same section as + the reloc will be wrong if there is a PC relative reloc + between two sections both of which were placed in the + same output section. This should not happen. */ + if (bfd_get_section (sym) != insec->output_section) + fprintf (stderr, _("%s: unresolved PC relative reloc against %s\n"), + program_name, bfd_asymbol_name (sym)); + else + { + bfd_vma val; + + assert (rel->howto->size == 2 && rel->howto->pcrel_offset); + val = bfd_get_32 (outbfd, (bfd_byte *) contents + rel->address); + val = ((val &~ rel->howto->dst_mask) + | (((val & rel->howto->src_mask) + + (sym->value - rel->address) + + rel->addend) + & rel->howto->dst_mask)); + bfd_put_32 (outbfd, val, (bfd_byte *) contents + rel->address); + + /* If this reloc is against an stubbed symbol and the + next instruction is + cror 31,31,31 + then we replace the next instruction with + lwz r2,20(r1) + This reloads the TOC pointer after a stub call. */ + if (bfd_asymbol_name (sym)[0] == '.' + && (sym->flags & BSF_DYNAMIC) != 0 + && (bfd_get_32 (outbfd, + (bfd_byte *) contents + rel->address + 4) + == 0x4ffffb82)) /* cror 31,31,31 */ + bfd_put_32 (outbfd, (bfd_vma) 0x80410014, /* lwz r2,20(r1) */ + (bfd_byte *) contents + rel->address + 4); + + --*reloc_count_ptr; + --relocs; + memmove (relocs, relocs + 1, + (size_t) ((reloc_count - 1) * sizeof (arelent *))); + continue; + } + } + + /* When considering a TOC reloc, we do not want to include the + symbol value. The symbol will be start of the TOC section + (which is named .got). We do want to include the addend. */ + if (rel->howto == toc_howto) + sym_value = 0; + else + sym_value = sym->value; + + /* If this is a relocation against a symbol with a value, or + there is a reloc addend, we need to update the addend in the + object file. */ + if (sym_value + rel->addend != 0) + { + bfd_vma val; + + switch (rel->howto->size) + { + case 1: + val = bfd_get_16 (outbfd, + (bfd_byte *) contents + rel->address); + val = ((val &~ rel->howto->dst_mask) + | (((val & rel->howto->src_mask) + + sym_value + + rel->addend) + & rel->howto->dst_mask)); + if ((bfd_signed_vma) val < - 0x8000 + || (bfd_signed_vma) val >= 0x8000) + fprintf (stderr, + _("%s: overflow when adjusting relocation against %s\n"), + program_name, bfd_asymbol_name (sym)); + bfd_put_16 (outbfd, val, (bfd_byte *) contents + rel->address); + break; + + case 2: + val = bfd_get_32 (outbfd, + (bfd_byte *) contents + rel->address); + val = ((val &~ rel->howto->dst_mask) + | (((val & rel->howto->src_mask) + + sym_value + + rel->addend) + & rel->howto->dst_mask)); + bfd_put_32 (outbfd, val, (bfd_byte *) contents + rel->address); + break; + + default: + abort (); + } + + if (! bfd_is_und_section (bfd_get_section (sym))) + rel->sym_ptr_ptr = bfd_get_section (sym)->symbol_ptr_ptr; + rel->addend = 0; + } + + /* Now that we have incorporated the addend, remove any TOC + relocs. */ + if (rel->howto == toc_howto) + { + --*reloc_count_ptr; + --relocs; + memmove (relocs, relocs + 1, + (size_t) ((reloc_count - i) * sizeof (arelent *))); + continue; + } + + rel->address += insec->output_offset; + } +} + +#endif /* NLMCONV_POWERPC */ + +/* Name of linker. */ +#ifndef LD_NAME +#define LD_NAME "ld" +#endif + +/* Temporary file name base. */ +static char *temp_filename; + +/* The user has specified several input files. Invoke the linker to + link them all together, and convert and delete the resulting output + file. */ + +static char * +link_inputs (inputs, ld) + struct string_list *inputs; + char *ld; +{ + size_t c; + struct string_list *q; + char **argv; + size_t i; + int pid; + int status; + char *errfmt; + char *errarg; + + c = 0; + for (q = inputs; q != NULL; q = q->next) + ++c; + + argv = (char **) alloca ((c + 5) * sizeof(char *)); + +#ifndef __MSDOS__ + if (ld == NULL) + { + char *p; + + /* Find the linker to invoke based on how nlmconv was run. */ + p = program_name + strlen (program_name); + while (p != program_name) + { + if (p[-1] == '/') + { + ld = (char *) xmalloc (p - program_name + strlen (LD_NAME) + 1); + memcpy (ld, program_name, p - program_name); + strcpy (ld + (p - program_name), LD_NAME); + break; + } + --p; + } + } +#endif + + if (ld == NULL) + ld = (char *) LD_NAME; + + temp_filename = choose_temp_base (); + + unlink_on_exit = xmalloc (strlen (temp_filename) + 3); + sprintf (unlink_on_exit, "%s.O", temp_filename); + + argv[0] = ld; + argv[1] = (char *) "-Ur"; + argv[2] = (char *) "-o"; + argv[3] = unlink_on_exit; + i = 4; + for (q = inputs; q != NULL; q = q->next, i++) + argv[i] = q->string; + argv[i] = NULL; + + if (debug) + { + for (i = 0; argv[i] != NULL; i++) + fprintf (stderr, " %s", argv[i]); + fprintf (stderr, "\n"); + } + + pid = pexecute (ld, argv, program_name, (char *) NULL, &errfmt, &errarg, + PEXECUTE_SEARCH | PEXECUTE_ONE); + if (pid == -1) + { + fprintf (stderr, _("%s: execution of %s failed: "), program_name, ld); + fprintf (stderr, errfmt, errarg); + unlink (unlink_on_exit); + exit (1); + } + + if (pwait (pid, &status, 0) < 0) + { + perror ("pwait"); + unlink (unlink_on_exit); + exit (1); + } + + if (status != 0) + { + fprintf (stderr, _("%s: Execution of %s failed\n"), program_name, ld); + unlink (unlink_on_exit); + exit (1); + } + + return unlink_on_exit; +} diff --git a/binutils/nlmconv.h b/binutils/nlmconv.h new file mode 100644 index 0000000..c92a557 --- /dev/null +++ b/binutils/nlmconv.h @@ -0,0 +1,84 @@ +/* nlmconv.h -- header file for NLM conversion program + Copyright (C) 1993 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Ian Lance Taylor <ian@cygnus.com>. + + bfd.h, nlm/common.h and nlm/internal.h must be included before this + file. */ + +/* A linked list of strings. */ + +struct string_list +{ + struct string_list *next; + char *string; +}; + +/* The NLM header parser in nlmheader.y stores information in the + following variables. */ + +extern Nlm_Internal_Fixed_Header *fixed_hdr; +extern Nlm_Internal_Variable_Header *var_hdr; +extern Nlm_Internal_Version_Header *version_hdr; +extern Nlm_Internal_Copyright_Header *copyright_hdr; +extern Nlm_Internal_Extended_Header *extended_hdr; + +/* Procedure named by CHECK. */ +extern char *check_procedure; +/* File named by CUSTOM. */ +extern char *custom_file; +/* Whether to generate debugging information (DEBUG). */ +extern boolean debug_info; +/* Procedure named by EXIT. */ +extern char *exit_procedure; +/* Exported symbols (EXPORT). */ +extern struct string_list *export_symbols; +/* List of files from INPUT. */ +extern struct string_list *input_files; +/* Map file name (MAP, FULLMAP). */ +extern char *map_file; +/* Whether a full map has been requested (FULLMAP). */ +extern boolean full_map; +/* File named by HELP. */ +extern char *help_file; +/* Imported symbols (IMPORT). */ +extern struct string_list *import_symbols; +/* File named by MESSAGES. */ +extern char *message_file; +/* Autoload module list (MODULE). */ +extern struct string_list *modules; +/* File named by OUTPUT. */ +extern char *output_file; +/* File named by SHARELIB. */ +extern char *sharelib_file; +/* Start procedure name (START). */ +extern char *start_procedure; +/* VERBOSE. */ +extern boolean verbose; +/* RPC description file (XDCDATA). */ +extern char *rpc_file; + +/* The number of serious parse errors. */ +extern int parse_errors; + +/* The parser. */ +extern int yyparse PARAMS ((void)); + +/* Tell the lexer what file to read. */ +extern boolean nlmlex_file PARAMS ((const char *)); diff --git a/binutils/nlmheader.y b/binutils/nlmheader.y new file mode 100644 index 0000000..0f1e22a --- /dev/null +++ b/binutils/nlmheader.y @@ -0,0 +1,978 @@ +%{/* nlmheader.y - parse NLM header specification keywords. + Copyright (C) 1993, 94, 95, 97, 1998 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Ian Lance Taylor <ian@cygnus.com>. + + This bison file parses the commands recognized by the NetWare NLM + linker, except for lists of object files. It stores the + information in global variables. + + This implementation is based on the description in the NetWare Tool + Maker Specification manual, edition 1.0. */ + +#include <ansidecl.h> +#include <stdio.h> +#include <ctype.h> +#include "bfd.h" +#include "bucomm.h" +#include "nlm/common.h" +#include "nlm/internal.h" +#include "nlmconv.h" + +/* Information is stored in the structures pointed to by these + variables. */ + +Nlm_Internal_Fixed_Header *fixed_hdr; +Nlm_Internal_Variable_Header *var_hdr; +Nlm_Internal_Version_Header *version_hdr; +Nlm_Internal_Copyright_Header *copyright_hdr; +Nlm_Internal_Extended_Header *extended_hdr; + +/* Procedure named by CHECK. */ +char *check_procedure; +/* File named by CUSTOM. */ +char *custom_file; +/* Whether to generate debugging information (DEBUG). */ +boolean debug_info; +/* Procedure named by EXIT. */ +char *exit_procedure; +/* Exported symbols (EXPORT). */ +struct string_list *export_symbols; +/* List of files from INPUT. */ +struct string_list *input_files; +/* Map file name (MAP, FULLMAP). */ +char *map_file; +/* Whether a full map has been requested (FULLMAP). */ +boolean full_map; +/* File named by HELP. */ +char *help_file; +/* Imported symbols (IMPORT). */ +struct string_list *import_symbols; +/* File named by MESSAGES. */ +char *message_file; +/* Autoload module list (MODULE). */ +struct string_list *modules; +/* File named by OUTPUT. */ +char *output_file; +/* File named by SHARELIB. */ +char *sharelib_file; +/* Start procedure name (START). */ +char *start_procedure; +/* VERBOSE. */ +boolean verbose; +/* RPC description file (XDCDATA). */ +char *rpc_file; + +/* The number of serious errors that have occurred. */ +int parse_errors; + +/* The current symbol prefix when reading a list of import or export + symbols. */ +static char *symbol_prefix; + +/* Parser error message handler. */ +#define yyerror(msg) nlmheader_error (msg); + +/* Local functions. */ +static int yylex PARAMS ((void)); +static void nlmlex_file_push PARAMS ((const char *)); +static boolean nlmlex_file_open PARAMS ((const char *)); +static int nlmlex_buf_init PARAMS ((void)); +static char nlmlex_buf_add PARAMS ((int)); +static long nlmlex_get_number PARAMS ((const char *)); +static void nlmheader_identify PARAMS ((void)); +static void nlmheader_warn PARAMS ((const char *, int)); +static void nlmheader_error PARAMS ((const char *)); +static struct string_list * string_list_cons PARAMS ((char *, + struct string_list *)); +static struct string_list * string_list_append PARAMS ((struct string_list *, + struct string_list *)); +static struct string_list * string_list_append1 PARAMS ((struct string_list *, + char *)); +static char *xstrdup PARAMS ((const char *)); + +%} + +%union +{ + char *string; + struct string_list *list; +}; + +/* The reserved words. */ + +%token CHECK CODESTART COPYRIGHT CUSTOM DATE DEBUG DESCRIPTION EXIT +%token EXPORT FLAG_ON FLAG_OFF FULLMAP HELP IMPORT INPUT MAP MESSAGES +%token MODULE MULTIPLE OS_DOMAIN OUTPUT PSEUDOPREEMPTION REENTRANT +%token SCREENNAME SHARELIB STACK START SYNCHRONIZE +%token THREADNAME TYPE VERBOSE VERSIONK XDCDATA + +/* Arguments. */ + +%token <string> STRING +%token <string> QUOTED_STRING + +/* Typed non-terminals. */ +%type <list> symbol_list_opt symbol_list string_list +%type <string> symbol + +%% + +/* Keywords must start in the leftmost column of the file. Arguments + may appear anywhere else. The lexer uses this to determine what + token to return, so we don't have to worry about it here. */ + +/* The entire file is just a list of commands. */ + +file: + commands + ; + +/* A possibly empty list of commands. */ + +commands: + /* May be empty. */ + | command commands + ; + +/* A single command. There is where most of the work takes place. */ + +command: + CHECK STRING + { + check_procedure = $2; + } + | CODESTART STRING + { + nlmheader_warn (_("CODESTART is not implemented; sorry"), -1); + free ($2); + } + | COPYRIGHT QUOTED_STRING + { + int len; + + strncpy (copyright_hdr->stamp, "CoPyRiGhT=", 10); + len = strlen ($2); + if (len >= NLM_MAX_COPYRIGHT_MESSAGE_LENGTH) + { + nlmheader_warn (_("copyright string is too long"), + NLM_MAX_COPYRIGHT_MESSAGE_LENGTH - 1); + len = NLM_MAX_COPYRIGHT_MESSAGE_LENGTH - 1; + } + copyright_hdr->copyrightMessageLength = len; + strncpy (copyright_hdr->copyrightMessage, $2, len); + copyright_hdr->copyrightMessage[len] = '\0'; + free ($2); + } + | CUSTOM STRING + { + custom_file = $2; + } + | DATE STRING STRING STRING + { + /* We don't set the version stamp here, because we use the + version stamp to detect whether the required VERSION + keyword was given. */ + version_hdr->month = nlmlex_get_number ($2); + version_hdr->day = nlmlex_get_number ($3); + version_hdr->year = nlmlex_get_number ($4); + free ($2); + free ($3); + free ($4); + if (version_hdr->month < 1 || version_hdr->month > 12) + nlmheader_warn (_("illegal month"), -1); + if (version_hdr->day < 1 || version_hdr->day > 31) + nlmheader_warn (_("illegal day"), -1); + if (version_hdr->year < 1900 || version_hdr->year > 3000) + nlmheader_warn (_("illegal year"), -1); + } + | DEBUG + { + debug_info = true; + } + | DESCRIPTION QUOTED_STRING + { + int len; + + len = strlen ($2); + if (len > NLM_MAX_DESCRIPTION_LENGTH) + { + nlmheader_warn (_("description string is too long"), + NLM_MAX_DESCRIPTION_LENGTH); + len = NLM_MAX_DESCRIPTION_LENGTH; + } + var_hdr->descriptionLength = len; + strncpy (var_hdr->descriptionText, $2, len); + var_hdr->descriptionText[len] = '\0'; + free ($2); + } + | EXIT STRING + { + exit_procedure = $2; + } + | EXPORT + { + symbol_prefix = NULL; + } + symbol_list_opt + { + export_symbols = string_list_append (export_symbols, $3); + } + | FLAG_ON STRING + { + fixed_hdr->flags |= nlmlex_get_number ($2); + free ($2); + } + | FLAG_OFF STRING + { + fixed_hdr->flags &=~ nlmlex_get_number ($2); + free ($2); + } + | FULLMAP + { + map_file = ""; + full_map = true; + } + | FULLMAP STRING + { + map_file = $2; + full_map = true; + } + | HELP STRING + { + help_file = $2; + } + | IMPORT + { + symbol_prefix = NULL; + } + symbol_list_opt + { + import_symbols = string_list_append (import_symbols, $3); + } + | INPUT string_list + { + input_files = string_list_append (input_files, $2); + } + | MAP + { + map_file = ""; + } + | MAP STRING + { + map_file = $2; + } + | MESSAGES STRING + { + message_file = $2; + } + | MODULE string_list + { + modules = string_list_append (modules, $2); + } + | MULTIPLE + { + fixed_hdr->flags |= 0x2; + } + | OS_DOMAIN + { + fixed_hdr->flags |= 0x10; + } + | OUTPUT STRING + { + if (output_file == NULL) + output_file = $2; + else + nlmheader_warn (_("ignoring duplicate OUTPUT statement"), -1); + } + | PSEUDOPREEMPTION + { + fixed_hdr->flags |= 0x8; + } + | REENTRANT + { + fixed_hdr->flags |= 0x1; + } + | SCREENNAME QUOTED_STRING + { + int len; + + len = strlen ($2); + if (len >= NLM_MAX_SCREEN_NAME_LENGTH) + { + nlmheader_warn (_("screen name is too long"), + NLM_MAX_SCREEN_NAME_LENGTH); + len = NLM_MAX_SCREEN_NAME_LENGTH; + } + var_hdr->screenNameLength = len; + strncpy (var_hdr->screenName, $2, len); + var_hdr->screenName[NLM_MAX_SCREEN_NAME_LENGTH] = '\0'; + free ($2); + } + | SHARELIB STRING + { + sharelib_file = $2; + } + | STACK STRING + { + var_hdr->stackSize = nlmlex_get_number ($2); + free ($2); + } + | START STRING + { + start_procedure = $2; + } + | SYNCHRONIZE + { + fixed_hdr->flags |= 0x4; + } + | THREADNAME QUOTED_STRING + { + int len; + + len = strlen ($2); + if (len >= NLM_MAX_THREAD_NAME_LENGTH) + { + nlmheader_warn (_("thread name is too long"), + NLM_MAX_THREAD_NAME_LENGTH); + len = NLM_MAX_THREAD_NAME_LENGTH; + } + var_hdr->threadNameLength = len; + strncpy (var_hdr->threadName, $2, len); + var_hdr->threadName[len] = '\0'; + free ($2); + } + | TYPE STRING + { + fixed_hdr->moduleType = nlmlex_get_number ($2); + free ($2); + } + | VERBOSE + { + verbose = true; + } + | VERSIONK STRING STRING STRING + { + long val; + + strncpy (version_hdr->stamp, "VeRsIoN#", 8); + version_hdr->majorVersion = nlmlex_get_number ($2); + val = nlmlex_get_number ($3); + if (val < 0 || val > 99) + nlmheader_warn (_("illegal minor version number (must be between 0 and 99)"), + -1); + else + version_hdr->minorVersion = val; + val = nlmlex_get_number ($4); + if (val < 0) + nlmheader_warn (_("illegal revision number (must be between 0 and 26)"), + -1); + else if (val > 26) + version_hdr->revision = 0; + else + version_hdr->revision = val; + free ($2); + free ($3); + free ($4); + } + | VERSIONK STRING STRING + { + long val; + + strncpy (version_hdr->stamp, "VeRsIoN#", 8); + version_hdr->majorVersion = nlmlex_get_number ($2); + val = nlmlex_get_number ($3); + if (val < 0 || val > 99) + nlmheader_warn (_("illegal minor version number (must be between 0 and 99)"), + -1); + else + version_hdr->minorVersion = val; + version_hdr->revision = 0; + free ($2); + free ($3); + } + | XDCDATA STRING + { + rpc_file = $2; + } + ; + +/* A possibly empty list of symbols. */ + +symbol_list_opt: + /* Empty. */ + { + $$ = NULL; + } + | symbol_list + { + $$ = $1; + } + ; + +/* A list of symbols in an import or export list. Prefixes may appear + in parentheses. We need to use left recursion here to avoid + building up a large import list on the parser stack. */ + +symbol_list: + symbol + { + $$ = string_list_cons ($1, NULL); + } + | symbol_prefix + { + $$ = NULL; + } + | symbol_list symbol + { + $$ = string_list_append1 ($1, $2); + } + | symbol_list symbol_prefix + { + $$ = $1; + } + ; + +/* A prefix for subsequent symbols. */ + +symbol_prefix: + '(' STRING ')' + { + if (symbol_prefix != NULL) + free (symbol_prefix); + symbol_prefix = $2; + } + ; + +/* A single symbol. */ + +symbol: + STRING + { + if (symbol_prefix == NULL) + $$ = $1; + else + { + $$ = xmalloc (strlen (symbol_prefix) + strlen ($1) + 2); + sprintf ($$, "%s@%s", symbol_prefix, $1); + free ($1); + } + } + ; + +/* A list of strings. */ + +string_list: + /* May be empty. */ + { + $$ = NULL; + } + | STRING string_list + { + $$ = string_list_cons ($1, $2); + } + ; + +%% + +/* If strerror is just a macro, we want to use the one from libiberty + since it will handle undefined values. */ +#undef strerror +extern char *strerror (); + +/* The lexer is simple, too simple for flex. Keywords are only + recognized at the start of lines. Everything else must be an + argument. A comma is treated as whitespace. */ + +/* The states the lexer can be in. */ + +enum lex_state +{ + /* At the beginning of a line. */ + BEGINNING_OF_LINE, + /* In the middle of a line. */ + IN_LINE +}; + +/* We need to keep a stack of files to handle file inclusion. */ + +struct input +{ + /* The file to read from. */ + FILE *file; + /* The name of the file. */ + char *name; + /* The current line number. */ + int lineno; + /* The current state. */ + enum lex_state state; + /* The next file on the stack. */ + struct input *next; +}; + +/* The current input file. */ + +static struct input current; + +/* The character which introduces comments. */ +#define COMMENT_CHAR '#' + +/* Start the lexer going on the main input file. */ + +boolean +nlmlex_file (name) + const char *name; +{ + current.next = NULL; + return nlmlex_file_open (name); +} + +/* Start the lexer going on a subsidiary input file. */ + +static void +nlmlex_file_push (name) + const char *name; +{ + struct input *push; + + push = (struct input *) xmalloc (sizeof (struct input)); + *push = current; + if (nlmlex_file_open (name)) + current.next = push; + else + { + current = *push; + free (push); + } +} + +/* Start lexing from a file. */ + +static boolean +nlmlex_file_open (name) + const char *name; +{ + current.file = fopen (name, "r"); + if (current.file == NULL) + { + fprintf (stderr, "%s:%s: %s\n", program_name, name, strerror (errno)); + ++parse_errors; + return false; + } + current.name = xstrdup (name); + current.lineno = 1; + current.state = BEGINNING_OF_LINE; + return true; +} + +/* Table used to turn keywords into tokens. */ + +struct keyword_tokens_struct +{ + const char *keyword; + int token; +}; + +struct keyword_tokens_struct keyword_tokens[] = +{ + { "CHECK", CHECK }, + { "CODESTART", CODESTART }, + { "COPYRIGHT", COPYRIGHT }, + { "CUSTOM", CUSTOM }, + { "DATE", DATE }, + { "DEBUG", DEBUG }, + { "DESCRIPTION", DESCRIPTION }, + { "EXIT", EXIT }, + { "EXPORT", EXPORT }, + { "FLAG_ON", FLAG_ON }, + { "FLAG_OFF", FLAG_OFF }, + { "FULLMAP", FULLMAP }, + { "HELP", HELP }, + { "IMPORT", IMPORT }, + { "INPUT", INPUT }, + { "MAP", MAP }, + { "MESSAGES", MESSAGES }, + { "MODULE", MODULE }, + { "MULTIPLE", MULTIPLE }, + { "OS_DOMAIN", OS_DOMAIN }, + { "OUTPUT", OUTPUT }, + { "PSEUDOPREEMPTION", PSEUDOPREEMPTION }, + { "REENTRANT", REENTRANT }, + { "SCREENNAME", SCREENNAME }, + { "SHARELIB", SHARELIB }, + { "STACK", STACK }, + { "STACKSIZE", STACK }, + { "START", START }, + { "SYNCHRONIZE", SYNCHRONIZE }, + { "THREADNAME", THREADNAME }, + { "TYPE", TYPE }, + { "VERBOSE", VERBOSE }, + { "VERSION", VERSIONK }, + { "XDCDATA", XDCDATA } +}; + +#define KEYWORD_COUNT (sizeof (keyword_tokens) / sizeof (keyword_tokens[0])) + +/* The lexer accumulates strings in these variables. */ +static char *lex_buf; +static int lex_size; +static int lex_pos; + +/* Start accumulating strings into the buffer. */ +#define BUF_INIT() \ + ((void) (lex_buf != NULL ? lex_pos = 0 : nlmlex_buf_init ())) + +static int +nlmlex_buf_init () +{ + lex_size = 10; + lex_buf = xmalloc (lex_size + 1); + lex_pos = 0; + return 0; +} + +/* Finish a string in the buffer. */ +#define BUF_FINISH() ((void) (lex_buf[lex_pos] = '\0')) + +/* Accumulate a character into the buffer. */ +#define BUF_ADD(c) \ + ((void) (lex_pos < lex_size \ + ? lex_buf[lex_pos++] = (c) \ + : nlmlex_buf_add (c))) + +static char +nlmlex_buf_add (c) + int c; +{ + if (lex_pos >= lex_size) + { + lex_size *= 2; + lex_buf = xrealloc (lex_buf, lex_size + 1); + } + + return lex_buf[lex_pos++] = c; +} + +/* The lexer proper. This is called by the bison generated parsing + code. */ + +static int +yylex () +{ + int c; + +tail_recurse: + + c = getc (current.file); + + /* Commas are treated as whitespace characters. */ + while (isspace ((unsigned char) c) || c == ',') + { + current.state = IN_LINE; + if (c == '\n') + { + ++current.lineno; + current.state = BEGINNING_OF_LINE; + } + c = getc (current.file); + } + + /* At the end of the file we either pop to the previous file or + finish up. */ + if (c == EOF) + { + fclose (current.file); + free (current.name); + if (current.next == NULL) + return 0; + else + { + struct input *next; + + next = current.next; + current = *next; + free (next); + goto tail_recurse; + } + } + + /* A comment character always means to drop everything until the + next newline. */ + if (c == COMMENT_CHAR) + { + do + { + c = getc (current.file); + } + while (c != '\n'); + ++current.lineno; + current.state = BEGINNING_OF_LINE; + goto tail_recurse; + } + + /* An '@' introduces an include file. */ + if (c == '@') + { + do + { + c = getc (current.file); + if (c == '\n') + ++current.lineno; + } + while (isspace ((unsigned char) c)); + BUF_INIT (); + while (! isspace ((unsigned char) c) && c != EOF) + { + BUF_ADD (c); + c = getc (current.file); + } + BUF_FINISH (); + + ungetc (c, current.file); + + nlmlex_file_push (lex_buf); + goto tail_recurse; + } + + /* A non-space character at the start of a line must be the start of + a keyword. */ + if (current.state == BEGINNING_OF_LINE) + { + BUF_INIT (); + while (isalnum ((unsigned char) c) || c == '_') + { + if (islower ((unsigned char) c)) + BUF_ADD (toupper ((unsigned char) c)); + else + BUF_ADD (c); + c = getc (current.file); + } + BUF_FINISH (); + + if (c != EOF && ! isspace ((unsigned char) c) && c != ',') + { + nlmheader_identify (); + fprintf (stderr, _("%s:%d: illegal character in keyword: %c\n"), + current.name, current.lineno, c); + } + else + { + unsigned int i; + + for (i = 0; i < KEYWORD_COUNT; i++) + { + if (lex_buf[0] == keyword_tokens[i].keyword[0] + && strcmp (lex_buf, keyword_tokens[i].keyword) == 0) + { + /* Pushing back the final whitespace avoids worrying + about \n here. */ + ungetc (c, current.file); + current.state = IN_LINE; + return keyword_tokens[i].token; + } + } + + nlmheader_identify (); + fprintf (stderr, _("%s:%d: unrecognized keyword: %s\n"), + current.name, current.lineno, lex_buf); + } + + ++parse_errors; + /* Treat the rest of this line as a comment. */ + ungetc (COMMENT_CHAR, current.file); + goto tail_recurse; + } + + /* Parentheses just represent themselves. */ + if (c == '(' || c == ')') + return c; + + /* Handle quoted strings. */ + if (c == '"' || c == '\'') + { + int quote; + int start_lineno; + + quote = c; + start_lineno = current.lineno; + + c = getc (current.file); + BUF_INIT (); + while (c != quote && c != EOF) + { + BUF_ADD (c); + if (c == '\n') + ++current.lineno; + c = getc (current.file); + } + BUF_FINISH (); + + if (c == EOF) + { + nlmheader_identify (); + fprintf (stderr, _("%s:%d: end of file in quoted string\n"), + current.name, start_lineno); + ++parse_errors; + } + + /* FIXME: Possible memory leak. */ + yylval.string = xstrdup (lex_buf); + return QUOTED_STRING; + } + + /* Gather a generic argument. */ + BUF_INIT (); + while (! isspace (c) + && c != ',' + && c != COMMENT_CHAR + && c != '(' + && c != ')') + { + BUF_ADD (c); + c = getc (current.file); + } + BUF_FINISH (); + + ungetc (c, current.file); + + /* FIXME: Possible memory leak. */ + yylval.string = xstrdup (lex_buf); + return STRING; +} + +/* Get a number from a string. */ + +static long +nlmlex_get_number (s) + const char *s; +{ + long ret; + char *send; + + ret = strtol (s, &send, 10); + if (*send != '\0') + nlmheader_warn (_("bad number"), -1); + return ret; +} + +/* Prefix the nlmconv warnings with a note as to where they come from. + We don't use program_name on every warning, because then some + versions of the emacs next-error function can't recognize the line + number. */ + +static void +nlmheader_identify () +{ + static int done; + + if (! done) + { + fprintf (stderr, _("%s: problems in NLM command language input:\n"), + program_name); + done = 1; + } +} + +/* Issue a warning. */ + +static void +nlmheader_warn (s, imax) + const char *s; + int imax; +{ + nlmheader_identify (); + fprintf (stderr, "%s:%d: %s", current.name, current.lineno, s); + if (imax != -1) + fprintf (stderr, " (max %d)", imax); + fprintf (stderr, "\n"); +} + +/* Report an error. */ + +static void +nlmheader_error (s) + const char *s; +{ + nlmheader_warn (s, -1); + ++parse_errors; +} + +/* Add a string to a string list. */ + +static struct string_list * +string_list_cons (s, l) + char *s; + struct string_list *l; +{ + struct string_list *ret; + + ret = (struct string_list *) xmalloc (sizeof (struct string_list)); + ret->next = l; + ret->string = s; + return ret; +} + +/* Append a string list to another string list. */ + +static struct string_list * +string_list_append (l1, l2) + struct string_list *l1; + struct string_list *l2; +{ + register struct string_list **pp; + + for (pp = &l1; *pp != NULL; pp = &(*pp)->next) + ; + *pp = l2; + return l1; +} + +/* Append a string to a string list. */ + +static struct string_list * +string_list_append1 (l, s) + struct string_list *l; + char *s; +{ + struct string_list *n; + register struct string_list **pp; + + n = (struct string_list *) xmalloc (sizeof (struct string_list)); + n->next = NULL; + n->string = s; + for (pp = &l; *pp != NULL; pp = &(*pp)->next) + ; + *pp = n; + return l; +} + +/* Duplicate a string in memory. */ + +static char * +xstrdup (s) + const char *s; +{ + unsigned long len; + char *ret; + + len = strlen (s); + ret = xmalloc (len + 1); + strcpy (ret, s); + return ret; +} diff --git a/binutils/nm.1 b/binutils/nm.1 new file mode 100644 index 0000000..c2ad99e --- /dev/null +++ b/binutils/nm.1 @@ -0,0 +1,230 @@ +.\" Copyright (c) 1991 Free Software Foundation +.\" See section COPYING for conditions for redistribution +.TH nm 1 "5 November 1991" "cygnus support" "GNU Development Tools" +.de BP +.sp +.ti \-.2i +\(** +.. + +.SH NAME +nm \- list symbols from object files. + +.SH SYNOPSIS +.hy 0 +.na +.TP +.B nm +.RB "[\|" \-a | \-\-debug\-syms "\|]" +.RB "[\|" \-g | \-\-extern\-only "\|]" +.RB "[\|" \-B "\|]" +.RB "[\|" \-C | \-\-demangle "\|]" +.RB "[\|" \-D | \-\-dynamic "\|]" +.RB "[\|" \-s | \-\-print\-armap "\|]" +.RB "[\|" \-o | \-\-print\-file\-name "\|]" +.RB "[\|" \-n | \-\-numeric\-sort "\|]" +.RB "[\|" \-p | \-\-no\-sort "\|]" +.RB "[\|" \-r | \-\-reverse\-sort "\|]" +.RB "[\|" \-\-size\-sort "\|]" +.RB "[\|" \-u | \-\-undefined\-only "\|]" +.RB "[\|" \-l | \-\-line\-numbers "\|]" +.RB "[\|" \-\-help "\|]" +.RB "[\|" \-\-version "\|]" +.RB "[\|" "\-t \fIradix" | \-\-radix=\fIradix "\|]" +.RB "[\|" \-P | --portability "\|]" +.RB "[\|" "\-f \fIformat" | \-\-format=\fIformat "\|]" +.RB "[\|" "\-\-target=\fIbfdname" "\|]" +.RB "[\|" \c +.I objfile\c +\&.\|.\|.\|] +.ad b +.hy 1 +.SH DESCRIPTION +GNU \c +.B nm\c +\& lists the symbols from object files \c +.I objfile\c +\&. If no object files are given as arguments, \c +.B nm\c +\& assumes `\|\c +.B a.out\c +\|'. + +.SH OPTIONS +The long and short forms of options, shown here as alternatives, are +equivalent. + +.TP +.B \-A +.TP +.B \-o +.TP +.B \-\-print\-file\-name +Precede each symbol by the name of the input file where it was found, +rather than identifying the input file once only before all of its +symbols. + +.TP +.B \-a +.TP +.B \-\-debug\-syms +Display debugger-only symbols; normally these are not listed. + +.TP +.B \-B +The same as +.B \-\-format=bsd +(for compatibility with the MIPS \fBnm\fP). + +.TP +.B \-C +.TP +.B \-\-demangle +Decode (\fIdemangle\fP) low-level symbol names into user-level names. +Besides removing any initial underscore prepended by the system, this +makes C++ function names readable. + +.TP +.B \-D +.TP +.B \-\-dynamic +Display the dynamic symbols rather than the normal symbols. This is +only meaningful for dynamic objects, such as certain types of shared +libraries. + +.TP +.B "\-f \fIformat" +Use the output format \fIformat\fP, which can be ``bsd'', +``sysv'', or ``posix''. The default is ``bsd''. +Only the first character of \fIformat\fP is significant; it can be +either upper or lower case. + +.TP +.B \-g +.TP +.B \-\-extern\-only +Display only external symbols. + +.TP +.B \-n +.TP +.B \-v +.TP +.B \-\-numeric\-sort +Sort symbols numerically by their addresses, not alphabetically by their +names. + +.TP +.B \-p +.TP +.B \-\-no\-sort +Don't bother to sort the symbols in any order; just print them in the +order encountered. + +.TP +.B \-P +.TP +.B \-\-portability +Use the POSIX.2 standard output format instead of the default format. +Equivalent to ``\-f posix''. + +.TP +.B \-s +.TP +.B \-\-print\-armap +When listing symbols from archive members, include the index: a mapping +(stored in the archive by \c +.B ar\c +\& or \c +.B ranlib\c +\&) of what modules +contain definitions for what names. + +.TP +.B \-r +.TP +.B \-\-reverse\-sort +Reverse the sense of the sort (whether numeric or alphabetic); let the +last come first. + +.TP +.B \-\-size\-sort +Sort symbols by size. The size is computed as the difference between +the value of the symbol and the value of the symbol with the next higher +value. The size of the symbol is printed, rather than the value. + +.TP +.B "\-t \fIradix" +.TP +.B "\-\-radix=\fIradix" +Use \fIradix\fP as the radix for printing the symbol values. It must be +``d'' for decimal, ``o'' for octal, or ``x'' for hexadecimal. + +.TP +.BI "\-\-target=" "bfdname" +Specify an object code format other than your system's default format. +See +.BR objdump ( 1 ), +for information on listing available formats. + +.TP +.B \-u +.TP +.B \-\-undefined\-only +Display only undefined symbols (those external to each object file). + +.TP +.B \-l +.TP +.B \-\-line\-numbers +For each symbol, use debugging information to try to find a filename and +line number. For a defined symbol, look for the line number of the +address of the symbol. For an undefined symbol, look for the line +number of a relocation entry which refers to the symbol. If line number +information can be found, print it after the other symbol information. + +.TP +.B \-V +.TP +.B \-\-version +Show the version number of +.B nm +and exit. + +.TP +.B \-\-help +Show a summary of the options to +.B nm +and exit. + +.SH "SEE ALSO" +.RB "`\|" binutils "\|'" +entry in +.B +info\c +\&; +.I +The GNU Binary Utilities\c +\&, Roland H. Pesch (October 1991); +.BR ar "(" 1 ")," +.BR objdump ( 1 ), +.BR ranlib "(" 1 ")." + + +.SH COPYING +Copyright (c) 1991 Free Software Foundation, Inc. +.PP +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. +.PP +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the +entire resulting derived work is distributed under the terms of a +permission notice identical to this one. +.PP +Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be included in +translations approved by the Free Software Foundation instead of in +the original English. diff --git a/binutils/nm.c b/binutils/nm.c new file mode 100644 index 0000000..c51b7fb --- /dev/null +++ b/binutils/nm.c @@ -0,0 +1,1558 @@ +/* nm.c -- Describe symbol table of a rel file. + Copyright 1991, 92, 93, 94, 95, 96, 97, 98, 1999 + Free Software Foundation, Inc. + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#include "bfd.h" +#include "progress.h" +#include "bucomm.h" +#include "getopt.h" +#include "aout/stab_gnu.h" +#include "aout/ranlib.h" +#include "demangle.h" +#include "libiberty.h" + +/* When sorting by size, we use this structure to hold the size and a + pointer to the minisymbol. */ + +struct size_sym +{ + const PTR minisym; + bfd_vma size; +}; + +/* When fetching relocs, we use this structure to pass information to + get_relocs. */ + +struct get_relocs_info +{ + asection **secs; + arelent ***relocs; + long *relcount; + asymbol **syms; +}; + +static void +usage PARAMS ((FILE *, int)); + +static void +set_print_radix PARAMS ((char *)); + +static void +set_output_format PARAMS ((char *)); + +static void +display_archive PARAMS ((bfd *)); + +static boolean +display_file PARAMS ((char *filename)); + +static void +display_rel_file PARAMS ((bfd * file, bfd * archive)); + +static long +filter_symbols PARAMS ((bfd *, boolean, PTR, long, unsigned int)); + +static long +sort_symbols_by_size PARAMS ((bfd *, boolean, PTR, long, unsigned int, + struct size_sym **)); + +static void +print_symbols PARAMS ((bfd *, boolean, PTR, long, unsigned int, bfd *)); + +static void +print_size_symbols PARAMS ((bfd *, boolean, struct size_sym *, long, bfd *)); + +static void +print_symname PARAMS ((const char *, const char *, bfd *)); + +static void +print_symbol PARAMS ((bfd *, asymbol *, bfd *)); + +static void +print_symdef_entry PARAMS ((bfd * abfd)); + +/* The sorting functions. */ + +static int +numeric_forward PARAMS ((const PTR, const PTR)); + +static int +numeric_reverse PARAMS ((const PTR, const PTR)); + +static int +non_numeric_forward PARAMS ((const PTR, const PTR)); + +static int +non_numeric_reverse PARAMS ((const PTR, const PTR)); + +static int +size_forward1 PARAMS ((const PTR, const PTR)); + +static int +size_forward2 PARAMS ((const PTR, const PTR)); + +/* The output formatting functions. */ + +static void +print_object_filename_bsd PARAMS ((char *filename)); + +static void +print_object_filename_sysv PARAMS ((char *filename)); + +static void +print_object_filename_posix PARAMS ((char *filename)); + + +static void +print_archive_filename_bsd PARAMS ((char *filename)); + +static void +print_archive_filename_sysv PARAMS ((char *filename)); + +static void +print_archive_filename_posix PARAMS ((char *filename)); + + +static void +print_archive_member_bsd PARAMS ((char *archive, CONST char *filename)); + +static void +print_archive_member_sysv PARAMS ((char *archive, CONST char *filename)); + +static void +print_archive_member_posix PARAMS ((char *archive, CONST char *filename)); + + +static void +print_symbol_filename_bsd PARAMS ((bfd * archive_bfd, bfd * abfd)); + +static void +print_symbol_filename_sysv PARAMS ((bfd * archive_bfd, bfd * abfd)); + +static void +print_symbol_filename_posix PARAMS ((bfd * archive_bfd, bfd * abfd)); + + +static void +print_value PARAMS ((bfd_vma)); + +static void +print_symbol_info_bsd PARAMS ((symbol_info * info, bfd * abfd)); + +static void +print_symbol_info_sysv PARAMS ((symbol_info * info, bfd * abfd)); + +static void +print_symbol_info_posix PARAMS ((symbol_info * info, bfd * abfd)); + +static void +get_relocs PARAMS ((bfd *, asection *, PTR)); + +/* Support for different output formats. */ +struct output_fns + { + /* Print the name of an object file given on the command line. */ + void (*print_object_filename) PARAMS ((char *filename)); + + /* Print the name of an archive file given on the command line. */ + void (*print_archive_filename) PARAMS ((char *filename)); + + /* Print the name of an archive member file. */ + void (*print_archive_member) PARAMS ((char *archive, CONST char *filename)); + + /* Print the name of the file (and archive, if there is one) + containing a symbol. */ + void (*print_symbol_filename) PARAMS ((bfd * archive_bfd, bfd * abfd)); + + /* Print a line of information about a symbol. */ + void (*print_symbol_info) PARAMS ((symbol_info * info, bfd * abfd)); + }; +static struct output_fns formats[] = +{ + {print_object_filename_bsd, + print_archive_filename_bsd, + print_archive_member_bsd, + print_symbol_filename_bsd, + print_symbol_info_bsd}, + {print_object_filename_sysv, + print_archive_filename_sysv, + print_archive_member_sysv, + print_symbol_filename_sysv, + print_symbol_info_sysv}, + {print_object_filename_posix, + print_archive_filename_posix, + print_archive_member_posix, + print_symbol_filename_posix, + print_symbol_info_posix} +}; + +/* Indices in `formats'. */ +#define FORMAT_BSD 0 +#define FORMAT_SYSV 1 +#define FORMAT_POSIX 2 +#define FORMAT_DEFAULT FORMAT_BSD + +/* The output format to use. */ +static struct output_fns *format = &formats[FORMAT_DEFAULT]; + + +/* Command options. */ + +static int do_demangle = 0; /* Pretty print C++ symbol names. */ +static int external_only = 0; /* print external symbols only */ +static int defined_only = 0; /* Print defined symbols only */ +static int no_sort = 0; /* don't sort; print syms in order found */ +static int print_debug_syms = 0; /* print debugger-only symbols too */ +static int print_armap = 0; /* describe __.SYMDEF data in archive files. */ +static int reverse_sort = 0; /* sort in downward(alpha or numeric) order */ +static int sort_numerically = 0; /* sort in numeric rather than alpha order */ +static int sort_by_size = 0; /* sort by size of symbol */ +static int undefined_only = 0; /* print undefined symbols only */ +static int dynamic = 0; /* print dynamic symbols. */ +static int show_version = 0; /* show the version number */ +static int show_stats = 0; /* show statistics */ +static int line_numbers = 0; /* print line numbers for symbols */ + +/* When to print the names of files. Not mutually exclusive in SYSV format. */ +static int filename_per_file = 0; /* Once per file, on its own line. */ +static int filename_per_symbol = 0; /* Once per symbol, at start of line. */ + +/* Print formats for printing a symbol value. */ +#ifndef BFD64 +static char value_format[] = "%08lx"; +#else +#if BFD_HOST_64BIT_LONG +static char value_format[] = "%016lx"; +#else +/* We don't use value_format for this case. */ +#endif +#endif +static int print_radix = 16; +/* Print formats for printing stab info. */ +static char other_format[] = "%02x"; +static char desc_format[] = "%04x"; + +static char *target = NULL; + +/* Used to cache the line numbers for a BFD. */ +static bfd *lineno_cache_bfd; +static bfd *lineno_cache_rel_bfd; + +static struct option long_options[] = +{ + {"debug-syms", no_argument, &print_debug_syms, 1}, + {"demangle", no_argument, &do_demangle, 1}, + {"dynamic", no_argument, &dynamic, 1}, + {"extern-only", no_argument, &external_only, 1}, + {"format", required_argument, 0, 'f'}, + {"help", no_argument, 0, 'h'}, + {"line-numbers", no_argument, 0, 'l'}, + {"no-cplus", no_argument, &do_demangle, 0}, /* Linux compatibility. */ + {"no-demangle", no_argument, &do_demangle, 0}, + {"no-sort", no_argument, &no_sort, 1}, + {"numeric-sort", no_argument, &sort_numerically, 1}, + {"portability", no_argument, 0, 'P'}, + {"print-armap", no_argument, &print_armap, 1}, + {"print-file-name", no_argument, 0, 'o'}, + {"radix", required_argument, 0, 't'}, + {"reverse-sort", no_argument, &reverse_sort, 1}, + {"size-sort", no_argument, &sort_by_size, 1}, + {"stats", no_argument, &show_stats, 1}, + {"target", required_argument, 0, 200}, + {"defined-only", no_argument, &defined_only, 1}, + {"undefined-only", no_argument, &undefined_only, 1}, + {"version", no_argument, &show_version, 1}, + {0, no_argument, 0, 0} +}; + +/* Some error-reporting functions */ + +static void +usage (stream, status) + FILE *stream; + int status; +{ + fprintf (stream, _("\ +Usage: %s [-aABCDglnopPrsuvV] [-t radix] [--radix=radix] [--target=bfdname]\n\ + [--debug-syms] [--extern-only] [--print-armap] [--print-file-name]\n\ + [--numeric-sort] [--no-sort] [--reverse-sort] [--size-sort]\n\ + [--undefined-only] [--portability] [-f {bsd,sysv,posix}]\n\ + [--format={bsd,sysv,posix}] [--demangle] [--no-demangle] [--dynamic]\n\ + [--defined-only] [--line-numbers]\n\ + [--version] [--help]\n\ + [file...]\n"), + program_name); + list_supported_targets (program_name, stream); + if (status == 0) + fprintf (stream, _("Report bugs to bug-gnu-utils@gnu.org\n")); + exit (status); +} + +/* Set the radix for the symbol value and size according to RADIX. */ + +static void +set_print_radix (radix) + char *radix; +{ + switch (*radix) + { + case 'x': + break; + case 'd': + case 'o': + if (*radix == 'd') + print_radix = 10; + else + print_radix = 8; +#ifndef BFD64 + value_format[4] = *radix; +#else +#if BFD_HOST_64BIT_LONG + value_format[5] = *radix; +#else + /* This case requires special handling for octal and decimal + printing. */ +#endif +#endif + other_format[3] = desc_format[3] = *radix; + break; + default: + fprintf (stderr, _("%s: %s: invalid radix\n"), program_name, radix); + exit (1); + } +} + +static void +set_output_format (f) + char *f; +{ + int i; + + switch (*f) + { + case 'b': + case 'B': + i = FORMAT_BSD; + break; + case 'p': + case 'P': + i = FORMAT_POSIX; + break; + case 's': + case 'S': + i = FORMAT_SYSV; + break; + default: + fprintf (stderr, _("%s: %s: invalid output format\n"), program_name, f); + exit (1); + } + format = &formats[i]; +} + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int retval; + +#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) + setlocale (LC_MESSAGES, ""); +#endif + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + + program_name = *argv; + xmalloc_set_program_name (program_name); + + START_PROGRESS (program_name, 0); + + bfd_init (); + set_default_bfd_target (); + + while ((c = getopt_long (argc, argv, "aABCDef:glnopPrst:uvV", long_options, (int *) 0)) != EOF) + { + switch (c) + { + case 'a': + print_debug_syms = 1; + break; + case 'A': + case 'o': + filename_per_symbol = 1; + break; + case 'B': /* For MIPS compatibility. */ + set_output_format ("bsd"); + break; + case 'C': + do_demangle = 1; + break; + case 'D': + dynamic = 1; + break; + case 'e': + /* Ignored for HP/UX compatibility. */ + break; + case 'f': + set_output_format (optarg); + break; + case 'g': + external_only = 1; + break; + case 'h': + usage (stdout, 0); + case 'l': + line_numbers = 1; + break; + case 'n': + case 'v': + sort_numerically = 1; + break; + case 'p': + no_sort = 1; + break; + case 'P': + set_output_format ("posix"); + break; + case 'r': + reverse_sort = 1; + break; + case 's': + print_armap = 1; + break; + case 't': + set_print_radix (optarg); + break; + case 'u': + undefined_only = 1; + break; + case 'V': + show_version = 1; + break; + + case 200: /* --target */ + target = optarg; + break; + + case 0: /* A long option that just sets a flag. */ + break; + + default: + usage (stderr, 1); + } + } + + if (show_version) + print_version ("nm"); + + /* OK, all options now parsed. If no filename specified, do a.out. */ + if (optind == argc) + return !display_file ("a.out"); + + retval = 0; + + if (argc - optind > 1) + filename_per_file = 1; + + /* We were given several filenames to do. */ + while (optind < argc) + { + PROGRESS (1); + if (!display_file (argv[optind++])) + retval++; + } + + END_PROGRESS (program_name); + +#ifdef HAVE_SBRK + if (show_stats) + { + char *lim = (char *) sbrk (0); + + fprintf (stderr, _("%s: data size %ld\n"), program_name, + (long) (lim - (char *) &environ)); + } +#endif + + exit (retval); + return retval; +} + +static void +display_archive (file) + bfd *file; +{ + bfd *arfile = NULL; + bfd *last_arfile = NULL; + char **matching; + + (*format->print_archive_filename) (bfd_get_filename (file)); + + if (print_armap) + print_symdef_entry (file); + + for (;;) + { + PROGRESS (1); + + arfile = bfd_openr_next_archived_file (file, arfile); + + if (arfile == NULL) + { + if (bfd_get_error () != bfd_error_no_more_archived_files) + bfd_fatal (bfd_get_filename (file)); + break; + } + + if (bfd_check_format_matches (arfile, bfd_object, &matching)) + { + (*format->print_archive_member) (bfd_get_filename (file), + bfd_get_filename (arfile)); + display_rel_file (arfile, file); + } + else + { + bfd_nonfatal (bfd_get_filename (arfile)); + if (bfd_get_error () == bfd_error_file_ambiguously_recognized) + { + list_matching_formats (matching); + free (matching); + } + } + + if (last_arfile != NULL) + { + bfd_close (last_arfile); + lineno_cache_bfd = NULL; + lineno_cache_rel_bfd = NULL; + } + last_arfile = arfile; + } + + if (last_arfile != NULL) + { + bfd_close (last_arfile); + lineno_cache_bfd = NULL; + lineno_cache_rel_bfd = NULL; + } +} + +static boolean +display_file (filename) + char *filename; +{ + boolean retval = true; + bfd *file; + char **matching; + + file = bfd_openr (filename, target); + if (file == NULL) + { + bfd_nonfatal (filename); + return false; + } + + if (bfd_check_format (file, bfd_archive)) + { + display_archive (file); + } + else if (bfd_check_format_matches (file, bfd_object, &matching)) + { + (*format->print_object_filename) (filename); + display_rel_file (file, NULL); + } + else + { + bfd_nonfatal (filename); + if (bfd_get_error () == bfd_error_file_ambiguously_recognized) + { + list_matching_formats (matching); + free (matching); + } + retval = false; + } + + if (bfd_close (file) == false) + bfd_fatal (filename); + + lineno_cache_bfd = NULL; + lineno_cache_rel_bfd = NULL; + + return retval; +} + +/* These globals are used to pass information into the sorting + routines. */ +static bfd *sort_bfd; +static boolean sort_dynamic; +static asymbol *sort_x; +static asymbol *sort_y; + +/* Symbol-sorting predicates */ +#define valueof(x) ((x)->section->vma + (x)->value) + +/* Numeric sorts. Undefined symbols are always considered "less than" + defined symbols with zero values. Common symbols are not treated + specially -- i.e., their sizes are used as their "values". */ + +static int +numeric_forward (P_x, P_y) + const PTR P_x; + const PTR P_y; +{ + asymbol *x, *y; + asection *xs, *ys; + + x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x); + y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y); + if (x == NULL || y == NULL) + bfd_fatal (bfd_get_filename (sort_bfd)); + + xs = bfd_get_section (x); + ys = bfd_get_section (y); + + if (bfd_is_und_section (xs)) + { + if (! bfd_is_und_section (ys)) + return -1; + } + else if (bfd_is_und_section (ys)) + return 1; + else if (valueof (x) != valueof (y)) + return valueof (x) < valueof (y) ? -1 : 1; + + return non_numeric_forward (P_x, P_y); +} + +static int +numeric_reverse (x, y) + const PTR x; + const PTR y; +{ + return - numeric_forward (x, y); +} + +static int +non_numeric_forward (P_x, P_y) + const PTR P_x; + const PTR P_y; +{ + asymbol *x, *y; + const char *xn, *yn; + + x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x); + y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y); + if (x == NULL || y == NULL) + bfd_fatal (bfd_get_filename (sort_bfd)); + + xn = bfd_asymbol_name (x); + yn = bfd_asymbol_name (y); + + return ((xn == NULL) ? ((yn == NULL) ? 0 : -1) : + ((yn == NULL) ? 1 : strcmp (xn, yn))); +} + +static int +non_numeric_reverse (x, y) + const PTR x; + const PTR y; +{ + return - non_numeric_forward (x, y); +} + +static int (*(sorters[2][2])) PARAMS ((const PTR, const PTR)) = +{ + { non_numeric_forward, non_numeric_reverse }, + { numeric_forward, numeric_reverse } +}; + +/* This sort routine is used by sort_symbols_by_size. It is similar + to numeric_forward, but when symbols have the same value it sorts + by section VMA. This simplifies the sort_symbols_by_size code + which handles symbols at the end of sections. Also, this routine + tries to sort file names before other symbols with the same value. + That will make the file name have a zero size, which will make + sort_symbols_by_size choose the non file name symbol, leading to + more meaningful output. For similar reasons, this code sorts + gnu_compiled_* and gcc2_compiled before other symbols with the same + value. */ + +static int +size_forward1 (P_x, P_y) + const PTR P_x; + const PTR P_y; +{ + asymbol *x, *y; + asection *xs, *ys; + const char *xn, *yn; + size_t xnl, ynl; + int xf, yf; + + x = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_x, sort_x); + y = bfd_minisymbol_to_symbol (sort_bfd, sort_dynamic, P_y, sort_y); + if (x == NULL || y == NULL) + bfd_fatal (bfd_get_filename (sort_bfd)); + + xs = bfd_get_section (x); + ys = bfd_get_section (y); + + if (bfd_is_und_section (xs)) + abort (); + if (bfd_is_und_section (ys)) + abort (); + + if (valueof (x) != valueof (y)) + return valueof (x) < valueof (y) ? -1 : 1; + + if (xs->vma != ys->vma) + return xs->vma < ys->vma ? -1 : 1; + + xn = bfd_asymbol_name (x); + yn = bfd_asymbol_name (y); + xnl = strlen (xn); + ynl = strlen (yn); + + /* The symbols gnu_compiled and gcc2_compiled convey even less + information than the file name, so sort them out first. */ + + xf = (strstr (xn, "gnu_compiled") != NULL + || strstr (xn, "gcc2_compiled") != NULL); + yf = (strstr (yn, "gnu_compiled") != NULL + || strstr (yn, "gcc2_compiled") != NULL); + + if (xf && ! yf) + return -1; + if (! xf && yf) + return 1; + + /* We use a heuristic for the file name. It may not work on non + Unix systems, but it doesn't really matter; the only difference + is precisely which symbol names get printed. */ + +#define file_symbol(s, sn, snl) \ + (((s)->flags & BSF_FILE) != 0 \ + || ((sn)[(snl) - 2] == '.' \ + && ((sn)[(snl) - 1] == 'o' \ + || (sn)[(snl) - 1] == 'a'))) + + xf = file_symbol (x, xn, xnl); + yf = file_symbol (y, yn, ynl); + + if (xf && ! yf) + return -1; + if (! xf && yf) + return 1; + + return non_numeric_forward (P_x, P_y); +} + +/* This sort routine is used by sort_symbols_by_size. It is sorting + an array of size_sym structures into size order. */ + +static int +size_forward2 (P_x, P_y) + const PTR P_x; + const PTR P_y; +{ + const struct size_sym *x = (const struct size_sym *) P_x; + const struct size_sym *y = (const struct size_sym *) P_y; + + if (x->size < y->size) + return reverse_sort ? 1 : -1; + else if (x->size > y->size) + return reverse_sort ? -1 : 1; + else + return sorters[0][reverse_sort] (x->minisym, y->minisym); +} + +/* Sort the symbols by size. We guess the size by assuming that the + difference between the address of a symbol and the address of the + next higher symbol is the size. FIXME: ELF actually stores a size + with each symbol. We should use it. */ + +static long +sort_symbols_by_size (abfd, dynamic, minisyms, symcount, size, symsizesp) + bfd *abfd; + boolean dynamic; + PTR minisyms; + long symcount; + unsigned int size; + struct size_sym **symsizesp; +{ + struct size_sym *symsizes; + bfd_byte *from, *fromend; + asymbol *sym = NULL; + asymbol *store_sym, *store_next; + + qsort (minisyms, symcount, size, size_forward1); + + /* We are going to return a special set of symbols and sizes to + print. */ + symsizes = (struct size_sym *) xmalloc (symcount * sizeof (struct size_sym)); + *symsizesp = symsizes; + + /* Note that filter_symbols has already removed all absolute and + undefined symbols. Here we remove all symbols whose size winds + up as zero. */ + + from = (bfd_byte *) minisyms; + fromend = from + symcount * size; + + store_sym = sort_x; + store_next = sort_y; + + if (from < fromend) + { + sym = bfd_minisymbol_to_symbol (abfd, dynamic, (const PTR) from, + store_sym); + if (sym == NULL) + bfd_fatal (bfd_get_filename (abfd)); + } + + for (; from < fromend; from += size) + { + asymbol *next; + asection *sec; + bfd_vma sz; + asymbol *temp; + + if (from + size < fromend) + { + next = bfd_minisymbol_to_symbol (abfd, + dynamic, + (const PTR) (from + size), + store_next); + if (next == NULL) + bfd_fatal (bfd_get_filename (abfd)); + } + else + next = NULL; + + sec = bfd_get_section (sym); + + if (bfd_is_com_section (sec)) + sz = sym->value; + else + { + if (from + size < fromend + && sec == bfd_get_section (next)) + sz = valueof (next) - valueof (sym); + else + sz = (bfd_get_section_vma (abfd, sec) + + bfd_section_size (abfd, sec) + - valueof (sym)); + } + + if (sz != 0) + { + symsizes->minisym = (const PTR) from; + symsizes->size = sz; + ++symsizes; + } + + sym = next; + + temp = store_sym; + store_sym = store_next; + store_next = temp; + } + + symcount = symsizes - *symsizesp; + + /* We must now sort again by size. */ + qsort ((PTR) *symsizesp, symcount, sizeof (struct size_sym), size_forward2); + + return symcount; +} + +/* If ARCHIVE_BFD is non-NULL, it is the archive containing ABFD. */ + +static void +display_rel_file (abfd, archive_bfd) + bfd *abfd; + bfd *archive_bfd; +{ + long symcount; + PTR minisyms; + unsigned int size; + struct size_sym *symsizes; + + if (! dynamic) + { + if (!(bfd_get_file_flags (abfd) & HAS_SYMS)) + { + fprintf (stderr, _("%s: no symbols\n"), bfd_get_filename (abfd)); + return; + } + } + + symcount = bfd_read_minisymbols (abfd, dynamic, &minisyms, &size); + if (symcount < 0) + bfd_fatal (bfd_get_filename (abfd)); + + if (symcount == 0) + { + fprintf (stderr, _("%s: no symbols\n"), bfd_get_filename (abfd)); + return; + } + + /* Discard the symbols we don't want to print. + It's OK to do this in place; we'll free the storage anyway + (after printing). */ + + symcount = filter_symbols (abfd, dynamic, minisyms, symcount, size); + + symsizes = NULL; + if (! no_sort) + { + sort_bfd = abfd; + sort_dynamic = dynamic; + sort_x = bfd_make_empty_symbol (abfd); + sort_y = bfd_make_empty_symbol (abfd); + if (sort_x == NULL || sort_y == NULL) + bfd_fatal (bfd_get_filename (abfd)); + + if (! sort_by_size) + qsort (minisyms, symcount, size, + sorters[sort_numerically][reverse_sort]); + else + symcount = sort_symbols_by_size (abfd, dynamic, minisyms, symcount, + size, &symsizes); + } + + if (! sort_by_size) + print_symbols (abfd, dynamic, minisyms, symcount, size, archive_bfd); + else + print_size_symbols (abfd, dynamic, symsizes, symcount, archive_bfd); + + free (minisyms); +} + +/* Choose which symbol entries to print; + compact them downward to get rid of the rest. + Return the number of symbols to be printed. */ + +static long +filter_symbols (abfd, dynamic, minisyms, symcount, size) + bfd *abfd; + boolean dynamic; + PTR minisyms; + long symcount; + unsigned int size; +{ + bfd_byte *from, *fromend, *to; + asymbol *store; + + store = bfd_make_empty_symbol (abfd); + if (store == NULL) + bfd_fatal (bfd_get_filename (abfd)); + + from = (bfd_byte *) minisyms; + fromend = from + symcount * size; + to = (bfd_byte *) minisyms; + + for (; from < fromend; from += size) + { + int keep = 0; + asymbol *sym; + + PROGRESS (1); + + sym = bfd_minisymbol_to_symbol (abfd, dynamic, (const PTR) from, store); + if (sym == NULL) + bfd_fatal (bfd_get_filename (abfd)); + + if (undefined_only) + keep = bfd_is_und_section (sym->section); + else if (external_only) + keep = ((sym->flags & BSF_GLOBAL) != 0 + || (sym->flags & BSF_WEAK) != 0 + || bfd_is_und_section (sym->section) + || bfd_is_com_section (sym->section)); + else + keep = 1; + + if (keep + && ! print_debug_syms + && (sym->flags & BSF_DEBUGGING) != 0) + keep = 0; + + if (keep + && sort_by_size + && (bfd_is_abs_section (sym->section) + || bfd_is_und_section (sym->section))) + keep = 0; + + if (keep + && defined_only) + { + if (bfd_is_und_section (sym->section)) + keep = 0; + } + + if (keep) + { + memcpy (to, from, size); + to += size; + } + } + + return (to - (bfd_byte *) minisyms) / size; +} + +/* Print symbol name NAME, read from ABFD, with printf format FORMAT, + demangling it if requested. */ + +static void +print_symname (format, name, abfd) + const char *format; + const char *name; + bfd *abfd; +{ + if (do_demangle && *name) + { + char *res; + + /* In this mode, give a user-level view of the symbol name + even if it's not mangled; strip off any leading + underscore. */ + if (bfd_get_symbol_leading_char (abfd) == name[0]) + name++; + + res = cplus_demangle (name, DMGL_ANSI | DMGL_PARAMS); + if (res) + { + printf (format, res); + free (res); + return; + } + } + + printf (format, name); +} + +/* Print the symbols. If ARCHIVE_BFD is non-NULL, it is the archive + containing ABFD. */ + +static void +print_symbols (abfd, dynamic, minisyms, symcount, size, archive_bfd) + bfd *abfd; + boolean dynamic; + PTR minisyms; + long symcount; + unsigned int size; + bfd *archive_bfd; +{ + asymbol *store; + bfd_byte *from, *fromend; + + store = bfd_make_empty_symbol (abfd); + if (store == NULL) + bfd_fatal (bfd_get_filename (abfd)); + + from = (bfd_byte *) minisyms; + fromend = from + symcount * size; + for (; from < fromend; from += size) + { + asymbol *sym; + + sym = bfd_minisymbol_to_symbol (abfd, dynamic, from, store); + if (sym == NULL) + bfd_fatal (bfd_get_filename (abfd)); + + print_symbol (abfd, sym, archive_bfd); + } +} + +/* Print the symbols when sorting by size. */ + +static void +print_size_symbols (abfd, dynamic, symsizes, symcount, archive_bfd) + bfd *abfd; + boolean dynamic; + struct size_sym *symsizes; + long symcount; + bfd *archive_bfd; +{ + asymbol *store; + struct size_sym *from, *fromend; + + store = bfd_make_empty_symbol (abfd); + if (store == NULL) + bfd_fatal (bfd_get_filename (abfd)); + + from = symsizes; + fromend = from + symcount; + for (; from < fromend; from++) + { + asymbol *sym; + + sym = bfd_minisymbol_to_symbol (abfd, dynamic, from->minisym, store); + if (sym == NULL) + bfd_fatal (bfd_get_filename (abfd)); + + /* Set the symbol value so that we actually display the symbol + size. */ + sym->value = from->size - bfd_section_vma (abfd, bfd_get_section (sym)); + + print_symbol (abfd, sym, archive_bfd); + } +} + +/* Print a single symbol. */ + +static void +print_symbol (abfd, sym, archive_bfd) + bfd *abfd; + asymbol *sym; + bfd *archive_bfd; +{ + PROGRESS (1); + + (*format->print_symbol_filename) (archive_bfd, abfd); + + if (undefined_only) + { + if (bfd_is_und_section (bfd_get_section (sym))) + print_symname ("%s", bfd_asymbol_name (sym), abfd); + } + else + { + symbol_info syminfo; + + bfd_get_symbol_info (abfd, sym, &syminfo); + (*format->print_symbol_info) (&syminfo, abfd); + } + + if (line_numbers) + { + static asymbol **syms; + static long symcount; + const char *filename, *functionname; + unsigned int lineno; + + /* We need to get the canonical symbols in order to call + bfd_find_nearest_line. This is inefficient, but, then, you + don't have to use --line-numbers. */ + if (abfd != lineno_cache_bfd && syms != NULL) + { + free (syms); + syms = NULL; + } + if (syms == NULL) + { + long symsize; + + symsize = bfd_get_symtab_upper_bound (abfd); + if (symsize < 0) + bfd_fatal (bfd_get_filename (abfd)); + syms = (asymbol **) xmalloc (symsize); + symcount = bfd_canonicalize_symtab (abfd, syms); + if (symcount < 0) + bfd_fatal (bfd_get_filename (abfd)); + lineno_cache_bfd = abfd; + } + + if (bfd_is_und_section (bfd_get_section (sym))) + { + static asection **secs; + static arelent ***relocs; + static long *relcount; + static unsigned int seccount; + unsigned int i; + const char *symname; + + /* For an undefined symbol, we try to find a reloc for the + symbol, and print the line number of the reloc. */ + + if (abfd != lineno_cache_rel_bfd && relocs != NULL) + { + for (i = 0; i < seccount; i++) + if (relocs[i] != NULL) + free (relocs[i]); + free (secs); + free (relocs); + free (relcount); + secs = NULL; + relocs = NULL; + relcount = NULL; + } + + if (relocs == NULL) + { + struct get_relocs_info info; + + seccount = bfd_count_sections (abfd); + + secs = (asection **) xmalloc (seccount * sizeof *secs); + relocs = (arelent ***) xmalloc (seccount * sizeof *relocs); + relcount = (long *) xmalloc (seccount * sizeof *relcount); + + info.secs = secs; + info.relocs = relocs; + info.relcount = relcount; + info.syms = syms; + bfd_map_over_sections (abfd, get_relocs, (PTR) &info); + lineno_cache_rel_bfd = abfd; + } + + symname = bfd_asymbol_name (sym); + for (i = 0; i < seccount; i++) + { + long j; + + for (j = 0; j < relcount[i]; j++) + { + arelent *r; + + r = relocs[i][j]; + if (r->sym_ptr_ptr != NULL + && (*r->sym_ptr_ptr)->section == sym->section + && (*r->sym_ptr_ptr)->value == sym->value + && strcmp (symname, + bfd_asymbol_name (*r->sym_ptr_ptr)) == 0 + && bfd_find_nearest_line (abfd, secs[i], syms, + r->address, &filename, + &functionname, &lineno)) + { + /* We only print the first one we find. */ + printf ("\t%s:%u", filename, lineno); + i = seccount; + break; + } + } + } + } + else if (bfd_get_section (sym)->owner == abfd) + { + if (bfd_find_nearest_line (abfd, bfd_get_section (sym), syms, + sym->value, &filename, &functionname, + &lineno) + && filename != NULL + && lineno != 0) + { + printf ("\t%s:%u", filename, lineno); + } + } + } + + putchar ('\n'); +} + +/* The following 3 groups of functions are called unconditionally, + once at the start of processing each file of the appropriate type. + They should check `filename_per_file' and `filename_per_symbol', + as appropriate for their output format, to determine whether to + print anything. */ + +/* Print the name of an object file given on the command line. */ + +static void +print_object_filename_bsd (filename) + char *filename; +{ + if (filename_per_file && !filename_per_symbol) + printf ("\n%s:\n", filename); +} + +static void +print_object_filename_sysv (filename) + char *filename; +{ + if (undefined_only) + printf (_("\n\nUndefined symbols from %s:\n\n"), filename); + else + printf (_("\n\nSymbols from %s:\n\n"), filename); + printf (_("\ +Name Value Class Type Size Line Section\n\n")); +} + +static void +print_object_filename_posix (filename) + char *filename; +{ + if (filename_per_file && !filename_per_symbol) + printf ("%s:\n", filename); +} + +/* Print the name of an archive file given on the command line. */ + +static void +print_archive_filename_bsd (filename) + char *filename; +{ + if (filename_per_file) + printf ("\n%s:\n", filename); +} + +static void +print_archive_filename_sysv (filename) + char *filename; +{ +} + +static void +print_archive_filename_posix (filename) + char *filename; +{ +} + +/* Print the name of an archive member file. */ + +static void +print_archive_member_bsd (archive, filename) + char *archive; + CONST char *filename; +{ + if (!filename_per_symbol) + printf ("\n%s:\n", filename); +} + +static void +print_archive_member_sysv (archive, filename) + char *archive; + CONST char *filename; +{ + if (undefined_only) + printf (_("\n\nUndefined symbols from %s[%s]:\n\n"), archive, filename); + else + printf (_("\n\nSymbols from %s[%s]:\n\n"), archive, filename); + printf (_("\ +Name Value Class Type Size Line Section\n\n")); +} + +static void +print_archive_member_posix (archive, filename) + char *archive; + CONST char *filename; +{ + if (!filename_per_symbol) + printf ("%s[%s]:\n", archive, filename); +} + +/* Print the name of the file (and archive, if there is one) + containing a symbol. */ + +static void +print_symbol_filename_bsd (archive_bfd, abfd) + bfd *archive_bfd, *abfd; +{ + if (filename_per_symbol) + { + if (archive_bfd) + printf ("%s:", bfd_get_filename (archive_bfd)); + printf ("%s:", bfd_get_filename (abfd)); + } +} + +static void +print_symbol_filename_sysv (archive_bfd, abfd) + bfd *archive_bfd, *abfd; +{ + if (filename_per_symbol) + { + if (archive_bfd) + printf ("%s:", bfd_get_filename (archive_bfd)); + printf ("%s:", bfd_get_filename (abfd)); + } +} + +static void +print_symbol_filename_posix (archive_bfd, abfd) + bfd *archive_bfd, *abfd; +{ + if (filename_per_symbol) + { + if (archive_bfd) + printf ("%s[%s]: ", bfd_get_filename (archive_bfd), + bfd_get_filename (abfd)); + else + printf ("%s: ", bfd_get_filename (abfd)); + } +} + +/* Print a symbol value. */ + +static void +print_value (val) + bfd_vma val; +{ +#if ! defined (BFD64) || BFD_HOST_64BIT_LONG + printf (value_format, val); +#else + /* We have a 64 bit value to print, but the host is only 32 bit. */ + if (print_radix == 16) + fprintf_vma (stdout, val); + else + { + char buf[30]; + char *s; + + s = buf + sizeof buf; + *--s = '\0'; + while (val > 0) + { + *--s = (val % print_radix) + '0'; + val /= print_radix; + } + while ((buf + sizeof buf - 1) - s < 16) + *--s = '0'; + printf ("%s", s); + } +#endif +} + +/* Print a line of information about a symbol. */ + +static void +print_symbol_info_bsd (info, abfd) + symbol_info *info; + bfd *abfd; +{ + if (info->type == 'U') + { + printf ("%*s", +#ifdef BFD64 + 16, +#else + 8, +#endif + ""); + } + else + print_value (info->value); + printf (" %c", info->type); + if (info->type == '-') + { + /* A stab. */ + printf (" "); + printf (other_format, info->stab_other); + printf (" "); + printf (desc_format, info->stab_desc); + printf (" %5s", info->stab_name); + } + print_symname (" %s", info->name, abfd); +} + +static void +print_symbol_info_sysv (info, abfd) + symbol_info *info; + bfd *abfd; +{ + print_symname ("%-20s|", info->name, abfd); /* Name */ + if (info->type == 'U') + printf (" "); /* Value */ + else + print_value (info->value); + printf ("| %c |", info->type); /* Class */ + if (info->type == '-') + { + /* A stab. */ + printf ("%18s| ", info->stab_name); /* (C) Type */ + printf (desc_format, info->stab_desc); /* Size */ + printf ("| |"); /* Line, Section */ + } + else + printf (" | | |"); /* Type, Size, Line, Section */ +} + +static void +print_symbol_info_posix (info, abfd) + symbol_info *info; + bfd *abfd; +{ + print_symname ("%s ", info->name, abfd); + printf ("%c ", info->type); + if (info->type == 'U') + printf (" "); + else + print_value (info->value); + /* POSIX.2 wants the symbol size printed here, when applicable; + BFD currently doesn't provide it, so we take the easy way out by + considering it to never be applicable. */ +} + +static void +print_symdef_entry (abfd) + bfd *abfd; +{ + symindex idx = BFD_NO_MORE_SYMBOLS; + carsym *thesym; + boolean everprinted = false; + + for (idx = bfd_get_next_mapent (abfd, idx, &thesym); + idx != BFD_NO_MORE_SYMBOLS; + idx = bfd_get_next_mapent (abfd, idx, &thesym)) + { + bfd *elt; + if (!everprinted) + { + printf (_("\nArchive index:\n")); + everprinted = true; + } + elt = bfd_get_elt_at_index (abfd, idx); + if (elt == NULL) + bfd_fatal ("bfd_get_elt_at_index"); + if (thesym->name != (char *) NULL) + { + print_symname ("%s", thesym->name, abfd); + printf (" in %s\n", bfd_get_filename (elt)); + } + } +} + +/* This function is used to get the relocs for a particular section. + It is called via bfd_map_over_sections. */ + +static void +get_relocs (abfd, sec, dataarg) + bfd *abfd; + asection *sec; + PTR dataarg; +{ + struct get_relocs_info *data = (struct get_relocs_info *) dataarg; + + *data->secs = sec; + + if ((sec->flags & SEC_RELOC) == 0) + { + *data->relocs = NULL; + *data->relcount = 0; + } + else + { + long relsize; + + relsize = bfd_get_reloc_upper_bound (abfd, sec); + if (relsize < 0) + bfd_fatal (bfd_get_filename (abfd)); + + *data->relocs = (arelent **) xmalloc (relsize); + *data->relcount = bfd_canonicalize_reloc (abfd, sec, *data->relocs, + data->syms); + if (*data->relcount < 0) + bfd_fatal (bfd_get_filename (abfd)); + } + + ++data->secs; + ++data->relocs; + ++data->relcount; +} diff --git a/binutils/not-ranlib.c b/binutils/not-ranlib.c new file mode 100644 index 0000000..afb9ceb --- /dev/null +++ b/binutils/not-ranlib.c @@ -0,0 +1,3 @@ +/* Linked with ar.o to flag that this program is 'ar' (not 'ranlib'). */ + +int is_ranlib = 0; diff --git a/binutils/not-strip.c b/binutils/not-strip.c new file mode 100644 index 0000000..98093ce --- /dev/null +++ b/binutils/not-strip.c @@ -0,0 +1,4 @@ +/* Linked with objcopy.o to flag that this program is 'objcopy' (not + 'strip'). */ + +int is_strip = 0; diff --git a/binutils/objcopy.1 b/binutils/objcopy.1 new file mode 100644 index 0000000..aee7760 --- /dev/null +++ b/binutils/objcopy.1 @@ -0,0 +1,319 @@ +.\" Copyright (c) 1991, 93, 94, 95, 96, 97, 1998 Free Software Foundation +.\" See section COPYING for conditions for redistribution +.TH objcopy 1 "October 1994" "cygnus support" "GNU Development Tools" +.de BP +.sp +.ti \-.2i +\(** +.. + +.SH NAME +objcopy \- copy and translate object files + +.SH SYNOPSIS +.hy 0 +.na +.TP +.B objcopy +.RB "[\|" \-F\ \fIbfdname\fR\ |\ \fB\-\-target=\fIbfdname\fR "\|]" +.RB "[\|" \-I\ \fIbfdname\fR\ |\ \fB\-\-input\-target=\fIbfdname\fR "\|]" +.RB "[\|" \-O\ \fIbfdname\fR\ |\ \fB\-\-output\-target=\fIbfdname\fR "\|]" +.RB "[\|" \-R\ \fIsectionname\fR\ |\ \fB\-\-remove\-section=\fIsectionname\fR "\|]" +.RB "[\|" \-S\fR\ |\ \fB\-\-strip\-all\fR "\|]" +.RB "[\|" \-g\fR\ |\ \fB\-\-strip\-debug\fR "\|]" +.RB "[\|" \-\-strip\-unneeded\fR "\|]" +.RB "[\|" \-K\ \fIsymbolname\fR\ |\ \fB\-\-keep\-symbol=\fIsymbolname\fR "\|]" +.RB "[\|" \-N\ \fIsymbolname\fR\ |\ \fB\-\-strip\-symbol=\fIsymbolname\fR "\|]" +.RB "[\|" \-L\ \fIsymbolname\fR\ |\ \fB\-\-localize\-symbol=\fIsymbolname\fR "\|]" +.RB "[\|" \-W\ \fIsymbolname\fR\ |\ \fB\-\-weaken\-symbol=\fIsymbolname\fR "\|]" +.RB "[\|" \-x\fR\ |\ \fB\-\-discard\-all\fR "\|]" +.RB "[\|" \-X\fR\ |\ \fB\-\-discard\-locals\fR "\|]" +.RB "[\|" \-b\ \fIbyte\fR\ |\ \fB\-\-byte=\fIbyte\fR "\|]" +.RB "[\|" \-i\ \fIinterleave\fR\ |\ \fB\-\-interleave=\fIinterleave\fR "\|]" +.RB "[\|" \-p\fR\ |\ \fB\-\-preserve\-dates\fR "\|]" +.RB "[\|" \-\-debugging "\|]" +.RB "[\|" \-\-gap\-fill=\fIval\fR "\|]" +.RB "[\|" \-\-pad\-to=\fIaddress\fR "\|]" +.RB "[\|" \-\-set\-start=\fIval\fR "\|]" +.RB "[\|" \-\-change\-start=\fIincr\fR "\|]" +.RB "[\|" \-\-change\-addresses=\fIincr\fR "\|]" +.RB "[\|" \-\-change\-section\-address=\fIsection{=,+,-}val\fR "\|]" +.RB "[\|" \-\-change\-section\-lma=\fIsection{=,+,-}val\fR "\|]" +.RB "[\|" \-\-change\-section\-vma=\fIsection{=,+,-}val\fR "\|]" +.RB "[\|" \-\-change\-warnings\fR "\|]" +.RB "[\|" \-\-no\-change\-warnings\fR "\|]" +.RB "[\|" \-\-set\-section\-flags=\fIsection=flags\fR "\|]" +.RB "[\|" \-\-add\-section=\fIsectionname=filename\fR "\|]" +.RB "[\|" \-\-change\-leading\-char\fR "\|]" +.RB "[\|" \-\-remove\-leading\-char\fR "\|]" +.RB "[\|" \-\-weaken\fR "\|]" +.RB "[\|" \-v\ |\ \-\-verbose\fR "\|]" +.RB "[\|" \-V\ |\ \-\-version\fR "\|]" +.RB "[\|" \-\-help\fR "\|]" +.B infile +.RB "[\|" outfile\fR "\|]" +.SH DESCRIPTION +The GNU +.B objcopy +utility copies the contents of an object file to another. +.B objcopy +uses the GNU BFD Library to read and write the object files. It can +write the destination object file in a format different from that of +the source object file. The exact behavior of +.B objcopy +is controlled by command-line options. +.PP +.B objcopy +creates temporary files to do its translations and deletes them +afterward. +.B objcopy +uses BFD to do all its translation work; it knows about all the +formats BFD knows about, and thus is able to recognize most formats +without being told explicitly. +.PP +.B objcopy +can be used to generate S-records by using an output target of +.B srec +(e.g., use +.B -O srec). +.PP +.B objcopy +can be used to generate a raw binary file by using an output target of +.B binary +(e.g., use +.B -O binary). +When +.B objcopy +generates a raw binary file, it will essentially produce a memory dump +of the contents of the input object file. All symbols and relocation +information will be discarded. The memory dump will start at the +virtual address of the lowest section copied into the output file. +.PP +When generating an S-record or a raw binary file, it may be helpful to +use +.B -S +to remove sections containing debugging information. In some cases +.B -R +will be useful to remove sections which contain information which is +not needed by the binary file. +.PP +.I infile +and +.I outfile +are the source and output files respectively. If you do not specify +.IR outfile , +.B objcopy +creates a temporary file and destructively renames the result with the +name of the input file. + +.SH OPTIONS +.TP +.B \-I \fIbfdname\fR, \fB\-\-input\-target=\fIbfdname +Consider the source file's object format to be +.IR bfdname , +rather than attempting to deduce it. +.TP +.B \-O \fIbfdname\fR, \fB\-\-output\-target=\fIbfdname +Write the output file using the object format +.IR bfdname . +.TP +.B \-F \fIbfdname\fR, \fB\-\-target=\fIbfdname +Use +.I bfdname +as the object format for both the input and the output file; i.e. +simply transfer data from source to destination with no translation. +.TP +.B \-R \fIsectionname\fR, \fB\-\-remove-section=\fIsectionname +Remove the named section from the file. This option may be given more +than once. Note that using this option inappropriately may make the +output file unusable. +.TP +.B \-S\fR, \fB\-\-strip\-all +Do not copy relocation and symbol information from the source file. +.TP +.B \-g\fR, \fB\-\-strip\-debug +Do not copy debugging symbols from the source file. +.TP +.B \-\-strip\-unneeded +Strip all symbols that are not needed for relocation processing. +.TP +.B \-K \fIsymbolname\fR, \fB\-\-keep\-symbol=\fIsymbolname +Copy only symbol \fIsymbolname\fP from the source file. This option +may be given more than once. +.TP +.B \-N \fIsymbolname\fR, \fB\-\-strip\-symbol=\fIsymbolname +Do not copy symbol \fIsymbolname\fP from the source file. This option +may be given more than once. +.TP +.B \-L \fIsymbolname\fR, \fB\-\-localize\-symbol=\fIsymbolname +Make symbol \fIsymbolname\fP local to the file, so that it is not +visible externally. This option may be given more than once. +.TP +.B \-W \fIsymbolname\fR, \fB\-\-weaken\-symbol=\fIsymbolname +Make symbol \fIsymbolname\fP weak. This option may be given more than once. +.TP +.B \-x\fR, \fB \-\-discard\-all +Do not copy non-global symbols from the source file. +.TP +.B \-X\fR, \fB\-\-discard\-locals +Do not copy compiler-generated local symbols. (These usually start +with "L" or "."). +.TP +.B \-b \fIbyte\fR, \fB\-\-byte=\fIbyte +Keep only every \fIbyte\fPth byte of the input file (header data is +not affected). \fIbyte\fP can be in the range from 0 to the +interleave-1. This option is useful for creating files to program +ROMs. It is typically used with an srec output target. +.TP +.B \-i \fIinterleave\fR, \fB\-\-interleave=\fIinterleave +Only copy one out of every \fIinterleave\fP bytes. Which one to copy is +selected by the \fB\-b\fP or \fB\-\-byte\fP option. The default is 4. +The interleave is ignored if neither \fB\-b\fP nor \fB\-\-byte\fP is given. +.TP +.B \-p\fR, \fB\-\-preserve\-dates +Set the access and modification dates of the output file to be the same +as those of the input file. +.TP +.B \-\-debugging +Convert debugging information, if possible. This is not the default +because only certain debugging formats are supported, and the +conversion process can be time consuming. +.TP +.B \-\-gap\-fill=\fIval +Fill gaps between sections with \fIval\fP. This operation applies to +the \fIload address\fP (LMA) of the sections. It is done by increasing +the size of the section with the lower address, and filling in the extra +space created with \fIval\fP. +.TP +.B \-\-pad\-to=\fIaddress +Pad the output file up to the load address \fIaddress\fP. This is +done by increasing the size of the last section. The extra space is +filled in with the value specified by \fB\-\-gap\-fill\fP (default +zero). +.TP +.B \fB\-\-set\-start=\fIval +Set the start address of the new file to \fIval\fP. Not all object +file formats support setting the start address. +.TP +.B \fB\-\-change\-start=\fIincr\fR, \fB\-\-adjust\-start=\fIincr +Changes the start address by adding \fIincr\fP. Not all object file +formats support setting the start address. +.TP +.B \fB\-\-change\-addresses=\fIincr\fR, \fB\-\-adjust\-vma=\fIincr +Changes the address of all sections, as well as the start address, by +adding \fIincr\fP. Some object file formats do not permit section +addresses to be changed arbitrarily. Note that this does not relocate +the sections; if the program expects sections to be loaded at a +certain address, and this option is used to change the sections such +that they are loaded at a different address, the program may fail. +.TP +.B \fB\-\-change\-section\-address=\fIsection{=,+,-}val\fR, \fB\-\-adjust\-section\-vma=\fIsection{=,+,-}val +Set or changes the VMA and LMA addresses of the named \fIsection\fP. +If \fI=\fP is used, the section address is set to \fIval\fP. +Otherwise, \fIval\fP is added to or subtracted from the section +address. See the comments under \fB\-\-change\-addresses\fP, above. If +\fIsection\fP does not exist in the input file, a warning will be +issued, unless \fB\-\-no\-change\-warnings\fP is used. +.TP +.B \fB\-\-change\-section\-lma=\fIsection{=,+,-}val +Set or change the LMA address of the named \fIsection\fP. If \fI=\fP is +used, the section address is set to \fIval\fP. Otherwise, \fIval\fP +is added to or subtracted from the section address. See the comments +under \fB\-\-change\-addresses\fP, above. If \fIsection\fP does not exist +in the input file, a warning will be issued, unless +\fB\-\-no\-change\-warnings\fP is used. +.TP +.B \fB\-\-change\-section\-vma=\fIsection{=,+,-}val +Set or change the VMA address of the named \fIsection\fP. If \fI=\fP is +used, the section address is set to \fIval\fP. Otherwise, \fIval\fP +is added to or subtracted from the section address. See the comments +under \fB\-\-change\-addresses\fP, above. If \fIsection\fP does not exist +in the input file, a warning will be issued, unless +\fB\-\-no\-change\-warnings\fP is used. +.TP +.B \fB\-\-change\-warnings\fR, \fB\-\-adjust\-warnings +If \fB\-\-change\-section\-XXX\fP is used, and the named section does +not exist, issue a warning. This is the default. +.TP +.B \fB\-\-no\-change\-warnings\fR, \fB\-\-no\-adjust\-warnings +Do not issue a warning if \fB\-\-change\-section\-XXX\fP is used, even +if the named section does not exist. +.TP +.B \fB\-\-set\-section\-flags=\fIsection=flags +Set the flags for the named section. The \fIflags\fP argument is a +comma separated string of flag names. The recognized names are +\fIalloc\fP, \fIload\fP, \fIreadonly\fP, \fIcode\fP, \fIdata\fP, and +\fIrom\fP. Not all flags are meaningful for all object file +formats. +.TP +.B \fB\-\-add\-section=\fIsectionname=filename +Add a new section named \fIsectionname\fR while copying the file. The +contents of the new section are taken from the file \fIfilename\fR. +The size of the section will be the size of the file. This option +only works on file formats which can support sections with arbitrary +names. +.TP +.B \-\-change\-leading\-char +Some object file formats use special characters at the start of +symbols. The most common such character is underscore, which compilers +often add before every symbol. This option tells +.B objcopy +to change the leading character of every symbol when it converts +between object file formats. If the object file formats use the same +leading character, this option has no effect. Otherwise, it will add +a character, or remove a character, or change a character, as +appropriate. +.TP +.B \-\-remove\-leading\-char +If the first character of a global symbol is a special symbol leading +character used by the object file format, remove the character. The +most common symbol leading character is underscore. This option will +remove a leading underscore from all global symbols. This can be +useful if you want to link together objects of different file formats +with different conventions for symbol names. This is different from +\fB\-\-change\-leading\-char\fP because it always changes the symbol name +when appropriate, regardless of the object file format of the output +.TP +.B \-\-weaken +Change all global symbols in the file to be weak. +.TP +.B \-v\fR, \fB\-\-verbose +Verbose output: list all object files modified. In the case of +archives, "\fBobjcopy \-V\fR" lists all members of the archive. +.TP +.B \-V\fR, \fB\-\-version +Show the version number of +.B objcopy +and exit. +.TP +.B \-\-help +Show a summary of the options to +.B objcopy +and exit. +.SH "SEE ALSO" +.RB "`\|" binutils "\|'" +entry in +.B +info\c +\&; +.I +The GNU Binary Utilities\c +\&, Roland H. Pesch (June 1993). + +.SH COPYING +Copyright (c) 1993, 94, 95, 96, 1997 Free Software Foundation, Inc. +.PP +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. +.PP +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the +entire resulting derived work is distributed under the terms of a +permission notice identical to this one. +.PP +Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be included in +translations approved by the Free Software Foundation instead of in +the original English. diff --git a/binutils/objcopy.c b/binutils/objcopy.c new file mode 100644 index 0000000..5fd7777 --- /dev/null +++ b/binutils/objcopy.c @@ -0,0 +1,2029 @@ +/* objcopy.c -- copy object file from input to output, optionally massaging it. + Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 1999 + Free Software Foundation, Inc. + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#include "bfd.h" +#include "progress.h" +#include "bucomm.h" +#include "getopt.h" +#include "libiberty.h" +#include "budbg.h" +#include <sys/stat.h> + +/* A list of symbols to explicitly strip out, or to keep. A linked + list is good enough for a small number from the command line, but + this will slow things down a lot if many symbols are being + deleted. */ + +struct symlist +{ + const char *name; + struct symlist *next; +}; + +static void copy_usage PARAMS ((FILE *, int)); +static void strip_usage PARAMS ((FILE *, int)); +static flagword parse_flags PARAMS ((const char *)); +static struct section_list *find_section_list PARAMS ((const char *, boolean)); +static void setup_section PARAMS ((bfd *, asection *, PTR)); +static void copy_section PARAMS ((bfd *, asection *, PTR)); +static void get_sections PARAMS ((bfd *, asection *, PTR)); +static int compare_section_lma PARAMS ((const PTR, const PTR)); +static void add_specific_symbol PARAMS ((const char *, struct symlist **)); +static boolean is_specified_symbol PARAMS ((const char *, struct symlist *)); +static boolean is_strip_section PARAMS ((bfd *, asection *)); +static unsigned int filter_symbols + PARAMS ((bfd *, bfd *, asymbol **, asymbol **, long)); +static void mark_symbols_used_in_relocations PARAMS ((bfd *, asection *, PTR)); +static void filter_bytes PARAMS ((char *, bfd_size_type *)); +static boolean write_debugging_info PARAMS ((bfd *, PTR, long *, asymbol ***)); +static void copy_object PARAMS ((bfd *, bfd *)); +static void copy_archive PARAMS ((bfd *, bfd *, const char *)); +static void copy_file + PARAMS ((const char *, const char *, const char *, const char *)); +static int strip_main PARAMS ((int, char **)); +static int copy_main PARAMS ((int, char **)); + +#define RETURN_NONFATAL(s) {bfd_nonfatal (s); status = 1; return;} + +static asymbol **isympp = NULL; /* Input symbols */ +static asymbol **osympp = NULL; /* Output symbols that survive stripping */ + +/* If `copy_byte' >= 0, copy only that byte of every `interleave' bytes. */ +static int copy_byte = -1; +static int interleave = 4; + +static boolean verbose; /* Print file and target names. */ +static boolean preserve_dates; /* Preserve input file timestamp. */ +static int status = 0; /* Exit status. */ + +enum strip_action + { + STRIP_UNDEF, + STRIP_NONE, /* don't strip */ + STRIP_DEBUG, /* strip all debugger symbols */ + STRIP_UNNEEDED, /* strip unnecessary symbols */ + STRIP_ALL /* strip all symbols */ + }; + +/* Which symbols to remove. */ +static enum strip_action strip_symbols; + +enum locals_action + { + LOCALS_UNDEF, + LOCALS_START_L, /* discard locals starting with L */ + LOCALS_ALL /* discard all locals */ + }; + +/* Which local symbols to remove. Overrides STRIP_ALL. */ +static enum locals_action discard_locals; + +/* What kind of change to perform. */ +enum change_action +{ + CHANGE_IGNORE, + CHANGE_MODIFY, + CHANGE_SET +}; + +/* Structure used to hold lists of sections and actions to take. */ +struct section_list +{ + struct section_list * next; /* Next section to change. */ + const char * name; /* Section name. */ + boolean used; /* Whether this entry was used. */ + boolean remove; /* Whether to remove this section. */ + enum change_action change_vma;/* Whether to change or set VMA. */ + bfd_vma vma_val; /* Amount to change by or set to. */ + enum change_action change_lma;/* Whether to change or set LMA. */ + bfd_vma lma_val; /* Amount to change by or set to. */ + boolean set_flags; /* Whether to set the section flags. */ + flagword flags; /* What to set the section flags to. */ +}; + +static struct section_list *change_sections; +static boolean sections_removed; + +/* Changes to the start address. */ +static bfd_vma change_start = 0; +static boolean set_start_set = false; +static bfd_vma set_start; + +/* Changes to section addresses. */ +static bfd_vma change_section_address = 0; + +/* Filling gaps between sections. */ +static boolean gap_fill_set = false; +static bfd_byte gap_fill = 0; + +/* Pad to a given address. */ +static boolean pad_to_set = false; +static bfd_vma pad_to; + +/* List of sections to add. */ + +struct section_add +{ + /* Next section to add. */ + struct section_add *next; + /* Name of section to add. */ + const char *name; + /* Name of file holding section contents. */ + const char *filename; + /* Size of file. */ + size_t size; + /* Contents of file. */ + bfd_byte *contents; + /* BFD section, after it has been added. */ + asection *section; +}; + +static struct section_add *add_sections; + +/* Whether to convert debugging information. */ + +static boolean convert_debugging = false; + +/* Whether to change the leading character in symbol names. */ + +static boolean change_leading_char = false; + +/* Whether to remove the leading character from global symbol names. */ + +static boolean remove_leading_char = false; + +/* List of symbols to strip, keep, localize, and weaken. */ + +static struct symlist *strip_specific_list = NULL; +static struct symlist *keep_specific_list = NULL; +static struct symlist *localize_specific_list = NULL; +static struct symlist *weaken_specific_list = NULL; + +/* If this is true, we weaken global symbols (set BSF_WEAK). */ + +static boolean weaken = false; + +/* 150 isn't special; it's just an arbitrary non-ASCII char value. */ + +#define OPTION_ADD_SECTION 150 +#define OPTION_CHANGE_ADDRESSES (OPTION_ADD_SECTION + 1) +#define OPTION_CHANGE_LEADING_CHAR (OPTION_CHANGE_ADDRESSES + 1) +#define OPTION_CHANGE_START (OPTION_CHANGE_LEADING_CHAR + 1) +#define OPTION_CHANGE_SECTION_ADDRESS (OPTION_CHANGE_START + 1) +#define OPTION_CHANGE_SECTION_LMA (OPTION_CHANGE_SECTION_ADDRESS + 1) +#define OPTION_CHANGE_SECTION_VMA (OPTION_CHANGE_SECTION_LMA + 1) +#define OPTION_CHANGE_WARNINGS (OPTION_CHANGE_SECTION_VMA + 1) +#define OPTION_DEBUGGING (OPTION_CHANGE_WARNINGS + 1) +#define OPTION_GAP_FILL (OPTION_DEBUGGING + 1) +#define OPTION_NO_CHANGE_WARNINGS (OPTION_GAP_FILL + 1) +#define OPTION_PAD_TO (OPTION_NO_CHANGE_WARNINGS + 1) +#define OPTION_REMOVE_LEADING_CHAR (OPTION_PAD_TO + 1) +#define OPTION_SET_SECTION_FLAGS (OPTION_REMOVE_LEADING_CHAR + 1) +#define OPTION_SET_START (OPTION_SET_SECTION_FLAGS + 1) +#define OPTION_STRIP_UNNEEDED (OPTION_SET_START + 1) +#define OPTION_WEAKEN (OPTION_STRIP_UNNEEDED + 1) + +/* Options to handle if running as "strip". */ + +static struct option strip_options[] = +{ + {"discard-all", no_argument, 0, 'x'}, + {"discard-locals", no_argument, 0, 'X'}, + {"format", required_argument, 0, 'F'}, /* Obsolete */ + {"help", no_argument, 0, 'h'}, + {"input-format", required_argument, 0, 'I'}, /* Obsolete */ + {"input-target", required_argument, 0, 'I'}, + {"keep-symbol", required_argument, 0, 'K'}, + {"output-format", required_argument, 0, 'O'}, /* Obsolete */ + {"output-target", required_argument, 0, 'O'}, + {"preserve-dates", no_argument, 0, 'p'}, + {"remove-section", required_argument, 0, 'R'}, + {"strip-all", no_argument, 0, 's'}, + {"strip-debug", no_argument, 0, 'S'}, + {"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED}, + {"strip-symbol", required_argument, 0, 'N'}, + {"target", required_argument, 0, 'F'}, + {"verbose", no_argument, 0, 'v'}, + {"version", no_argument, 0, 'V'}, + {0, no_argument, 0, 0} +}; + +/* Options to handle if running as "objcopy". */ + +static struct option copy_options[] = +{ + {"add-section", required_argument, 0, OPTION_ADD_SECTION}, + {"adjust-start", required_argument, 0, OPTION_CHANGE_START}, + {"adjust-vma", required_argument, 0, OPTION_CHANGE_ADDRESSES}, + {"adjust-section-vma", required_argument, 0, OPTION_CHANGE_SECTION_ADDRESS}, + {"adjust-warnings", no_argument, 0, OPTION_CHANGE_WARNINGS}, + {"byte", required_argument, 0, 'b'}, + {"change-addresses", required_argument, 0, OPTION_CHANGE_ADDRESSES}, + {"change-leading-char", no_argument, 0, OPTION_CHANGE_LEADING_CHAR}, + {"change-section-address", required_argument, 0, OPTION_CHANGE_SECTION_ADDRESS}, + {"change-section-lma", required_argument, 0, OPTION_CHANGE_SECTION_LMA}, + {"change-section-vma", required_argument, 0, OPTION_CHANGE_SECTION_VMA}, + {"change-start", required_argument, 0, OPTION_CHANGE_START}, + {"change-warnings", no_argument, 0, OPTION_CHANGE_WARNINGS}, + {"debugging", no_argument, 0, OPTION_DEBUGGING}, + {"discard-all", no_argument, 0, 'x'}, + {"discard-locals", no_argument, 0, 'X'}, + {"format", required_argument, 0, 'F'}, /* Obsolete */ + {"gap-fill", required_argument, 0, OPTION_GAP_FILL}, + {"help", no_argument, 0, 'h'}, + {"input-format", required_argument, 0, 'I'}, /* Obsolete */ + {"input-target", required_argument, 0, 'I'}, + {"interleave", required_argument, 0, 'i'}, + {"keep-symbol", required_argument, 0, 'K'}, + {"no-adjust-warnings", no_argument, 0, OPTION_NO_CHANGE_WARNINGS}, + {"no-change-warnings", no_argument, 0, OPTION_NO_CHANGE_WARNINGS}, + {"output-format", required_argument, 0, 'O'}, /* Obsolete */ + {"output-target", required_argument, 0, 'O'}, + {"pad-to", required_argument, 0, OPTION_PAD_TO}, + {"preserve-dates", no_argument, 0, 'p'}, + {"localize-symbol", required_argument, 0, 'L'}, + {"remove-leading-char", no_argument, 0, OPTION_REMOVE_LEADING_CHAR}, + {"remove-section", required_argument, 0, 'R'}, + {"set-section-flags", required_argument, 0, OPTION_SET_SECTION_FLAGS}, + {"set-start", required_argument, 0, OPTION_SET_START}, + {"strip-all", no_argument, 0, 'S'}, + {"strip-debug", no_argument, 0, 'g'}, + {"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED}, + {"strip-symbol", required_argument, 0, 'N'}, + {"target", required_argument, 0, 'F'}, + {"verbose", no_argument, 0, 'v'}, + {"version", no_argument, 0, 'V'}, + {"weaken", no_argument, 0, OPTION_WEAKEN}, + {"weaken-symbol", required_argument, 0, 'W'}, + {0, no_argument, 0, 0} +}; + +/* IMPORTS */ +extern char *program_name; + +/* This flag distinguishes between strip and objcopy: + 1 means this is 'strip'; 0 means this is 'objcopy'. + -1 means if we should use argv[0] to decide. */ +extern int is_strip; + + +static void +copy_usage (stream, exit_status) + FILE *stream; + int exit_status; +{ + fprintf (stream, _("\ +Usage: %s [-vVSpgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-b byte]\n\ + [-R section] [-i interleave] [--interleave=interleave] [--byte=byte]\n\ + [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\ + [--strip-all] [--strip-debug] [--strip-unneeded] [--discard-all]\n\ + [--discard-locals] [--debugging] [--remove-section=section]\n"), + program_name); + fprintf (stream, _("\ + [--gap-fill=val] [--pad-to=address] [--preserve-dates]\n\ + [--set-start=val] \n\ + [--change-start=incr] [--change-addresses=incr] \n\ + (--adjust-start and --adjust-vma are aliases for these two) \n\ + [--change-section-address=section{=,+,-}val]\n\ + (--adjust-section-vma is an alias for --change-section-address)\n\ + [--change-section-lma=section{=,+,-}val]\n\ + [--change-section-vma=section{=,+,-}val]\n\ + [--adjust-warnings] [--no-adjust-warnings]\n\ + [--change-warnings] [--no-change-warnings]\n\ + [--set-section-flags=section=flags] [--add-section=sectionname=filename]\n\ + [--keep-symbol symbol] [-K symbol] [--strip-symbol symbol] [-N symbol]\n\ + [--localize-symbol symbol] [-L symbol] [--weaken-symbol symbol]\n\ + [-W symbol] [--change-leading-char] [--remove-leading-char] [--weaken]\n\ + [--verbose] [--version] [--help] in-file [out-file]\n")); + list_supported_targets (program_name, stream); + if (exit_status == 0) + fprintf (stream, _("Report bugs to bug-gnu-utils@gnu.org\n")); + exit (exit_status); +} + +static void +strip_usage (stream, exit_status) + FILE *stream; + int exit_status; +{ + fprintf (stream, _("\ +Usage: %s [-vVsSpgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-R section]\n\ + [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\ + [--strip-all] [--strip-debug] [--strip-unneeded] [--discard-all]\n\ + [--discard-locals] [--keep-symbol symbol] [-K symbol]\n\ + [--strip-symbol symbol] [-N symbol] [--remove-section=section]\n\ + [-o file] [--preserve-dates] [--verbose] [--version] [--help] file...\n"), + program_name); + list_supported_targets (program_name, stream); + if (exit_status == 0) + fprintf (stream, _("Report bugs to bug-gnu-utils@gnu.org\n")); + exit (exit_status); +} + +/* Parse section flags into a flagword, with a fatal error if the + string can't be parsed. */ + +static flagword +parse_flags (s) + const char *s; +{ + flagword ret; + const char *snext; + int len; + + ret = SEC_NO_FLAGS; + + do + { + snext = strchr (s, ','); + if (snext == NULL) + len = strlen (s); + else + { + len = snext - s; + ++snext; + } + + if (0) ; +#define PARSE_FLAG(fname,fval) \ + else if (strncasecmp (fname, s, len) == 0) ret |= fval + PARSE_FLAG ("alloc", SEC_ALLOC); + PARSE_FLAG ("load", SEC_LOAD); + PARSE_FLAG ("readonly", SEC_READONLY); + PARSE_FLAG ("code", SEC_CODE); + PARSE_FLAG ("data", SEC_DATA); + PARSE_FLAG ("rom", SEC_ROM); + PARSE_FLAG ("contents", SEC_HAS_CONTENTS); +#undef PARSE_FLAG + else + { + char *copy; + + copy = xmalloc (len + 1); + strncpy (copy, s, len); + copy[len] = '\0'; + non_fatal (_("unrecognized section flag `%s'"), copy); + fatal (_("supported flags: alloc, load, readonly, code, data, rom, contents")); + } + + s = snext; + } + while (s != NULL); + + return ret; +} + +/* Find and optionally add an entry in the change_sections list. */ + +static struct section_list * +find_section_list (name, add) + const char *name; + boolean add; +{ + register struct section_list *p; + + for (p = change_sections; p != NULL; p = p->next) + if (strcmp (p->name, name) == 0) + return p; + + if (! add) + return NULL; + + p = (struct section_list *) xmalloc (sizeof (struct section_list)); + p->name = name; + p->used = false; + p->remove = false; + p->change_vma = CHANGE_IGNORE; + p->change_lma = CHANGE_IGNORE; + p->vma_val = 0; + p->lma_val = 0; + p->set_flags = false; + p->flags = 0; + + p->next = change_sections; + change_sections = p; + + return p; +} + +/* Add a symbol to strip_specific_list. */ + +static void +add_specific_symbol (name, list) + const char *name; + struct symlist **list; +{ + struct symlist *tmp_list; + + tmp_list = (struct symlist *) xmalloc (sizeof (struct symlist)); + tmp_list->name = name; + tmp_list->next = *list; + *list = tmp_list; +} + +/* See whether a symbol should be stripped or kept based on + strip_specific_list and keep_symbols. */ + +static boolean +is_specified_symbol (name, list) + const char *name; + struct symlist *list; +{ + struct symlist *tmp_list; + + for (tmp_list = list; tmp_list; tmp_list = tmp_list->next) + { + if (strcmp (name, tmp_list->name) == 0) + return true; + } + return false; +} + +/* See if a section is being removed. */ + +static boolean +is_strip_section (abfd, sec) + bfd *abfd; + asection *sec; +{ + struct section_list *p; + + if ((bfd_get_section_flags (abfd, sec) & SEC_DEBUGGING) != 0 + && (strip_symbols == STRIP_DEBUG + || strip_symbols == STRIP_UNNEEDED + || strip_symbols == STRIP_ALL + || discard_locals == LOCALS_ALL + || convert_debugging)) + return true; + + if (! sections_removed) + return false; + p = find_section_list (bfd_get_section_name (abfd, sec), false); + return p != NULL && p->remove ? true : false; +} + +/* Choose which symbol entries to copy; put the result in OSYMS. + We don't copy in place, because that confuses the relocs. + Return the number of symbols to print. */ + +static unsigned int +filter_symbols (abfd, obfd, osyms, isyms, symcount) + bfd *abfd; + bfd *obfd; + asymbol **osyms, **isyms; + long symcount; +{ + register asymbol **from = isyms, **to = osyms; + long src_count = 0, dst_count = 0; + + for (; src_count < symcount; src_count++) + { + asymbol *sym = from[src_count]; + flagword flags = sym->flags; + const char *name = bfd_asymbol_name (sym); + int keep; + + if (change_leading_char + && (bfd_get_symbol_leading_char (abfd) + != bfd_get_symbol_leading_char (obfd)) + && (bfd_get_symbol_leading_char (abfd) == '\0' + || (name[0] == bfd_get_symbol_leading_char (abfd)))) + { + if (bfd_get_symbol_leading_char (obfd) == '\0') + name = bfd_asymbol_name (sym) = name + 1; + else + { + char *n; + + n = xmalloc (strlen (name) + 2); + n[0] = bfd_get_symbol_leading_char (obfd); + if (bfd_get_symbol_leading_char (abfd) == '\0') + strcpy (n + 1, name); + else + strcpy (n + 1, name + 1); + name = bfd_asymbol_name (sym) = n; + } + } + + if (remove_leading_char + && ((flags & BSF_GLOBAL) != 0 + || (flags & BSF_WEAK) != 0 + || bfd_is_und_section (bfd_get_section (sym)) + || bfd_is_com_section (bfd_get_section (sym))) + && name[0] == bfd_get_symbol_leading_char (abfd)) + name = bfd_asymbol_name (sym) = name + 1; + + if (strip_symbols == STRIP_ALL) + keep = 0; + else if ((flags & BSF_KEEP) != 0 /* Used in relocation. */ + || ((flags & BSF_SECTION_SYM) != 0 + && ((*bfd_get_section (sym)->symbol_ptr_ptr)->flags + & BSF_KEEP) != 0)) + keep = 1; + else if ((flags & BSF_GLOBAL) != 0 /* Global symbol. */ + || (flags & BSF_WEAK) != 0 + || bfd_is_und_section (bfd_get_section (sym)) + || bfd_is_com_section (bfd_get_section (sym))) + keep = strip_symbols != STRIP_UNNEEDED; + else if ((flags & BSF_DEBUGGING) != 0) /* Debugging symbol. */ + keep = (strip_symbols != STRIP_DEBUG + && strip_symbols != STRIP_UNNEEDED + && ! convert_debugging); + else /* Local symbol. */ + keep = (strip_symbols != STRIP_UNNEEDED + && (discard_locals != LOCALS_ALL + && (discard_locals != LOCALS_START_L + || ! bfd_is_local_label (abfd, sym)))); + + if (keep && is_specified_symbol (name, strip_specific_list)) + keep = 0; + if (!keep && is_specified_symbol (name, keep_specific_list)) + keep = 1; + if (keep && is_strip_section (abfd, bfd_get_section (sym))) + keep = 0; + + if (keep && (flags & BSF_GLOBAL) != 0 + && (weaken || is_specified_symbol (name, weaken_specific_list))) + { + sym->flags &=~ BSF_GLOBAL; + sym->flags |= BSF_WEAK; + } + if (keep && (flags & (BSF_GLOBAL | BSF_WEAK)) + && is_specified_symbol (name, localize_specific_list)) + { + sym->flags &= ~(BSF_GLOBAL | BSF_WEAK); + sym->flags |= BSF_LOCAL; + } + + if (keep) + to[dst_count++] = sym; + } + + to[dst_count] = NULL; + + return dst_count; +} + +/* Keep only every `copy_byte'th byte in MEMHUNK, which is *SIZE bytes long. + Adjust *SIZE. */ + +static void +filter_bytes (memhunk, size) + char *memhunk; + bfd_size_type *size; +{ + char *from = memhunk + copy_byte, *to = memhunk, *end = memhunk + *size; + + for (; from < end; from += interleave) + *to++ = *from; + if (*size % interleave > copy_byte) + *size = (*size / interleave) + 1; + else + *size /= interleave; +} + +/* Copy object file IBFD onto OBFD. */ + +static void +copy_object (ibfd, obfd) + bfd *ibfd; + bfd *obfd; +{ + bfd_vma start; + long symcount; + asection **osections = NULL; + bfd_size_type *gaps = NULL; + bfd_size_type max_gap = 0; + long symsize; + PTR dhandle; + + + if (!bfd_set_format (obfd, bfd_get_format (ibfd))) + RETURN_NONFATAL (bfd_get_filename (obfd)); + + if (verbose) + printf (_("copy from %s(%s) to %s(%s)\n"), + bfd_get_filename (ibfd), bfd_get_target (ibfd), + bfd_get_filename (obfd), bfd_get_target (obfd)); + + if (set_start_set) + start = set_start; + else + start = bfd_get_start_address (ibfd); + start += change_start; + + if (!bfd_set_start_address (obfd, start) + || !bfd_set_file_flags (obfd, + (bfd_get_file_flags (ibfd) + & bfd_applicable_file_flags (obfd)))) + RETURN_NONFATAL (bfd_get_filename (ibfd)); + + /* Copy architecture of input file to output file */ + if (!bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), + bfd_get_mach (ibfd))) + non_fatal (_("Warning: Output file cannot represent architecture %s"), + bfd_printable_arch_mach (bfd_get_arch (ibfd), + bfd_get_mach (ibfd))); + + if (!bfd_set_format (obfd, bfd_get_format (ibfd))) + RETURN_NONFATAL (bfd_get_filename (ibfd)); + + if (isympp) + free (isympp); + + if (osympp != isympp) + free (osympp); + + /* BFD mandates that all output sections be created and sizes set before + any output is done. Thus, we traverse all sections multiple times. */ + bfd_map_over_sections (ibfd, setup_section, (void *) obfd); + + if (add_sections != NULL) + { + struct section_add *padd; + struct section_list *pset; + + for (padd = add_sections; padd != NULL; padd = padd->next) + { + padd->section = bfd_make_section (obfd, padd->name); + if (padd->section == NULL) + { + non_fatal (_("can't create section `%s': %s"), + padd->name, bfd_errmsg (bfd_get_error ())); + status = 1; + return; + } + else + { + flagword flags; + + if (! bfd_set_section_size (obfd, padd->section, padd->size)) + RETURN_NONFATAL (bfd_get_filename (obfd)); + + pset = find_section_list (padd->name, false); + if (pset != NULL) + pset->used = true; + + if (pset != NULL && pset->set_flags) + flags = pset->flags | SEC_HAS_CONTENTS; + else + flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DATA; + + if (! bfd_set_section_flags (obfd, padd->section, flags)) + RETURN_NONFATAL (bfd_get_filename (obfd)); + + if (pset != NULL) + { + if (pset->change_vma != CHANGE_IGNORE) + if (! bfd_set_section_vma (obfd, padd->section, pset->vma_val)) + RETURN_NONFATAL (bfd_get_filename (obfd)); + + if (pset->change_lma != CHANGE_IGNORE) + { + padd->section->lma = pset->lma_val; + + if (! bfd_set_section_alignment + (obfd, padd->section, + bfd_section_alignment (obfd, padd->section))) + RETURN_NONFATAL (bfd_get_filename (obfd)); + } + } + } + } + } + + if (gap_fill_set || pad_to_set) + { + asection **set; + unsigned int c, i; + + /* We must fill in gaps between the sections and/or we must pad + the last section to a specified address. We do this by + grabbing a list of the sections, sorting them by VMA, and + increasing the section sizes as required to fill the gaps. + We write out the gap contents below. */ + + c = bfd_count_sections (obfd); + osections = (asection **) xmalloc (c * sizeof (asection *)); + set = osections; + bfd_map_over_sections (obfd, get_sections, (void *) &set); + + qsort (osections, c, sizeof (asection *), compare_section_lma); + + gaps = (bfd_size_type *) xmalloc (c * sizeof (bfd_size_type)); + memset (gaps, 0, c * sizeof (bfd_size_type)); + + if (gap_fill_set) + { + for (i = 0; i < c - 1; i++) + { + flagword flags; + bfd_size_type size; + bfd_vma gap_start, gap_stop; + + flags = bfd_get_section_flags (obfd, osections[i]); + if ((flags & SEC_HAS_CONTENTS) == 0 + || (flags & SEC_LOAD) == 0) + continue; + + size = bfd_section_size (obfd, osections[i]); + gap_start = bfd_section_lma (obfd, osections[i]) + size; + gap_stop = bfd_section_lma (obfd, osections[i + 1]); + if (gap_start < gap_stop) + { + if (! bfd_set_section_size (obfd, osections[i], + size + (gap_stop - gap_start))) + { + non_fatal (_("Can't fill gap after %s: %s"), + bfd_get_section_name (obfd, osections[i]), + bfd_errmsg (bfd_get_error ())); + status = 1; + break; + } + gaps[i] = gap_stop - gap_start; + if (max_gap < gap_stop - gap_start) + max_gap = gap_stop - gap_start; + } + } + } + + if (pad_to_set) + { + bfd_vma lma; + bfd_size_type size; + + lma = bfd_section_lma (obfd, osections[c - 1]); + size = bfd_section_size (obfd, osections[c - 1]); + if (lma + size < pad_to) + { + if (! bfd_set_section_size (obfd, osections[c - 1], + pad_to - lma)) + { + non_fatal (_("Can't add padding to %s: %s"), + bfd_get_section_name (obfd, osections[c - 1]), + bfd_errmsg (bfd_get_error ())); + status = 1; + } + else + { + gaps[c - 1] = pad_to - (lma + size); + if (max_gap < pad_to - (lma + size)) + max_gap = pad_to - (lma + size); + } + } + } + } + + /* Symbol filtering must happen after the output sections have + been created, but before their contents are set. */ + dhandle = NULL; + symsize = bfd_get_symtab_upper_bound (ibfd); + if (symsize < 0) + RETURN_NONFATAL (bfd_get_filename (ibfd)); + + osympp = isympp = (asymbol **) xmalloc (symsize); + symcount = bfd_canonicalize_symtab (ibfd, isympp); + if (symcount < 0) + RETURN_NONFATAL (bfd_get_filename (ibfd)); + + if (convert_debugging) + dhandle = read_debugging_info (ibfd, isympp, symcount); + + if (strip_symbols == STRIP_DEBUG + || strip_symbols == STRIP_ALL + || strip_symbols == STRIP_UNNEEDED + || discard_locals != LOCALS_UNDEF + || strip_specific_list != NULL + || keep_specific_list != NULL + || localize_specific_list != NULL + || weaken_specific_list != NULL + || sections_removed + || convert_debugging + || change_leading_char + || remove_leading_char + || weaken) + { + /* Mark symbols used in output relocations so that they + are kept, even if they are local labels or static symbols. + + Note we iterate over the input sections examining their + relocations since the relocations for the output sections + haven't been set yet. mark_symbols_used_in_relocations will + ignore input sections which have no corresponding output + section. */ + if (strip_symbols != STRIP_ALL) + bfd_map_over_sections (ibfd, + mark_symbols_used_in_relocations, + (PTR)isympp); + osympp = (asymbol **) xmalloc ((symcount + 1) * sizeof (asymbol *)); + symcount = filter_symbols (ibfd, obfd, osympp, isympp, symcount); + } + + if (convert_debugging && dhandle != NULL) + { + if (! write_debugging_info (obfd, dhandle, &symcount, &osympp)) + { + status = 1; + return; + } + } + + bfd_set_symtab (obfd, osympp, symcount); + + /* This has to happen after the symbol table has been set. */ + bfd_map_over_sections (ibfd, copy_section, (void *) obfd); + + if (add_sections != NULL) + { + struct section_add *padd; + + for (padd = add_sections; padd != NULL; padd = padd->next) + { + if (! bfd_set_section_contents (obfd, padd->section, + (PTR) padd->contents, + (file_ptr) 0, + (bfd_size_type) padd->size)) + RETURN_NONFATAL (bfd_get_filename (obfd)); + } + } + + if (gap_fill_set || pad_to_set) + { + bfd_byte *buf; + int c, i; + + /* Fill in the gaps. */ + + if (max_gap > 8192) + max_gap = 8192; + buf = (bfd_byte *) xmalloc (max_gap); + memset (buf, gap_fill, (size_t) max_gap); + + c = bfd_count_sections (obfd); + for (i = 0; i < c; i++) + { + if (gaps[i] != 0) + { + bfd_size_type left; + file_ptr off; + + left = gaps[i]; + off = bfd_section_size (obfd, osections[i]) - left; + while (left > 0) + { + bfd_size_type now; + + if (left > 8192) + now = 8192; + else + now = left; + + if (! bfd_set_section_contents (obfd, osections[i], buf, + off, now)) + RETURN_NONFATAL (bfd_get_filename (obfd)); + + left -= now; + off += now; + } + } + } + } + + /* Allow the BFD backend to copy any private data it understands + from the input BFD to the output BFD. This is done last to + permit the routine to look at the filtered symbol table, which is + important for the ECOFF code at least. */ + if (!bfd_copy_private_bfd_data (ibfd, obfd)) + { + non_fatal (_("%s: error copying private BFD data: %s"), + bfd_get_filename (obfd), + bfd_errmsg (bfd_get_error ())); + status = 1; + return; + } +} + +/* Read each archive element in turn from IBFD, copy the + contents to temp file, and keep the temp file handle. */ + +static void +copy_archive (ibfd, obfd, output_target) + bfd *ibfd; + bfd *obfd; + const char *output_target; +{ + struct name_list + { + struct name_list *next; + char *name; + bfd *obfd; + } *list, *l; + bfd **ptr = &obfd->archive_head; + bfd *this_element; + char *dir = make_tempname (bfd_get_filename (obfd)); + + /* Make a temp directory to hold the contents. */ +#if defined (_WIN32) && !defined (__CYGWIN32__) + if (mkdir (dir) != 0) +#else + if (mkdir (dir, 0700) != 0) +#endif + { + fatal (_("cannot mkdir %s for archive copying (error: %s)"), + dir, strerror (errno)); + } + obfd->has_armap = ibfd->has_armap; + + list = NULL; + + this_element = bfd_openr_next_archived_file (ibfd, NULL); + while (!status && this_element != (bfd *) NULL) + { + /* Create an output file for this member. */ + char *output_name = concat (dir, "/", bfd_get_filename (this_element), + (char *) NULL); + bfd *output_bfd = bfd_openw (output_name, output_target); + bfd *last_element; + + l = (struct name_list *) xmalloc (sizeof (struct name_list)); + l->name = output_name; + l->next = list; + list = l; + + if (output_bfd == (bfd *) NULL) + RETURN_NONFATAL (output_name); + + if (!bfd_set_format (obfd, bfd_get_format (ibfd))) + RETURN_NONFATAL (bfd_get_filename (obfd)); + + if (bfd_check_format (this_element, bfd_object) == true) + copy_object (this_element, output_bfd); + + if (!bfd_close (output_bfd)) + { + bfd_nonfatal (bfd_get_filename (output_bfd)); + /* Error in new object file. Don't change archive. */ + status = 1; + } + + /* Open the newly output file and attach to our list. */ + output_bfd = bfd_openr (output_name, output_target); + + l->obfd = output_bfd; + + *ptr = output_bfd; + ptr = &output_bfd->next; + + last_element = this_element; + + this_element = bfd_openr_next_archived_file (ibfd, last_element); + + bfd_close (last_element); + } + *ptr = (bfd *) NULL; + + if (!bfd_close (obfd)) + RETURN_NONFATAL (bfd_get_filename (obfd)); + + if (!bfd_close (ibfd)) + RETURN_NONFATAL (bfd_get_filename (ibfd)); + + /* Delete all the files that we opened. */ + for (l = list; l != NULL; l = l->next) + { + bfd_close (l->obfd); + unlink (l->name); + } + rmdir (dir); +} + +/* The top-level control. */ + +static void +copy_file (input_filename, output_filename, input_target, output_target) + const char *input_filename; + const char *output_filename; + const char *input_target; + const char *output_target; +{ + bfd *ibfd; + char **matching; + + /* To allow us to do "strip *" without dying on the first + non-object file, failures are nonfatal. */ + + ibfd = bfd_openr (input_filename, input_target); + if (ibfd == NULL) + RETURN_NONFATAL (input_filename); + + if (bfd_check_format (ibfd, bfd_archive)) + { + bfd *obfd; + + /* bfd_get_target does not return the correct value until + bfd_check_format succeeds. */ + if (output_target == NULL) + output_target = bfd_get_target (ibfd); + + obfd = bfd_openw (output_filename, output_target); + if (obfd == NULL) + RETURN_NONFATAL (output_filename); + + copy_archive (ibfd, obfd, output_target); + } + else if (bfd_check_format_matches (ibfd, bfd_object, &matching)) + { + bfd *obfd; + + /* bfd_get_target does not return the correct value until + bfd_check_format succeeds. */ + if (output_target == NULL) + output_target = bfd_get_target (ibfd); + + obfd = bfd_openw (output_filename, output_target); + if (obfd == NULL) + RETURN_NONFATAL (output_filename); + + copy_object (ibfd, obfd); + + if (!bfd_close (obfd)) + RETURN_NONFATAL (output_filename); + + if (!bfd_close (ibfd)) + RETURN_NONFATAL (input_filename); + } + else + { + bfd_nonfatal (input_filename); + + if (bfd_get_error () == bfd_error_file_ambiguously_recognized) + { + list_matching_formats (matching); + free (matching); + } + + status = 1; + } +} + +/* Create a section in OBFD with the same name and attributes + as ISECTION in IBFD. */ + +static void +setup_section (ibfd, isection, obfdarg) + bfd *ibfd; + sec_ptr isection; + PTR obfdarg; +{ + bfd *obfd = (bfd *) obfdarg; + struct section_list *p; + sec_ptr osection; + bfd_size_type size; + bfd_vma vma; + bfd_vma lma; + flagword flags; + char *err; + + if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0 + && (strip_symbols == STRIP_DEBUG + || strip_symbols == STRIP_UNNEEDED + || strip_symbols == STRIP_ALL + || discard_locals == LOCALS_ALL + || convert_debugging)) + return; + + p = find_section_list (bfd_section_name (ibfd, isection), false); + if (p != NULL) + p->used = true; + + if (p != NULL && p->remove) + return; + + osection = bfd_make_section_anyway (obfd, bfd_section_name (ibfd, isection)); + + if (osection == NULL) + { + err = "making"; + goto loser; + } + + size = bfd_section_size (ibfd, isection); + if (copy_byte >= 0) + size = (size + interleave - 1) / interleave; + if (! bfd_set_section_size (obfd, osection, size)) + { + err = "size"; + goto loser; + } + + vma = bfd_section_vma (ibfd, isection); + if (p != NULL && p->change_vma == CHANGE_MODIFY) + vma += p->vma_val; + else if (p != NULL && p->change_vma == CHANGE_SET) + vma = p->vma_val; + else + vma += change_section_address; + + if (! bfd_set_section_vma (obfd, osection, vma)) + { + err = "vma"; + goto loser; + } + + lma = isection->lma; + if ((p != NULL) && p->change_lma != CHANGE_IGNORE) + { + if (p->change_lma == CHANGE_MODIFY) + lma += p->lma_val; + else if (p->change_lma == CHANGE_SET) + lma = p->lma_val; + else + abort (); + } + else + lma += change_section_address; + + osection->lma = lma; + + /* FIXME: This is probably not enough. If we change the LMA we + may have to recompute the header for the file as well. */ + if (bfd_set_section_alignment (obfd, + osection, + bfd_section_alignment (ibfd, isection)) + == false) + { + err = "alignment"; + goto loser; + } + + flags = bfd_get_section_flags (ibfd, isection); + if (p != NULL && p->set_flags) + flags = p->flags | (flags & SEC_HAS_CONTENTS); + if (!bfd_set_section_flags (obfd, osection, flags)) + { + err = "flags"; + goto loser; + } + + /* This used to be mangle_section; we do here to avoid using + bfd_get_section_by_name since some formats allow multiple + sections with the same name. */ + isection->output_section = osection; + isection->output_offset = 0; + + /* Allow the BFD backend to copy any private data it understands + from the input section to the output section. */ + if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection)) + { + err = "private data"; + goto loser; + } + + /* All went well */ + return; + +loser: + non_fatal (_("%s: section `%s': error in %s: %s"), + bfd_get_filename (ibfd), + bfd_section_name (ibfd, isection), + err, bfd_errmsg (bfd_get_error ())); + status = 1; +} + +/* Copy the data of input section ISECTION of IBFD + to an output section with the same name in OBFD. + If stripping then don't copy any relocation info. */ + +static void +copy_section (ibfd, isection, obfdarg) + bfd *ibfd; + sec_ptr isection; + PTR obfdarg; +{ + bfd *obfd = (bfd *) obfdarg; + struct section_list *p; + arelent **relpp; + long relcount; + sec_ptr osection; + bfd_size_type size; + long relsize; + + /* If we have already failed earlier on, do not keep on generating + complaints now. */ + if (status != 0) + return; + + if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0 + && (strip_symbols == STRIP_DEBUG + || strip_symbols == STRIP_UNNEEDED + || strip_symbols == STRIP_ALL + || discard_locals == LOCALS_ALL + || convert_debugging)) + { + return; + } + + p = find_section_list (bfd_section_name (ibfd, isection), false); + + if (p != NULL && p->remove) + return; + + osection = isection->output_section; + size = bfd_get_section_size_before_reloc (isection); + + if (size == 0 || osection == 0) + return; + + + relsize = bfd_get_reloc_upper_bound (ibfd, isection); + if (relsize < 0) + RETURN_NONFATAL (bfd_get_filename (ibfd)); + + if (relsize == 0) + bfd_set_reloc (obfd, osection, (arelent **) NULL, 0); + else + { + relpp = (arelent **) xmalloc (relsize); + relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp); + if (relcount < 0) + RETURN_NONFATAL (bfd_get_filename (ibfd)); + + if (strip_symbols == STRIP_ALL) + { + /* Remove relocations which are not in + keep_strip_specific_list. */ + arelent **temp_relpp; + long temp_relcount = 0; + long i; + + temp_relpp = (arelent **) xmalloc (relsize); + for (i = 0; i < relcount; i++) + if (is_specified_symbol + (bfd_asymbol_name (*relpp [i]->sym_ptr_ptr), + keep_specific_list)) + temp_relpp [temp_relcount++] = relpp [i]; + relcount = temp_relcount; + free (relpp); + relpp = temp_relpp; + } + bfd_set_reloc (obfd, osection, + (relcount == 0 ? (arelent **) NULL : relpp), relcount); + } + + isection->_cooked_size = isection->_raw_size; + isection->reloc_done = true; + + if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS) + { + PTR memhunk = (PTR) xmalloc ((unsigned) size); + + if (!bfd_get_section_contents (ibfd, isection, memhunk, (file_ptr) 0, + size)) + RETURN_NONFATAL (bfd_get_filename (ibfd)); + + if (copy_byte >= 0) + filter_bytes (memhunk, &size); + + if (!bfd_set_section_contents (obfd, osection, memhunk, (file_ptr) 0, + size)) + RETURN_NONFATAL (bfd_get_filename (obfd)); + + free (memhunk); + } + else if (p != NULL && p->set_flags && (p->flags & SEC_HAS_CONTENTS) != 0) + { + PTR memhunk = (PTR) xmalloc ((unsigned) size); + + /* We don't permit the user to turn off the SEC_HAS_CONTENTS + flag--they can just remove the section entirely and add it + back again. However, we do permit them to turn on the + SEC_HAS_CONTENTS flag, and take it to mean that the section + contents should be zeroed out. */ + + memset (memhunk, 0, size); + if (! bfd_set_section_contents (obfd, osection, memhunk, (file_ptr) 0, + size)) + RETURN_NONFATAL (bfd_get_filename (obfd)); + free (memhunk); + } +} + +/* Get all the sections. This is used when --gap-fill or --pad-to is + used. */ + +static void +get_sections (obfd, osection, secppparg) + bfd *obfd; + asection *osection; + PTR secppparg; +{ + asection ***secppp = (asection ***) secppparg; + + **secppp = osection; + ++(*secppp); +} + +/* Sort sections by VMA. This is called via qsort, and is used when + --gap-fill or --pad-to is used. We force non loadable or empty + sections to the front, where they are easier to ignore. */ + +static int +compare_section_lma (arg1, arg2) + const PTR arg1; + const PTR arg2; +{ + const asection **sec1 = (const asection **) arg1; + const asection **sec2 = (const asection **) arg2; + flagword flags1, flags2; + + /* Sort non loadable sections to the front. */ + flags1 = (*sec1)->flags; + flags2 = (*sec2)->flags; + if ((flags1 & SEC_HAS_CONTENTS) == 0 + || (flags1 & SEC_LOAD) == 0) + { + if ((flags2 & SEC_HAS_CONTENTS) != 0 + && (flags2 & SEC_LOAD) != 0) + return -1; + } + else + { + if ((flags2 & SEC_HAS_CONTENTS) == 0 + || (flags2 & SEC_LOAD) == 0) + return 1; + } + + /* Sort sections by LMA. */ + if ((*sec1)->lma > (*sec2)->lma) + return 1; + else if ((*sec1)->lma < (*sec2)->lma) + return -1; + + /* Sort sections with the same LMA by size. */ + if ((*sec1)->_raw_size > (*sec2)->_raw_size) + return 1; + else if ((*sec1)->_raw_size < (*sec2)->_raw_size) + return -1; + + return 0; +} + +/* Mark all the symbols which will be used in output relocations with + the BSF_KEEP flag so that those symbols will not be stripped. + + Ignore relocations which will not appear in the output file. */ + +static void +mark_symbols_used_in_relocations (ibfd, isection, symbolsarg) + bfd *ibfd; + sec_ptr isection; + PTR symbolsarg; +{ + asymbol **symbols = (asymbol **) symbolsarg; + long relsize; + arelent **relpp; + long relcount, i; + + /* Ignore an input section with no corresponding output section. */ + if (isection->output_section == NULL) + return; + + relsize = bfd_get_reloc_upper_bound (ibfd, isection); + if (relsize < 0) + bfd_fatal (bfd_get_filename (ibfd)); + + if (relsize == 0) + return; + + relpp = (arelent **) xmalloc (relsize); + relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, symbols); + if (relcount < 0) + bfd_fatal (bfd_get_filename (ibfd)); + + /* Examine each symbol used in a relocation. If it's not one of the + special bfd section symbols, then mark it with BSF_KEEP. */ + for (i = 0; i < relcount; i++) + { + if (*relpp[i]->sym_ptr_ptr != bfd_com_section_ptr->symbol + && *relpp[i]->sym_ptr_ptr != bfd_abs_section_ptr->symbol + && *relpp[i]->sym_ptr_ptr != bfd_und_section_ptr->symbol) + (*relpp[i]->sym_ptr_ptr)->flags |= BSF_KEEP; + } + + if (relpp != NULL) + free (relpp); +} + +/* Write out debugging information. */ + +static boolean +write_debugging_info (obfd, dhandle, symcountp, symppp) + bfd *obfd; + PTR dhandle; + long *symcountp; + asymbol ***symppp; +{ + if (bfd_get_flavour (obfd) == bfd_target_ieee_flavour) + return write_ieee_debugging_info (obfd, dhandle); + + if (bfd_get_flavour (obfd) == bfd_target_coff_flavour + || bfd_get_flavour (obfd) == bfd_target_elf_flavour) + { + bfd_byte *syms, *strings; + bfd_size_type symsize, stringsize; + asection *stabsec, *stabstrsec; + + if (! write_stabs_in_sections_debugging_info (obfd, dhandle, &syms, + &symsize, &strings, + &stringsize)) + return false; + + stabsec = bfd_make_section (obfd, ".stab"); + stabstrsec = bfd_make_section (obfd, ".stabstr"); + if (stabsec == NULL + || stabstrsec == NULL + || ! bfd_set_section_size (obfd, stabsec, symsize) + || ! bfd_set_section_size (obfd, stabstrsec, stringsize) + || ! bfd_set_section_alignment (obfd, stabsec, 2) + || ! bfd_set_section_alignment (obfd, stabstrsec, 0) + || ! bfd_set_section_flags (obfd, stabsec, + (SEC_HAS_CONTENTS + | SEC_READONLY + | SEC_DEBUGGING)) + || ! bfd_set_section_flags (obfd, stabstrsec, + (SEC_HAS_CONTENTS + | SEC_READONLY + | SEC_DEBUGGING))) + { + non_fatal (_("%s: can't create debugging section: %s"), + bfd_get_filename (obfd), + bfd_errmsg (bfd_get_error ())); + return false; + } + + /* We can get away with setting the section contents now because + the next thing the caller is going to do is copy over the + real sections. We may someday have to split the contents + setting out of this function. */ + if (! bfd_set_section_contents (obfd, stabsec, syms, (file_ptr) 0, + symsize) + || ! bfd_set_section_contents (obfd, stabstrsec, strings, + (file_ptr) 0, stringsize)) + { + non_fatal (_("%s: can't set debugging section contents: %s"), + bfd_get_filename (obfd), + bfd_errmsg (bfd_get_error ())); + return false; + } + + return true; + } + + non_fatal (_("%s: don't know how to write debugging information for %s"), + bfd_get_filename (obfd), bfd_get_target (obfd)); + return false; +} + +static int +strip_main (argc, argv) + int argc; + char *argv[]; +{ + char *input_target = NULL, *output_target = NULL; + boolean show_version = false; + int c, i; + struct section_list *p; + char *output_file = NULL; + + while ((c = getopt_long (argc, argv, "I:O:F:K:N:R:o:sSpgxXVv", + strip_options, (int *) 0)) != EOF) + { + switch (c) + { + case 'I': + input_target = optarg; + break; + case 'O': + output_target = optarg; + break; + case 'F': + input_target = output_target = optarg; + break; + case 'R': + p = find_section_list (optarg, true); + p->remove = true; + sections_removed = true; + break; + case 's': + strip_symbols = STRIP_ALL; + break; + case 'S': + case 'g': + strip_symbols = STRIP_DEBUG; + break; + case OPTION_STRIP_UNNEEDED: + strip_symbols = STRIP_UNNEEDED; + break; + case 'K': + add_specific_symbol (optarg, &keep_specific_list); + break; + case 'N': + add_specific_symbol (optarg, &strip_specific_list); + break; + case 'o': + output_file = optarg; + break; + case 'p': + preserve_dates = true; + break; + case 'x': + discard_locals = LOCALS_ALL; + break; + case 'X': + discard_locals = LOCALS_START_L; + break; + case 'v': + verbose = true; + break; + case 'V': + show_version = true; + break; + case 0: + break; /* we've been given a long option */ + case 'h': + strip_usage (stdout, 0); + default: + strip_usage (stderr, 1); + } + } + + if (show_version) + print_version ("strip"); + + /* Default is to strip all symbols. */ + if (strip_symbols == STRIP_UNDEF + && discard_locals == LOCALS_UNDEF + && strip_specific_list == NULL) + strip_symbols = STRIP_ALL; + + if (output_target == (char *) NULL) + output_target = input_target; + + i = optind; + if (i == argc + || (output_file != NULL && (i + 1) < argc)) + strip_usage (stderr, 1); + + for (; i < argc; i++) + { + int hold_status = status; + struct stat statbuf; + char *tmpname; + + if (preserve_dates) + { + if (stat (argv[i], &statbuf) < 0) + { + non_fatal (_("%s: cannot stat: %s"), argv[i], strerror (errno)); + continue; + } + } + + if (output_file != NULL) + tmpname = output_file; + else + tmpname = make_tempname (argv[i]); + status = 0; + + copy_file (argv[i], tmpname, input_target, output_target); + if (status == 0) + { + if (preserve_dates) + set_times (tmpname, &statbuf); + if (output_file == NULL) + smart_rename (tmpname, argv[i], preserve_dates); + status = hold_status; + } + else + unlink (tmpname); + if (output_file == NULL) + free (tmpname); + } + + return 0; +} + +static int +copy_main (argc, argv) + int argc; + char *argv[]; +{ + char *input_filename = NULL, *output_filename = NULL; + char *input_target = NULL, *output_target = NULL; + boolean show_version = false; + boolean change_warn = true; + int c; + struct section_list *p; + struct stat statbuf; + + while ((c = getopt_long (argc, argv, "b:i:I:K:N:s:O:d:F:L:R:SpgxXVvW:", + copy_options, (int *) 0)) != EOF) + { + switch (c) + { + case 'b': + copy_byte = atoi (optarg); + if (copy_byte < 0) + fatal (_("byte number must be non-negative")); + break; + case 'i': + interleave = atoi (optarg); + if (interleave < 1) + fatal (_("interleave must be positive")); + break; + case 'I': + case 's': /* "source" - 'I' is preferred */ + input_target = optarg; + break; + case 'O': + case 'd': /* "destination" - 'O' is preferred */ + output_target = optarg; + break; + case 'F': + input_target = output_target = optarg; + break; + case 'R': + p = find_section_list (optarg, true); + p->remove = true; + sections_removed = true; + break; + case 'S': + strip_symbols = STRIP_ALL; + break; + case 'g': + strip_symbols = STRIP_DEBUG; + break; + case OPTION_STRIP_UNNEEDED: + strip_symbols = STRIP_UNNEEDED; + break; + case 'K': + add_specific_symbol (optarg, &keep_specific_list); + break; + case 'N': + add_specific_symbol (optarg, &strip_specific_list); + break; + case 'L': + add_specific_symbol (optarg, &localize_specific_list); + break; + case 'W': + add_specific_symbol (optarg, &weaken_specific_list); + break; + case 'p': + preserve_dates = true; + break; + case 'x': + discard_locals = LOCALS_ALL; + break; + case 'X': + discard_locals = LOCALS_START_L; + break; + case 'v': + verbose = true; + break; + case 'V': + show_version = true; + break; + case OPTION_WEAKEN: + weaken = true; + break; + case OPTION_ADD_SECTION: + { + const char *s; + struct stat st; + struct section_add *pa; + int len; + char *name; + FILE *f; + + s = strchr (optarg, '='); + + if (s == NULL) + fatal (_("bad format for --add-section NAME=FILENAME")); + + if (stat (s + 1, & st) < 0) + fatal (_("cannot stat: %s: %s"), s + 1, strerror (errno)); + + pa = (struct section_add *) xmalloc (sizeof (struct section_add)); + + len = s - optarg; + name = (char *) xmalloc (len + 1); + strncpy (name, optarg, len); + name[len] = '\0'; + pa->name = name; + + pa->filename = s + 1; + + pa->size = st.st_size; + + pa->contents = (bfd_byte *) xmalloc (pa->size); + f = fopen (pa->filename, FOPEN_RB); + + if (f == NULL) + fatal (_("cannot open: %s: %s"), pa->filename, strerror (errno)); + + if (fread (pa->contents, 1, pa->size, f) == 0 + || ferror (f)) + fatal (_("%s: fread failed"), pa->filename); + + fclose (f); + + pa->next = add_sections; + add_sections = pa; + } + break; + case OPTION_CHANGE_START: + change_start = parse_vma (optarg, "--change-start"); + break; + case OPTION_CHANGE_SECTION_ADDRESS: + case OPTION_CHANGE_SECTION_LMA: + case OPTION_CHANGE_SECTION_VMA: + { + const char *s; + int len; + char *name; + char *option; + bfd_vma val; + enum change_action what; + + switch (c) + { + case OPTION_CHANGE_SECTION_ADDRESS: option = "--change-section-address"; break; + case OPTION_CHANGE_SECTION_LMA: option = "--change-section-lma"; break; + case OPTION_CHANGE_SECTION_VMA: option = "--change-section-vma"; break; + } + + s = strchr (optarg, '='); + if (s == NULL) + { + s = strchr (optarg, '+'); + if (s == NULL) + { + s = strchr (optarg, '-'); + if (s == NULL) + fatal (_("bad format for %s"), option); + } + } + + len = s - optarg; + name = (char *) xmalloc (len + 1); + strncpy (name, optarg, len); + name[len] = '\0'; + + p = find_section_list (name, true); + + val = parse_vma (s + 1, option); + + switch (*s) + { + case '=': what = CHANGE_SET; break; + case '-': val = - val; /* Drop through. */ + case '+': what = CHANGE_MODIFY; break; + } + + switch (c) + { + case OPTION_CHANGE_SECTION_ADDRESS: + p->change_vma = what; + p->vma_val = val; + /* Drop through. */ + + case OPTION_CHANGE_SECTION_LMA: + p->change_lma = what; + p->lma_val = val; + break; + + case OPTION_CHANGE_SECTION_VMA: + p->change_vma = what; + p->vma_val = val; + break; + } + } + break; + case OPTION_CHANGE_ADDRESSES: + change_section_address = parse_vma (optarg, "--change-addresses"); + change_start = change_section_address; + break; + case OPTION_CHANGE_WARNINGS: + change_warn = true; + break; + case OPTION_CHANGE_LEADING_CHAR: + change_leading_char = true; + break; + case OPTION_DEBUGGING: + convert_debugging = true; + break; + case OPTION_GAP_FILL: + { + bfd_vma gap_fill_vma; + + gap_fill_vma = parse_vma (optarg, "--gap-fill"); + gap_fill = (bfd_byte) gap_fill_vma; + if ((bfd_vma) gap_fill != gap_fill_vma) + { + char buff[20]; + + sprintf_vma (buff, gap_fill_vma); + + non_fatal (_("Warning: truncating gap-fill from 0x%s to 0x%x"), + buff, gap_fill); + } + gap_fill_set = true; + } + break; + case OPTION_NO_CHANGE_WARNINGS: + change_warn = false; + break; + case OPTION_PAD_TO: + pad_to = parse_vma (optarg, "--pad-to"); + pad_to_set = true; + break; + case OPTION_REMOVE_LEADING_CHAR: + remove_leading_char = true; + break; + case OPTION_SET_SECTION_FLAGS: + { + const char *s; + int len; + char *name; + + s = strchr (optarg, '='); + if (s == NULL) + fatal (_("bad format for --set-section-flags")); + + len = s - optarg; + name = (char *) xmalloc (len + 1); + strncpy (name, optarg, len); + name[len] = '\0'; + + p = find_section_list (name, true); + + p->set_flags = true; + p->flags = parse_flags (s + 1); + } + break; + case OPTION_SET_START: + set_start = parse_vma (optarg, "--set-start"); + set_start_set = true; + break; + case 0: + break; /* we've been given a long option */ + case 'h': + copy_usage (stdout, 0); + default: + copy_usage (stderr, 1); + } + } + + if (show_version) + print_version ("objcopy"); + + if (copy_byte >= interleave) + fatal (_("byte number must be less than interleave")); + + if (optind == argc || optind + 2 < argc) + copy_usage (stderr, 1); + + input_filename = argv[optind]; + if (optind + 1 < argc) + output_filename = argv[optind + 1]; + + /* Default is to strip no symbols. */ + if (strip_symbols == STRIP_UNDEF && discard_locals == LOCALS_UNDEF) + strip_symbols = STRIP_NONE; + + if (output_target == (char *) NULL) + output_target = input_target; + + if (preserve_dates) + { + if (stat (input_filename, &statbuf) < 0) + fatal (_("Cannot stat: %s: %s"), input_filename, strerror (errno)); + } + + /* If there is no destination file then create a temp and rename + the result into the input. */ + + if (output_filename == (char *) NULL) + { + char *tmpname = make_tempname (input_filename); + + copy_file (input_filename, tmpname, input_target, output_target); + if (status == 0) + { + if (preserve_dates) + set_times (tmpname, &statbuf); + smart_rename (tmpname, input_filename, preserve_dates); + } + else + unlink (tmpname); + } + else + { + copy_file (input_filename, output_filename, input_target, output_target); + if (status == 0 && preserve_dates) + set_times (output_filename, &statbuf); + } + + if (change_warn) + { + for (p = change_sections; p != NULL; p = p->next) + { + if (! p->used) + { + if (p->change_vma != CHANGE_IGNORE) + { + char buff [20]; + + sprintf_vma (buff, p->vma_val); + + /* xgettext:c-format */ + non_fatal (_("Warning: --change-section-vma %s%c0x%s never used"), + p->name, + p->change_vma == CHANGE_SET ? '=' : '+', + buff); + } + + if (p->change_lma != CHANGE_IGNORE) + { + char buff [20]; + + sprintf_vma (buff, p->lma_val); + + /* xgettext:c-format */ + non_fatal (_("Warning: --change-section-lma %s%c0x%s never used"), + p->name, + p->change_lma == CHANGE_SET ? '=' : '+', + buff); + } + } + } + } + + return 0; +} + +int +main (argc, argv) + int argc; + char *argv[]; +{ +#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) + setlocale (LC_MESSAGES, ""); +#endif + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + + program_name = argv[0]; + xmalloc_set_program_name (program_name); + + START_PROGRESS (program_name, 0); + + strip_symbols = STRIP_UNDEF; + discard_locals = LOCALS_UNDEF; + + bfd_init (); + set_default_bfd_target (); + + if (is_strip < 0) + { + int i = strlen (program_name); + is_strip = (i >= 5 && strcmp (program_name + i - 5, "strip") == 0); + } + + if (is_strip) + strip_main (argc, argv); + else + copy_main (argc, argv); + + END_PROGRESS (program_name); + + return status; +} diff --git a/binutils/objdump.1 b/binutils/objdump.1 new file mode 100644 index 0000000..ddc153e --- /dev/null +++ b/binutils/objdump.1 @@ -0,0 +1,412 @@ +.\" Copyright (c) 1991, 92, 93, 94, 95, 96, 97, 1998 Free Software Foundation +.\" See section COPYING for conditions for redistribution +.TH objdump 1 "5 November 1991" "cygnus support" "GNU Development Tools" +.de BP +.sp +.ti \-.2i +\(** +.. + +.SH NAME +objdump \- display information from object files. + +.SH SYNOPSIS +.hy 0 +.na +.TP +.B objdump +.RB "[\|" \-a | \-\-archive\-headers "\|]" +.RB "[\|" "\-b\ "\c +.I bfdname\c +.RB " | " "\-\-target="\c +.I bfdname\c +\&\|] +.RB "[\|" \-C | \-\-demangle "\|]" +.RB "[\|" \-\-debugging "\|]" +.RB "[\|" \-d | \-\-disassemble "\|]" +.RB "[\|" \-D | \-\-disassemble-all "\|]" +.RB "[\|" \-\-disassemble\-zeroes "\|]" +.RB "[\|" \-EB | \-EL | \-\-endian=\c +.I {big|little}\c +\&\|] +.RB "[\|" \-f | \-\-file\-headers "\|]" +.RB "[\|" \-h | \-\-section\-headers +.RB "| " \-\-headers "\|]" +.RB "[\|" \-i | \-\-info "\|]" +.RB "[\|" "\-j\ "\c +.I section\c +.RB " | " "\-\-section="\c +.I section\c +\&\|] +.RB "[\|" \-l | \-\-line\-numbers "\|]" +.RB "[\|" "\-m\ "\c +.I machine\c +.RB " | " "\-\-architecture="\c +.I machine\c +\&\|] +.RB "[\|" \-p | \-\-private\-headers "\|]" +.RB "[\|" \-\-prefix\-addresses "\|]" +.RB "[\|" \-r | \-\-reloc "\|]" +.RB "[\|" \-R | \-\-dynamic\-reloc "\|]" +.RB "[\|" \-s | \-\-full\-contents "\|]" +.RB "[\|" \-S | \-\-source "\|]" +.RB "[\|" \-\-[no\-]show\-raw\-insn "\|]" +.RB "[\|" \-\-stabs "\|]" +.RB "[\|" \-t | \-\-syms "\|]" +.RB "[\|" \-T | \-\-dynamic\-syms "\|]" +.RB "[\|" \-x | \-\-all\-headers "\|]" +.RB "[\|" "\-\-start\-address="\c +.I address\c +\&\|] +.RB "[\|" "\-\-stop\-address="\c +.I address\c +\&\|] +.RB "[\|" "\-\-adjust\-vma="\c +.I offset\c +\&\|] +.RB "[\|" \-\-version "\|]" +.RB "[\|" \-\-help "\|]" +.I objfile\c +\&.\|.\|. +.ad b +.hy 1 +.SH DESCRIPTION +\c +.B objdump\c +\& displays information about one or more object files. +The options control what particular information to display. This +information is mostly useful to programmers who are working on the +compilation tools, as opposed to programmers who just want their +program to compile and work. +.PP +.IR "objfile" .\|.\|. +are the object files to be examined. When you specify archives, +\c +.B objdump\c +\& shows information on each of the member object files. + +.SH OPTIONS +Where long and short forms of an option are shown together, they are +equivalent. At least one option besides +.B \-l +(\fB\-\-line\-numbers\fP) must be given. + +.TP +.B \-a +.TP +.B \-\-archive\-headers +If any files from \c +.I objfile\c +\& are archives, display the archive +header information (in a format similar to `\|\c +.B ls \-l\c +\|'). Besides the +information you could list with `\|\c +.B ar tv\c +\|', `\|\c +.B objdump \-a\c +\|' shows +the object file format of each archive member. + +.TP +.BI "\-\-adjust\-vma=" "offset" +When dumping information, first add +.I offset +to all the section addresses. This is useful if the section addresses +do not correspond to the symbol table, which can happen when putting +sections at particular addresses when using a format which can not +represent section addresses, such as a.out. + +.TP +.BI "\-b " "bfdname"\c +.TP +.BI "\-\-target=" "bfdname" +Specify the object-code format for the object files to be +\c +.I bfdname\c +\&. This may not be necessary; \c +.I objdump\c +\& can +automatically recognize many formats. For example, +.sp +.br +objdump\ \-b\ oasys\ \-m\ vax\ \-h\ fu.o +.br +.sp +display summary information from the section headers (`\|\c +.B \-h\c +\|') of +`\|\c +.B fu.o\c +\|', which is explicitly identified (`\|\c +.B \-m\c +\|') as a Vax object +file in the format produced by Oasys compilers. You can list the +formats available with the `\|\c +.B \-i\c +\|' option. + +.TP +.B \-C +.TP +.B \-\-demangle +Decode (\fIdemangle\fP) low-level symbol names into user-level names. +Besides removing any initial underscore prepended by the system, this +makes C++ function names readable. + +.TP +.B \-\-debugging +Display debugging information. This attempts to parse debugging +information stored in the file and print it out using a C like syntax. +Only certain types of debugging information have been implemented. + +.TP +.B \-d +.TP +.B \-\-disassemble +Display the assembler mnemonics for the machine +instructions from \c +.I objfile\c +\&. +This option only disassembles those sections which are +expected to contain instructions. + +.TP +.B \-D +.TP +.B \-\-disassemble-all +Like \fB\-d\fP, but disassemble the contents of all sections, not just +those expected to contain instructions. + +.TP +.B \-\-prefix\-addresses +When disassembling, print the complete address on each line. This is +the older disassembly format. + +.TP +.B \-\-disassemble\-zeroes +Normally the disassembly output will skip blocks of zeroes. This +option directs the disassembler to disassemble those blocks, just like +any other data. + +.TP +.B \-EB +.TP +.B \-EL +.TP +.BI "\-\-endian=" "{big|little}" +Specify the endianness of the object files. This only affects +disassembly. This can be useful when disassembling a file format which +does not describe endianness information, such as S-records. + +.TP +.B \-f +.TP +.B \-\-file\-headers +Display summary information from the overall header of +each file in \c +.I objfile\c +\&. + +.TP +.B \-h +.TP +.B \-\-section\-headers +.TP +.B \-\-headers +Display summary information from the section headers of the +object file. + +.TP +.B \-\-help +Print a summary of the options to +.B objdump +and exit. + +.TP +.B \-i +.TP +.B \-\-info +Display a list showing all architectures and object formats available +for specification with \c +.B \-b\c +\& or \c +.B \-m\c +\&. + +.TP +.BI "\-j " "name"\c +.TP +.BI "\-\-section=" "name" +Display information only for section \c +.I name\c +\&. + +.TP +.B \-l +.TP +.B \-\-line\-numbers +Label the display (using debugging information) with the filename +and source line numbers corresponding to the object code shown. +Only useful with \fB\-d\fP, \fB\-D\fP, or \fB\-r\fP. + +.TP +.BI "\-m " "machine"\c +.TP +.BI "\-\-architecture=" "machine" +Specify the architecture to use when disassembling object files. This +can be useful when disassembling object files which do not describe +architecture information, such as S-records. You can list the available +architectures with the \fB\-i\fP option. + +.TP +.B \-p +.TP +.B \-\-private\-headers +Print information that is specific to the object file format. The +exact information printed depends upon the object file format. For +some object file formats, no additional information is printed. + +.TP +.B \-r +.TP +.B \-\-reloc +Print the relocation entries of the file. If used with \fB\-d\fP or +\fB\-D\fP, the relocations are printed interspersed with the +disassembly. + +.TP +.B \-R +.TP +.B \-\-dynamic\-reloc +Print the dynamic relocation entries of the file. This is only +meaningful for dynamic objects, such as certain types of shared +libraries. + +.TP +.B \-s +.TP +.B \-\-full\-contents +Display the full contents of any sections requested. + +.TP +.B \-S +.TP +.B \-\-source +Display source code intermixed with disassembly, if possible. Implies +\fB-d\fP. + +.TP +.B \-\-show\-raw\-insn +When disassembling instructions, print the instruction in hex as well as +in symbolic form. This is the default except when +.B \-\-prefix\-addresses +is used. + +.TP +.B \-\-no\-show\-raw\-insn +When disassembling instructions, do not print the instruction bytes. +This is the default when +.B \-\-prefix\-addresses +is used. + +.TP +.B \-\-stabs +Display the contents of the .stab, .stab.index, and .stab.excl +sections from an ELF file. This is only useful on systems (such as +Solaris 2.0) in which .stab debugging symbol-table entries are carried +in an ELF section. In most other file formats, debugging symbol-table +entries are interleaved with linkage symbols, and are visible in the +.B \-\-syms +output. + +.TP +.BI "\-\-start\-address=" "address" +Start displaying data at the specified address. This affects the output +of the +.B \-d\c +, +.B \-r +and +.B \-s +options. + +.TP +.BI "\-\-stop\-address=" "address" +Stop displaying data at the specified address. This affects the output +of the +.B \-d\c +, +.B \-r +and +.B \-s +options. + +.TP +.B \-t +.TP +.B \-\-syms +Symbol Table. Print the symbol table entries of the file. +This is similar to the information provided by the `\|\c +.B nm\c +\|' program. + +.TP +.B \-T +.TP +.B \-\-dynamic\-syms +Dynamic Symbol Table. Print the dynamic symbol table entries of the +file. This is only meaningful for dynamic objects, such as certain +types of shared libraries. This is similar to the information +provided by the `\|\c +.B nm\c +\|' program when given the +.B \-D (\-\-dynamic) +option. + +.TP +.B \-\-version +Print the version number of +.B objdump +and exit. + +.TP +.B \-x +.TP +.B \-\-all\-headers +Display all available header information, including the symbol table and +relocation entries. Using `\|\c +.B \-x\c +\|' is equivalent to specifying all of +`\|\c +.B \-a \-f \-h \-r \-t\c +\|'. + +.SH "SEE ALSO" +.RB "`\|" binutils "\|'" +entry in +.B +info\c +\&; +.I +The GNU Binary Utilities\c +\&, Roland H. Pesch (October 1991); +.BR nm "(" 1 ")." + +.SH COPYING +Copyright (c) 1991, 92, 93, 94, 95, 1996 Free Software Foundation, Inc. +.PP +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. +.PP +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the +entire resulting derived work is distributed under the terms of a +permission notice identical to this one. +.PP +Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be included in +translations approved by the Free Software Foundation instead of in +the original English. diff --git a/binutils/objdump.c b/binutils/objdump.c new file mode 100644 index 0000000..3f9e8c4 --- /dev/null +++ b/binutils/objdump.c @@ -0,0 +1,2829 @@ +/* objdump.c -- dump information about an object file. + Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 98, 1999 + Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +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, 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "bfd.h" +#include "getopt.h" +#include "progress.h" +#include "bucomm.h" +#include <ctype.h> +#include "dis-asm.h" +#include "libiberty.h" +#include "demangle.h" +#include "debug.h" +#include "budbg.h" + +#ifdef ANSI_PROTOTYPES +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +/* Internal headers for the ELF .stab-dump code - sorry. */ +#define BYTES_IN_WORD 32 +#include "aout/aout64.h" + +#ifdef NEED_DECLARATION_FPRINTF +/* This is needed by INIT_DISASSEMBLE_INFO. */ +extern int fprintf PARAMS ((FILE *, const char *, ...)); +#endif + +static char *default_target = NULL; /* default at runtime */ + +static int show_version = 0; /* show the version number */ +static int dump_section_contents; /* -s */ +static int dump_section_headers; /* -h */ +static boolean dump_file_header; /* -f */ +static int dump_symtab; /* -t */ +static int dump_dynamic_symtab; /* -T */ +static int dump_reloc_info; /* -r */ +static int dump_dynamic_reloc_info; /* -R */ +static int dump_ar_hdrs; /* -a */ +static int dump_private_headers; /* -p */ +static int prefix_addresses; /* --prefix-addresses */ +static int with_line_numbers; /* -l */ +static boolean with_source_code; /* -S */ +static int show_raw_insn; /* --show-raw-insn */ +static int dump_stab_section_info; /* --stabs */ +static int do_demangle; /* -C, --demangle */ +static boolean disassemble; /* -d */ +static boolean disassemble_all; /* -D */ +static int disassemble_zeroes; /* --disassemble-zeroes */ +static boolean formats_info; /* -i */ +static char *only; /* -j secname */ +static int wide_output; /* -w */ +static bfd_vma start_address = (bfd_vma) -1; /* --start-address */ +static bfd_vma stop_address = (bfd_vma) -1; /* --stop-address */ +static int dump_debugging; /* --debugging */ +static bfd_vma adjust_section_vma = 0; /* --adjust-vma */ + +/* Extra info to pass to the disassembler address printing function. */ +struct objdump_disasm_info { + bfd *abfd; + asection *sec; + boolean require_sec; +}; + +/* Architecture to disassemble for, or default if NULL. */ +static char *machine = (char *) NULL; + +/* Endianness to disassemble for, or default if BFD_ENDIAN_UNKNOWN. */ +static enum bfd_endian endian = BFD_ENDIAN_UNKNOWN; + +/* The symbol table. */ +static asymbol **syms; + +/* Number of symbols in `syms'. */ +static long symcount = 0; + +/* The sorted symbol table. */ +static asymbol **sorted_syms; + +/* Number of symbols in `sorted_syms'. */ +static long sorted_symcount = 0; + +/* The dynamic symbol table. */ +static asymbol **dynsyms; + +/* Number of symbols in `dynsyms'. */ +static long dynsymcount = 0; + +/* Static declarations. */ + +static void +usage PARAMS ((FILE *, int)); + +static void +display_file PARAMS ((char *filename, char *target)); + +static void +dump_section_header PARAMS ((bfd *, asection *, PTR)); + +static void +dump_headers PARAMS ((bfd *)); + +static void +dump_data PARAMS ((bfd *abfd)); + +static void +dump_relocs PARAMS ((bfd *abfd)); + +static void +dump_dynamic_relocs PARAMS ((bfd * abfd)); + +static void +dump_reloc_set PARAMS ((bfd *, asection *, arelent **, long)); + +static void +dump_symbols PARAMS ((bfd *abfd, boolean dynamic)); + +static void +dump_bfd_header PARAMS ((bfd *)); + +static void +dump_bfd_private_header PARAMS ((bfd *)); + +static void +display_bfd PARAMS ((bfd *abfd)); + +static void +display_target_list PARAMS ((void)); + +static void +display_info_table PARAMS ((int, int)); + +static void +display_target_tables PARAMS ((void)); + +static void +display_info PARAMS ((void)); + +static void +objdump_print_value PARAMS ((bfd_vma, struct disassemble_info *, boolean)); + +static void +objdump_print_symname PARAMS ((bfd *, struct disassemble_info *, asymbol *)); + +static asymbol * +find_symbol_for_address PARAMS ((bfd *, asection *, bfd_vma, boolean, long *)); + +static void +objdump_print_addr_with_sym PARAMS ((bfd *, asection *, asymbol *, bfd_vma, + struct disassemble_info *, boolean)); + +static void +objdump_print_addr PARAMS ((bfd_vma, struct disassemble_info *, boolean)); + +static void +objdump_print_address PARAMS ((bfd_vma, struct disassemble_info *)); + +static void +show_line PARAMS ((bfd *, asection *, bfd_vma)); + +static void +disassemble_bytes PARAMS ((struct disassemble_info *, disassembler_ftype, + boolean, bfd_byte *, bfd_vma, bfd_vma, + arelent ***, arelent **)); + +static void +disassemble_data PARAMS ((bfd *)); + +static const char * +endian_string PARAMS ((enum bfd_endian)); + +static asymbol ** +slurp_symtab PARAMS ((bfd *)); + +static asymbol ** +slurp_dynamic_symtab PARAMS ((bfd *)); + +static long +remove_useless_symbols PARAMS ((asymbol **, long)); + +static int +compare_symbols PARAMS ((const PTR, const PTR)); + +static int +compare_relocs PARAMS ((const PTR, const PTR)); + +static void +dump_stabs PARAMS ((bfd *)); + +static boolean +read_section_stabs PARAMS ((bfd *, const char *, const char *)); + +static void +print_section_stabs PARAMS ((bfd *, const char *, const char *)); + +static void +usage (stream, status) + FILE *stream; + int status; +{ + fprintf (stream, _("\ +Usage: %s [-ahifCdDprRtTxsSlw] [-b bfdname] [-m machine] [-j section-name]\n\ + [--archive-headers] [--target=bfdname] [--debugging] [--disassemble]\n\ + [--disassemble-all] [--disassemble-zeroes] [--file-headers]\n\ + [--section-headers] [--headers]\n\ + [--info] [--section=section-name] [--line-numbers] [--source]\n"), + program_name); + fprintf (stream, _("\ + [--architecture=machine] [--reloc] [--full-contents] [--stabs]\n\ + [--syms] [--all-headers] [--dynamic-syms] [--dynamic-reloc]\n\ + [--wide] [--version] [--help] [--private-headers]\n\ + [--start-address=addr] [--stop-address=addr]\n\ + [--prefix-addresses] [--[no-]show-raw-insn] [--demangle]\n\ + [--adjust-vma=offset] [-EB|-EL] [--endian={big|little}] objfile...\n\ +at least one option besides -l (--line-numbers) must be given\n")); + list_supported_targets (program_name, stream); + if (status == 0) + fprintf (stream, _("Report bugs to bug-gnu-utils@gnu.org\n")); + exit (status); +} + +/* 150 isn't special; it's just an arbitrary non-ASCII char value. */ + +#define OPTION_ENDIAN (150) +#define OPTION_START_ADDRESS (OPTION_ENDIAN + 1) +#define OPTION_STOP_ADDRESS (OPTION_START_ADDRESS + 1) +#define OPTION_ADJUST_VMA (OPTION_STOP_ADDRESS + 1) + +static struct option long_options[]= +{ + {"adjust-vma", required_argument, NULL, OPTION_ADJUST_VMA}, + {"all-headers", no_argument, NULL, 'x'}, + {"private-headers", no_argument, NULL, 'p'}, + {"architecture", required_argument, NULL, 'm'}, + {"archive-headers", no_argument, NULL, 'a'}, + {"debugging", no_argument, &dump_debugging, 1}, + {"demangle", no_argument, &do_demangle, 1}, + {"disassemble", no_argument, NULL, 'd'}, + {"disassemble-all", no_argument, NULL, 'D'}, + {"disassemble-zeroes", no_argument, &disassemble_zeroes, 1}, + {"dynamic-reloc", no_argument, NULL, 'R'}, + {"dynamic-syms", no_argument, NULL, 'T'}, + {"endian", required_argument, NULL, OPTION_ENDIAN}, + {"file-headers", no_argument, NULL, 'f'}, + {"full-contents", no_argument, NULL, 's'}, + {"headers", no_argument, NULL, 'h'}, + {"help", no_argument, NULL, 'H'}, + {"info", no_argument, NULL, 'i'}, + {"line-numbers", no_argument, NULL, 'l'}, + {"no-show-raw-insn", no_argument, &show_raw_insn, -1}, + {"prefix-addresses", no_argument, &prefix_addresses, 1}, + {"reloc", no_argument, NULL, 'r'}, + {"section", required_argument, NULL, 'j'}, + {"section-headers", no_argument, NULL, 'h'}, + {"show-raw-insn", no_argument, &show_raw_insn, 1}, + {"source", no_argument, NULL, 'S'}, + {"stabs", no_argument, &dump_stab_section_info, 1}, + {"start-address", required_argument, NULL, OPTION_START_ADDRESS}, + {"stop-address", required_argument, NULL, OPTION_STOP_ADDRESS}, + {"syms", no_argument, NULL, 't'}, + {"target", required_argument, NULL, 'b'}, + {"version", no_argument, &show_version, 1}, + {"wide", no_argument, &wide_output, 'w'}, + {0, no_argument, 0, 0} +}; + +static void +dump_section_header (abfd, section, ignored) + bfd *abfd; + asection *section; + PTR ignored; +{ + char *comma = ""; + + printf ("%3d %-13s %08lx ", section->index, + bfd_get_section_name (abfd, section), + (unsigned long) bfd_section_size (abfd, section)); + printf_vma (bfd_get_section_vma (abfd, section)); + printf (" "); + printf_vma (section->lma); + printf (" %08lx 2**%u", section->filepos, + bfd_get_section_alignment (abfd, section)); + if (! wide_output) + printf ("\n "); + printf (" "); + +#define PF(x, y) \ + if (section->flags & x) { printf ("%s%s", comma, y); comma = ", "; } + + PF (SEC_HAS_CONTENTS, "CONTENTS"); + PF (SEC_ALLOC, "ALLOC"); + PF (SEC_CONSTRUCTOR, "CONSTRUCTOR"); + PF (SEC_CONSTRUCTOR_TEXT, "CONSTRUCTOR TEXT"); + PF (SEC_CONSTRUCTOR_DATA, "CONSTRUCTOR DATA"); + PF (SEC_CONSTRUCTOR_BSS, "CONSTRUCTOR BSS"); + PF (SEC_LOAD, "LOAD"); + PF (SEC_RELOC, "RELOC"); +#ifdef SEC_BALIGN + PF (SEC_BALIGN, "BALIGN"); +#endif + PF (SEC_READONLY, "READONLY"); + PF (SEC_CODE, "CODE"); + PF (SEC_DATA, "DATA"); + PF (SEC_ROM, "ROM"); + PF (SEC_DEBUGGING, "DEBUGGING"); + PF (SEC_NEVER_LOAD, "NEVER_LOAD"); + PF (SEC_EXCLUDE, "EXCLUDE"); + PF (SEC_SORT_ENTRIES, "SORT_ENTRIES"); + + if ((section->flags & SEC_LINK_ONCE) != 0) + { + const char *ls; + + switch (section->flags & SEC_LINK_DUPLICATES) + { + default: + abort (); + case SEC_LINK_DUPLICATES_DISCARD: + ls = "LINK_ONCE_DISCARD"; + break; + case SEC_LINK_DUPLICATES_ONE_ONLY: + ls = "LINK_ONCE_ONE_ONLY"; + break; + case SEC_LINK_DUPLICATES_SAME_SIZE: + ls = "LINK_ONCE_SAME_SIZE"; + break; + case SEC_LINK_DUPLICATES_SAME_CONTENTS: + ls = "LINK_ONCE_SAME_CONTENTS"; + break; + } + printf ("%s%s", comma, ls); + comma = ", "; + } + + printf ("\n"); +#undef PF +} + +static void +dump_headers (abfd) + bfd *abfd; +{ + printf (_("Sections:\n")); +#ifndef BFD64 + printf (_("Idx Name Size VMA LMA File off Algn\n")); +#else + printf (_("Idx Name Size VMA LMA File off Algn\n")); +#endif + bfd_map_over_sections (abfd, dump_section_header, (PTR) NULL); +} + +static asymbol ** +slurp_symtab (abfd) + bfd *abfd; +{ + asymbol **sy = (asymbol **) NULL; + long storage; + + if (!(bfd_get_file_flags (abfd) & HAS_SYMS)) + { + fprintf (stderr, _("%s: no symbols\n"), bfd_get_filename (abfd)); + symcount = 0; + return NULL; + } + + storage = bfd_get_symtab_upper_bound (abfd); + if (storage < 0) + bfd_fatal (bfd_get_filename (abfd)); + + if (storage) + { + sy = (asymbol **) xmalloc (storage); + } + symcount = bfd_canonicalize_symtab (abfd, sy); + if (symcount < 0) + bfd_fatal (bfd_get_filename (abfd)); + if (symcount == 0) + fprintf (stderr, _("%s: no symbols\n"), bfd_get_filename (abfd)); + return sy; +} + +/* Read in the dynamic symbols. */ + +static asymbol ** +slurp_dynamic_symtab (abfd) + bfd *abfd; +{ + asymbol **sy = (asymbol **) NULL; + long storage; + + storage = bfd_get_dynamic_symtab_upper_bound (abfd); + if (storage < 0) + { + if (!(bfd_get_file_flags (abfd) & DYNAMIC)) + { + fprintf (stderr, _("%s: %s: not a dynamic object\n"), + program_name, bfd_get_filename (abfd)); + dynsymcount = 0; + return NULL; + } + + bfd_fatal (bfd_get_filename (abfd)); + } + + if (storage) + { + sy = (asymbol **) xmalloc (storage); + } + dynsymcount = bfd_canonicalize_dynamic_symtab (abfd, sy); + if (dynsymcount < 0) + bfd_fatal (bfd_get_filename (abfd)); + if (dynsymcount == 0) + fprintf (stderr, _("%s: %s: No dynamic symbols\n"), + program_name, bfd_get_filename (abfd)); + return sy; +} + +/* Filter out (in place) symbols that are useless for disassembly. + COUNT is the number of elements in SYMBOLS. + Return the number of useful symbols. */ + +static long +remove_useless_symbols (symbols, count) + asymbol **symbols; + long count; +{ + register asymbol **in_ptr = symbols, **out_ptr = symbols; + + while (--count >= 0) + { + asymbol *sym = *in_ptr++; + + if (sym->name == NULL || sym->name[0] == '\0') + continue; + if (sym->flags & (BSF_DEBUGGING)) + continue; + if (bfd_is_und_section (sym->section) + || bfd_is_com_section (sym->section)) + continue; + + *out_ptr++ = sym; + } + return out_ptr - symbols; +} + +/* Sort symbols into value order. */ + +static int +compare_symbols (ap, bp) + const PTR ap; + const PTR bp; +{ + const asymbol *a = *(const asymbol **)ap; + const asymbol *b = *(const asymbol **)bp; + const char *an, *bn; + size_t anl, bnl; + boolean af, bf; + flagword aflags, bflags; + + if (bfd_asymbol_value (a) > bfd_asymbol_value (b)) + return 1; + else if (bfd_asymbol_value (a) < bfd_asymbol_value (b)) + return -1; + + if (a->section > b->section) + return 1; + else if (a->section < b->section) + return -1; + + an = bfd_asymbol_name (a); + bn = bfd_asymbol_name (b); + anl = strlen (an); + bnl = strlen (bn); + + /* The symbols gnu_compiled and gcc2_compiled convey no real + information, so put them after other symbols with the same value. */ + + af = (strstr (an, "gnu_compiled") != NULL + || strstr (an, "gcc2_compiled") != NULL); + bf = (strstr (bn, "gnu_compiled") != NULL + || strstr (bn, "gcc2_compiled") != NULL); + + if (af && ! bf) + return 1; + if (! af && bf) + return -1; + + /* We use a heuristic for the file name, to try to sort it after + more useful symbols. It may not work on non Unix systems, but it + doesn't really matter; the only difference is precisely which + symbol names get printed. */ + +#define file_symbol(s, sn, snl) \ + (((s)->flags & BSF_FILE) != 0 \ + || ((sn)[(snl) - 2] == '.' \ + && ((sn)[(snl) - 1] == 'o' \ + || (sn)[(snl) - 1] == 'a'))) + + af = file_symbol (a, an, anl); + bf = file_symbol (b, bn, bnl); + + if (af && ! bf) + return 1; + if (! af && bf) + return -1; + + /* Try to sort global symbols before local symbols before function + symbols before debugging symbols. */ + + aflags = a->flags; + bflags = b->flags; + + if ((aflags & BSF_DEBUGGING) != (bflags & BSF_DEBUGGING)) + { + if ((aflags & BSF_DEBUGGING) != 0) + return 1; + else + return -1; + } + if ((aflags & BSF_FUNCTION) != (bflags & BSF_FUNCTION)) + { + if ((aflags & BSF_FUNCTION) != 0) + return -1; + else + return 1; + } + if ((aflags & BSF_LOCAL) != (bflags & BSF_LOCAL)) + { + if ((aflags & BSF_LOCAL) != 0) + return 1; + else + return -1; + } + if ((aflags & BSF_GLOBAL) != (bflags & BSF_GLOBAL)) + { + if ((aflags & BSF_GLOBAL) != 0) + return -1; + else + return 1; + } + + /* Symbols that start with '.' might be section names, so sort them + after symbols that don't start with '.'. */ + if (an[0] == '.' && bn[0] != '.') + return 1; + if (an[0] != '.' && bn[0] == '.') + return -1; + + /* Finally, if we can't distinguish them in any other way, try to + get consistent results by sorting the symbols by name. */ + return strcmp (an, bn); +} + +/* Sort relocs into address order. */ + +static int +compare_relocs (ap, bp) + const PTR ap; + const PTR bp; +{ + const arelent *a = *(const arelent **)ap; + const arelent *b = *(const arelent **)bp; + + if (a->address > b->address) + return 1; + else if (a->address < b->address) + return -1; + + /* So that associated relocations tied to the same address show up + in the correct order, we don't do any further sorting. */ + if (a > b) + return 1; + else if (a < b) + return -1; + else + return 0; +} + +/* Print VMA to STREAM. If SKIP_ZEROES is true, omit leading zeroes. */ + +static void +objdump_print_value (vma, info, skip_zeroes) + bfd_vma vma; + struct disassemble_info *info; + boolean skip_zeroes; +{ + char buf[30]; + char *p; + + sprintf_vma (buf, vma); + if (! skip_zeroes) + p = buf; + else + { + for (p = buf; *p == '0'; ++p) + ; + if (*p == '\0') + --p; + } + (*info->fprintf_func) (info->stream, "%s", p); +} + +/* Print the name of a symbol. */ + +static void +objdump_print_symname (abfd, info, sym) + bfd *abfd; + struct disassemble_info *info; + asymbol *sym; +{ + char *alloc; + const char *name; + const char *print; + + alloc = NULL; + name = bfd_asymbol_name (sym); + if (! do_demangle || name[0] == '\0') + print = name; + else + { + /* Demangle the name. */ + if (bfd_get_symbol_leading_char (abfd) == name[0]) + ++name; + + alloc = cplus_demangle (name, DMGL_ANSI | DMGL_PARAMS); + if (alloc == NULL) + print = name; + else + print = alloc; + } + + if (info != NULL) + (*info->fprintf_func) (info->stream, "%s", print); + else + printf ("%s", print); + + if (alloc != NULL) + free (alloc); +} + +/* Locate a symbol given a bfd, a section, and a VMA. If REQUIRE_SEC + is true, then always require the symbol to be in the section. This + returns NULL if there is no suitable symbol. If PLACE is not NULL, + then *PLACE is set to the index of the symbol in sorted_syms. */ + +static asymbol * +find_symbol_for_address (abfd, sec, vma, require_sec, place) + bfd *abfd; + asection *sec; + bfd_vma vma; + boolean require_sec; + long *place; +{ + /* @@ Would it speed things up to cache the last two symbols returned, + and maybe their address ranges? For many processors, only one memory + operand can be present at a time, so the 2-entry cache wouldn't be + constantly churned by code doing heavy memory accesses. */ + + /* Indices in `sorted_syms'. */ + long min = 0; + long max = sorted_symcount; + long thisplace; + + if (sorted_symcount < 1) + return NULL; + + /* Perform a binary search looking for the closest symbol to the + required value. We are searching the range (min, max]. */ + while (min + 1 < max) + { + asymbol *sym; + + thisplace = (max + min) / 2; + sym = sorted_syms[thisplace]; + + if (bfd_asymbol_value (sym) > vma) + max = thisplace; + else if (bfd_asymbol_value (sym) < vma) + min = thisplace; + else + { + min = thisplace; + break; + } + } + + /* The symbol we want is now in min, the low end of the range we + were searching. If there are several symbols with the same + value, we want the first one. */ + thisplace = min; + while (thisplace > 0 + && (bfd_asymbol_value (sorted_syms[thisplace]) + == bfd_asymbol_value (sorted_syms[thisplace - 1]))) + --thisplace; + + /* If the file is relocateable, and the symbol could be from this + section, prefer a symbol from this section over symbols from + others, even if the other symbol's value might be closer. + + Note that this may be wrong for some symbol references if the + sections have overlapping memory ranges, but in that case there's + no way to tell what's desired without looking at the relocation + table. */ + + if (sorted_syms[thisplace]->section != sec + && (require_sec + || ((abfd->flags & HAS_RELOC) != 0 + && vma >= bfd_get_section_vma (abfd, sec) + && vma < (bfd_get_section_vma (abfd, sec) + + bfd_section_size (abfd, sec))))) + { + long i; + + for (i = thisplace + 1; i < sorted_symcount; i++) + { + if (bfd_asymbol_value (sorted_syms[i]) + != bfd_asymbol_value (sorted_syms[thisplace])) + break; + } + --i; + for (; i >= 0; i--) + { + if (sorted_syms[i]->section == sec + && (i == 0 + || sorted_syms[i - 1]->section != sec + || (bfd_asymbol_value (sorted_syms[i]) + != bfd_asymbol_value (sorted_syms[i - 1])))) + { + thisplace = i; + break; + } + } + + if (sorted_syms[thisplace]->section != sec) + { + /* We didn't find a good symbol with a smaller value. + Look for one with a larger value. */ + for (i = thisplace + 1; i < sorted_symcount; i++) + { + if (sorted_syms[i]->section == sec) + { + thisplace = i; + break; + } + } + } + + if (sorted_syms[thisplace]->section != sec + && (require_sec + || ((abfd->flags & HAS_RELOC) != 0 + && vma >= bfd_get_section_vma (abfd, sec) + && vma < (bfd_get_section_vma (abfd, sec) + + bfd_section_size (abfd, sec))))) + { + /* There is no suitable symbol. */ + return NULL; + } + } + + if (place != NULL) + *place = thisplace; + + return sorted_syms[thisplace]; +} + +/* Print an address to INFO symbolically. */ + +static void +objdump_print_addr_with_sym (abfd, sec, sym, vma, info, skip_zeroes) + bfd *abfd; + asection *sec; + asymbol *sym; + bfd_vma vma; + struct disassemble_info *info; + boolean skip_zeroes; +{ + objdump_print_value (vma, info, skip_zeroes); + + if (sym == NULL) + { + bfd_vma secaddr; + + (*info->fprintf_func) (info->stream, " <%s", + bfd_get_section_name (abfd, sec)); + secaddr = bfd_get_section_vma (abfd, sec); + if (vma < secaddr) + { + (*info->fprintf_func) (info->stream, "-0x"); + objdump_print_value (secaddr - vma, info, true); + } + else if (vma > secaddr) + { + (*info->fprintf_func) (info->stream, "+0x"); + objdump_print_value (vma - secaddr, info, true); + } + (*info->fprintf_func) (info->stream, ">"); + } + else + { + (*info->fprintf_func) (info->stream, " <"); + objdump_print_symname (abfd, info, sym); + if (bfd_asymbol_value (sym) > vma) + { + (*info->fprintf_func) (info->stream, "-0x"); + objdump_print_value (bfd_asymbol_value (sym) - vma, info, true); + } + else if (vma > bfd_asymbol_value (sym)) + { + (*info->fprintf_func) (info->stream, "+0x"); + objdump_print_value (vma - bfd_asymbol_value (sym), info, true); + } + (*info->fprintf_func) (info->stream, ">"); + } +} + +/* Print VMA to INFO, symbolically if possible. If SKIP_ZEROES is + true, don't output leading zeroes. */ + +static void +objdump_print_addr (vma, info, skip_zeroes) + bfd_vma vma; + struct disassemble_info *info; + boolean skip_zeroes; +{ + struct objdump_disasm_info *aux; + asymbol *sym; + + if (sorted_symcount < 1) + { + (*info->fprintf_func) (info->stream, "0x"); + objdump_print_value (vma, info, skip_zeroes); + return; + } + + aux = (struct objdump_disasm_info *) info->application_data; + sym = find_symbol_for_address (aux->abfd, aux->sec, vma, aux->require_sec, + (long *) NULL); + objdump_print_addr_with_sym (aux->abfd, aux->sec, sym, vma, info, + skip_zeroes); +} + +/* Print VMA to INFO. This function is passed to the disassembler + routine. */ + +static void +objdump_print_address (vma, info) + bfd_vma vma; + struct disassemble_info *info; +{ + objdump_print_addr (vma, info, ! prefix_addresses); +} + +/* Determine of the given address has a symbol associated with it. */ + +static int +objdump_symbol_at_address (vma, info) + bfd_vma vma; + struct disassemble_info * info; +{ + struct objdump_disasm_info * aux; + asymbol * sym; + + /* No symbols - do not bother checking. */ + if (sorted_symcount < 1) + return 0; + + aux = (struct objdump_disasm_info *) info->application_data; + sym = find_symbol_for_address (aux->abfd, aux->sec, vma, aux->require_sec, + (long *) NULL); + + return (sym != NULL && (bfd_asymbol_value (sym) == vma)); +} + +/* Hold the last function name and the last line number we displayed + in a disassembly. */ + +static char *prev_functionname; +static unsigned int prev_line; + +/* We keep a list of all files that we have seen when doing a + dissassembly with source, so that we know how much of the file to + display. This can be important for inlined functions. */ + +struct print_file_list +{ + struct print_file_list *next; + char *filename; + unsigned int line; + FILE *f; +}; + +static struct print_file_list *print_files; + +/* The number of preceding context lines to show when we start + displaying a file for the first time. */ + +#define SHOW_PRECEDING_CONTEXT_LINES (5) + +/* Skip ahead to a given line in a file, optionally printing each + line. */ + +static void +skip_to_line PARAMS ((struct print_file_list *, unsigned int, boolean)); + +static void +skip_to_line (p, line, show) + struct print_file_list *p; + unsigned int line; + boolean show; +{ + while (p->line < line) + { + char buf[100]; + + if (fgets (buf, sizeof buf, p->f) == NULL) + { + fclose (p->f); + p->f = NULL; + break; + } + + if (show) + printf ("%s", buf); + + if (strchr (buf, '\n') != NULL) + ++p->line; + } +} + +/* Show the line number, or the source line, in a dissassembly + listing. */ + +static void +show_line (abfd, section, off) + bfd *abfd; + asection *section; + bfd_vma off; +{ + CONST char *filename; + CONST char *functionname; + unsigned int line; + + if (! with_line_numbers && ! with_source_code) + return; + + if (! bfd_find_nearest_line (abfd, section, syms, off, &filename, + &functionname, &line)) + return; + + if (filename != NULL && *filename == '\0') + filename = NULL; + if (functionname != NULL && *functionname == '\0') + functionname = NULL; + + if (with_line_numbers) + { + if (functionname != NULL + && (prev_functionname == NULL + || strcmp (functionname, prev_functionname) != 0)) + printf ("%s():\n", functionname); + if (line > 0 && line != prev_line) + printf ("%s:%u\n", filename == NULL ? "???" : filename, line); + } + + if (with_source_code + && filename != NULL + && line > 0) + { + struct print_file_list **pp, *p; + + for (pp = &print_files; *pp != NULL; pp = &(*pp)->next) + if (strcmp ((*pp)->filename, filename) == 0) + break; + p = *pp; + + if (p != NULL) + { + if (p != print_files) + { + int l; + + /* We have reencountered a file name which we saw + earlier. This implies that either we are dumping out + code from an included file, or the same file was + linked in more than once. There are two common cases + of an included file: inline functions in a header + file, and a bison or flex skeleton file. In the + former case we want to just start printing (but we + back up a few lines to give context); in the latter + case we want to continue from where we left off. I + can't think of a good way to distinguish the cases, + so I used a heuristic based on the file name. */ + if (strcmp (p->filename + strlen (p->filename) - 2, ".h") != 0) + l = p->line; + else + { + l = line - SHOW_PRECEDING_CONTEXT_LINES; + if (l <= 0) + l = 1; + } + + if (p->f == NULL) + { + p->f = fopen (p->filename, "r"); + p->line = 0; + } + if (p->f != NULL) + skip_to_line (p, l, false); + + if (print_files->f != NULL) + { + fclose (print_files->f); + print_files->f = NULL; + } + } + + if (p->f != NULL) + { + skip_to_line (p, line, true); + *pp = p->next; + p->next = print_files; + print_files = p; + } + } + else + { + FILE *f; + + f = fopen (filename, "r"); + if (f != NULL) + { + int l; + + p = ((struct print_file_list *) + xmalloc (sizeof (struct print_file_list))); + p->filename = xmalloc (strlen (filename) + 1); + strcpy (p->filename, filename); + p->line = 0; + p->f = f; + + if (print_files != NULL && print_files->f != NULL) + { + fclose (print_files->f); + print_files->f = NULL; + } + p->next = print_files; + print_files = p; + + l = line - SHOW_PRECEDING_CONTEXT_LINES; + if (l <= 0) + l = 1; + skip_to_line (p, l, false); + if (p->f != NULL) + skip_to_line (p, line, true); + } + } + } + + if (functionname != NULL + && (prev_functionname == NULL + || strcmp (functionname, prev_functionname) != 0)) + { + if (prev_functionname != NULL) + free (prev_functionname); + prev_functionname = xmalloc (strlen (functionname) + 1); + strcpy (prev_functionname, functionname); + } + + if (line > 0 && line != prev_line) + prev_line = line; +} + +/* Pseudo FILE object for strings. */ +typedef struct +{ + char *buffer; + size_t size; + char *current; +} SFILE; + +/* sprintf to a "stream" */ + +static int +#ifdef ANSI_PROTOTYPES +objdump_sprintf (SFILE *f, const char *format, ...) +#else +objdump_sprintf (va_alist) + va_dcl +#endif +{ +#ifndef ANSI_PROTOTYPES + SFILE *f; + const char *format; +#endif + char *buf; + va_list args; + size_t n; + +#ifdef ANSI_PROTOTYPES + va_start (args, format); +#else + va_start (args); + f = va_arg (args, SFILE *); + format = va_arg (args, const char *); +#endif + + vasprintf (&buf, format, args); + + va_end (args); + + if (buf == NULL) + { + fprintf (stderr, _("Out of virtual memory\n")); + exit (1); + } + + n = strlen (buf); + + while ((f->buffer + f->size) - f->current < n + 1) + { + size_t curroff; + + curroff = f->current - f->buffer; + f->size *= 2; + f->buffer = xrealloc (f->buffer, f->size); + f->current = f->buffer + curroff; + } + + memcpy (f->current, buf, n); + f->current += n; + f->current[0] = '\0'; + + free (buf); + + return n; +} + +/* The number of zeroes we want to see before we start skipping them. + The number is arbitrarily chosen. */ + +#define SKIP_ZEROES (8) + +/* The number of zeroes to skip at the end of a section. If the + number of zeroes at the end is between SKIP_ZEROES_AT_END and + SKIP_ZEROES, they will be disassembled. If there are fewer than + SKIP_ZEROES_AT_END, they will be skipped. This is a heuristic + attempt to avoid disassembling zeroes inserted by section + alignment. */ + +#define SKIP_ZEROES_AT_END (3) + +/* Disassemble some data in memory between given values. */ + +static void +disassemble_bytes (info, disassemble_fn, insns, data, start, stop, relppp, + relppend) + struct disassemble_info *info; + disassembler_ftype disassemble_fn; + boolean insns; + bfd_byte *data; + bfd_vma start; + bfd_vma stop; + arelent ***relppp; + arelent **relppend; +{ + struct objdump_disasm_info *aux; + asection *section; + int bytes_per_line; + boolean done_dot; + int skip_addr_chars; + bfd_vma i; + + aux = (struct objdump_disasm_info *) info->application_data; + section = aux->sec; + + if (insns) + bytes_per_line = 4; + else + bytes_per_line = 16; + + /* Figure out how many characters to skip at the start of an + address, to make the disassembly look nicer. We discard leading + zeroes in chunks of 4, ensuring that there is always a leading + zero remaining. */ + skip_addr_chars = 0; + if (! prefix_addresses) + { + char buf[30]; + char *s; + + sprintf_vma (buf, + section->vma + bfd_section_size (section->owner, section)); + s = buf; + while (s[0] == '0' && s[1] == '0' && s[2] == '0' && s[3] == '0' + && s[4] == '0') + { + skip_addr_chars += 4; + s += 4; + } + } + + info->insn_info_valid = 0; + + done_dot = false; + i = start; + while (i < stop) + { + bfd_vma z; + int bytes = 0; + boolean need_nl = false; + + /* If we see more than SKIP_ZEROES bytes of zeroes, we just + print `...'. */ + for (z = i; z < stop; z++) + if (data[z] != 0) + break; + if (! disassemble_zeroes + && (info->insn_info_valid == 0 + || info->branch_delay_insns == 0) + && (z - i >= SKIP_ZEROES + || (z == stop && z - i < SKIP_ZEROES_AT_END))) + { + printf ("\t...\n"); + + /* If there are more nonzero bytes to follow, we only skip + zeroes in multiples of 4, to try to avoid running over + the start of an instruction which happens to start with + zero. */ + if (z != stop) + z = i + ((z - i) &~ 3); + + bytes = z - i; + } + else + { + char buf[50]; + SFILE sfile; + int bpc = 0; + int pb = 0; + + done_dot = false; + + if (with_line_numbers || with_source_code) + show_line (aux->abfd, section, i); + + if (! prefix_addresses) + { + char *s; + + sprintf_vma (buf, section->vma + i); + for (s = buf + skip_addr_chars; *s == '0'; s++) + *s = ' '; + if (*s == '\0') + *--s = '0'; + printf ("%s:\t", buf + skip_addr_chars); + } + else + { + aux->require_sec = true; + objdump_print_address (section->vma + i, info); + aux->require_sec = false; + putchar (' '); + } + + if (insns) + { + sfile.size = 120; + sfile.buffer = xmalloc (sfile.size); + sfile.current = sfile.buffer; + info->fprintf_func = (fprintf_ftype) objdump_sprintf; + info->stream = (FILE *) &sfile; + info->bytes_per_line = 0; + info->bytes_per_chunk = 0; + + /* FIXME: This is wrong. It tests the number of bytes + in the last instruction, not the current one. */ + if (*relppp < relppend + && (**relppp)->address >= i + && (**relppp)->address < i + bytes) + info->flags = INSN_HAS_RELOC; + else + info->flags = 0; + + bytes = (*disassemble_fn) (section->vma + i, info); + info->fprintf_func = (fprintf_ftype) fprintf; + info->stream = stdout; + if (info->bytes_per_line != 0) + bytes_per_line = info->bytes_per_line; + if (bytes < 0) + break; + } + else + { + long j; + + bytes = bytes_per_line; + if (i + bytes > stop) + bytes = stop - i; + + for (j = i; j < i + bytes; ++j) + { + if (isprint (data[j])) + buf[j - i] = data[j]; + else + buf[j - i] = '.'; + } + buf[j - i] = '\0'; + } + + if (prefix_addresses + ? show_raw_insn > 0 + : show_raw_insn >= 0) + { + long j; + + /* If ! prefix_addresses and ! wide_output, we print + bytes_per_line bytes per line. */ + pb = bytes; + if (pb > bytes_per_line && ! prefix_addresses && ! wide_output) + pb = bytes_per_line; + + if (info->bytes_per_chunk) + bpc = info->bytes_per_chunk; + else + bpc = 1; + + for (j = i; j < i + pb; j += bpc) + { + int k; + if (bpc > 1 && info->display_endian == BFD_ENDIAN_LITTLE) + { + for (k = bpc - 1; k >= 0; k--) + printf ("%02x", (unsigned) data[j + k]); + putchar (' '); + } + else + { + for (k = 0; k < bpc; k++) + printf ("%02x", (unsigned) data[j + k]); + putchar (' '); + } + } + + for (; pb < bytes_per_line; pb += bpc) + { + int k; + + for (k = 0; k < bpc; k++) + printf (" "); + putchar (' '); + } + + /* Separate raw data from instruction by extra space. */ + if (insns) + putchar ('\t'); + else + printf (" "); + } + + if (! insns) + printf ("%s", buf); + else + { + printf ("%s", sfile.buffer); + free (sfile.buffer); + } + + if (prefix_addresses + ? show_raw_insn > 0 + : show_raw_insn >= 0) + { + while (pb < bytes) + { + long j; + char *s; + + putchar ('\n'); + j = i + pb; + + sprintf_vma (buf, section->vma + j); + for (s = buf + skip_addr_chars; *s == '0'; s++) + *s = ' '; + if (*s == '\0') + *--s = '0'; + printf ("%s:\t", buf + skip_addr_chars); + + pb += bytes_per_line; + if (pb > bytes) + pb = bytes; + for (; j < i + pb; j += bpc) + { + int k; + + if (bpc > 1 && info->display_endian == BFD_ENDIAN_LITTLE) + { + for (k = bpc - 1; k >= 0; k--) + printf ("%02x", (unsigned) data[j + k]); + putchar (' '); + } + else + { + for (k = 0; k < bpc; k++) + printf ("%02x", (unsigned) data[j + k]); + putchar (' '); + } + } + } + } + + if (!wide_output) + putchar ('\n'); + else + need_nl = true; + } + + if (dump_reloc_info + && (section->flags & SEC_RELOC) != 0) + { + while ((*relppp) < relppend + && ((**relppp)->address >= (bfd_vma) i + && (**relppp)->address < (bfd_vma) i + bytes)) + { + arelent *q; + + q = **relppp; + + if (wide_output) + putchar ('\t'); + else + printf ("\t\t\t"); + + objdump_print_value (section->vma + q->address, info, true); + + printf (": %s\t", q->howto->name); + + if (q->sym_ptr_ptr == NULL || *q->sym_ptr_ptr == NULL) + printf ("*unknown*"); + else + { + const char *sym_name; + + sym_name = bfd_asymbol_name (*q->sym_ptr_ptr); + if (sym_name != NULL && *sym_name != '\0') + objdump_print_symname (aux->abfd, info, *q->sym_ptr_ptr); + else + { + asection *sym_sec; + + sym_sec = bfd_get_section (*q->sym_ptr_ptr); + sym_name = bfd_get_section_name (aux->abfd, sym_sec); + if (sym_name == NULL || *sym_name == '\0') + sym_name = "*unknown*"; + printf ("%s", sym_name); + } + } + + if (q->addend) + { + printf ("+0x"); + objdump_print_value (q->addend, info, true); + } + + printf ("\n"); + need_nl = false; + ++(*relppp); + } + } + + if (need_nl) + printf ("\n"); + + i += bytes; + } +} + +/* Disassemble the contents of an object file. */ + +static void +disassemble_data (abfd) + bfd *abfd; +{ + long i; + disassembler_ftype disassemble_fn; + struct disassemble_info disasm_info; + struct objdump_disasm_info aux; + asection *section; + + print_files = NULL; + prev_functionname = NULL; + prev_line = -1; + + /* We make a copy of syms to sort. We don't want to sort syms + because that will screw up the relocs. */ + sorted_syms = (asymbol **) xmalloc (symcount * sizeof (asymbol *)); + memcpy (sorted_syms, syms, symcount * sizeof (asymbol *)); + + sorted_symcount = remove_useless_symbols (sorted_syms, symcount); + + /* Sort the symbols into section and symbol order */ + qsort (sorted_syms, sorted_symcount, sizeof (asymbol *), compare_symbols); + + INIT_DISASSEMBLE_INFO(disasm_info, stdout, fprintf); + disasm_info.application_data = (PTR) &aux; + aux.abfd = abfd; + aux.require_sec = false; + disasm_info.print_address_func = objdump_print_address; + disasm_info.symbol_at_address_func = objdump_symbol_at_address; + + if (machine != (char *) NULL) + { + const bfd_arch_info_type *info = bfd_scan_arch (machine); + if (info == NULL) + { + fprintf (stderr, _("%s: Can't use supplied machine %s\n"), + program_name, + machine); + exit (1); + } + abfd->arch_info = info; + } + + if (endian != BFD_ENDIAN_UNKNOWN) + { + struct bfd_target *xvec; + + xvec = (struct bfd_target *) xmalloc (sizeof (struct bfd_target)); + memcpy (xvec, abfd->xvec, sizeof (struct bfd_target)); + xvec->byteorder = endian; + abfd->xvec = xvec; + } + + disassemble_fn = disassembler (abfd); + if (!disassemble_fn) + { + fprintf (stderr, _("%s: Can't disassemble for architecture %s\n"), + program_name, + bfd_printable_arch_mach (bfd_get_arch (abfd), 0)); + return; + } + + disasm_info.flavour = bfd_get_flavour (abfd); + disasm_info.arch = bfd_get_arch (abfd); + disasm_info.mach = bfd_get_mach (abfd); + if (bfd_big_endian (abfd)) + disasm_info.endian = BFD_ENDIAN_BIG; + else if (bfd_little_endian (abfd)) + disasm_info.endian = BFD_ENDIAN_LITTLE; + else + /* ??? Aborting here seems too drastic. We could default to big or little + instead. */ + disasm_info.endian = BFD_ENDIAN_UNKNOWN; + + for (section = abfd->sections; + section != (asection *) NULL; + section = section->next) + { + bfd_byte *data = NULL; + bfd_size_type datasize = 0; + arelent **relbuf = NULL; + arelent **relpp = NULL; + arelent **relppend = NULL; + long stop; + asymbol *sym = NULL; + long place = 0; + + if ((section->flags & SEC_LOAD) == 0 + || (! disassemble_all + && only == NULL + && (section->flags & SEC_CODE) == 0)) + continue; + if (only != (char *) NULL && strcmp (only, section->name) != 0) + continue; + + if (dump_reloc_info + && (section->flags & SEC_RELOC) != 0) + { + long relsize; + + relsize = bfd_get_reloc_upper_bound (abfd, section); + if (relsize < 0) + bfd_fatal (bfd_get_filename (abfd)); + + if (relsize > 0) + { + long relcount; + + relbuf = (arelent **) xmalloc (relsize); + relcount = bfd_canonicalize_reloc (abfd, section, relbuf, syms); + if (relcount < 0) + bfd_fatal (bfd_get_filename (abfd)); + + /* Sort the relocs by address. */ + qsort (relbuf, relcount, sizeof (arelent *), compare_relocs); + + relpp = relbuf; + relppend = relpp + relcount; + + /* Skip over the relocs belonging to addresses below the + start address. */ + if (start_address != (bfd_vma) -1) + { + while (relpp < relppend + && (*relpp)->address < start_address) + ++relpp; + } + } + } + + printf (_("Disassembly of section %s:\n"), section->name); + + datasize = bfd_get_section_size_before_reloc (section); + if (datasize == 0) + continue; + + data = (bfd_byte *) xmalloc ((size_t) datasize); + + bfd_get_section_contents (abfd, section, data, 0, datasize); + + aux.sec = section; + disasm_info.buffer = data; + disasm_info.buffer_vma = section->vma; + disasm_info.buffer_length = datasize; + if (start_address == (bfd_vma) -1 + || start_address < disasm_info.buffer_vma) + i = 0; + else + i = start_address - disasm_info.buffer_vma; + if (stop_address == (bfd_vma) -1) + stop = datasize; + else + { + if (stop_address < disasm_info.buffer_vma) + stop = 0; + else + stop = stop_address - disasm_info.buffer_vma; + if (stop > disasm_info.buffer_length) + stop = disasm_info.buffer_length; + } + + sym = find_symbol_for_address (abfd, section, section->vma + i, + true, &place); + + while (i < stop) + { + asymbol *nextsym; + long nextstop; + boolean insns; + + if (sym != NULL && bfd_asymbol_value (sym) <= section->vma + i) + { + int x; + + for (x = place; + (x < sorted_symcount + && bfd_asymbol_value (sorted_syms[x]) <= section->vma + i); + ++x) + continue; + disasm_info.symbols = & sorted_syms[place]; + disasm_info.num_symbols = x - place; + } + else + disasm_info.symbols = NULL; + + if (! prefix_addresses) + { + printf ("\n"); + objdump_print_addr_with_sym (abfd, section, sym, + section->vma + i, + &disasm_info, + false); + printf (":\n"); + } + + if (sym != NULL && bfd_asymbol_value (sym) > section->vma + i) + nextsym = sym; + else if (sym == NULL) + nextsym = NULL; + else + { + while (place < sorted_symcount + /* ??? Why the test for != section? */ + && (sorted_syms[place]->section != section + || (bfd_asymbol_value (sorted_syms[place]) + <= bfd_asymbol_value (sym)))) + ++place; + if (place >= sorted_symcount) + nextsym = NULL; + else + nextsym = sorted_syms[place]; + } + + if (sym != NULL && bfd_asymbol_value (sym) > section->vma + i) + { + nextstop = bfd_asymbol_value (sym) - section->vma; + if (nextstop > stop) + nextstop = stop; + } + else if (nextsym == NULL) + nextstop = stop; + else + { + nextstop = bfd_asymbol_value (nextsym) - section->vma; + if (nextstop > stop) + nextstop = stop; + } + + /* If a symbol is explicitly marked as being an object + rather than a function, just dump the bytes without + disassembling them. */ + if (disassemble_all + || sym == NULL + || bfd_asymbol_value (sym) > section->vma + i + || ((sym->flags & BSF_OBJECT) == 0 + && (strstr (bfd_asymbol_name (sym), "gnu_compiled") + == NULL) + && (strstr (bfd_asymbol_name (sym), "gcc2_compiled") + == NULL)) + || (sym->flags & BSF_FUNCTION) != 0) + insns = true; + else + insns = false; + + disassemble_bytes (&disasm_info, disassemble_fn, insns, data, i, + nextstop, &relpp, relppend); + + i = nextstop; + sym = nextsym; + } + + free (data); + if (relbuf != NULL) + free (relbuf); + } + free (sorted_syms); +} + + +/* Define a table of stab values and print-strings. We wish the initializer + could be a direct-mapped table, but instead we build one the first + time we need it. */ + +static void dump_section_stabs PARAMS ((bfd *abfd, char *stabsect_name, + char *strsect_name)); + +/* Dump the stabs sections from an object file that has a section that + uses Sun stabs encoding. */ + +static void +dump_stabs (abfd) + bfd *abfd; +{ + dump_section_stabs (abfd, ".stab", ".stabstr"); + dump_section_stabs (abfd, ".stab.excl", ".stab.exclstr"); + dump_section_stabs (abfd, ".stab.index", ".stab.indexstr"); + dump_section_stabs (abfd, "$GDB_SYMBOLS$", "$GDB_STRINGS$"); +} + +static bfd_byte *stabs; +static bfd_size_type stab_size; + +static char *strtab; +static bfd_size_type stabstr_size; + +/* Read ABFD's stabs section STABSECT_NAME into `stabs' + and string table section STRSECT_NAME into `strtab'. + If the section exists and was read, allocate the space and return true. + Otherwise return false. */ + +static boolean +read_section_stabs (abfd, stabsect_name, strsect_name) + bfd *abfd; + const char *stabsect_name; + const char *strsect_name; +{ + asection *stabsect, *stabstrsect; + + stabsect = bfd_get_section_by_name (abfd, stabsect_name); + if (0 == stabsect) + { + printf (_("No %s section present\n\n"), stabsect_name); + return false; + } + + stabstrsect = bfd_get_section_by_name (abfd, strsect_name); + if (0 == stabstrsect) + { + fprintf (stderr, _("%s: %s has no %s section\n"), program_name, + bfd_get_filename (abfd), strsect_name); + return false; + } + + stab_size = bfd_section_size (abfd, stabsect); + stabstr_size = bfd_section_size (abfd, stabstrsect); + + stabs = (bfd_byte *) xmalloc (stab_size); + strtab = (char *) xmalloc (stabstr_size); + + if (! bfd_get_section_contents (abfd, stabsect, (PTR) stabs, 0, stab_size)) + { + fprintf (stderr, _("%s: Reading %s section of %s failed: %s\n"), + program_name, stabsect_name, bfd_get_filename (abfd), + bfd_errmsg (bfd_get_error ())); + free (stabs); + free (strtab); + return false; + } + + if (! bfd_get_section_contents (abfd, stabstrsect, (PTR) strtab, 0, + stabstr_size)) + { + fprintf (stderr, _("%s: Reading %s section of %s failed: %s\n"), + program_name, strsect_name, bfd_get_filename (abfd), + bfd_errmsg (bfd_get_error ())); + free (stabs); + free (strtab); + return false; + } + + return true; +} + +/* Stabs entries use a 12 byte format: + 4 byte string table index + 1 byte stab type + 1 byte stab other field + 2 byte stab desc field + 4 byte stab value + FIXME: This will have to change for a 64 bit object format. */ + +#define STRDXOFF (0) +#define TYPEOFF (4) +#define OTHEROFF (5) +#define DESCOFF (6) +#define VALOFF (8) +#define STABSIZE (12) + +/* Print ABFD's stabs section STABSECT_NAME (in `stabs'), + using string table section STRSECT_NAME (in `strtab'). */ + +static void +print_section_stabs (abfd, stabsect_name, strsect_name) + bfd *abfd; + const char *stabsect_name; + const char *strsect_name; +{ + int i; + unsigned file_string_table_offset = 0, next_file_string_table_offset = 0; + bfd_byte *stabp, *stabs_end; + + stabp = stabs; + stabs_end = stabp + stab_size; + + printf (_("Contents of %s section:\n\n"), stabsect_name); + printf ("Symnum n_type n_othr n_desc n_value n_strx String\n"); + + /* Loop through all symbols and print them. + + We start the index at -1 because there is a dummy symbol on + the front of stabs-in-{coff,elf} sections that supplies sizes. */ + + for (i = -1; stabp < stabs_end; stabp += STABSIZE, i++) + { + const char *name; + unsigned long strx; + unsigned char type, other; + unsigned short desc; + bfd_vma value; + + strx = bfd_h_get_32 (abfd, stabp + STRDXOFF); + type = bfd_h_get_8 (abfd, stabp + TYPEOFF); + other = bfd_h_get_8 (abfd, stabp + OTHEROFF); + desc = bfd_h_get_16 (abfd, stabp + DESCOFF); + value = bfd_h_get_32 (abfd, stabp + VALOFF); + + printf ("\n%-6d ", i); + /* Either print the stab name, or, if unnamed, print its number + again (makes consistent formatting for tools like awk). */ + name = bfd_get_stab_name (type); + if (name != NULL) + printf ("%-6s", name); + else if (type == N_UNDF) + printf ("HdrSym"); + else + printf ("%-6d", type); + printf (" %-6d %-6d ", other, desc); + printf_vma (value); + printf (" %-6lu", strx); + + /* Symbols with type == 0 (N_UNDF) specify the length of the + string table associated with this file. We use that info + to know how to relocate the *next* file's string table indices. */ + + if (type == N_UNDF) + { + file_string_table_offset = next_file_string_table_offset; + next_file_string_table_offset += value; + } + else + { + /* Using the (possibly updated) string table offset, print the + string (if any) associated with this symbol. */ + + if ((strx + file_string_table_offset) < stabstr_size) + printf (" %s", &strtab[strx + file_string_table_offset]); + else + printf (" *"); + } + } + printf ("\n\n"); +} + +static void +dump_section_stabs (abfd, stabsect_name, strsect_name) + bfd *abfd; + char *stabsect_name; + char *strsect_name; +{ + asection *s; + + /* Check for section names for which stabsect_name is a prefix, to + handle .stab0, etc. */ + for (s = abfd->sections; + s != NULL; + s = s->next) + { + int len; + + len = strlen (stabsect_name); + + /* If the prefix matches, and the files section name ends with a + nul or a digit, then we match. I.e., we want either an exact + match or a section followed by a number. */ + if (strncmp (stabsect_name, s->name, len) == 0 + && (s->name[len] == '\000' + || isdigit ((unsigned char) s->name[len]))) + { + if (read_section_stabs (abfd, s->name, strsect_name)) + { + print_section_stabs (abfd, s->name, strsect_name); + free (stabs); + free (strtab); + } + } + } +} + +static void +dump_bfd_header (abfd) + bfd *abfd; +{ + char *comma = ""; + + printf (_("architecture: %s, "), + bfd_printable_arch_mach (bfd_get_arch (abfd), + bfd_get_mach (abfd))); + printf (_("flags 0x%08x:\n"), abfd->flags); + +#define PF(x, y) if (abfd->flags & x) {printf("%s%s", comma, y); comma=", ";} + PF (HAS_RELOC, "HAS_RELOC"); + PF (EXEC_P, "EXEC_P"); + PF (HAS_LINENO, "HAS_LINENO"); + PF (HAS_DEBUG, "HAS_DEBUG"); + PF (HAS_SYMS, "HAS_SYMS"); + PF (HAS_LOCALS, "HAS_LOCALS"); + PF (DYNAMIC, "DYNAMIC"); + PF (WP_TEXT, "WP_TEXT"); + PF (D_PAGED, "D_PAGED"); + PF (BFD_IS_RELAXABLE, "BFD_IS_RELAXABLE"); + printf (_("\nstart address 0x")); + printf_vma (abfd->start_address); + printf ("\n"); +} + +static void +dump_bfd_private_header (abfd) +bfd *abfd; +{ + bfd_print_private_bfd_data (abfd, stdout); +} + +static void +display_bfd (abfd) + bfd *abfd; +{ + char **matching; + + if (!bfd_check_format_matches (abfd, bfd_object, &matching)) + { + bfd_nonfatal (bfd_get_filename (abfd)); + if (bfd_get_error () == bfd_error_file_ambiguously_recognized) + { + list_matching_formats (matching); + free (matching); + } + return; + } + + /* If we are adjusting section VMA's, change them all now. Changing + the BFD information is a hack. However, we must do it, or + bfd_find_nearest_line will not do the right thing. */ + if (adjust_section_vma != 0) + { + asection *s; + + for (s = abfd->sections; s != NULL; s = s->next) + { + s->vma += adjust_section_vma; + s->lma += adjust_section_vma; + } + } + + printf (_("\n%s: file format %s\n"), bfd_get_filename (abfd), + abfd->xvec->name); + if (dump_ar_hdrs) + print_arelt_descr (stdout, abfd, true); + if (dump_file_header) + dump_bfd_header (abfd); + if (dump_private_headers) + dump_bfd_private_header (abfd); + putchar ('\n'); + if (dump_section_headers) + dump_headers (abfd); + if (dump_symtab || dump_reloc_info || disassemble || dump_debugging) + { + syms = slurp_symtab (abfd); + } + if (dump_dynamic_symtab || dump_dynamic_reloc_info) + { + dynsyms = slurp_dynamic_symtab (abfd); + } + if (dump_symtab) + dump_symbols (abfd, false); + if (dump_dynamic_symtab) + dump_symbols (abfd, true); + if (dump_stab_section_info) + dump_stabs (abfd); + if (dump_reloc_info && ! disassemble) + dump_relocs (abfd); + if (dump_dynamic_reloc_info) + dump_dynamic_relocs (abfd); + if (dump_section_contents) + dump_data (abfd); + if (disassemble) + disassemble_data (abfd); + if (dump_debugging) + { + PTR dhandle; + + dhandle = read_debugging_info (abfd, syms, symcount); + if (dhandle != NULL) + { + if (! print_debugging_info (stdout, dhandle)) + fprintf (stderr, _("%s: printing debugging information failed\n"), + bfd_get_filename (abfd)); + } + } + if (syms) + { + free (syms); + syms = NULL; + } + if (dynsyms) + { + free (dynsyms); + dynsyms = NULL; + } +} + +static void +display_file (filename, target) + char *filename; + char *target; +{ + bfd *file, *arfile = (bfd *) NULL; + + file = bfd_openr (filename, target); + if (file == NULL) + { + bfd_nonfatal (filename); + return; + } + + if (bfd_check_format (file, bfd_archive) == true) + { + bfd *last_arfile = NULL; + + printf (_("In archive %s:\n"), bfd_get_filename (file)); + for (;;) + { + bfd_set_error (bfd_error_no_error); + + arfile = bfd_openr_next_archived_file (file, arfile); + if (arfile == NULL) + { + if (bfd_get_error () != bfd_error_no_more_archived_files) + { + bfd_nonfatal (bfd_get_filename (file)); + } + break; + } + + display_bfd (arfile); + + if (last_arfile != NULL) + bfd_close (last_arfile); + last_arfile = arfile; + } + + if (last_arfile != NULL) + bfd_close (last_arfile); + } + else + display_bfd (file); + + bfd_close (file); +} + +/* Actually display the various requested regions */ + +static void +dump_data (abfd) + bfd *abfd; +{ + asection *section; + bfd_byte *data = 0; + bfd_size_type datasize = 0; + bfd_size_type i; + bfd_size_type start, stop; + + for (section = abfd->sections; section != NULL; section = + section->next) + { + int onaline = 16; + + if (only == (char *) NULL || + strcmp (only, section->name) == 0) + { + if (section->flags & SEC_HAS_CONTENTS) + { + printf (_("Contents of section %s:\n"), section->name); + + if (bfd_section_size (abfd, section) == 0) + continue; + data = (bfd_byte *) xmalloc ((size_t) bfd_section_size (abfd, section)); + datasize = bfd_section_size (abfd, section); + + + bfd_get_section_contents (abfd, section, (PTR) data, 0, bfd_section_size (abfd, section)); + + if (start_address == (bfd_vma) -1 + || start_address < section->vma) + start = 0; + else + start = start_address - section->vma; + if (stop_address == (bfd_vma) -1) + stop = bfd_section_size (abfd, section); + else + { + if (stop_address < section->vma) + stop = 0; + else + stop = stop_address - section->vma; + if (stop > bfd_section_size (abfd, section)) + stop = bfd_section_size (abfd, section); + } + for (i = start; i < stop; i += onaline) + { + bfd_size_type j; + + printf (" %04lx ", (unsigned long int) (i + section->vma)); + for (j = i; j < i + onaline; j++) + { + if (j < stop) + printf ("%02x", (unsigned) (data[j])); + else + printf (" "); + if ((j & 3) == 3) + printf (" "); + } + + printf (" "); + for (j = i; j < i + onaline; j++) + { + if (j >= stop) + printf (" "); + else + printf ("%c", isprint (data[j]) ? data[j] : '.'); + } + putchar ('\n'); + } + free (data); + } + } + } +} + +/* Should perhaps share code and display with nm? */ +static void +dump_symbols (abfd, dynamic) + bfd *abfd; + boolean dynamic; +{ + asymbol **current; + long max; + long count; + + if (dynamic) + { + current = dynsyms; + max = dynsymcount; + if (max == 0) + return; + printf ("DYNAMIC SYMBOL TABLE:\n"); + } + else + { + current = syms; + max = symcount; + if (max == 0) + return; + printf ("SYMBOL TABLE:\n"); + } + + for (count = 0; count < max; count++) + { + if (*current) + { + bfd *cur_bfd = bfd_asymbol_bfd (*current); + + if (cur_bfd != NULL) + { + const char *name; + char *alloc; + + name = bfd_asymbol_name (*current); + alloc = NULL; + if (do_demangle && name != NULL && *name != '\0') + { + const char *n; + + /* If we want to demangle the name, we demangle it + here, and temporarily clobber it while calling + bfd_print_symbol. FIXME: This is a gross hack. */ + + n = name; + if (bfd_get_symbol_leading_char (cur_bfd) == *n) + ++n; + alloc = cplus_demangle (n, DMGL_ANSI | DMGL_PARAMS); + if (alloc != NULL) + (*current)->name = alloc; + else + (*current)->name = n; + } + + bfd_print_symbol (cur_bfd, stdout, *current, + bfd_print_symbol_all); + + (*current)->name = name; + if (alloc != NULL) + free (alloc); + + printf ("\n"); + } + } + current++; + } + printf ("\n"); + printf ("\n"); +} + +static void +dump_relocs (abfd) + bfd *abfd; +{ + arelent **relpp; + long relcount; + asection *a; + + for (a = abfd->sections; a != (asection *) NULL; a = a->next) + { + long relsize; + + if (bfd_is_abs_section (a)) + continue; + if (bfd_is_und_section (a)) + continue; + if (bfd_is_com_section (a)) + continue; + + if (only) + { + if (strcmp (only, a->name)) + continue; + } + else if ((a->flags & SEC_RELOC) == 0) + continue; + + relsize = bfd_get_reloc_upper_bound (abfd, a); + if (relsize < 0) + bfd_fatal (bfd_get_filename (abfd)); + + printf ("RELOCATION RECORDS FOR [%s]:", a->name); + + if (relsize == 0) + { + printf (" (none)\n\n"); + } + else + { + relpp = (arelent **) xmalloc (relsize); + relcount = bfd_canonicalize_reloc (abfd, a, relpp, syms); + if (relcount < 0) + bfd_fatal (bfd_get_filename (abfd)); + else if (relcount == 0) + { + printf (" (none)\n\n"); + } + else + { + printf ("\n"); + dump_reloc_set (abfd, a, relpp, relcount); + printf ("\n\n"); + } + free (relpp); + } + } +} + +static void +dump_dynamic_relocs (abfd) + bfd *abfd; +{ + long relsize; + arelent **relpp; + long relcount; + + relsize = bfd_get_dynamic_reloc_upper_bound (abfd); + if (relsize < 0) + bfd_fatal (bfd_get_filename (abfd)); + + printf ("DYNAMIC RELOCATION RECORDS"); + + if (relsize == 0) + { + printf (" (none)\n\n"); + } + else + { + relpp = (arelent **) xmalloc (relsize); + relcount = bfd_canonicalize_dynamic_reloc (abfd, relpp, dynsyms); + if (relcount < 0) + bfd_fatal (bfd_get_filename (abfd)); + else if (relcount == 0) + { + printf (" (none)\n\n"); + } + else + { + printf ("\n"); + dump_reloc_set (abfd, (asection *) NULL, relpp, relcount); + printf ("\n\n"); + } + free (relpp); + } +} + +static void +dump_reloc_set (abfd, sec, relpp, relcount) + bfd *abfd; + asection *sec; + arelent **relpp; + long relcount; +{ + arelent **p; + char *last_filename, *last_functionname; + unsigned int last_line; + + /* Get column headers lined up reasonably. */ + { + static int width; + if (width == 0) + { + char buf[30]; + sprintf_vma (buf, (bfd_vma) -1); + width = strlen (buf) - 7; + } + printf ("OFFSET %*s TYPE %*s VALUE \n", width, "", 12, ""); + } + + last_filename = NULL; + last_functionname = NULL; + last_line = 0; + + for (p = relpp; relcount && *p != (arelent *) NULL; p++, relcount--) + { + arelent *q = *p; + const char *filename, *functionname; + unsigned int line; + const char *sym_name; + const char *section_name; + + if (start_address != (bfd_vma) -1 + && q->address < start_address) + continue; + if (stop_address != (bfd_vma) -1 + && q->address > stop_address) + continue; + + if (with_line_numbers + && sec != NULL + && bfd_find_nearest_line (abfd, sec, syms, q->address, + &filename, &functionname, &line)) + { + if (functionname != NULL + && (last_functionname == NULL + || strcmp (functionname, last_functionname) != 0)) + { + printf ("%s():\n", functionname); + if (last_functionname != NULL) + free (last_functionname); + last_functionname = xstrdup (functionname); + } + if (line > 0 + && (line != last_line + || (filename != NULL + && last_filename != NULL + && strcmp (filename, last_filename) != 0))) + { + printf ("%s:%u\n", filename == NULL ? "???" : filename, line); + last_line = line; + if (last_filename != NULL) + free (last_filename); + if (filename == NULL) + last_filename = NULL; + else + last_filename = xstrdup (filename); + } + } + + if (q->sym_ptr_ptr && *q->sym_ptr_ptr) + { + sym_name = (*(q->sym_ptr_ptr))->name; + section_name = (*(q->sym_ptr_ptr))->section->name; + } + else + { + sym_name = NULL; + section_name = NULL; + } + if (sym_name) + { + printf_vma (q->address); + printf (" %-16s ", q->howto->name); + objdump_print_symname (abfd, (struct disassemble_info *) NULL, + *q->sym_ptr_ptr); + } + else + { + if (section_name == (CONST char *) NULL) + section_name = "*unknown*"; + printf_vma (q->address); + printf (" %-16s [%s]", + q->howto->name, + section_name); + } + if (q->addend) + { + printf ("+0x"); + printf_vma (q->addend); + } + printf ("\n"); + } +} + +/* The length of the longest architecture name + 1. */ +#define LONGEST_ARCH sizeof("rs6000:6000") + +static const char * +endian_string (endian) + enum bfd_endian endian; +{ + if (endian == BFD_ENDIAN_BIG) + return "big endian"; + else if (endian == BFD_ENDIAN_LITTLE) + return "little endian"; + else + return "endianness unknown"; +} + +/* List the targets that BFD is configured to support, each followed + by its endianness and the architectures it supports. */ + +static void +display_target_list () +{ + extern bfd_target *bfd_target_vector[]; + char *dummy_name; + int t; + + dummy_name = choose_temp_base (); + for (t = 0; bfd_target_vector[t]; t++) + { + bfd_target *p = bfd_target_vector[t]; + bfd *abfd = bfd_openw (dummy_name, p->name); + int a; + + printf ("%s\n (header %s, data %s)\n", p->name, + endian_string (p->header_byteorder), + endian_string (p->byteorder)); + + if (abfd == NULL) + { + bfd_nonfatal (dummy_name); + continue; + } + + if (! bfd_set_format (abfd, bfd_object)) + { + if (bfd_get_error () != bfd_error_invalid_operation) + bfd_nonfatal (p->name); + continue; + } + + for (a = (int) bfd_arch_obscure + 1; a < (int) bfd_arch_last; a++) + if (bfd_set_arch_mach (abfd, (enum bfd_architecture) a, 0)) + printf (" %s\n", + bfd_printable_arch_mach ((enum bfd_architecture) a, 0)); + } + unlink (dummy_name); + free (dummy_name); +} + +/* Print a table showing which architectures are supported for entries + FIRST through LAST-1 of bfd_target_vector (targets across, + architectures down). */ + +static void +display_info_table (first, last) + int first; + int last; +{ + extern bfd_target *bfd_target_vector[]; + int t, a; + char *dummy_name; + + /* Print heading of target names. */ + printf ("\n%*s", (int) LONGEST_ARCH, " "); + for (t = first; t < last && bfd_target_vector[t]; t++) + printf ("%s ", bfd_target_vector[t]->name); + putchar ('\n'); + + dummy_name = choose_temp_base (); + for (a = (int) bfd_arch_obscure + 1; a < (int) bfd_arch_last; a++) + if (strcmp (bfd_printable_arch_mach (a, 0), "UNKNOWN!") != 0) + { + printf ("%*s ", (int) LONGEST_ARCH - 1, + bfd_printable_arch_mach (a, 0)); + for (t = first; t < last && bfd_target_vector[t]; t++) + { + bfd_target *p = bfd_target_vector[t]; + boolean ok = true; + bfd *abfd = bfd_openw (dummy_name, p->name); + + if (abfd == NULL) + { + bfd_nonfatal (p->name); + ok = false; + } + + if (ok) + { + if (! bfd_set_format (abfd, bfd_object)) + { + if (bfd_get_error () != bfd_error_invalid_operation) + bfd_nonfatal (p->name); + ok = false; + } + } + + if (ok) + { + if (! bfd_set_arch_mach (abfd, a, 0)) + ok = false; + } + + if (ok) + printf ("%s ", p->name); + else + { + int l = strlen (p->name); + while (l--) + putchar ('-'); + putchar (' '); + } + } + putchar ('\n'); + } + unlink (dummy_name); + free (dummy_name); +} + +/* Print tables of all the target-architecture combinations that + BFD has been configured to support. */ + +static void +display_target_tables () +{ + int t, columns; + extern bfd_target *bfd_target_vector[]; + char *colum; + + columns = 0; + colum = getenv ("COLUMNS"); + if (colum != NULL) + columns = atoi (colum); + if (columns == 0) + columns = 80; + + t = 0; + while (bfd_target_vector[t] != NULL) + { + int oldt = t, wid; + + wid = LONGEST_ARCH + strlen (bfd_target_vector[t]->name) + 1; + ++t; + while (wid < columns && bfd_target_vector[t] != NULL) + { + int newwid; + + newwid = wid + strlen (bfd_target_vector[t]->name) + 1; + if (newwid >= columns) + break; + wid = newwid; + ++t; + } + display_info_table (oldt, t); + } +} + +static void +display_info () +{ + printf (_("BFD header file version %s\n"), BFD_VERSION); + display_target_list (); + display_target_tables (); +} + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + char *target = default_target; + boolean seenflag = false; + +#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) + setlocale (LC_MESSAGES, ""); +#endif + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + + program_name = *argv; + xmalloc_set_program_name (program_name); + + START_PROGRESS (program_name, 0); + + bfd_init (); + set_default_bfd_target (); + + while ((c = getopt_long (argc, argv, "pib:m:VCdDlfahrRtTxsSj:wE:", + long_options, (int *) 0)) + != EOF) + { + if (c != 'l' && c != OPTION_START_ADDRESS && c != OPTION_STOP_ADDRESS) + seenflag = true; + switch (c) + { + case 0: + break; /* we've been given a long option */ + case 'm': + machine = optarg; + break; + case 'j': + only = optarg; + break; + case 'l': + with_line_numbers = 1; + break; + case 'b': + target = optarg; + break; + case 'f': + dump_file_header = true; + break; + case 'i': + formats_info = true; + break; + case 'p': + dump_private_headers = 1; + break; + case 'x': + dump_private_headers = 1; + dump_symtab = 1; + dump_reloc_info = 1; + dump_file_header = true; + dump_ar_hdrs = 1; + dump_section_headers = 1; + break; + case 't': + dump_symtab = 1; + break; + case 'T': + dump_dynamic_symtab = 1; + break; + case 'C': + do_demangle = 1; + break; + case 'd': + disassemble = true; + break; + case 'D': + disassemble = disassemble_all = true; + break; + case 'S': + disassemble = true; + with_source_code = true; + break; + case 's': + dump_section_contents = 1; + break; + case 'r': + dump_reloc_info = 1; + break; + case 'R': + dump_dynamic_reloc_info = 1; + break; + case 'a': + dump_ar_hdrs = 1; + break; + case 'h': + dump_section_headers = 1; + break; + case 'H': + usage (stdout, 0); + case 'V': + show_version = 1; + break; + case 'w': + wide_output = 1; + break; + case OPTION_ADJUST_VMA: + adjust_section_vma = parse_vma (optarg, "--adjust-vma"); + break; + case OPTION_START_ADDRESS: + start_address = parse_vma (optarg, "--start-address"); + break; + case OPTION_STOP_ADDRESS: + stop_address = parse_vma (optarg, "--stop-address"); + break; + case 'E': + if (strcmp (optarg, "B") == 0) + endian = BFD_ENDIAN_BIG; + else if (strcmp (optarg, "L") == 0) + endian = BFD_ENDIAN_LITTLE; + else + { + fprintf (stderr, _("%s: unrecognized -E option\n"), program_name); + usage (stderr, 1); + } + break; + case OPTION_ENDIAN: + if (strncmp (optarg, "big", strlen (optarg)) == 0) + endian = BFD_ENDIAN_BIG; + else if (strncmp (optarg, "little", strlen (optarg)) == 0) + endian = BFD_ENDIAN_LITTLE; + else + { + fprintf (stderr, _("%s: unrecognized --endian type `%s'\n"), + program_name, optarg); + usage (stderr, 1); + } + break; + default: + usage (stderr, 1); + } + } + + if (show_version) + print_version ("objdump"); + + if (seenflag == false) + usage (stderr, 1); + + if (formats_info) + { + display_info (); + } + else + { + if (optind == argc) + display_file ("a.out", target); + else + for (; optind < argc;) + display_file (argv[optind++], target); + } + + END_PROGRESS (program_name); + + return 0; +} diff --git a/binutils/po/Make-in b/binutils/po/Make-in new file mode 100644 index 0000000..0552db1 --- /dev/null +++ b/binutils/po/Make-in @@ -0,0 +1,251 @@ +# Makefile for program source directory in GNU NLS utilities package. +# Copyright (C) 1995, 1996, 1997 by Ulrich Drepper <drepper@gnu.ai.mit.edu> +# +# This file file be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ + +SHELL = /bin/sh +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +datadir = $(prefix)/@DATADIRNAME@ +localedir = $(datadir)/locale +gnulocaledir = $(prefix)/share/locale +gettextsrcdir = $(prefix)/share/gettext/po +subdir = po + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +MKINSTALLDIRS = @MKINSTALLDIRS@ + +CC = @CC@ +GENCAT = @GENCAT@ +GMSGFMT = PATH=../src:$$PATH @GMSGFMT@ +MSGFMT = @MSGFMT@ +XGETTEXT = PATH=../src:$$PATH @XGETTEXT@ +MSGMERGE = PATH=../src:$$PATH msgmerge + +DEFS = @DEFS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ + +INCLUDES = -I.. -I$(top_srcdir)/intl + +COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS) + +SOURCES = cat-id-tbl.c +POFILES = @POFILES@ +GMOFILES = @GMOFILES@ +DISTFILES = ChangeLog Makefile.in.in POTFILES.in $(PACKAGE).pot \ +stamp-cat-id $(POFILES) $(GMOFILES) $(SOURCES) + +POTFILES = \ + +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +INSTOBJEXT = @INSTOBJEXT@ + +.SUFFIXES: +.SUFFIXES: .c .o .po .pox .gmo .mo .msg .cat + +.c.o: + $(COMPILE) $< + +.po.pox: + $(MAKE) $(PACKAGE).pot + $(MSGMERGE) $< $(srcdir)/$(PACKAGE).pot -o $*.pox + +.po.mo: + $(MSGFMT) -o $@ $< + +.po.gmo: + file=$(srcdir)/`echo $* | sed 's,.*/,,'`.gmo \ + && rm -f $$file && $(GMSGFMT) -o $$file $< + +.po.cat: + sed -f ../intl/po2msg.sed < $< > $*.msg \ + && rm -f $@ && $(GENCAT) $@ $*.msg + + +all: all-@USE_NLS@ + +all-yes: $(CATALOGS) @MAINT@ $(PACKAGE).pot +all-no: + +$(srcdir)/$(PACKAGE).pot: $(POTFILES) + $(XGETTEXT) --default-domain=$(PACKAGE) --directory=$(top_srcdir) \ + --add-comments --keyword=_ --keyword=N_ \ + --files-from=$(srcdir)/POTFILES.in + rm -f $(srcdir)/$(PACKAGE).pot + mv $(PACKAGE).po $(srcdir)/$(PACKAGE).pot + +$(srcdir)/cat-id-tbl.c: stamp-cat-id; @: +$(srcdir)/stamp-cat-id: $(PACKAGE).pot + rm -f cat-id-tbl.tmp + sed -f ../intl/po2tbl.sed $(srcdir)/$(PACKAGE).pot \ + | sed -e "s/@PACKAGE NAME@/$(PACKAGE)/" > cat-id-tbl.tmp + if cmp -s cat-id-tbl.tmp $(srcdir)/cat-id-tbl.c; then \ + rm cat-id-tbl.tmp; \ + else \ + echo cat-id-tbl.c changed; \ + rm -f $(srcdir)/cat-id-tbl.c; \ + mv cat-id-tbl.tmp $(srcdir)/cat-id-tbl.c; \ + fi + cd $(srcdir) && rm -f stamp-cat-id && echo timestamp > stamp-cat-id + + +install: install-exec install-data +install-exec: +install-info: +install-data: install-data-@USE_NLS@ +install-data-no: all +install-data-yes: all + if test -r $(MKINSTALLDIRS); then \ + $(MKINSTALLDIRS) $(datadir); \ + else \ + $(top_srcdir)/mkinstalldirs $(datadir); \ + fi + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + case "$$cat" in \ + *.gmo) destdir=$(gnulocaledir);; \ + *) destdir=$(localedir);; \ + esac; \ + lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \ + dir=$$destdir/$$lang/LC_MESSAGES; \ + if test -r $(MKINSTALLDIRS); then \ + $(MKINSTALLDIRS) $$dir; \ + else \ + $(top_srcdir)/mkinstalldirs $$dir; \ + fi; \ + if test -r $$cat; then \ + $(INSTALL_DATA) $$cat $$dir/$(PACKAGE)$(INSTOBJEXT); \ + echo "installing $$cat as $$dir/$(PACKAGE)$(INSTOBJEXT)"; \ + else \ + $(INSTALL_DATA) $(srcdir)/$$cat $$dir/$(PACKAGE)$(INSTOBJEXT); \ + echo "installing $(srcdir)/$$cat as" \ + "$$dir/$(PACKAGE)$(INSTOBJEXT)"; \ + fi; \ + if test -r $$cat.m; then \ + $(INSTALL_DATA) $$cat.m $$dir/$(PACKAGE)$(INSTOBJEXT).m; \ + echo "installing $$cat.m as $$dir/$(PACKAGE)$(INSTOBJEXT).m"; \ + else \ + if test -r $(srcdir)/$$cat.m ; then \ + $(INSTALL_DATA) $(srcdir)/$$cat.m \ + $$dir/$(PACKAGE)$(INSTOBJEXT).m; \ + echo "installing $(srcdir)/$$cat as" \ + "$$dir/$(PACKAGE)$(INSTOBJEXT).m"; \ + else \ + true; \ + fi; \ + fi; \ + done + if test "$(PACKAGE)" = "gettext"; then \ + if test -r $(MKINSTALLDIRS); then \ + $(MKINSTALLDIRS) $(gettextsrcdir); \ + else \ + $(top_srcdir)/mkinstalldirs $(gettextsrcdir); \ + fi; \ + $(INSTALL_DATA) $(srcdir)/Makefile.in.in \ + $(gettextsrcdir)/Makefile.in.in; \ + else \ + : ; \ + fi + +# Define this as empty until I found a useful application. +installcheck: + +uninstall: + catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \ + rm -f $(localedir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT); \ + rm -f $(localedir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT).m; \ + rm -f $(gnulocaledir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT); \ + rm -f $(gnulocaledir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT).m; \ + done + rm -f $(gettextsrcdir)/po-Makefile.in.in + +check: all + +cat-id-tbl.o: ../intl/libgettext.h + +dvi info tags TAGS ID: + +mostlyclean: + rm -f core core.* *.pox $(PACKAGE).po *.old.po cat-id-tbl.tmp + rm -fr *.o + +clean: mostlyclean + +distclean: clean + rm -f Makefile Makefile.in POTFILES *.mo *.msg *.cat *.cat.m + +maintainer-clean: distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + rm -f $(GMOFILES) + +distdir = ../$(PACKAGE)-$(VERSION)/$(subdir) +dist distdir: update-po $(DISTFILES) + dists="$(DISTFILES)"; \ + for file in $$dists; do \ + ln $(srcdir)/$$file $(distdir) 2> /dev/null \ + || cp -p $(srcdir)/$$file $(distdir); \ + done + +update-po: Makefile + $(MAKE) $(PACKAGE).pot + PATH=`pwd`/../src:$$PATH; \ + cd $(srcdir); \ + catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \ + mv $$lang.po $$lang.old.po; \ + echo "$$lang:"; \ + if $(MSGMERGE) $$lang.old.po $(PACKAGE).pot -o $$lang.po; then \ + rm -f $$lang.old.po; \ + else \ + echo "msgmerge for $$cat failed!"; \ + rm -f $$lang.po; \ + mv $$lang.old.po $$lang.po; \ + fi; \ + done + +POTFILES: POTFILES.in + ( if test 'x$(srcdir)' != 'x.'; then \ + posrcprefix='$(top_srcdir)/'; \ + else \ + posrcprefix="../"; \ + fi; \ + rm -f $@-t $@ \ + && (sed -e '/^#/d' -e '/^[ ]*$$/d' \ + -e "s@.*@ $$posrcprefix& \\\\@" < $(srcdir)/$@.in \ + | sed -e '$$s/\\$$//') > $@-t \ + && chmod a-w $@-t \ + && mv $@-t $@ ) + +POTFILES.in: @MAINT@ ../Makefile + cd .. && $(MAKE) po/POTFILES.in + +Makefile: Make-in ../config.status POTFILES + cd .. \ + && CONFIG_FILES=$(subdir)/Makefile.in:$(subdir)/Make-in \ + CONFIG_HEADERS= $(SHELL) ./config.status + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/binutils/po/POTFILES.in b/binutils/po/POTFILES.in new file mode 100644 index 0000000..47f3860 --- /dev/null +++ b/binutils/po/POTFILES.in @@ -0,0 +1,52 @@ +readelf.c +addr2line.c +ar.c +arsup.c +arsup.h +bucomm.c +bucomm.h +budbg.h +coffdump.c +coffgrok.c +coffgrok.h +debug.c +debug.h +dlltool.c +dlltool.h +dllwrap.c +dyn-string.c +dyn-string.h +filemode.c +ieee.c +is-ranlib.c +is-strip.c +maybe-ranlib.c +maybe-strip.c +nlmconv.c +nlmconv.h +nm.c +not-ranlib.c +not-strip.c +objcopy.c +objdump.c +prdbg.c +rdcoff.c +rddbg.c +rename.c +resbin.c +rescoff.c +resrc.c +resres.c +size.c +srconv.c +stabs.c +strings.c +sysdump.c +version.c +windres.c +windres.h +winduni.c +winduni.h +wrstabs.c +testsuite/binutils-all/readelf.h +testsuite/binutils-all/testprog.c diff --git a/binutils/po/binutils.pot b/binutils/po/binutils.pot new file mode 100644 index 0000000..beeb383 --- /dev/null +++ b/binutils/po/binutils.pot @@ -0,0 +1,3443 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Free Software Foundation, Inc. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 1999-04-26 10:11-0600\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: ENCODING\n" + +#: addr2line.c:76 +#, c-format +msgid "" +"Usage: %s [-CfsHV] [-b bfdname] [--target=bfdname]\n" +" [-e executable] [--exe=executable] [--demangle]\n" +" [--basenames] [--functions] [addr addr ...]\n" +msgstr "" + +#: addr2line.c:83 ar.c:255 nlmconv.c:1141 nm.c:304 objcopy.c:318 objcopy.c:337 +#: objdump.c:236 readelf.c:1133 size.c:89 strings.c:512 windres.c:723 +msgid "Report bugs to bug-gnu-utils@gnu.org\n" +msgstr "" + +#: addr2line.c:243 +#, c-format +msgid "%s: can not get addresses from archive" +msgstr "" + +#: ar.c:207 +#, c-format +msgid "no entry %s in archive\n" +msgstr "" + +#: ar.c:224 +#, c-format +msgid "" +"Usage: %s [-]{dmpqrstx}[abcilosSuvV] [member-name] archive-file file...\n" +msgstr "" + +#: ar.c:226 +#, c-format +msgid " %s -M [<mri-script]\n" +msgstr "" + +#: ar.c:227 +msgid " commands:\n" +msgstr "" + +#: ar.c:228 +msgid " d - delete file(s) from the archive\n" +msgstr "" + +#: ar.c:229 +msgid " m[ab] - move file(s) in the archive\n" +msgstr "" + +#: ar.c:230 +msgid " p - print file(s) found in the archive\n" +msgstr "" + +#: ar.c:231 +msgid " q[f] - quick append file(s) to the archive\n" +msgstr "" + +#: ar.c:232 +msgid "" +" r[ab][f][u] - replace existing or insert new file(s) into the archive\n" +msgstr "" + +#: ar.c:233 +msgid " t - display contents of archive\n" +msgstr "" + +#: ar.c:234 +msgid " x[o] - extract file(s) from the archive\n" +msgstr "" + +#: ar.c:235 +msgid " command specific modifiers:\n" +msgstr "" + +#: ar.c:236 +msgid " [a] - put file(s) after [member-name]\n" +msgstr "" + +#: ar.c:237 +msgid " [b] - put file(s) before [member-name] (same as [i])\n" +msgstr "" + +#: ar.c:238 +msgid " [f] - truncate inserted file names\n" +msgstr "" + +#: ar.c:239 +msgid " [o] - preserve original dates\n" +msgstr "" + +#: ar.c:240 +msgid "" +" [u] - only replace files that are newer than current archive " +"contents\n" +msgstr "" + +#: ar.c:241 +msgid " generic modifiers:\n" +msgstr "" + +#: ar.c:242 +msgid " [c] - do not warn if the library had to be created\n" +msgstr "" + +#: ar.c:243 +msgid " [s] - create an archive index (cf. ranlib)\n" +msgstr "" + +#: ar.c:244 +msgid " [S] - do not build a symbol table\n" +msgstr "" + +#: ar.c:245 +msgid " [v] - be verbose\n" +msgstr "" + +#: ar.c:246 +msgid " [V] - display the version number\n" +msgstr "" + +#: ar.c:250 +#, c-format +msgid "Usage: %s [-vV] archive\n" +msgstr "" + +#: ar.c:431 +msgid "two different operation options specified" +msgstr "" + +#: ar.c:500 +#, c-format +msgid "%s: illegal option -- %c\n" +msgstr "" + +#: ar.c:532 +msgid "no operation specified" +msgstr "" + +#: ar.c:535 +msgid "`u' is only meaningful with the `r' option." +msgstr "" + +#: ar.c:615 +#, c-format +msgid "%s: internal error -- this option not implemented\n" +msgstr "" + +#: ar.c:730 ar.c:782 ar.c:1212 +#, c-format +msgid "internal stat error on %s" +msgstr "" + +#: ar.c:734 +#, c-format +msgid "" +"\n" +"<member %s>\n" +"\n" +msgstr "" + +#: ar.c:751 ar.c:819 +#, c-format +msgid "%s is not a valid archive" +msgstr "" + +#: ar.c:787 +#, c-format +msgid "stat returns negative size for %s" +msgstr "" + +#: ar.c:908 +#, c-format +msgid "%s is not an archive" +msgstr "" + +#: ar.c:915 +#, c-format +msgid "%s: creating %s\n" +msgstr "" + +#: ar.c:1110 +#, c-format +msgid "No member named `%s'\n" +msgstr "" + +#: ar.c:1162 +#, c-format +msgid "%s: no entry %s in archive %s!\n" +msgstr "" + +#: ar.c:1322 +#, c-format +msgid "%s: no archive map to update" +msgstr "" + +#: arsup.c:86 +#, c-format +msgid "No entry %s in archive.\n" +msgstr "" + +#: arsup.c:118 +#, c-format +msgid "Can't open file %s\n" +msgstr "" + +#: arsup.c:166 +#, c-format +msgid "%s: Can't open output archive %s\n" +msgstr "" + +#: arsup.c:178 +#, c-format +msgid "%s: Can't open input archive %s\n" +msgstr "" + +#: arsup.c:184 +#, c-format +msgid "%s: file %s is not an archive\n" +msgstr "" + +#: arsup.c:225 +#, c-format +msgid "%s: no output archive specified yet\n" +msgstr "" + +#: arsup.c:245 arsup.c:280 arsup.c:316 arsup.c:336 arsup.c:394 +#, c-format +msgid "%s: no open output archive\n" +msgstr "" + +#: arsup.c:253 arsup.c:354 arsup.c:374 +#, c-format +msgid "%s: can't open file %s\n" +msgstr "" + +#: arsup.c:301 arsup.c:370 arsup.c:449 +#, c-format +msgid "%s: can't find module file %s\n" +msgstr "" + +#: arsup.c:401 +#, c-format +msgid "Current open archive is %s\n" +msgstr "" + +#: arsup.c:428 +#, c-format +msgid "%s: no open archive\n" +msgstr "" + +#: bucomm.c:139 +#, c-format +msgid "can't set BFD default target to `%s': %s" +msgstr "" + +#: bucomm.c:151 +#, c-format +msgid "%s: Matching formats:" +msgstr "" + +#: bucomm.c:168 +msgid "Supported targets:" +msgstr "" + +#: bucomm.c:170 +#, c-format +msgid "%s: supported targets:" +msgstr "" + +#: bucomm.c:263 +#, c-format +msgid "%s: bad number: %s" +msgstr "" + +#: coffdump.c:94 +#, c-format +msgid "#lines %d " +msgstr "" + +#: coffdump.c:456 sysdump.c:719 +#, c-format +msgid "%s: Print a human readable interpretation of a SYSROFF object file\n" +msgstr "" + +#: coffdump.c:498 srconv.c:1940 sysdump.c:755 +#, c-format +msgid "GNU %s version %s\n" +msgstr "" + +#: coffdump.c:516 srconv.c:1977 sysdump.c:775 +#, c-format +msgid "%s: no input file specified\n" +msgstr "" + +#: debug.c:653 +msgid "debug_add_to_current_namespace: no current file" +msgstr "" + +#: debug.c:736 +msgid "debug_start_source: no debug_set_filename call" +msgstr "" + +#: debug.c:795 +msgid "debug_record_function: no debug_set_filename call" +msgstr "" + +#: debug.c:851 +msgid "debug_record_parameter: no current function" +msgstr "" + +#: debug.c:885 +msgid "debug_end_function: no current function" +msgstr "" + +#: debug.c:891 +msgid "debug_end_function: some blocks were not closed" +msgstr "" + +#: debug.c:921 +msgid "debug_start_block: no current block" +msgstr "" + +#: debug.c:959 +msgid "debug_end_block: no current block" +msgstr "" + +#: debug.c:966 +msgid "debug_end_block: attempt to close top level block" +msgstr "" + +#: debug.c:992 +msgid "debug_record_line: no current unit" +msgstr "" + +#. FIXME +#: debug.c:1046 +msgid "debug_start_common_block: not implemented" +msgstr "" + +#. FIXME +#: debug.c:1058 +msgid "debug_end_common_block: not implemented" +msgstr "" + +#. FIXME. +#: debug.c:1152 +msgid "debug_record_label not implemented" +msgstr "" + +#: debug.c:1178 +msgid "debug_record_variable: no current file" +msgstr "" + +#: debug.c:1194 +msgid "debug_record_variable: no current block" +msgstr "" + +#: debug.c:1764 +msgid "debug_make_undefined_type: unsupported kind" +msgstr "" + +#: debug.c:1970 +msgid "debug_name_type: no current file" +msgstr "" + +#: debug.c:2018 +msgid "debug_tag_type: no current file" +msgstr "" + +#: debug.c:2026 +msgid "debug_tag_type: extra tag attempted" +msgstr "" + +#: debug.c:2066 +#, c-format +msgid "Warning: changing type size from %d to %d\n" +msgstr "" + +#: debug.c:2090 +msgid "debug_find_named_type: no current compilation unit" +msgstr "" + +#: debug.c:2197 +#, c-format +msgid "debug_get_real_type: circular debug information for %s\n" +msgstr "" + +#: debug.c:2663 +msgid "debug_write_type: illegal type encountered" +msgstr "" + +#: dlltool.c:627 dlltool.c:646 dlltool.c:666 +#, c-format +msgid "Internal error: Unknown machine type: %d\n" +msgstr "" + +#: dlltool.c:700 +#, c-format +msgid "Can't open def file: %s" +msgstr "" + +#: dlltool.c:705 +#, c-format +msgid "Processing def file: %s" +msgstr "" + +#: dlltool.c:709 +msgid "Processed def file" +msgstr "" + +#: dlltool.c:734 +#, c-format +msgid "Syntax error in def file %s:%d\n" +msgstr "" + +#: dlltool.c:767 +#, c-format +msgid "NAME: %s base: %x" +msgstr "" + +#: dlltool.c:770 +msgid "Can't have LIBRARY and NAME\n" +msgstr "" + +#: dlltool.c:786 +#, c-format +msgid "LIBRARY: %s base: %x" +msgstr "" + +#: dlltool.c:789 +#, c-format +msgid "%s: Can't have LIBRARY and NAME\n" +msgstr "" + +#: dlltool.c:1044 +#, c-format +msgid "wait: %s" +msgstr "" + +#: dlltool.c:1049 +#, c-format +msgid "subprocess got fatal signal %d" +msgstr "" + +#: dlltool.c:1055 +#, c-format +msgid "%s exited with status %d\n" +msgstr "" + +#: dlltool.c:1087 +#, c-format +msgid "Sucking in info from .drective section in %s\n" +msgstr "" + +#: dlltool.c:1197 +#, c-format +msgid "Excluding symbol: %s\n" +msgstr "" + +#: dlltool.c:1292 dlltool.c:1303 nm.c:902 nm.c:913 objdump.c:379 objdump.c:396 +#, c-format +msgid "%s: no symbols\n" +msgstr "" + +#. FIXME: we ought to read in and block out the base relocations +#: dlltool.c:1330 +#, c-format +msgid "%s: Done reading %s\n" +msgstr "" + +#: dlltool.c:1341 +#, c-format +msgid "Unable to open object file: %s" +msgstr "" + +#: dlltool.c:1344 +#, c-format +msgid "Scanning object file %s" +msgstr "" + +#: dlltool.c:1434 +msgid "Adding exports to output file" +msgstr "" + +#: dlltool.c:1479 +msgid "Added exports to output file" +msgstr "" + +#: dlltool.c:1587 +#, c-format +msgid "Generating export file: %s\n" +msgstr "" + +#: dlltool.c:1592 +#, c-format +msgid "Unable to open temporary assembler file: %s" +msgstr "" + +#: dlltool.c:1595 +#, c-format +msgid "Opened temporary file: %s" +msgstr "" + +#: dlltool.c:1828 +msgid "Generated exports file" +msgstr "" + +#: dlltool.c:2081 +#, c-format +msgid "bfd_open failed open stub file: %s" +msgstr "" + +#: dlltool.c:2084 +#, c-format +msgid "Creating stub file: %s" +msgstr "" + +#: dlltool.c:2593 +#, c-format +msgid "Can't open .lib file: %s" +msgstr "" + +#: dlltool.c:2596 +#, c-format +msgid "Creating library file: %s\n" +msgstr "" + +#: dlltool.c:2652 +#, c-format +msgid "cannot delete %s: %s\n" +msgstr "" + +#: dlltool.c:2656 +msgid "Created lib file" +msgstr "" + +#: dlltool.c:2757 +#, c-format +msgid "Warning, ignoring duplicate EXPORT %s %d,%d\n" +msgstr "" + +#: dlltool.c:2763 +#, c-format +msgid "Error, duplicate EXPORT with oridinals: %s" +msgstr "" + +#: dlltool.c:2890 +msgid "Processing definitions" +msgstr "" + +#: dlltool.c:2928 +msgid "Processed definitions" +msgstr "" + +#. xgetext:c-format +#: dlltool.c:2939 +#, c-format +msgid "Usage %s <options> <object-files>\n" +msgstr "" + +#. xgetext:c-format +#: dlltool.c:2941 +#, c-format +msgid "" +" -m --machine <machine> Create {arm, i386, ppc, thumb} DLL. [default: " +"%s]\n" +msgstr "" + +#: dlltool.c:2942 +msgid " -e --output-exp <outname> Generate an export file.\n" +msgstr "" + +#: dlltool.c:2943 +msgid " -l --output-lib <outname> Generate an interface library.\n" +msgstr "" + +#: dlltool.c:2944 +msgid " -a --add-indirect Add dll indirects to export file.\n" +msgstr "" + +#: dlltool.c:2945 +msgid "" +" -D --dllname <name> Name of input dll to put into interface lib.\n" +msgstr "" + +#: dlltool.c:2946 +msgid " -d --input-def <deffile> Name of .def file to be read in.\n" +msgstr "" + +#: dlltool.c:2947 +msgid " -z --output-def <deffile> Name of .def file to be created.\n" +msgstr "" + +#: dlltool.c:2948 +msgid " --export-all-symbols Export all symbols to .def\n" +msgstr "" + +#: dlltool.c:2949 +msgid " --no-export-all-symbols Only export listed symbols\n" +msgstr "" + +#: dlltool.c:2950 +msgid " --exclude-symbols <list> Don't export <list>\n" +msgstr "" + +#: dlltool.c:2951 +msgid " --no-default-excludes Clear default exclude symbols\n" +msgstr "" + +#: dlltool.c:2952 +msgid " -b --base-file <basefile> Read linker generated base file.\n" +msgstr "" + +#: dlltool.c:2953 +msgid " -x --no-idata4 Don't generate idata$4 section.\n" +msgstr "" + +#: dlltool.c:2954 +msgid " -c --no-idata5 Don't generate idata$5 section.\n" +msgstr "" + +#: dlltool.c:2955 +msgid "" +" -U --add-underscore Add underscores to symbols in interface " +"library.\n" +msgstr "" + +#: dlltool.c:2956 +msgid " -k --kill-at Kill @<n> from exported names.\n" +msgstr "" + +#: dlltool.c:2957 +msgid " -A --add-stdcall-alias Add aliases without @<n>.\n" +msgstr "" + +#: dlltool.c:2958 +msgid " -S --as <name> Use <name> for assembler.\n" +msgstr "" + +#: dlltool.c:2959 +msgid " -f --as-flags <flags> Pass <flags> to the assembler.\n" +msgstr "" + +#: dlltool.c:2961 +msgid " -i --interwork Support ARM/Thumb interworking.\n" +msgstr "" + +#: dlltool.c:2963 +msgid "" +" -n --no-delete Keep temp files (repeat for extra " +"preservation).\n" +msgstr "" + +#: dlltool.c:2964 +msgid " -v --verbose Be verbose.\n" +msgstr "" + +#: dlltool.c:2965 +msgid " -V --version Display the program version.\n" +msgstr "" + +#: dlltool.c:2966 +msgid " -h --help Display this information.\n" +msgstr "" + +#: dlltool.c:3120 +#, c-format +msgid "Unable to open base-file: %s" +msgstr "" + +#: dlltool.c:3137 +#, c-format +msgid "Machine '%s' not supported" +msgstr "" + +#: ieee.c:316 +msgid "unexpected end of debugging information" +msgstr "" + +#: ieee.c:411 +msgid "invalid number" +msgstr "" + +#: ieee.c:470 +msgid "invalid string length" +msgstr "" + +#: ieee.c:527 ieee.c:568 +msgid "expression stack overflow" +msgstr "" + +#: ieee.c:547 +msgid "unsupported IEEE expression operator" +msgstr "" + +#: ieee.c:562 +msgid "unknown section" +msgstr "" + +#: ieee.c:583 +msgid "expression stack underflow" +msgstr "" + +#: ieee.c:597 +msgid "expression stack mismatch" +msgstr "" + +#: ieee.c:636 +msgid "unknown builtin type" +msgstr "" + +#: ieee.c:781 +msgid "BCD float type not supported" +msgstr "" + +#: ieee.c:927 +msgid "unexpected number" +msgstr "" + +#: ieee.c:934 +msgid "unexpected record type" +msgstr "" + +#: ieee.c:967 +msgid "blocks left on stack at end" +msgstr "" + +#: ieee.c:1232 +msgid "unknown BB type" +msgstr "" + +#: ieee.c:1241 +msgid "stack overflow" +msgstr "" + +#: ieee.c:1266 +msgid "stack underflow" +msgstr "" + +#: ieee.c:1380 ieee.c:1452 ieee.c:2151 +msgid "illegal variable index" +msgstr "" + +#: ieee.c:1430 +msgid "illegal type index" +msgstr "" + +#: ieee.c:1440 ieee.c:1477 +msgid "unknown TY code" +msgstr "" + +#: ieee.c:1459 +msgid "undefined variable in TY" +msgstr "" + +#. Pascal file name. FIXME. +#: ieee.c:1870 +msgid "Pascal file name not supported" +msgstr "" + +#: ieee.c:1918 +msgid "unsupported qualifer" +msgstr "" + +#: ieee.c:2189 +msgid "undefined variable in ATN" +msgstr "" + +#: ieee.c:2232 +msgid "unknown ATN type" +msgstr "" + +#. Reserved for FORTRAN common. +#: ieee.c:2354 +msgid "unsupported ATN11" +msgstr "" + +#. We have no way to record this information. FIXME. +#: ieee.c:2381 +msgid "unsupported ATN12" +msgstr "" + +#: ieee.c:2441 +msgid "unexpected string in C++ misc" +msgstr "" + +#: ieee.c:2454 +msgid "bad misc record" +msgstr "" + +#: ieee.c:2497 +msgid "unrecognized C++ misc record" +msgstr "" + +#: ieee.c:2614 +msgid "undefined C++ object" +msgstr "" + +#: ieee.c:2648 +msgid "unrecognized C++ object spec" +msgstr "" + +#: ieee.c:2684 +msgid "unsupported C++ object type" +msgstr "" + +#: ieee.c:2694 +msgid "C++ base class not defined" +msgstr "" + +#: ieee.c:2706 ieee.c:2811 +msgid "C++ object has no fields" +msgstr "" + +#: ieee.c:2725 +msgid "C++ base class not found in container" +msgstr "" + +#: ieee.c:2832 +msgid "C++ data member not found in container" +msgstr "" + +#: ieee.c:2873 ieee.c:3023 +msgid "unknown C++ visibility" +msgstr "" + +#: ieee.c:2907 +msgid "bad C++ field bit pos or size" +msgstr "" + +#: ieee.c:2999 +msgid "bad type for C++ method function" +msgstr "" + +#: ieee.c:3009 +msgid "no type information for C++ method function" +msgstr "" + +#: ieee.c:3048 +msgid "C++ static virtual method" +msgstr "" + +#: ieee.c:3143 +msgid "unrecognized C++ object overhead spec" +msgstr "" + +#: ieee.c:3182 +msgid "undefined C++ vtable" +msgstr "" + +#: ieee.c:3253 +msgid "C++ default values not in a function" +msgstr "" + +#: ieee.c:3293 +msgid "unrecognized C++ default type" +msgstr "" + +#: ieee.c:3324 +msgid "reference parameter is not a pointer" +msgstr "" + +#: ieee.c:3409 +msgid "unrecognized C++ reference type" +msgstr "" + +#: ieee.c:3491 +msgid "C++ reference not found" +msgstr "" + +#: ieee.c:3499 +msgid "C++ reference is not pointer" +msgstr "" + +#: ieee.c:3528 ieee.c:3536 +msgid "missing required ASN" +msgstr "" + +#: ieee.c:3566 ieee.c:3574 +msgid "missing required ATN65" +msgstr "" + +#: ieee.c:3588 +msgid "bad ATN65 record" +msgstr "" + +#: ieee.c:4235 +msgid "IEEE numeric overflow: 0x" +msgstr "" + +#: ieee.c:4281 +#, c-format +msgid "IEEE string length overflow: %u\n" +msgstr "" + +#: ieee.c:5315 +#, c-format +msgid "IEEE unsupported integer type size %u\n" +msgstr "" + +#: ieee.c:5351 +#, c-format +msgid "IEEE unsupported float type size %u\n" +msgstr "" + +#: ieee.c:5387 +#, c-format +msgid "IEEE unsupported complex type size %u\n" +msgstr "" + +#: nlmconv.c:275 srconv.c:1966 +#, c-format +msgid "%s: input and output files must be different\n" +msgstr "" + +#: nlmconv.c:325 +#, c-format +msgid "%s: input file named both on command line and with INPUT\n" +msgstr "" + +#: nlmconv.c:336 +#, c-format +msgid "%s: no input file\n" +msgstr "" + +#: nlmconv.c:366 +#, c-format +msgid "%s: no name for output file\n" +msgstr "" + +#: nlmconv.c:381 +#, c-format +msgid "%s: warning:input and output formats are not compatible\n" +msgstr "" + +#: nlmconv.c:411 +msgid "make .bss section" +msgstr "" + +#: nlmconv.c:420 +msgid "make .nlmsections section" +msgstr "" + +#: nlmconv.c:422 +msgid "set .nlmsections flags" +msgstr "" + +#: nlmconv.c:450 +msgid "set .bss vma" +msgstr "" + +#: nlmconv.c:457 +msgid "set .data size" +msgstr "" + +#: nlmconv.c:638 +#, c-format +msgid "%s: warning: symbol %s imported but not in import list\n" +msgstr "" + +#: nlmconv.c:658 +msgid "set start address" +msgstr "" + +#: nlmconv.c:707 +#, c-format +msgid "%s: warning: START procedure %s not defined\n" +msgstr "" + +#: nlmconv.c:710 +#, c-format +msgid "%s: warning: EXIT procedure %s not defined\n" +msgstr "" + +#: nlmconv.c:714 +#, c-format +msgid "%s: warning: CHECK procedure %s not defined\n" +msgstr "" + +#: nlmconv.c:736 nlmconv.c:928 +msgid "custom section" +msgstr "" + +#: nlmconv.c:757 nlmconv.c:960 +msgid "help section" +msgstr "" + +#: nlmconv.c:779 nlmconv.c:979 +msgid "message section" +msgstr "" + +#: nlmconv.c:795 nlmconv.c:1012 +msgid "module section" +msgstr "" + +#: nlmconv.c:815 nlmconv.c:1029 +msgid "rpc section" +msgstr "" + +#: nlmconv.c:852 +#, c-format +msgid "%s:%s: warning: shared libraries can not have uninitialized data\n" +msgstr "" + +#: nlmconv.c:873 nlmconv.c:1049 +msgid "shared section" +msgstr "" + +#: nlmconv.c:881 +#, c-format +msgid "%s: warning: No version number given\n" +msgstr "" + +#: nlmconv.c:922 nlmconv.c:954 nlmconv.c:973 nlmconv.c:1023 nlmconv.c:1043 +#, c-format +msgid "%s:%s: read: %s\n" +msgstr "" + +#: nlmconv.c:946 +#, c-format +msgid "%s: warning: MAP and FULLMAP are not supported; try ld -M\n" +msgstr "" + +#: nlmconv.c:1121 +#, c-format +msgid "%s: Convert an object file into a NetWare Loadable Module\n" +msgstr "" + +#: nlmconv.c:1133 +#, c-format +msgid "" +"Usage: %s [-dhV] [-I bfdname] [-O bfdname] [-T header-file] [-l linker]\n" +" [--input-target=bfdname] [--output-target=bfdname]\n" +" [--header-file=file] [--linker=linker] [--debug]\n" +" [--help] [--version]\n" +" [in-file [out-file]]\n" +msgstr "" + +#: nlmconv.c:1173 +#, c-format +msgid "%s: support not compiled in for %s\n" +msgstr "" + +#: nlmconv.c:1216 +msgid "make section" +msgstr "" + +#: nlmconv.c:1230 +msgid "set section size" +msgstr "" + +#: nlmconv.c:1236 +msgid "set section alignment" +msgstr "" + +#: nlmconv.c:1240 +msgid "set section flags" +msgstr "" + +#: nlmconv.c:1251 +msgid "set .nlmsections size" +msgstr "" + +#: nlmconv.c:1339 nlmconv.c:1347 nlmconv.c:1356 nlmconv.c:1361 +msgid "set .nlmsection contents" +msgstr "" + +#: nlmconv.c:1864 +msgid "stub section sizes" +msgstr "" + +#: nlmconv.c:1913 +msgid "writing stub" +msgstr "" + +#: nlmconv.c:2003 +#, c-format +msgid "%s: unresolved PC relative reloc against %s\n" +msgstr "" + +#: nlmconv.c:2068 +#, c-format +msgid "%s: overflow when adjusting relocation against %s\n" +msgstr "" + +#: nlmconv.c:2191 +#, c-format +msgid "%s: execution of %s failed: " +msgstr "" + +#: nlmconv.c:2206 +#, c-format +msgid "%s: Execution of %s failed\n" +msgstr "" + +#: nm.c:292 +#, c-format +msgid "" +"Usage: %s [-aABCDglnopPrsuvV] [-t radix] [--radix=radix] [--target=bfdname]\n" +" [--debug-syms] [--extern-only] [--print-armap] [--print-file-name]\n" +" [--numeric-sort] [--no-sort] [--reverse-sort] [--size-sort]\n" +" [--undefined-only] [--portability] [-f {bsd,sysv,posix}]\n" +" [--format={bsd,sysv,posix}] [--demangle] [--no-demangle] [--dynamic]\n" +" [--defined-only] [--line-numbers]\n" +" [--version] [--help]\n" +" [file...]\n" +msgstr "" + +#: nm.c:337 +#, c-format +msgid "%s: %s: invalid radix\n" +msgstr "" + +#: nm.c:363 +#, c-format +msgid "%s: %s: invalid output format\n" +msgstr "" + +#: nm.c:490 +#, c-format +msgid "%s: data size %ld\n" +msgstr "" + +#: nm.c:1281 +#, c-format +msgid "" +"\n" +"\n" +"Undefined symbols from %s:\n" +"\n" +msgstr "" + +#: nm.c:1283 +#, c-format +msgid "" +"\n" +"\n" +"Symbols from %s:\n" +"\n" +msgstr "" + +#: nm.c:1284 nm.c:1338 +msgid "" +"Name Value Class Type Size Line " +"Section\n" +"\n" +msgstr "" + +#: nm.c:1335 +#, c-format +msgid "" +"\n" +"\n" +"Undefined symbols from %s[%s]:\n" +"\n" +msgstr "" + +#: nm.c:1337 +#, c-format +msgid "" +"\n" +"\n" +"Symbols from %s[%s]:\n" +"\n" +msgstr "" + +#: nm.c:1508 +msgid "" +"\n" +"Archive index:\n" +msgstr "" + +#: objcopy.c:293 +#, c-format +msgid "" +"Usage: %s [-vVSpgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-b byte]\n" +" [-R section] [-i interleave] [--interleave=interleave] [--byte=byte]\n" +" [--input-target=bfdname] [--output-target=bfdname] " +"[--target=bfdname]\n" +" [--strip-all] [--strip-debug] [--strip-unneeded] [--discard-all]\n" +" [--discard-locals] [--debugging] [--remove-section=section]\n" +msgstr "" + +#: objcopy.c:300 +msgid "" +" [--gap-fill=val] [--pad-to=address] [--preserve-dates]\n" +" [--set-start=val] \n" +" [--change-start=incr] [--change-addresses=incr] \n" +" (--adjust-start and --adjust-vma are aliases for these two) \n" +" [--change-section-address=section{=,+,-}val]\n" +" (--adjust-section-vma is an alias for --change-section-address)\n" +" [--change-section-lma=section{=,+,-}val]\n" +" [--change-section-vma=section{=,+,-}val]\n" +" [--adjust-warnings] [--no-adjust-warnings]\n" +" [--change-warnings] [--no-change-warnings]\n" +" [--set-section-flags=section=flags] " +"[--add-section=sectionname=filename]\n" +" [--keep-symbol symbol] [-K symbol] [--strip-symbol symbol] [-N " +"symbol]\n" +" [--localize-symbol symbol] [-L symbol] [--weaken-symbol symbol]\n" +" [-W symbol] [--change-leading-char] [--remove-leading-char] " +"[--weaken]\n" +" [--verbose] [--version] [--help] in-file [out-file]\n" +msgstr "" + +#: objcopy.c:327 +#, c-format +msgid "" +"Usage: %s [-vVsSpgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-R section]\n" +" [--input-target=bfdname] [--output-target=bfdname] " +"[--target=bfdname]\n" +" [--strip-all] [--strip-debug] [--strip-unneeded] [--discard-all]\n" +" [--discard-locals] [--keep-symbol symbol] [-K symbol]\n" +" [--strip-symbol symbol] [-N symbol] [--remove-section=section]\n" +" [-o file] [--preserve-dates] [--verbose] [--version] [--help] " +"file...\n" +msgstr "" + +#: objcopy.c:383 +#, c-format +msgid "unrecognized section flag `%s'" +msgstr "" + +#: objcopy.c:384 +msgid "supported flags: alloc, load, readonly, code, data, rom, contents" +msgstr "" + +#: objcopy.c:623 +#, c-format +msgid "copy from %s(%s) to %s(%s)\n" +msgstr "" + +#: objcopy.c:642 +#, c-format +msgid "Warning: Output file cannot represent architecture %s" +msgstr "" + +#: objcopy.c:669 +#, c-format +msgid "can't create section `%s': %s" +msgstr "" + +#: objcopy.c:755 +#, c-format +msgid "Can't fill gap after %s: %s" +msgstr "" + +#: objcopy.c:780 +#, c-format +msgid "Can't add padding to %s: %s" +msgstr "" + +#: objcopy.c:916 +#, c-format +msgid "%s: error copying private BFD data: %s" +msgstr "" + +#: objcopy.c:950 +#, c-format +msgid "cannot mkdir %s for archive copying (error: %s)" +msgstr "" + +#: objcopy.c:1204 +#, c-format +msgid "%s: section `%s': error in %s: %s" +msgstr "" + +#: objcopy.c:1476 +#, c-format +msgid "%s: can't create debugging section: %s" +msgstr "" + +#: objcopy.c:1491 +#, c-format +msgid "%s: can't set debugging section contents: %s" +msgstr "" + +#: objcopy.c:1500 +#, c-format +msgid "%s: don't know how to write debugging information for %s" +msgstr "" + +#: objcopy.c:1605 +#, c-format +msgid "%s: cannot stat: %s" +msgstr "" + +#: objcopy.c:1655 +msgid "byte number must be non-negative" +msgstr "" + +#: objcopy.c:1660 +msgid "interleave must be positive" +msgstr "" + +#: objcopy.c:1729 +msgid "bad format for --add-section NAME=FILENAME" +msgstr "" + +#: objcopy.c:1732 +#, c-format +msgid "cannot stat: %s: %s" +msgstr "" + +#: objcopy.c:1750 +#, c-format +msgid "cannot open: %s: %s" +msgstr "" + +#: objcopy.c:1754 +#, c-format +msgid "%s: fread failed" +msgstr "" + +#: objcopy.c:1791 +#, c-format +msgid "bad format for %s" +msgstr "" + +#: objcopy.c:1855 +#, c-format +msgid "Warning: truncating gap-fill from 0x%s to 0x%x" +msgstr "" + +#: objcopy.c:1879 +msgid "bad format for --set-section-flags" +msgstr "" + +#: objcopy.c:1909 +msgid "byte number must be less than interleave" +msgstr "" + +#: objcopy.c:1928 +#, c-format +msgid "Cannot stat: %s: %s" +msgstr "" + +#: objcopy.c:1968 +#, c-format +msgid "Warning: --change-section-vma %s%c0x%s never used" +msgstr "" + +#: objcopy.c:1981 +#, c-format +msgid "Warning: --change-section-lma %s%c0x%s never used" +msgstr "" + +#: objdump.c:219 +#, c-format +msgid "" +"Usage: %s [-ahifCdDprRtTxsSlw] [-b bfdname] [-m machine] [-j section-name]\n" +" [--archive-headers] [--target=bfdname] [--debugging] [--disassemble]\n" +" [--disassemble-all] [--disassemble-zeroes] [--file-headers]\n" +" [--section-headers] [--headers]\n" +" [--info] [--section=section-name] [--line-numbers] [--source]\n" +msgstr "" + +#: objdump.c:226 +msgid "" +" [--architecture=machine] [--reloc] [--full-contents] [--stabs]\n" +" [--syms] [--all-headers] [--dynamic-syms] [--dynamic-reloc]\n" +" [--wide] [--version] [--help] [--private-headers]\n" +" [--start-address=addr] [--stop-address=addr]\n" +" [--prefix-addresses] [--[no-]show-raw-insn] [--demangle]\n" +" [--adjust-vma=offset] [-EB|-EL] [--endian={big|little}] objfile...\n" +"at least one option besides -l (--line-numbers) must be given\n" +msgstr "" + +#: objdump.c:361 +msgid "Sections:\n" +msgstr "" + +#: objdump.c:363 +msgid "Idx Name Size VMA LMA File off Algn\n" +msgstr "" + +#: objdump.c:365 +msgid "" +"Idx Name Size VMA LMA File off " +"Algn\n" +msgstr "" + +#: objdump.c:414 +#, c-format +msgid "%s: %s: not a dynamic object\n" +msgstr "" + +#: objdump.c:431 +#, c-format +msgid "%s: %s: No dynamic symbols\n" +msgstr "" + +#: objdump.c:1131 +msgid "Out of virtual memory\n" +msgstr "" + +#: objdump.c:1532 +#, c-format +msgid "%s: Can't use supplied machine %s\n" +msgstr "" + +#: objdump.c:1553 +#, c-format +msgid "%s: Can't disassemble for architecture %s\n" +msgstr "" + +#: objdump.c:1627 +#, c-format +msgid "Disassembly of section %s:\n" +msgstr "" + +#: objdump.c:1798 +#, c-format +msgid "" +"No %s section present\n" +"\n" +msgstr "" + +#: objdump.c:1805 +#, c-format +msgid "%s: %s has no %s section\n" +msgstr "" + +#: objdump.c:1818 objdump.c:1829 +#, c-format +msgid "%s: Reading %s section of %s failed: %s\n" +msgstr "" + +#: objdump.c:1871 +#, c-format +msgid "" +"Contents of %s section:\n" +"\n" +msgstr "" + +#: objdump.c:1971 +#, c-format +msgid "architecture: %s, " +msgstr "" + +#: objdump.c:1974 +#, c-format +msgid "flags 0x%08x:\n" +msgstr "" + +#: objdump.c:1987 +msgid "" +"\n" +"start address 0x" +msgstr "" + +#: objdump.c:2030 +#, c-format +msgid "" +"\n" +"%s: file format %s\n" +msgstr "" + +#: objdump.c:2071 +#, c-format +msgid "%s: printing debugging information failed\n" +msgstr "" + +#: objdump.c:2105 +#, c-format +msgid "In archive %s:\n" +msgstr "" + +#: objdump.c:2158 +#, c-format +msgid "Contents of section %s:\n" +msgstr "" + +#: objdump.c:2661 +#, c-format +msgid "BFD header file version %s\n" +msgstr "" + +#: objdump.c:2786 +#, c-format +msgid "%s: unrecognized -E option\n" +msgstr "" + +#: objdump.c:2797 +#, c-format +msgid "%s: unrecognized --endian type `%s'\n" +msgstr "" + +#: rdcoff.c:204 +#, c-format +msgid "%s: parse_coff_type: Bad type code 0x%x\n" +msgstr "" + +#: rdcoff.c:423 rdcoff.c:531 rdcoff.c:712 +#, c-format +msgid "%s: bfd_coff_get_syment failed: %s\n" +msgstr "" + +#: rdcoff.c:439 rdcoff.c:732 +#, c-format +msgid "%s: bfd_coff_get_auxent failed: %s\n" +msgstr "" + +#: rdcoff.c:798 +#, c-format +msgid "%s: %ld: .bf without preceding function\n" +msgstr "" + +#: rdcoff.c:848 +#, c-format +msgid "%s: %ld: unexpected .ef\n" +msgstr "" + +#: rddbg.c:87 +#, c-format +msgid "%s: no recognized debugging information\n" +msgstr "" + +#: rddbg.c:400 +msgid "Last stabs entries before error:\n" +msgstr "" + +#: readelf.c:229 readelf.c:255 +#, c-format +msgid "%s: Error: " +msgstr "" + +#: readelf.c:241 readelf.c:270 +#, c-format +msgid "%s: Warning: " +msgstr "" + +#: readelf.c:300 readelf.c:325 +#, c-format +msgid "Unhandled data length: %d\n" +msgstr "" + +#: readelf.c:420 +msgid "Don't know about relocations on this machine architecture\n" +msgstr "" + +#: readelf.c:426 +msgid "" +" Offset Info Type Symbol's Value Symbol's Name " +"Addend\n" +msgstr "" + +#: readelf.c:429 +msgid " Offset Info Type Symbol's Value Symbol's Name\n" +msgstr "" + +#: readelf.c:533 +#, c-format +msgid "unrecognised: %-7lx" +msgstr "" + +#: readelf.c:551 +#, c-format +msgid "<string table index %3ld>" +msgstr "" + +#: readelf.c:703 +#, c-format +msgid "Processor Specific: %lx" +msgstr "" + +#: readelf.c:706 +#, c-format +msgid "Operating System specific: %lx" +msgstr "" + +#: readelf.c:708 readelf.c:961 +#, c-format +msgid "<unknown>: %lx" +msgstr "" + +#: readelf.c:722 +msgid "NONE (None)" +msgstr "" + +#: readelf.c:723 +msgid "REL (Relocatable file)" +msgstr "" + +#: readelf.c:724 +msgid "EXEC (Executable file)" +msgstr "" + +#: readelf.c:725 +msgid "DYN (Shared object file)" +msgstr "" + +#: readelf.c:726 +msgid "CORE (Core file)" +msgstr "" + +#: readelf.c:730 +#, c-format +msgid "Processor Specific: (%x)" +msgstr "" + +#: readelf.c:732 +#, c-format +msgid "OS Specific: (%x)" +msgstr "" + +#: readelf.c:734 readelf.c:793 readelf.c:897 readelf.c:1072 +#, c-format +msgid "<unknown>: %x" +msgstr "" + +#: readelf.c:747 +msgid "None" +msgstr "" + +#: readelf.c:894 +msgid "ELFDATA2LSB (little endian)" +msgstr "" + +#: readelf.c:895 +msgid "ELFDATA2MSB (big endian)" +msgstr "" + +#: readelf.c:1108 +msgid "Usage: readelf {options} elf-file(s)\n" +msgstr "" + +#: readelf.c:1109 +msgid " Options are:\n" +msgstr "" + +#: readelf.c:1110 +msgid "" +" -a or --all Equivalent to: -h -l -S -s -r -d -V --histogram\n" +msgstr "" + +#: readelf.c:1111 +msgid " -h or --file-header Display the ELF file header\n" +msgstr "" + +#: readelf.c:1112 +msgid " -l or --program-headers or --segments\n" +msgstr "" + +#: readelf.c:1113 +msgid " Display the program headers\n" +msgstr "" + +#: readelf.c:1114 +msgid " -S or --section-headers or --sections\n" +msgstr "" + +#: readelf.c:1115 +msgid " Display the sections' header\n" +msgstr "" + +#: readelf.c:1116 +msgid " -e or --headers Equivalent to: -h -l -S\n" +msgstr "" + +#: readelf.c:1117 +msgid " -s or --syms or --symbols Display the symbol table\n" +msgstr "" + +#: readelf.c:1118 +msgid " -r or --relocs Display the relocations (if present)\n" +msgstr "" + +#: readelf.c:1119 +msgid " -d or --dynamic Display the dynamic segment (if present)\n" +msgstr "" + +#: readelf.c:1120 +msgid " -V or --version-info Display the version sections (if present)\n" +msgstr "" + +#: readelf.c:1121 +msgid "" +" -D or --use-dynamic Use the dynamic section info when displaying " +"symbols\n" +msgstr "" + +#: readelf.c:1122 +msgid " -x <number> or --hex-dump=<number>\n" +msgstr "" + +#: readelf.c:1123 +msgid " Dump the contents of section <number>\n" +msgstr "" + +#: readelf.c:1124 +msgid " -w[liapr] or --debug-dump[=line,=info,=abbrev,=pubnames,=ranges]\n" +msgstr "" + +#: readelf.c:1125 +msgid "" +" Display the contents of DWARF2 debug sections\n" +msgstr "" + +#: readelf.c:1127 +msgid " -i <number> or --instruction-dump=<number>\n" +msgstr "" + +#: readelf.c:1128 +msgid "" +" Disassemble the contents of section <number>\n" +msgstr "" + +#: readelf.c:1130 +msgid " --histogram Display histogram of bucket list lengths\n" +msgstr "" + +#: readelf.c:1131 +msgid " -v or --version Display the version number of readelf\n" +msgstr "" + +#: readelf.c:1132 +msgid " -H or --help Display this information\n" +msgstr "" + +#: readelf.c:1150 +msgid "Out of memory allocating dump request table." +msgstr "" + +#: readelf.c:1274 +#, c-format +msgid "Unrecognised debug option '%s'\n" +msgstr "" + +#: readelf.c:1299 +#, c-format +msgid "Invalid option '-%c'\n" +msgstr "" + +#: readelf.c:1312 +msgid "Nothing to do.\n" +msgstr "" + +#: readelf.c:1323 readelf.c:1336 readelf.c:2459 +msgid "none" +msgstr "" + +#: readelf.c:1324 +msgid "ELF32" +msgstr "" + +#: readelf.c:1325 +msgid "ELF64" +msgstr "" + +#: readelf.c:1326 readelf.c:1339 readelf.c:1352 +msgid "<unknown>" +msgstr "" + +#: readelf.c:1337 +msgid "2's compilment, little endian" +msgstr "" + +#: readelf.c:1338 +msgid "2's compilment, big endian" +msgstr "" + +#: readelf.c:1349 +msgid "UNIX - System V" +msgstr "" + +#: readelf.c:1350 +msgid "UNIX - HP-UX" +msgstr "" + +#: readelf.c:1351 +msgid "Standalone App" +msgstr "" + +#: readelf.c:1366 +msgid "Not an ELF file - it has the wrong magic bytes at the start\n" +msgstr "" + +#: readelf.c:1374 +msgid "ELF Header:\n" +msgstr "" + +#: readelf.c:1375 +msgid " Magic: " +msgstr "" + +#: readelf.c:1379 +#, c-format +msgid " Class: %s\n" +msgstr "" + +#: readelf.c:1381 readelf.c:1397 +#, c-format +msgid " Data: %s\n" +msgstr "" + +#: readelf.c:1383 +#, c-format +msgid " Version: %d %s\n" +msgstr "" + +#: readelf.c:1387 +#, c-format +msgid " OS/ABI: %s\n" +msgstr "" + +#: readelf.c:1389 +#, c-format +msgid " ABI Version: %d\n" +msgstr "" + +#: readelf.c:1391 +#, c-format +msgid " Type: %s\n" +msgstr "" + +#: readelf.c:1393 +#, c-format +msgid " Machine: %s\n" +msgstr "" + +#: readelf.c:1395 +#, c-format +msgid " Version: 0x%lx\n" +msgstr "" + +#: readelf.c:1399 +#, c-format +msgid " Entry point address: 0x%lx\n" +msgstr "" + +#: readelf.c:1401 +#, c-format +msgid " Start of program headers: %ld (bytes into file)\n" +msgstr "" + +#: readelf.c:1403 +#, c-format +msgid " Start of section headers: %ld (bytes into file)\n" +msgstr "" + +#: readelf.c:1405 +#, c-format +msgid " Flags: 0x%lx%s\n" +msgstr "" + +#: readelf.c:1408 +#, c-format +msgid " Size of this header: %ld (bytes)\n" +msgstr "" + +#: readelf.c:1410 +#, c-format +msgid " Size of program headers: %ld (bytes)\n" +msgstr "" + +#: readelf.c:1412 +#, c-format +msgid " Number of program headers: %ld\n" +msgstr "" + +#: readelf.c:1414 +#, c-format +msgid " Size of section headers: %ld (bytes)\n" +msgstr "" + +#: readelf.c:1416 +#, c-format +msgid " Number of section headers: %ld\n" +msgstr "" + +#: readelf.c:1418 +#, c-format +msgid " Section header string table index: %ld\n" +msgstr "" + +#: readelf.c:1428 +msgid "Not a 32 bit ELF file\n" +msgstr "" + +#: readelf.c:1448 +msgid "" +"\n" +"There are no program headers in this file.\n" +msgstr "" + +#: readelf.c:1454 +#, c-format +msgid "" +"\n" +"Elf file is %s\n" +msgstr "" + +#: readelf.c:1455 +#, c-format +msgid "Entry point 0x%lx\n" +msgstr "" + +#: readelf.c:1456 +#, c-format +msgid "There are %d program headers, starting at offset %lx:\n" +msgstr "" + +#: readelf.c:1469 readelf.c:1619 readelf.c:1662 readelf.c:2018 readelf.c:2142 +#: readelf.c:3043 readelf.c:3057 +msgid "Out of memory\n" +msgstr "" + +#: readelf.c:1492 +#, c-format +msgid "" +"\n" +"Program Header%s:\n" +msgstr "" + +#: readelf.c:1494 +msgid "" +" Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align\n" +msgstr "" + +#: readelf.c:1529 +msgid "more than one dynamic segment\n" +msgstr "" + +#: readelf.c:1537 +msgid "Unable to find program interpreter name\n" +msgstr "" + +#: readelf.c:1544 +#, c-format +msgid "" +"\n" +" [Requesting program interpreter: %s]" +msgstr "" + +#: readelf.c:1562 +msgid "" +"\n" +" Section to Segment mapping:\n" +msgstr "" + +#: readelf.c:1563 +msgid " Segment Sections...\n" +msgstr "" + +#: readelf.c:1697 +msgid "" +"\n" +"There are no sections in this file.\n" +msgstr "" + +#: readelf.c:1703 +#, c-format +msgid "There are %d section headers, starting at offset %lx:\n" +msgstr "" + +#: readelf.c:1737 +msgid "File contains multiple dynamic symbol tables\n" +msgstr "" + +#: readelf.c:1750 +msgid "File contains multiple dynamic string tables\n" +msgstr "" + +#: readelf.c:1777 +#, c-format +msgid "" +"\n" +"Section Header%s:\n" +msgstr "" + +#: readelf.c:1779 +msgid "" +" [Nr] Name Type Addr Off Size ES Flg Lk " +"Inf Al\n" +msgstr "" + +#: readelf.c:1844 +#, c-format +msgid "" +"\n" +"Relocation section at offset 0x%lx contains %ld bytes:\n" +msgstr "" + +#: readelf.c:1851 +msgid "" +"\n" +"There are no dynamic relocations in this file.\n" +msgstr "" + +#: readelf.c:1877 +msgid "" +"\n" +"Relocation section " +msgstr "" + +#: readelf.c:1884 +#, c-format +msgid " at offset 0x%lx contains %lu entries:\n" +msgstr "" + +#: readelf.c:1910 +msgid "" +"\n" +"There are no relocations in this file.\n" +msgstr "" + +#: readelf.c:1998 +msgid "" +"\n" +"There is no dynamic segment in this file.\n" +msgstr "" + +#: readelf.c:2056 +msgid "Unable to seek to end of file!" +msgstr "" + +#: readelf.c:2062 +msgid "Unable to determine the number of symbols to load\n" +msgstr "" + +#: readelf.c:2092 +msgid "Unable to seek to end of file\n" +msgstr "" + +#: readelf.c:2098 +msgid "Unable to determine the length of the dynamic string table\n" +msgstr "" + +#: readelf.c:2159 +#, c-format +msgid "" +"\n" +"Dynamic segment at offset 0x%x contains %d entries:\n" +msgstr "" + +#: readelf.c:2162 +msgid " Tag Type Name/Value\n" +msgstr "" + +#: readelf.c:2169 +#, c-format +msgid " 0x%-8.8lx (%s)%*s" +msgstr "" + +#: readelf.c:2182 +msgid "Auxiliary library" +msgstr "" + +#: readelf.c:2184 +msgid "Filter library" +msgstr "" + +#: readelf.c:2196 readelf.c:2217 readelf.c:2243 +msgid "Flags:" +msgstr "" + +#: readelf.c:2198 readelf.c:2219 readelf.c:2245 +msgid " None\n" +msgstr "" + +#: readelf.c:2348 +#, c-format +msgid "Shared library: [%s]" +msgstr "" + +#: readelf.c:2353 +msgid " program interpreter\n" +msgstr "" + +#: readelf.c:2357 +#, c-format +msgid "Library soname: [%s]\n" +msgstr "" + +#: readelf.c:2361 +#, c-format +msgid "Library rpath: [%s]\n" +msgstr "" + +#: readelf.c:2413 +#, c-format +msgid "Not needed object: [%s]\n" +msgstr "" + +#: readelf.c:2505 +#, c-format +msgid "" +"\n" +"Version definition section '%s' contains %ld entries:\n" +msgstr "" + +#: readelf.c:2508 +msgid " Addr: 0x" +msgstr "" + +#: readelf.c:2510 readelf.c:2699 +#, c-format +msgid " Offset: %#08lx Link: %lx (%s)\n" +msgstr "" + +#: readelf.c:2540 +#, c-format +msgid " %#06x: Rev: %d Flags: %s" +msgstr "" + +#: readelf.c:2543 +#, c-format +msgid " Index: %d Cnt: %d " +msgstr "" + +#: readelf.c:2554 +#, c-format +msgid "Name: %s\n" +msgstr "" + +#: readelf.c:2556 +#, c-format +msgid "Name index: %ld\n" +msgstr "" + +#: readelf.c:2571 +#, c-format +msgid " %#06x: Parent %d: %s\n" +msgstr "" + +#: readelf.c:2574 +#, c-format +msgid " %#06x: Parent %d, name index: %ld\n" +msgstr "" + +#: readelf.c:2593 +#, c-format +msgid "" +"\n" +"Version needs section '%s' contains %ld entries:\n" +msgstr "" + +#: readelf.c:2596 +msgid " Addr: 0x" +msgstr "" + +#: readelf.c:2598 +#, c-format +msgid " Offset: %#08lx Link to section: %ld (%s)\n" +msgstr "" + +#: readelf.c:2624 +#, c-format +msgid " %#06x: Version: %d" +msgstr "" + +#: readelf.c:2627 +#, c-format +msgid " File: %s" +msgstr "" + +#: readelf.c:2629 +#, c-format +msgid " File: %lx" +msgstr "" + +#: readelf.c:2631 +#, c-format +msgid " Cnt: %d\n" +msgstr "" + +#: readelf.c:2649 +#, c-format +msgid " %#06x: Name: %s" +msgstr "" + +#: readelf.c:2652 +#, c-format +msgid " %#06x: Name index: %lx" +msgstr "" + +#: readelf.c:2655 +#, c-format +msgid " Flags: %s Version: %d\n" +msgstr "" + +#: readelf.c:2694 +#, c-format +msgid "" +"\n" +"Version symbols section '%s' contains %d entries:\n" +msgstr "" + +#: readelf.c:2697 +msgid " Addr: " +msgstr "" + +#: readelf.c:2726 +msgid " 0 (*local*) " +msgstr "" + +#: readelf.c:2730 +msgid " 1 (*global*) " +msgstr "" + +#: readelf.c:2953 +msgid "" +"\n" +"No version information found in this file.\n" +msgstr "" + +#: readelf.c:2966 +msgid "LOCAL" +msgstr "" + +#: readelf.c:2967 +msgid "GLOBAL" +msgstr "" + +#: readelf.c:2968 +msgid "WEAK" +msgstr "" + +#: readelf.c:2971 readelf.c:2995 +#, c-format +msgid "<processor specific>: %d" +msgstr "" + +#: readelf.c:2973 readelf.c:2997 +#, c-format +msgid "<OS specific>: %d" +msgstr "" + +#: readelf.c:2975 readelf.c:2999 +#, c-format +msgid "<unknown>: %d" +msgstr "" + +#: readelf.c:2988 +msgid "NOTYPE" +msgstr "" + +#: readelf.c:2989 +msgid "OBJECT" +msgstr "" + +#: readelf.c:2990 +msgid "FUNC" +msgstr "" + +#: readelf.c:2991 +msgid "SECTION" +msgstr "" + +#: readelf.c:2992 +msgid "FILE" +msgstr "" + +#: readelf.c:3049 +msgid "Unable to read in dynamic data\n" +msgstr "" + +#: readelf.c:3091 +msgid "Unable to seek to start of dynamic information" +msgstr "" + +#: readelf.c:3097 +msgid "Failed to read in number of buckets\n" +msgstr "" + +#: readelf.c:3103 +msgid "Failed to read in number of chains\n" +msgstr "" + +#: readelf.c:3123 +msgid "" +"\n" +"Symbol table for image:\n" +msgstr "" + +#: readelf.c:3124 +msgid " Num Buc: Value Size Type Bind Ot Ndx Name\n" +msgstr "" + +#: readelf.c:3169 +#, c-format +msgid "" +"\n" +"Symbol table '%s' contains %lu entries:\n" +msgstr "" + +#: readelf.c:3172 +msgid " Num: Value Size Type Bind Ot Ndx Name\n" +msgstr "" + +#: readelf.c:3291 +msgid "bad dynamic symbol" +msgstr "" + +#: readelf.c:3350 +msgid "" +"\n" +"Dynamic symbol information is not available for displaying symbols.\n" +msgstr "" + +#: readelf.c:3362 +#, c-format +msgid "" +"\n" +"Histogram for bucket list length (total of %d buckets):\n" +msgstr "" + +#: readelf.c:3364 +msgid " Length Number %% of total Coverage\n" +msgstr "" + +#: readelf.c:3369 readelf.c:3388 readelf.c:5271 readelf.c:5461 +msgid "Out of memory" +msgstr "" + +#: readelf.c:3434 +#, c-format +msgid "" +"\n" +"Dynamic info segment at offset 0x%lx contains %d entries:\n" +msgstr "" + +#: readelf.c:3437 +msgid " Num: Name BoundTo Flags\n" +msgstr "" + +#: readelf.c:3485 +#, c-format +msgid "" +"\n" +"Assembly dump of section %s\n" +msgstr "" + +#: readelf.c:3508 +#, c-format +msgid "" +"\n" +"Section '%s' has no data to dump.\n" +msgstr "" + +#: readelf.c:3513 +#, c-format +msgid "" +"\n" +"Hex dump of section '%s':\n" +msgstr "" + +#: readelf.c:3663 +msgid "badly formed extended line op encountered!" +msgstr "" + +#: readelf.c:3670 +#, c-format +msgid " Extended opcode %d: " +msgstr "" + +#: readelf.c:3675 +msgid "" +"End of Sequence\n" +"\n" +msgstr "" + +#: readelf.c:3682 +#, c-format +msgid "set Address to 0x%lx\n" +msgstr "" + +#: readelf.c:3687 +msgid " define new File Table entry\n" +msgstr "" + +#: readelf.c:3688 readelf.c:3806 +msgid " Entry\tDir\tTime\tSize\tName\n" +msgstr "" + +#: readelf.c:3690 +#, c-format +msgid " %d\t" +msgstr "" + +#: readelf.c:3693 readelf.c:3695 readelf.c:3697 readelf.c:3818 readelf.c:3820 +#: readelf.c:3822 +#, c-format +msgid "%lu\t" +msgstr "" + +#: readelf.c:3698 +#, c-format +msgid "" +"%s\n" +"\n" +msgstr "" + +#: readelf.c:3702 +#, c-format +msgid "UNKNOWN: length %d\n" +msgstr "" + +#: readelf.c:3724 +#, c-format +msgid "" +"\n" +"Dump of debug contents of section %s:\n" +"\n" +msgstr "" + +#: readelf.c:3736 +msgid "The line info appears to be corrupt - the section is too small\n" +msgstr "" + +#: readelf.c:3744 +msgid "Only DWARF version 2 line info is currently supported.\n" +msgstr "" + +#: readelf.c:3759 +#, c-format +msgid " Length: %ld\n" +msgstr "" + +#: readelf.c:3760 +#, c-format +msgid " DWARF Version: %d\n" +msgstr "" + +#: readelf.c:3761 +#, c-format +msgid " Prolgue Length: %d\n" +msgstr "" + +#: readelf.c:3762 +#, c-format +msgid " Minimum Instruction Length: %d\n" +msgstr "" + +#: readelf.c:3763 +#, c-format +msgid " Initial value of 'is_stmt': %d\n" +msgstr "" + +#: readelf.c:3764 +#, c-format +msgid " Line Base: %d\n" +msgstr "" + +#: readelf.c:3765 +#, c-format +msgid " Line Range: %d\n" +msgstr "" + +#: readelf.c:3766 +#, c-format +msgid " Opcode Base: %d\n" +msgstr "" + +#: readelf.c:3775 +msgid "" +"\n" +" Opcodes:\n" +msgstr "" + +#: readelf.c:3778 +#, c-format +msgid " Opcode %d has %d args\n" +msgstr "" + +#: readelf.c:3784 +msgid "" +"\n" +" The Directory Table is empty.\n" +msgstr "" + +#: readelf.c:3787 +msgid "" +"\n" +" The Directory Table:\n" +msgstr "" + +#: readelf.c:3791 +#, c-format +msgid " %s\n" +msgstr "" + +#: readelf.c:3802 +msgid "" +"\n" +" The File Name Table is empty.\n" +msgstr "" + +#: readelf.c:3805 +msgid "" +"\n" +" The File Name Table:\n" +msgstr "" + +#: readelf.c:3813 +#, c-format +msgid " %d\t" +msgstr "" + +#: readelf.c:3824 +#, c-format +msgid "%s\n" +msgstr "" + +#. Now display the statements. +#: readelf.c:3832 +msgid "" +"\n" +" Line Number Statements:\n" +msgstr "" + +#: readelf.c:3850 +msgid " Copy\n" +msgstr "" + +#: readelf.c:3857 +#, c-format +msgid " Advance PC by %d to %lx\n" +msgstr "" + +#: readelf.c:3865 +#, c-format +msgid " Advance Line by %d to %d\n" +msgstr "" + +#: readelf.c:3872 +#, c-format +msgid " Set File Name to entry %d in the File Name Table\n" +msgstr "" + +#: readelf.c:3880 +#, c-format +msgid " Set column to %d\n" +msgstr "" + +#: readelf.c:3887 +#, c-format +msgid " Set is_stmt to %d\n" +msgstr "" + +#: readelf.c:3892 +msgid " Set basic block\n" +msgstr "" + +#: readelf.c:3899 +#, c-format +msgid " Advance PC by constant %d to 0x%lx\n" +msgstr "" + +#: readelf.c:3907 +#, c-format +msgid " Advance PC by fixed size amount %d to 0x%lx\n" +msgstr "" + +#: readelf.c:3915 +#, c-format +msgid " Special opcode %d: advance Address by %d to 0x%lx" +msgstr "" + +#: readelf.c:3919 +#, c-format +msgid " and Line by %d to %d\n" +msgstr "" + +#: readelf.c:3942 readelf.c:4361 +#, c-format +msgid "" +"Contents of the %s section:\n" +"\n" +msgstr "" + +#: readelf.c:3961 +msgid "Only DWARF 2 pubnames are currently supported" +msgstr "" + +#: readelf.c:3965 +#, c-format +msgid " Length: %ld\n" +msgstr "" + +#: readelf.c:3967 +#, c-format +msgid " Version: %d\n" +msgstr "" + +#: readelf.c:3969 +#, c-format +msgid " Offset into .debug_info section: %ld\n" +msgstr "" + +#: readelf.c:3971 +#, c-format +msgid " Size of area in .debug_info section: %ld\n" +msgstr "" + +#: readelf.c:3974 +msgid "" +"\n" +" Offset\tName\n" +msgstr "" + +#: readelf.c:4056 +#, c-format +msgid "Unknown TAG value: %lx" +msgstr "" + +#: readelf.c:4151 +#, c-format +msgid "Unknown AT value: %lx" +msgstr "" + +#: readelf.c:4188 +#, c-format +msgid "Unknown FORM value: %lx" +msgstr "" + +#: readelf.c:4367 +msgid " Number TAG\n" +msgstr "" + +#: readelf.c:4373 +#, c-format +msgid " %ld %s [%s]\n" +msgstr "" + +#: readelf.c:4376 +msgid "has children" +msgstr "" + +#: readelf.c:4376 +msgid "no children" +msgstr "" + +#: readelf.c:4380 +#, c-format +msgid " %-18s %s\n" +msgstr "" + +#: readelf.c:4399 +#, c-format +msgid " %lu byte block: " +msgstr "" + +#: readelf.c:4568 +msgid "(User defined location op)" +msgstr "" + +#: readelf.c:4570 +msgid "(Unknown location op)" +msgstr "" + +#: readelf.c:4687 +#, c-format +msgid "Unable to handle FORM: %d" +msgstr "" + +#: readelf.c:4691 +#, c-format +msgid "Unrecognised form: %d" +msgstr "" + +#: readelf.c:4704 +msgid "(not inlined)" +msgstr "" + +#: readelf.c:4705 +msgid "(inlined)" +msgstr "" + +#: readelf.c:4706 +msgid "(declared as inline but ignored)" +msgstr "" + +#: readelf.c:4707 +msgid "(declared as inline and inlined)" +msgstr "" + +#: readelf.c:4708 +#, c-format +msgid " (Unknown inline attribute value: %lx)" +msgstr "" + +#: readelf.c:4838 readelf.c:4962 +#, c-format +msgid "" +"The section %s contains:\n" +"\n" +msgstr "" + +#: readelf.c:4860 +msgid "Only version 2 DWARF debug information is currently supported.\n" +msgstr "" + +#: readelf.c:4864 +msgid " Compilation Unit:\n" +msgstr "" + +#: readelf.c:4865 +#, c-format +msgid " Length: %ld\n" +msgstr "" + +#: readelf.c:4866 +#, c-format +msgid " Version: %d\n" +msgstr "" + +#: readelf.c:4867 +#, c-format +msgid " Abbrev Offset: %ld\n" +msgstr "" + +#: readelf.c:4868 +#, c-format +msgid " Pointer Size: %d\n" +msgstr "" + +#: readelf.c:4888 +msgid "Unable to locate .debug_abbrev section!\n" +msgstr "" + +#: readelf.c:4928 +#, c-format +msgid "Unable to locate entry %d in the abbreviation table\n" +msgstr "" + +#: readelf.c:4933 +#, c-format +msgid " <%d><%x>: Abbrev Number: %d (%s)\n" +msgstr "" + +#: readelf.c:4980 +#, c-format +msgid " Length: %ld\n" +msgstr "" + +#: readelf.c:4981 +#, c-format +msgid " Version: %d\n" +msgstr "" + +#: readelf.c:4982 +#, c-format +msgid " Offset into .debug_info: %lx\n" +msgstr "" + +#: readelf.c:4983 +#, c-format +msgid " Pointer Size: %d\n" +msgstr "" + +#: readelf.c:4984 +#, c-format +msgid " Segment Size: %d\n" +msgstr "" + +#: readelf.c:4986 +msgid "" +"\n" +" Address Length\n" +msgstr "" + +#: readelf.c:5021 +#, c-format +msgid "Displaying the debug contents of section %s is not yet supported.\n" +msgstr "" + +#: readelf.c:5063 +#, c-format +msgid "" +"\n" +"Section '%s' has no debugging data.\n" +msgstr "" + +#: readelf.c:5079 +#, c-format +msgid "Unrecognised debug section: %s\n" +msgstr "" + +#: readelf.c:5118 +msgid "Some sections were not dumped because they do not exist!\n" +msgstr "" + +#: readelf.c:5293 +#, c-format +msgid "" +"\n" +"Section '%s' contains %d entries:\n" +msgstr "" + +#: readelf.c:5454 +msgid "conflict list with without table" +msgstr "" + +#: readelf.c:5482 +#, c-format +msgid "" +"\n" +"Section '.conflict' contains %d entries:\n" +msgstr "" + +#: readelf.c:5483 +msgid " Num: Index Value Name" +msgstr "" + +#: readelf.c:5560 +#, c-format +msgid "Cannot stat input file %s.\n" +msgstr "" + +#: readelf.c:5567 +#, c-format +msgid "Input file %s not found.\n" +msgstr "" + +#: readelf.c:5573 +#, c-format +msgid "%s: Failed to read file header\n" +msgstr "" + +#: readelf.c:5587 +#, c-format +msgid "" +"\n" +"File: %s\n" +msgstr "" + +#: rename.c:121 +#, c-format +msgid "%s: cannot set time: %s" +msgstr "" + +#. We have to clean up here. +#: rename.c:160 rename.c:193 +#, c-format +msgid "%s: rename: %s" +msgstr "" + +#: rename.c:201 +#, c-format +msgid "%s: simple_copy: %s" +msgstr "" + +#: resbin.c:130 +#, c-format +msgid "%s: not enough binary data" +msgstr "" + +#: resbin.c:149 +msgid "null terminated unicode string" +msgstr "" + +#: resbin.c:179 resbin.c:185 +msgid "resource ID" +msgstr "" + +#: resbin.c:229 +msgid "cursor" +msgstr "" + +#: resbin.c:263 resbin.c:270 +msgid "menu header" +msgstr "" + +#: resbin.c:280 +msgid "menuex header" +msgstr "" + +#: resbin.c:284 +msgid "menuex offset" +msgstr "" + +#: resbin.c:291 +#, c-format +msgid "unsupported menu version %d" +msgstr "" + +#: resbin.c:319 resbin.c:334 resbin.c:400 +msgid "menuitem header" +msgstr "" + +#: resbin.c:430 +msgid "menuitem" +msgstr "" + +#: resbin.c:471 resbin.c:499 +msgid "dialog header" +msgstr "" + +#: resbin.c:489 +#, c-format +msgid "unexpected dialog signature %d" +msgstr "" + +#: resbin.c:531 +msgid "dialog font point size" +msgstr "" + +#: resbin.c:539 +msgid "dialogex font information" +msgstr "" + +#: resbin.c:564 resbin.c:582 +msgid "dialog control" +msgstr "" + +#: resbin.c:574 +msgid "dialogex control" +msgstr "" + +#: resbin.c:603 +msgid "dialog control end" +msgstr "" + +#: resbin.c:615 +msgid "dialog control data" +msgstr "" + +#: resbin.c:658 +msgid "stringtable string length" +msgstr "" + +#: resbin.c:668 +msgid "stringtable string" +msgstr "" + +#: resbin.c:701 +msgid "fontdir header" +msgstr "" + +#: resbin.c:714 +msgid "fontdir" +msgstr "" + +#: resbin.c:730 +msgid "fontdir device name" +msgstr "" + +#: resbin.c:736 +msgid "fontdir face name" +msgstr "" + +#: resbin.c:779 +msgid "accelerator" +msgstr "" + +#: resbin.c:843 +msgid "group cursor header" +msgstr "" + +#: resbin.c:847 +#, c-format +msgid "unexpected group cursor type %d" +msgstr "" + +#: resbin.c:862 +msgid "group cursor" +msgstr "" + +#: resbin.c:901 +msgid "group icon header" +msgstr "" + +#: resbin.c:905 +#, c-format +msgid "unexpected group icon type %d" +msgstr "" + +#: resbin.c:920 +msgid "group icon" +msgstr "" + +#: resbin.c:991 resbin.c:1210 +msgid "unexpected version string" +msgstr "" + +#: resbin.c:1025 +#, c-format +msgid "version length %d does not match resource length %lu" +msgstr "" + +#: resbin.c:1029 +#, c-format +msgid "unexpected version type %d" +msgstr "" + +#: resbin.c:1041 +#, c-format +msgid "unexpected fixed version information length %d" +msgstr "" + +#: resbin.c:1044 +msgid "fixed version info" +msgstr "" + +#: resbin.c:1048 +#, c-format +msgid "unexpected fixed version signature %lu" +msgstr "" + +#: resbin.c:1052 +#, c-format +msgid "unexpected fixed version info version %lu" +msgstr "" + +#: resbin.c:1081 +msgid "version var info" +msgstr "" + +#: resbin.c:1098 +#, c-format +msgid "unexpected stringfileinfo value length %d" +msgstr "" + +#: resbin.c:1108 +#, c-format +msgid "unexpected version stringtable value length %d" +msgstr "" + +#: resbin.c:1142 +#, c-format +msgid "unexpected version string length %d != %d + %d" +msgstr "" + +#: resbin.c:1153 +#, c-format +msgid "unexpected version string length %d < %d" +msgstr "" + +#: resbin.c:1170 +#, c-format +msgid "unexpected varfileinfo value length %d" +msgstr "" + +#: resbin.c:1189 +msgid "version varfileinfo" +msgstr "" + +#: resbin.c:1204 +#, c-format +msgid "unexpected version value length %d" +msgstr "" + +#: rescoff.c:128 +msgid "filename required for COFF input" +msgstr "" + +#: rescoff.c:145 +#, c-format +msgid "%s: %s: no resource section\n" +msgstr "" + +#: rescoff.c:154 +msgid "can't read resource section" +msgstr "" + +#: rescoff.c:180 +#, c-format +msgid "%s: %s: address out of bounds" +msgstr "" + +#: rescoff.c:199 +msgid "directory" +msgstr "" + +#: rescoff.c:227 +msgid "named directory entry" +msgstr "" + +#: rescoff.c:236 +msgid "directory entry name" +msgstr "" + +#: rescoff.c:256 +msgid "named subdirectory" +msgstr "" + +#: rescoff.c:264 +msgid "named resource" +msgstr "" + +#: rescoff.c:279 +msgid "ID directory entry" +msgstr "" + +#: rescoff.c:296 +msgid "ID subdirectory" +msgstr "" + +#: rescoff.c:304 +msgid "ID resource" +msgstr "" + +#: rescoff.c:330 +msgid "resource type unknown" +msgstr "" + +#: rescoff.c:333 +msgid "data entry" +msgstr "" + +#: rescoff.c:341 +msgid "resource data" +msgstr "" + +#: rescoff.c:346 +msgid "resource data size" +msgstr "" + +#: rescoff.c:441 +msgid "filename required for COFF output" +msgstr "" + +#: rescoff.c:729 +msgid "can't get BFD_RELOC_RVA relocation type" +msgstr "" + +#: resrc.c:150 +#, c-format +msgid "can't popen `%s': %s" +msgstr "" + +#: resrc.c:163 +#, c-format +msgid "%s: warning: preprocessor failed\n" +msgstr "" + +#: resrc.c:208 +#, c-format +msgid "%s: unexpected EOF" +msgstr "" + +#: resrc.c:265 +#, c-format +msgid "%s: read of %lu returned %lu" +msgstr "" + +#: resrc.c:307 resrc.c:538 resrc.c:811 resrc.c:965 +#, c-format +msgid "stat failed on bitmap file `%s': %s" +msgstr "" + +#: resrc.c:360 +#, c-format +msgid "cursor file `%s' does not contain cursor data" +msgstr "" + +#: resrc.c:392 resrc.c:682 +#, c-format +msgid "%s: fseek to %lu failed: %s" +msgstr "" + +#: resrc.c:651 +#, c-format +msgid "icon file `%s' does not contain icon data" +msgstr "" + +#: resrc.c:1170 +#, c-format +msgid "can't open `%s' for output: %s" +msgstr "" + +#: size.c:79 +#, c-format +msgid "" +"Usage: %s [-ABdoxV] [--format=berkeley|sysv] [--radix=8|10|16]\n" +" [--target=bfdname] [--version] [--help] [file...]\n" +msgstr "" + +#: size.c:83 +msgid "default is --format=berkeley\n" +msgstr "" + +#: size.c:85 +msgid "default is --format=sysv\n" +msgstr "" + +#: size.c:139 +#, c-format +msgid "invalid argument to --format: %s\n" +msgstr "" + +#: size.c:166 +#, c-format +msgid "Invalid radix: %s\n" +msgstr "" + +#: srconv.c:1879 +#, c-format +msgid "Usage: %s [-dhVq] in-file [out-file]\n" +msgstr "" + +#: srconv.c:1886 +#, c-format +msgid "%s: Convert a COFF object file into a SYSROFF object file\n" +msgstr "" + +#: srconv.c:2024 +#, c-format +msgid "%s: unable to open output file %s\n" +msgstr "" + +#: stabs.c:349 stabs.c:1762 +msgid "numeric overflow" +msgstr "" + +#: stabs.c:360 +#, c-format +msgid "Bad stab: %s\n" +msgstr "" + +#: stabs.c:370 +#, c-format +msgid "Warning: %s: %s\n" +msgstr "" + +#: stabs.c:492 +msgid "N_LBRAC not within function\n" +msgstr "" + +#: stabs.c:531 +msgid "Too many N_RBRACs\n" +msgstr "" + +#: stabs.c:780 +msgid "unknown C++ encoded name" +msgstr "" + +#. Complain and keep going, so compilers can invent new +#. cross-reference types. +#: stabs.c:1306 +msgid "unrecognized cross reference type" +msgstr "" + +#. Does this actually ever happen? Is that why we are worrying +#. about dealing with it rather than just calling error_type? +#: stabs.c:1854 +msgid "missing index type" +msgstr "" + +#: stabs.c:2181 +msgid "unknown virtual character for baseclass" +msgstr "" + +#: stabs.c:2199 +msgid "unknown visibility character for baseclass" +msgstr "" + +#: stabs.c:2391 +msgid "unnamed $vb type" +msgstr "" + +#: stabs.c:2397 +msgid "unrecognized C++ abbreviation" +msgstr "" + +#: stabs.c:2477 +msgid "unknown visibility character for field" +msgstr "" + +#: stabs.c:2733 +msgid "const/volatile indicator missing" +msgstr "" + +#: stabs.c:2973 +#, c-format +msgid "No mangling for \"%s\"\n" +msgstr "" + +#: stabs.c:3286 +msgid "Undefined N_EXCL" +msgstr "" + +#: stabs.c:3374 +#, c-format +msgid "Type file number %d out of range\n" +msgstr "" + +#: stabs.c:3379 +#, c-format +msgid "Type index number %d out of range\n" +msgstr "" + +#: stabs.c:3466 +#, c-format +msgid "Unrecognized XCOFF type %d\n" +msgstr "" + +#: stabs.c:3765 +#, c-format +msgid "bad mangled name `%s'\n" +msgstr "" + +#: stabs.c:3861 +msgid "no argument types in mangled string\n" +msgstr "" + +#: strings.c:159 +#, c-format +msgid "%s: invalid number %s\n" +msgstr "" + +#: strings.c:494 +#, c-format +msgid "%s: invalid integer argument %s\n" +msgstr "" + +#: strings.c:505 +#, c-format +msgid "" +"Usage: %s [-afov] [-n min-len] [-min-len] [-t {o,x,d}] [-]\n" +" [--all] [--print-file-name] [--bytes=min-len] [--radix={o,x,d}]\n" +" [--target=bfdname] [--help] [--version] file...\n" +msgstr "" + +#: sysdump.c:712 +#, c-format +msgid "Usage: %s [-hV] in-file\n" +msgstr "" + +#: sysdump.c:783 +#, c-format +msgid "%s: cannot open input file %s\n" +msgstr "" + +#: version.c:39 +msgid "Copyright 1997, 1998, 1999 Free Software Foundation, Inc.\n" +msgstr "" + +#: version.c:40 +msgid "" +"This program is free software; you may redistribute it under the terms of\n" +"the GNU General Public License. This program has absolutely no warranty.\n" +msgstr "" + +#: windres.c:228 +#, c-format +msgid "can't open %s `%s': %s" +msgstr "" + +#: windres.c:407 +msgid ": expected to be a directory\n" +msgstr "" + +#: windres.c:419 +msgid ": expected to be a leaf\n" +msgstr "" + +#: windres.c:428 +#, c-format +msgid "%s: warning: " +msgstr "" + +#: windres.c:430 +msgid ": duplicate value\n" +msgstr "" + +#: windres.c:593 +#, c-format +msgid "%s: unknown format type `%s'\n" +msgstr "" + +#: windres.c:594 +#, c-format +msgid "%s: supported formats:" +msgstr "" + +#. Otherwise, we give up. +#: windres.c:681 +#, c-format +msgid "can not determine type of file `%s'; use the -I option" +msgstr "" + +#: windres.c:695 +#, c-format +msgid "Usage: %s [options] [input-file] [output-file]\n" +msgstr "" + +#: windres.c:697 +msgid "" +"Options:\n" +" -i FILE, --input FILE Name input file\n" +" -o FILE, --output FILE Name output file\n" +" -I FORMAT, --input-format FORMAT\n" +" Specify input format\n" +" -O FORMAT, --output-format FORMAT\n" +" Specify output format\n" +" -F TARGET, --target TARGET Specify COFF target\n" +" --preprocessor PROGRAM Program to use to preprocess rc file\n" +" --include-dir DIR Include directory when preprocessing rc file\n" +" --define SYM[=VAL] Define SYM when preprocessing rc file\n" +" --language VAL Set language when reading rc file\n" +msgstr "" + +#: windres.c:711 +msgid " --yydebug Turn on parser debugging\n" +msgstr "" + +#: windres.c:714 +msgid "" +" --help Print this help message\n" +" --version Print version information\n" +msgstr "" + +#: windres.c:717 +msgid "" +"FORMAT is one of rc, res, or coff, and is deduced from the file name\n" +"extension if not specified. A single file name is an input file.\n" +"No input-file is stdin, default rc. No output-file is stdout, default rc.\n" +msgstr "" + +#: windres.c:918 +msgid "no resources" +msgstr "" + +#: wrstabs.c:366 wrstabs.c:2028 +#, c-format +msgid "string_hash_lookup failed: %s\n" +msgstr "" + +#: wrstabs.c:666 +#, c-format +msgid "stab_int_type: bad size %u\n" +msgstr "" + +#: wrstabs.c:1468 +#, c-format +msgid "%s: warning: unknown size for field `%s' in struct\n" +msgstr "" diff --git a/binutils/prdbg.c b/binutils/prdbg.c new file mode 100644 index 0000000..958cbd2 --- /dev/null +++ b/binutils/prdbg.c @@ -0,0 +1,1862 @@ +/* prdbg.c -- Print out generic debugging information. + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Written by Ian Lance Taylor <ian@cygnus.com>. + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* This file prints out the generic debugging information, by + supplying a set of routines to debug_write. */ + +#include <stdio.h> +#include <assert.h> + +#include "bfd.h" +#include "bucomm.h" +#include "libiberty.h" +#include "debug.h" +#include "budbg.h" + +/* This is the structure we use as a handle for these routines. */ + +struct pr_handle +{ + /* File to print information to. */ + FILE *f; + /* Current indentation level. */ + unsigned int indent; + /* Type stack. */ + struct pr_stack *stack; + /* Parameter number we are about to output. */ + int parameter; +}; + +/* The type stack. */ + +struct pr_stack +{ + /* Next element on the stack. */ + struct pr_stack *next; + /* This element. */ + char *type; + /* Current visibility of fields if this is a class. */ + enum debug_visibility visibility; + /* Name of the current method we are handling. */ + const char *method; +}; + +static void indent PARAMS ((struct pr_handle *)); +static boolean push_type PARAMS ((struct pr_handle *, const char *)); +static boolean prepend_type PARAMS ((struct pr_handle *, const char *)); +static boolean append_type PARAMS ((struct pr_handle *, const char *)); +static boolean substitute_type PARAMS ((struct pr_handle *, const char *)); +static boolean indent_type PARAMS ((struct pr_handle *)); +static char *pop_type PARAMS ((struct pr_handle *)); +static void print_vma PARAMS ((bfd_vma, char *, boolean, boolean)); +static boolean pr_fix_visibility + PARAMS ((struct pr_handle *, enum debug_visibility)); + +static boolean pr_start_compilation_unit PARAMS ((PTR, const char *)); +static boolean pr_start_source PARAMS ((PTR, const char *)); +static boolean pr_empty_type PARAMS ((PTR)); +static boolean pr_void_type PARAMS ((PTR)); +static boolean pr_int_type PARAMS ((PTR, unsigned int, boolean)); +static boolean pr_float_type PARAMS ((PTR, unsigned int)); +static boolean pr_complex_type PARAMS ((PTR, unsigned int)); +static boolean pr_bool_type PARAMS ((PTR, unsigned int)); +static boolean pr_enum_type + PARAMS ((PTR, const char *, const char **, bfd_signed_vma *)); +static boolean pr_pointer_type PARAMS ((PTR)); +static boolean pr_function_type PARAMS ((PTR, int, boolean)); +static boolean pr_reference_type PARAMS ((PTR)); +static boolean pr_range_type PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma)); +static boolean pr_array_type + PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma, boolean)); +static boolean pr_set_type PARAMS ((PTR, boolean)); +static boolean pr_offset_type PARAMS ((PTR)); +static boolean pr_method_type PARAMS ((PTR, boolean, int, boolean)); +static boolean pr_const_type PARAMS ((PTR)); +static boolean pr_volatile_type PARAMS ((PTR)); +static boolean pr_start_struct_type + PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int)); +static boolean pr_struct_field + PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility)); +static boolean pr_end_struct_type PARAMS ((PTR)); +static boolean pr_start_class_type + PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int, boolean, + boolean)); +static boolean pr_class_static_member + PARAMS ((PTR, const char *, const char *, enum debug_visibility)); +static boolean pr_class_baseclass + PARAMS ((PTR, bfd_vma, boolean, enum debug_visibility)); +static boolean pr_class_start_method PARAMS ((PTR, const char *)); +static boolean pr_class_method_variant + PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean, + bfd_vma, boolean)); +static boolean pr_class_static_method_variant + PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean)); +static boolean pr_class_end_method PARAMS ((PTR)); +static boolean pr_end_class_type PARAMS ((PTR)); +static boolean pr_typedef_type PARAMS ((PTR, const char *)); +static boolean pr_tag_type + PARAMS ((PTR, const char *, unsigned int, enum debug_type_kind)); +static boolean pr_typdef PARAMS ((PTR, const char *)); +static boolean pr_tag PARAMS ((PTR, const char *)); +static boolean pr_int_constant PARAMS ((PTR, const char *, bfd_vma)); +static boolean pr_float_constant PARAMS ((PTR, const char *, double)); +static boolean pr_typed_constant PARAMS ((PTR, const char *, bfd_vma)); +static boolean pr_variable + PARAMS ((PTR, const char *, enum debug_var_kind, bfd_vma)); +static boolean pr_start_function PARAMS ((PTR, const char *, boolean)); +static boolean pr_function_parameter + PARAMS ((PTR, const char *, enum debug_parm_kind, bfd_vma)); +static boolean pr_start_block PARAMS ((PTR, bfd_vma)); +static boolean pr_end_block PARAMS ((PTR, bfd_vma)); +static boolean pr_end_function PARAMS ((PTR)); +static boolean pr_lineno PARAMS ((PTR, const char *, unsigned long, bfd_vma)); + +static const struct debug_write_fns pr_fns = +{ + pr_start_compilation_unit, + pr_start_source, + pr_empty_type, + pr_void_type, + pr_int_type, + pr_float_type, + pr_complex_type, + pr_bool_type, + pr_enum_type, + pr_pointer_type, + pr_function_type, + pr_reference_type, + pr_range_type, + pr_array_type, + pr_set_type, + pr_offset_type, + pr_method_type, + pr_const_type, + pr_volatile_type, + pr_start_struct_type, + pr_struct_field, + pr_end_struct_type, + pr_start_class_type, + pr_class_static_member, + pr_class_baseclass, + pr_class_start_method, + pr_class_method_variant, + pr_class_static_method_variant, + pr_class_end_method, + pr_end_class_type, + pr_typedef_type, + pr_tag_type, + pr_typdef, + pr_tag, + pr_int_constant, + pr_float_constant, + pr_typed_constant, + pr_variable, + pr_start_function, + pr_function_parameter, + pr_start_block, + pr_end_block, + pr_end_function, + pr_lineno +}; + +/* Print out the generic debugging information recorded in dhandle. */ + +boolean +print_debugging_info (f, dhandle) + FILE *f; + PTR dhandle; +{ + struct pr_handle info; + + info.f = f; + info.indent = 0; + info.stack = NULL; + info.parameter = 0; + + return debug_write (dhandle, &pr_fns, (PTR) &info); +} + +/* Indent to the current indentation level. */ + +static void +indent (info) + struct pr_handle *info; +{ + unsigned int i; + + for (i = 0; i < info->indent; i++) + putc (' ', info->f); +} + +/* Push a type on the type stack. */ + +static boolean +push_type (info, type) + struct pr_handle *info; + const char *type; +{ + struct pr_stack *n; + + if (type == NULL) + return false; + + n = (struct pr_stack *) xmalloc (sizeof *n); + memset (n, 0, sizeof *n); + + n->type = xstrdup (type); + n->visibility = DEBUG_VISIBILITY_IGNORE; + n->method = NULL; + n->next = info->stack; + info->stack = n; + + return true; +} + +/* Prepend a string onto the type on the top of the type stack. */ + +static boolean +prepend_type (info, s) + struct pr_handle *info; + const char *s; +{ + char *n; + + assert (info->stack != NULL); + + n = (char *) xmalloc (strlen (s) + strlen (info->stack->type) + 1); + sprintf (n, "%s%s", s, info->stack->type); + free (info->stack->type); + info->stack->type = n; + + return true; +} + +/* Append a string to the type on the top of the type stack. */ + +static boolean +append_type (info, s) + struct pr_handle *info; + const char *s; +{ + unsigned int len; + + if (s == NULL) + return false; + + assert (info->stack != NULL); + + len = strlen (info->stack->type); + info->stack->type = (char *) xrealloc (info->stack->type, + len + strlen (s) + 1); + strcpy (info->stack->type + len, s); + + return true; +} + +/* We use an underscore to indicate where the name should go in a type + string. This function substitutes a string for the underscore. If + there is no underscore, the name follows the type. */ + +static boolean +substitute_type (info, s) + struct pr_handle *info; + const char *s; +{ + char *u; + + assert (info->stack != NULL); + + u = strchr (info->stack->type, '|'); + if (u != NULL) + { + char *n; + + n = (char *) xmalloc (strlen (info->stack->type) + strlen (s)); + + memcpy (n, info->stack->type, u - info->stack->type); + strcpy (n + (u - info->stack->type), s); + strcat (n, u + 1); + + free (info->stack->type); + info->stack->type = n; + + return true; + } + + if (strchr (s, '|') != NULL + && (strchr (info->stack->type, '{') != NULL + || strchr (info->stack->type, '(') != NULL)) + { + if (! prepend_type (info, "(") + || ! append_type (info, ")")) + return false; + } + + if (*s == '\0') + return true; + + return (append_type (info, " ") + && append_type (info, s)); +} + +/* Indent the type at the top of the stack by appending spaces. */ + +static boolean +indent_type (info) + struct pr_handle *info; +{ + unsigned int i; + + for (i = 0; i < info->indent; i++) + { + if (! append_type (info, " ")) + return false; + } + + return true; +} + +/* Pop a type from the type stack. */ + +static char * +pop_type (info) + struct pr_handle *info; +{ + struct pr_stack *o; + char *ret; + + assert (info->stack != NULL); + + o = info->stack; + info->stack = o->next; + ret = o->type; + free (o); + + return ret; +} + +/* Print a VMA value into a string. */ + +static void +print_vma (vma, buf, unsignedp, hexp) + bfd_vma vma; + char *buf; + boolean unsignedp; + boolean hexp; +{ + if (sizeof (vma) <= sizeof (unsigned long)) + { + if (hexp) + sprintf (buf, "0x%lx", (unsigned long) vma); + else if (unsignedp) + sprintf (buf, "%lu", (unsigned long) vma); + else + sprintf (buf, "%ld", (long) vma); + } + else + { + buf[0] = '0'; + buf[1] = 'x'; + sprintf_vma (buf + 2, vma); + } +} + +/* Start a new compilation unit. */ + +static boolean +pr_start_compilation_unit (p, filename) + PTR p; + const char *filename; +{ + struct pr_handle *info = (struct pr_handle *) p; + + assert (info->indent == 0); + + fprintf (info->f, "%s:\n", filename); + + return true; +} + +/* Start a source file within a compilation unit. */ + +static boolean +pr_start_source (p, filename) + PTR p; + const char *filename; +{ + struct pr_handle *info = (struct pr_handle *) p; + + assert (info->indent == 0); + + fprintf (info->f, " %s:\n", filename); + + return true; +} + +/* Push an empty type onto the type stack. */ + +static boolean +pr_empty_type (p) + PTR p; +{ + struct pr_handle *info = (struct pr_handle *) p; + + return push_type (info, "<undefined>"); +} + +/* Push a void type onto the type stack. */ + +static boolean +pr_void_type (p) + PTR p; +{ + struct pr_handle *info = (struct pr_handle *) p; + + return push_type (info, "void"); +} + +/* Push an integer type onto the type stack. */ + +static boolean +pr_int_type (p, size, unsignedp) + PTR p; + unsigned int size; + boolean unsignedp; +{ + struct pr_handle *info = (struct pr_handle *) p; + char ab[10]; + + sprintf (ab, "%sint%d", unsignedp ? "u" : "", size * 8); + return push_type (info, ab); +} + +/* Push a floating type onto the type stack. */ + +static boolean +pr_float_type (p, size) + PTR p; + unsigned int size; +{ + struct pr_handle *info = (struct pr_handle *) p; + char ab[10]; + + if (size == 4) + return push_type (info, "float"); + else if (size == 8) + return push_type (info, "double"); + + sprintf (ab, "float%d", size * 8); + return push_type (info, ab); +} + +/* Push a complex type onto the type stack. */ + +static boolean +pr_complex_type (p, size) + PTR p; + unsigned int size; +{ + struct pr_handle *info = (struct pr_handle *) p; + + if (! pr_float_type (p, size)) + return false; + + return prepend_type (info, "complex "); +} + +/* Push a boolean type onto the type stack. */ + +static boolean +pr_bool_type (p, size) + PTR p; + unsigned int size; +{ + struct pr_handle *info = (struct pr_handle *) p; + char ab[10]; + + sprintf (ab, "bool%d", size * 8); + + return push_type (info, ab); +} + +/* Push an enum type onto the type stack. */ + +static boolean +pr_enum_type (p, tag, names, values) + PTR p; + const char *tag; + const char **names; + bfd_signed_vma *values; +{ + struct pr_handle *info = (struct pr_handle *) p; + unsigned int i; + bfd_signed_vma val; + + if (! push_type (info, "enum ")) + return false; + if (tag != NULL) + { + if (! append_type (info, tag) + || ! append_type (info, " ")) + return false; + } + if (! append_type (info, "{ ")) + return false; + + if (names == NULL) + { + if (! append_type (info, "/* undefined */")) + return false; + } + else + { + val = 0; + for (i = 0; names[i] != NULL; i++) + { + if (i > 0) + { + if (! append_type (info, ", ")) + return false; + } + + if (! append_type (info, names[i])) + return false; + + if (values[i] != val) + { + char ab[20]; + + print_vma (values[i], ab, false, false); + if (! append_type (info, " = ") + || ! append_type (info, ab)) + return false; + val = values[i]; + } + + ++val; + } + } + + return append_type (info, " }"); +} + +/* Turn the top type on the stack into a pointer. */ + +static boolean +pr_pointer_type (p) + PTR p; +{ + struct pr_handle *info = (struct pr_handle *) p; + char *s; + + assert (info->stack != NULL); + + s = strchr (info->stack->type, '|'); + if (s != NULL && s[1] == '[') + return substitute_type (info, "(*|)"); + return substitute_type (info, "*|"); +} + +/* Turn the top type on the stack into a function returning that type. */ + +static boolean +pr_function_type (p, argcount, varargs) + PTR p; + int argcount; + boolean varargs; +{ + struct pr_handle *info = (struct pr_handle *) p; + char **arg_types; + unsigned int len; + char *s; + + assert (info->stack != NULL); + + len = 10; + + if (argcount <= 0) + { + arg_types = NULL; + len += 15; + } + else + { + int i; + + arg_types = (char **) xmalloc (argcount * sizeof *arg_types); + for (i = argcount - 1; i >= 0; i--) + { + if (! substitute_type (info, "")) + return false; + arg_types[i] = pop_type (info); + if (arg_types[i] == NULL) + return false; + len += strlen (arg_types[i]) + 2; + } + if (varargs) + len += 5; + } + + /* Now the return type is on the top of the stack. */ + + s = (char *) xmalloc (len); + strcpy (s, "(|) ("); + + if (argcount < 0) + strcat (s, "/* unknown */"); + else + { + int i; + + for (i = 0; i < argcount; i++) + { + if (i > 0) + strcat (s, ", "); + strcat (s, arg_types[i]); + } + if (varargs) + { + if (i > 0) + strcat (s, ", "); + strcat (s, "..."); + } + if (argcount > 0) + free (arg_types); + } + + strcat (s, ")"); + + if (! substitute_type (info, s)) + return false; + + free (s); + + return true; +} + +/* Turn the top type on the stack into a reference to that type. */ + +static boolean +pr_reference_type (p) + PTR p; +{ + struct pr_handle *info = (struct pr_handle *) p; + + assert (info->stack != NULL); + + return substitute_type (info, "&|"); +} + +/* Make a range type. */ + +static boolean +pr_range_type (p, lower, upper) + PTR p; + bfd_signed_vma lower; + bfd_signed_vma upper; +{ + struct pr_handle *info = (struct pr_handle *) p; + char abl[20], abu[20]; + + assert (info->stack != NULL); + + if (! substitute_type (info, "")) + return false; + + print_vma (lower, abl, false, false); + print_vma (upper, abu, false, false); + + return (prepend_type (info, "range (") + && append_type (info, "):") + && append_type (info, abl) + && append_type (info, ":") + && append_type (info, abu)); +} + +/* Make an array type. */ + +/*ARGSUSED*/ +static boolean +pr_array_type (p, lower, upper, stringp) + PTR p; + bfd_signed_vma lower; + bfd_signed_vma upper; + boolean stringp; +{ + struct pr_handle *info = (struct pr_handle *) p; + char *range_type; + char abl[20], abu[20], ab[50]; + + range_type = pop_type (info); + if (range_type == NULL) + return false; + + if (lower == 0) + { + if (upper == -1) + sprintf (ab, "|[]"); + else + { + print_vma (upper + 1, abu, false, false); + sprintf (ab, "|[%s]", abu); + } + } + else + { + print_vma (lower, abl, false, false); + print_vma (upper, abu, false, false); + sprintf (ab, "|[%s:%s]", abl, abu); + } + + if (! substitute_type (info, ab)) + return false; + + if (strcmp (range_type, "int") != 0) + { + if (! append_type (info, ":") + || ! append_type (info, range_type)) + return false; + } + + if (stringp) + { + if (! append_type (info, " /* string */")) + return false; + } + + return true; +} + +/* Make a set type. */ + +/*ARGSUSED*/ +static boolean +pr_set_type (p, bitstringp) + PTR p; + boolean bitstringp; +{ + struct pr_handle *info = (struct pr_handle *) p; + + if (! substitute_type (info, "")) + return false; + + if (! prepend_type (info, "set { ") + || ! append_type (info, " }")) + return false; + + if (bitstringp) + { + if (! append_type (info, "/* bitstring */")) + return false; + } + + return true; +} + +/* Make an offset type. */ + +static boolean +pr_offset_type (p) + PTR p; +{ + struct pr_handle *info = (struct pr_handle *) p; + char *t; + + if (! substitute_type (info, "")) + return false; + + t = pop_type (info); + if (t == NULL) + return false; + + return (substitute_type (info, "") + && prepend_type (info, " ") + && prepend_type (info, t) + && append_type (info, "::|")); +} + +/* Make a method type. */ + +static boolean +pr_method_type (p, domain, argcount, varargs) + PTR p; + boolean domain; + int argcount; + boolean varargs; +{ + struct pr_handle *info = (struct pr_handle *) p; + unsigned int len; + char *domain_type; + char **arg_types; + char *s; + + len = 10; + + if (! domain) + domain_type = NULL; + else + { + if (! substitute_type (info, "")) + return false; + domain_type = pop_type (info); + if (domain_type == NULL) + return false; + if (strncmp (domain_type, "class ", sizeof "class " - 1) == 0 + && strchr (domain_type + sizeof "class " - 1, ' ') == NULL) + domain_type += sizeof "class " - 1; + else if (strncmp (domain_type, "union class ", + sizeof "union class ") == 0 + && (strchr (domain_type + sizeof "union class " - 1, ' ') + == NULL)) + domain_type += sizeof "union class " - 1; + len += strlen (domain_type); + } + + if (argcount <= 0) + { + arg_types = NULL; + len += 15; + } + else + { + int i; + + arg_types = (char **) xmalloc (argcount * sizeof *arg_types); + for (i = argcount - 1; i >= 0; i--) + { + if (! substitute_type (info, "")) + return false; + arg_types[i] = pop_type (info); + if (arg_types[i] == NULL) + return false; + len += strlen (arg_types[i]) + 2; + } + if (varargs) + len += 5; + } + + /* Now the return type is on the top of the stack. */ + + s = (char *) xmalloc (len); + if (! domain) + *s = '\0'; + else + strcpy (s, domain_type); + strcat (s, "::| ("); + + if (argcount < 0) + strcat (s, "/* unknown */"); + else + { + int i; + + for (i = 0; i < argcount; i++) + { + if (i > 0) + strcat (s, ", "); + strcat (s, arg_types[i]); + } + if (varargs) + { + if (i > 0) + strcat (s, ", "); + strcat (s, "..."); + } + if (argcount > 0) + free (arg_types); + } + + strcat (s, ")"); + + if (! substitute_type (info, s)) + return false; + + free (s); + + return true; +} + +/* Make a const qualified type. */ + +static boolean +pr_const_type (p) + PTR p; +{ + struct pr_handle *info = (struct pr_handle *) p; + + return substitute_type (info, "const |"); +} + +/* Make a volatile qualified type. */ + +static boolean +pr_volatile_type (p) + PTR p; +{ + struct pr_handle *info = (struct pr_handle *) p; + + return substitute_type (info, "volatile |"); +} + +/* Start accumulating a struct type. */ + +static boolean +pr_start_struct_type (p, tag, id, structp, size) + PTR p; + const char *tag; + unsigned int id; + boolean structp; + unsigned int size; +{ + struct pr_handle *info = (struct pr_handle *) p; + + info->indent += 2; + + if (! push_type (info, structp ? "struct " : "union ")) + return false; + if (tag != NULL) + { + if (! append_type (info, tag)) + return false; + } + else + { + char idbuf[20]; + + sprintf (idbuf, "%%anon%u", id); + if (! append_type (info, idbuf)) + return false; + } + + if (! append_type (info, " {")) + return false; + if (size != 0 || tag != NULL) + { + char ab[30]; + + if (! append_type (info, " /*")) + return false; + + if (size != 0) + { + sprintf (ab, " size %u", size); + if (! append_type (info, ab)) + return false; + } + if (tag != NULL) + { + sprintf (ab, " id %u", id); + if (! append_type (info, ab)) + return false; + } + if (! append_type (info, " */")) + return false; + } + if (! append_type (info, "\n")) + return false; + + info->stack->visibility = DEBUG_VISIBILITY_PUBLIC; + + return indent_type (info); +} + +/* Output the visibility of a field in a struct. */ + +static boolean +pr_fix_visibility (info, visibility) + struct pr_handle *info; + enum debug_visibility visibility; +{ + const char *s; + char *t; + unsigned int len; + + assert (info->stack != NULL); + + if (info->stack->visibility == visibility) + return true; + + assert (info->stack->visibility != DEBUG_VISIBILITY_IGNORE); + + switch (visibility) + { + case DEBUG_VISIBILITY_PUBLIC: + s = "public"; + break; + case DEBUG_VISIBILITY_PRIVATE: + s = "private"; + break; + case DEBUG_VISIBILITY_PROTECTED: + s = "protected"; + break; + case DEBUG_VISIBILITY_IGNORE: + s = "/* ignore */"; + break; + default: + abort (); + return false; + } + + /* Trim off a trailing space in the struct string, to make the + output look a bit better, then stick on the visibility string. */ + + t = info->stack->type; + len = strlen (t); + assert (t[len - 1] == ' '); + t[len - 1] = '\0'; + + if (! append_type (info, s) + || ! append_type (info, ":\n") + || ! indent_type (info)) + return false; + + info->stack->visibility = visibility; + + return true; +} + +/* Add a field to a struct type. */ + +static boolean +pr_struct_field (p, name, bitpos, bitsize, visibility) + PTR p; + const char *name; + bfd_vma bitpos; + bfd_vma bitsize; + enum debug_visibility visibility; +{ + struct pr_handle *info = (struct pr_handle *) p; + char ab[20]; + char *t; + + if (! substitute_type (info, name)) + return false; + + if (! append_type (info, "; /* ")) + return false; + + if (bitsize != 0) + { + print_vma (bitsize, ab, true, false); + if (! append_type (info, "bitsize ") + || ! append_type (info, ab) + || ! append_type (info, ", ")) + return false; + } + + print_vma (bitpos, ab, true, false); + if (! append_type (info, "bitpos ") + || ! append_type (info, ab) + || ! append_type (info, " */\n") + || ! indent_type (info)) + return false; + + t = pop_type (info); + if (t == NULL) + return false; + + if (! pr_fix_visibility (info, visibility)) + return false; + + return append_type (info, t); +} + +/* Finish a struct type. */ + +static boolean +pr_end_struct_type (p) + PTR p; +{ + struct pr_handle *info = (struct pr_handle *) p; + char *s; + + assert (info->stack != NULL); + assert (info->indent >= 2); + + info->indent -= 2; + + /* Change the trailing indentation to have a close brace. */ + s = info->stack->type + strlen (info->stack->type) - 2; + assert (s[0] == ' ' && s[1] == ' ' && s[2] == '\0'); + + *s++ = '}'; + *s = '\0'; + + return true; +} + +/* Start a class type. */ + +static boolean +pr_start_class_type (p, tag, id, structp, size, vptr, ownvptr) + PTR p; + const char *tag; + unsigned int id; + boolean structp; + unsigned int size; + boolean vptr; + boolean ownvptr; +{ + struct pr_handle *info = (struct pr_handle *) p; + char *tv = NULL; + + info->indent += 2; + + if (vptr && ! ownvptr) + { + tv = pop_type (info); + if (tv == NULL) + return false; + } + + if (! push_type (info, structp ? "class " : "union class ")) + return false; + if (tag != NULL) + { + if (! append_type (info, tag)) + return false; + } + else + { + char idbuf[20]; + + sprintf (idbuf, "%%anon%u", id); + if (! append_type (info, idbuf)) + return false; + } + + if (! append_type (info, " {")) + return false; + if (size != 0 || vptr || ownvptr || tag != NULL) + { + if (! append_type (info, " /*")) + return false; + + if (size != 0) + { + char ab[20]; + + sprintf (ab, "%u", size); + if (! append_type (info, " size ") + || ! append_type (info, ab)) + return false; + } + + if (vptr) + { + if (! append_type (info, " vtable ")) + return false; + if (ownvptr) + { + if (! append_type (info, "self ")) + return false; + } + else + { + if (! append_type (info, tv) + || ! append_type (info, " ")) + return false; + } + } + + if (tag != NULL) + { + char ab[30]; + + sprintf (ab, " id %u", id); + if (! append_type (info, ab)) + return false; + } + + if (! append_type (info, " */")) + return false; + } + + info->stack->visibility = DEBUG_VISIBILITY_PRIVATE; + + return (append_type (info, "\n") + && indent_type (info)); +} + +/* Add a static member to a class. */ + +static boolean +pr_class_static_member (p, name, physname, visibility) + PTR p; + const char *name; + const char *physname; + enum debug_visibility visibility; +{ + struct pr_handle *info = (struct pr_handle *) p; + char *t; + + if (! substitute_type (info, name)) + return false; + + if (! prepend_type (info, "static ") + || ! append_type (info, "; /* ") + || ! append_type (info, physname) + || ! append_type (info, " */\n") + || ! indent_type (info)) + return false; + + t = pop_type (info); + if (t == NULL) + return false; + + if (! pr_fix_visibility (info, visibility)) + return false; + + return append_type (info, t); +} + +/* Add a base class to a class. */ + +static boolean +pr_class_baseclass (p, bitpos, virtual, visibility) + PTR p; + bfd_vma bitpos; + boolean virtual; + enum debug_visibility visibility; +{ + struct pr_handle *info = (struct pr_handle *) p; + char *t; + const char *prefix; + char ab[20]; + char *s, *l, *n; + + assert (info->stack != NULL && info->stack->next != NULL); + + if (! substitute_type (info, "")) + return false; + + t = pop_type (info); + if (t == NULL) + return false; + + if (strncmp (t, "class ", sizeof "class " - 1) == 0) + t += sizeof "class " - 1; + + /* Push it back on to take advantage of the prepend_type and + append_type routines. */ + if (! push_type (info, t)) + return false; + + if (virtual) + { + if (! prepend_type (info, "virtual ")) + return false; + } + + switch (visibility) + { + case DEBUG_VISIBILITY_PUBLIC: + prefix = "public "; + break; + case DEBUG_VISIBILITY_PROTECTED: + prefix = "protected "; + break; + case DEBUG_VISIBILITY_PRIVATE: + prefix = "private "; + break; + default: + prefix = "/* unknown visibility */ "; + break; + } + + if (! prepend_type (info, prefix)) + return false; + + if (bitpos != 0) + { + print_vma (bitpos, ab, true, false); + if (! append_type (info, " /* bitpos ") + || ! append_type (info, ab) + || ! append_type (info, " */")) + return false; + } + + /* Now the top of the stack is something like "public A / * bitpos + 10 * /". The next element on the stack is something like "class + xx { / * size 8 * /\n...". We want to substitute the top of the + stack in before the {. */ + s = strchr (info->stack->next->type, '{'); + assert (s != NULL); + --s; + + /* If there is already a ':', then we already have a baseclass, and + we must append this one after a comma. */ + for (l = info->stack->next->type; l != s; l++) + if (*l == ':') + break; + if (! prepend_type (info, l == s ? " : " : ", ")) + return false; + + t = pop_type (info); + if (t == NULL) + return false; + + n = (char *) xmalloc (strlen (info->stack->type) + strlen (t) + 1); + memcpy (n, info->stack->type, s - info->stack->type); + strcpy (n + (s - info->stack->type), t); + strcat (n, s); + + free (info->stack->type); + info->stack->type = n; + + free (t); + + return true; +} + +/* Start adding a method to a class. */ + +static boolean +pr_class_start_method (p, name) + PTR p; + const char *name; +{ + struct pr_handle *info = (struct pr_handle *) p; + + assert (info->stack != NULL); + info->stack->method = name; + return true; +} + +/* Add a variant to a method. */ + +static boolean +pr_class_method_variant (p, physname, visibility, constp, volatilep, voffset, + context) + PTR p; + const char *physname; + enum debug_visibility visibility; + boolean constp; + boolean volatilep; + bfd_vma voffset; + boolean context; +{ + struct pr_handle *info = (struct pr_handle *) p; + char *method_type; + char *context_type; + + assert (info->stack != NULL); + assert (info->stack->next != NULL); + + /* Put the const and volatile qualifiers on the type. */ + if (volatilep) + { + if (! append_type (info, " volatile")) + return false; + } + if (constp) + { + if (! append_type (info, " const")) + return false; + } + + /* Stick the name of the method into its type. */ + if (! substitute_type (info, + (context + ? info->stack->next->next->method + : info->stack->next->method))) + return false; + + /* Get the type. */ + method_type = pop_type (info); + if (method_type == NULL) + return false; + + /* Pull off the context type if there is one. */ + if (! context) + context_type = NULL; + else + { + context_type = pop_type (info); + if (context_type == NULL) + return false; + } + + /* Now the top of the stack is the class. */ + + if (! pr_fix_visibility (info, visibility)) + return false; + + if (! append_type (info, method_type) + || ! append_type (info, " /* ") + || ! append_type (info, physname) + || ! append_type (info, " ")) + return false; + if (context || voffset != 0) + { + char ab[20]; + + if (context) + { + if (! append_type (info, "context ") + || ! append_type (info, context_type) + || ! append_type (info, " ")) + return false; + } + print_vma (voffset, ab, true, false); + if (! append_type (info, "voffset ") + || ! append_type (info, ab)) + return false; + } + + return (append_type (info, " */;\n") + && indent_type (info)); +} + +/* Add a static variant to a method. */ + +static boolean +pr_class_static_method_variant (p, physname, visibility, constp, volatilep) + PTR p; + const char *physname; + enum debug_visibility visibility; + boolean constp; + boolean volatilep; +{ + struct pr_handle *info = (struct pr_handle *) p; + char *method_type; + + assert (info->stack != NULL); + assert (info->stack->next != NULL); + assert (info->stack->next->method != NULL); + + /* Put the const and volatile qualifiers on the type. */ + if (volatilep) + { + if (! append_type (info, " volatile")) + return false; + } + if (constp) + { + if (! append_type (info, " const")) + return false; + } + + /* Mark it as static. */ + if (! prepend_type (info, "static ")) + return false; + + /* Stick the name of the method into its type. */ + if (! substitute_type (info, info->stack->next->method)) + return false; + + /* Get the type. */ + method_type = pop_type (info); + if (method_type == NULL) + return false; + + /* Now the top of the stack is the class. */ + + if (! pr_fix_visibility (info, visibility)) + return false; + + return (append_type (info, method_type) + && append_type (info, " /* ") + && append_type (info, physname) + && append_type (info, " */;\n") + && indent_type (info)); +} + +/* Finish up a method. */ + +static boolean +pr_class_end_method (p) + PTR p; +{ + struct pr_handle *info = (struct pr_handle *) p; + + info->stack->method = NULL; + return true; +} + +/* Finish up a class. */ + +static boolean +pr_end_class_type (p) + PTR p; +{ + return pr_end_struct_type (p); +} + +/* Push a type on the stack using a typedef name. */ + +static boolean +pr_typedef_type (p, name) + PTR p; + const char *name; +{ + struct pr_handle *info = (struct pr_handle *) p; + + return push_type (info, name); +} + +/* Push a type on the stack using a tag name. */ + +static boolean +pr_tag_type (p, name, id, kind) + PTR p; + const char *name; + unsigned int id; + enum debug_type_kind kind; +{ + struct pr_handle *info = (struct pr_handle *) p; + const char *t, *tag; + char idbuf[20]; + + switch (kind) + { + case DEBUG_KIND_STRUCT: + t = "struct "; + break; + case DEBUG_KIND_UNION: + t = "union "; + break; + case DEBUG_KIND_ENUM: + t = "enum "; + break; + case DEBUG_KIND_CLASS: + t = "class "; + break; + case DEBUG_KIND_UNION_CLASS: + t = "union class "; + break; + default: + abort (); + return false; + } + + if (! push_type (info, t)) + return false; + if (name != NULL) + tag = name; + else + { + sprintf (idbuf, "%%anon%u", id); + tag = idbuf; + } + + if (! append_type (info, tag)) + return false; + if (name != NULL && kind != DEBUG_KIND_ENUM) + { + sprintf (idbuf, " /* id %u */", id); + if (! append_type (info, idbuf)) + return false; + } + + return true; +} + +/* Output a typedef. */ + +static boolean +pr_typdef (p, name) + PTR p; + const char *name; +{ + struct pr_handle *info = (struct pr_handle *) p; + char *s; + + if (! substitute_type (info, name)) + return false; + + s = pop_type (info); + if (s == NULL) + return false; + + indent (info); + fprintf (info->f, "typedef %s;\n", s); + + free (s); + + return true; +} + +/* Output a tag. The tag should already be in the string on the + stack, so all we have to do here is print it out. */ + +/*ARGSUSED*/ +static boolean +pr_tag (p, name) + PTR p; + const char *name; +{ + struct pr_handle *info = (struct pr_handle *) p; + char *t; + + t = pop_type (info); + if (t == NULL) + return false; + + indent (info); + fprintf (info->f, "%s;\n", t); + + free (t); + + return true; +} + +/* Output an integer constant. */ + +static boolean +pr_int_constant (p, name, val) + PTR p; + const char *name; + bfd_vma val; +{ + struct pr_handle *info = (struct pr_handle *) p; + char ab[20]; + + indent (info); + print_vma (val, ab, false, false); + fprintf (info->f, "const int %s = %s;\n", name, ab); + return true; +} + +/* Output a floating point constant. */ + +static boolean +pr_float_constant (p, name, val) + PTR p; + const char *name; + double val; +{ + struct pr_handle *info = (struct pr_handle *) p; + + indent (info); + fprintf (info->f, "const double %s = %g;\n", name, val); + return true; +} + +/* Output a typed constant. */ + +static boolean +pr_typed_constant (p, name, val) + PTR p; + const char *name; + bfd_vma val; +{ + struct pr_handle *info = (struct pr_handle *) p; + char *t; + char ab[20]; + + t = pop_type (info); + if (t == NULL) + return false; + + indent (info); + print_vma (val, ab, false, false); + fprintf (info->f, "const %s %s = %s;\n", t, name, ab); + + free (t); + + return true; +} + +/* Output a variable. */ + +static boolean +pr_variable (p, name, kind, val) + PTR p; + const char *name; + enum debug_var_kind kind; + bfd_vma val; +{ + struct pr_handle *info = (struct pr_handle *) p; + char *t; + char ab[20]; + + if (! substitute_type (info, name)) + return false; + + t = pop_type (info); + if (t == NULL) + return false; + + indent (info); + switch (kind) + { + case DEBUG_STATIC: + case DEBUG_LOCAL_STATIC: + fprintf (info->f, "static "); + break; + case DEBUG_REGISTER: + fprintf (info->f, "register "); + break; + default: + break; + } + print_vma (val, ab, true, true); + fprintf (info->f, "%s /* %s */;\n", t, ab); + + free (t); + + return true; +} + +/* Start outputting a function. */ + +static boolean +pr_start_function (p, name, global) + PTR p; + const char *name; + boolean global; +{ + struct pr_handle *info = (struct pr_handle *) p; + char *t; + + if (! substitute_type (info, name)) + return false; + + t = pop_type (info); + if (t == NULL) + return false; + + indent (info); + if (! global) + fprintf (info->f, "static "); + fprintf (info->f, "%s (", t); + + info->parameter = 1; + + return true; +} + +/* Output a function parameter. */ + +static boolean +pr_function_parameter (p, name, kind, val) + PTR p; + const char *name; + enum debug_parm_kind kind; + bfd_vma val; +{ + struct pr_handle *info = (struct pr_handle *) p; + char *t; + char ab[20]; + + if (kind == DEBUG_PARM_REFERENCE + || kind == DEBUG_PARM_REF_REG) + { + if (! pr_reference_type (p)) + return false; + } + + if (! substitute_type (info, name)) + return false; + + t = pop_type (info); + if (t == NULL) + return false; + + if (info->parameter != 1) + fprintf (info->f, ", "); + + if (kind == DEBUG_PARM_REG || kind == DEBUG_PARM_REF_REG) + fprintf (info->f, "register "); + + print_vma (val, ab, true, true); + fprintf (info->f, "%s /* %s */", t, ab); + + free (t); + + ++info->parameter; + + return true; +} + +/* Start writing out a block. */ + +static boolean +pr_start_block (p, addr) + PTR p; + bfd_vma addr; +{ + struct pr_handle *info = (struct pr_handle *) p; + char ab[20]; + + if (info->parameter > 0) + { + fprintf (info->f, ")\n"); + info->parameter = 0; + } + + indent (info); + print_vma (addr, ab, true, true); + fprintf (info->f, "{ /* %s */\n", ab); + + info->indent += 2; + + return true; +} + +/* Write out line number information. */ + +static boolean +pr_lineno (p, filename, lineno, addr) + PTR p; + const char *filename; + unsigned long lineno; + bfd_vma addr; +{ + struct pr_handle *info = (struct pr_handle *) p; + char ab[20]; + + indent (info); + print_vma (addr, ab, true, true); + fprintf (info->f, "/* file %s line %lu addr %s */\n", filename, lineno, ab); + + return true; +} + +/* Finish writing out a block. */ + +static boolean +pr_end_block (p, addr) + PTR p; + bfd_vma addr; +{ + struct pr_handle *info = (struct pr_handle *) p; + char ab[20]; + + info->indent -= 2; + + indent (info); + print_vma (addr, ab, true, true); + fprintf (info->f, "} /* %s */\n", ab); + + return true; +} + +/* Finish writing out a function. */ + +/*ARGSUSED*/ +static boolean +pr_end_function (p) + PTR p; +{ + return true; +} diff --git a/binutils/ranlib.1 b/binutils/ranlib.1 new file mode 100644 index 0000000..7efb5c8 --- /dev/null +++ b/binutils/ranlib.1 @@ -0,0 +1,83 @@ +.\" Copyright (c) 1991 Free Software Foundation +.\" See section COPYING for conditions for redistribution +.TH ranlib 1 "5 November 1991" "cygnus support" "GNU Development Tools" +.de BP +.sp +.ti \-.2i +\(** +.. + +.SH NAME +ranlib \- generate index to archive. + +.SH SYNOPSIS +.hy 0 +.na +.B ranlib \c +.RB "[\|" \-v | \-V "\|]" +.I archive\c +\& +.ad b +.hy 1 +.SH DESCRIPTION +.B ranlib +generates an index to the contents of an archive, and +stores it in the archive. The index lists each symbol defined by a +member of an archive that is a relocatable object file. +.PP +You may use +.RB ` "nm \-s" ' +or +.RB ` "nm \-\-print-armap" ' +to list this index. +.PP +An archive with such an index speeds up linking to the library, and +allows routines in the library to call each other without regard to +their placement in the archive. +.PP +The GNU +.B ranlib +program is another form of GNU +.BR ar ; +running +.B ranlib +is completely equivalent to executing +.RB ` "ar \-s" '. + +.SH OPTIONS +.TP +.B \-v +Print the version number of +.B ranlib +and exit. + +.SH "SEE ALSO" +.RB "`\|" binutils "\|'" +entry in +.B +info\c +\&; +.I +The GNU Binary Utilities\c +\&, Roland H. Pesch (October 1991); +.BR ar "(" 1 ")," +.BR nm "(" 1 ")." + + +.SH COPYING +Copyright (c) 1991 Free Software Foundation, Inc. +.PP +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. +.PP +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the +entire resulting derived work is distributed under the terms of a +permission notice identical to this one. +.PP +Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be included in +translations approved by the Free Software Foundation instead of in +the original English. diff --git a/binutils/ranlib.sh b/binutils/ranlib.sh new file mode 100755 index 0000000..2b6fbc4 --- /dev/null +++ b/binutils/ranlib.sh @@ -0,0 +1,3 @@ +#!/bin/sh +# A simple ranlib script, to use less disk space than a ranlib program. +ar s $1 diff --git a/binutils/rclex.l b/binutils/rclex.l new file mode 100644 index 0000000..06a6607 --- /dev/null +++ b/binutils/rclex.l @@ -0,0 +1,465 @@ +%{ /* rclex.l -- lexer for Windows rc files parser */ +/* Copyright 1997, 1998 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Cygnus Support. + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* This is a lex input file which generates a lexer used by the + Windows rc file parser. It basically just recognized a bunch of + keywords. */ + +#include "bfd.h" +#include "bucomm.h" +#include "libiberty.h" +#include "windres.h" +#include "rcparse.h" + +#include <ctype.h> +#include <assert.h> + +/* Whether we are in rcdata mode, in which we returns the lengths of + strings. */ + +static int rcdata_mode; + +/* List of allocated strings. */ + +struct alloc_string +{ + struct alloc_string *next; + char *s; +}; + +static struct alloc_string *strings; + +/* Local functions. */ + +static void cpp_line PARAMS ((const char *)); +static char *handle_quotes PARAMS ((const char *, unsigned long *)); +static char *get_string PARAMS ((int)); + +%} + +%% + +"BEGIN" { return BEG; } +"{" { return BEG; } +"END" { return END; } +"}" { return END; } +"ACCELERATORS" { return ACCELERATORS; } +"VIRTKEY" { return VIRTKEY; } +"ASCII" { return ASCII; } +"NOINVERT" { return NOINVERT; } +"SHIFT" { return SHIFT; } +"CONTROL" { return CONTROL; } +"ALT" { return ALT; } +"BITMAP" { return BITMAP; } +"CURSOR" { return CURSOR; } +"DIALOG" { return DIALOG; } +"DIALOGEX" { return DIALOGEX; } +"EXSTYLE" { return EXSTYLE; } +"CAPTION" { return CAPTION; } +"CLASS" { return CLASS; } +"STYLE" { return STYLE; } +"AUTO3STATE" { return AUTO3STATE; } +"AUTOCHECKBOX" { return AUTOCHECKBOX; } +"AUTORADIOBUTTON" { return AUTORADIOBUTTON; } +"CHECKBOX" { return CHECKBOX; } +"COMBOBOX" { return COMBOBOX; } +"CTEXT" { return CTEXT; } +"DEFPUSHBUTTON" { return DEFPUSHBUTTON; } +"EDITTEXT" { return EDITTEXT; } +"GROUPBOX" { return GROUPBOX; } +"LISTBOX" { return LISTBOX; } +"LTEXT" { return LTEXT; } +"PUSHBOX" { return PUSHBOX; } +"PUSHBUTTON" { return PUSHBUTTON; } +"RADIOBUTTON" { return RADIOBUTTON; } +"RTEXT" { return RTEXT; } +"SCROLLBAR" { return SCROLLBAR; } +"STATE3" { return STATE3; } +"USERBUTTON" { return USERBUTTON; } +"BEDIT" { return BEDIT; } +"HEDIT" { return HEDIT; } +"IEDIT" { return IEDIT; } +"FONT" { return FONT; } +"ICON" { return ICON; } +"LANGUAGE" { return LANGUAGE; } +"CHARACTERISTICS" { return CHARACTERISTICS; } +"VERSION" { return VERSIONK; } +"MENU" { return MENU; } +"MENUEX" { return MENUEX; } +"MENUITEM" { return MENUITEM; } +"SEPARATOR" { return SEPARATOR; } +"POPUP" { return POPUP; } +"CHECKED" { return CHECKED; } +"GRAYED" { return GRAYED; } +"HELP" { return HELP; } +"INACTIVE" { return INACTIVE; } +"MENUBARBREAK" { return MENUBARBREAK; } +"MENUBREAK" { return MENUBREAK; } +"MESSAGETABLE" { return MESSAGETABLE; } +"RCDATA" { return RCDATA; } +"STRINGTABLE" { return STRINGTABLE; } +"VERSIONINFO" { return VERSIONINFO; } +"FILEVERSION" { return FILEVERSION; } +"PRODUCTVERSION" { return PRODUCTVERSION; } +"FILEFLAGSMASK" { return FILEFLAGSMASK; } +"FILEFLAGS" { return FILEFLAGS; } +"FILEOS" { return FILEOS; } +"FILETYPE" { return FILETYPE; } +"FILESUBTYPE" { return FILESUBTYPE; } +"VALUE" { return VALUE; } +"MOVEABLE" { return MOVEABLE; } +"FIXED" { return FIXED; } +"PURE" { return PURE; } +"IMPURE" { return IMPURE; } +"PRELOAD" { return PRELOAD; } +"LOADONCALL" { return LOADONCALL; } +"DISCARDABLE" { return DISCARDABLE; } +"NOT" { return NOT; } + +"BLOCK"[ \t\n]*"\""[^\#\n]*"\"" { + char *s, *send; + + /* This is a hack to let us parse version + information easily. */ + + s = strchr (yytext, '"'); + ++s; + send = strchr (s, '"'); + if (strncmp (s, "StringFileInfo", + sizeof "StringFileInfo" - 1) == 0 + && s + sizeof "StringFileInfo" - 1 == send) + return BLOCKSTRINGFILEINFO; + else if (strncmp (s, "VarFileInfo", + sizeof "VarFileInfo" - 1) == 0 + && s + sizeof "VarFileInfo" - 1 == send) + return BLOCKVARFILEINFO; + else + { + char *r; + + r = get_string (send - s + 1); + strncpy (r, s, send - s); + r[send - s] = '\0'; + yylval.s = r; + return BLOCK; + } + } + +"#"[^\n]* { + cpp_line (yytext); + } + +[0-9][x0-9A-Fa-f]*L { + yylval.i.val = strtoul (yytext, 0, 0); + yylval.i.dword = 1; + return NUMBER; + } + +[0-9][x0-9A-Fa-f]* { + yylval.i.val = strtoul (yytext, 0, 0); + yylval.i.dword = 0; + return NUMBER; + } + +("\""[^\"\n]*"\""[ \t]*)+ { + char *s; + unsigned long length; + + s = handle_quotes (yytext, &length); + if (! rcdata_mode) + { + yylval.s = s; + return QUOTEDSTRING; + } + else + { + yylval.ss.length = length; + yylval.ss.s = s; + return SIZEDSTRING; + } + } + +[A-Za-z][^ ,\t\r\n]* { + char *s; + + /* I rejected comma in a string in order to + handle VIRTKEY, CONTROL in an accelerator + resource. This means that an unquoted + file name can not contain a comma. I + don't know what rc permits. */ + + s = get_string (strlen (yytext) + 1); + strcpy (s, yytext); + yylval.s = s; + return STRING; + } + +[\n] { ++rc_lineno; } +[ \t\r]+ { /* ignore whitespace */ } +. { return *yytext; } + +%% +#ifndef yywrap +/* This is needed for some versions of lex. */ +int yywrap () +{ + return 1; +} +#endif + +/* Handle a C preprocessor line. */ + +static void +cpp_line (s) + const char *s; +{ + int line; + char *send, *fn; + + ++s; + while (isspace ((unsigned char) *s)) + ++s; + + line = strtol (s, &send, 0); + if (*send != '\0' && ! isspace ((unsigned char) *send)) + return; + + /* Subtract 1 because we are about to count the newline. */ + rc_lineno = line - 1; + + s = send; + while (isspace ((unsigned char) *s)) + ++s; + + if (*s != '"') + return; + + ++s; + send = strchr (s, '"'); + if (send == NULL) + return; + + fn = (char *) xmalloc (send - s + 1); + strncpy (fn, s, send - s); + fn[send - s] = '\0'; + + free (rc_filename); + rc_filename = fn; +} + +/* Handle a quoted string. The quotes are stripped. A pair of quotes + in a string are turned into a single quote. Adjacent strings are + merged separated by whitespace are merged, as in C. */ + +static char * +handle_quotes (input, len) + const char *input; + unsigned long *len; +{ + char *ret, *s; + const char *t; + int ch; + + ret = get_string (strlen (input) + 1); + + s = ret; + t = input; + if (*t == '"') + ++t; + while (*t != '\0') + { + if (*t == '\\') + { + ++t; + switch (*t) + { + case '\0': + rcparse_warning ("backslash at end of string"); + break; + + case '\"': + rcparse_warning ("use \"\" to put \" in a string"); + break; + + case 'a': + *s++ = ESCAPE_A; + ++t; + break; + + case 'b': + *s++ = ESCAPE_B; + ++t; + break; + + case 'f': + *s++ = ESCAPE_F; + ++t; + break; + + case 'n': + *s++ = ESCAPE_N; + ++t; + break; + + case 'r': + *s++ = ESCAPE_R; + ++t; + break; + + case 't': + *s++ = ESCAPE_T; + ++t; + break; + + case 'v': + *s++ = ESCAPE_V; + ++t; + break; + + case '\\': + *s++ = *t++; + break; + + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + ch = *t - '0'; + ++t; + if (*t >= '0' && *t <= '7') + { + ch = (ch << 3) | (*t - '0'); + ++t; + if (*t >= '0' && *t <= '7') + { + ch = (ch << 3) | (*t - '0'); + ++t; + } + } + *s++ = ch; + break; + + case 'x': + ++t; + ch = 0; + while (1) + { + if (*t >= '0' && *t <= '9') + ch = (ch << 4) | (*t - '0'); + else if (*t >= 'a' && *t <= 'f') + ch = (ch << 4) | (*t - 'a'); + else if (*t >= 'A' && *t <= 'F') + ch = (ch << 4) | (*t - 'A'); + else + break; + ++t; + } + *s++ = ch; + break; + + default: + rcparse_warning ("unrecognized escape sequence"); + *s++ = '\\'; + *s++ = *t++; + break; + } + } + else if (*t != '"') + *s++ = *t++; + else if (t[1] == '\0') + break; + else if (t[1] == '"') + { + *s++ = '"'; + t += 2; + } + else + { + ++t; + assert (isspace ((unsigned char) *t)); + while (isspace ((unsigned char) *t)) + ++t; + if (*t == '\0') + break; + assert (*t == '"'); + ++t; + } + } + + *s = '\0'; + + *len = s - ret; + + return ret; +} + +/* Allocate a string of a given length. */ + +static char * +get_string (len) + int len; +{ + struct alloc_string *as; + + as = (struct alloc_string *) xmalloc (sizeof *as); + as->s = xmalloc (len); + + as->next = strings; + strings = as->next; + + return as->s; +} + +/* Discard all the strings we have allocated. The parser calls this + when it no longer needs them. */ + +void +rcparse_discard_strings () +{ + struct alloc_string *as; + + as = strings; + while (as != NULL) + { + struct alloc_string *n; + + free (as->s); + n = as->next; + free (as); + as = n; + } + + strings = NULL; +} + +/* Enter rcdata mode. */ + +void +rcparse_rcdata () +{ + rcdata_mode = 1; +} + +/* Go back to normal mode from rcdata mode. */ + +void +rcparse_normal () +{ + rcdata_mode = 0; +} diff --git a/binutils/rcparse.y b/binutils/rcparse.y new file mode 100644 index 0000000..67079a5 --- /dev/null +++ b/binutils/rcparse.y @@ -0,0 +1,1617 @@ +%{ /* rcparse.y -- parser for Windows rc files + Copyright 1997, 1998 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Cygnus Support. + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* This is a parser for Windows rc files. It is based on the parser + by Gunther Ebert <gunther.ebert@ixos-leipzig.de>. */ + +#include "bfd.h" +#include "bucomm.h" +#include "libiberty.h" +#include "windres.h" + +#include <ctype.h> + +/* The current language. */ + +static unsigned short language; + +/* The resource information during a sub statement. */ + +static struct res_res_info sub_res_info; + +/* Dialog information. This is built by the nonterminals styles and + controls. */ + +static struct dialog dialog; + +/* This is used when building a style. It is modified by the + nonterminal styleexpr. */ + +static unsigned long style; + +/* These are used when building a control. They are set before using + control_params. */ + +static unsigned long base_style; +static unsigned long default_style; +static unsigned long class; + +%} + +%union +{ + struct accelerator acc; + struct accelerator *pacc; + struct dialog_control *dialog_control; + struct menuitem *menuitem; + struct + { + struct rcdata_item *first; + struct rcdata_item *last; + } rcdata; + struct rcdata_item *rcdata_item; + struct stringtable_data *stringtable; + struct fixed_versioninfo *fixver; + struct ver_info *verinfo; + struct ver_stringinfo *verstring; + struct ver_varinfo *vervar; + struct res_id id; + struct res_res_info res_info; + struct + { + unsigned short on; + unsigned short off; + } memflags; + struct + { + unsigned long val; + /* Nonzero if this number was explicitly specified as long. */ + int dword; + } i; + unsigned long il; + unsigned short is; + const char *s; + struct + { + unsigned long length; + const char *s; + } ss; +}; + +%token BEG END +%token ACCELERATORS VIRTKEY ASCII NOINVERT SHIFT CONTROL ALT +%token BITMAP +%token CURSOR +%token DIALOG DIALOGEX EXSTYLE CAPTION CLASS STYLE +%token AUTO3STATE AUTOCHECKBOX AUTORADIOBUTTON CHECKBOX COMBOBOX CTEXT +%token DEFPUSHBUTTON EDITTEXT GROUPBOX LISTBOX LTEXT PUSHBOX PUSHBUTTON +%token RADIOBUTTON RTEXT SCROLLBAR STATE3 USERBUTTON +%token BEDIT HEDIT IEDIT +%token FONT +%token ICON +%token LANGUAGE CHARACTERISTICS VERSIONK +%token MENU MENUEX MENUITEM SEPARATOR POPUP CHECKED GRAYED HELP INACTIVE +%token MENUBARBREAK MENUBREAK +%token MESSAGETABLE +%token RCDATA +%token STRINGTABLE +%token VERSIONINFO FILEVERSION PRODUCTVERSION FILEFLAGSMASK FILEFLAGS +%token FILEOS FILETYPE FILESUBTYPE BLOCKSTRINGFILEINFO BLOCKVARFILEINFO +%token VALUE +%token <s> BLOCK +%token MOVEABLE FIXED PURE IMPURE PRELOAD LOADONCALL DISCARDABLE +%token NOT +%token <s> QUOTEDSTRING STRING +%token <i> NUMBER +%token <ss> SIZEDSTRING + +%type <pacc> acc_entries +%type <acc> acc_entry acc_event +%type <dialog_control> control control_params +%type <menuitem> menuitems menuitem menuexitems menuexitem +%type <rcdata> optrcdata_data optrcdata_data_int rcdata_data +%type <rcdata_item> opt_control_data +%type <fixver> fixedverinfo +%type <verinfo> verblocks +%type <verstring> vervals +%type <vervar> vertrans +%type <res_info> suboptions memflags_move_discard memflags_move +%type <memflags> memflag +%type <id> id +%type <il> exstyle parennumber +%type <il> numexpr posnumexpr cnumexpr optcnumexpr cposnumexpr +%type <is> acc_options acc_option menuitem_flags menuitem_flag +%type <s> optstringc file_name +%type <i> sizednumexpr sizedposnumexpr + +%left '|' +%left '^' +%left '&' +%left '+' '-' +%left '*' '/' '%' +%right '~' NEG + +%% + +input: + /* empty */ + | input newcmd accelerator + | input newcmd bitmap + | input newcmd cursor + | input newcmd dialog + | input newcmd font + | input newcmd icon + | input newcmd language + | input newcmd menu + | input newcmd menuex + | input newcmd messagetable + | input newcmd rcdata + | input newcmd stringtable + | input newcmd user + | input newcmd versioninfo + ; + +newcmd: + /* empty */ + { + rcparse_discard_strings (); + } + ; + +/* Accelerator resources. */ + +accelerator: + id ACCELERATORS suboptions BEG acc_entries END + { + define_accelerator ($1, &$3, $5); + } + ; + +acc_entries: + /* empty */ + { + $$ = NULL; + } + | acc_entries acc_entry + { + struct accelerator *a; + + a = (struct accelerator *) res_alloc (sizeof *a); + *a = $2; + if ($1 == NULL) + $$ = a; + else + { + struct accelerator **pp; + + for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next) + ; + *pp = a; + $$ = $1; + } + } + ; + +acc_entry: + acc_event cposnumexpr + { + $$ = $1; + $$.id = $2; + } + | acc_event cposnumexpr ',' acc_options + { + $$ = $1; + $$.id = $2; + $$.flags |= $4; + if (($$.flags & ACC_VIRTKEY) == 0 + && ($$.flags & (ACC_SHIFT | ACC_CONTROL | ACC_ALT)) != 0) + rcparse_warning (_("inappropriate modifiers for non-VIRTKEY")); + } + ; + +acc_event: + QUOTEDSTRING + { + const char *s = $1; + char ch; + + $$.next = NULL; + $$.id = 0; + ch = *s; + if (ch != '^') + $$.flags = 0; + else + { + $$.flags = ACC_CONTROL | ACC_VIRTKEY; + ++s; + ch = *s; + ch = toupper ((unsigned char) ch); + } + $$.key = ch; + if (s[1] != '\0') + rcparse_warning (_("accelerator should only be one character")); + } + | posnumexpr + { + $$.next = NULL; + $$.flags = 0; + $$.id = 0; + $$.key = $1; + } + ; + +acc_options: + acc_option + { + $$ = $1; + } + | acc_options ',' acc_option + { + $$ = $1 | $3; + } + /* I've had one report that the comma is optional. */ + | acc_options acc_option + { + $$ = $1 | $2; + } + ; + +acc_option: + VIRTKEY + { + $$ = ACC_VIRTKEY; + } + | ASCII + { + /* This is just the absence of VIRTKEY. */ + $$ = 0; + } + | NOINVERT + { + $$ = ACC_NOINVERT; + } + | SHIFT + { + $$ = ACC_SHIFT; + } + | CONTROL + { + $$ = ACC_CONTROL; + } + | ALT + { + $$ = ACC_ALT; + } + ; + +/* Bitmap resources. */ + +bitmap: + id BITMAP memflags_move file_name + { + define_bitmap ($1, &$3, $4); + } + ; + +/* Cursor resources. */ + +cursor: + id CURSOR memflags_move_discard file_name + { + define_cursor ($1, &$3, $4); + } + ; + +/* Dialog resources. */ + +dialog: + id DIALOG memflags_move exstyle posnumexpr cnumexpr cnumexpr + cnumexpr + { + memset (&dialog, 0, sizeof dialog); + dialog.x = $5; + dialog.y = $6; + dialog.width = $7; + dialog.height = $8; + dialog.style = WS_POPUP | WS_BORDER | WS_SYSMENU; + dialog.exstyle = $4; + dialog.menu.named = 1; + dialog.class.named = 1; + dialog.font = NULL; + dialog.ex = NULL; + dialog.controls = NULL; + sub_res_info = $3; + } + styles BEG controls END + { + define_dialog ($1, &sub_res_info, &dialog); + } + | id DIALOGEX memflags_move exstyle posnumexpr cnumexpr cnumexpr + cnumexpr + { + memset (&dialog, 0, sizeof dialog); + dialog.x = $5; + dialog.y = $6; + dialog.width = $7; + dialog.height = $8; + dialog.style = WS_POPUP | WS_BORDER | WS_SYSMENU; + dialog.exstyle = $4; + dialog.menu.named = 1; + dialog.class.named = 1; + dialog.font = NULL; + dialog.ex = ((struct dialog_ex *) + res_alloc (sizeof (struct dialog_ex))); + memset (dialog.ex, 0, sizeof (struct dialog_ex)); + dialog.controls = NULL; + sub_res_info = $3; + } + styles BEG controls END + { + define_dialog ($1, &sub_res_info, &dialog); + } + | id DIALOGEX memflags_move exstyle posnumexpr cnumexpr cnumexpr + cnumexpr cnumexpr + { + memset (&dialog, 0, sizeof dialog); + dialog.x = $5; + dialog.y = $6; + dialog.width = $7; + dialog.height = $8; + dialog.style = WS_POPUP | WS_BORDER | WS_SYSMENU; + dialog.exstyle = $4; + dialog.menu.named = 1; + dialog.class.named = 1; + dialog.font = NULL; + dialog.ex = ((struct dialog_ex *) + res_alloc (sizeof (struct dialog_ex))); + memset (dialog.ex, 0, sizeof (struct dialog_ex)); + dialog.ex->help = $9; + dialog.controls = NULL; + sub_res_info = $3; + } + styles BEG controls END + { + define_dialog ($1, &sub_res_info, &dialog); + } + ; + +exstyle: + /* empty */ + { + $$ = 0; + } + | EXSTYLE '=' numexpr + { + $$ = $3; + } + ; + +styles: + /* empty */ + | styles CAPTION QUOTEDSTRING + { + unicode_from_ascii ((int *) NULL, &dialog.caption, $3); + } + | styles CLASS id + { + dialog.class = $3; + } + | styles STYLE + { style = dialog.style; } + styleexpr + { + dialog.style = style; + } + | styles EXSTYLE numexpr + { + dialog.exstyle = $3; + } + | styles FONT numexpr ',' QUOTEDSTRING + { + dialog.style |= DS_SETFONT; + dialog.pointsize = $3; + unicode_from_ascii ((int *) NULL, &dialog.font, $5); + } + | styles FONT numexpr ',' QUOTEDSTRING cnumexpr cnumexpr + { + dialog.style |= DS_SETFONT; + dialog.pointsize = $3; + unicode_from_ascii ((int *) NULL, &dialog.font, $5); + if (dialog.ex == NULL) + rcparse_warning (_("extended FONT requires DIALOGEX")); + else + { + dialog.ex->weight = $6; + dialog.ex->italic = $7; + } + } + | styles MENU id + { + dialog.menu = $3; + } + | styles CHARACTERISTICS numexpr + { + sub_res_info.characteristics = $3; + } + | styles LANGUAGE numexpr cnumexpr + { + sub_res_info.language = $3 | ($4 << 8); + } + | styles VERSIONK numexpr + { + sub_res_info.version = $3; + } + ; + +controls: + /* empty */ + | controls control + { + struct dialog_control **pp; + + for (pp = &dialog.controls; *pp != NULL; pp = &(*pp)->next) + ; + *pp = $2; + } + ; + +control: + AUTO3STATE + { + default_style = BS_AUTO3STATE | WS_TABSTOP; + base_style = BS_AUTO3STATE; + class = CTL_BUTTON; + } + control_params + { + $$ = $3; + } + | AUTOCHECKBOX + { + default_style = BS_AUTOCHECKBOX | WS_TABSTOP; + base_style = BS_AUTOCHECKBOX; + class = CTL_BUTTON; + } + control_params + { + $$ = $3; + } + | AUTORADIOBUTTON + { + default_style = BS_AUTORADIOBUTTON | WS_TABSTOP; + base_style = BS_AUTORADIOBUTTON; + class = CTL_BUTTON; + } + control_params + { + $$ = $3; + } + | BEDIT + { + default_style = ES_LEFT | WS_BORDER | WS_TABSTOP; + base_style = ES_LEFT | WS_BORDER | WS_TABSTOP; + class = CTL_EDIT; + } + control_params + { + $$ = $3; + if (dialog.ex == NULL) + rcparse_warning (_("IEDIT requires DIALOGEX")); + res_string_to_id (&$$->class, "BEDIT"); + } + | CHECKBOX + { + default_style = BS_CHECKBOX | WS_TABSTOP; + base_style = BS_CHECKBOX | WS_TABSTOP; + class = CTL_BUTTON; + } + control_params + { + $$ = $3; + } + | COMBOBOX + { + default_style = CBS_SIMPLE | WS_TABSTOP; + base_style = 0; + class = CTL_COMBOBOX; + } + control_params + { + $$ = $3; + } + | CONTROL optstringc numexpr cnumexpr control_styleexpr cnumexpr + cnumexpr cnumexpr cnumexpr optcnumexpr opt_control_data + { + $$ = define_control ($2, $3, $6, $7, $8, $9, $4, style, $10); + if ($11 != NULL) + { + if (dialog.ex == NULL) + rcparse_warning (_("control data requires DIALOGEX")); + $$->data = $11; + } + } + | CONTROL optstringc numexpr cnumexpr control_styleexpr cnumexpr + cnumexpr cnumexpr cnumexpr cnumexpr cnumexpr opt_control_data + { + $$ = define_control ($2, $3, $6, $7, $8, $9, $4, style, $10); + if (dialog.ex == NULL) + rcparse_warning (_("help ID requires DIALOGEX")); + $$->help = $11; + $$->data = $12; + } + | CONTROL optstringc numexpr ',' QUOTEDSTRING control_styleexpr + cnumexpr cnumexpr cnumexpr cnumexpr optcnumexpr opt_control_data + { + $$ = define_control ($2, $3, $7, $8, $9, $10, 0, style, $11); + if ($12 != NULL) + { + if (dialog.ex == NULL) + rcparse_warning ("control data requires DIALOGEX"); + $$->data = $12; + } + $$->class.named = 1; + unicode_from_ascii(&$$->class.u.n.length, &$$->class.u.n.name, $5); + } + | CONTROL optstringc numexpr ',' QUOTEDSTRING control_styleexpr + cnumexpr cnumexpr cnumexpr cnumexpr cnumexpr cnumexpr opt_control_data + { + $$ = define_control ($2, $3, $7, $8, $9, $10, 0, style, $11); + if (dialog.ex == NULL) + rcparse_warning ("help ID requires DIALOGEX"); + $$->help = $12; + $$->data = $13; + $$->class.named = 1; + unicode_from_ascii(&$$->class.u.n.length, &$$->class.u.n.name, $5); + } + | CTEXT + { + default_style = SS_CENTER | WS_GROUP; + base_style = SS_CENTER; + class = CTL_STATIC; + } + control_params + { + $$ = $3; + } + | DEFPUSHBUTTON + { + default_style = BS_DEFPUSHBUTTON | WS_TABSTOP; + base_style = BS_DEFPUSHBUTTON | WS_TABSTOP; + class = CTL_BUTTON; + } + control_params + { + $$ = $3; + } + | EDITTEXT + { + default_style = ES_LEFT | WS_BORDER | WS_TABSTOP; + base_style = ES_LEFT | WS_BORDER | WS_TABSTOP; + class = CTL_EDIT; + } + control_params + { + $$ = $3; + } + | GROUPBOX + { + default_style = BS_GROUPBOX; + base_style = BS_GROUPBOX; + class = CTL_BUTTON; + } + control_params + { + $$ = $3; + } + | HEDIT + { + default_style = ES_LEFT | WS_BORDER | WS_TABSTOP; + base_style = ES_LEFT | WS_BORDER | WS_TABSTOP; + class = CTL_EDIT; + } + control_params + { + $$ = $3; + if (dialog.ex == NULL) + rcparse_warning (_("IEDIT requires DIALOGEX")); + res_string_to_id (&$$->class, "HEDIT"); + } + | ICON optstringc numexpr cnumexpr cnumexpr opt_control_data + { + $$ = define_control ($2, $3, $4, $5, 0, 0, CTL_STATIC, + SS_ICON | WS_CHILD | WS_VISIBLE, 0); + if ($6 != NULL) + { + if (dialog.ex == NULL) + rcparse_warning (_("control data requires DIALOGEX")); + $$->data = $6; + } + } + | ICON optstringc numexpr cnumexpr cnumexpr cnumexpr cnumexpr + icon_styleexpr optcnumexpr opt_control_data + { + $$ = define_control ($2, $3, $4, $5, $6, $7, CTL_STATIC, + style, $9); + if ($10 != NULL) + { + if (dialog.ex == NULL) + rcparse_warning (_("control data requires DIALOGEX")); + $$->data = $10; + } + } + | ICON optstringc numexpr cnumexpr cnumexpr cnumexpr cnumexpr + icon_styleexpr cnumexpr cnumexpr opt_control_data + { + $$ = define_control ($2, $3, $4, $5, $6, $7, CTL_STATIC, + style, $9); + if (dialog.ex == NULL) + rcparse_warning (_("help ID requires DIALOGEX")); + $$->help = $10; + $$->data = $11; + } + | IEDIT + { + default_style = ES_LEFT | WS_BORDER | WS_TABSTOP; + base_style = ES_LEFT | WS_BORDER | WS_TABSTOP; + class = CTL_EDIT; + } + control_params + { + $$ = $3; + if (dialog.ex == NULL) + rcparse_warning (_("IEDIT requires DIALOGEX")); + res_string_to_id (&$$->class, "IEDIT"); + } + | LISTBOX + { + default_style = LBS_NOTIFY | WS_BORDER; + base_style = LBS_NOTIFY | WS_BORDER; + class = CTL_LISTBOX; + } + control_params + { + $$ = $3; + } + | LTEXT + { + default_style = SS_LEFT | WS_GROUP; + base_style = SS_LEFT; + class = CTL_STATIC; + } + control_params + { + $$ = $3; + } + | PUSHBOX + { + default_style = BS_PUSHBOX | WS_TABSTOP; + base_style = BS_PUSHBOX; + class = CTL_BUTTON; + } + control_params + { + $$ = $3; + } + | PUSHBUTTON + { + default_style = BS_PUSHBUTTON | WS_TABSTOP; + base_style = BS_PUSHBUTTON | WS_TABSTOP; + class = CTL_BUTTON; + } + control_params + { + $$ = $3; + } + | RADIOBUTTON + { + default_style = BS_RADIOBUTTON | WS_TABSTOP; + base_style = BS_RADIOBUTTON; + class = CTL_BUTTON; + } + control_params + { + $$ = $3; + } + | RTEXT + { + default_style = SS_RIGHT | WS_GROUP; + base_style = SS_RIGHT; + class = CTL_STATIC; + } + control_params + { + $$ = $3; + } + | SCROLLBAR + { + default_style = SBS_HORZ; + base_style = 0; + class = CTL_SCROLLBAR; + } + control_params + { + $$ = $3; + } + | STATE3 + { + default_style = BS_3STATE | WS_TABSTOP; + base_style = BS_3STATE; + class = CTL_BUTTON; + } + control_params + { + $$ = $3; + } + | USERBUTTON QUOTEDSTRING ',' numexpr ',' numexpr ',' numexpr ',' + numexpr ',' numexpr ',' + { style = WS_CHILD | WS_VISIBLE; } + styleexpr optcnumexpr + { + $$ = define_control ($2, $4, $6, $8, $10, $12, CTL_BUTTON, + style, $16); + } + ; + +/* Parameters for a control. The static variables DEFAULT_STYLE, + BASE_STYLE, and CLASS must be initialized before this nonterminal + is used. DEFAULT_STYLE is the style to use if no style expression + is specified. BASE_STYLE is the base style to use if a style + expression is specified; the style expression modifies the base + style. CLASS is the class of the control. */ + +control_params: + optstringc numexpr cnumexpr cnumexpr cnumexpr cnumexpr + opt_control_data + { + $$ = define_control ($1, $2, $3, $4, $5, $6, class, + default_style | WS_CHILD | WS_VISIBLE, 0); + if ($7 != NULL) + { + if (dialog.ex == NULL) + rcparse_warning (_("control data requires DIALOGEX")); + $$->data = $7; + } + } + | optstringc numexpr cnumexpr cnumexpr cnumexpr cnumexpr + control_params_styleexpr optcnumexpr opt_control_data + { + $$ = define_control ($1, $2, $3, $4, $5, $6, class, style, $8); + if ($9 != NULL) + { + if (dialog.ex == NULL) + rcparse_warning (_("control data requires DIALOGEX")); + $$->data = $9; + } + } + | optstringc numexpr cnumexpr cnumexpr cnumexpr cnumexpr + control_params_styleexpr cnumexpr cnumexpr opt_control_data + { + $$ = define_control ($1, $2, $3, $4, $5, $6, class, style, $8); + if (dialog.ex == NULL) + rcparse_warning (_("help ID requires DIALOGEX")); + $$->help = $9; + $$->data = $10; + } + ; + +optstringc: + /* empty */ + { + $$ = NULL; + } + | QUOTEDSTRING ',' + { + $$ = $1; + } + ; + +opt_control_data: + /* empty */ + { + $$ = NULL; + } + | BEG optrcdata_data END + { + $$ = $2.first; + } + ; + +/* These only exist to parse a reduction out of a common case. */ + +control_styleexpr: + ',' + { style = WS_CHILD | WS_VISIBLE; } + styleexpr + ; + +icon_styleexpr: + ',' + { style = SS_ICON | WS_CHILD | WS_VISIBLE; } + styleexpr + ; + +control_params_styleexpr: + ',' + { style = base_style | WS_CHILD | WS_VISIBLE; } + styleexpr + ; + +/* Font resources. */ + +font: + id FONT memflags_move_discard file_name + { + define_font ($1, &$3, $4); + } + ; + +/* Icon resources. */ + +icon: + id ICON memflags_move_discard file_name + { + define_icon ($1, &$3, $4); + } + ; + +/* Language command. This changes the static variable language, which + affects all subsequent resources. */ + +language: + LANGUAGE numexpr cnumexpr + { + language = $2 | ($3 << 8); + } + ; + +/* Menu resources. */ + +menu: + id MENU suboptions BEG menuitems END + { + define_menu ($1, &$3, $5); + } + ; + +menuitems: + /* empty */ + { + $$ = NULL; + } + | menuitems menuitem + { + if ($1 == NULL) + $$ = $2; + else + { + struct menuitem **pp; + + for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next) + ; + *pp = $2; + $$ = $1; + } + } + ; + +menuitem: + MENUITEM QUOTEDSTRING cnumexpr menuitem_flags + { + $$ = define_menuitem ($2, $3, $4, 0, 0, NULL); + } + | MENUITEM SEPARATOR + { + $$ = define_menuitem (NULL, 0, 0, 0, 0, NULL); + } + | POPUP QUOTEDSTRING menuitem_flags BEG menuitems END + { + $$ = define_menuitem ($2, 0, $3, 0, 0, $5); + } + ; + +menuitem_flags: + /* empty */ + { + $$ = 0; + } + | menuitem_flags ',' menuitem_flag + { + $$ = $1 | $3; + } + | menuitem_flags menuitem_flag + { + $$ = $1 | $2; + } + ; + +menuitem_flag: + CHECKED + { + $$ = MENUITEM_CHECKED; + } + | GRAYED + { + $$ = MENUITEM_GRAYED; + } + | HELP + { + $$ = MENUITEM_HELP; + } + | INACTIVE + { + $$ = MENUITEM_INACTIVE; + } + | MENUBARBREAK + { + $$ = MENUITEM_MENUBARBREAK; + } + | MENUBREAK + { + $$ = MENUITEM_MENUBREAK; + } + ; + +/* Menuex resources. */ + +menuex: + id MENUEX suboptions BEG menuexitems END + { + define_menu ($1, &$3, $5); + } + ; + +menuexitems: + /* empty */ + { + $$ = NULL; + } + | menuexitems menuexitem + { + if ($1 == NULL) + $$ = $2; + else + { + struct menuitem **pp; + + for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next) + ; + *pp = $2; + $$ = $1; + } + } + ; + +menuexitem: + MENUITEM QUOTEDSTRING + { + $$ = define_menuitem ($2, 0, 0, 0, 0, NULL); + } + | MENUITEM QUOTEDSTRING cnumexpr + { + $$ = define_menuitem ($2, $3, 0, 0, 0, NULL); + } + | MENUITEM QUOTEDSTRING cnumexpr cnumexpr optcnumexpr + { + $$ = define_menuitem ($2, $3, $4, $5, 0, NULL); + } + | MENUITEM SEPARATOR + { + $$ = define_menuitem (NULL, 0, 0, 0, 0, NULL); + } + | POPUP QUOTEDSTRING BEG menuexitems END + { + $$ = define_menuitem ($2, 0, 0, 0, 0, $4); + } + | POPUP QUOTEDSTRING cnumexpr BEG menuexitems END + { + $$ = define_menuitem ($2, $3, 0, 0, 0, $5); + } + | POPUP QUOTEDSTRING cnumexpr cnumexpr BEG menuexitems END + { + $$ = define_menuitem ($2, $3, $4, 0, 0, $6); + } + | POPUP QUOTEDSTRING cnumexpr cnumexpr cnumexpr optcnumexpr + BEG menuexitems END + { + $$ = define_menuitem ($2, $3, $4, $5, $6, $8); + } + ; + +/* Messagetable resources. */ + +messagetable: + id MESSAGETABLE memflags_move file_name + { + define_messagetable ($1, &$3, $4); + } + ; + +/* Rcdata resources. */ + +rcdata: + id RCDATA suboptions BEG optrcdata_data END + { + define_rcdata ($1, &$3, $5.first); + } + ; + +/* We use a different lexing algorithm, because rcdata strings may + contain embedded null bytes, and we need to know the length to use. */ + +optrcdata_data: + { + rcparse_rcdata (); + } + optrcdata_data_int + { + rcparse_normal (); + $$ = $2; + } + ; + +optrcdata_data_int: + /* empty */ + { + $$.first = NULL; + $$.last = NULL; + } + | rcdata_data + { + $$ = $1; + } + ; + +rcdata_data: + SIZEDSTRING + { + struct rcdata_item *ri; + + ri = define_rcdata_string ($1.s, $1.length); + $$.first = ri; + $$.last = ri; + } + | sizednumexpr + { + struct rcdata_item *ri; + + ri = define_rcdata_number ($1.val, $1.dword); + $$.first = ri; + $$.last = ri; + } + | rcdata_data ',' SIZEDSTRING + { + struct rcdata_item *ri; + + ri = define_rcdata_string ($3.s, $3.length); + $$.first = $1.first; + $1.last->next = ri; + $$.last = ri; + } + | rcdata_data ',' sizednumexpr + { + struct rcdata_item *ri; + + ri = define_rcdata_number ($3.val, $3.dword); + $$.first = $1.first; + $1.last->next = ri; + $$.last = ri; + } + ; + +/* Stringtable resources. */ + +stringtable: + STRINGTABLE suboptions BEG + { sub_res_info = $2; } + string_data END + ; + +string_data: + /* empty */ + | string_data numexpr QUOTEDSTRING + { + define_stringtable (&sub_res_info, $2, $3); + } + | string_data numexpr ',' QUOTEDSTRING + { + define_stringtable (&sub_res_info, $2, $4); + } + ; + +/* User defined resources. We accept general suboptions in the + file_name case to keep the parser happy. */ + +user: + id id suboptions BEG optrcdata_data END + { + define_user_data ($1, $2, &$3, $5.first); + } + | id id suboptions file_name + { + define_user_file ($1, $2, &$3, $4); + } + ; + +/* Versioninfo resources. */ + +versioninfo: + id VERSIONINFO fixedverinfo BEG verblocks END + { + define_versioninfo ($1, language, $3, $5); + } + ; + +fixedverinfo: + /* empty */ + { + $$ = ((struct fixed_versioninfo *) + res_alloc (sizeof (struct fixed_versioninfo))); + memset ($$, 0, sizeof (struct fixed_versioninfo)); + } + | fixedverinfo FILEVERSION numexpr cnumexpr cnumexpr cnumexpr + { + $1->file_version_ms = ($3 << 16) | $4; + $1->file_version_ls = ($5 << 16) | $6; + $$ = $1; + } + | fixedverinfo PRODUCTVERSION numexpr cnumexpr cnumexpr cnumexpr + { + $1->product_version_ms = ($3 << 16) | $4; + $1->product_version_ls = ($5 << 16) | $6; + $$ = $1; + } + | fixedverinfo FILEFLAGSMASK numexpr + { + $1->file_flags_mask = $3; + $$ = $1; + } + | fixedverinfo FILEFLAGS numexpr + { + $1->file_flags = $3; + $$ = $1; + } + | fixedverinfo FILEOS numexpr + { + $1->file_os = $3; + $$ = $1; + } + | fixedverinfo FILETYPE numexpr + { + $1->file_type = $3; + $$ = $1; + } + | fixedverinfo FILESUBTYPE numexpr + { + $1->file_subtype = $3; + $$ = $1; + } + ; + +/* To handle verblocks successfully, the lexer handles BLOCK + specially. A BLOCK "StringFileInfo" is returned as + BLOCKSTRINGFILEINFO. A BLOCK "VarFileInfo" is returned as + BLOCKVARFILEINFO. A BLOCK with some other string returns BLOCK + with the string as the value. */ + +verblocks: + /* empty */ + { + $$ = NULL; + } + | verblocks BLOCKSTRINGFILEINFO BEG BLOCK BEG vervals END END + { + $$ = append_ver_stringfileinfo ($1, $4, $6); + } + | verblocks BLOCKVARFILEINFO BEG VALUE QUOTEDSTRING vertrans END + { + $$ = append_ver_varfileinfo ($1, $5, $6); + } + ; + +vervals: + /* empty */ + { + $$ = NULL; + } + | vervals VALUE QUOTEDSTRING ',' QUOTEDSTRING + { + $$ = append_verval ($1, $3, $5); + } + ; + +vertrans: + /* empty */ + { + $$ = NULL; + } + | vertrans cnumexpr cnumexpr + { + $$ = append_vertrans ($1, $2, $3); + } + ; + +/* A resource ID. */ + +id: + posnumexpr + { + $$.named = 0; + $$.u.id = $1; + } + | STRING + { + char *copy, *s; + + /* It seems that resource ID's are forced to upper case. */ + copy = xstrdup ($1); + for (s = copy; *s != '\0'; s++) + if (islower ((unsigned char) *s)) + *s = toupper ((unsigned char) *s); + res_string_to_id (&$$, copy); + free (copy); + } + ; + +/* Generic suboptions. These may appear before the BEGIN in any + multiline statement. */ + +suboptions: + /* empty */ + { + memset (&$$, 0, sizeof (struct res_res_info)); + $$.language = language; + /* FIXME: Is this the right default? */ + $$.memflags = MEMFLAG_MOVEABLE; + } + | suboptions memflag + { + $$ = $1; + $$.memflags |= $2.on; + $$.memflags &=~ $2.off; + } + | suboptions CHARACTERISTICS numexpr + { + $$ = $1; + $$.characteristics = $3; + } + | suboptions LANGUAGE numexpr cnumexpr + { + $$ = $1; + $$.language = $3 | ($4 << 8); + } + | suboptions VERSIONK numexpr + { + $$ = $1; + $$.version = $3; + } + ; + +/* Memory flags which default to MOVEABLE and DISCARDABLE. */ + +memflags_move_discard: + /* empty */ + { + memset (&$$, 0, sizeof (struct res_res_info)); + $$.language = language; + $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_DISCARDABLE; + } + | memflags_move_discard memflag + { + $$ = $1; + $$.memflags |= $2.on; + $$.memflags &=~ $2.off; + } + ; + +/* Memory flags which default to MOVEABLE. */ + +memflags_move: + /* empty */ + { + memset (&$$, 0, sizeof (struct res_res_info)); + $$.language = language; + $$.memflags = MEMFLAG_MOVEABLE; + } + | memflags_move memflag + { + $$ = $1; + $$.memflags |= $2.on; + $$.memflags &=~ $2.off; + } + ; + +/* Memory flags. This returns a struct with two integers, because we + sometimes want to set bits and we sometimes want to clear them. */ + +memflag: + MOVEABLE + { + $$.on = MEMFLAG_MOVEABLE; + $$.off = 0; + } + | FIXED + { + $$.on = 0; + $$.off = MEMFLAG_MOVEABLE; + } + | PURE + { + $$.on = MEMFLAG_PURE; + $$.off = 0; + } + | IMPURE + { + $$.on = 0; + $$.off = MEMFLAG_PURE; + } + | PRELOAD + { + $$.on = MEMFLAG_PRELOAD; + $$.off = 0; + } + | LOADONCALL + { + $$.on = 0; + $$.off = MEMFLAG_PRELOAD; + } + | DISCARDABLE + { + $$.on = MEMFLAG_DISCARDABLE; + $$.off = 0; + } + ; + +/* A file name. */ + +file_name: + QUOTEDSTRING + { + $$ = $1; + } + | STRING + { + $$ = $1; + } + ; + +/* A style expression. This changes the static variable STYLE. We do + it this way because rc appears to permit a style to be set to + something like + WS_GROUP | NOT WS_TABSTOP + to mean that a default of WS_TABSTOP should be removed. Anything + which wants to accept a style must first set STYLE to the default + value. The styleexpr nonterminal will change STYLE as specified by + the user. Note that we do not accept arbitrary expressions here, + just numbers separated by '|'. */ + +styleexpr: + parennumber + { + style |= $1; + } + | NOT parennumber + { + style &=~ $2; + } + | styleexpr '|' parennumber + { + style |= $3; + } + | styleexpr '|' NOT parennumber + { + style &=~ $4; + } + ; + +parennumber: + NUMBER + { + $$ = $1.val; + } + | '(' numexpr ')' + { + $$ = $2; + } + ; + +/* An optional expression with a leading comma. */ + +optcnumexpr: + /* empty */ + { + $$ = 0; + } + | cnumexpr + { + $$ = $1; + } + ; + +/* An expression with a leading comma. */ + +cnumexpr: + ',' numexpr + { + $$ = $2; + } + ; + +/* A possibly negated numeric expression. */ + +numexpr: + sizednumexpr + { + $$ = $1.val; + } + ; + +/* A possibly negated expression with a size. */ + +sizednumexpr: + NUMBER + { + $$ = $1; + } + | '(' sizednumexpr ')' + { + $$ = $2; + } + | '~' sizednumexpr %prec '~' + { + $$.val = ~ $2.val; + $$.dword = $2.dword; + } + | '-' sizednumexpr %prec NEG + { + $$.val = - $2.val; + $$.dword = $2.dword; + } + | sizednumexpr '*' sizednumexpr + { + $$.val = $1.val * $3.val; + $$.dword = $1.dword || $3.dword; + } + | sizednumexpr '/' sizednumexpr + { + $$.val = $1.val / $3.val; + $$.dword = $1.dword || $3.dword; + } + | sizednumexpr '%' sizednumexpr + { + $$.val = $1.val % $3.val; + $$.dword = $1.dword || $3.dword; + } + | sizednumexpr '+' sizednumexpr + { + $$.val = $1.val + $3.val; + $$.dword = $1.dword || $3.dword; + } + | sizednumexpr '-' sizednumexpr + { + $$.val = $1.val - $3.val; + $$.dword = $1.dword || $3.dword; + } + | sizednumexpr '&' sizednumexpr + { + $$.val = $1.val & $3.val; + $$.dword = $1.dword || $3.dword; + } + | sizednumexpr '^' sizednumexpr + { + $$.val = $1.val ^ $3.val; + $$.dword = $1.dword || $3.dword; + } + | sizednumexpr '|' sizednumexpr + { + $$.val = $1.val | $3.val; + $$.dword = $1.dword || $3.dword; + } + ; + +/* An expression with a leading comma which does not use unary + negation. */ + +cposnumexpr: + ',' posnumexpr + { + $$ = $2; + } + ; + +/* An expression which does not use unary negation. */ + +posnumexpr: + sizedposnumexpr + { + $$ = $1.val; + } + ; + +/* An expression which does not use unary negation. We separate unary + negation to avoid parsing conflicts when two numeric expressions + appear consecutively. */ + +sizedposnumexpr: + NUMBER + { + $$ = $1; + } + | '(' sizednumexpr ')' + { + $$ = $2; + } + | '~' sizednumexpr %prec '~' + { + $$.val = ~ $2.val; + $$.dword = $2.dword; + } + | sizedposnumexpr '*' sizednumexpr + { + $$.val = $1.val * $3.val; + $$.dword = $1.dword || $3.dword; + } + | sizedposnumexpr '/' sizednumexpr + { + $$.val = $1.val / $3.val; + $$.dword = $1.dword || $3.dword; + } + | sizedposnumexpr '%' sizednumexpr + { + $$.val = $1.val % $3.val; + $$.dword = $1.dword || $3.dword; + } + | sizedposnumexpr '+' sizednumexpr + { + $$.val = $1.val + $3.val; + $$.dword = $1.dword || $3.dword; + } + | sizedposnumexpr '-' sizednumexpr + { + $$.val = $1.val - $3.val; + $$.dword = $1.dword || $3.dword; + } + | sizedposnumexpr '&' sizednumexpr + { + $$.val = $1.val & $3.val; + $$.dword = $1.dword || $3.dword; + } + | sizedposnumexpr '^' sizednumexpr + { + $$.val = $1.val ^ $3.val; + $$.dword = $1.dword || $3.dword; + } + | sizedposnumexpr '|' sizednumexpr + { + $$.val = $1.val | $3.val; + $$.dword = $1.dword || $3.dword; + } + ; + +%% + +/* Set the language from the command line. */ + +void +rcparse_set_language (lang) + int lang; +{ + language = lang; +} diff --git a/binutils/rdcoff.c b/binutils/rdcoff.c new file mode 100644 index 0000000..ee68bc6 --- /dev/null +++ b/binutils/rdcoff.c @@ -0,0 +1,889 @@ +/* stabs.c -- Parse COFF debugging information + Copyright (C) 1996, 1998 Free Software Foundation, Inc. + Written by Ian Lance Taylor <ian@cygnus.com>. + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* This file contains code which parses COFF debugging information. */ + +#include "bfd.h" +#include "coff/internal.h" +#include "bucomm.h" +#include "libiberty.h" +#include "demangle.h" +#include "debug.h" +#include "budbg.h" + +/* FIXME: We should not need this BFD internal file. We need it for + the N_BTMASK, etc., values. */ +#include "libcoff.h" + +/* These macros extract the right mask and shifts for this BFD. They + assume that there is a local variable named ABFD. This is so that + macros like ISFCN and DECREF, from coff/internal.h, will work + without modification. */ +#define N_BTMASK (coff_data (abfd)->local_n_btmask) +#define N_BTSHFT (coff_data (abfd)->local_n_btshft) +#define N_TMASK (coff_data (abfd)->local_n_tmask) +#define N_TSHIFT (coff_data (abfd)->local_n_tshift) + +/* This structure is used to hold the symbols, as well as the current + location within the symbols. */ + +struct coff_symbols +{ + /* The symbols. */ + asymbol **syms; + /* The number of symbols. */ + long symcount; + /* The index of the current symbol. */ + long symno; + /* The index of the current symbol in the COFF symbol table (where + each auxent counts as a symbol). */ + long coff_symno; +}; + +/* The largest basic type we are prepared to handle. */ + +#define T_MAX (T_LNGDBL) + +/* This structure is used to hold slots. */ + +struct coff_slots +{ + /* Next set of slots. */ + struct coff_slots *next; + /* Slots. */ +#define COFF_SLOTS (16) + debug_type slots[COFF_SLOTS]; +}; + +/* This structure is used to map symbol indices to types. */ + +struct coff_types +{ + /* Slots. */ + struct coff_slots *slots; + /* Basic types. */ + debug_type basic[T_MAX + 1]; +}; + +static debug_type *coff_get_slot PARAMS ((struct coff_types *, int)); +static debug_type parse_coff_type + PARAMS ((bfd *, struct coff_symbols *, struct coff_types *, long, int, + union internal_auxent *, boolean, PTR)); +static debug_type parse_coff_base_type + PARAMS ((bfd *, struct coff_symbols *, struct coff_types *, long, int, + union internal_auxent *, PTR)); +static debug_type parse_coff_struct_type + PARAMS ((bfd *, struct coff_symbols *, struct coff_types *, int, + union internal_auxent *, PTR)); +static debug_type parse_coff_enum_type + PARAMS ((bfd *, struct coff_symbols *, struct coff_types *, + union internal_auxent *, PTR)); +static boolean parse_coff_symbol + PARAMS ((bfd *, struct coff_types *, asymbol *, long, + struct internal_syment *, PTR, debug_type, boolean)); + +/* Return the slot for a type. */ + +static debug_type * +coff_get_slot (types, indx) + struct coff_types *types; + int indx; +{ + struct coff_slots **pps; + + pps = &types->slots; + + while (indx >= COFF_SLOTS) + { + if (*pps == NULL) + { + *pps = (struct coff_slots *) xmalloc (sizeof **pps); + memset (*pps, 0, sizeof **pps); + } + pps = &(*pps)->next; + indx -= COFF_SLOTS; + } + + if (*pps == NULL) + { + *pps = (struct coff_slots *) xmalloc (sizeof **pps); + memset (*pps, 0, sizeof **pps); + } + + return (*pps)->slots + indx; +} + +/* Parse a COFF type code in NTYPE. */ + +static debug_type +parse_coff_type (abfd, symbols, types, coff_symno, ntype, pauxent, useaux, + dhandle) + bfd *abfd; + struct coff_symbols *symbols; + struct coff_types *types; + long coff_symno; + int ntype; + union internal_auxent *pauxent; + boolean useaux; + PTR dhandle; +{ + debug_type type; + + if ((ntype & ~N_BTMASK) != 0) + { + int newtype; + + newtype = DECREF (ntype); + + if (ISPTR (ntype)) + { + type = parse_coff_type (abfd, symbols, types, coff_symno, newtype, + pauxent, useaux, dhandle); + type = debug_make_pointer_type (dhandle, type); + } + else if (ISFCN (ntype)) + { + type = parse_coff_type (abfd, symbols, types, coff_symno, newtype, + pauxent, useaux, dhandle); + type = debug_make_function_type (dhandle, type, (debug_type *) NULL, + false); + } + else if (ISARY (ntype)) + { + int n; + + if (pauxent == NULL) + n = 0; + else + { + unsigned short *dim; + int i; + + /* FIXME: If pauxent->x_sym.x_tagndx.l == 0, gdb sets + the c_naux field of the syment to 0. */ + + /* Move the dimensions down, so that the next array + picks up the next one. */ + dim = pauxent->x_sym.x_fcnary.x_ary.x_dimen; + n = dim[0]; + for (i = 0; *dim != 0 && i < DIMNUM - 1; i++, dim++) + *dim = *(dim + 1); + *dim = 0; + } + + type = parse_coff_type (abfd, symbols, types, coff_symno, newtype, + pauxent, false, dhandle); + type = debug_make_array_type (dhandle, type, + parse_coff_base_type (abfd, symbols, + types, + coff_symno, + T_INT, + NULL, dhandle), + 0, n - 1, false); + } + else + { + fprintf (stderr, _("%s: parse_coff_type: Bad type code 0x%x\n"), + program_name, ntype); + return DEBUG_TYPE_NULL; + } + + return type; + } + + if (pauxent != NULL && pauxent->x_sym.x_tagndx.l > 0) + { + debug_type *slot; + + /* This is a reference to an existing type. FIXME: gdb checks + that the class is not C_STRTAG, nor C_UNTAG, nor C_ENTAG. */ + slot = coff_get_slot (types, pauxent->x_sym.x_tagndx.l); + if (*slot != DEBUG_TYPE_NULL) + return *slot; + else + return debug_make_indirect_type (dhandle, slot, (const char *) NULL); + } + + /* If the aux entry has already been used for something, useaux will + have been set to false, indicating that parse_coff_base_type + should not use it. We need to do it this way, rather than simply + passing pauxent as NULL, because we need to be able handle + multiple array dimensions while still discarding pauxent after + having handled all of them. */ + if (! useaux) + pauxent = NULL; + + return parse_coff_base_type (abfd, symbols, types, coff_symno, ntype, + pauxent, dhandle); +} + +/* Parse a basic COFF type in NTYPE. */ + +static debug_type +parse_coff_base_type (abfd, symbols, types, coff_symno, ntype, pauxent, + dhandle) + bfd *abfd; + struct coff_symbols *symbols; + struct coff_types *types; + long coff_symno; + int ntype; + union internal_auxent *pauxent; + PTR dhandle; +{ + debug_type ret; + boolean set_basic; + const char *name; + debug_type *slot; + + if (ntype >= 0 + && ntype <= T_MAX + && types->basic[ntype] != DEBUG_TYPE_NULL) + return types->basic[ntype]; + + set_basic = true; + name = NULL; + + switch (ntype) + { + default: + ret = debug_make_void_type (dhandle); + break; + + case T_NULL: + case T_VOID: + ret = debug_make_void_type (dhandle); + name = "void"; + break; + + case T_CHAR: + ret = debug_make_int_type (dhandle, 1, false); + name = "char"; + break; + + case T_SHORT: + ret = debug_make_int_type (dhandle, 2, false); + name = "short"; + break; + + case T_INT: + /* FIXME: Perhaps the size should depend upon the architecture. */ + ret = debug_make_int_type (dhandle, 4, false); + name = "int"; + break; + + case T_LONG: + ret = debug_make_int_type (dhandle, 4, false); + name = "long"; + break; + + case T_FLOAT: + ret = debug_make_float_type (dhandle, 4); + name = "float"; + break; + + case T_DOUBLE: + ret = debug_make_float_type (dhandle, 8); + name = "double"; + break; + + case T_LNGDBL: + ret = debug_make_float_type (dhandle, 12); + name = "long double"; + break; + + case T_UCHAR: + ret = debug_make_int_type (dhandle, 1, true); + name = "unsigned char"; + break; + + case T_USHORT: + ret = debug_make_int_type (dhandle, 2, true); + name = "unsigned short"; + break; + + case T_UINT: + ret = debug_make_int_type (dhandle, 4, true); + name = "unsigned int"; + break; + + case T_ULONG: + ret = debug_make_int_type (dhandle, 4, true); + name = "unsigned long"; + break; + + case T_STRUCT: + if (pauxent == NULL) + ret = debug_make_struct_type (dhandle, true, 0, + (debug_field *) NULL); + else + ret = parse_coff_struct_type (abfd, symbols, types, ntype, pauxent, + dhandle); + + slot = coff_get_slot (types, coff_symno); + *slot = ret; + + set_basic = false; + break; + + case T_UNION: + if (pauxent == NULL) + ret = debug_make_struct_type (dhandle, false, 0, (debug_field *) NULL); + else + ret = parse_coff_struct_type (abfd, symbols, types, ntype, pauxent, + dhandle); + + slot = coff_get_slot (types, coff_symno); + *slot = ret; + + set_basic = false; + break; + + case T_ENUM: + if (pauxent == NULL) + ret = debug_make_enum_type (dhandle, (const char **) NULL, + (bfd_signed_vma *) NULL); + else + ret = parse_coff_enum_type (abfd, symbols, types, pauxent, dhandle); + + slot = coff_get_slot (types, coff_symno); + *slot = ret; + + set_basic = false; + break; + } + + if (name != NULL) + ret = debug_name_type (dhandle, name, ret); + + if (set_basic + && ntype >= 0 + && ntype <= T_MAX) + types->basic[ntype] = ret; + + return ret; +} + +/* Parse a struct type. */ + +static debug_type +parse_coff_struct_type (abfd, symbols, types, ntype, pauxent, dhandle) + bfd *abfd; + struct coff_symbols *symbols; + struct coff_types *types; + int ntype; + union internal_auxent *pauxent; + PTR dhandle; +{ + long symend; + int alloc; + debug_field *fields; + int count; + boolean done; + + symend = pauxent->x_sym.x_fcnary.x_fcn.x_endndx.l; + + alloc = 10; + fields = (debug_field *) xmalloc (alloc * sizeof *fields); + count = 0; + + done = false; + while (! done + && symbols->coff_symno < symend + && symbols->symno < symbols->symcount) + { + asymbol *sym; + long this_coff_symno; + struct internal_syment syment; + union internal_auxent auxent; + union internal_auxent *psubaux; + bfd_vma bitpos = 0, bitsize = 0; + + sym = symbols->syms[symbols->symno]; + + if (! bfd_coff_get_syment (abfd, sym, &syment)) + { + fprintf (stderr, _("%s: bfd_coff_get_syment failed: %s\n"), + program_name, bfd_errmsg (bfd_get_error ())); + return DEBUG_TYPE_NULL; + } + + this_coff_symno = symbols->coff_symno; + + ++symbols->symno; + symbols->coff_symno += 1 + syment.n_numaux; + + if (syment.n_numaux == 0) + psubaux = NULL; + else + { + if (! bfd_coff_get_auxent (abfd, sym, 0, &auxent)) + { + fprintf (stderr, _("%s: bfd_coff_get_auxent failed: %s\n"), + program_name, bfd_errmsg (bfd_get_error ())); + return DEBUG_TYPE_NULL; + } + psubaux = &auxent; + } + + switch (syment.n_sclass) + { + case C_MOS: + case C_MOU: + bitpos = 8 * bfd_asymbol_value (sym); + bitsize = 0; + break; + + case C_FIELD: + bitpos = bfd_asymbol_value (sym); + bitsize = auxent.x_sym.x_misc.x_lnsz.x_size; + break; + + case C_EOS: + done = true; + break; + } + + if (! done) + { + debug_type ftype; + debug_field f; + + ftype = parse_coff_type (abfd, symbols, types, this_coff_symno, + syment.n_type, psubaux, true, dhandle); + f = debug_make_field (dhandle, bfd_asymbol_name (sym), ftype, + bitpos, bitsize, DEBUG_VISIBILITY_PUBLIC); + if (f == DEBUG_FIELD_NULL) + return DEBUG_TYPE_NULL; + + if (count + 1 >= alloc) + { + alloc += 10; + fields = ((debug_field *) + xrealloc (fields, alloc * sizeof *fields)); + } + + fields[count] = f; + ++count; + } + } + + fields[count] = DEBUG_FIELD_NULL; + + return debug_make_struct_type (dhandle, ntype == T_STRUCT, + pauxent->x_sym.x_misc.x_lnsz.x_size, + fields); +} + +/* Parse an enum type. */ + +static debug_type +parse_coff_enum_type (abfd, symbols, types, pauxent, dhandle) + bfd *abfd; + struct coff_symbols *symbols; + struct coff_types *types; + union internal_auxent *pauxent; + PTR dhandle; +{ + long symend; + int alloc; + const char **names; + bfd_signed_vma *vals; + int count; + boolean done; + + symend = pauxent->x_sym.x_fcnary.x_fcn.x_endndx.l; + + alloc = 10; + names = (const char **) xmalloc (alloc * sizeof *names); + vals = (bfd_signed_vma *) xmalloc (alloc * sizeof *vals); + count = 0; + + done = false; + while (! done + && symbols->coff_symno < symend + && symbols->symno < symbols->symcount) + { + asymbol *sym; + struct internal_syment syment; + + sym = symbols->syms[symbols->symno]; + + if (! bfd_coff_get_syment (abfd, sym, &syment)) + { + fprintf (stderr, _("%s: bfd_coff_get_syment failed: %s\n"), + program_name, bfd_errmsg (bfd_get_error ())); + return DEBUG_TYPE_NULL; + } + + ++symbols->symno; + symbols->coff_symno += 1 + syment.n_numaux; + + switch (syment.n_sclass) + { + case C_MOE: + if (count + 1 >= alloc) + { + alloc += 10; + names = ((const char **) + xrealloc (names, alloc * sizeof *names)); + vals = ((bfd_signed_vma *) + xrealloc (vals, alloc * sizeof *vals)); + } + + names[count] = bfd_asymbol_name (sym); + vals[count] = bfd_asymbol_value (sym); + ++count; + break; + + case C_EOS: + done = true; + break; + } + } + + names[count] = NULL; + + return debug_make_enum_type (dhandle, names, vals); +} + +/* Handle a single COFF symbol. */ + +static boolean +parse_coff_symbol (abfd, types, sym, coff_symno, psyment, dhandle, type, + within_function) + bfd *abfd; + struct coff_types *types; + asymbol *sym; + long coff_symno; + struct internal_syment *psyment; + PTR dhandle; + debug_type type; + boolean within_function; +{ + switch (psyment->n_sclass) + { + case C_NULL: + break; + + case C_AUTO: + if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type, + DEBUG_LOCAL, bfd_asymbol_value (sym))) + return false; + break; + + case C_EXT: + if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type, + DEBUG_GLOBAL, bfd_asymbol_value (sym))) + return false; + break; + + case C_STAT: + if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type, + (within_function + ? DEBUG_LOCAL_STATIC + : DEBUG_STATIC), + bfd_asymbol_value (sym))) + return false; + break; + + case C_REG: + /* FIXME: We may need to convert the register number. */ + if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type, + DEBUG_REGISTER, bfd_asymbol_value (sym))) + return false; + break; + + case C_LABEL: + break; + + case C_ARG: + if (! debug_record_parameter (dhandle, bfd_asymbol_name (sym), type, + DEBUG_PARM_STACK, bfd_asymbol_value (sym))) + return false; + break; + + case C_REGPARM: + /* FIXME: We may need to convert the register number. */ + if (! debug_record_parameter (dhandle, bfd_asymbol_name (sym), type, + DEBUG_PARM_REG, bfd_asymbol_value (sym))) + return false; + break; + + case C_TPDEF: + type = debug_name_type (dhandle, bfd_asymbol_name (sym), type); + if (type == DEBUG_TYPE_NULL) + return false; + break; + + case C_STRTAG: + case C_UNTAG: + case C_ENTAG: + { + debug_type *slot; + + type = debug_tag_type (dhandle, bfd_asymbol_name (sym), type); + if (type == DEBUG_TYPE_NULL) + return false; + + /* Store the named type into the slot, so that references get + the name. */ + slot = coff_get_slot (types, coff_symno); + *slot = type; + } + break; + + default: + break; + } + + return true; +} + +/* This is the main routine. It looks through all the symbols and + handles them. */ + +boolean +parse_coff (abfd, syms, symcount, dhandle) + bfd *abfd; + asymbol **syms; + long symcount; + PTR dhandle; +{ + struct coff_symbols symbols; + struct coff_types types; + int i; + long next_c_file; + const char *fnname; + int fnclass; + int fntype; + bfd_vma fnend; + alent *linenos; + boolean within_function; + long this_coff_symno; + + symbols.syms = syms; + symbols.symcount = symcount; + symbols.symno = 0; + symbols.coff_symno = 0; + + types.slots = NULL; + for (i = 0; i <= T_MAX; i++) + types.basic[i] = DEBUG_TYPE_NULL; + + next_c_file = -1; + fnname = NULL; + fnclass = 0; + fntype = 0; + fnend = 0; + linenos = NULL; + within_function = false; + + while (symbols.symno < symcount) + { + asymbol *sym; + const char *name; + struct internal_syment syment; + union internal_auxent auxent; + union internal_auxent *paux; + debug_type type; + + sym = syms[symbols.symno]; + + if (! bfd_coff_get_syment (abfd, sym, &syment)) + { + fprintf (stderr, _("%s: bfd_coff_get_syment failed: %s\n"), + program_name, bfd_errmsg (bfd_get_error ())); + return false; + } + + name = bfd_asymbol_name (sym); + + this_coff_symno = symbols.coff_symno; + + ++symbols.symno; + symbols.coff_symno += 1 + syment.n_numaux; + + /* We only worry about the first auxent, because that is the + only one which is relevant for debugging information. */ + if (syment.n_numaux == 0) + paux = NULL; + else + { + if (! bfd_coff_get_auxent (abfd, sym, 0, &auxent)) + { + fprintf (stderr, _("%s: bfd_coff_get_auxent failed: %s\n"), + program_name, bfd_errmsg (bfd_get_error ())); + return false; + } + paux = &auxent; + } + + if (this_coff_symno == next_c_file && syment.n_sclass != C_FILE) + { + /* The last C_FILE symbol points to the first external + symbol. */ + if (! debug_set_filename (dhandle, "*globals*")) + return false; + } + + switch (syment.n_sclass) + { + case C_EFCN: + case C_EXTDEF: + case C_ULABEL: + case C_USTATIC: + case C_LINE: + case C_ALIAS: + case C_HIDDEN: + /* Just ignore these classes. */ + break; + + case C_FILE: + next_c_file = syment.n_value; + if (! debug_set_filename (dhandle, name)) + return false; + break; + + case C_STAT: + /* Ignore static symbols with a type of T_NULL. These + represent section entries. */ + if (syment.n_type == T_NULL) + break; + /* Fall through. */ + case C_EXT: + if (ISFCN (syment.n_type)) + { + fnname = name; + fnclass = syment.n_sclass; + fntype = syment.n_type; + if (syment.n_numaux > 0) + fnend = bfd_asymbol_value (sym) + auxent.x_sym.x_misc.x_fsize; + else + fnend = 0; + linenos = BFD_SEND (abfd, _get_lineno, (abfd, sym)); + break; + } + type = parse_coff_type (abfd, &symbols, &types, this_coff_symno, + syment.n_type, paux, true, dhandle); + if (type == DEBUG_TYPE_NULL) + return false; + if (! parse_coff_symbol (abfd, &types, sym, this_coff_symno, &syment, + dhandle, type, within_function)) + return false; + break; + + case C_FCN: + if (strcmp (name, ".bf") == 0) + { + if (fnname == NULL) + { + fprintf (stderr, _("%s: %ld: .bf without preceding function\n"), + program_name, this_coff_symno); + return false; + } + + type = parse_coff_type (abfd, &symbols, &types, this_coff_symno, + DECREF (fntype), paux, false, dhandle); + if (type == DEBUG_TYPE_NULL) + return false; + + if (! debug_record_function (dhandle, fnname, type, + fnclass == C_EXT, + bfd_asymbol_value (sym))) + return false; + + if (linenos != NULL) + { + int base; + bfd_vma addr; + + if (syment.n_numaux == 0) + base = 0; + else + base = auxent.x_sym.x_misc.x_lnsz.x_lnno - 1; + + addr = bfd_get_section_vma (abfd, bfd_get_section (sym)); + + ++linenos; + + while (linenos->line_number != 0) + { + if (! debug_record_line (dhandle, + linenos->line_number + base, + linenos->u.offset + addr)) + return false; + ++linenos; + } + } + + fnname = NULL; + linenos = NULL; + fnclass = 0; + fntype = 0; + + within_function = true; + } + else if (strcmp (name, ".ef") == 0) + { + if (! within_function) + { + fprintf (stderr, _("%s: %ld: unexpected .ef\n"), + program_name, this_coff_symno); + return false; + } + + if (bfd_asymbol_value (sym) > fnend) + fnend = bfd_asymbol_value (sym); + if (! debug_end_function (dhandle, fnend)) + return false; + + fnend = 0; + within_function = false; + } + break; + + case C_BLOCK: + if (strcmp (name, ".bb") == 0) + { + if (! debug_start_block (dhandle, bfd_asymbol_value (sym))) + return false; + } + else if (strcmp (name, ".eb") == 0) + { + if (! debug_end_block (dhandle, bfd_asymbol_value (sym))) + return false; + } + break; + + default: + type = parse_coff_type (abfd, &symbols, &types, this_coff_symno, + syment.n_type, paux, true, dhandle); + if (type == DEBUG_TYPE_NULL) + return false; + if (! parse_coff_symbol (abfd, &types, sym, this_coff_symno, &syment, + dhandle, type, within_function)) + return false; + break; + } + } + + return true; +} diff --git a/binutils/rddbg.c b/binutils/rddbg.c new file mode 100644 index 0000000..9428c37 --- /dev/null +++ b/binutils/rddbg.c @@ -0,0 +1,448 @@ +/* rddbg.c -- Read debugging information into a generic form. + Copyright (C) 1995, 96, 1997, 1998 Free Software Foundation, Inc. + Written by Ian Lance Taylor <ian@cygnus.com>. + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* This file reads debugging information into a generic form. This + file knows how to dig the debugging information out of an object + file. */ + +#include "bfd.h" +#include "bucomm.h" +#include "libiberty.h" +#include "debug.h" +#include "budbg.h" + +static boolean read_section_stabs_debugging_info + PARAMS ((bfd *, asymbol **, long, PTR, boolean *)); +static boolean read_symbol_stabs_debugging_info + PARAMS ((bfd *, asymbol **, long, PTR, boolean *)); +static boolean read_ieee_debugging_info PARAMS ((bfd *, PTR, boolean *)); +static void save_stab PARAMS ((int, int, bfd_vma, const char *)); +static void stab_context PARAMS ((void)); +static void free_saved_stabs PARAMS ((void)); + +/* Read debugging information from a BFD. Returns a generic debugging + pointer. */ + +PTR +read_debugging_info (abfd, syms, symcount) + bfd *abfd; + asymbol **syms; + long symcount; +{ + PTR dhandle; + boolean found; + + dhandle = debug_init (); + if (dhandle == NULL) + return NULL; + + if (! read_section_stabs_debugging_info (abfd, syms, symcount, dhandle, + &found)) + return NULL; + + if (bfd_get_flavour (abfd) == bfd_target_aout_flavour) + { + if (! read_symbol_stabs_debugging_info (abfd, syms, symcount, dhandle, + &found)) + return NULL; + } + + if (bfd_get_flavour (abfd) == bfd_target_ieee_flavour) + { + if (! read_ieee_debugging_info (abfd, dhandle, &found)) + return NULL; + } + + /* Try reading the COFF symbols if we didn't find any stabs in COFF + sections. */ + if (! found + && bfd_get_flavour (abfd) == bfd_target_coff_flavour + && symcount > 0) + { + if (! parse_coff (abfd, syms, symcount, dhandle)) + return NULL; + found = true; + } + + if (! found) + { + fprintf (stderr, _("%s: no recognized debugging information\n"), + bfd_get_filename (abfd)); + return NULL; + } + + return dhandle; +} + +/* Read stabs in sections debugging information from a BFD. */ + +static boolean +read_section_stabs_debugging_info (abfd, syms, symcount, dhandle, pfound) + bfd *abfd; + asymbol **syms; + long symcount; + PTR dhandle; + boolean *pfound; +{ + static struct + { + const char *secname; + const char *strsecname; + } names[] = { { ".stab", ".stabstr" } }; + unsigned int i; + PTR shandle; + + *pfound = false; + shandle = NULL; + + for (i = 0; i < sizeof names / sizeof names[0]; i++) + { + asection *sec, *strsec; + + sec = bfd_get_section_by_name (abfd, names[i].secname); + strsec = bfd_get_section_by_name (abfd, names[i].strsecname); + if (sec != NULL && strsec != NULL) + { + bfd_size_type stabsize, strsize; + bfd_byte *stabs, *strings; + bfd_byte *stab; + bfd_size_type stroff, next_stroff; + + stabsize = bfd_section_size (abfd, sec); + stabs = (bfd_byte *) xmalloc (stabsize); + if (! bfd_get_section_contents (abfd, sec, stabs, 0, stabsize)) + { + fprintf (stderr, "%s: %s: %s\n", + bfd_get_filename (abfd), names[i].secname, + bfd_errmsg (bfd_get_error ())); + return false; + } + + strsize = bfd_section_size (abfd, strsec); + strings = (bfd_byte *) xmalloc (strsize); + if (! bfd_get_section_contents (abfd, strsec, strings, 0, strsize)) + { + fprintf (stderr, "%s: %s: %s\n", + bfd_get_filename (abfd), names[i].strsecname, + bfd_errmsg (bfd_get_error ())); + return false; + } + + if (shandle == NULL) + { + shandle = start_stab (dhandle, abfd, true, syms, symcount); + if (shandle == NULL) + return false; + } + + *pfound = true; + + stroff = 0; + next_stroff = 0; + for (stab = stabs; stab < stabs + stabsize; stab += 12) + { + bfd_size_type strx; + int type; + int other; + int desc; + bfd_vma value; + + /* This code presumes 32 bit values. */ + + strx = bfd_get_32 (abfd, stab); + type = bfd_get_8 (abfd, stab + 4); + other = bfd_get_8 (abfd, stab + 5); + desc = bfd_get_16 (abfd, stab + 6); + value = bfd_get_32 (abfd, stab + 8); + + if (type == 0) + { + /* Special type 0 stabs indicate the offset to the + next string table. */ + stroff = next_stroff; + next_stroff += value; + } + else + { + char *f, *s; + + f = NULL; + s = (char *) strings + stroff + strx; + while (s[strlen (s) - 1] == '\\' + && stab + 12 < stabs + stabsize) + { + char *p; + + stab += 12; + p = s + strlen (s) - 1; + *p = '\0'; + s = concat (s, + ((char *) strings + + stroff + + bfd_get_32 (abfd, stab)), + (const char *) NULL); + + /* We have to restore the backslash, because, if + the linker is hashing stabs strings, we may + see the same string more than once. */ + *p = '\\'; + + if (f != NULL) + free (f); + f = s; + } + + save_stab (type, desc, value, s); + + if (! parse_stab (dhandle, shandle, type, desc, value, s)) + { + stab_context (); + free_saved_stabs (); + return false; + } + + /* Don't free f, since I think the stabs code + expects strings to hang around. This should be + straightened out. FIXME. */ + } + } + + free_saved_stabs (); + free (stabs); + + /* Don't free strings, since I think the stabs code expects + the strings to hang around. This should be straightened + out. FIXME. */ + } + } + + if (shandle != NULL) + { + if (! finish_stab (dhandle, shandle)) + return false; + } + + return true; +} + +/* Read stabs in the symbol table. */ + +static boolean +read_symbol_stabs_debugging_info (abfd, syms, symcount, dhandle, pfound) + bfd *abfd; + asymbol **syms; + long symcount; + PTR dhandle; + boolean *pfound; +{ + PTR shandle; + asymbol **ps, **symend; + + shandle = NULL; + symend = syms + symcount; + for (ps = syms; ps < symend; ps++) + { + symbol_info i; + + bfd_get_symbol_info (abfd, *ps, &i); + + if (i.type == '-') + { + const char *s; + char *f; + + if (shandle == NULL) + { + shandle = start_stab (dhandle, abfd, false, syms, symcount); + if (shandle == NULL) + return false; + } + + *pfound = true; + + s = i.name; + f = NULL; + while (s[strlen (s) - 1] == '\\' + && ps + 1 < symend) + { + char *sc, *n; + + ++ps; + sc = xstrdup (s); + sc[strlen (sc) - 1] = '\0'; + n = concat (sc, bfd_asymbol_name (*ps), (const char *) NULL); + free (sc); + if (f != NULL) + free (f); + f = n; + s = n; + } + + save_stab (i.stab_type, i.stab_desc, i.value, s); + + if (! parse_stab (dhandle, shandle, i.stab_type, i.stab_desc, + i.value, s)) + { + stab_context (); + free_saved_stabs (); + return false; + } + + /* Don't free f, since I think the stabs code expects + strings to hang around. This should be straightened out. + FIXME. */ + } + } + + free_saved_stabs (); + + if (shandle != NULL) + { + if (! finish_stab (dhandle, shandle)) + return false; + } + + return true; +} + +/* Read IEEE debugging information. */ + +static boolean +read_ieee_debugging_info (abfd, dhandle, pfound) + bfd *abfd; + PTR dhandle; + boolean *pfound; +{ + asection *dsec; + bfd_size_type size; + bfd_byte *contents; + + /* The BFD backend puts the debugging information into a section + named .debug. */ + + dsec = bfd_get_section_by_name (abfd, ".debug"); + if (dsec == NULL) + return true; + + size = bfd_section_size (abfd, dsec); + contents = (bfd_byte *) xmalloc (size); + if (! bfd_get_section_contents (abfd, dsec, contents, 0, size)) + return false; + + if (! parse_ieee (dhandle, abfd, contents, size)) + return false; + + free (contents); + + *pfound = true; + + return true; +} + +/* Record stabs strings, so that we can give some context for errors. */ + +#define SAVE_STABS_COUNT (16) + +struct saved_stab +{ + int type; + int desc; + bfd_vma value; + char *string; +}; + +static struct saved_stab saved_stabs[SAVE_STABS_COUNT]; +static int saved_stabs_index; + +/* Save a stabs string. */ + +static void +save_stab (type, desc, value, string) + int type; + int desc; + bfd_vma value; + const char *string; +{ + if (saved_stabs[saved_stabs_index].string != NULL) + free (saved_stabs[saved_stabs_index].string); + saved_stabs[saved_stabs_index].type = type; + saved_stabs[saved_stabs_index].desc = desc; + saved_stabs[saved_stabs_index].value = value; + saved_stabs[saved_stabs_index].string = xstrdup (string); + saved_stabs_index = (saved_stabs_index + 1) % SAVE_STABS_COUNT; +} + +/* Provide context for an error. */ + +static void +stab_context () +{ + int i; + + fprintf (stderr, _("Last stabs entries before error:\n")); + fprintf (stderr, "n_type n_desc n_value string\n"); + + i = saved_stabs_index; + do + { + struct saved_stab *stabp; + + stabp = saved_stabs + i; + if (stabp->string != NULL) + { + const char *s; + + s = bfd_get_stab_name (stabp->type); + if (s != NULL) + fprintf (stderr, "%-6s", s); + else if (stabp->type == 0) + fprintf (stderr, "HdrSym"); + else + fprintf (stderr, "%-6d", stabp->type); + fprintf (stderr, " %-6d ", stabp->desc); + fprintf_vma (stderr, stabp->value); + if (stabp->type != 0) + fprintf (stderr, " %s", stabp->string); + fprintf (stderr, "\n"); + } + i = (i + 1) % SAVE_STABS_COUNT; + } + while (i != saved_stabs_index); +} + +/* Free the saved stab strings. */ + +static void +free_saved_stabs () +{ + int i; + + for (i = 0; i < SAVE_STABS_COUNT; i++) + { + if (saved_stabs[i].string != NULL) + { + free (saved_stabs[i].string); + saved_stabs[i].string = NULL; + } + } + + saved_stabs_index = 0; +} diff --git a/binutils/readelf.c b/binutils/readelf.c new file mode 100644 index 0000000..549bf1a --- /dev/null +++ b/binutils/readelf.c @@ -0,0 +1,5682 @@ +/* readelf.c -- display contents of an ELF format file + Copyright (C) 1998, 1999 Free Software Foundation, Inc. + + Originally developed by Eric Youngdale <eric@andante.jic.com> + Modifications by Nick Clifton <nickc@cygnus.com> + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + + +#include <assert.h> +#include <sys/stat.h> +#include <stdio.h> +#include <time.h> + +#include "bfd.h" + +#include "elf/common.h" +#include "elf/external.h" +#include "elf/internal.h" +#include "elf/dwarf2.h" + +/* The following headers use the elf/reloc-macros.h file to + automatically generate relocation recognition functions + such as elf_mips_reloc_type() */ + +#define RELOC_MACROS_GEN_FUNC + +#include "elf/i386.h" +#include "elf/v850.h" +#include "elf/ppc.h" +#include "elf/mips.h" +#include "elf/alpha.h" +#include "elf/arm.h" +#include "elf/m68k.h" +#include "elf/sparc.h" +#include "elf/m32r.h" +#include "elf/d10v.h" +#include "elf/d30v.h" +#include "elf/sh.h" +#include "elf/mn10200.h" +#include "elf/mn10300.h" +#include "elf/hppa.h" +#include "elf/arc.h" +#include "elf/fr30.h" +#include "elf/mcore.h" + +#include "bucomm.h" +#include "getopt.h" + +#ifdef ANSI_PROTOTYPES +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +char * program_name = "readelf"; +unsigned int dynamic_addr; +unsigned int dynamic_size; +unsigned int rela_addr; +unsigned int rela_size; +char * dynamic_strings; +char * string_table; +Elf_Internal_Sym * dynamic_symbols; +Elf_Internal_Syminfo * dynamic_syminfo; +unsigned long dynamic_syminfo_offset; +unsigned int dynamic_syminfo_nent; +char program_interpreter [64]; +int dynamic_info[DT_JMPREL + 1]; +int version_info[16]; +int loadaddr = 0; +Elf_Internal_Ehdr elf_header; +Elf_Internal_Shdr * section_headers; +Elf_Internal_Dyn * dynamic_segment; +int show_name; +int do_dynamic; +int do_syms; +int do_reloc; +int do_sections; +int do_segments; +int do_using_dynamic; +int do_header; +int do_dump; +int do_version; +int do_histogram; +int do_debugging; +int do_debug_info; +int do_debug_abbrevs; +int do_debug_lines; +int do_debug_pubnames; +int do_debug_aranges; +int binary_class; + +/* A dynamic array of flags indicating which sections require dumping. */ +char * dump_sects = NULL; +unsigned int num_dump_sects = 0; + +#define HEX_DUMP (1 << 0) +#define DISASS_DUMP (1 << 1) +#define DEBUG_DUMP (1 << 2) + +/* Forward declarations for dumb compilers. */ +static unsigned long (* byte_get) PARAMS ((unsigned char *, int)); +static const char * get_mips_dynamic_type PARAMS ((unsigned long type)); +static const char * get_dynamic_type PARAMS ((unsigned long type)); +static int dump_relocations PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Sym *, char *)); +static char * get_file_type PARAMS ((unsigned e_type)); +static char * get_machine_name PARAMS ((unsigned e_machine)); +static char * get_machine_data PARAMS ((unsigned e_data)); +static char * get_machine_flags PARAMS ((unsigned, unsigned e_machine)); +static const char * get_mips_segment_type PARAMS ((unsigned long type)); +static const char * get_segment_type PARAMS ((unsigned long p_type)); +static const char * get_mips_section_type_name PARAMS ((unsigned int sh_type)); +static const char * get_section_type_name PARAMS ((unsigned int sh_type)); +static char * get_symbol_binding PARAMS ((unsigned int binding)); +static char * get_symbol_type PARAMS ((unsigned int type)); +static void usage PARAMS ((void)); +static void parse_args PARAMS ((int argc, char ** argv)); +static int process_file_header PARAMS ((void)); +static int process_program_headers PARAMS ((FILE *)); +static int process_section_headers PARAMS ((FILE *)); +static void dynamic_segment_mips_val PARAMS ((Elf_Internal_Dyn *entry)); +static int process_dynamic_segment PARAMS ((FILE *)); +static int process_symbol_table PARAMS ((FILE *)); +static int process_section_contents PARAMS ((FILE *)); +static void process_file PARAMS ((char * file_name)); +static int process_relocs PARAMS ((FILE *)); +static int process_version_sections PARAMS ((FILE *)); +static char * get_ver_flags PARAMS ((unsigned int flags)); +static char * get_symbol_index_type PARAMS ((unsigned int type)); +static int get_section_headers PARAMS ((FILE * file)); +static int get_file_header PARAMS ((FILE * file)); +static Elf_Internal_Sym * get_elf_symbols PARAMS ((FILE * file, unsigned long offset, unsigned long number)); +static int * get_dynamic_data PARAMS ((FILE * file, unsigned int number)); +#ifdef SUPPORT_DISASSEMBLY +static int disassemble_section PARAMS ((Elf32_Internal_Shdr *, FILE *)); +#endif +static int dump_section PARAMS ((Elf32_Internal_Shdr *, FILE *)); +static int display_debug_section PARAMS ((Elf32_Internal_Shdr *, FILE *)); +static int display_debug_info PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); +static int display_debug_not_supported PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); +static int display_debug_lines PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); +static int display_debug_abbrev PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); +static int display_debug_aranges PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); +static unsigned char * process_abbrev_section PARAMS ((unsigned char *, unsigned char *)); +static unsigned long read_leb128 PARAMS ((unsigned char *, int *, int)); +static int process_extended_line_op PARAMS ((unsigned char *, int)); +static void reset_state_machine PARAMS ((int)); +static char * get_TAG_name PARAMS ((unsigned long)); +static char * get_AT_name PARAMS ((unsigned long)); +static char * get_FORM_name PARAMS ((unsigned long)); +static void free_abbrevs PARAMS ((void)); +static void add_abbrev PARAMS ((unsigned long, unsigned long, int)); +static void add_abbrev_attr PARAMS ((unsigned long, unsigned long)); +static unsigned char * read_and_display_attr PARAMS ((unsigned long, unsigned long, unsigned char *, unsigned long)); +static unsigned char * display_block PARAMS ((unsigned char *, unsigned long)); +static void decode_location_expression PARAMS ((unsigned char *, unsigned int)); +static void request_dump PARAMS ((unsigned int, char)); +static const char * get_elf_class PARAMS ((unsigned char)); +static const char * get_data_encoding PARAMS ((unsigned char)); +static const char * get_osabi_name PARAMS ((unsigned char)); + +typedef int Elf32_Word; + +#define SECTION_NAME(X) (string_table + (X)->sh_name) + +#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ + +#define BYTE_GET(field) byte_get (field, sizeof (field)) + +#define NUM_ELEM(array) (sizeof (array) / sizeof ((array)[0])) + +#define GET_DATA_ALLOC(offset, size, var, type, reason) \ + if (fseek (file, offset, SEEK_SET)) \ + { \ + error (_("Unable to seek to start of %s at %x\n"), reason, offset); \ + return 0; \ + } \ + \ + var = (type) malloc (size); \ + \ + if (var == NULL) \ + { \ + error (_("Out of memory allocating %d bytes for %s\n"), size, reason); \ + return 0; \ + } \ + \ + if (fread (var, size, 1, file) != 1) \ + { \ + error (_("Unable to read in %d bytes of %s\n"), size, reason); \ + free (var); \ + var = NULL; \ + return 0; \ + } + + +#define GET_DATA(offset, var, reason) \ + if (fseek (file, offset, SEEK_SET)) \ + { \ + error (_("Unable to seek to %x for %s\n"), offset, reason); \ + return 0; \ + } \ + else if (fread (& var, sizeof (var), 1, file) != 1) \ + { \ + error (_("Unable to read data at %x for %s\n"), offset, reason); \ + return 0; \ + } + +#ifdef ANSI_PROTOTYPES +static void +error (const char * message, ...) +{ + va_list args; + + fprintf (stderr, _("%s: Error: "), program_name); + va_start (args, message); + vfprintf (stderr, message, args); + va_end (args); + return; +} + +static void +warn (const char * message, ...) +{ + va_list args; + + fprintf (stderr, _("%s: Warning: "), program_name); + va_start (args, message); + vfprintf (stderr, message, args); + va_end (args); + return; +} +#else +static void +error (va_alist) + va_dcl +{ + char * message; + va_list args; + + fprintf (stderr, _("%s: Error: "), program_name); + va_start (args); + message = va_arg (args, char *); + vfprintf (stderr, message, args); + va_end (args); + return; +} + +static void +warn (va_alist) + va_dcl +{ + char * message; + va_list args; + + fprintf (stderr, _("%s: Warning: "), program_name); + va_start (args); + message = va_arg (args, char *); + vfprintf (stderr, message, args); + va_end (args); + return; +} +#endif + +static unsigned long int +byte_get_little_endian (field, size) + unsigned char * field; + int size; +{ + switch (size) + { + case 1: + return * field; + + case 2: + return ((unsigned int) (field [0])) + | (((unsigned int) (field [1])) << 8); + + case 4: + return ((unsigned long) (field [0])) + | (((unsigned long) (field [1])) << 8) + | (((unsigned long) (field [2])) << 16) + | (((unsigned long) (field [3])) << 24); + + default: + error (_("Unhandled data length: %d\n"), size); + abort(); + } +} + +static unsigned long int +byte_get_big_endian (field, size) + unsigned char * field; + int size; +{ + switch (size) + { + case 1: + return * field; + + case 2: + return ((unsigned int) (field [1])) | (((int) (field [0])) << 8); + + case 4: + return ((unsigned long) (field [3])) + | (((unsigned long) (field [2])) << 8) + | (((unsigned long) (field [1])) << 16) + | (((unsigned long) (field [0])) << 24); + + default: + error (_("Unhandled data length: %d\n"), size); + abort(); + } +} + + +/* Display the contents of the relocation data + found at the specified offset. */ +static int +dump_relocations (file, rel_offset, rel_size, symtab, strtab) + FILE * file; + unsigned long rel_offset; + unsigned long rel_size; + Elf_Internal_Sym * symtab; + char * strtab; +{ + unsigned int i; + int is_rela; + Elf_Internal_Rel * rels; + Elf_Internal_Rela * relas; + + + /* Compute number of relocations and read them in. */ + switch (elf_header.e_machine) + { + /* Targets that use REL relocations. */ + case EM_ARM: + case EM_386: + case EM_486: + case EM_CYGNUS_M32R: + case EM_CYGNUS_D10V: + case EM_MIPS: + case EM_MIPS_RS4_BE: + { + Elf32_External_Rel * erels; + + GET_DATA_ALLOC (rel_offset, rel_size, erels, + Elf32_External_Rel *, "relocs"); + + rel_size = rel_size / sizeof (Elf32_External_Rel); + + rels = (Elf_Internal_Rel *) malloc (rel_size * + sizeof (Elf_Internal_Rel)); + + for (i = 0; i < rel_size; i++) + { + rels[i].r_offset = BYTE_GET (erels[i].r_offset); + rels[i].r_info = BYTE_GET (erels[i].r_info); + } + + free (erels); + + is_rela = 0; + relas = (Elf_Internal_Rela *) rels; + } + break; + + /* Targets that use RELA relocations. */ + case EM_68K: + case EM_SPARC: + case EM_PPC: + case EM_CYGNUS_V850: + case EM_CYGNUS_D30V: + case EM_CYGNUS_MN10200: + case EM_CYGNUS_MN10300: + case EM_CYGNUS_FR30: + case EM_SH: + case EM_ALPHA: + case EM_MCORE: + { + Elf32_External_Rela * erelas; + + GET_DATA_ALLOC (rel_offset, rel_size, erelas, + Elf32_External_Rela *, "relocs"); + + rel_size = rel_size / sizeof (Elf32_External_Rela); + + relas = (Elf_Internal_Rela *) malloc (rel_size * + sizeof (Elf_Internal_Rela)); + + for (i = 0; i < rel_size; i++) + { + relas[i].r_offset = BYTE_GET (erelas[i].r_offset); + relas[i].r_info = BYTE_GET (erelas[i].r_info); + relas[i].r_addend = BYTE_GET (erelas[i].r_addend); + } + + free (erelas); + + is_rela = 1; + rels = (Elf_Internal_Rel *) relas; + } + break; + + default: + warn (_("Don't know about relocations on this machine architecture\n")); + return 0; + } + + if (is_rela) + printf + (_(" Offset Info Type Symbol's Value Symbol's Name Addend\n")); + else + printf + (_(" Offset Info Type Symbol's Value Symbol's Name\n")); + + for (i = 0; i < rel_size; i++) + { + const char * rtype; + unsigned long offset; + unsigned long info; + int symtab_index; + + if (is_rela) + { + offset = relas [i].r_offset; + info = relas [i].r_info; + } + else + { + offset = rels [i].r_offset; + info = rels [i].r_info; + } + + printf (" %8.8lx %5.5lx ", offset, info); + + switch (elf_header.e_machine) + { + default: + rtype = NULL; + break; + + case EM_CYGNUS_M32R: + rtype = elf_m32r_reloc_type (ELF32_R_TYPE (info)); + break; + + case EM_386: + case EM_486: + rtype = elf_i386_reloc_type (ELF32_R_TYPE (info)); + break; + + case EM_68K: + rtype = elf_m68k_reloc_type (ELF32_R_TYPE (info)); + break; + + case EM_SPARC: + rtype = elf_sparc_reloc_type (ELF32_R_TYPE (info)); + break; + + case EM_CYGNUS_V850: + rtype = v850_reloc_type (ELF32_R_TYPE (info)); + break; + + case EM_CYGNUS_D10V: + rtype = elf_d10v_reloc_type (ELF32_R_TYPE (info)); + break; + + case EM_CYGNUS_D30V: + rtype = elf_d30v_reloc_type (ELF32_R_TYPE (info)); + break; + + case EM_SH: + rtype = elf_sh_reloc_type (ELF32_R_TYPE (info)); + break; + + case EM_CYGNUS_MN10300: + rtype = elf_mn10300_reloc_type (ELF32_R_TYPE (info)); + break; + + case EM_CYGNUS_MN10200: + rtype = elf_mn10200_reloc_type (ELF32_R_TYPE (info)); + break; + + case EM_CYGNUS_FR30: + rtype = elf_fr30_reloc_type (ELF32_R_TYPE (info)); + break; + + case EM_MCORE: + rtype = elf_mcore_reloc_type (ELF32_R_TYPE (info)); + break; + + case EM_PPC: + rtype = elf_ppc_reloc_type (ELF32_R_TYPE (info)); + break; + + case EM_MIPS: + case EM_MIPS_RS4_BE: + rtype = elf_mips_reloc_type (ELF32_R_TYPE (info)); + break; + + case EM_ALPHA: + rtype = elf_alpha_reloc_type (ELF32_R_TYPE (info)); + break; + + case EM_ARM: + rtype = elf_arm_reloc_type (ELF32_R_TYPE (info)); + break; + + case EM_CYGNUS_ARC: + rtype = elf_arc_reloc_type (ELF32_R_TYPE (info)); + break; + + case EM_PARISC: + rtype = elf32_hppa_reloc_type (ELF32_R_TYPE (info)); + break; + } + + if (rtype == NULL) + printf (_("unrecognised: %-7lx"), ELF32_R_TYPE (info)); + else + printf ("%-21.21s", rtype); + + symtab_index = ELF32_R_SYM (info); + + if (symtab_index && symtab != NULL) + { + Elf_Internal_Sym * psym; + + psym = symtab + symtab_index; + + printf (" %08lx ", (unsigned long) psym->st_value); + + if (psym->st_name == 0) + printf ("%-25.25s", + SECTION_NAME (section_headers + psym->st_shndx)); + else if (strtab == NULL) + printf (_("<string table index %3ld>"), psym->st_name); + else + printf ("%-25.25s", strtab + psym->st_name); + + if (is_rela) + printf (" + %lx", (unsigned long) relas [i].r_addend); + } + + putchar ('\n'); + } + + free (relas); + + return 1; +} + +static const char * +get_mips_dynamic_type (type) + unsigned long type; +{ + switch (type) + { + case DT_MIPS_RLD_VERSION: return "MIPS_RLD_VERSION"; + case DT_MIPS_TIME_STAMP: return "MIPS_TIME_STAMP"; + case DT_MIPS_ICHECKSUM: return "MIPS_ICHECKSUM"; + case DT_MIPS_IVERSION: return "MIPS_IVERSION"; + case DT_MIPS_FLAGS: return "MIPS_FLAGS"; + case DT_MIPS_BASE_ADDRESS: return "MIPS_BASE_ADDRESS"; + case DT_MIPS_MSYM: return "MIPS_MSYM"; + case DT_MIPS_CONFLICT: return "MIPS_CONFLICT"; + case DT_MIPS_LIBLIST: return "MIPS_LIBLIST"; + case DT_MIPS_LOCAL_GOTNO: return "MIPS_LOCAL_GOTNO"; + case DT_MIPS_CONFLICTNO: return "MIPS_CONFLICTNO"; + case DT_MIPS_LIBLISTNO: return "MIPS_LIBLISTNO"; + case DT_MIPS_SYMTABNO: return "MIPS_SYMTABNO"; + case DT_MIPS_UNREFEXTNO: return "MIPS_UNREFEXTNO"; + case DT_MIPS_GOTSYM: return "MIPS_GOTSYM"; + case DT_MIPS_HIPAGENO: return "MIPS_HIPAGENO"; + case DT_MIPS_RLD_MAP: return "MIPS_RLD_MAP"; + case DT_MIPS_DELTA_CLASS: return "MIPS_DELTA_CLASS"; + case DT_MIPS_DELTA_CLASS_NO: return "MIPS_DELTA_CLASS_NO"; + case DT_MIPS_DELTA_INSTANCE: return "MIPS_DELTA_INSTANCE"; + case DT_MIPS_DELTA_INSTANCE_NO: return "MIPS_DELTA_INSTANCE_NO"; + case DT_MIPS_DELTA_RELOC: return "MIPS_DELTA_RELOC"; + case DT_MIPS_DELTA_RELOC_NO: return "MIPS_DELTA_RELOC_NO"; + case DT_MIPS_DELTA_SYM: return "MIPS_DELTA_SYM"; + case DT_MIPS_DELTA_SYM_NO: return "MIPS_DELTA_SYM_NO"; + case DT_MIPS_DELTA_CLASSSYM: return "MIPS_DELTA_CLASSSYM"; + case DT_MIPS_DELTA_CLASSSYM_NO: return "MIPS_DELTA_CLASSSYM_NO"; + case DT_MIPS_CXX_FLAGS: return "MIPS_CXX_FLAGS"; + case DT_MIPS_PIXIE_INIT: return "MIPS_PIXIE_INIT"; + case DT_MIPS_SYMBOL_LIB: return "MIPS_SYMBOL_LIB"; + case DT_MIPS_LOCALPAGE_GOTIDX: return "MIPS_LOCALPAGE_GOTIDX"; + case DT_MIPS_LOCAL_GOTIDX: return "MIPS_LOCAL_GOTIDX"; + case DT_MIPS_HIDDEN_GOTIDX: return "MIPS_HIDDEN_GOTIDX"; + case DT_MIPS_PROTECTED_GOTIDX: return "MIPS_PROTECTED_GOTIDX"; + case DT_MIPS_OPTIONS: return "MIPS_OPTIONS"; + case DT_MIPS_INTERFACE: return "MIPS_INTERFACE"; + case DT_MIPS_DYNSTR_ALIGN: return "MIPS_DYNSTR_ALIGN"; + case DT_MIPS_INTERFACE_SIZE: return "MIPS_INTERFACE_SIZE"; + case DT_MIPS_RLD_TEXT_RESOLVE_ADDR: return "MIPS_RLD_TEXT_RESOLVE_ADDR"; + case DT_MIPS_PERF_SUFFIX: return "MIPS_PERF_SUFFIX"; + case DT_MIPS_COMPACT_SIZE: return "MIPS_COMPACT_SIZE"; + case DT_MIPS_GP_VALUE: return "MIPS_GP_VALUE"; + case DT_MIPS_AUX_DYNAMIC: return "MIPS_AUX_DYNAMIC"; + default: + return NULL; + } +} + +static const char * +get_dynamic_type (type) + unsigned long type; +{ + static char buff [32]; + + switch (type) + { + case DT_NULL: return "NULL"; + case DT_NEEDED: return "NEEDED"; + case DT_PLTRELSZ: return "PLTRELSZ"; + case DT_PLTGOT: return "PLTGOT"; + case DT_HASH: return "HASH"; + case DT_STRTAB: return "STRTAB"; + case DT_SYMTAB: return "SYMTAB"; + case DT_RELA: return "RELA"; + case DT_RELASZ: return "RELASZ"; + case DT_RELAENT: return "RELAENT"; + case DT_STRSZ: return "STRSZ"; + case DT_SYMENT: return "SYMENT"; + case DT_INIT: return "INIT"; + case DT_FINI: return "FINI"; + case DT_SONAME: return "SONAME"; + case DT_RPATH: return "RPATH"; + case DT_SYMBOLIC: return "SYMBOLIC"; + case DT_REL: return "REL"; + case DT_RELSZ: return "RELSZ"; + case DT_RELENT: return "RELENT"; + case DT_PLTREL: return "PLTREL"; + case DT_DEBUG: return "DEBUG"; + case DT_TEXTREL: return "TEXTREL"; + case DT_JMPREL: return "JMPREL"; + case DT_BIND_NOW: return "BIND_NOW"; + case DT_INIT_ARRAY: return "INIT_ARRAY"; + case DT_FINI_ARRAY: return "FINI_ARRAY"; + case DT_INIT_ARRAYSZ: return "INIT_ARRAYSZ"; + case DT_FINI_ARRAYSZ: return "FINI_ARRAYSZ"; + + case DT_PLTPADSZ: return "PLTPADSZ"; + case DT_MOVEENT: return "MOVEENT"; + case DT_MOVESZ: return "MOVESZ"; + case DT_FEATURE_1: return "FEATURE_1"; + case DT_POSFLAG_1: return "POSFLAG_1"; + case DT_SYMINSZ: return "SYMINSZ"; + case DT_SYMINENT: return "SYMINENT"; /* aka VALRNGHI */ + + case DT_ADDRRNGLO: return "ADDRRNGLO"; + case DT_SYMINFO: return "SYMINFO"; /* aka ADDRRNGHI */ + + case DT_VERSYM: return "VERSYM"; + + case DT_RELACOUNT: return "RELACOUNT"; + case DT_RELCOUNT: return "RELCOUNT"; + case DT_FLAGS_1: return "FLAGS_1"; + case DT_VERDEF: return "VERDEF"; + case DT_VERDEFNUM: return "VERDEFNUM"; + case DT_VERNEED: return "VERNEED"; + case DT_VERNEEDNUM: return "VERNEEDNUM"; + + case DT_AUXILIARY: return "AUXILARY"; + case DT_USED: return "USED"; + case DT_FILTER: return "FILTER"; + + default: + if ((type >= DT_LOPROC) && (type <= DT_HIPROC)) + { + const char * result; + + switch (elf_header.e_machine) + { + case EM_MIPS: + case EM_MIPS_RS4_BE: + result = get_mips_dynamic_type (type); + break; + default: + result = NULL; + break; + } + + if (result != NULL) + return result; + + sprintf (buff, _("Processor Specific: %lx"), type); + } + else if ((type >= DT_LOOS) && (type <= DT_HIOS)) + sprintf (buff, _("Operating System specific: %lx"), type); + else + sprintf (buff, _("<unknown>: %lx"), type); + + return buff; + } +} + +static char * +get_file_type (e_type) + unsigned e_type; +{ + static char buff [32]; + + switch (e_type) + { + case ET_NONE: return _("NONE (None)"); + case ET_REL: return _("REL (Relocatable file)"); + case ET_EXEC: return _("EXEC (Executable file)"); + case ET_DYN: return _("DYN (Shared object file)"); + case ET_CORE: return _("CORE (Core file)"); + + default: + if ((e_type >= ET_LOPROC) && (e_type <= ET_HIPROC)) + sprintf (buff, _("Processor Specific: (%x)"), e_type); + else if ((e_type >= ET_LOOS) && (e_type <= ET_HIOS)) + sprintf (buff, _("OS Specific: (%x)"), e_type); + else + sprintf (buff, _("<unknown>: %x"), e_type); + return buff; + } +} + +static char * +get_machine_name (e_machine) + unsigned e_machine; +{ + static char buff [32]; + + switch (e_machine) + { + case EM_NONE: return _("None"); + case EM_M32: return "WE32100"; + case EM_SPARC: return "Sparc"; + case EM_386: return "Intel 80386"; + case EM_68K: return "MC68000"; + case EM_88K: return "MC88000"; + case EM_486: return "Intel 80486"; + case EM_860: return "Intel 80860"; + case EM_MIPS: return "MIPS R3000 big-endian"; + case EM_S370: return "Amdahl"; + case EM_MIPS_RS4_BE: return "MIPS R4000 big-endian"; + case EM_OLD_SPARCV9: return "Sparc v9 (old)"; + case EM_PARISC: return "HPPA"; + case EM_PPC_OLD: return "Power PC (old)"; + case EM_SPARC32PLUS: return "Sparc v8+" ; + case EM_960: return "Intel 90860"; + case EM_PPC: return "PowerPC"; + case EM_V800: return "NEC V800"; + case EM_FR20: return "Fujitsu FR20"; + case EM_RH32: return "TRW RH32"; + case EM_MCORE: return "MCORE"; + case EM_ARM: return "ARM"; + case EM_OLD_ALPHA: return "Digital Alpha (old)"; + case EM_SH: return "Hitachi SH"; + case EM_SPARCV9: return "Sparc v9"; + case EM_TRICORE: return "Siemens Tricore"; + case EM_ARC: return "Argonaut RISC Core"; + case EM_H8_300: return "Hitachi H8/300"; + case EM_H8_300H: return "Hitachi H8/300H"; + case EM_H8S: return "Hitachi H8S"; + case EM_H8_500: return "Hitachi H8/500"; + case EM_IA_64: return "Intel Merced"; + case EM_MIPS_X: return "Stanford MIPS-X"; + case EM_COLDFIRE: return "Motorola Coldfire"; + case EM_68HC12: return "Motorola M68HC12"; + case EM_ALPHA: return "Alpha"; + case EM_CYGNUS_D10V: return "d10v"; + case EM_CYGNUS_D30V: return "d30v"; + case EM_CYGNUS_ARC: return "Arc"; + case EM_CYGNUS_M32R: return "Mitsubishi M32r"; + case EM_CYGNUS_V850: return "NEC v850"; + case EM_CYGNUS_MN10300: return "mn10300"; + case EM_CYGNUS_MN10200: return "mn10200"; + case EM_CYGNUS_FR30: return "Fujitsu FR30"; + + default: + sprintf (buff, _("<unknown>: %x"), e_machine); + return buff; + } +} + +static char * +get_machine_flags (e_flags, e_machine) + unsigned e_flags; + unsigned e_machine; +{ + static char buf [1024]; + + buf[0] = '\0'; + if (e_flags) + { + switch (e_machine) + { + default: + break; + + case EM_PPC: + if (e_flags & EF_PPC_EMB) + strcat (buf, ", emb"); + + if (e_flags & EF_PPC_RELOCATABLE) + strcat (buf, ", relocatable"); + + if (e_flags & EF_PPC_RELOCATABLE_LIB) + strcat (buf, ", relocatable-lib"); + break; + + case EM_CYGNUS_V850: + switch (e_flags & EF_V850_ARCH) + { + case E_V850E_ARCH: + strcat (buf, ", v850e"); + break; + case E_V850EA_ARCH: + strcat (buf, ", v850ea"); + break; + case E_V850_ARCH: + strcat (buf, ", v850"); + break; + default: + strcat (buf, ", unknown v850 architecture variant"); + break; + } + break; + + case EM_CYGNUS_M32R: + if ((e_flags & EF_M32R_ARCH) == E_M32R_ARCH) + strcat (buf, ", m32r"); + + break; + + case EM_MIPS: + case EM_MIPS_RS4_BE: + if (e_flags & EF_MIPS_NOREORDER) + strcat (buf, ", noreorder"); + + if (e_flags & EF_MIPS_PIC) + strcat (buf, ", pic"); + + if (e_flags & EF_MIPS_CPIC) + strcat (buf, ", cpic"); + + if (e_flags & EF_MIPS_ABI2) + strcat (buf, ", abi2"); + + if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_1) + strcat (buf, ", mips1"); + + if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_2) + strcat (buf, ", mips2"); + + if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_3) + strcat (buf, ", mips3"); + + if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_4) + strcat (buf, ", mips4"); + break; + } + } + + return buf; +} + +static char * +get_machine_data (e_data) + unsigned e_data; +{ + static char buff [32]; + + switch (e_data) + { + case ELFDATA2LSB: return _("ELFDATA2LSB (little endian)"); + case ELFDATA2MSB: return _("ELFDATA2MSB (big endian)"); + default: + sprintf (buff, _("<unknown>: %x"), e_data); + return buff; + } +} + +static const char * +get_mips_segment_type (type) + unsigned long type; +{ + switch (type) + { + case PT_MIPS_REGINFO: + return "REGINFO"; + case PT_MIPS_RTPROC: + return "RTPROC"; + case PT_MIPS_OPTIONS: + return "OPTIONS"; + default: + break; + } + + return NULL; +} + +static const char * +get_segment_type (p_type) + unsigned long p_type; +{ + static char buff [32]; + + switch (p_type) + { + case PT_NULL: return "NULL"; + case PT_LOAD: return "LOAD"; + case PT_DYNAMIC: return "DYNAMIC"; + case PT_INTERP: return "INTERP"; + case PT_NOTE: return "NOTE"; + case PT_SHLIB: return "SHLIB"; + case PT_PHDR: return "PHDR"; + + default: + if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC)) + { + const char * result; + + switch (elf_header.e_machine) + { + case EM_MIPS: + case EM_MIPS_RS4_BE: + result = get_mips_segment_type (p_type); + break; + default: + result = NULL; + break; + } + + if (result != NULL) + return result; + + sprintf (buff, "LOPROC+%lx", p_type - PT_LOPROC); + } + else if ((p_type >= PT_LOOS) && (p_type <= PT_HIOS)) + sprintf (buff, "LOOS+%lx", p_type - PT_LOOS); + else + sprintf (buff, _("<unknown>: %lx"), p_type); + + return buff; + } +} + +static const char * +get_mips_section_type_name (sh_type) + unsigned int sh_type; +{ + switch (sh_type) + { + case SHT_MIPS_LIBLIST: return "MIPS_LIBLIST"; + case SHT_MIPS_MSYM: return "MIPS_MSYM"; + case SHT_MIPS_CONFLICT: return "MIPS_CONFLICT"; + case SHT_MIPS_GPTAB: return "MIPS_GPTAB"; + case SHT_MIPS_UCODE: return "MIPS_UCODE"; + case SHT_MIPS_DEBUG: return "MIPS_DEBUG"; + case SHT_MIPS_REGINFO: return "MIPS_REGINFO"; + case SHT_MIPS_PACKAGE: return "MIPS_PACKAGE"; + case SHT_MIPS_PACKSYM: return "MIPS_PACKSYM"; + case SHT_MIPS_RELD: return "MIPS_RELD"; + case SHT_MIPS_IFACE: return "MIPS_IFACE"; + case SHT_MIPS_CONTENT: return "MIPS_CONTENT"; + case SHT_MIPS_OPTIONS: return "MIPS_OPTIONS"; + case SHT_MIPS_SHDR: return "MIPS_SHDR"; + case SHT_MIPS_FDESC: return "MIPS_FDESC"; + case SHT_MIPS_EXTSYM: return "MIPS_EXTSYM"; + case SHT_MIPS_DENSE: return "MIPS_DENSE"; + case SHT_MIPS_PDESC: return "MIPS_PDESC"; + case SHT_MIPS_LOCSYM: return "MIPS_LOCSYM"; + case SHT_MIPS_AUXSYM: return "MIPS_AUXSYM"; + case SHT_MIPS_OPTSYM: return "MIPS_OPTSYM"; + case SHT_MIPS_LOCSTR: return "MIPS_LOCSTR"; + case SHT_MIPS_LINE: return "MIPS_LINE"; + case SHT_MIPS_RFDESC: return "MIPS_RFDESC"; + case SHT_MIPS_DELTASYM: return "MIPS_DELTASYM"; + case SHT_MIPS_DELTAINST: return "MIPS_DELTAINST"; + case SHT_MIPS_DELTACLASS: return "MIPS_DELTACLASS"; + case SHT_MIPS_DWARF: return "MIPS_DWARF"; + case SHT_MIPS_DELTADECL: return "MIPS_DELTADECL"; + case SHT_MIPS_SYMBOL_LIB: return "MIPS_SYMBOL_LIB"; + case SHT_MIPS_EVENTS: return "MIPS_EVENTS"; + case SHT_MIPS_TRANSLATE: return "MIPS_TRANSLATE"; + case SHT_MIPS_PIXIE: return "MIPS_PIXIE"; + case SHT_MIPS_XLATE: return "MIPS_XLATE"; + case SHT_MIPS_XLATE_DEBUG: return "MIPS_XLATE_DEBUG"; + case SHT_MIPS_WHIRL: return "MIPS_WHIRL"; + case SHT_MIPS_EH_REGION: return "MIPS_EH_REGION"; + case SHT_MIPS_XLATE_OLD: return "MIPS_XLATE_OLD"; + case SHT_MIPS_PDR_EXCEPTION: return "MIPS_PDR_EXCEPTION"; + default: + break; + } + return NULL; +} + +static const char * +get_section_type_name (sh_type) + unsigned int sh_type; +{ + static char buff [32]; + + switch (sh_type) + { + case SHT_NULL: return "NULL"; + case SHT_PROGBITS: return "PROGBITS"; + case SHT_SYMTAB: return "SYMTAB"; + case SHT_STRTAB: return "STRTAB"; + case SHT_RELA: return "RELA"; + case SHT_HASH: return "HASH"; + case SHT_DYNAMIC: return "DYNAMIC"; + case SHT_NOTE: return "NOTE"; + case SHT_NOBITS: return "NOBITS"; + case SHT_REL: return "REL"; + case SHT_SHLIB: return "SHLIB"; + case SHT_DYNSYM: return "DYNSYM"; + case SHT_GNU_verdef: return "VERDEF"; + case SHT_GNU_verneed: return "VERNEED"; + case SHT_GNU_versym: return "VERSYM"; + case 0x6ffffff0: return "VERSYM"; + case 0x6ffffffc: return "VERDEF"; + case 0x7ffffffd: return "AUXILIARY"; + case 0x7fffffff: return "FILTER"; + + default: + if ((sh_type >= SHT_LOPROC) && (sh_type <= SHT_HIPROC)) + { + const char * result; + + switch (elf_header.e_machine) + { + case EM_MIPS: + case EM_MIPS_RS4_BE: + result = get_mips_section_type_name (sh_type); + break; + default: + result = NULL; + break; + } + + if (result != NULL) + return result; + + sprintf (buff, "SHT_LOPROC+%x", sh_type - SHT_LOPROC); + } + else if ((sh_type >= SHT_LOOS) && (sh_type <= SHT_HIOS)) + sprintf (buff, "SHT_LOOS+%x", sh_type - SHT_LOOS); + else if ((sh_type >= SHT_LOUSER) && (sh_type <= SHT_HIUSER)) + sprintf (buff, "SHT_LOUSER+%x", sh_type - SHT_LOUSER); + else + sprintf (buff, _("<unknown>: %x"), sh_type); + + return buff; + } +} + +struct option options [] = +{ + {"all", no_argument, 0, 'a'}, + {"file-header", no_argument, 0, 'h'}, + {"program-headers", no_argument, 0, 'l'}, + {"headers", no_argument, 0, 'e'}, + {"histogram", no_argument, & do_histogram, 1}, + {"segments", no_argument, 0, 'l'}, + {"sections", no_argument, 0, 'S'}, + {"section-headers", no_argument, 0, 'S'}, + {"symbols", no_argument, 0, 's'}, + {"syms", no_argument, 0, 's'}, + {"relocs", no_argument, 0, 'r'}, + {"dynamic", no_argument, 0, 'd'}, + {"version-info", no_argument, 0, 'V'}, + {"use-dynamic", no_argument, 0, 'D'}, + {"hex-dump", required_argument, 0, 'x'}, + {"debug-dump", optional_argument, 0, 'w'}, +#ifdef SUPPORT_DISASSEMBLY + {"instruction-dump", required_argument, 0, 'i'}, +#endif + + {"version", no_argument, 0, 'v'}, + {"help", no_argument, 0, 'H'}, + {0, no_argument, 0, 0} +}; + +static void +usage () +{ + fprintf (stdout, _("Usage: readelf {options} elf-file(s)\n")); + fprintf (stdout, _(" Options are:\n")); + fprintf (stdout, _(" -a or --all Equivalent to: -h -l -S -s -r -d -V --histogram\n")); + fprintf (stdout, _(" -h or --file-header Display the ELF file header\n")); + fprintf (stdout, _(" -l or --program-headers or --segments\n")); + fprintf (stdout, _(" Display the program headers\n")); + fprintf (stdout, _(" -S or --section-headers or --sections\n")); + fprintf (stdout, _(" Display the sections' header\n")); + fprintf (stdout, _(" -e or --headers Equivalent to: -h -l -S\n")); + fprintf (stdout, _(" -s or --syms or --symbols Display the symbol table\n")); + fprintf (stdout, _(" -r or --relocs Display the relocations (if present)\n")); + fprintf (stdout, _(" -d or --dynamic Display the dynamic segment (if present)\n")); + fprintf (stdout, _(" -V or --version-info Display the version sections (if present)\n")); + fprintf (stdout, _(" -D or --use-dynamic Use the dynamic section info when displaying symbols\n")); + fprintf (stdout, _(" -x <number> or --hex-dump=<number>\n")); + fprintf (stdout, _(" Dump the contents of section <number>\n")); + fprintf (stdout, _(" -w[liapr] or --debug-dump[=line,=info,=abbrev,=pubnames,=ranges]\n")); + fprintf (stdout, _(" Display the contents of DWARF2 debug sections\n")); +#ifdef SUPPORT_DISASSEMBLY + fprintf (stdout, _(" -i <number> or --instruction-dump=<number>\n")); + fprintf (stdout, _(" Disassemble the contents of section <number>\n")); +#endif + fprintf (stdout, _(" --histogram Display histogram of bucket list lengths\n")); + fprintf (stdout, _(" -v or --version Display the version number of readelf\n")); + fprintf (stdout, _(" -H or --help Display this information\n")); + fprintf (stdout, _("Report bugs to bug-gnu-utils@gnu.org\n")); + + exit (0); +} + +static void +request_dump (section, type) + unsigned int section; + char type; +{ + if (section >= num_dump_sects) + { + char * new_dump_sects; + + new_dump_sects = (char *) calloc (section + 1, 1); + + if (new_dump_sects == NULL) + error (_("Out of memory allocating dump request table.")); + else + { + /* Copy current flag settings. */ + memcpy (new_dump_sects, dump_sects, num_dump_sects); + + free (dump_sects); + + dump_sects = new_dump_sects; + num_dump_sects = section + 1; + } + } + + if (dump_sects) + dump_sects [section] |= type; + + return; +} + +static void +parse_args (argc, argv) + int argc; + char ** argv; +{ + int c; + + if (argc < 2) + usage (); + + while ((c = getopt_long + (argc, argv, "ersahldSDw::x:i:vV", options, NULL)) != EOF) + { + char * cp; + int section; + + switch (c) + { + case 0: + /* Long options. */ + break; + case 'H': + usage (); + break; + + case 'a': + do_syms ++; + do_reloc ++; + do_dynamic ++; + do_header ++; + do_sections ++; + do_segments ++; + do_version ++; + do_histogram ++; + break; + case 'e': + do_header ++; + do_sections ++; + do_segments ++; + break; + case 'D': + do_using_dynamic ++; + break; + case 'r': + do_reloc ++; + break; + case 'h': + do_header ++; + break; + case 'l': + do_segments ++; + break; + case 's': + do_syms ++; + break; + case 'S': + do_sections ++; + break; + case 'd': + do_dynamic ++; + break; + case 'x': + do_dump ++; + section = strtoul (optarg, & cp, 0); + if (! * cp && section >= 0) + { + request_dump (section, HEX_DUMP); + break; + } + goto oops; + case 'w': + do_dump ++; + if (optarg == 0) + do_debugging = 1; + else + { + do_debugging = 0; + switch (optarg[0]) + { + case 'i': + case 'I': + do_debug_info = 1; + break; + + case 'a': + case 'A': + do_debug_abbrevs = 1; + break; + + case 'l': + case 'L': + do_debug_lines = 1; + break; + + case 'p': + case 'P': + do_debug_pubnames = 1; + break; + + case 'r': + case 'R': + do_debug_aranges = 1; + break; + + default: + warn (_("Unrecognised debug option '%s'\n"), optarg); + break; + } + } + break; +#ifdef SUPPORT_DISASSEMBLY + case 'i': + do_dump ++; + section = strtoul (optarg, & cp, 0); + if (! * cp && section >= 0) + { + request_dump (section, DISASS_DUMP); + break; + } + goto oops; +#endif + case 'v': + print_version (program_name); + break; + case 'V': + do_version ++; + break; + default: + oops: + /* xgettext:c-format */ + error (_("Invalid option '-%c'\n"), c); + /* Drop through. */ + case '?': + usage (); + } + } + + if (!do_dynamic && !do_syms && !do_reloc && !do_sections + && !do_segments && !do_header && !do_dump && !do_version + && !do_histogram && !do_debugging) + usage (); + else if (argc < 3) + { + warn (_("Nothing to do.\n")); + usage(); + } +} + +static const char * +get_elf_class (elf_class) + unsigned char elf_class; +{ + switch (elf_class) + { + case ELFCLASSNONE: return _("none"); + case ELFCLASS32: return _("ELF32"); + case ELFCLASS64: return _("ELF64"); + default: return _("<unknown>"); + } +} + +static const char * +get_data_encoding (encoding) + unsigned char encoding; +{ + switch (encoding) + { + case ELFDATANONE: return _("none"); + case ELFDATA2LSB: return _("2's compilment, little endian"); + case ELFDATA2MSB: return _("2's compilment, big endian"); + default: return _("<unknown>"); + } +} + +static const char * +get_osabi_name (osabi) + unsigned char osabi; +{ + switch (osabi) + { + case ELFOSABI_SYSV: return _("UNIX - System V"); + case ELFOSABI_HPUX: return _("UNIX - HP-UX"); + case ELFOSABI_STANDALONE: return _("Standalone App"); + default: return _("<unknown>"); + } +} + +/* Decode the data held in 'elf_header'. */ +static int +process_file_header () +{ + if ( elf_header.e_ident [EI_MAG0] != ELFMAG0 + || elf_header.e_ident [EI_MAG1] != ELFMAG1 + || elf_header.e_ident [EI_MAG2] != ELFMAG2 + || elf_header.e_ident [EI_MAG3] != ELFMAG3) + { + error + (_("Not an ELF file - it has the wrong magic bytes at the start\n")); + return 0; + } + + if (do_header) + { + int i; + + printf (_("ELF Header:\n")); + printf (_(" Magic: ")); + for (i = 0; i < EI_NIDENT; i ++) + printf ("%2.2x ", elf_header.e_ident [i]); + printf ("\n"); + printf (_(" Class: %s\n"), + get_elf_class (elf_header.e_ident [EI_CLASS])); + printf (_(" Data: %s\n"), + get_data_encoding (elf_header.e_ident [EI_DATA])); + printf (_(" Version: %d %s\n"), + elf_header.e_ident [EI_VERSION], + elf_header.e_ident [EI_VERSION] == EV_CURRENT ? "(current)" : + elf_header.e_ident [EI_VERSION] != EV_NONE ? "<unknown>" : ""); + printf (_(" OS/ABI: %s\n"), + get_osabi_name (elf_header.e_ident [EI_OSABI])); + printf (_(" ABI Version: %d\n"), + elf_header.e_ident [EI_ABIVERSION]); + printf (_(" Type: %s\n"), + get_file_type (elf_header.e_type)); + printf (_(" Machine: %s\n"), + get_machine_name (elf_header.e_machine)); + printf (_(" Version: 0x%lx\n"), + (unsigned long) elf_header.e_version); + printf (_(" Data: %s\n"), + get_machine_data (elf_header.e_ident [EI_DATA])); + printf (_(" Entry point address: 0x%lx\n"), + (unsigned long) elf_header.e_entry); + printf (_(" Start of program headers: %ld (bytes into file)\n"), + (long) elf_header.e_phoff); + printf (_(" Start of section headers: %ld (bytes into file)\n"), + (long) elf_header.e_shoff); + printf (_(" Flags: 0x%lx%s\n"), + (unsigned long) elf_header.e_flags, + get_machine_flags (elf_header.e_flags, elf_header.e_machine)); + printf (_(" Size of this header: %ld (bytes)\n"), + (long) elf_header.e_ehsize); + printf (_(" Size of program headers: %ld (bytes)\n"), + (long) elf_header.e_phentsize); + printf (_(" Number of program headers: %ld\n"), + (long) elf_header.e_phnum); + printf (_(" Size of section headers: %ld (bytes)\n"), + (long) elf_header.e_shentsize); + printf (_(" Number of section headers: %ld\n"), + (long) elf_header.e_shnum); + printf (_(" Section header string table index: %ld\n"), + (long) elf_header.e_shstrndx); + } + + /* Test class after dumping header so that at least the header can be + display on 64 bit binaries. */ + + binary_class = elf_header.e_ident [EI_CLASS]; + if (binary_class != ELFCLASS32) + { + error (_("Not a 32 bit ELF file\n")); + return 0; + } + + return 1; +} + + +static int +process_program_headers (file) + FILE * file; +{ + Elf32_External_Phdr * phdrs; + Elf32_Internal_Phdr * program_headers; + Elf32_Internal_Phdr * segment; + unsigned int i; + + if (elf_header.e_phnum == 0) + { + if (do_segments) + printf (_("\nThere are no program headers in this file.\n")); + return 1; + } + + if (do_segments && !do_header) + { + printf (_("\nElf file is %s\n"), get_file_type (elf_header.e_type)); + printf (_("Entry point 0x%lx\n"), (unsigned long) elf_header.e_entry); + printf (_("There are %d program headers, starting at offset %lx:\n"), + elf_header.e_phnum, (unsigned long) elf_header.e_phoff); + } + + GET_DATA_ALLOC (elf_header.e_phoff, + elf_header.e_phentsize * elf_header.e_phnum, + phdrs, Elf32_External_Phdr *, "program headers"); + + program_headers = (Elf32_Internal_Phdr *) malloc + (elf_header.e_phnum * sizeof (Elf32_Internal_Phdr)); + + if (program_headers == NULL) + { + error (_("Out of memory\n")); + return 0; + } + + for (i = 0, segment = program_headers; + i < elf_header.e_phnum; + i ++, segment ++) + { + segment->p_type = BYTE_GET (phdrs[i].p_type); + segment->p_offset = BYTE_GET (phdrs[i].p_offset); + segment->p_vaddr = BYTE_GET (phdrs[i].p_vaddr); + segment->p_paddr = BYTE_GET (phdrs[i].p_paddr); + segment->p_filesz = BYTE_GET (phdrs[i].p_filesz); + segment->p_memsz = BYTE_GET (phdrs[i].p_memsz); + segment->p_flags = BYTE_GET (phdrs[i].p_flags); + segment->p_align = BYTE_GET (phdrs[i].p_align); + } + + free (phdrs); + + if (do_segments) + { + printf + (_("\nProgram Header%s:\n"), elf_header.e_phnum > 1 ? "s" : ""); + printf + (_(" Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align\n")); + } + + loadaddr = -1; + dynamic_addr = 0; + + for (i = 0, segment = program_headers; + i < elf_header.e_phnum; + i ++, segment ++) + { + if (do_segments) + { + printf (" %-11.11s ", get_segment_type (segment->p_type)); + printf ("0x%6.6lx ", (unsigned long) segment->p_offset); + printf ("0x%8.8lx ", (unsigned long) segment->p_vaddr); + printf ("0x%8.8lx ", (unsigned long) segment->p_paddr); + printf ("0x%5.5lx ", (unsigned long) segment->p_filesz); + printf ("0x%5.5lx ", (unsigned long) segment->p_memsz); + printf ("%c%c%c ", + (segment->p_flags & PF_R ? 'R' : ' '), + (segment->p_flags & PF_W ? 'W' : ' '), + (segment->p_flags & PF_X ? 'E' : ' ')); + printf ("%#lx", (unsigned long) segment->p_align); + } + + switch (segment->p_type) + { + case PT_LOAD: + if (loadaddr == -1) + loadaddr = (segment->p_vaddr & 0xfffff000) + - (segment->p_offset & 0xfffff000); + break; + + case PT_DYNAMIC: + if (dynamic_addr) + error (_("more than one dynamic segment\n")); + + dynamic_addr = segment->p_offset; + dynamic_size = segment->p_filesz; + break; + + case PT_INTERP: + if (fseek (file, segment->p_offset, SEEK_SET)) + error (_("Unable to find program interpreter name\n")); + else + { + program_interpreter[0] = 0; + fscanf (file, "%63s", program_interpreter); + + if (do_segments) + printf (_("\n [Requesting program interpreter: %s]"), + program_interpreter); + } + break; + } + + if (do_segments) + putc ('\n', stdout); + } + + if (loadaddr == -1) + { + /* Very strange. */ + loadaddr = 0; + } + + if (do_segments && section_headers != NULL) + { + printf (_("\n Section to Segment mapping:\n")); + printf (_(" Segment Sections...\n")); + + assert (string_table != NULL); + + for (i = 0; i < elf_header.e_phnum; i++) + { + int j; + Elf32_Internal_Shdr * section; + + segment = program_headers + i; + section = section_headers; + + printf (" %2.2d ", i); + + for (j = 0; j < elf_header.e_shnum; j++, section ++) + { + if (section->sh_size > 0 + /* Compare allocated sections by VMA, unallocated + sections by file offset. */ + && (section->sh_flags & SHF_ALLOC + ? (section->sh_addr >= segment->p_vaddr + && section->sh_addr + section->sh_size + <= segment->p_vaddr + segment->p_memsz) + : (section->sh_offset >= segment->p_offset + && (section->sh_offset + section->sh_size + <= segment->p_offset + segment->p_filesz)))) + printf ("%s ", SECTION_NAME (section)); + } + + putc ('\n',stdout); + } + } + + free (program_headers); + + return 1; +} + + +static int +get_section_headers (file) + FILE * file; +{ + Elf32_External_Shdr * shdrs; + Elf32_Internal_Shdr * internal; + unsigned int i; + + GET_DATA_ALLOC (elf_header.e_shoff, + elf_header.e_shentsize * elf_header.e_shnum, + shdrs, Elf32_External_Shdr *, "section headers"); + + section_headers = (Elf32_Internal_Shdr *) malloc + (elf_header.e_shnum * sizeof (Elf32_Internal_Shdr)); + + if (section_headers == NULL) + { + error (_("Out of memory\n")); + return 0; + } + + for (i = 0, internal = section_headers; + i < elf_header.e_shnum; + i ++, internal ++) + { + internal->sh_name = BYTE_GET (shdrs[i].sh_name); + internal->sh_type = BYTE_GET (shdrs[i].sh_type); + internal->sh_flags = BYTE_GET (shdrs[i].sh_flags); + internal->sh_addr = BYTE_GET (shdrs[i].sh_addr); + internal->sh_offset = BYTE_GET (shdrs[i].sh_offset); + internal->sh_size = BYTE_GET (shdrs[i].sh_size); + internal->sh_link = BYTE_GET (shdrs[i].sh_link); + internal->sh_info = BYTE_GET (shdrs[i].sh_info); + internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign); + internal->sh_entsize = BYTE_GET (shdrs[i].sh_entsize); + } + + free (shdrs); + + return 1; +} + +static Elf_Internal_Sym * +get_elf_symbols (file, offset, number) + FILE * file; + unsigned long offset; + unsigned long number; +{ + Elf32_External_Sym * esyms; + Elf_Internal_Sym * isyms; + Elf_Internal_Sym * psym; + unsigned int j; + + GET_DATA_ALLOC (offset, number * sizeof (Elf32_External_Sym), + esyms, Elf32_External_Sym *, "symbols"); + + isyms = (Elf_Internal_Sym *) malloc (number * sizeof (Elf_Internal_Sym)); + + if (isyms == NULL) + { + error (_("Out of memory\n")); + free (esyms); + + return NULL; + } + + for (j = 0, psym = isyms; + j < number; + j ++, psym ++) + { + psym->st_name = BYTE_GET (esyms[j].st_name); + psym->st_value = BYTE_GET (esyms[j].st_value); + psym->st_size = BYTE_GET (esyms[j].st_size); + psym->st_shndx = BYTE_GET (esyms[j].st_shndx); + psym->st_info = BYTE_GET (esyms[j].st_info); + psym->st_other = BYTE_GET (esyms[j].st_other); + } + + free (esyms); + + return isyms; +} + +static int +process_section_headers (file) + FILE * file; +{ + Elf32_Internal_Shdr * section; + int i; + + section_headers = NULL; + + if (elf_header.e_shnum == 0) + { + if (do_sections) + printf (_("\nThere are no sections in this file.\n")); + + return 1; + } + + if (do_sections && !do_header) + printf (_("There are %d section headers, starting at offset %lx:\n"), + elf_header.e_shnum, (unsigned long) elf_header.e_shoff); + + if (! get_section_headers (file)) + return 0; + + /* Read in the string table, so that we have names to display. */ + section = section_headers + elf_header.e_shstrndx; + + if (section->sh_size != 0) + { + unsigned long string_table_offset; + + string_table_offset = section->sh_offset; + + GET_DATA_ALLOC (section->sh_offset, section->sh_size, + string_table, char *, "string table"); + } + + /* Scan the sections for the dynamic symbol table + and dynamic string table and debug sections. */ + dynamic_symbols = NULL; + dynamic_strings = NULL; + dynamic_syminfo = NULL; + for (i = 0, section = section_headers; + i < elf_header.e_shnum; + i ++, section ++) + { + char * name = SECTION_NAME (section); + + if (section->sh_type == SHT_DYNSYM) + { + if (dynamic_symbols != NULL) + { + error (_("File contains multiple dynamic symbol tables\n")); + continue; + } + + dynamic_symbols = get_elf_symbols + (file, section->sh_offset, + section->sh_size / section->sh_entsize); + } + else if (section->sh_type == SHT_STRTAB + && strcmp (name, ".dynstr") == 0) + { + if (dynamic_strings != NULL) + { + error (_("File contains multiple dynamic string tables\n")); + continue; + } + + GET_DATA_ALLOC (section->sh_offset, section->sh_size, + dynamic_strings, char *, "dynamic strings"); + } + else if ((do_debugging || do_debug_info || do_debug_abbrevs + || do_debug_lines || do_debug_pubnames || do_debug_aranges) + && strncmp (name, ".debug_", 7) == 0) + { + name += 7; + + if (do_debugging + || (do_debug_info && (strcmp (name, "info") == 0)) + || (do_debug_abbrevs && (strcmp (name, "abbrev") == 0)) + || (do_debug_lines && (strcmp (name, "line") == 0)) + || (do_debug_pubnames && (strcmp (name, "pubnames") == 0)) + || (do_debug_aranges && (strcmp (name, "aranges") == 0)) + ) + request_dump (i, DEBUG_DUMP); + } + } + + if (! do_sections) + return 1; + + printf (_("\nSection Header%s:\n"), elf_header.e_shnum > 1 ? "s" : ""); + printf + (_(" [Nr] Name Type Addr Off Size ES Flg Lk Inf Al\n")); + + for (i = 0, section = section_headers; + i < elf_header.e_shnum; + i ++, section ++) + { + printf (" [%2d] %-17.17s %-15.15s ", + i, + SECTION_NAME (section), + get_section_type_name (section->sh_type)); + + printf ( "%8.8lx %6.6lx %6.6lx %2.2lx", + (unsigned long) section->sh_addr, + (unsigned long) section->sh_offset, + (unsigned long) section->sh_size, + (unsigned long) section->sh_entsize); + + printf (" %c%c%c %2ld %3lx %ld\n", + (section->sh_flags & SHF_WRITE ? 'W' : ' '), + (section->sh_flags & SHF_ALLOC ? 'A' : ' '), + (section->sh_flags & SHF_EXECINSTR ? 'X' : ' '), + (unsigned long) section->sh_link, + (unsigned long) section->sh_info, + (unsigned long) section->sh_addralign); + } + + return 1; +} + +/* Process the reloc section. */ +static int +process_relocs (file) + FILE * file; +{ + unsigned long rel_size; + unsigned long rel_offset; + + + if (!do_reloc) + return 1; + + if (do_using_dynamic) + { + rel_size = 0; + rel_offset = 0; + + if (dynamic_info[DT_REL]) + { + rel_offset = dynamic_info[DT_REL]; + rel_size = dynamic_info[DT_RELSZ]; + } + else if (dynamic_info [DT_RELA]) + { + rel_offset = dynamic_info[DT_RELA]; + rel_size = dynamic_info[DT_RELASZ]; + } + else if (dynamic_info[DT_JMPREL]) + { + rel_offset = dynamic_info[DT_JMPREL]; + rel_size = dynamic_info[DT_PLTRELSZ]; + } + + if (rel_size) + { + printf + (_("\nRelocation section at offset 0x%lx contains %ld bytes:\n"), + rel_offset, rel_size); + + dump_relocations (file, rel_offset - loadaddr, rel_size, + dynamic_symbols, dynamic_strings); + } + else + printf (_("\nThere are no dynamic relocations in this file.\n")); + } + else + { + Elf32_Internal_Shdr * section; + unsigned long i; + int found = 0; + + for (i = 0, section = section_headers; + i < elf_header.e_shnum; + i++, section ++) + { + if ( section->sh_type != SHT_RELA + && section->sh_type != SHT_REL) + continue; + + rel_offset = section->sh_offset; + rel_size = section->sh_size; + + if (rel_size) + { + Elf32_Internal_Shdr * strsec; + Elf32_Internal_Shdr * symsec; + Elf_Internal_Sym * symtab; + char * strtab; + + printf (_("\nRelocation section ")); + + if (string_table == NULL) + printf ("%d", section->sh_name); + else + printf ("'%s'", SECTION_NAME (section)); + + printf (_(" at offset 0x%lx contains %lu entries:\n"), + rel_offset, (unsigned long) (rel_size / section->sh_entsize)); + + symsec = section_headers + section->sh_link; + + symtab = get_elf_symbols (file, symsec->sh_offset, + symsec->sh_size / symsec->sh_entsize); + + if (symtab == NULL) + continue; + + strsec = section_headers + symsec->sh_link; + + GET_DATA_ALLOC (strsec->sh_offset, strsec->sh_size, strtab, + char *, "string table"); + + dump_relocations (file, rel_offset, rel_size, symtab, strtab); + + free (strtab); + free (symtab); + + found = 1; + } + } + + if (! found) + printf (_("\nThere are no relocations in this file.\n")); + } + + return 1; +} + + +static void +dynamic_segment_mips_val (entry) + Elf_Internal_Dyn * entry; +{ + switch (entry->d_tag) + { + case DT_MIPS_FLAGS: + if (entry->d_un.d_val == 0) + printf ("NONE\n"); + else + { + static const char * opts[] = + { + "QUICKSTART", "NOTPOT", "NO_LIBRARY_REPLACEMENT", + "NO_MOVE", "SGI_ONLY", "GUARANTEE_INIT", "DELTA_C_PLUS_PLUS", + "GUARANTEE_START_INIT", "PIXIE", "DEFAULT_DELAY_LOAD", + "REQUICKSTART", "REQUICKSTARTED", "CORD", "NO_UNRES_UNDEF", + "RLD_ORDER_SAFE" + }; + unsigned int cnt; + int first = 1; + for (cnt = 0; cnt < NUM_ELEM (opts); ++ cnt) + if (entry->d_un.d_val & (1 << cnt)) + { + printf ("%s%s", first ? "" : " ", opts[cnt]); + first = 0; + } + puts (""); + } + break; + + case DT_MIPS_IVERSION: + if (dynamic_strings != NULL) + printf ("Interface Version: %s\n", + dynamic_strings + entry->d_un.d_val); + else + printf ("%ld\n", (long) entry->d_un.d_ptr); + break; + + case DT_MIPS_TIME_STAMP: + { + char timebuf[20]; + time_t time = entry->d_un.d_val; + strftime (timebuf, 20, "%Y-%m-%dT%H:%M:%S", gmtime (&time)); + printf ("Time Stamp: %s\n", timebuf); + } + break; + + case DT_MIPS_RLD_VERSION: + case DT_MIPS_LOCAL_GOTNO: + case DT_MIPS_CONFLICTNO: + case DT_MIPS_LIBLISTNO: + case DT_MIPS_SYMTABNO: + case DT_MIPS_UNREFEXTNO: + case DT_MIPS_HIPAGENO: + case DT_MIPS_DELTA_CLASS_NO: + case DT_MIPS_DELTA_INSTANCE_NO: + case DT_MIPS_DELTA_RELOC_NO: + case DT_MIPS_DELTA_SYM_NO: + case DT_MIPS_DELTA_CLASSSYM_NO: + case DT_MIPS_COMPACT_SIZE: + printf ("%ld\n", (long) entry->d_un.d_ptr); + break; + + default: + printf ("%#lx\n", (long) entry->d_un.d_ptr); + } +} + +/* Parse the dynamic segment */ +static int +process_dynamic_segment (file) + FILE * file; +{ + Elf_Internal_Dyn * entry; + Elf32_External_Dyn * edyn; + unsigned int i; + + if (dynamic_size == 0) + { + if (do_dynamic) + printf (_("\nThere is no dynamic segment in this file.\n")); + + return 1; + } + + GET_DATA_ALLOC (dynamic_addr, dynamic_size, + edyn, Elf32_External_Dyn *, "dynamic segment"); + + /* SGI's ELF has more than one section in the DYNAMIC segment. Determine + how large .dynamic is now. We can do this even before the byte + swapping since the DT_NULL tag is recognizable. */ + dynamic_size = 0; + while (*(Elf32_Word *) edyn[dynamic_size++].d_tag != DT_NULL) + ; + + dynamic_segment = (Elf_Internal_Dyn *) + malloc (dynamic_size * sizeof (Elf_Internal_Dyn)); + + if (dynamic_segment == NULL) + { + error (_("Out of memory\n")); + free (edyn); + return 0; + } + + for (i = 0, entry = dynamic_segment; + i < dynamic_size; + i ++, entry ++) + { + entry->d_tag = BYTE_GET (edyn [i].d_tag); + entry->d_un.d_val = BYTE_GET (edyn [i].d_un.d_val); + } + + free (edyn); + + /* Find the appropriate symbol table. */ + if (dynamic_symbols == NULL) + { + for (i = 0, entry = dynamic_segment; + i < dynamic_size; + ++i, ++ entry) + { + unsigned long offset; + long num_syms; + + if (entry->d_tag != DT_SYMTAB) + continue; + + dynamic_info[DT_SYMTAB] = entry->d_un.d_val; + + /* Since we do not know how big the symbol table is, + we default to reading in the entire file (!) and + processing that. This is overkill, I know, but it + should work. */ + + offset = entry->d_un.d_val - loadaddr; + + if (fseek (file, 0, SEEK_END)) + error (_("Unable to seek to end of file!")); + + num_syms = (ftell (file) - offset) / sizeof (Elf32_External_Sym); + + if (num_syms < 1) + { + error (_("Unable to determine the number of symbols to load\n")); + continue; + } + + dynamic_symbols = get_elf_symbols (file, offset, num_syms); + } + } + + /* Similarly find a string table. */ + if (dynamic_strings == NULL) + { + for (i = 0, entry = dynamic_segment; + i < dynamic_size; + ++i, ++ entry) + { + unsigned long offset; + long str_tab_len; + + if (entry->d_tag != DT_STRTAB) + continue; + + dynamic_info[DT_STRTAB] = entry->d_un.d_val; + + /* Since we do not know how big the string table is, + we default to reading in the entire file (!) and + processing that. This is overkill, I know, but it + should work. */ + + offset = entry->d_un.d_val - loadaddr; + if (fseek (file, 0, SEEK_END)) + error (_("Unable to seek to end of file\n")); + str_tab_len = ftell (file) - offset; + + if (str_tab_len < 1) + { + error + (_("Unable to determine the length of the dynamic string table\n")); + continue; + } + + GET_DATA_ALLOC (offset, str_tab_len, dynamic_strings, char *, + "dynamic string table"); + + break; + } + } + + /* And find the syminfo section if available. */ + if (dynamic_syminfo == NULL) + { + unsigned int syminsz = 0; + + for (i = 0, entry = dynamic_segment; + i < dynamic_size; + ++i, ++ entry) + { + if (entry->d_tag == DT_SYMINENT) + { + /* Note: these braces are necessary to avoid a syntax + error from the SunOS4 C compiler. */ + assert (sizeof (Elf_External_Syminfo) == entry->d_un.d_val); + } + else if (entry->d_tag == DT_SYMINSZ) + syminsz = entry->d_un.d_val; + else if (entry->d_tag == DT_SYMINFO) + dynamic_syminfo_offset = entry->d_un.d_val - loadaddr; + } + + if (dynamic_syminfo_offset != 0 && syminsz != 0) + { + Elf_External_Syminfo *extsyminfo; + Elf_Internal_Syminfo *syminfo; + + /* There is a syminfo section. Read the data. */ + GET_DATA_ALLOC (dynamic_syminfo_offset, syminsz, extsyminfo, + Elf_External_Syminfo *, "symbol information"); + + dynamic_syminfo = (Elf_Internal_Syminfo *) malloc (syminsz); + if (dynamic_syminfo == NULL) + { + error (_("Out of memory\n")); + return 0; + } + + dynamic_syminfo_nent = syminsz / sizeof (Elf_External_Syminfo); + for (i = 0, syminfo = dynamic_syminfo; i < dynamic_syminfo_nent; + ++i, ++syminfo) + { + syminfo->si_boundto = BYTE_GET (extsyminfo[i].si_boundto); + syminfo->si_flags = BYTE_GET (extsyminfo[i].si_flags); + } + + free (extsyminfo); + } + } + + if (do_dynamic && dynamic_addr) + printf (_("\nDynamic segment at offset 0x%x contains %d entries:\n"), + dynamic_addr, dynamic_size); + if (do_dynamic) + printf (_(" Tag Type Name/Value\n")); + + for (i = 0, entry = dynamic_segment; + i < dynamic_size; + i++, entry ++) + { + if (do_dynamic) + printf (_(" 0x%-8.8lx (%s)%*s"), + (unsigned long) entry->d_tag, + get_dynamic_type (entry->d_tag), + 27 - strlen (get_dynamic_type (entry->d_tag)), + " "); + + switch (entry->d_tag) + { + case DT_AUXILIARY: + case DT_FILTER: + if (do_dynamic) + { + if (entry->d_tag == DT_AUXILIARY) + printf (_("Auxiliary library")); + else + printf (_("Filter library")); + + if (dynamic_strings) + printf (": [%s]\n", dynamic_strings + entry->d_un.d_val); + else + printf (": %#lx\n", (long) entry->d_un.d_val); + } + break; + + case DT_FEATURE_1: + if (do_dynamic) + { + printf (_("Flags:")); + if (entry->d_un.d_val == 0) + printf (_(" None\n")); + else + { + unsigned long int val = entry->d_un.d_val; + if (val & DTF_1_PARINIT) + { + printf (" PARINIT"); + val ^= DTF_1_PARINIT; + } + if (val != 0) + printf (" %lx", val); + puts (""); + } + } + break; + + case DT_POSFLAG_1: + if (do_dynamic) + { + printf (_("Flags:")); + if (entry->d_un.d_val == 0) + printf (_(" None\n")); + else + { + unsigned long int val = entry->d_un.d_val; + if (val & DF_P1_LAZYLOAD) + { + printf (" LAZYLOAD"); + val ^= DF_P1_LAZYLOAD; + } + if (val & DF_P1_GROUPPERM) + { + printf (" GROUPPERM"); + val ^= DF_P1_GROUPPERM; + } + if (val != 0) + printf (" %lx", val); + puts (""); + } + } + break; + + case DT_FLAGS_1: + if (do_dynamic) + { + printf (_("Flags:")); + if (entry->d_un.d_val == 0) + printf (_(" None\n")); + else + { + unsigned long int val = entry->d_un.d_val; + if (val & DF_1_NOW) + { + printf (" NOW"); + val ^= DF_1_NOW; + } + if (val & DF_1_GLOBAL) + { + printf (" GLOBAL"); + val ^= DF_1_GLOBAL; + } + if (val & DF_1_GROUP) + { + printf (" GROUP"); + val ^= DF_1_GROUP; + } + if (val & DF_1_NODELETE) + { + printf (" NODELETE"); + val ^= DF_1_NODELETE; + } + if (val & DF_1_LOADFLTR) + { + printf (" LOADFLTR"); + val ^= DF_1_LOADFLTR; + } + if (val & DF_1_INITFIRST) + { + printf (" INITFIRST"); + val ^= DF_1_INITFIRST; + } + if (val & DF_1_NOOPEN) + { + printf (" NOOPEN"); + val ^= DF_1_NOOPEN; + } + if (val & DF_1_ORIGIN) + { + printf (" ORIGIN"); + val ^= DF_1_ORIGIN; + } + if (val & DF_1_DIRECT) + { + printf (" DIRECT"); + val ^= DF_1_DIRECT; + } + if (val & DF_1_TRANS) + { + printf (" TRANS"); + val ^= DF_1_TRANS; + } + if (val & DF_1_INTERPOSE) + { + printf (" INTERPOSE"); + val ^= DF_1_INTERPOSE; + } + if (val != 0) + printf (" %lx", val); + puts (""); + } + } + break; + + case DT_PLTREL: + if (do_dynamic) + puts (get_dynamic_type (entry->d_un.d_val)); + break; + + case DT_NULL : + case DT_NEEDED : + case DT_PLTGOT : + case DT_HASH : + case DT_STRTAB : + case DT_SYMTAB : + case DT_RELA : + case DT_INIT : + case DT_FINI : + case DT_SONAME : + case DT_RPATH : + case DT_SYMBOLIC: + case DT_REL : + case DT_DEBUG : + case DT_TEXTREL : + case DT_JMPREL : + dynamic_info[entry->d_tag] = entry->d_un.d_val; + + if (do_dynamic) + { + char * name; + + if (dynamic_strings == NULL) + name = NULL; + else + name = dynamic_strings + entry->d_un.d_val; + + if (name) + { + switch (entry->d_tag) + { + case DT_NEEDED: + printf (_("Shared library: [%s]"), name); + + if (strcmp (name, program_interpreter)) + printf ("\n"); + else + printf (_(" program interpreter\n")); + break; + + case DT_SONAME: + printf (_("Library soname: [%s]\n"), name); + break; + + case DT_RPATH: + printf (_("Library rpath: [%s]\n"), name); + break; + + default: + printf ("%#lx\n", (long) entry->d_un.d_val); + } + } + else + printf ("%#lx\n", (long) entry->d_un.d_val); + } + break; + + case DT_PLTRELSZ: + case DT_RELASZ : + case DT_STRSZ : + case DT_RELSZ : + case DT_RELAENT : + case DT_SYMENT : + case DT_RELENT : + case DT_PLTPADSZ: + case DT_MOVEENT : + case DT_MOVESZ : + case DT_INIT_ARRAYSZ: + case DT_FINI_ARRAYSZ: + if (do_dynamic) + printf ("%lu (bytes)\n", (unsigned long) entry->d_un.d_val); + break; + + case DT_VERDEFNUM: + case DT_VERNEEDNUM: + case DT_RELACOUNT: + case DT_RELCOUNT: + if (do_dynamic) + printf ("%lu\n", (unsigned long) entry->d_un.d_val); + break; + + case DT_SYMINSZ: + case DT_SYMINENT: + case DT_SYMINFO: + case DT_USED: + case DT_INIT_ARRAY: + case DT_FINI_ARRAY: + if (do_dynamic) + { + if (dynamic_strings != NULL && entry->d_tag == DT_USED) + { + char * name; + + name = dynamic_strings + entry->d_un.d_val; + + if (* name) + { + printf (_("Not needed object: [%s]\n"), name); + break; + } + } + + printf ("%#lx\n", (long) entry->d_un.d_val); + } + break; + + case DT_BIND_NOW: + /* The value of this entry is ignored. */ + break; + + default: + if ((entry->d_tag >= DT_VERSYM) && (entry->d_tag <= DT_VERNEEDNUM)) + version_info [DT_VERSIONTAGIDX (entry->d_tag)] = + entry->d_un.d_val; + + if (do_dynamic) + { + switch (elf_header.e_machine) + { + case EM_MIPS: + case EM_MIPS_RS4_BE: + dynamic_segment_mips_val (entry); + break; + default: + printf ("%#lx\n", (long) entry->d_un.d_ptr); + } + } + break; + } + } + + return 1; +} + +static char * +get_ver_flags (flags) + unsigned int flags; +{ + static char buff [32]; + + buff[0] = 0; + + if (flags == 0) + return _("none"); + + if (flags & VER_FLG_BASE) + strcat (buff, "BASE "); + + if (flags & VER_FLG_WEAK) + { + if (flags & VER_FLG_BASE) + strcat (buff, "| "); + + strcat (buff, "WEAK "); + } + + if (flags & ~(VER_FLG_BASE | VER_FLG_WEAK)) + strcat (buff, "| <unknown>"); + + return buff; +} + +/* Display the contents of the version sections. */ +static int +process_version_sections (file) + FILE * file; +{ + Elf32_Internal_Shdr * section; + unsigned i; + int found = 0; + + if (! do_version) + return 1; + + for (i = 0, section = section_headers; + i < elf_header.e_shnum; + i++, section ++) + { + switch (section->sh_type) + { + case SHT_GNU_verdef: + { + Elf_External_Verdef * edefs; + unsigned int idx; + unsigned int cnt; + + found = 1; + + printf + (_("\nVersion definition section '%s' contains %ld entries:\n"), + SECTION_NAME (section), section->sh_info); + + printf (_(" Addr: 0x")); + printf_vma (section->sh_addr); + printf (_(" Offset: %#08lx Link: %lx (%s)\n"), + section->sh_offset, section->sh_link, + SECTION_NAME (section_headers + section->sh_link)); + + GET_DATA_ALLOC (section->sh_offset, section->sh_size, + edefs, Elf_External_Verdef *, + "version definition section"); + + for (idx = cnt = 0; cnt < section->sh_info; ++ cnt) + { + char * vstart; + Elf_External_Verdef * edef; + Elf_Internal_Verdef ent; + Elf_External_Verdaux * eaux; + Elf_Internal_Verdaux aux; + int j; + int isum; + + vstart = ((char *) edefs) + idx; + + edef = (Elf_External_Verdef *) vstart; + + ent.vd_version = BYTE_GET (edef->vd_version); + ent.vd_flags = BYTE_GET (edef->vd_flags); + ent.vd_ndx = BYTE_GET (edef->vd_ndx); + ent.vd_cnt = BYTE_GET (edef->vd_cnt); + ent.vd_hash = BYTE_GET (edef->vd_hash); + ent.vd_aux = BYTE_GET (edef->vd_aux); + ent.vd_next = BYTE_GET (edef->vd_next); + + printf (_(" %#06x: Rev: %d Flags: %s"), + idx, ent.vd_version, get_ver_flags (ent.vd_flags)); + + printf (_(" Index: %d Cnt: %d "), + ent.vd_ndx, ent.vd_cnt); + + vstart += ent.vd_aux; + + eaux = (Elf_External_Verdaux *) vstart; + + aux.vda_name = BYTE_GET (eaux->vda_name); + aux.vda_next = BYTE_GET (eaux->vda_next); + + if (dynamic_strings) + printf (_("Name: %s\n"), dynamic_strings + aux.vda_name); + else + printf (_("Name index: %ld\n"), aux.vda_name); + + isum = idx + ent.vd_aux; + + for (j = 1; j < ent.vd_cnt; j ++) + { + isum += aux.vda_next; + vstart += aux.vda_next; + + eaux = (Elf_External_Verdaux *) vstart; + + aux.vda_name = BYTE_GET (eaux->vda_name); + aux.vda_next = BYTE_GET (eaux->vda_next); + + if (dynamic_strings) + printf (_(" %#06x: Parent %d: %s\n"), + isum, j, dynamic_strings + aux.vda_name); + else + printf (_(" %#06x: Parent %d, name index: %ld\n"), + isum, j, aux.vda_name); + } + + idx += ent.vd_next; + } + + free (edefs); + } + break; + + case SHT_GNU_verneed: + { + Elf_External_Verneed * eneed; + unsigned int idx; + unsigned int cnt; + + found = 1; + + printf (_("\nVersion needs section '%s' contains %ld entries:\n"), + SECTION_NAME (section), section->sh_info); + + printf (_(" Addr: 0x")); + printf_vma (section->sh_addr); + printf (_(" Offset: %#08lx Link to section: %ld (%s)\n"), + section->sh_offset, section->sh_link, + SECTION_NAME (section_headers + section->sh_link)); + + GET_DATA_ALLOC (section->sh_offset, section->sh_size, + eneed, Elf_External_Verneed *, + "version need section"); + + for (idx = cnt = 0; cnt < section->sh_info; ++cnt) + { + Elf_External_Verneed * entry; + Elf_Internal_Verneed ent; + int j; + int isum; + char * vstart; + + vstart = ((char *) eneed) + idx; + + entry = (Elf_External_Verneed *) vstart; + + ent.vn_version = BYTE_GET (entry->vn_version); + ent.vn_cnt = BYTE_GET (entry->vn_cnt); + ent.vn_file = BYTE_GET (entry->vn_file); + ent.vn_aux = BYTE_GET (entry->vn_aux); + ent.vn_next = BYTE_GET (entry->vn_next); + + printf (_(" %#06x: Version: %d"), idx, ent.vn_version); + + if (dynamic_strings) + printf (_(" File: %s"), dynamic_strings + ent.vn_file); + else + printf (_(" File: %lx"), ent.vn_file); + + printf (_(" Cnt: %d\n"), ent.vn_cnt); + + vstart += ent.vn_aux; + + for (j = 0, isum = idx + ent.vn_aux; j < ent.vn_cnt; ++j) + { + Elf_External_Vernaux * eaux; + Elf_Internal_Vernaux aux; + + eaux = (Elf_External_Vernaux *) vstart; + + aux.vna_hash = BYTE_GET (eaux->vna_hash); + aux.vna_flags = BYTE_GET (eaux->vna_flags); + aux.vna_other = BYTE_GET (eaux->vna_other); + aux.vna_name = BYTE_GET (eaux->vna_name); + aux.vna_next = BYTE_GET (eaux->vna_next); + + if (dynamic_strings) + printf (_(" %#06x: Name: %s"), + isum, dynamic_strings + aux.vna_name); + else + printf (_(" %#06x: Name index: %lx"), + isum, aux.vna_name); + + printf (_(" Flags: %s Version: %d\n"), + get_ver_flags (aux.vna_flags), aux.vna_other); + + isum += aux.vna_next; + vstart += aux.vna_next; + } + + idx += ent.vn_next; + } + + free (eneed); + } + break; + + case SHT_GNU_versym: + { + Elf32_Internal_Shdr * link_section; + int total; + int cnt; + unsigned char * edata; + unsigned short * data; + char * strtab; + Elf_Internal_Sym * symbols; + Elf32_Internal_Shdr * string_sec; + + link_section = section_headers + section->sh_link; + total = section->sh_size / section->sh_entsize; + + found = 1; + + symbols = get_elf_symbols + (file, link_section->sh_offset, + link_section->sh_size / link_section->sh_entsize); + + string_sec = section_headers + link_section->sh_link; + + GET_DATA_ALLOC (string_sec->sh_offset, string_sec->sh_size, + strtab, char *, "version string table"); + + printf (_("\nVersion symbols section '%s' contains %d entries:\n"), + SECTION_NAME (section), total); + + printf (_(" Addr: ")); + printf_vma (section->sh_addr); + printf (_(" Offset: %#08lx Link: %lx (%s)\n"), + section->sh_offset, section->sh_link, + SECTION_NAME (link_section)); + + GET_DATA_ALLOC (version_info [DT_VERSIONTAGIDX (DT_VERSYM)] + - loadaddr, + total * sizeof (short), edata, + unsigned char *, "version symbol data"); + + data = (unsigned short *) malloc (total * sizeof (short)); + + for (cnt = total; cnt --;) + data [cnt] = byte_get (edata + cnt * sizeof (short), + sizeof (short)); + + free (edata); + + for (cnt = 0; cnt < total; cnt += 4) + { + int j, nn; + + printf (" %03x:", cnt); + + for (j = 0; (j < 4) && (cnt + j) < total; ++j) + switch (data [cnt + j]) + { + case 0: + fputs (_(" 0 (*local*) "), stdout); + break; + + case 1: + fputs (_(" 1 (*global*) "), stdout); + break; + + default: + nn = printf ("%4x%c", data [cnt + j] & 0x7fff, + data [cnt + j] & 0x8000 ? 'h' : ' '); + + if (symbols [cnt + j].st_shndx < SHN_LORESERVE + && section_headers[symbols [cnt + j].st_shndx].sh_type + == SHT_NOBITS) + { + /* We must test both. */ + Elf_Internal_Verneed ivn; + unsigned long offset; + + offset = version_info [DT_VERSIONTAGIDX (DT_VERNEED)] + - loadaddr; + + do + { + Elf_External_Verneed evn; + Elf_External_Vernaux evna; + Elf_Internal_Vernaux ivna; + unsigned long vna_off; + + GET_DATA (offset, evn, "version need"); + + ivn.vn_aux = BYTE_GET (evn.vn_aux); + ivn.vn_next = BYTE_GET (evn.vn_next); + + vna_off = offset + ivn.vn_aux; + + do + { + GET_DATA (vna_off, evna, + "version need aux (1)"); + + ivna.vna_next = BYTE_GET (evna.vna_next); + ivna.vna_other = BYTE_GET (evna.vna_other); + + vna_off += ivna.vna_next; + } + while (ivna.vna_other != data [cnt + j] + && ivna.vna_next != 0); + + if (ivna.vna_other == data [cnt + j]) + { + ivna.vna_name = BYTE_GET (evna.vna_name); + + nn += printf ("(%s%-*s", + strtab + ivna.vna_name, + 12 - strlen (strtab + + ivna.vna_name), + ")"); + break; + } + else if (ivn.vn_next == 0) + { + if (data [cnt + j] != 0x8001) + { + Elf_Internal_Verdef ivd; + Elf_External_Verdef evd; + + offset = version_info + [DT_VERSIONTAGIDX (DT_VERDEF)] + - loadaddr; + + do + { + GET_DATA (offset, evd, + "version definition"); + + ivd.vd_next = BYTE_GET (evd.vd_next); + ivd.vd_ndx = BYTE_GET (evd.vd_ndx); + + offset += ivd.vd_next; + } + while (ivd.vd_ndx + != (data [cnt + j] & 0x7fff) + && ivd.vd_next != 0); + + if (ivd.vd_ndx + == (data [cnt + j] & 0x7fff)) + { + Elf_External_Verdaux evda; + Elf_Internal_Verdaux ivda; + + ivd.vd_aux = BYTE_GET (evd.vd_aux); + + GET_DATA (offset + ivd.vd_aux, evda, + "version definition aux"); + + ivda.vda_name = + BYTE_GET (evda.vda_name); + + nn += + printf ("(%s%-*s", + strtab + ivda.vda_name, + 12 + - strlen (strtab + + ivda.vda_name), + ")"); + } + } + + break; + } + else + offset += ivn.vn_next; + } + while (ivn.vn_next); + } + else if (symbols [cnt + j].st_shndx == SHN_UNDEF) + { + Elf_Internal_Verneed ivn; + unsigned long offset; + + offset = version_info [DT_VERSIONTAGIDX (DT_VERNEED)] + - loadaddr; + + do + { + Elf_Internal_Vernaux ivna; + Elf_External_Verneed evn; + Elf_External_Vernaux evna; + unsigned long a_off; + + GET_DATA (offset, evn, "version need"); + + ivn.vn_aux = BYTE_GET (evn.vn_aux); + ivn.vn_next = BYTE_GET (evn.vn_next); + + a_off = offset + ivn.vn_aux; + + do + { + GET_DATA (a_off, evna, + "version need aux (2)"); + + ivna.vna_next = BYTE_GET (evna.vna_next); + ivna.vna_other = BYTE_GET (evna.vna_other); + + a_off += ivna.vna_next; + } + while (ivna.vna_other != data [cnt + j] + && ivna.vna_next != 0); + + if (ivna.vna_other == data [cnt + j]) + { + ivna.vna_name = BYTE_GET (evna.vna_name); + + nn += printf ("(%s%-*s", + strtab + ivna.vna_name, + 12 - strlen (strtab + + ivna.vna_name), + ")"); + break; + } + + offset += ivn.vn_next; + } + while (ivn.vn_next); + } + else if (data [cnt + j] != 0x8001) + { + Elf_Internal_Verdef ivd; + Elf_External_Verdef evd; + unsigned long offset; + + offset = version_info + [DT_VERSIONTAGIDX (DT_VERDEF)] - loadaddr; + + do + { + GET_DATA (offset, evd, "version def"); + + ivd.vd_next = BYTE_GET (evd.vd_next); + ivd.vd_ndx = BYTE_GET (evd.vd_ndx); + + offset += ivd.vd_next; + } + while (ivd.vd_ndx != (data [cnt + j] & 0x7fff) + && ivd.vd_next != 0); + + if (ivd.vd_ndx == (data [cnt + j] & 0x7fff)) + { + Elf_External_Verdaux evda; + Elf_Internal_Verdaux ivda; + + ivd.vd_aux = BYTE_GET (evd.vd_aux); + + GET_DATA (offset - ivd.vd_next + ivd.vd_aux, + evda, "version def aux"); + + ivda.vda_name = BYTE_GET (evda.vda_name); + + nn += printf ("(%s%-*s", + strtab + ivda.vda_name, + 12 - strlen (strtab + + ivda.vda_name), + ")"); + } + } + + if (nn < 18) + printf ("%*c", 18 - nn, ' '); + } + + putchar ('\n'); + } + + free (data); + free (strtab); + free (symbols); + } + break; + + default: + break; + } + } + + if (! found) + printf (_("\nNo version information found in this file.\n")); + + return 1; +} + +static char * +get_symbol_binding (binding) + unsigned int binding; +{ + static char buff [32]; + + switch (binding) + { + case STB_LOCAL: return _("LOCAL"); + case STB_GLOBAL: return _("GLOBAL"); + case STB_WEAK: return _("WEAK"); + default: + if (binding >= STB_LOPROC && binding <= STB_HIPROC) + sprintf (buff, _("<processor specific>: %d"), binding); + else if (binding >= STB_LOOS && binding <= STB_HIOS) + sprintf (buff, _("<OS specific>: %d"), binding); + else + sprintf (buff, _("<unknown>: %d"), binding); + return buff; + } +} + +static char * +get_symbol_type (type) + unsigned int type; +{ + static char buff [32]; + + switch (type) + { + case STT_NOTYPE: return _("NOTYPE"); + case STT_OBJECT: return _("OBJECT"); + case STT_FUNC: return _("FUNC"); + case STT_SECTION: return _("SECTION"); + case STT_FILE: return _("FILE"); + default: + if (type >= STT_LOPROC && type <= STT_HIPROC) + sprintf (buff, _("<processor specific>: %d"), type); + else if (type >= STT_LOOS && type <= STT_HIOS) + sprintf (buff, _("<OS specific>: %d"), type); + else + sprintf (buff, _("<unknown>: %d"), type); + return buff; + } +} + +static char * +get_symbol_index_type (type) + unsigned int type; +{ + switch (type) + { + case SHN_UNDEF: return "UND"; + case SHN_ABS: return "ABS"; + case SHN_COMMON: return "COM"; + default: + if (type >= SHN_LOPROC && type <= SHN_HIPROC) + return "PRC"; + else if (type >= SHN_LORESERVE && type <= SHN_HIRESERVE) + return "RSV"; + else if (type >= SHN_LOOS && type <= SHN_HIOS) + return "OS "; + else + { + static char buff [32]; + + sprintf (buff, "%3d", type); + return buff; + } + } +} + + +static int * +get_dynamic_data (file, number) + FILE * file; + unsigned int number; +{ + char * e_data; + int * i_data; + + e_data = (char *) malloc (number * 4); + + if (e_data == NULL) + { + error (_("Out of memory\n")); + return NULL; + } + + if (fread (e_data, 4, number, file) != number) + { + error (_("Unable to read in dynamic data\n")); + return NULL; + } + + i_data = (int *) malloc (number * sizeof (* i_data)); + + if (i_data == NULL) + { + error (_("Out of memory\n")); + free (e_data); + return NULL; + } + + while (number--) + i_data [number] = byte_get (e_data + number * 4, 4); + + free (e_data); + + return i_data; +} + +/* Dump the symbol table */ +static int +process_symbol_table (file) + FILE * file; +{ + Elf32_Internal_Shdr * section; + char nb [4]; + char nc [4]; + int nbuckets; + int nchains; + int * buckets = NULL; + int * chains = NULL; + + if (! do_syms && !do_histogram) + return 1; + + if (dynamic_info[DT_HASH] && ((do_using_dynamic && dynamic_strings != NULL) + || do_histogram)) + { + if (fseek (file, dynamic_info[DT_HASH] - loadaddr, SEEK_SET)) + { + error (_("Unable to seek to start of dynamic information")); + return 0; + } + + if (fread (nb, sizeof (nb), 1, file) != 1) + { + error (_("Failed to read in number of buckets\n")); + return 0; + } + + if (fread (nc, sizeof (nc), 1, file) != 1) + { + error (_("Failed to read in number of chains\n")); + return 0; + } + + nbuckets = byte_get (nb, 4); + nchains = byte_get (nc, 4); + + buckets = get_dynamic_data (file, nbuckets); + chains = get_dynamic_data (file, nchains); + + if (buckets == NULL || chains == NULL) + return 0; + } + + if (do_syms + && dynamic_info[DT_HASH] && do_using_dynamic && dynamic_strings != NULL) + { + int hn; + int si; + + printf (_("\nSymbol table for image:\n")); + printf (_(" Num Buc: Value Size Type Bind Ot Ndx Name\n")); + + for (hn = 0; hn < nbuckets; hn++) + { + if (! buckets [hn]) + continue; + + for (si = buckets [hn]; si; si = chains [si]) + { + Elf_Internal_Sym * psym; + + psym = dynamic_symbols + si; + + printf (" %3d %3d: %8lx %5ld %6s %6s %2d ", + si, hn, + (unsigned long) psym->st_value, + (unsigned long) psym->st_size, + get_symbol_type (ELF_ST_TYPE (psym->st_info)), + get_symbol_binding (ELF_ST_BIND (psym->st_info)), + psym->st_other); + + printf ("%3.3s", get_symbol_index_type (psym->st_shndx)); + + printf (" %s\n", dynamic_strings + psym->st_name); + } + } + } + else if (do_syms && !do_using_dynamic) + { + unsigned int i; + + for (i = 0, section = section_headers; + i < elf_header.e_shnum; + i++, section++) + { + unsigned int si; + char * strtab; + Elf_Internal_Sym * symtab; + Elf_Internal_Sym * psym; + + + if ( section->sh_type != SHT_SYMTAB + && section->sh_type != SHT_DYNSYM) + continue; + + printf (_("\nSymbol table '%s' contains %lu entries:\n"), + SECTION_NAME (section), + (unsigned long) (section->sh_size / section->sh_entsize)); + fputs (_(" Num: Value Size Type Bind Ot Ndx Name\n"), + stdout); + + symtab = get_elf_symbols (file, section->sh_offset, + section->sh_size / section->sh_entsize); + if (symtab == NULL) + continue; + + if (section->sh_link == elf_header.e_shstrndx) + strtab = string_table; + else + { + Elf32_Internal_Shdr * string_sec; + + string_sec = section_headers + section->sh_link; + + GET_DATA_ALLOC (string_sec->sh_offset, string_sec->sh_size, + strtab, char *, "string table"); + } + + for (si = 0, psym = symtab; + si < section->sh_size / section->sh_entsize; + si ++, psym ++) + { + printf (" %3d: %8lx %5ld %-7s %-6s %2d ", + si, + (unsigned long) psym->st_value, + (unsigned long) psym->st_size, + get_symbol_type (ELF_ST_TYPE (psym->st_info)), + get_symbol_binding (ELF_ST_BIND (psym->st_info)), + psym->st_other); + + if (psym->st_shndx == 0) + fputs (" UND", stdout); + else if ((psym->st_shndx & 0xffff) == 0xfff1) + fputs (" ABS", stdout); + else if ((psym->st_shndx & 0xffff) == 0xfff2) + fputs (" COM", stdout); + else + printf ("%4x", psym->st_shndx); + + printf (" %s", strtab + psym->st_name); + + if (section->sh_type == SHT_DYNSYM && + version_info [DT_VERSIONTAGIDX (DT_VERSYM)] != 0) + { + unsigned char data[2]; + unsigned short vers_data; + unsigned long offset; + int is_nobits; + int check_def; + + offset = version_info [DT_VERSIONTAGIDX (DT_VERSYM)] + - loadaddr; + + GET_DATA (offset + si * sizeof (vers_data), data, + "version data"); + + vers_data = byte_get (data, 2); + + is_nobits = psym->st_shndx < SHN_LORESERVE ? + (section_headers [psym->st_shndx].sh_type == SHT_NOBITS) + : 0; + + check_def = (psym->st_shndx != SHN_UNDEF); + + if ((vers_data & 0x8000) || vers_data > 1) + { + if (is_nobits || ! check_def) + { + Elf_External_Verneed evn; + Elf_Internal_Verneed ivn; + Elf_Internal_Vernaux ivna; + + /* We must test both. */ + offset = version_info + [DT_VERSIONTAGIDX (DT_VERNEED)] - loadaddr; + + GET_DATA (offset, evn, "version need"); + + ivn.vn_aux = BYTE_GET (evn.vn_aux); + ivn.vn_next = BYTE_GET (evn.vn_next); + + do + { + unsigned long vna_off; + + vna_off = offset + ivn.vn_aux; + + do + { + Elf_External_Vernaux evna; + + GET_DATA (vna_off, evna, + "version need aux (3)"); + + ivna.vna_other = BYTE_GET (evna.vna_other); + ivna.vna_next = BYTE_GET (evna.vna_next); + ivna.vna_name = BYTE_GET (evna.vna_name); + + vna_off += ivna.vna_next; + } + while (ivna.vna_other != vers_data + && ivna.vna_next != 0); + + if (ivna.vna_other == vers_data) + break; + + offset += ivn.vn_next; + } + while (ivn.vn_next != 0); + + if (ivna.vna_other == vers_data) + { + printf ("@%s (%d)", + strtab + ivna.vna_name, ivna.vna_other); + check_def = 0; + } + else if (! is_nobits) + error (_("bad dynamic symbol")); + else + check_def = 1; + } + + if (check_def) + { + if (vers_data != 0x8001) + { + Elf_Internal_Verdef ivd; + Elf_Internal_Verdaux ivda; + Elf_External_Verdaux evda; + unsigned long offset; + + offset = + version_info [DT_VERSIONTAGIDX (DT_VERDEF)] + - loadaddr; + + do + { + Elf_External_Verdef evd; + + GET_DATA (offset, evd, "version def"); + + ivd.vd_ndx = BYTE_GET (evd.vd_ndx); + ivd.vd_aux = BYTE_GET (evd.vd_aux); + ivd.vd_next = BYTE_GET (evd.vd_next); + + offset += ivd.vd_next; + } + while (ivd.vd_ndx != (vers_data & 0x7fff) + && ivd.vd_next != 0); + + offset -= ivd.vd_next; + offset += ivd.vd_aux; + + GET_DATA (offset, evda, "version def aux"); + + ivda.vda_name = BYTE_GET (evda.vda_name); + + if (psym->st_name != ivda.vda_name) + printf ((vers_data & 0x8000) + ? "@%s" : "@@%s", + strtab + ivda.vda_name); + } + } + } + } + + putchar ('\n'); + } + + free (symtab); + if (strtab != string_table) + free (strtab); + } + } + else if (do_syms) + printf + (_("\nDynamic symbol information is not available for displaying symbols.\n")); + + if (do_histogram && buckets != NULL) + { + int *lengths; + int *counts; + int hn; + int si; + int maxlength = 0; + int nzero_counts = 0; + int nsyms = 0; + + printf (_("\nHistogram for bucket list length (total of %d buckets):\n"), + nbuckets); + printf (_(" Length Number %% of total Coverage\n")); + + lengths = (int *) calloc (nbuckets, sizeof (int)); + if (lengths == NULL) + { + error (_("Out of memory")); + return 0; + } + for (hn = 0; hn < nbuckets; ++hn) + { + if (! buckets [hn]) + continue; + + for (si = buckets[hn]; si; si = chains[si]) + { + ++nsyms; + if (maxlength < ++lengths[hn]) + ++maxlength; + } + } + + counts = (int *) calloc (maxlength + 1, sizeof (int)); + if (counts == NULL) + { + error (_("Out of memory")); + return 0; + } + + for (hn = 0; hn < nbuckets; ++hn) + ++ counts [lengths [hn]]; + + printf (" 0 %-10d (%5.1f%%)\n", + counts[0], (counts[0] * 100.0) / nbuckets); + for (si = 1; si <= maxlength; ++si) + { + nzero_counts += counts[si] * si; + printf ("%7d %-10d (%5.1f%%) %5.1f%%\n", + si, counts[si], (counts[si] * 100.0) / nbuckets, + (nzero_counts * 100.0) / nsyms); + } + + free (counts); + free (lengths); + } + + if (buckets != NULL) + { + free (buckets); + free (chains); + } + + return 1; +} + +static int +process_syminfo (file) + FILE * file; +{ + int i; + + if (dynamic_syminfo == NULL + || !do_dynamic) + /* No syminfo, this is ok. */ + return 1; + + /* There better should be a dynamic symbol section. */ + if (dynamic_symbols == NULL || dynamic_strings == NULL) + return 0; + + if (dynamic_addr) + printf (_("\nDynamic info segment at offset 0x%lx contains %d entries:\n"), + dynamic_syminfo_offset, dynamic_syminfo_nent); + + printf (_(" Num: Name BoundTo Flags\n")); + for (i = 0; i < dynamic_syminfo_nent; ++i) + { + unsigned short int flags = dynamic_syminfo[i].si_flags; + + printf ("%4d: %-30s ", i, + dynamic_strings + dynamic_symbols[i].st_name); + + switch (dynamic_syminfo[i].si_boundto) + { + case SYMINFO_BT_SELF: + fputs ("SELF ", stdout); + break; + case SYMINFO_BT_PARENT: + fputs ("PARENT ", stdout); + break; + default: + if (dynamic_syminfo[i].si_boundto > 0 + && dynamic_syminfo[i].si_boundto < dynamic_size) + printf ("%-10s ", + dynamic_strings + + dynamic_segment[dynamic_syminfo[i].si_boundto].d_un.d_val); + else + printf ("%-10d ", dynamic_syminfo[i].si_boundto); + break; + } + + if (flags & SYMINFO_FLG_DIRECT) + printf (" DIRECT"); + if (flags & SYMINFO_FLG_PASSTHRU) + printf (" PASSTHRU"); + if (flags & SYMINFO_FLG_COPY) + printf (" COPY"); + if (flags & SYMINFO_FLG_LAZYLOAD) + printf (" LAZYLOAD"); + + puts (""); + } + + return 1; +} + +#ifdef SUPPORT_DISASSEMBLY +static void +disassemble_section (section, file) + Elf32_Internal_Shdr * section; + FILE * file; +{ + printf (_("\nAssembly dump of section %s\n"), + SECTION_NAME (section)); + + /* XXX -- to be done --- XXX */ + + return 1; +} +#endif + +static int +dump_section (section, file) + Elf32_Internal_Shdr * section; + FILE * file; +{ + int bytes; + int addr; + unsigned char * data; + unsigned char * start; + + bytes = section->sh_size; + + if (bytes == 0) + { + printf (_("\nSection '%s' has no data to dump.\n"), + SECTION_NAME (section)); + return 0; + } + else + printf (_("\nHex dump of section '%s':\n"), SECTION_NAME (section)); + + addr = section->sh_addr; + + GET_DATA_ALLOC (section->sh_offset, bytes, start, unsigned char *, + "section data"); + + data = start; + + while (bytes) + { + int j; + int k; + int lbytes; + + lbytes = (bytes > 16 ? 16 : bytes); + + printf (" 0x%8.8x ", addr); + + switch (elf_header.e_ident [EI_DATA]) + { + case ELFDATA2LSB: + for (j = 15; j >= 0; j --) + { + if (j < lbytes) + printf ("%2.2x", data [j]); + else + printf (" "); + + if (!(j & 0x3)) + printf (" "); + } + break; + + case ELFDATA2MSB: + for (j = 0; j < 16; j++) + { + if (j < lbytes) + printf ("%2.2x", data [j]); + else + printf (" "); + + if ((j & 3) == 3) + printf (" "); + } + break; + } + + for (j = 0; j < lbytes; j++) + { + k = data [j]; + if (k >= ' ' && k < 0x80) + printf ("%c", k); + else + printf ("."); + } + + putchar ('\n'); + + data += lbytes; + addr += lbytes; + bytes -= lbytes; + } + + free (start); + + return 1; +} + + +static unsigned long int +read_leb128 (data, length_return, sign) + unsigned char * data; + int * length_return; + int sign; +{ + unsigned long int result = 0; + unsigned int num_read = 0; + int shift = 0; + unsigned char byte; + + do + { + byte = * data ++; + num_read ++; + + result |= (byte & 0x7f) << shift; + + shift += 7; + + } + while (byte & 0x80); + + if (length_return != NULL) + * length_return = num_read; + + if (sign && (shift < 32) && (byte & 0x40)) + result |= -1 << shift; + + return result; +} + +typedef struct State_Machine_Registers +{ + unsigned long address; + unsigned int file; + unsigned int line; + unsigned int column; + int is_stmt; + int basic_block; + int end_sequence; +/* This variable hold the number of the last entry seen + in the File Table. */ + unsigned int last_file_entry; +} SMR; + +static SMR state_machine_regs; + +static void +reset_state_machine (is_stmt) + int is_stmt; +{ + state_machine_regs.address = 0; + state_machine_regs.file = 1; + state_machine_regs.line = 1; + state_machine_regs.column = 0; + state_machine_regs.is_stmt = is_stmt; + state_machine_regs.basic_block = 0; + state_machine_regs.end_sequence = 0; + state_machine_regs.last_file_entry = 0; +} + +/* Handled an extend line op. Returns true if this is the end + of sequence. */ +static int +process_extended_line_op (data, is_stmt) + unsigned char * data; + int is_stmt; +{ + unsigned char op_code; + int bytes_read; + unsigned int len; + unsigned char * name; + unsigned long adr; + + len = read_leb128 (data, & bytes_read, 0); + data += bytes_read; + + if (len == 0) + { + warn (_("badly formed extended line op encountered!")); + return bytes_read; + } + + len += bytes_read; + op_code = * data ++; + + printf (_(" Extended opcode %d: "), op_code); + + switch (op_code) + { + case DW_LNE_end_sequence: + printf (_("End of Sequence\n\n")); + reset_state_machine (is_stmt); + break; + + case DW_LNE_set_address: + /* XXX - assumption here that address size is 4! */ + adr = byte_get (data, 4); + printf (_("set Address to 0x%lx\n"), adr); + state_machine_regs.address = adr; + break; + + case DW_LNE_define_file: + printf (_(" define new File Table entry\n")); + printf (_(" Entry\tDir\tTime\tSize\tName\n")); + + printf (_(" %d\t"), ++ state_machine_regs.last_file_entry); + name = data; + data += strlen (data) + 1; + printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); + data += bytes_read; + printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); + data += bytes_read; + printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); + printf (_("%s\n\n"), name); + break; + + default: + printf (_("UNKNOWN: length %d\n"), len - bytes_read); + break; + } + + return len; +} + + +static int +display_debug_lines (section, start, file) + Elf32_Internal_Shdr * section; + unsigned char * start; + FILE * file; +{ + DWARF2_External_LineInfo * external; + DWARF2_Internal_LineInfo info; + unsigned char * standard_opcodes; + unsigned char * data = start; + unsigned char * end = start + section->sh_size; + unsigned char * end_of_sequence; + int i; + + printf (_("\nDump of debug contents of section %s:\n\n"), + SECTION_NAME (section)); + + while (data < end) + { + external = (DWARF2_External_LineInfo *) data; + + /* Check the length of the block. */ + info.li_length = BYTE_GET (external->li_length); + if (info.li_length > section->sh_size) + { + warn + (_("The line info appears to be corrupt - the section is too small\n")); + return 0; + } + + /* Check its version number. */ + info.li_version = BYTE_GET (external->li_version); + if (info.li_version != 2) + { + warn (_("Only DWARF version 2 line info is currently supported.\n")); + return 0; + } + + info.li_prologue_length = BYTE_GET (external->li_prologue_length); + info.li_min_insn_length = BYTE_GET (external->li_min_insn_length); + info.li_default_is_stmt = BYTE_GET (external->li_default_is_stmt); + info.li_line_base = BYTE_GET (external->li_line_base); + info.li_line_range = BYTE_GET (external->li_line_range); + info.li_opcode_base = BYTE_GET (external->li_opcode_base); + + /* Sign extend the line base field. */ + info.li_line_base <<= 24; + info.li_line_base >>= 24; + + printf (_(" Length: %ld\n"), info.li_length); + printf (_(" DWARF Version: %d\n"), info.li_version); + printf (_(" Prolgue Length: %d\n"), info.li_prologue_length); + printf (_(" Minimum Instruction Length: %d\n"), info.li_min_insn_length); + printf (_(" Initial value of 'is_stmt': %d\n"), info.li_default_is_stmt); + printf (_(" Line Base: %d\n"), info.li_line_base); + printf (_(" Line Range: %d\n"), info.li_line_range); + printf (_(" Opcode Base: %d\n"), info.li_opcode_base); + + end_of_sequence = data + info.li_length + sizeof (info.li_length); + + reset_state_machine (info.li_default_is_stmt); + + /* Display the contents of the Opcodes table. */ + standard_opcodes = data + sizeof (* external); + + printf (_("\n Opcodes:\n")); + + for (i = 1; i < info.li_opcode_base; i++) + printf (_(" Opcode %d has %d args\n"), i, standard_opcodes[i]); + + /* Display the contents of the Directory table. */ + data = standard_opcodes + info.li_opcode_base - 1; + + if (* data == 0) + printf (_("\n The Directory Table is empty.\n")); + else + { + printf (_("\n The Directory Table:\n")); + + while (* data != 0) + { + printf (_(" %s\n"), data); + + data += strlen (data) + 1; + } + } + + /* Skip the NUL at the end of the table. */ + data ++; + + /* Display the contents of the File Name table. */ + if (* data == 0) + printf (_("\n The File Name Table is empty.\n")); + else + { + printf (_("\n The File Name Table:\n")); + printf (_(" Entry\tDir\tTime\tSize\tName\n")); + + while (* data != 0) + { + char * name; + int bytes_read; + + printf (_(" %d\t"), ++ state_machine_regs.last_file_entry); + name = data; + + data += strlen (data) + 1; + + printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); + data += bytes_read; + printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); + data += bytes_read; + printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); + data += bytes_read; + printf (_("%s\n"), name); + } + } + + /* Skip the NUL at the end of the table. */ + data ++; + + /* Now display the statements. */ + printf (_("\n Line Number Statements:\n")); + + + while (data < end_of_sequence) + { + unsigned char op_code; + int adv; + int bytes_read; + + op_code = * data ++; + + switch (op_code) + { + case DW_LNS_extended_op: + data += process_extended_line_op (data, info.li_default_is_stmt); + break; + + case DW_LNS_copy: + printf (_(" Copy\n")); + break; + + case DW_LNS_advance_pc: + adv = info.li_min_insn_length * read_leb128 (data, & bytes_read, 0); + data += bytes_read; + state_machine_regs.address += adv; + printf (_(" Advance PC by %d to %lx\n"), adv, + state_machine_regs.address); + break; + + case DW_LNS_advance_line: + adv = read_leb128 (data, & bytes_read, 1); + data += bytes_read; + state_machine_regs.line += adv; + printf (_(" Advance Line by %d to %d\n"), adv, + state_machine_regs.line); + break; + + case DW_LNS_set_file: + adv = read_leb128 (data, & bytes_read, 0); + data += bytes_read; + printf (_(" Set File Name to entry %d in the File Name Table\n"), + adv); + state_machine_regs.file = adv; + break; + + case DW_LNS_set_column: + adv = read_leb128 (data, & bytes_read, 0); + data += bytes_read; + printf (_(" Set column to %d\n"), adv); + state_machine_regs.column = adv; + break; + + case DW_LNS_negate_stmt: + adv = state_machine_regs.is_stmt; + adv = ! adv; + printf (_(" Set is_stmt to %d\n"), adv); + state_machine_regs.is_stmt = adv; + break; + + case DW_LNS_set_basic_block: + printf (_(" Set basic block\n")); + state_machine_regs.basic_block = 1; + break; + + case DW_LNS_const_add_pc: + adv = (255 - info.li_opcode_base) / info.li_line_range; + state_machine_regs.address += adv; + printf (_(" Advance PC by constant %d to 0x%lx\n"), adv, + state_machine_regs.address); + break; + + case DW_LNS_fixed_advance_pc: + adv = byte_get (data, 2); + data += 2; + state_machine_regs.address += adv; + printf (_(" Advance PC by fixed size amount %d to 0x%lx\n"), + adv, state_machine_regs.address); + break; + + default: + op_code -= info.li_opcode_base; + adv = (op_code / info.li_line_range) * info.li_min_insn_length; + state_machine_regs.address += adv; + printf (_(" Special opcode %d: advance Address by %d to 0x%lx"), + op_code, adv, state_machine_regs.address); + adv += (op_code % info.li_line_range) + info.li_line_base; + state_machine_regs.line += adv; + printf (_(" and Line by %d to %d\n"), + adv, state_machine_regs.line); + break; + } + } + printf ("\n"); + } + + return 1; +} + +static int +display_debug_pubnames (section, start, file) + Elf32_Internal_Shdr * section; + unsigned char * start; + FILE * file; +{ + DWARF2_External_PubNames * external; + DWARF2_Internal_PubNames pubnames; + unsigned char * end; + + end = start + section->sh_size; + + printf (_("Contents of the %s section:\n\n"), SECTION_NAME (section)); + + while (start < end) + { + unsigned char * data; + unsigned long offset; + + external = (DWARF2_External_PubNames *) start; + + pubnames.pn_length = BYTE_GET (external->pn_length); + pubnames.pn_version = BYTE_GET (external->pn_version); + pubnames.pn_offset = BYTE_GET (external->pn_offset); + pubnames.pn_size = BYTE_GET (external->pn_size); + + data = start + sizeof (* external); + start += pubnames.pn_length + sizeof (external->pn_length); + + if (pubnames.pn_version != 2) + { + warn (_("Only DWARF 2 pubnames are currently supported")); + continue; + } + + printf (_(" Length: %ld\n"), + pubnames.pn_length); + printf (_(" Version: %d\n"), + pubnames.pn_version); + printf (_(" Offset into .debug_info section: %ld\n"), + pubnames.pn_offset); + printf (_(" Size of area in .debug_info section: %ld\n"), + pubnames.pn_size); + + printf (_("\n Offset\tName\n")); + + do + { + offset = byte_get (data, 4); + + if (offset != 0) + { + data += 4; + printf (" %ld\t\t%s\n", offset, data); + data += strlen (data) + 1; + } + } + while (offset != 0); + } + + printf ("\n"); + return 1; +} + +static char * +get_TAG_name (tag) + unsigned long tag; +{ + switch (tag) + { + case DW_TAG_padding: return "DW_TAG_padding"; + case DW_TAG_array_type: return "DW_TAG_array_type"; + case DW_TAG_class_type: return "DW_TAG_class_type"; + case DW_TAG_entry_point: return "DW_TAG_entry_point"; + case DW_TAG_enumeration_type: return "DW_TAG_enumeration_type"; + case DW_TAG_formal_parameter: return "DW_TAG_formal_parameter"; + case DW_TAG_imported_declaration: return "DW_TAG_imported_declaration"; + case DW_TAG_label: return "DW_TAG_label"; + case DW_TAG_lexical_block: return "DW_TAG_lexical_block"; + case DW_TAG_member: return "DW_TAG_member"; + case DW_TAG_pointer_type: return "DW_TAG_pointer_type"; + case DW_TAG_reference_type: return "DW_TAG_reference_type"; + case DW_TAG_compile_unit: return "DW_TAG_compile_unit"; + case DW_TAG_string_type: return "DW_TAG_string_type"; + case DW_TAG_structure_type: return "DW_TAG_structure_type"; + case DW_TAG_subroutine_type: return "DW_TAG_subroutine_type"; + case DW_TAG_typedef: return "DW_TAG_typedef"; + case DW_TAG_union_type: return "DW_TAG_union_type"; + case DW_TAG_unspecified_parameters: return "DW_TAG_unspecified_parameters"; + case DW_TAG_variant: return "DW_TAG_variant"; + case DW_TAG_common_block: return "DW_TAG_common_block"; + case DW_TAG_common_inclusion: return "DW_TAG_common_inclusion"; + case DW_TAG_inheritance: return "DW_TAG_inheritance"; + case DW_TAG_inlined_subroutine: return "DW_TAG_inlined_subroutine"; + case DW_TAG_module: return "DW_TAG_module"; + case DW_TAG_ptr_to_member_type: return "DW_TAG_ptr_to_member_type"; + case DW_TAG_set_type: return "DW_TAG_set_type"; + case DW_TAG_subrange_type: return "DW_TAG_subrange_type"; + case DW_TAG_with_stmt: return "DW_TAG_with_stmt"; + case DW_TAG_access_declaration: return "DW_TAG_access_declaration"; + case DW_TAG_base_type: return "DW_TAG_base_type"; + case DW_TAG_catch_block: return "DW_TAG_catch_block"; + case DW_TAG_const_type: return "DW_TAG_const_type"; + case DW_TAG_constant: return "DW_TAG_constant"; + case DW_TAG_enumerator: return "DW_TAG_enumerator"; + case DW_TAG_file_type: return "DW_TAG_file_type"; + case DW_TAG_friend: return "DW_TAG_friend"; + case DW_TAG_namelist: return "DW_TAG_namelist"; + case DW_TAG_namelist_item: return "DW_TAG_namelist_item"; + case DW_TAG_packed_type: return "DW_TAG_packed_type"; + case DW_TAG_subprogram: return "DW_TAG_subprogram"; + case DW_TAG_template_type_param: return "DW_TAG_template_type_param"; + case DW_TAG_template_value_param: return "DW_TAG_template_value_param"; + case DW_TAG_thrown_type: return "DW_TAG_thrown_type"; + case DW_TAG_try_block: return "DW_TAG_try_block"; + case DW_TAG_variant_part: return "DW_TAG_variant_part"; + case DW_TAG_variable: return "DW_TAG_variable"; + case DW_TAG_volatile_type: return "DW_TAG_volatile_type"; + case DW_TAG_MIPS_loop: return "DW_TAG_MIPS_loop"; + case DW_TAG_format_label: return "DW_TAG_format_label"; + case DW_TAG_function_template: return "DW_TAG_function_template"; + case DW_TAG_class_template: return "DW_TAG_class_template"; + default: + { + static char buffer [100]; + + sprintf (buffer, _("Unknown TAG value: %lx"), tag); + return buffer; + } + } +} + +static char * +get_AT_name (attribute) + unsigned long attribute; +{ + switch (attribute) + { + case DW_AT_sibling: return "DW_AT_sibling"; + case DW_AT_location: return "DW_AT_location"; + case DW_AT_name: return "DW_AT_name"; + case DW_AT_ordering: return "DW_AT_ordering"; + case DW_AT_subscr_data: return "DW_AT_subscr_data"; + case DW_AT_byte_size: return "DW_AT_byte_size"; + case DW_AT_bit_offset: return "DW_AT_bit_offset"; + case DW_AT_bit_size: return "DW_AT_bit_size"; + case DW_AT_element_list: return "DW_AT_element_list"; + case DW_AT_stmt_list: return "DW_AT_stmt_list"; + case DW_AT_low_pc: return "DW_AT_low_pc"; + case DW_AT_high_pc: return "DW_AT_high_pc"; + case DW_AT_language: return "DW_AT_language"; + case DW_AT_member: return "DW_AT_member"; + case DW_AT_discr: return "DW_AT_discr"; + case DW_AT_discr_value: return "DW_AT_discr_value"; + case DW_AT_visibility: return "DW_AT_visibility"; + case DW_AT_import: return "DW_AT_import"; + case DW_AT_string_length: return "DW_AT_string_length"; + case DW_AT_common_reference: return "DW_AT_common_reference"; + case DW_AT_comp_dir: return "DW_AT_comp_dir"; + case DW_AT_const_value: return "DW_AT_const_value"; + case DW_AT_containing_type: return "DW_AT_containing_type"; + case DW_AT_default_value: return "DW_AT_default_value"; + case DW_AT_inline: return "DW_AT_inline"; + case DW_AT_is_optional: return "DW_AT_is_optional"; + case DW_AT_lower_bound: return "DW_AT_lower_bound"; + case DW_AT_producer: return "DW_AT_producer"; + case DW_AT_prototyped: return "DW_AT_prototyped"; + case DW_AT_return_addr: return "DW_AT_return_addr"; + case DW_AT_start_scope: return "DW_AT_start_scope"; + case DW_AT_stride_size: return "DW_AT_stride_size"; + case DW_AT_upper_bound: return "DW_AT_upper_bound"; + case DW_AT_abstract_origin: return "DW_AT_abstract_origin"; + case DW_AT_accessibility: return "DW_AT_accessibility"; + case DW_AT_address_class: return "DW_AT_address_class"; + case DW_AT_artificial: return "DW_AT_artificial"; + case DW_AT_base_types: return "DW_AT_base_types"; + case DW_AT_calling_convention: return "DW_AT_calling_convention"; + case DW_AT_count: return "DW_AT_count"; + case DW_AT_data_member_location: return "DW_AT_data_member_location"; + case DW_AT_decl_column: return "DW_AT_decl_column"; + case DW_AT_decl_file: return "DW_AT_decl_file"; + case DW_AT_decl_line: return "DW_AT_decl_line"; + case DW_AT_declaration: return "DW_AT_declaration"; + case DW_AT_discr_list: return "DW_AT_discr_list"; + case DW_AT_encoding: return "DW_AT_encoding"; + case DW_AT_external: return "DW_AT_external"; + case DW_AT_frame_base: return "DW_AT_frame_base"; + case DW_AT_friend: return "DW_AT_friend"; + case DW_AT_identifier_case: return "DW_AT_identifier_case"; + case DW_AT_macro_info: return "DW_AT_macro_info"; + case DW_AT_namelist_items: return "DW_AT_namelist_items"; + case DW_AT_priority: return "DW_AT_priority"; + case DW_AT_segment: return "DW_AT_segment"; + case DW_AT_specification: return "DW_AT_specification"; + case DW_AT_static_link: return "DW_AT_static_link"; + case DW_AT_type: return "DW_AT_type"; + case DW_AT_use_location: return "DW_AT_use_location"; + case DW_AT_variable_parameter: return "DW_AT_variable_parameter"; + case DW_AT_virtuality: return "DW_AT_virtuality"; + case DW_AT_vtable_elem_location: return "DW_AT_vtable_elem_location"; + case DW_AT_MIPS_fde: return "DW_AT_MIPS_fde"; + case DW_AT_MIPS_loop_begin: return "DW_AT_MIPS_loop_begin"; + case DW_AT_MIPS_tail_loop_begin: return "DW_AT_MIPS_tail_loop_begin"; + case DW_AT_MIPS_epilog_begin: return "DW_AT_MIPS_epilog_begin"; + case DW_AT_MIPS_loop_unroll_factor: return "DW_AT_MIPS_loop_unroll_factor"; + case DW_AT_MIPS_software_pipeline_depth: return "DW_AT_MIPS_software_pipeline_depth"; + case DW_AT_MIPS_linkage_name: return "DW_AT_MIPS_linkage_name"; + case DW_AT_MIPS_stride: return "DW_AT_MIPS_stride"; + case DW_AT_MIPS_abstract_name: return "DW_AT_MIPS_abstract_name"; + case DW_AT_MIPS_clone_origin: return "DW_AT_MIPS_clone_origin"; + case DW_AT_MIPS_has_inlines: return "DW_AT_MIPS_has_inlines"; + case DW_AT_sf_names: return "DW_AT_sf_names"; + case DW_AT_src_info: return "DW_AT_src_info"; + case DW_AT_mac_info: return "DW_AT_mac_info"; + case DW_AT_src_coords: return "DW_AT_src_coords"; + case DW_AT_body_begin: return "DW_AT_body_begin"; + case DW_AT_body_end: return "DW_AT_body_end"; + default: + { + static char buffer [100]; + + sprintf (buffer, _("Unknown AT value: %lx"), attribute); + return buffer; + } + } +} + +static char * +get_FORM_name (form) + unsigned long form; +{ + switch (form) + { + case DW_FORM_addr: return "DW_FORM_addr"; + case DW_FORM_block2: return "DW_FORM_block2"; + case DW_FORM_block4: return "DW_FORM_block4"; + case DW_FORM_data2: return "DW_FORM_data2"; + case DW_FORM_data4: return "DW_FORM_data4"; + case DW_FORM_data8: return "DW_FORM_data8"; + case DW_FORM_string: return "DW_FORM_string"; + case DW_FORM_block: return "DW_FORM_block"; + case DW_FORM_block1: return "DW_FORM_block1"; + case DW_FORM_data1: return "DW_FORM_data1"; + case DW_FORM_flag: return "DW_FORM_flag"; + case DW_FORM_sdata: return "DW_FORM_sdata"; + case DW_FORM_strp: return "DW_FORM_strp"; + case DW_FORM_udata: return "DW_FORM_udata"; + case DW_FORM_ref_addr: return "DW_FORM_ref_addr"; + case DW_FORM_ref1: return "DW_FORM_ref1"; + case DW_FORM_ref2: return "DW_FORM_ref2"; + case DW_FORM_ref4: return "DW_FORM_ref4"; + case DW_FORM_ref8: return "DW_FORM_ref8"; + case DW_FORM_ref_udata: return "DW_FORM_ref_udata"; + case DW_FORM_indirect: return "DW_FORM_indirect"; + default: + { + static char buffer [100]; + + sprintf (buffer, _("Unknown FORM value: %lx"), form); + return buffer; + } + } +} + +/* FIXME: There are better and more effiecint ways to handle + these structures. For now though, I just want something that + is simple to implement. */ +typedef struct abbrev_attr +{ + unsigned long attribute; + unsigned long form; + struct abbrev_attr * next; +} +abbrev_attr; + +typedef struct abbrev_entry +{ + unsigned long entry; + unsigned long tag; + int children; + struct abbrev_attr * first_attr; + struct abbrev_attr * last_attr; + struct abbrev_entry * next; +} +abbrev_entry; + +static abbrev_entry * first_abbrev = NULL; +static abbrev_entry * last_abbrev = NULL; + +static void +free_abbrevs PARAMS ((void)) +{ + abbrev_entry * abbrev; + + for (abbrev = first_abbrev; abbrev;) + { + abbrev_entry * next = abbrev->next; + abbrev_attr * attr; + + for (attr = abbrev->first_attr; attr;) + { + abbrev_attr * next = attr->next; + + free (attr); + attr = next; + } + + free (abbrev); + abbrev = next; + } + + last_abbrev = first_abbrev = NULL; +} + +static void +add_abbrev (number, tag, children) + unsigned long number; + unsigned long tag; + int children; +{ + abbrev_entry * entry; + + entry = (abbrev_entry *) malloc (sizeof (* entry)); + + if (entry == NULL) + /* ugg */ + return; + + entry->entry = number; + entry->tag = tag; + entry->children = children; + entry->first_attr = NULL; + entry->last_attr = NULL; + entry->next = NULL; + + if (first_abbrev == NULL) + first_abbrev = entry; + else + last_abbrev->next = entry; + + last_abbrev = entry; +} + +static void +add_abbrev_attr (attribute, form) + unsigned long attribute; + unsigned long form; +{ + abbrev_attr * attr; + + attr = (abbrev_attr *) malloc (sizeof (* attr)); + + if (attr == NULL) + /* ugg */ + return; + + attr->attribute = attribute; + attr->form = form; + attr->next = NULL; + + if (last_abbrev->first_attr == NULL) + last_abbrev->first_attr = attr; + else + last_abbrev->last_attr->next = attr; + + last_abbrev->last_attr = attr; +} + +/* Processes the (partial) contents of a .debug_abbrev section. + Returns NULL if the end of the section was encountered. + Returns the address after the last byte read if the end of + an abbreviation set was found. */ + +static unsigned char * +process_abbrev_section (start, end) + unsigned char * start; + unsigned char * end; +{ + if (first_abbrev != NULL) + return NULL; + + while (start < end) + { + int bytes_read; + unsigned long entry; + unsigned long tag; + unsigned long attribute; + int children; + + entry = read_leb128 (start, & bytes_read, 0); + start += bytes_read; + + if (entry == 0) + return start; + + tag = read_leb128 (start, & bytes_read, 0); + start += bytes_read; + + children = * start ++; + + add_abbrev (entry, tag, children); + + do + { + unsigned long form; + + attribute = read_leb128 (start, & bytes_read, 0); + start += bytes_read; + + form = read_leb128 (start, & bytes_read, 0); + start += bytes_read; + + if (attribute != 0) + add_abbrev_attr (attribute, form); + } + while (attribute != 0); + } + + return NULL; +} + + +static int +display_debug_abbrev (section, start, file) + Elf32_Internal_Shdr * section; + unsigned char * start; + FILE * file; +{ + abbrev_entry * entry; + unsigned char * end = start + section->sh_size; + + printf (_("Contents of the %s section:\n\n"), SECTION_NAME (section)); + + do + { + start = process_abbrev_section (start, end); + + printf (_(" Number TAG\n")); + + for (entry = first_abbrev; entry; entry = entry->next) + { + abbrev_attr * attr; + + printf (_(" %ld %s [%s]\n"), + entry->entry, + get_TAG_name (entry->tag), + entry->children ? _("has children") : _("no children")); + + for (attr = entry->first_attr; attr; attr = attr->next) + { + printf (_(" %-18s %s\n"), + get_AT_name (attr->attribute), + get_FORM_name (attr->form)); + } + } + } + while (start); + + printf ("\n"); + + return 1; +} + + +static unsigned char * +display_block (data, length) + unsigned char * data; + unsigned long length; +{ + printf (_(" %lu byte block: "), length); + + while (length --) + printf ("%lx ", byte_get (data ++, 1)); + + return data; +} + +static void +decode_location_expression (data, pointer_size) + unsigned char * data; + unsigned int pointer_size; +{ + unsigned char op; + int bytes_read; + + op = * data ++; + + switch (op) + { + case DW_OP_addr: printf ("DW_OP_addr: %lx", byte_get (data, pointer_size)); break; + case DW_OP_deref: printf ("DW_OP_deref"); break; + case DW_OP_const1u: printf ("DW_OP_const1u: %lu", byte_get (data, 1)); break; + case DW_OP_const1s: printf ("DW_OP_const1s: %ld", (long) byte_get (data, 1)); break; + case DW_OP_const2u: printf ("DW_OP_const2u: %lu", byte_get (data, 2)); break; + case DW_OP_const2s: printf ("DW_OP_const2s: %ld", (long) byte_get (data, 2)); break; + case DW_OP_const4u: printf ("DW_OP_const4u: %lu", byte_get (data, 4)); break; + case DW_OP_const4s: printf ("DW_OP_const4s: %ld", (long) byte_get (data, 4)); break; + case DW_OP_const8u: printf ("DW_OP_const8u: %lu %lu", byte_get (data, 4), byte_get (data + 4, 4)); break; + case DW_OP_const8s: printf ("DW_OP_const8s: %ld %ld", byte_get (data, 4), byte_get (data + 4, 4)); break; + case DW_OP_constu: printf ("DW_OP_constu: %lu", read_leb128 (data, NULL, 0)); break; + case DW_OP_consts: printf ("DW_OP_consts: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_dup: printf ("DW_OP_dup"); break; + case DW_OP_drop: printf ("DW_OP_drop"); break; + case DW_OP_over: printf ("DW_OP_over"); break; + case DW_OP_pick: printf ("DW_OP_pick: %ld", byte_get (data, 1)); break; + case DW_OP_swap: printf ("DW_OP_swap"); break; + case DW_OP_rot: printf ("DW_OP_rot"); break; + case DW_OP_xderef: printf ("DW_OP_xderef"); break; + case DW_OP_abs: printf ("DW_OP_abs"); break; + case DW_OP_and: printf ("DW_OP_and"); break; + case DW_OP_div: printf ("DW_OP_div"); break; + case DW_OP_minus: printf ("DW_OP_minus"); break; + case DW_OP_mod: printf ("DW_OP_mod"); break; + case DW_OP_mul: printf ("DW_OP_mul"); break; + case DW_OP_neg: printf ("DW_OP_neg"); break; + case DW_OP_not: printf ("DW_OP_not"); break; + case DW_OP_or: printf ("DW_OP_or"); break; + case DW_OP_plus: printf ("DW_OP_plus"); break; + case DW_OP_plus_uconst: printf ("DW_OP_plus_uconst: %lu", read_leb128 (data, NULL, 0)); break; + case DW_OP_shl: printf ("DW_OP_shl"); break; + case DW_OP_shr: printf ("DW_OP_shr"); break; + case DW_OP_shra: printf ("DW_OP_shra"); break; + case DW_OP_xor: printf ("DW_OP_xor"); break; + case DW_OP_bra: printf ("DW_OP_bra: %ld", byte_get (data, 2)); break; + case DW_OP_eq: printf ("DW_OP_eq"); break; + case DW_OP_ge: printf ("DW_OP_ge"); break; + case DW_OP_gt: printf ("DW_OP_gt"); break; + case DW_OP_le: printf ("DW_OP_le"); break; + case DW_OP_lt: printf ("DW_OP_lt"); break; + case DW_OP_ne: printf ("DW_OP_ne"); break; + case DW_OP_skip: printf ("DW_OP_skip: %ld", byte_get (data, 2)); break; + case DW_OP_lit0: printf ("DW_OP_lit0"); break; + case DW_OP_lit1: printf ("DW_OP_lit1"); break; + case DW_OP_lit2: printf ("DW_OP_lit2"); break; + case DW_OP_lit3: printf ("DW_OP_lit3"); break; + case DW_OP_lit4: printf ("DW_OP_lit4"); break; + case DW_OP_lit5: printf ("DW_OP_lit5"); break; + case DW_OP_lit6: printf ("DW_OP_lit6"); break; + case DW_OP_lit7: printf ("DW_OP_lit7"); break; + case DW_OP_lit8: printf ("DW_OP_lit8"); break; + case DW_OP_lit9: printf ("DW_OP_lit9"); break; + case DW_OP_lit10: printf ("DW_OP_lit10"); break; + case DW_OP_lit11: printf ("DW_OP_lit11"); break; + case DW_OP_lit12: printf ("DW_OP_lit12"); break; + case DW_OP_lit13: printf ("DW_OP_lit13"); break; + case DW_OP_lit14: printf ("DW_OP_lit14"); break; + case DW_OP_lit15: printf ("DW_OP_lit15"); break; + case DW_OP_lit16: printf ("DW_OP_lit16"); break; + case DW_OP_lit17: printf ("DW_OP_lit17"); break; + case DW_OP_lit18: printf ("DW_OP_lit18"); break; + case DW_OP_lit19: printf ("DW_OP_lit19"); break; + case DW_OP_lit20: printf ("DW_OP_lit20"); break; + case DW_OP_lit21: printf ("DW_OP_lit21"); break; + case DW_OP_lit22: printf ("DW_OP_lit22"); break; + case DW_OP_lit23: printf ("DW_OP_lit23"); break; + case DW_OP_lit24: printf ("DW_OP_lit24"); break; + case DW_OP_lit25: printf ("DW_OP_lit25"); break; + case DW_OP_lit26: printf ("DW_OP_lit26"); break; + case DW_OP_lit27: printf ("DW_OP_lit27"); break; + case DW_OP_lit28: printf ("DW_OP_lit28"); break; + case DW_OP_lit29: printf ("DW_OP_lit29"); break; + case DW_OP_lit30: printf ("DW_OP_lit30"); break; + case DW_OP_lit31: printf ("DW_OP_lit31"); break; + case DW_OP_reg0: printf ("DW_OP_reg0"); break; + case DW_OP_reg1: printf ("DW_OP_reg1"); break; + case DW_OP_reg2: printf ("DW_OP_reg2"); break; + case DW_OP_reg3: printf ("DW_OP_reg3"); break; + case DW_OP_reg4: printf ("DW_OP_reg4"); break; + case DW_OP_reg5: printf ("DW_OP_reg5"); break; + case DW_OP_reg6: printf ("DW_OP_reg6"); break; + case DW_OP_reg7: printf ("DW_OP_reg7"); break; + case DW_OP_reg8: printf ("DW_OP_reg8"); break; + case DW_OP_reg9: printf ("DW_OP_reg9"); break; + case DW_OP_reg10: printf ("DW_OP_reg10"); break; + case DW_OP_reg11: printf ("DW_OP_reg11"); break; + case DW_OP_reg12: printf ("DW_OP_reg12"); break; + case DW_OP_reg13: printf ("DW_OP_reg13"); break; + case DW_OP_reg14: printf ("DW_OP_reg14"); break; + case DW_OP_reg15: printf ("DW_OP_reg15"); break; + case DW_OP_reg16: printf ("DW_OP_reg16"); break; + case DW_OP_reg17: printf ("DW_OP_reg17"); break; + case DW_OP_reg18: printf ("DW_OP_reg18"); break; + case DW_OP_reg19: printf ("DW_OP_reg19"); break; + case DW_OP_reg20: printf ("DW_OP_reg20"); break; + case DW_OP_reg21: printf ("DW_OP_reg21"); break; + case DW_OP_reg22: printf ("DW_OP_reg22"); break; + case DW_OP_reg23: printf ("DW_OP_reg23"); break; + case DW_OP_reg24: printf ("DW_OP_reg24"); break; + case DW_OP_reg25: printf ("DW_OP_reg25"); break; + case DW_OP_reg26: printf ("DW_OP_reg26"); break; + case DW_OP_reg27: printf ("DW_OP_reg27"); break; + case DW_OP_reg28: printf ("DW_OP_reg28"); break; + case DW_OP_reg29: printf ("DW_OP_reg29"); break; + case DW_OP_reg30: printf ("DW_OP_reg30"); break; + case DW_OP_reg31: printf ("DW_OP_reg31"); break; + case DW_OP_breg0: printf ("DW_OP_breg0: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg1: printf ("DW_OP_breg1: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg2: printf ("DW_OP_breg2: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg3: printf ("DW_OP_breg3: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg4: printf ("DW_OP_breg4: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg5: printf ("DW_OP_breg5: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg6: printf ("DW_OP_breg6: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg7: printf ("DW_OP_breg7: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg8: printf ("DW_OP_breg8: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg9: printf ("DW_OP_breg9: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg10: printf ("DW_OP_breg10: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg11: printf ("DW_OP_breg11: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg12: printf ("DW_OP_breg12: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg13: printf ("DW_OP_breg13: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg14: printf ("DW_OP_breg14: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg15: printf ("DW_OP_breg15: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg16: printf ("DW_OP_breg16: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg17: printf ("DW_OP_breg17: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg18: printf ("DW_OP_breg18: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg19: printf ("DW_OP_breg19: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg20: printf ("DW_OP_breg20: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg21: printf ("DW_OP_breg21: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg22: printf ("DW_OP_breg22: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg23: printf ("DW_OP_breg23: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg24: printf ("DW_OP_breg24: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg25: printf ("DW_OP_breg25: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg26: printf ("DW_OP_breg26: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg27: printf ("DW_OP_breg27: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg28: printf ("DW_OP_breg28: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg29: printf ("DW_OP_breg29: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg30: printf ("DW_OP_breg30: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_breg31: printf ("DW_OP_breg31: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_regx: printf ("DW_OP_regx: %lu", read_leb128 (data, NULL, 0)); break; + case DW_OP_fbreg: printf ("DW_OP_fbreg: %ld", read_leb128 (data, NULL, 1)); break; + case DW_OP_bregx: printf ("DW_OP_bregx: %lu %ld", read_leb128 (data, & bytes_read, 0), read_leb128 (data + bytes_read, NULL, 1)); break; + case DW_OP_piece: printf ("DW_OP_piece: %lu", read_leb128 (data, NULL, 0)); break; + case DW_OP_deref_size: printf ("DW_OP_deref_size: %ld", byte_get (data, 1)); break; + case DW_OP_xderef_size: printf ("DW_OP_xderef_size: %ld", byte_get (data, 1)); break; + case DW_OP_nop: printf ("DW_OP_nop"); break; + + default: + if (op >= DW_OP_lo_user + && op <= DW_OP_hi_user) + printf (_("(User defined location op)")); + else + printf (_("(Unknown location op)")); + break; + } +} + + +static unsigned char * +read_and_display_attr (attribute, form, data, pointer_size) + unsigned long attribute; + unsigned long form; + unsigned char * data; + unsigned long pointer_size; +{ + unsigned long uvalue; + unsigned char * block_start; + int bytes_read; + int is_ref = 0; + + printf (" %-18s:", get_AT_name (attribute)); + + switch (form) + { + case DW_FORM_ref_addr: + case DW_FORM_ref1: + case DW_FORM_ref2: + case DW_FORM_ref4: + case DW_FORM_ref8: + case DW_FORM_ref_udata: + is_ref = 1; + } + + switch (form) + { + case DW_FORM_ref_addr: + case DW_FORM_addr: + uvalue = byte_get (data, pointer_size); + printf (is_ref ? " <%x>" : " %#x", uvalue); + data += pointer_size; + break; + + case DW_FORM_ref1: + case DW_FORM_flag: + case DW_FORM_data1: + uvalue = byte_get (data ++, 1); + printf (is_ref ? " <%x>" : " %d", uvalue); + break; + + case DW_FORM_ref2: + case DW_FORM_data2: + uvalue = byte_get (data, 2); + data += 2; + printf (is_ref ? " <%x>" : " %d", uvalue); + break; + + case DW_FORM_ref4: + case DW_FORM_data4: + uvalue = byte_get (data, 4); + data += 4; + printf (is_ref ? " <%x>" : " %d", uvalue); + break; + + case DW_FORM_ref8: + case DW_FORM_data8: + uvalue = byte_get (data, 4); + printf (" %lx", uvalue); + printf (" %lx", byte_get (data + 4, 4)); + data += 8; + break; + + case DW_FORM_string: + printf (" %s", data); + data += strlen (data) + 1; + break; + + case DW_FORM_sdata: + uvalue = read_leb128 (data, & bytes_read, 1); + data += bytes_read; + printf (" %ld", (long) uvalue); + break; + + case DW_FORM_ref_udata: + case DW_FORM_udata: + uvalue = read_leb128 (data, & bytes_read, 0); + data += bytes_read; + printf (is_ref ? " <%lx>" : " %ld", uvalue); + break; + + case DW_FORM_block: + uvalue = read_leb128 (data, & bytes_read, 0); + block_start = data + bytes_read; + data = display_block (block_start, uvalue); + uvalue = * block_start; + break; + + case DW_FORM_block1: + uvalue = byte_get (data, 1); + block_start = data + 1; + data = display_block (block_start, uvalue); + uvalue = * block_start; + break; + + case DW_FORM_block2: + uvalue = byte_get (data, 2); + block_start = data + 2; + data = display_block (block_start, uvalue); + uvalue = * block_start; + break; + + case DW_FORM_block4: + uvalue = byte_get (data, 4); + block_start = data + 4; + data = display_block (block_start, uvalue); + uvalue = * block_start; + break; + + case DW_FORM_strp: + case DW_FORM_indirect: + warn (_("Unable to handle FORM: %d"), form); + break; + + default: + warn (_("Unrecognised form: %d"), form); + break; + } + + /* For some attributes we can display futher information. */ + + printf ("\t"); + + switch (attribute) + { + case DW_AT_inline: + switch (uvalue) + { + case DW_INL_not_inlined: printf (_("(not inlined)")); break; + case DW_INL_inlined: printf (_("(inlined)")); break; + case DW_INL_declared_not_inlined: printf (_("(declared as inline but ignored)")); break; + case DW_INL_declared_inlined: printf (_("(declared as inline and inlined)")); break; + default: printf (_(" (Unknown inline attribute value: %lx)"), uvalue); break; + } + break; + + case DW_AT_frame_base: + if (uvalue >= DW_OP_reg0 && uvalue <= DW_OP_reg31) + printf ("(reg %ld)", uvalue - DW_OP_reg0); + break; + + case DW_AT_language: + switch (uvalue) + { + case DW_LANG_C: printf ("(non-ANSI C)"); break; + case DW_LANG_C89: printf ("(ANSI C)"); break; + case DW_LANG_C_plus_plus: printf ("(C++)"); break; + case DW_LANG_Fortran77: printf ("(FORTRAN 77)"); break; + case DW_LANG_Fortran90: printf ("(Fortran 90)"); break; + case DW_LANG_Modula2: printf ("(Modula 2)"); break; + case DW_LANG_Pascal83: printf ("(ANSI Pascal)"); break; + case DW_LANG_Ada83: printf ("(Ada)"); break; + case DW_LANG_Cobol74: printf ("(Cobol 74)"); break; + case DW_LANG_Cobol85: printf ("(Cobol 85)"); break; + case DW_LANG_Mips_Assembler: printf ("(MIPS assembler)"); break; + default: printf ("(Unknown: %lx)", uvalue); break; + } + break; + + case DW_AT_encoding: + switch (uvalue) + { + case DW_ATE_void: printf ("(void)"); break; + case DW_ATE_address: printf ("(machine address)"); break; + case DW_ATE_boolean: printf ("(boolean)"); break; + case DW_ATE_complex_float: printf ("(complex float)"); break; + case DW_ATE_float: printf ("(float)"); break; + case DW_ATE_signed: printf ("(signed)"); break; + case DW_ATE_signed_char: printf ("(signed char)"); break; + case DW_ATE_unsigned: printf ("(unsigned)"); break; + case DW_ATE_unsigned_char: printf ("(unsigned char)"); break; + default: + if (uvalue >= DW_ATE_lo_user + && uvalue <= DW_ATE_hi_user) + printf ("(user defined type)"); + else + printf ("(unknown type)"); + break; + } + break; + + case DW_AT_accessibility: + switch (uvalue) + { + case DW_ACCESS_public: printf ("(public)"); break; + case DW_ACCESS_protected: printf ("(protected)"); break; + case DW_ACCESS_private: printf ("(private)"); break; + default: printf ("(unknown accessibility)"); break; + } + break; + + case DW_AT_visibility: + switch (uvalue) + { + case DW_VIS_local: printf ("(local)"); break; + case DW_VIS_exported: printf ("(exported)"); break; + case DW_VIS_qualified: printf ("(qualified)"); break; + default: printf ("(unknown visibility)"); break; + } + break; + + case DW_AT_virtuality: + switch (uvalue) + { + case DW_VIRTUALITY_none: printf ("(none)"); break; + case DW_VIRTUALITY_virtual: printf ("(virtual)"); break; + case DW_VIRTUALITY_pure_virtual:printf ("(pure_virtual)"); break; + default: printf ("(unknown virtuality)"); break; + } + break; + + case DW_AT_identifier_case: + switch (uvalue) + { + case DW_ID_case_sensitive: printf ("(case_sensitive)"); break; + case DW_ID_up_case: printf ("(up_case)"); break; + case DW_ID_down_case: printf ("(down_case)"); break; + case DW_ID_case_insensitive: printf ("(case_insensitive)"); break; + default: printf ("(unknown case)"); break; + } + break; + + case DW_AT_calling_convention: + switch (uvalue) + { + case DW_CC_normal: printf ("(normal)"); break; + case DW_CC_program: printf ("(program)"); break; + case DW_CC_nocall: printf ("(nocall)"); break; + default: + if (uvalue >= DW_CC_lo_user + && uvalue <= DW_CC_hi_user) + printf ("(user defined)"); + else + printf ("(unknown convention)"); + } + break; + + case DW_AT_location: + case DW_AT_data_member_location: + case DW_AT_vtable_elem_location: + printf ("("); + decode_location_expression (block_start, pointer_size); + printf (")"); + break; + + default: + break; + } + + printf ("\n"); + return data; +} + +static int +display_debug_info (section, start, file) + Elf32_Internal_Shdr * section; + unsigned char * start; + FILE * file; +{ + unsigned char * end = start + section->sh_size; + unsigned char * section_begin = start; + + printf (_("The section %s contains:\n\n"), SECTION_NAME (section)); + + while (start < end) + { + DWARF2_External_CompUnit * external; + DWARF2_Internal_CompUnit compunit; + unsigned char * tags; + int i; + int level; + + external = (DWARF2_External_CompUnit *) start; + + compunit.cu_length = BYTE_GET (external->cu_length); + compunit.cu_version = BYTE_GET (external->cu_version); + compunit.cu_abbrev_offset = BYTE_GET (external->cu_abbrev_offset); + compunit.cu_pointer_size = BYTE_GET (external->cu_pointer_size); + + tags = start + sizeof (* external); + start += compunit.cu_length + sizeof (external->cu_length); + + if (compunit.cu_version != 2) + { + warn (_("Only version 2 DWARF debug information is currently supported.\n")); + continue; + } + + printf (_(" Compilation Unit:\n")); + printf (_(" Length: %ld\n"), compunit.cu_length); + printf (_(" Version: %d\n"), compunit.cu_version); + printf (_(" Abbrev Offset: %ld\n"), compunit.cu_abbrev_offset); + printf (_(" Pointer Size: %d\n"), compunit.cu_pointer_size); + + if (first_abbrev != NULL) + free_abbrevs (); + + /* Read in the abbrevs used by this compilation unit. */ + + { + Elf32_Internal_Shdr * sec; + unsigned char * begin; + + /* Locate the .debug_abbrev section and process it. */ + for (i = 0, sec = section_headers; + i < elf_header.e_shnum; + i ++, sec ++) + if (strcmp (SECTION_NAME (sec), ".debug_abbrev") == 0) + break; + + if (i == -1 || sec->sh_size == 0) + { + warn (_("Unable to locate .debug_abbrev section!\n")); + return 0; + } + + GET_DATA_ALLOC (sec->sh_offset, sec->sh_size, begin, unsigned char *, + "debug_abbrev section data"); + + process_abbrev_section (begin + compunit.cu_abbrev_offset, + begin + sec->sh_size); + + free (begin); + } + + level = 0; + while (tags < start) + { + int bytes_read; + int abbrev_number; + abbrev_entry * entry; + abbrev_attr * attr; + + abbrev_number = read_leb128 (tags, & bytes_read, 0); + tags += bytes_read; + + /* A null DIE marks the end of a list of children. */ + if (abbrev_number == 0) + { + --level; + continue; + } + + /* Scan through the abbreviation list until we reach the + correct entry. */ + for (entry = first_abbrev; + entry && entry->entry != abbrev_number; + entry = entry->next) + continue; + + if (entry == NULL) + { + warn (_("Unable to locate entry %d in the abbreviation table\n"), + abbrev_number); + return 0; + } + + printf (_(" <%d><%x>: Abbrev Number: %d (%s)\n"), + level, tags - section_begin - bytes_read, + abbrev_number, + get_TAG_name (entry->tag)); + + for (attr = entry->first_attr; attr; attr = attr->next) + tags = read_and_display_attr (attr->attribute, + attr->form, + tags, + compunit.cu_pointer_size); + + if (entry->children) + ++level; + } + } + + printf ("\n"); + + return 1; +} + +static int +display_debug_aranges (section, start, file) + Elf32_Internal_Shdr * section; + unsigned char * start; + FILE * file; +{ + unsigned char * end = start + section->sh_size; + + printf (_("The section %s contains:\n\n"), SECTION_NAME (section)); + + while (start < end) + { + DWARF2_External_ARange * external; + DWARF2_Internal_ARange arange; + unsigned char * ranges; + unsigned long length; + unsigned long address; + + external = (DWARF2_External_ARange *) start; + + arange.ar_length = BYTE_GET (external->ar_length); + arange.ar_version = BYTE_GET (external->ar_version); + arange.ar_info_offset = BYTE_GET (external->ar_info_offset); + arange.ar_pointer_size = BYTE_GET (external->ar_pointer_size); + arange.ar_segment_size = BYTE_GET (external->ar_segment_size); + + printf (_(" Length: %ld\n"), arange.ar_length); + printf (_(" Version: %d\n"), arange.ar_version); + printf (_(" Offset into .debug_info: %lx\n"), arange.ar_info_offset); + printf (_(" Pointer Size: %d\n"), arange.ar_pointer_size); + printf (_(" Segment Size: %d\n"), arange.ar_segment_size); + + printf (_("\n Address Length\n")); + + ranges = start + sizeof (* external); + + for (;;) + { + address = byte_get (ranges, arange.ar_pointer_size); + + if (address == 0) + break; + + ranges += arange.ar_pointer_size; + + length = byte_get (ranges, arange.ar_pointer_size); + + ranges += arange.ar_pointer_size; + + printf (" %8.8lx %lu\n", address, length); + } + + start += arange.ar_length + sizeof (external->ar_length); + } + + printf ("\n"); + + return 1; +} + + +static int +display_debug_not_supported (section, start, file) + Elf32_Internal_Shdr * section; + unsigned char * start; + FILE * file; +{ + printf (_("Displaying the debug contents of section %s is not yet supported.\n"), + SECTION_NAME (section)); + + return 1; +} + + /* A structure containing the name of a debug section and a pointer + to a function that can decode it. */ +struct +{ + char * name; + int (* display) PARAMS((Elf32_Internal_Shdr *, unsigned char *, FILE *)); +} +debug_displays[] = +{ + { ".debug_info", display_debug_info }, + { ".debug_abbrev", display_debug_abbrev }, + { ".debug_line", display_debug_lines }, + { ".debug_aranges", display_debug_aranges }, + { ".debug_pubnames", display_debug_pubnames }, + { ".debug_macinfo", display_debug_not_supported }, + { ".debug_frame", display_debug_not_supported }, + { ".debug_str", display_debug_not_supported }, + { ".debug_static_func", display_debug_not_supported }, + { ".debug_static_vars", display_debug_not_supported }, + { ".debug_types", display_debug_not_supported }, + { ".debug_weaknames", display_debug_not_supported } +}; + +static int +display_debug_section (section, file) + Elf32_Internal_Shdr * section; + FILE * file; +{ + char * name = SECTION_NAME (section); + bfd_size_type length; + unsigned char * start; + int i; + + length = section->sh_size; + if (length == 0) + { + printf (_("\nSection '%s' has no debugging data.\n"), name); + return 0; + } + + GET_DATA_ALLOC (section->sh_offset, length, start, unsigned char *, + "debug section data"); + + /* See if we know how to display the contents of this section. */ + for (i = NUM_ELEM (debug_displays); i--;) + if (strcmp (debug_displays[i].name, name) == 0) + { + debug_displays[i].display (section, start, file); + break; + } + + if (i == -1) + printf (_("Unrecognised debug section: %s\n"), name); + + free (start); + + /* If we loaded in the abbrev section at some point, + we must release it here. */ + if (first_abbrev != NULL) + free_abbrevs (); + + return 1; +} + +static int +process_section_contents (file) + FILE * file; +{ + Elf32_Internal_Shdr * section; + unsigned int i; + + if (! do_dump) + return 1; + + for (i = 0, section = section_headers; + i < elf_header.e_shnum + && i < num_dump_sects; + i ++, section ++) + { +#ifdef SUPPORT_DISASSEMBLY + if (dump_sects[i] & DISASS_DUMP) + disassemble_section (section, file); +#endif + if (dump_sects[i] & HEX_DUMP) + dump_section (section, file); + + if (dump_sects[i] & DEBUG_DUMP) + display_debug_section (section, file); + } + + if (i < num_dump_sects) + warn (_("Some sections were not dumped because they do not exist!\n")); + + return 1; +} + +static void +process_mips_fpe_exception (mask) + int mask; +{ + if (mask) + { + int first = 1; + if (mask & OEX_FPU_INEX) + fputs ("INEX", stdout), first = 0; + if (mask & OEX_FPU_UFLO) + printf ("%sUFLO", first ? "" : "|"), first = 0; + if (mask & OEX_FPU_OFLO) + printf ("%sOFLO", first ? "" : "|"), first = 0; + if (mask & OEX_FPU_DIV0) + printf ("%sDIV0", first ? "" : "|"), first = 0; + if (mask & OEX_FPU_INVAL) + printf ("%sINVAL", first ? "" : "|"); + } + else + fputs ("0", stdout); +} + +static int +process_mips_specific (file) + FILE *file; +{ + Elf_Internal_Dyn *entry; + size_t liblist_offset = 0; + size_t liblistno = 0; + size_t conflictsno = 0; + size_t options_offset = 0; + size_t conflicts_offset = 0; + + /* We have a lot of special sections. Thanks SGI! */ + if (dynamic_segment == NULL) + /* No information available. */ + return 0; + + for (entry = dynamic_segment; entry->d_tag != DT_NULL; ++entry) + switch (entry->d_tag) + { + case DT_MIPS_LIBLIST: + liblist_offset = entry->d_un.d_val - loadaddr; + break; + case DT_MIPS_LIBLISTNO: + liblistno = entry->d_un.d_val; + break; + case DT_MIPS_OPTIONS: + options_offset = entry->d_un.d_val - loadaddr; + break; + case DT_MIPS_CONFLICT: + conflicts_offset = entry->d_un.d_val - loadaddr; + break; + case DT_MIPS_CONFLICTNO: + conflictsno = entry->d_un.d_val; + break; + default: + break; + } + + if (liblist_offset != 0 && liblistno != 0 && do_dynamic) + { + Elf32_External_Lib *elib; + size_t cnt; + + GET_DATA_ALLOC (liblist_offset, liblistno * sizeof (Elf32_External_Lib), + elib, Elf32_External_Lib *, "liblist"); + + printf ("\nSection '.liblist' contains %d entries:\n", liblistno); + fputs (" Library Time Stamp Checksum Version Flags\n", + stdout); + + for (cnt = 0; cnt < liblistno; ++cnt) + { + Elf32_Lib liblist; + time_t time; + char timebuf[20]; + + liblist.l_name = BYTE_GET (elib[cnt].l_name); + time = BYTE_GET (elib[cnt].l_time_stamp); + liblist.l_checksum = BYTE_GET (elib[cnt].l_checksum); + liblist.l_version = BYTE_GET (elib[cnt].l_version); + liblist.l_flags = BYTE_GET (elib[cnt].l_flags); + + strftime (timebuf, 20, "%Y-%m-%dT%H:%M:%S", gmtime (&time)); + + printf ("%3d: %-20s %s %#10lx %-7ld", cnt, + dynamic_strings + liblist.l_name, timebuf, + liblist.l_checksum, liblist.l_version); + + if (liblist.l_flags == 0) + puts (" NONE"); + else + { + static const struct + { + const char *name; + int bit; + } l_flags_vals[] = + { + { " EXACT_MATCH", LL_EXACT_MATCH }, + { " IGNORE_INT_VER", LL_IGNORE_INT_VER }, + { " REQUIRE_MINOR", LL_REQUIRE_MINOR }, + { " EXPORTS", LL_EXPORTS }, + { " DELAY_LOAD", LL_DELAY_LOAD }, + { " DELTA", LL_DELTA } + }; + int flags = liblist.l_flags; + int fcnt; + + for (fcnt = 0; + fcnt < sizeof (l_flags_vals) / sizeof (l_flags_vals[0]); + ++fcnt) + if ((flags & l_flags_vals[fcnt].bit) != 0) + { + fputs (l_flags_vals[fcnt].name, stdout); + flags ^= l_flags_vals[fcnt].bit; + } + if (flags != 0) + printf (" %#x", (unsigned int) flags); + + puts (""); + } + } + + free (elib); + } + + if (options_offset != 0) + { + Elf_External_Options *eopt; + Elf_Internal_Shdr *sect = section_headers; + Elf_Internal_Options *iopt; + Elf_Internal_Options *option; + size_t offset; + int cnt; + + /* Find the section header so that we get the size. */ + while (sect->sh_type != SHT_MIPS_OPTIONS) + ++sect; + + GET_DATA_ALLOC (options_offset, sect->sh_size, eopt, + Elf_External_Options *, "options"); + + iopt = (Elf_Internal_Options *) malloc ((sect->sh_size / sizeof (eopt)) + * sizeof (*iopt)); + if (iopt == NULL) + { + error (_("Out of memory")); + return 0; + } + + offset = cnt = 0; + option = iopt; + while (offset < sect->sh_size) + { + Elf_External_Options *eoption; + + eoption = (Elf_External_Options *) ((char *) eopt + offset); + + option->kind = BYTE_GET (eoption->kind); + option->size = BYTE_GET (eoption->size); + option->section = BYTE_GET (eoption->section); + option->info = BYTE_GET (eoption->info); + + offset += option->size; + ++option; + ++cnt; + } + + printf (_("\nSection '%s' contains %d entries:\n"), + string_table + sect->sh_name, cnt); + + option = iopt; + while (cnt-- > 0) + { + size_t len; + + switch (option->kind) + { + case ODK_NULL: + /* This shouldn't happen. */ + printf (" NULL %d %lx", option->section, option->info); + break; + case ODK_REGINFO: + printf (" REGINFO "); + if (elf_header.e_machine == EM_MIPS) + { + /* 32bit form. */ + Elf32_External_RegInfo *ereg; + Elf32_RegInfo reginfo; + + ereg = (Elf32_External_RegInfo *) (option + 1); + reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask); + reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]); + reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]); + reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]); + reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]); + reginfo.ri_gp_value = BYTE_GET (ereg->ri_gp_value); + + printf ("GPR %08lx GP 0x%lx\n", + reginfo.ri_gprmask, + (unsigned long) reginfo.ri_gp_value); + printf (" CPR0 %08lx CPR1 %08lx CPR2 %08lx CPR3 %08lx\n", + reginfo.ri_cprmask[0], reginfo.ri_cprmask[1], + reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]); + } + else + { + /* 64 bit form. */ + Elf64_External_RegInfo *ereg; + Elf64_Internal_RegInfo reginfo; + + ereg = (Elf64_External_RegInfo *) (option + 1); + reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask); + reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]); + reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]); + reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]); + reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]); + reginfo.ri_gp_value = BYTE_GET (ereg->ri_gp_value); + + printf ("GPR %08lx GP 0x", + reginfo.ri_gprmask); + printf_vma (reginfo.ri_gp_value); + printf ("\n"); + + printf (" CPR0 %08lx CPR1 %08lx CPR2 %08lx CPR3 %08lx\n", + reginfo.ri_cprmask[0], reginfo.ri_cprmask[1], + reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]); + } + ++option; + continue; + case ODK_EXCEPTIONS: + fputs (" EXCEPTIONS fpe_min(", stdout); + process_mips_fpe_exception (option->info & OEX_FPU_MIN); + fputs (") fpe_max(", stdout); + process_mips_fpe_exception ((option->info & OEX_FPU_MAX) >> 8); + fputs (")", stdout); + + if (option->info & OEX_PAGE0) + fputs (" PAGE0", stdout); + if (option->info & OEX_SMM) + fputs (" SMM", stdout); + if (option->info & OEX_FPDBUG) + fputs (" FPDBUG", stdout); + if (option->info & OEX_DISMISS) + fputs (" DISMISS", stdout); + break; + case ODK_PAD: + fputs (" PAD ", stdout); + if (option->info & OPAD_PREFIX) + fputs (" PREFIX", stdout); + if (option->info & OPAD_POSTFIX) + fputs (" POSTFIX", stdout); + if (option->info & OPAD_SYMBOL) + fputs (" SYMBOL", stdout); + break; + case ODK_HWPATCH: + fputs (" HWPATCH ", stdout); + if (option->info & OHW_R4KEOP) + fputs (" R4KEOP", stdout); + if (option->info & OHW_R8KPFETCH) + fputs (" R8KPFETCH", stdout); + if (option->info & OHW_R5KEOP) + fputs (" R5KEOP", stdout); + if (option->info & OHW_R5KCVTL) + fputs (" R5KCVTL", stdout); + break; + case ODK_FILL: + fputs (" FILL ", stdout); + /* XXX Print content of info word? */ + break; + case ODK_TAGS: + fputs (" TAGS ", stdout); + /* XXX Print content of info word? */ + break; + case ODK_HWAND: + fputs (" HWAND ", stdout); + if (option->info & OHWA0_R4KEOP_CHECKED) + fputs (" R4KEOP_CHECKED", stdout); + if (option->info & OHWA0_R4KEOP_CLEAN) + fputs (" R4KEOP_CLEAN", stdout); + break; + case ODK_HWOR: + fputs (" HWOR ", stdout); + if (option->info & OHWA0_R4KEOP_CHECKED) + fputs (" R4KEOP_CHECKED", stdout); + if (option->info & OHWA0_R4KEOP_CLEAN) + fputs (" R4KEOP_CLEAN", stdout); + break; + case ODK_GP_GROUP: + printf (" GP_GROUP %#06lx self-contained %#06lx", + option->info & OGP_GROUP, + (option->info & OGP_SELF) >> 16); + break; + case ODK_IDENT: + printf (" IDENT %#06lx self-contained %#06lx", + option->info & OGP_GROUP, + (option->info & OGP_SELF) >> 16); + break; + default: + /* This shouldn't happen. */ + printf (" %3d ??? %d %lx", + option->kind, option->section, option->info); + break; + } + + len = sizeof (*eopt); + while (len < option->size) + if (((char *) option)[len] >= ' ' + && ((char *) option)[len] < 0x7f) + printf ("%c", ((char *) option)[len++]); + else + printf ("\\%03o", ((char *) option)[len++]); + + fputs ("\n", stdout); + ++option; + } + + free (eopt); + } + + if (conflicts_offset != 0 && conflictsno != 0) + { + Elf32_External_Conflict *econf32; + Elf64_External_Conflict *econf64; + Elf32_Conflict *iconf; + size_t cnt; + + if (dynamic_symbols == NULL) + { + error (_("conflict list with without table")); + return 0; + } + + iconf = (Elf32_Conflict *) malloc (conflictsno * sizeof (*iconf)); + if (iconf == NULL) + { + error (_("Out of memory")); + return 0; + } + + if (binary_class == ELFCLASS32) + { + GET_DATA_ALLOC (conflicts_offset, conflictsno * sizeof (*econf32), + econf32, Elf32_External_Conflict *, "conflict"); + + for (cnt = 0; cnt < conflictsno; ++cnt) + iconf[cnt] = BYTE_GET (econf32[cnt]); + } + else + { + GET_DATA_ALLOC (conflicts_offset, conflictsno * sizeof (*econf64), + econf64, Elf64_External_Conflict *, "conflict"); + + for (cnt = 0; cnt < conflictsno; ++cnt) + iconf[cnt] = BYTE_GET (econf64[cnt]); + } + + printf (_("\nSection '.conflict' contains %d entries:\n"), conflictsno); + puts (_(" Num: Index Value Name")); + + for (cnt = 0; cnt < conflictsno; ++cnt) + { + Elf_Internal_Sym *psym = &dynamic_symbols[iconf[cnt]]; + + printf ("%5u: %8lu %#10lx %s\n", + cnt, iconf[cnt], (unsigned long) psym->st_value, + dynamic_strings + psym->st_name); + } + + + free (iconf); + } + + return 1; +} + +static int +process_arch_specific (file) + FILE *file; +{ + switch (elf_header.e_machine) + { + case EM_MIPS: + case EM_MIPS_RS4_BE: + return process_mips_specific (file); + break; + default: + break; + } + return 1; +} + +static int +get_file_header (file) + FILE * file; +{ + Elf32_External_Ehdr ehdr; + + if (fread (& ehdr, sizeof (ehdr), 1, file) != 1) + return 0; + + memcpy (elf_header.e_ident, ehdr.e_ident, EI_NIDENT); + + if (elf_header.e_ident [EI_DATA] == ELFDATA2LSB) + byte_get = byte_get_little_endian; + else + byte_get = byte_get_big_endian; + + elf_header.e_entry = BYTE_GET (ehdr.e_entry); + elf_header.e_phoff = BYTE_GET (ehdr.e_phoff); + elf_header.e_shoff = BYTE_GET (ehdr.e_shoff); + elf_header.e_version = BYTE_GET (ehdr.e_version); + elf_header.e_flags = BYTE_GET (ehdr.e_flags); + elf_header.e_type = BYTE_GET (ehdr.e_type); + elf_header.e_machine = BYTE_GET (ehdr.e_machine); + elf_header.e_ehsize = BYTE_GET (ehdr.e_ehsize); + elf_header.e_phentsize = BYTE_GET (ehdr.e_phentsize); + elf_header.e_phnum = BYTE_GET (ehdr.e_phnum); + elf_header.e_shentsize = BYTE_GET (ehdr.e_shentsize); + elf_header.e_shnum = BYTE_GET (ehdr.e_shnum); + elf_header.e_shstrndx = BYTE_GET (ehdr.e_shstrndx); + + return 1; +} + +static void +process_file (file_name) + char * file_name; +{ + FILE * file; + struct stat statbuf; + unsigned int i; + + if (stat (file_name, & statbuf) < 0) + { + error (_("Cannot stat input file %s.\n"), file_name); + return; + } + + file = fopen (file_name, "rb"); + if (file == NULL) + { + error (_("Input file %s not found.\n"), file_name); + return; + } + + if (! get_file_header (file)) + { + error (_("%s: Failed to read file header\n"), file_name); + fclose (file); + return; + } + + /* Initialise per file variables. */ + for (i = NUM_ELEM (version_info); i--;) + version_info[i] = 0; + + for (i = NUM_ELEM (dynamic_info); i--;) + dynamic_info[i] = 0; + + /* Process the file. */ + if (show_name) + printf (_("\nFile: %s\n"), file_name); + + if (! process_file_header ()) + { + fclose (file); + return; + } + + process_section_headers (file); + + process_program_headers (file); + + process_dynamic_segment (file); + + process_relocs (file); + + process_symbol_table (file); + + process_syminfo (file); + + process_version_sections (file); + + process_section_contents (file); + + process_arch_specific (file); + + fclose (file); + + if (section_headers) + { + free (section_headers); + section_headers = NULL; + } + + if (string_table) + { + free (string_table); + string_table = NULL; + } + + if (dynamic_strings) + { + free (dynamic_strings); + dynamic_strings = NULL; + } + + if (dynamic_symbols) + { + free (dynamic_symbols); + dynamic_symbols = NULL; + } + + if (dynamic_syminfo) + { + free (dynamic_syminfo); + dynamic_syminfo = NULL; + } +} + +#ifdef SUPPORT_DISASSEMBLY +/* Needed by the i386 disassembler. For extra credit, someone could +fix this so that we insert symbolic addresses here, esp for GOT/PLT +symbols */ + +void +print_address (unsigned int addr, FILE * outfile) +{ + fprintf (outfile,"0x%8.8x", addr); +} + +/* Needed by the i386 disassembler. */ +void +db_task_printsym (unsigned int addr) +{ + print_address (addr, stderr); +} +#endif + +int +main (argc, argv) + int argc; + char ** argv; +{ +#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) + setlocale (LC_MESSAGES, ""); +#endif + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + + parse_args (argc, argv); + + if (optind < (argc - 1)) + show_name = 1; + + while (optind < argc) + process_file (argv [optind ++]); + + if (dump_sects != NULL) + free (dump_sects); + + return 0; +} diff --git a/binutils/rename.c b/binutils/rename.c new file mode 100644 index 0000000..fdc7263 --- /dev/null +++ b/binutils/rename.c @@ -0,0 +1,210 @@ +/* rename.c -- rename a file, preserving symlinks. + Copyright (C) 1999 Free Software Foundation, Inc. + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#include "bfd.h" +#include "bucomm.h" + +#include <sys/stat.h> + +#ifdef HAVE_GOOD_UTIME_H +#include <utime.h> +#else /* ! HAVE_GOOD_UTIME_H */ +#ifdef HAVE_UTIMES +#include <sys/time.h> +#endif /* HAVE_UTIMES */ +#endif /* ! HAVE_GOOD_UTIME_H */ + +static int simple_copy PARAMS ((const char *, const char *)); + +/* The number of bytes to copy at once. */ +#define COPY_BUF 8192 + +/* Copy file FROM to file TO, performing no translations. + Return 0 if ok, -1 if error. */ + +static int +simple_copy (from, to) + const char *from; + const char *to; +{ + int fromfd, tofd, nread; + int saved; + char buf[COPY_BUF]; + + fromfd = open (from, O_RDONLY); + if (fromfd < 0) + return -1; + tofd = creat (to, 0777); + if (tofd < 0) + { + saved = errno; + close (fromfd); + errno = saved; + return -1; + } + while ((nread = read (fromfd, buf, sizeof buf)) > 0) + { + if (write (tofd, buf, nread) != nread) + { + saved = errno; + close (fromfd); + close (tofd); + errno = saved; + return -1; + } + } + saved = errno; + close (fromfd); + close (tofd); + if (nread < 0) + { + errno = saved; + return -1; + } + return 0; +} + +/* Set the times of the file DESTINATION to be the same as those in + STATBUF. */ + +void +set_times (destination, statbuf) + const char *destination; + const struct stat *statbuf; +{ + int result; + + { +#ifdef HAVE_GOOD_UTIME_H + struct utimbuf tb; + + tb.actime = statbuf->st_atime; + tb.modtime = statbuf->st_mtime; + result = utime (destination, &tb); +#else /* ! HAVE_GOOD_UTIME_H */ +#ifndef HAVE_UTIMES + long tb[2]; + + tb[0] = statbuf->st_atime; + tb[1] = statbuf->st_mtime; + result = utime (destination, tb); +#else /* HAVE_UTIMES */ + struct timeval tv[2]; + + tv[0].tv_sec = statbuf->st_atime; + tv[0].tv_usec = 0; + tv[1].tv_sec = statbuf->st_mtime; + tv[1].tv_usec = 0; + result = utimes (destination, tv); +#endif /* HAVE_UTIMES */ +#endif /* ! HAVE_GOOD_UTIME_H */ + } + + if (result != 0) + non_fatal (_("%s: cannot set time: %s"), destination, strerror (errno)); +} + +#ifndef S_ISLNK +#ifdef S_IFLNK +#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +#else +#define S_ISLNK(m) 0 +#define lstat stat +#endif +#endif + +/* Rename FROM to TO, copying if TO is a link. + Return 0 if ok, -1 if error. */ + +int +smart_rename (from, to, preserve_dates) + const char *from; + const char *to; + int preserve_dates; +{ + int exists; + struct stat s; + int ret = 0; + + exists = lstat (to, &s); + +#if defined (_WIN32) && !defined (__CYGWIN32__) + /* Win32, unlike unix, will not erase `to' in `rename(from, to)' but + fail instead. Also, chown is not present. */ + + if (exists == 0) + remove (to); + + ret = rename (from, to); + if (ret != 0) + { + /* We have to clean up here. */ + + non_fatal (_("%s: rename: %s"), to, strerror (errno)); + unlink (from); + } +#else + /* Use rename only if TO is not a symbolic link and has + only one hard link. */ + if (exists < 0 || (!S_ISLNK (s.st_mode) && s.st_nlink == 1)) + { + ret = rename (from, to); + if (ret == 0) + { + if (exists) + { + /* Try to preserve the permission bits and ownership of + TO. First get the mode right except for the setuid + bit. Then change the ownership. Then fix the setuid + bit. We do the chmod before the chown because if the + chown succeeds, and we are a normal user, we won't be + able to do the chmod afterward. We don't bother to + fix the setuid bit first because that might introduce + a fleeting security problem, and because the chown + will clear the setuid bit anyhow. We only fix the + setuid bit if the chown succeeds, because we don't + want to introduce an unexpected setuid file owned by + the user running objcopy. */ + chmod (to, s.st_mode & 0777); + if (chown (to, s.st_uid, s.st_gid) >= 0) + chmod (to, s.st_mode & 07777); + } + } + else + { + /* We have to clean up here. */ + non_fatal (_("%s: rename: %s"), to, strerror (errno)); + unlink (from); + } + } + else + { + ret = simple_copy (from, to); + if (ret != 0) + non_fatal (_("%s: simple_copy: %s"), to, strerror (errno)); + + if (preserve_dates) + set_times (to, &s); + unlink (from); + } +#endif /* _WIN32 && !__CYGWIN32__ */ + + return ret; +} diff --git a/binutils/resbin.c b/binutils/resbin.c new file mode 100644 index 0000000..8fc07fb --- /dev/null +++ b/binutils/resbin.c @@ -0,0 +1,2387 @@ +/* resbin.c -- manipulate the Windows binary resource format. + Copyright 1997, 1998 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Cygnus Support. + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* This file contains functions to convert between the binary resource + format and the internal structures that we want to use. The same + binary resource format is used in both res and COFF files. */ + +#include "bfd.h" +#include "bucomm.h" +#include "libiberty.h" +#include "windres.h" + +/* Macros to swap in values. */ + +#define get_16(be, s) ((be) ? bfd_getb16 (s) : bfd_getl16 (s)) +#define get_32(be, s) ((be) ? bfd_getb32 (s) : bfd_getl32 (s)) + +/* Local functions. */ + +static void toosmall PARAMS ((const char *)); +static unichar *get_unicode + PARAMS ((const unsigned char *, unsigned long, int, int *)); +static int get_resid + PARAMS ((struct res_id *, const unsigned char *, unsigned long, int)); +static struct res_resource *bin_to_res_generic + PARAMS ((enum res_type, const unsigned char *, unsigned long)); +static struct res_resource *bin_to_res_cursor + PARAMS ((const unsigned char *, unsigned long, int)); +static struct res_resource *bin_to_res_menu + PARAMS ((const unsigned char *, unsigned long, int)); +static struct menuitem *bin_to_res_menuitems + PARAMS ((const unsigned char *, unsigned long, int, int *)); +static struct menuitem *bin_to_res_menuexitems + PARAMS ((const unsigned char *, unsigned long, int, int *)); +static struct res_resource *bin_to_res_dialog + PARAMS ((const unsigned char *, unsigned long, int)); +static struct res_resource *bin_to_res_string + PARAMS ((const unsigned char *, unsigned long, int)); +static struct res_resource *bin_to_res_fontdir + PARAMS ((const unsigned char *, unsigned long, int)); +static struct res_resource *bin_to_res_accelerators + PARAMS ((const unsigned char *, unsigned long, int)); +static struct res_resource *bin_to_res_rcdata + PARAMS ((const unsigned char *, unsigned long, int)); +static struct res_resource *bin_to_res_group_cursor + PARAMS ((const unsigned char *, unsigned long, int)); +static struct res_resource *bin_to_res_group_icon + PARAMS ((const unsigned char *, unsigned long, int)); +static struct res_resource *bin_to_res_version + PARAMS ((const unsigned char *, unsigned long, int)); +static struct res_resource *bin_to_res_userdata + PARAMS ((const unsigned char *, unsigned long, int)); + +/* Given a resource type ID, a pointer to data, a length, return a + res_resource structure which represents that resource. The caller + is responsible for initializing the res_info and coff_info fields + of the returned structure. */ + +struct res_resource * +bin_to_res (type, data, length, big_endian) + struct res_id type; + const unsigned char *data; + unsigned long length; + int big_endian; +{ + if (type.named) + return bin_to_res_userdata (data, length, big_endian); + else + { + switch (type.u.id) + { + default: + return bin_to_res_userdata (data, length, big_endian); + case RT_CURSOR: + return bin_to_res_cursor (data, length, big_endian); + case RT_BITMAP: + return bin_to_res_generic (RES_TYPE_BITMAP, data, length); + case RT_ICON: + return bin_to_res_generic (RES_TYPE_ICON, data, length); + case RT_MENU: + return bin_to_res_menu (data, length, big_endian); + case RT_DIALOG: + return bin_to_res_dialog (data, length, big_endian); + case RT_STRING: + return bin_to_res_string (data, length, big_endian); + case RT_FONTDIR: + return bin_to_res_fontdir (data, length, big_endian); + case RT_FONT: + return bin_to_res_generic (RES_TYPE_FONT, data, length); + case RT_ACCELERATOR: + return bin_to_res_accelerators (data, length, big_endian); + case RT_RCDATA: + return bin_to_res_rcdata (data, length, big_endian); + case RT_MESSAGETABLE: + return bin_to_res_generic (RES_TYPE_MESSAGETABLE, data, length); + case RT_GROUP_CURSOR: + return bin_to_res_group_cursor (data, length, big_endian); + case RT_GROUP_ICON: + return bin_to_res_group_icon (data, length, big_endian); + case RT_VERSION: + return bin_to_res_version (data, length, big_endian); + } + } +} + +/* Give an error if the binary data is too small. */ + +static void +toosmall (msg) + const char *msg; +{ + fatal (_("%s: not enough binary data"), msg); +} + +/* Swap in a NULL terminated unicode string. */ + +static unichar * +get_unicode (data, length, big_endian, retlen) + const unsigned char *data; + unsigned long length; + int big_endian; + int *retlen; +{ + int c, i; + unichar *ret; + + c = 0; + while (1) + { + if (length < (unsigned long) c * 2 + 2) + toosmall (_("null terminated unicode string")); + if (get_16 (big_endian, data + c * 2) == 0) + break; + ++c; + } + + ret = (unichar *) res_alloc ((c + 1) * sizeof (unichar)); + + for (i = 0; i < c; i++) + ret[i] = get_16 (big_endian, data + i * 2); + ret[i] = 0; + + if (retlen != NULL) + *retlen = c; + + return ret; +} + +/* Get a resource identifier. This returns the number of bytes used. */ + +static int +get_resid (id, data, length, big_endian) + struct res_id *id; + const unsigned char *data; + unsigned long length; + int big_endian; +{ + int first; + + if (length < 2) + toosmall (_("resource ID")); + + first = get_16 (big_endian, data); + if (first == 0xffff) + { + if (length < 4) + toosmall (_("resource ID")); + id->named = 0; + id->u.id = get_16 (big_endian, data + 2); + return 4; + } + else + { + id->named = 1; + id->u.n.name = get_unicode (data, length, big_endian, &id->u.n.length); + return id->u.n.length * 2 + 2; + } +} + +/* Convert a resource which just stores uninterpreted data from + binary. */ + +struct res_resource * +bin_to_res_generic (type, data, length) + enum res_type type; + const unsigned char *data; + unsigned long length; +{ + struct res_resource *r; + + r = (struct res_resource *) res_alloc (sizeof *r); + r->type = type; + r->u.data.data = data; + r->u.data.length = length; + + return r; +} + +/* Convert a cursor resource from binary. */ + +struct res_resource * +bin_to_res_cursor (data, length, big_endian) + const unsigned char *data; + unsigned long length; + int big_endian; +{ + struct cursor *c; + struct res_resource *r; + + if (length < 4) + toosmall (_("cursor")); + + c = (struct cursor *) res_alloc (sizeof *c); + c->xhotspot = get_16 (big_endian, data); + c->yhotspot = get_16 (big_endian, data + 2); + c->length = length - 4; + c->data = data + 4; + + r = (struct res_resource *) res_alloc (sizeof *r); + r->type = RES_TYPE_CURSOR; + r->u.cursor = c; + + return r; +} + +/* Convert a menu resource from binary. */ + +struct res_resource * +bin_to_res_menu (data, length, big_endian) + const unsigned char *data; + unsigned long length; + int big_endian; +{ + struct res_resource *r; + struct menu *m; + int version, read; + + r = (struct res_resource *) res_alloc (sizeof *r); + r->type = RES_TYPE_MENU; + + m = (struct menu *) res_alloc (sizeof *m); + r->u.menu = m; + + if (length < 2) + toosmall (_("menu header")); + + version = get_16 (big_endian, data); + + if (version == 0) + { + if (length < 4) + toosmall (_("menu header")); + m->help = 0; + m->items = bin_to_res_menuitems (data + 4, length - 4, big_endian, + &read); + } + else if (version == 1) + { + unsigned int offset; + + if (length < 8) + toosmall (_("menuex header")); + m->help = get_32 (big_endian, data + 4); + offset = get_16 (big_endian, data + 2); + if (offset + 4 >= length) + toosmall (_("menuex offset")); + m->items = bin_to_res_menuexitems (data + 4 + offset, + length - (4 + offset), + big_endian, + &read); + } + else + fatal (_("unsupported menu version %d"), version); + + return r; +} + +/* Convert menu items from binary. */ + +static struct menuitem * +bin_to_res_menuitems (data, length, big_endian, read) + const unsigned char *data; + unsigned long length; + int big_endian; + int *read; +{ + struct menuitem *first, **pp; + + first = NULL; + pp = &first; + + *read = 0; + + while (length > 0) + { + int flags, slen, itemlen; + unsigned int stroff; + struct menuitem *mi; + + if (length < 4) + toosmall (_("menuitem header")); + + mi = (struct menuitem *) res_alloc (sizeof *mi); + mi->state = 0; + mi->help = 0; + + flags = get_16 (big_endian, data); + mi->type = flags &~ (MENUITEM_POPUP | MENUITEM_ENDMENU); + + if ((flags & MENUITEM_POPUP) == 0) + stroff = 4; + else + stroff = 2; + + if (length < stroff + 2) + toosmall (_("menuitem header")); + + if (get_16 (big_endian, data + stroff) == 0) + { + slen = 0; + mi->text = NULL; + } + else + mi->text = get_unicode (data + stroff, length - stroff, big_endian, + &slen); + + itemlen = stroff + slen * 2 + 2; + + if ((flags & MENUITEM_POPUP) == 0) + { + mi->popup = NULL; + mi->id = get_16 (big_endian, data + 2); + } + else + { + int subread; + + mi->id = 0; + mi->popup = bin_to_res_menuitems (data + itemlen, length - itemlen, + big_endian, &subread); + itemlen += subread; + } + + mi->next = NULL; + *pp = mi; + pp = &mi->next; + + data += itemlen; + length -= itemlen; + *read += itemlen; + + if ((flags & MENUITEM_ENDMENU) != 0) + return first; + } + + return first; +} + +/* Convert menuex items from binary. */ + +static struct menuitem * +bin_to_res_menuexitems (data, length, big_endian, read) + const unsigned char *data; + unsigned long length; + int big_endian; + int *read; +{ + struct menuitem *first, **pp; + + first = NULL; + pp = &first; + + *read = 0; + + while (length > 0) + { + int flags, slen; + unsigned int itemlen; + struct menuitem *mi; + + if (length < 14) + toosmall (_("menuitem header")); + + mi = (struct menuitem *) res_alloc (sizeof *mi); + mi->type = get_32 (big_endian, data); + mi->state = get_32 (big_endian, data + 4); + mi->id = get_16 (big_endian, data + 8); + + flags = get_16 (big_endian, data + 10); + + if (get_16 (big_endian, data + 12) == 0) + { + slen = 0; + mi->text = NULL; + } + else + mi->text = get_unicode (data + 12, length - 12, big_endian, &slen); + + itemlen = 12 + slen * 2 + 2; + itemlen = (itemlen + 3) &~ 3; + + if ((flags & 1) == 0) + { + mi->popup = NULL; + mi->help = 0; + } + else + { + int subread; + + if (length < itemlen + 4) + toosmall (_("menuitem")); + mi->help = get_32 (big_endian, data + itemlen); + itemlen += 4; + + mi->popup = bin_to_res_menuexitems (data + itemlen, + length - itemlen, + big_endian, &subread); + itemlen += subread; + } + + mi->next = NULL; + *pp = mi; + pp = &mi->next; + + data += itemlen; + length -= itemlen; + *read += itemlen; + + if ((flags & 0x80) != 0) + return first; + } + + return first; +} + +/* Convert a dialog resource from binary. */ + +static struct res_resource * +bin_to_res_dialog (data, length, big_endian) + const unsigned char *data; + unsigned long length; + int big_endian; +{ + int version; + struct dialog *d; + int c, sublen, i; + unsigned int off; + struct dialog_control **pp; + struct res_resource *r; + + if (length < 18) + toosmall (_("dialog header")); + + d = (struct dialog *) res_alloc (sizeof *d); + + version = get_16 (big_endian, data); + if (version != 1) + { + d->ex = NULL; + d->style = get_32 (big_endian, data); + d->exstyle = get_32 (big_endian, data + 4); + off = 8; + } + else + { + int signature; + + signature = get_16 (big_endian, data + 2); + if (signature != 0xffff) + fatal (_("unexpected dialog signature %d"), signature); + + d->ex = (struct dialog_ex *) res_alloc (sizeof (struct dialog_ex)); + d->ex->help = get_32 (big_endian, data + 4); + d->exstyle = get_32 (big_endian, data + 8); + d->style = get_32 (big_endian, data + 12); + off = 16; + } + + if (length < off + 10) + toosmall (_("dialog header")); + + c = get_16 (big_endian, data + off); + d->x = get_16 (big_endian, data + off + 2); + d->y = get_16 (big_endian, data + off + 4); + d->width = get_16 (big_endian, data + off + 6); + d->height = get_16 (big_endian, data + off + 8); + + off += 10; + + sublen = get_resid (&d->menu, data + off, length - off, big_endian); + off += sublen; + + sublen = get_resid (&d->class, data + off, length - off, big_endian); + off += sublen; + + d->caption = get_unicode (data + off, length - off, big_endian, &sublen); + off += sublen * 2 + 2; + + if ((d->style & DS_SETFONT) == 0) + { + d->pointsize = 0; + d->font = NULL; + if (d->ex != NULL) + { + d->ex->weight = 0; + d->ex->italic = 0; + } + } + else + { + if (length < off + 2) + toosmall (_("dialog font point size")); + + d->pointsize = get_16 (big_endian, data + off); + off += 2; + + if (d->ex != NULL) + { + if (length < off + 4) + toosmall (_("dialogex font information")); + d->ex->weight = get_16 (big_endian, data + off); + d->ex->italic = get_16 (big_endian, data + off + 2); + off += 4; + } + + d->font = get_unicode (data + off, length - off, big_endian, &sublen); + off += sublen * 2 + 2; + } + + d->controls = NULL; + pp = &d->controls; + + for (i = 0; i < c; i++) + { + struct dialog_control *dc; + int datalen; + + off = (off + 3) &~ 3; + + dc = (struct dialog_control *) res_alloc (sizeof *dc); + + if (d->ex == NULL) + { + if (length < off + 8) + toosmall (_("dialog control")); + + dc->style = get_32 (big_endian, data + off); + dc->exstyle = get_32 (big_endian, data + off + 4); + dc->help = 0; + off += 8; + } + else + { + if (length < off + 12) + toosmall (_("dialogex control")); + dc->help = get_32 (big_endian, data + off); + dc->exstyle = get_32 (big_endian, data + off + 4); + dc->style = get_32 (big_endian, data + off + 8); + off += 12; + } + + if (length < off + 10) + toosmall (_("dialog control")); + + dc->x = get_16 (big_endian, data + off); + dc->y = get_16 (big_endian, data + off + 2); + dc->width = get_16 (big_endian, data + off + 4); + dc->height = get_16 (big_endian, data + off + 6); + + if (d->ex != NULL) + dc->id = get_32 (big_endian, data + off + 8); + else + dc->id = get_16 (big_endian, data + off + 8); + + off += 10 + (d->ex != NULL ? 2 : 0); + + sublen = get_resid (&dc->class, data + off, length - off, big_endian); + off += sublen; + + sublen = get_resid (&dc->text, data + off, length - off, big_endian); + off += sublen; + + if (length < off + 2) + toosmall (_("dialog control end")); + + datalen = get_16 (big_endian, data + off); + off += 2; + + if (datalen == 0) + dc->data = NULL; + else + { + off = (off + 3) &~ 3; + + if (length < off + datalen) + toosmall (_("dialog control data")); + + dc->data = ((struct rcdata_item *) + res_alloc (sizeof (struct rcdata_item))); + dc->data->next = NULL; + dc->data->type = RCDATA_BUFFER; + dc->data->u.buffer.length = datalen; + dc->data->u.buffer.data = data + off; + + off += datalen; + } + + dc->next = NULL; + *pp = dc; + pp = &dc->next; + } + + r = (struct res_resource *) res_alloc (sizeof *r); + r->type = RES_TYPE_DIALOG; + r->u.dialog = d; + + return r; +} + +/* Convert a stringtable resource from binary. */ + +static struct res_resource * +bin_to_res_string (data, length, big_endian) + const unsigned char *data; + unsigned long length; + int big_endian; +{ + struct stringtable *st; + int i; + struct res_resource *r; + + st = (struct stringtable *) res_alloc (sizeof *st); + + for (i = 0; i < 16; i++) + { + unsigned int slen; + + if (length < 2) + toosmall (_("stringtable string length")); + slen = get_16 (big_endian, data); + st->strings[i].length = slen; + + if (slen > 0) + { + unichar *s; + unsigned int j; + + if (length < 2 + 2 * slen) + toosmall (_("stringtable string")); + + s = (unichar *) res_alloc (slen * sizeof (unichar)); + st->strings[i].string = s; + + for (j = 0; j < slen; j++) + s[j] = get_16 (big_endian, data + 2 + j * 2); + } + + data += 2 + 2 * slen; + length -= 2 + 2 * slen; + } + + r = (struct res_resource *) res_alloc (sizeof *r); + r->type = RES_TYPE_STRINGTABLE; + r->u.stringtable = st; + + return r; +} + +/* Convert a fontdir resource from binary. */ + +static struct res_resource * +bin_to_res_fontdir (data, length, big_endian) + const unsigned char *data; + unsigned long length; + int big_endian; +{ + int c, i; + struct fontdir *first, **pp; + struct res_resource *r; + + if (length < 2) + toosmall (_("fontdir header")); + + c = get_16 (big_endian, data); + + first = NULL; + pp = &first; + + for (i = 0; i < c; i++) + { + struct fontdir *fd; + unsigned int off; + + if (length < 56) + toosmall (_("fontdir")); + + fd = (struct fontdir *) res_alloc (sizeof *fd); + fd->index = get_16 (big_endian, data); + + /* To work out the length of the fontdir data, we must get the + length of the device name and face name strings, even though + we don't store them in the fontdir structure. The + documentation says that these are NULL terminated char + strings, not Unicode strings. */ + + off = 56; + + while (off < length && data[off] != '\0') + ++off; + if (off >= length) + toosmall (_("fontdir device name")); + ++off; + + while (off < length && data[off] != '\0') + ++off; + if (off >= length) + toosmall (_("fontdir face name")); + ++off; + + fd->length = off; + fd->data = data; + + fd->next = NULL; + *pp = fd; + pp = &fd->next; + + /* The documentation does not indicate that any rounding is + required. */ + + data += off; + length -= off; + } + + r = (struct res_resource *) res_alloc (sizeof *r); + r->type = RES_TYPE_FONTDIR; + r->u.fontdir = first; + + return r; +} + +/* Convert an accelerators resource from binary. */ + +static struct res_resource * +bin_to_res_accelerators (data, length, big_endian) + const unsigned char *data; + unsigned long length; + int big_endian; +{ + struct accelerator *first, **pp; + struct res_resource *r; + + first = NULL; + pp = &first; + + while (1) + { + struct accelerator *a; + + if (length < 8) + toosmall (_("accelerator")); + + a = (struct accelerator *) res_alloc (sizeof *a); + + a->flags = get_16 (big_endian, data); + a->key = get_16 (big_endian, data + 2); + a->id = get_16 (big_endian, data + 4); + + a->next = NULL; + *pp = a; + pp = &a->next; + + if ((a->flags & ACC_LAST) != 0) + break; + + data += 8; + length -= 8; + } + + r = (struct res_resource *) res_alloc (sizeof *r); + r->type = RES_TYPE_ACCELERATOR; + r->u.acc = first; + + return r; +} + +/* Convert an rcdata resource from binary. */ + +static struct res_resource * +bin_to_res_rcdata (data, length, big_endian) + const unsigned char *data; + unsigned long length; + int big_endian; +{ + struct rcdata_item *ri; + struct res_resource *r; + + ri = (struct rcdata_item *) res_alloc (sizeof *ri); + + ri->next = NULL; + ri->type = RCDATA_BUFFER; + ri->u.buffer.length = length; + ri->u.buffer.data = data; + + r = (struct res_resource *) res_alloc (sizeof *r); + r->type = RES_TYPE_RCDATA; + r->u.rcdata = ri; + + return r; +} + +/* Convert a group cursor resource from binary. */ + +static struct res_resource * +bin_to_res_group_cursor (data, length, big_endian) + const unsigned char *data; + unsigned long length; + int big_endian; +{ + int type, c, i; + struct group_cursor *first, **pp; + struct res_resource *r; + + if (length < 6) + toosmall (_("group cursor header")); + + type = get_16 (big_endian, data + 2); + if (type != 2) + fatal (_("unexpected group cursor type %d"), type); + + c = get_16 (big_endian, data + 4); + + data += 6; + length -= 6; + + first = NULL; + pp = &first; + + for (i = 0; i < c; i++) + { + struct group_cursor *gc; + + if (length < 14) + toosmall (_("group cursor")); + + gc = (struct group_cursor *) res_alloc (sizeof *gc); + + gc->width = get_16 (big_endian, data); + gc->height = get_16 (big_endian, data + 2); + gc->planes = get_16 (big_endian, data + 4); + gc->bits = get_16 (big_endian, data + 6); + gc->bytes = get_32 (big_endian, data + 8); + gc->index = get_16 (big_endian, data + 12); + + gc->next = NULL; + *pp = gc; + pp = &gc->next; + + data += 14; + length -= 14; + } + + r = (struct res_resource *) res_alloc (sizeof *r); + r->type = RES_TYPE_GROUP_CURSOR; + r->u.group_cursor = first; + + return r; +} + +/* Convert a group icon resource from binary. */ + +static struct res_resource * +bin_to_res_group_icon (data, length, big_endian) + const unsigned char *data; + unsigned long length; + int big_endian; +{ + int type, c, i; + struct group_icon *first, **pp; + struct res_resource *r; + + if (length < 6) + toosmall (_("group icon header")); + + type = get_16 (big_endian, data + 2); + if (type != 1) + fatal (_("unexpected group icon type %d"), type); + + c = get_16 (big_endian, data + 4); + + data += 6; + length -= 6; + + first = NULL; + pp = &first; + + for (i = 0; i < c; i++) + { + struct group_icon *gi; + + if (length < 14) + toosmall (_("group icon")); + + gi = (struct group_icon *) res_alloc (sizeof *gi); + + gi->width = data[0]; + gi->height = data[1]; + gi->colors = data[2]; + gi->planes = get_16 (big_endian, data + 4); + gi->bits = get_16 (big_endian, data + 6); + gi->bytes = get_32 (big_endian, data + 8); + gi->index = get_16 (big_endian, data + 12); + + gi->next = NULL; + *pp = gi; + pp = &gi->next; + + data += 14; + length -= 14; + } + + r = (struct res_resource *) res_alloc (sizeof *r); + r->type = RES_TYPE_GROUP_ICON; + r->u.group_icon = first; + + return r; +} + +/* Extract data from a version header. If KEY is not NULL, then the + key must be KEY; otherwise, the key is returned in *PKEY. This + sets *LEN to the total length, *VALLEN to the value length, *TYPE + to the type, and *OFF to the offset to the children. */ + +static void +get_version_header (data, length, big_endian, key, pkey, len, vallen, type, + off) + const unsigned char *data; + unsigned long length; + int big_endian; + const char *key; + unichar **pkey; + int *len; + int *vallen; + int *type; + int *off; +{ + if (length < 8) + toosmall (key); + + *len = get_16 (big_endian, data); + *vallen = get_16 (big_endian, data + 2); + *type = get_16 (big_endian, data + 4); + + *off = 6; + + length -= 6; + data += 6; + + if (key == NULL) + { + int sublen; + + *pkey = get_unicode (data, length, big_endian, &sublen); + *off += sublen * 2 + 2; + } + else + { + while (1) + { + if (length < 2) + toosmall (key); + if (get_16 (big_endian, data) != (unsigned char) *key) + fatal (_("unexpected version string")); + + *off += 2; + length -= 2; + data += 2; + + if (*key == '\0') + break; + + ++key; + } + } + + *off = (*off + 3) &~ 3; +} + +/* Convert a version resource from binary. */ + +static struct res_resource * +bin_to_res_version (data, length, big_endian) + const unsigned char *data; + unsigned long length; + int big_endian; +{ + int verlen, vallen, type, off; + struct fixed_versioninfo *fi; + struct ver_info *first, **pp; + struct versioninfo *v; + struct res_resource *r; + + get_version_header (data, length, big_endian, "VS_VERSION_INFO", + (unichar *) NULL, &verlen, &vallen, &type, &off); + + if ((unsigned int) verlen != length) + fatal (_("version length %d does not match resource length %lu"), + verlen, length); + + if (type != 0) + fatal (_("unexpected version type %d"), type); + + data += off; + length -= off; + + if (vallen == 0) + fi = NULL; + else + { + unsigned long signature, fiv; + + if (vallen != 52) + fatal (_("unexpected fixed version information length %d"), vallen); + + if (length < 52) + toosmall (_("fixed version info")); + + signature = get_32 (big_endian, data); + if (signature != 0xfeef04bd) + fatal (_("unexpected fixed version signature %lu"), signature); + + fiv = get_32 (big_endian, data + 4); + if (fiv != 0 && fiv != 0x10000) + fatal (_("unexpected fixed version info version %lu"), fiv); + + fi = (struct fixed_versioninfo *) res_alloc (sizeof *fi); + + fi->file_version_ms = get_32 (big_endian, data + 8); + fi->file_version_ls = get_32 (big_endian, data + 12); + fi->product_version_ms = get_32 (big_endian, data + 16); + fi->product_version_ls = get_32 (big_endian, data + 20); + fi->file_flags_mask = get_32 (big_endian, data + 24); + fi->file_flags = get_32 (big_endian, data + 28); + fi->file_os = get_32 (big_endian, data + 32); + fi->file_type = get_32 (big_endian, data + 36); + fi->file_subtype = get_32 (big_endian, data + 40); + fi->file_date_ms = get_32 (big_endian, data + 44); + fi->file_date_ls = get_32 (big_endian, data + 48); + + data += 52; + length -= 52; + } + + first = NULL; + pp = &first; + + while (length > 0) + { + struct ver_info *vi; + int ch; + + if (length < 8) + toosmall (_("version var info")); + + vi = (struct ver_info *) res_alloc (sizeof *vi); + + ch = get_16 (big_endian, data + 6); + + if (ch == 'S') + { + struct ver_stringinfo **ppvs; + + vi->type = VERINFO_STRING; + + get_version_header (data, length, big_endian, "StringFileInfo", + (unichar *) NULL, &verlen, &vallen, &type, + &off); + + if (vallen != 0) + fatal (_("unexpected stringfileinfo value length %d"), vallen); + + data += off; + length -= off; + + get_version_header (data, length, big_endian, (const char *) NULL, + &vi->u.string.language, &verlen, &vallen, + &type, &off); + + if (vallen != 0) + fatal (_("unexpected version stringtable value length %d"), vallen); + + data += off; + length -= off; + verlen -= off; + + vi->u.string.strings = NULL; + ppvs = &vi->u.string.strings; + + /* It's convenient to round verlen to a 4 byte alignment, + since we round the subvariables in the loop. */ + verlen = (verlen + 3) &~ 3; + + while (verlen > 0) + { + struct ver_stringinfo *vs; + int subverlen, vslen, valoff; + + vs = (struct ver_stringinfo *) res_alloc (sizeof *vs); + + get_version_header (data, length, big_endian, + (const char *) NULL, &vs->key, &subverlen, + &vallen, &type, &off); + + subverlen = (subverlen + 3) &~ 3; + + data += off; + length -= off; + + vs->value = get_unicode (data, length, big_endian, &vslen); + valoff = vslen * 2 + 2; + valoff = (valoff + 3) &~ 3; + + if (off + valoff != subverlen) + fatal (_("unexpected version string length %d != %d + %d"), + subverlen, off, valoff); + + vs->next = NULL; + *ppvs = vs; + ppvs = &vs->next; + + data += valoff; + length -= valoff; + + if (verlen < subverlen) + fatal (_("unexpected version string length %d < %d"), + verlen, subverlen); + + verlen -= subverlen; + } + } + else if (ch == 'V') + { + struct ver_varinfo **ppvv; + + vi->type = VERINFO_VAR; + + get_version_header (data, length, big_endian, "VarFileInfo", + (unichar *) NULL, &verlen, &vallen, &type, + &off); + + if (vallen != 0) + fatal (_("unexpected varfileinfo value length %d"), vallen); + + data += off; + length -= off; + + get_version_header (data, length, big_endian, (const char *) NULL, + &vi->u.var.key, &verlen, &vallen, &type, &off); + + data += off; + length -= off; + + vi->u.var.var = NULL; + ppvv = &vi->u.var.var; + + while (vallen > 0) + { + struct ver_varinfo *vv; + + if (length < 4) + toosmall (_("version varfileinfo")); + + vv = (struct ver_varinfo *) res_alloc (sizeof *vv); + + vv->language = get_16 (big_endian, data); + vv->charset = get_16 (big_endian, data + 2); + + vv->next = NULL; + *ppvv = vv; + ppvv = &vv->next; + + data += 4; + length -= 4; + + if (vallen < 4) + fatal (_("unexpected version value length %d"), vallen); + + vallen -= 4; + } + } + else + fatal (_("unexpected version string")); + + vi->next = NULL; + *pp = vi; + pp = &vi->next; + } + + v = (struct versioninfo *) res_alloc (sizeof *v); + v->fixed = fi; + v->var = first; + + r = (struct res_resource *) res_alloc (sizeof *r); + r->type = RES_TYPE_VERSIONINFO; + r->u.versioninfo = v; + + return r; +} + +/* Convert an arbitrary user defined resource from binary. */ + +static struct res_resource * +bin_to_res_userdata (data, length, big_endian) + const unsigned char *data; + unsigned long length; + int big_endian; +{ + struct rcdata_item *ri; + struct res_resource *r; + + ri = (struct rcdata_item *) res_alloc (sizeof *ri); + + ri->next = NULL; + ri->type = RCDATA_BUFFER; + ri->u.buffer.length = length; + ri->u.buffer.data = data; + + r = (struct res_resource *) res_alloc (sizeof *r); + r->type = RES_TYPE_USERDATA; + r->u.rcdata = ri; + + return r; +} + +/* Macros to swap out values. */ + +#define put_16(be, v, s) ((be) ? bfd_putb16 ((v), (s)) : bfd_putl16 ((v), (s))) +#define put_32(be, v, s) ((be) ? bfd_putb32 ((v), (s)) : bfd_putl32 ((v), (s))) + +/* Local functions used to convert resources to binary format. */ + +static void dword_align_bin PARAMS ((struct bindata ***, unsigned long *)); +static struct bindata *resid_to_bin PARAMS ((struct res_id, int)); +static struct bindata *unicode_to_bin PARAMS ((const unichar *, int)); +static struct bindata *res_to_bin_accelerator + PARAMS ((const struct accelerator *, int)); +static struct bindata *res_to_bin_cursor + PARAMS ((const struct cursor *, int)); +static struct bindata *res_to_bin_group_cursor + PARAMS ((const struct group_cursor *, int)); +static struct bindata *res_to_bin_dialog + PARAMS ((const struct dialog *, int)); +static struct bindata *res_to_bin_fontdir + PARAMS ((const struct fontdir *, int)); +static struct bindata *res_to_bin_group_icon + PARAMS ((const struct group_icon *, int)); +static struct bindata *res_to_bin_menu + PARAMS ((const struct menu *, int)); +static struct bindata *res_to_bin_menuitems + PARAMS ((const struct menuitem *, int)); +static struct bindata *res_to_bin_menuexitems + PARAMS ((const struct menuitem *, int)); +static struct bindata *res_to_bin_rcdata + PARAMS ((const struct rcdata_item *, int)); +static struct bindata *res_to_bin_stringtable + PARAMS ((const struct stringtable *, int)); +static struct bindata *string_to_unicode_bin PARAMS ((const char *, int)); +static struct bindata *res_to_bin_versioninfo + PARAMS ((const struct versioninfo *, int)); +static struct bindata *res_to_bin_generic + PARAMS ((unsigned long, const unsigned char *)); + +/* Convert a resource to binary. */ + +struct bindata * +res_to_bin (res, big_endian) + const struct res_resource *res; + int big_endian; +{ + switch (res->type) + { + default: + abort (); + case RES_TYPE_BITMAP: + case RES_TYPE_FONT: + case RES_TYPE_ICON: + case RES_TYPE_MESSAGETABLE: + return res_to_bin_generic (res->u.data.length, res->u.data.data); + case RES_TYPE_ACCELERATOR: + return res_to_bin_accelerator (res->u.acc, big_endian); + case RES_TYPE_CURSOR: + return res_to_bin_cursor (res->u.cursor, big_endian); + case RES_TYPE_GROUP_CURSOR: + return res_to_bin_group_cursor (res->u.group_cursor, big_endian); + case RES_TYPE_DIALOG: + return res_to_bin_dialog (res->u.dialog, big_endian); + case RES_TYPE_FONTDIR: + return res_to_bin_fontdir (res->u.fontdir, big_endian); + case RES_TYPE_GROUP_ICON: + return res_to_bin_group_icon (res->u.group_icon, big_endian); + case RES_TYPE_MENU: + return res_to_bin_menu (res->u.menu, big_endian); + case RES_TYPE_RCDATA: + return res_to_bin_rcdata (res->u.rcdata, big_endian); + case RES_TYPE_STRINGTABLE: + return res_to_bin_stringtable (res->u.stringtable, big_endian); + case RES_TYPE_USERDATA: + return res_to_bin_rcdata (res->u.rcdata, big_endian); + case RES_TYPE_VERSIONINFO: + return res_to_bin_versioninfo (res->u.versioninfo, big_endian); + } +} + +/* Align to a 32 bit boundary. PPP points to the of a list of bindata + structures. LENGTH points to the length of the structures. If + necessary, this adds a new bindata to bring length up to a 32 bit + boundary. It updates *PPP and *LENGTH. */ + +static void +dword_align_bin (ppp, length) + struct bindata ***ppp; + unsigned long *length; +{ + int add; + struct bindata *d; + + if ((*length & 3) == 0) + return; + + add = 4 - (*length & 3); + + d = (struct bindata *) reswr_alloc (sizeof *d); + d->length = add; + d->data = (unsigned char *) reswr_alloc (add); + memset (d->data, 0, add); + + d->next = NULL; + **ppp = d; + *ppp = &(**ppp)->next; + + *length += add; +} + +/* Convert a resource ID to binary. This always returns exactly one + bindata structure. */ + +static struct bindata * +resid_to_bin (id, big_endian) + struct res_id id; + int big_endian; +{ + struct bindata *d; + + d = (struct bindata *) reswr_alloc (sizeof *d); + + if (! id.named) + { + d->length = 4; + d->data = (unsigned char *) reswr_alloc (4); + put_16 (big_endian, 0xffff, d->data); + put_16 (big_endian, id.u.id, d->data + 2); + } + else + { + int i; + + d->length = id.u.n.length * 2 + 2; + d->data = (unsigned char *) reswr_alloc (d->length); + for (i = 0; i < id.u.n.length; i++) + put_16 (big_endian, id.u.n.name[i], d->data + i * 2); + put_16 (big_endian, 0, d->data + i * 2); + } + + d->next = NULL; + + return d; +} + +/* Convert a null terminated unicode string to binary. This always + returns exactly one bindata structure. */ + +static struct bindata * +unicode_to_bin (str, big_endian) + const unichar *str; + int big_endian; +{ + int len; + struct bindata *d; + + len = 0; + if (str != NULL) + { + const unichar *s; + + for (s = str; *s != 0; s++) + ++len; + } + + d = (struct bindata *) reswr_alloc (sizeof *d); + d->length = len * 2 + 2; + d->data = (unsigned char *) reswr_alloc (d->length); + + if (str == NULL) + put_16 (big_endian, 0, d->data); + else + { + const unichar *s; + int i; + + for (s = str, i = 0; *s != 0; s++, i++) + put_16 (big_endian, *s, d->data + i * 2); + put_16 (big_endian, 0, d->data + i * 2); + } + + d->next = NULL; + + return d; +} + +/* Convert an accelerator resource to binary. */ + +static struct bindata * +res_to_bin_accelerator (accelerators, big_endian) + const struct accelerator *accelerators; + int big_endian; +{ + struct bindata *first, **pp; + const struct accelerator *a; + + first = NULL; + pp = &first; + + for (a = accelerators; a != NULL; a = a->next) + { + struct bindata *d; + + d = (struct bindata *) reswr_alloc (sizeof *d); + d->length = 8; + d->data = (unsigned char *) reswr_alloc (8); + + put_16 (big_endian, + a->flags | (a->next != NULL ? 0 : ACC_LAST), + d->data); + put_16 (big_endian, a->key, d->data + 2); + put_16 (big_endian, a->id, d->data + 4); + put_16 (big_endian, 0, d->data + 8); + + d->next = NULL; + *pp = d; + pp = &d->next; + } + + return first; +} + +/* Convert a cursor resource to binary. */ + +static struct bindata * +res_to_bin_cursor (c, big_endian) + const struct cursor *c; + int big_endian; +{ + struct bindata *d; + + d = (struct bindata *) reswr_alloc (sizeof *d); + d->length = 4; + d->data = (unsigned char *) reswr_alloc (4); + + put_16 (big_endian, c->xhotspot, d->data); + put_16 (big_endian, c->yhotspot, d->data + 2); + + d->next = (struct bindata *) reswr_alloc (sizeof *d); + d->next->length = c->length; + d->next->data = (unsigned char *) c->data; + d->next->next = NULL; + + return d; +} + +/* Convert a group cursor resource to binary. */ + +static struct bindata * +res_to_bin_group_cursor (group_cursors, big_endian) + const struct group_cursor *group_cursors; + int big_endian; +{ + struct bindata *first, **pp; + int c; + const struct group_cursor *gc; + + first = (struct bindata *) reswr_alloc (sizeof *first); + first->length = 6; + first->data = (unsigned char *) reswr_alloc (6); + + put_16 (big_endian, 0, first->data); + put_16 (big_endian, 2, first->data + 2); + + first->next = NULL; + pp = &first->next; + + c = 0; + for (gc = group_cursors; gc != NULL; gc = gc->next) + { + struct bindata *d; + + ++c; + + d = (struct bindata *) reswr_alloc (sizeof *d); + d->length = 14; + d->data = (unsigned char *) reswr_alloc (14); + + put_16 (big_endian, gc->width, d->data); + put_16 (big_endian, gc->height, d->data + 2); + put_16 (big_endian, gc->planes, d->data + 4); + put_16 (big_endian, gc->bits, d->data + 6); + put_32 (big_endian, gc->bytes, d->data + 8); + put_16 (big_endian, gc->index, d->data + 12); + + d->next = NULL; + *pp = d; + pp = &d->next; + } + + put_16 (big_endian, c, first->data + 4); + + return first; +} + +/* Convert a dialog resource to binary. */ + +static struct bindata * +res_to_bin_dialog (dialog, big_endian) + const struct dialog *dialog; + int big_endian; +{ + int dialogex; + struct bindata *first, **pp; + unsigned long length; + int off, c; + struct dialog_control *dc; + + dialogex = extended_dialog (dialog); + + first = (struct bindata *) reswr_alloc (sizeof *first); + first->length = dialogex ? 26 : 18; + first->data = (unsigned char *) reswr_alloc (first->length); + + length = first->length; + + if (! dialogex) + { + put_32 (big_endian, dialog->style, first->data); + put_32 (big_endian, dialog->exstyle, first->data + 4); + off = 8; + } + else + { + put_16 (big_endian, 1, first->data); + put_16 (big_endian, 0xffff, first->data + 2); + + if (dialog->ex == NULL) + put_32 (big_endian, 0, first->data + 4); + else + put_32 (big_endian, dialog->ex->help, first->data + 4); + put_32 (big_endian, dialog->exstyle, first->data + 8); + put_32 (big_endian, dialog->style, first->data + 12); + off = 16; + } + + put_16 (big_endian, dialog->x, first->data + off + 2); + put_16 (big_endian, dialog->y, first->data + off + 4); + put_16 (big_endian, dialog->width, first->data + off + 6); + put_16 (big_endian, dialog->height, first->data + off + 8); + + pp = &first->next; + + *pp = resid_to_bin (dialog->menu, big_endian); + length += (*pp)->length; + pp = &(*pp)->next; + + *pp = resid_to_bin (dialog->class, big_endian); + length += (*pp)->length; + pp = &(*pp)->next; + + *pp = unicode_to_bin (dialog->caption, big_endian); + length += (*pp)->length; + pp = &(*pp)->next; + + if ((dialog->style & DS_SETFONT) != 0) + { + struct bindata *d; + + d = (struct bindata *) reswr_alloc (sizeof *d); + d->length = dialogex ? 6 : 2; + d->data = (unsigned char *) reswr_alloc (d->length); + + length += d->length; + + put_16 (big_endian, dialog->pointsize, d->data); + + if (dialogex) + { + if (dialog->ex == NULL) + { + put_16 (big_endian, 0, d->data + 2); + put_16 (big_endian, 0, d->data + 4); + } + else + { + put_16 (big_endian, dialog->ex->weight, d->data + 2); + put_16 (big_endian, dialog->ex->italic, d->data + 4); + } + } + + *pp = d; + pp = &d->next; + + *pp = unicode_to_bin (dialog->font, big_endian); + length += (*pp)->length; + pp = &(*pp)->next; + } + + c = 0; + for (dc = dialog->controls; dc != NULL; dc = dc->next) + { + struct bindata *d; + int dcoff; + + ++c; + + dword_align_bin (&pp, &length); + + d = (struct bindata *) reswr_alloc (sizeof *d); + d->length = dialogex ? 24 : 18; + d->data = (unsigned char *) reswr_alloc (d->length); + + length += d->length; + + if (! dialogex) + { + put_32 (big_endian, dc->style, d->data); + put_32 (big_endian, dc->exstyle, d->data + 4); + dcoff = 8; + } + else + { + put_32 (big_endian, dc->help, d->data); + put_32 (big_endian, dc->exstyle, d->data + 4); + put_32 (big_endian, dc->style, d->data + 8); + dcoff = 12; + } + + put_16 (big_endian, dc->x, d->data + dcoff); + put_16 (big_endian, dc->y, d->data + dcoff + 2); + put_16 (big_endian, dc->width, d->data + dcoff + 4); + put_16 (big_endian, dc->height, d->data + dcoff + 6); + + if (dialogex) + put_32 (big_endian, dc->id, d->data + dcoff + 8); + else + put_16 (big_endian, dc->id, d->data + dcoff + 8); + + *pp = d; + pp = &d->next; + + *pp = resid_to_bin (dc->class, big_endian); + length += (*pp)->length; + pp = &(*pp)->next; + + *pp = resid_to_bin (dc->text, big_endian); + length += (*pp)->length; + pp = &(*pp)->next; + + d = (struct bindata *) reswr_alloc (sizeof *d); + d->length = 2; + d->data = (unsigned char *) reswr_alloc (2); + + length += 2; + + d->next = NULL; + *pp = d; + pp = &d->next; + + if (dc->data == NULL) + put_16 (big_endian, 0, d->data); + else + { + unsigned long sublen; + + dword_align_bin (&pp, &length); + + *pp = res_to_bin_rcdata (dc->data, big_endian); + sublen = 0; + while (*pp != NULL) + { + sublen += (*pp)->length; + pp = &(*pp)->next; + } + + put_16 (big_endian, sublen, d->data); + + length += sublen; + } + } + put_16 (big_endian, c, first->data + off); + + return first; +} + +/* Convert a fontdir resource to binary. */ + +static struct bindata * +res_to_bin_fontdir (fontdirs, big_endian) + const struct fontdir *fontdirs; + int big_endian; +{ + struct bindata *first, **pp; + int c; + const struct fontdir *fd; + + first = (struct bindata *) reswr_alloc (sizeof *first); + first->length = 2; + first->data = (unsigned char *) reswr_alloc (2); + + first->next = NULL; + pp = &first->next; + + c = 0; + for (fd = fontdirs; fd != NULL; fd = fd->next) + { + struct bindata *d; + + ++c; + + d = (struct bindata *) reswr_alloc (sizeof *d); + d->length = 2; + d->data = (unsigned char *) reswr_alloc (2); + + put_16 (big_endian, fd->index, d->data); + + *pp = d; + pp = &d->next; + + d = (struct bindata *) reswr_alloc (sizeof *d); + d->length = fd->length; + d->data = (unsigned char *) fd->data; + + d->next = NULL; + *pp = d; + pp = &d->next; + } + + put_16 (big_endian, c, first->data); + + return first; +} + +/* Convert a group icon resource to binary. */ + +static struct bindata * +res_to_bin_group_icon (group_icons, big_endian) + const struct group_icon *group_icons; + int big_endian; +{ + struct bindata *first, **pp; + int c; + const struct group_icon *gi; + + first = (struct bindata *) reswr_alloc (sizeof *first); + first->length = 6; + first->data = (unsigned char *) reswr_alloc (6); + + put_16 (big_endian, 0, first->data); + put_16 (big_endian, 1, first->data + 2); + + first->next = NULL; + pp = &first->next; + + c = 0; + for (gi = group_icons; gi != NULL; gi = gi->next) + { + struct bindata *d; + + ++c; + + d = (struct bindata *) reswr_alloc (sizeof *d); + d->length = 14; + d->data = (unsigned char *) reswr_alloc (14); + + d->data[0] = gi->width; + d->data[1] = gi->height; + d->data[2] = gi->colors; + d->data[3] = 0; + put_16 (big_endian, gi->planes, d->data + 4); + put_16 (big_endian, gi->bits, d->data + 6); + put_32 (big_endian, gi->bytes, d->data + 8); + put_16 (big_endian, gi->index, d->data + 12); + + d->next = NULL; + *pp = d; + pp = &d->next; + } + + put_16 (big_endian, c, first->data + 4); + + return first; +} + +/* Convert a menu resource to binary. */ + +static struct bindata * +res_to_bin_menu (menu, big_endian) + const struct menu *menu; + int big_endian; +{ + int menuex; + struct bindata *d; + + menuex = extended_menu (menu); + + d = (struct bindata *) reswr_alloc (sizeof *d); + d->length = menuex ? 8 : 4; + d->data = (unsigned char *) reswr_alloc (d->length); + + if (! menuex) + { + put_16 (big_endian, 0, d->data); + put_16 (big_endian, 0, d->data + 2); + + d->next = res_to_bin_menuitems (menu->items, big_endian); + } + else + { + put_16 (big_endian, 1, d->data); + put_16 (big_endian, 4, d->data + 2); + put_32 (big_endian, menu->help, d->data + 4); + + d->next = res_to_bin_menuexitems (menu->items, big_endian); + } + + return d; +} + +/* Convert menu items to binary. */ + +static struct bindata * +res_to_bin_menuitems (items, big_endian) + const struct menuitem *items; + int big_endian; +{ + struct bindata *first, **pp; + const struct menuitem *mi; + + first = NULL; + pp = &first; + + for (mi = items; mi != NULL; mi = mi->next) + { + struct bindata *d; + int flags; + + d = (struct bindata *) reswr_alloc (sizeof *d); + d->length = mi->popup == NULL ? 4 : 2; + d->data = (unsigned char *) reswr_alloc (d->length); + + flags = mi->type; + if (mi->next == NULL) + flags |= MENUITEM_ENDMENU; + if (mi->popup != NULL) + flags |= MENUITEM_POPUP; + + put_16 (big_endian, flags, d->data); + + if (mi->popup == NULL) + put_16 (big_endian, mi->id, d->data + 2); + + *pp = d; + pp = &d->next; + + *pp = unicode_to_bin (mi->text, big_endian); + pp = &(*pp)->next; + + if (mi->popup != NULL) + { + *pp = res_to_bin_menuitems (mi->popup, big_endian); + while (*pp != NULL) + pp = &(*pp)->next; + } + } + + return first; +} + +/* Convert menuex items to binary. */ + +static struct bindata * +res_to_bin_menuexitems (items, big_endian) + const struct menuitem *items; + int big_endian; +{ + struct bindata *first, **pp; + unsigned long length; + const struct menuitem *mi; + + first = NULL; + pp = &first; + + length = 0; + + for (mi = items; mi != NULL; mi = mi->next) + { + struct bindata *d; + int flags; + + dword_align_bin (&pp, &length); + + d = (struct bindata *) reswr_alloc (sizeof *d); + d->length = 12; + d->data = (unsigned char *) reswr_alloc (12); + + length += 12; + + put_32 (big_endian, mi->type, d->data); + put_32 (big_endian, mi->state, d->data + 4); + put_16 (big_endian, mi->id, d->data + 8); + + flags = 0; + if (mi->next == NULL) + flags |= 0x80; + if (mi->popup != NULL) + flags |= 1; + put_16 (big_endian, flags, d->data + 10); + + *pp = d; + pp = &d->next; + + *pp = unicode_to_bin (mi->text, big_endian); + length += (*pp)->length; + pp = &(*pp)->next; + + if (mi->popup != NULL) + { + dword_align_bin (&pp, &length); + + d = (struct bindata *) reswr_alloc (sizeof *d); + d->length = 4; + d->data = (unsigned char *) reswr_alloc (4); + + put_32 (big_endian, mi->help, d->data); + + *pp = d; + pp = &d->next; + + *pp = res_to_bin_menuexitems (mi->popup, big_endian); + while (*pp != NULL) + { + length += (*pp)->length; + pp = &(*pp)->next; + } + } + } + + return first; +} + +/* Convert an rcdata resource to binary. This is also used to convert + other information which happens to be stored in rcdata_item lists + to binary. */ + +static struct bindata * +res_to_bin_rcdata (items, big_endian) + const struct rcdata_item *items; + int big_endian; +{ + struct bindata *first, **pp; + const struct rcdata_item *ri; + + first = NULL; + pp = &first; + + for (ri = items; ri != NULL; ri = ri->next) + { + struct bindata *d; + + d = (struct bindata *) reswr_alloc (sizeof *d); + + switch (ri->type) + { + default: + abort (); + + case RCDATA_WORD: + d->length = 2; + d->data = (unsigned char *) reswr_alloc (2); + put_16 (big_endian, ri->u.word, d->data); + break; + + case RCDATA_DWORD: + d->length = 4; + d->data = (unsigned char *) reswr_alloc (4); + put_32 (big_endian, ri->u.dword, d->data); + break; + + case RCDATA_STRING: + d->length = ri->u.string.length; + d->data = (unsigned char *) ri->u.string.s; + break; + + case RCDATA_WSTRING: + { + unsigned long i; + + d->length = ri->u.wstring.length * 2; + d->data = (unsigned char *) reswr_alloc (d->length); + for (i = 0; i < ri->u.wstring.length; i++) + put_16 (big_endian, ri->u.wstring.w[i], d->data + i * 2); + break; + } + + case RCDATA_BUFFER: + d->length = ri->u.buffer.length; + d->data = (unsigned char *) ri->u.buffer.data; + break; + } + + d->next = NULL; + *pp = d; + pp = &d->next; + } + + return first; +} + +/* Convert a stringtable resource to binary. */ + +static struct bindata * +res_to_bin_stringtable (st, big_endian) + const struct stringtable *st; + int big_endian; +{ + struct bindata *first, **pp; + int i; + + first = NULL; + pp = &first; + + for (i = 0; i < 16; i++) + { + int slen, j; + struct bindata *d; + unichar *s; + + slen = st->strings[i].length; + s = st->strings[i].string; + + d = (struct bindata *) reswr_alloc (sizeof *d); + d->length = 2 + slen * 2; + d->data = (unsigned char *) reswr_alloc (d->length); + + put_16 (big_endian, slen, d->data); + + for (j = 0; j < slen; j++) + put_16 (big_endian, s[j], d->data + 2 + j * 2); + + d->next = NULL; + *pp = d; + pp = &d->next; + } + + return first; +} + +/* Convert an ASCII string to a unicode binary string. This always + returns exactly one bindata structure. */ + +static struct bindata * +string_to_unicode_bin (s, big_endian) + const char *s; + int big_endian; +{ + size_t len, i; + struct bindata *d; + + len = strlen (s); + + d = (struct bindata *) reswr_alloc (sizeof *d); + d->length = len * 2 + 2; + d->data = (unsigned char *) reswr_alloc (d->length); + + for (i = 0; i < len; i++) + put_16 (big_endian, s[i], d->data + i * 2); + put_16 (big_endian, 0, d->data + i * 2); + + d->next = NULL; + + return d; +} + +/* Convert a versioninfo resource to binary. */ + +static struct bindata * +res_to_bin_versioninfo (versioninfo, big_endian) + const struct versioninfo *versioninfo; + int big_endian; +{ + struct bindata *first, **pp; + unsigned long length; + struct ver_info *vi; + + first = (struct bindata *) reswr_alloc (sizeof *first); + first->length = 6; + first->data = (unsigned char *) reswr_alloc (6); + + length = 6; + + if (versioninfo->fixed == NULL) + put_16 (big_endian, 0, first->data + 2); + else + put_16 (big_endian, 52, first->data + 2); + + put_16 (big_endian, 0, first->data + 4); + + pp = &first->next; + + *pp = string_to_unicode_bin ("VS_VERSION_INFO", big_endian); + length += (*pp)->length; + pp = &(*pp)->next; + + dword_align_bin (&pp, &length); + + if (versioninfo->fixed != NULL) + { + const struct fixed_versioninfo *fi; + struct bindata *d; + + d = (struct bindata *) reswr_alloc (sizeof *d); + d->length = 52; + d->data = (unsigned char *) reswr_alloc (52); + + length += 52; + + fi = versioninfo->fixed; + + put_32 (big_endian, 0xfeef04bd, d->data); + put_32 (big_endian, 0x10000, d->data + 4); + put_32 (big_endian, fi->file_version_ms, d->data + 8); + put_32 (big_endian, fi->file_version_ls, d->data + 12); + put_32 (big_endian, fi->product_version_ms, d->data + 16); + put_32 (big_endian, fi->product_version_ls, d->data + 20); + put_32 (big_endian, fi->file_flags_mask, d->data + 24); + put_32 (big_endian, fi->file_flags, d->data + 28); + put_32 (big_endian, fi->file_os, d->data + 32); + put_32 (big_endian, fi->file_type, d->data + 36); + put_32 (big_endian, fi->file_subtype, d->data + 40); + put_32 (big_endian, fi->file_date_ms, d->data + 44); + put_32 (big_endian, fi->file_date_ls, d->data + 48); + + d->next = NULL; + *pp = d; + pp = &d->next; + } + + for (vi = versioninfo->var; vi != NULL; vi = vi->next) + { + struct bindata *vid; + unsigned long vilen; + + dword_align_bin (&pp, &length); + + vid = (struct bindata *) reswr_alloc (sizeof *vid); + vid->length = 6; + vid->data = (unsigned char *) reswr_alloc (6); + + length += 6; + vilen = 6; + + put_16 (big_endian, 0, vid->data + 2); + put_16 (big_endian, 0, vid->data + 4); + + *pp = vid; + pp = &vid->next; + + switch (vi->type) + { + default: + abort (); + + case VERINFO_STRING: + { + unsigned long hold, vslen; + struct bindata *vsd; + const struct ver_stringinfo *vs; + + *pp = string_to_unicode_bin ("StringFileInfo", big_endian); + length += (*pp)->length; + vilen += (*pp)->length; + pp = &(*pp)->next; + + hold = length; + dword_align_bin (&pp, &length); + vilen += length - hold; + + vsd = (struct bindata *) reswr_alloc (sizeof *vsd); + vsd->length = 6; + vsd->data = (unsigned char *) reswr_alloc (6); + + length += 6; + vilen += 6; + vslen = 6; + + put_16 (big_endian, 0, vsd->data + 2); + put_16 (big_endian, 0, vsd->data + 4); + + *pp = vsd; + pp = &vsd->next; + + *pp = unicode_to_bin (vi->u.string.language, big_endian); + length += (*pp)->length; + vilen += (*pp)->length; + vslen += (*pp)->length; + pp = &(*pp)->next; + + for (vs = vi->u.string.strings; vs != NULL; vs = vs->next) + { + struct bindata *vssd; + unsigned long vsslen; + + hold = length; + dword_align_bin (&pp, &length); + vilen += length - hold; + vslen += length - hold; + + vssd = (struct bindata *) reswr_alloc (sizeof *vssd); + vssd->length = 6; + vssd->data = (unsigned char *) reswr_alloc (6); + + length += 6; + vilen += 6; + vslen += 6; + vsslen = 6; + + put_16 (big_endian, 1, vssd->data + 4); + + *pp = vssd; + pp = &vssd->next; + + *pp = unicode_to_bin (vs->key, big_endian); + length += (*pp)->length; + vilen += (*pp)->length; + vslen += (*pp)->length; + vsslen += (*pp)->length; + pp = &(*pp)->next; + + hold = length; + dword_align_bin (&pp, &length); + vilen += length - hold; + vslen += length - hold; + vsslen += length - hold; + + *pp = unicode_to_bin (vs->value, big_endian); + put_16 (big_endian, (*pp)->length / 2, vssd->data + 2); + length += (*pp)->length; + vilen += (*pp)->length; + vslen += (*pp)->length; + vsslen += (*pp)->length; + pp = &(*pp)->next; + + put_16 (big_endian, vsslen, vssd->data); + } + + put_16 (big_endian, vslen, vsd->data); + + break; + } + + case VERINFO_VAR: + { + unsigned long hold, vvlen, vvvlen; + struct bindata *vvd; + const struct ver_varinfo *vv; + + *pp = string_to_unicode_bin ("VarFileInfo", big_endian); + length += (*pp)->length; + vilen += (*pp)->length; + pp = &(*pp)->next; + + hold = length; + dword_align_bin (&pp, &length); + vilen += length - hold; + + vvd = (struct bindata *) reswr_alloc (sizeof *vvd); + vvd->length = 6; + vvd->data = (unsigned char *) reswr_alloc (6); + + length += 6; + vilen += 6; + vvlen = 6; + + put_16 (big_endian, 0, vvd->data + 4); + + *pp = vvd; + pp = &vvd->next; + + *pp = unicode_to_bin (vi->u.var.key, big_endian); + length += (*pp)->length; + vilen += (*pp)->length; + vvlen += (*pp)->length; + pp = &(*pp)->next; + + hold = length; + dword_align_bin (&pp, &length); + vilen += length - hold; + vvlen += length - hold; + + vvvlen = 0; + + for (vv = vi->u.var.var; vv != NULL; vv = vv->next) + { + struct bindata *vvsd; + + vvsd = (struct bindata *) reswr_alloc (sizeof *vvsd); + vvsd->length = 4; + vvsd->data = (unsigned char *) reswr_alloc (4); + + length += 4; + vilen += 4; + vvlen += 4; + vvvlen += 4; + + put_16 (big_endian, vv->language, vvsd->data); + put_16 (big_endian, vv->charset, vvsd->data + 2); + + vvsd->next = NULL; + *pp = vvsd; + pp = &vvsd->next; + } + + put_16 (big_endian, vvlen, vvd->data); + put_16 (big_endian, vvvlen, vvd->data + 2); + + break; + } + } + + put_16 (big_endian, vilen, vid->data); + } + + put_16 (big_endian, length, first->data); + + return first; +} + +/* Convert a generic resource to binary. */ + +static struct bindata * +res_to_bin_generic (length, data) + unsigned long length; + const unsigned char *data; +{ + struct bindata *d; + + d = (struct bindata *) reswr_alloc (sizeof *d); + d->length = length; + d->data = (unsigned char *) data; + + d->next = NULL; + + return d; +} diff --git a/binutils/rescoff.c b/binutils/rescoff.c new file mode 100644 index 0000000..9a028c7 --- /dev/null +++ b/binutils/rescoff.c @@ -0,0 +1,776 @@ +/* rescoff.c -- read and write resources in Windows COFF files. + Copyright 1997, 1998 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Cygnus Support. + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* This file contains function that read and write Windows resources + in COFF files. */ + +#include "bfd.h" +#include "bucomm.h" +#include "libiberty.h" +#include "windres.h" + +#include <assert.h> + +/* In order to use the address of a resource data entry, we need to + get the image base of the file. Right now we extract it from + internal BFD information. FIXME. */ + +#include "coff/internal.h" +#include "libcoff.h" + +/* Information we extract from the file. */ + +struct coff_file_info +{ + /* File name. */ + const char *filename; + /* Data read from the file. */ + const bfd_byte *data; + /* End of data read from file. */ + const bfd_byte *data_end; + /* Address of the resource section minus the image base of the file. */ + bfd_vma secaddr; + /* Non-zero if the file is big endian. */ + int big_endian; +}; + +/* A resource directory table in a COFF file. */ + +struct extern_res_directory +{ + /* Characteristics. */ + bfd_byte characteristics[4]; + /* Time stamp. */ + bfd_byte time[4]; + /* Major version number. */ + bfd_byte major[2]; + /* Minor version number. */ + bfd_byte minor[2]; + /* Number of named directory entries. */ + bfd_byte name_count[2]; + /* Number of directory entries with IDs. */ + bfd_byte id_count[2]; +}; + +/* A resource directory entry in a COFF file. */ + +struct extern_res_entry +{ + /* Name or ID. */ + bfd_byte name[4]; + /* Address of resource entry or subdirectory. */ + bfd_byte rva[4]; +}; + +/* A resource data entry in a COFF file. */ + +struct extern_res_data +{ + /* Address of resource data. This is apparently a file relative + address, rather than a section offset. */ + bfd_byte rva[4]; + /* Size of resource data. */ + bfd_byte size[4]; + /* Code page. */ + bfd_byte codepage[4]; + /* Reserved. */ + bfd_byte reserved[4]; +}; + +/* Macros to swap in values. */ + +#define getfi_16(fi, s) ((fi)->big_endian ? bfd_getb16 (s) : bfd_getl16 (s)) +#define getfi_32(fi, s) ((fi)->big_endian ? bfd_getb32 (s) : bfd_getl32 (s)) + +/* Local functions. */ + +static void overrun PARAMS ((const struct coff_file_info *, const char *)); +static struct res_directory *read_coff_res_dir + PARAMS ((const bfd_byte *, const struct coff_file_info *, + const struct res_id *, int)); +static struct res_resource *read_coff_data_entry + PARAMS ((const bfd_byte *, const struct coff_file_info *, + const struct res_id *)); + +/* Read the resources in a COFF file. */ + +struct res_directory * +read_coff_rsrc (filename, target) + const char *filename; + const char *target; +{ + bfd *abfd; + char **matching; + asection *sec; + bfd_size_type size; + bfd_byte *data; + struct coff_file_info finfo; + + if (filename == NULL) + fatal (_("filename required for COFF input")); + + abfd = bfd_openr (filename, target); + if (abfd == NULL) + bfd_fatal (filename); + + if (! bfd_check_format_matches (abfd, bfd_object, &matching)) + { + bfd_nonfatal (bfd_get_filename (abfd)); + if (bfd_get_error () == bfd_error_file_ambiguously_recognized) + list_matching_formats (matching); + xexit (1); + } + + sec = bfd_get_section_by_name (abfd, ".rsrc"); + if (sec == NULL) + { + fprintf (stderr, _("%s: %s: no resource section\n"), program_name, + filename); + xexit (1); + } + + size = bfd_section_size (abfd, sec); + data = (bfd_byte *) res_alloc (size); + + if (! bfd_get_section_contents (abfd, sec, data, 0, size)) + bfd_fatal (_("can't read resource section")); + + finfo.filename = filename; + finfo.data = data; + finfo.data_end = data + size; + finfo.secaddr = (bfd_get_section_vma (abfd, sec) + - pe_data (abfd)->pe_opthdr.ImageBase); + finfo.big_endian = bfd_big_endian (abfd); + + bfd_close (abfd); + + /* Now just read in the top level resource directory. Note that we + don't free data, since we create resource entries that point into + it. If we ever want to free up the resource information we read, + this will have to be cleaned up. */ + + return read_coff_res_dir (data, &finfo, (const struct res_id *) NULL, 0); +} + +/* Give an error if we are out of bounds. */ + +static void +overrun (finfo, msg) + const struct coff_file_info *finfo; + const char *msg; +{ + fatal (_("%s: %s: address out of bounds"), finfo->filename, msg); +} + +/* Read a resource directory. */ + +static struct res_directory * +read_coff_res_dir (data, finfo, type, level) + const bfd_byte *data; + const struct coff_file_info *finfo; + const struct res_id *type; + int level; +{ + const struct extern_res_directory *erd; + struct res_directory *rd; + int name_count, id_count, i; + struct res_entry **pp; + const struct extern_res_entry *ere; + + if ((size_t) (finfo->data_end - data) < sizeof (struct extern_res_directory)) + overrun (finfo, _("directory")); + + erd = (const struct extern_res_directory *) data; + + rd = (struct res_directory *) res_alloc (sizeof *rd); + rd->characteristics = getfi_32 (finfo, erd->characteristics); + rd->time = getfi_32 (finfo, erd->time); + rd->major = getfi_16 (finfo, erd->major); + rd->minor = getfi_16 (finfo, erd->minor); + rd->entries = NULL; + + name_count = getfi_16 (finfo, erd->name_count); + id_count = getfi_16 (finfo, erd->id_count); + + pp = &rd->entries; + + /* The resource directory entries immediately follow the directory + table. */ + ere = (const struct extern_res_entry *) (erd + 1); + + for (i = 0; i < name_count; i++, ere++) + { + unsigned long name, rva; + struct res_entry *re; + const bfd_byte *ers; + int length, j; + + if ((const bfd_byte *) ere >= finfo->data_end) + overrun (finfo, _("named directory entry")); + + name = getfi_32 (finfo, ere->name); + rva = getfi_32 (finfo, ere->rva); + + /* For some reason the high bit in NAME is set. */ + name &=~ 0x80000000; + + if (name > (size_t) (finfo->data_end - finfo->data)) + overrun (finfo, _("directory entry name")); + + ers = finfo->data + name; + + re = (struct res_entry *) res_alloc (sizeof *re); + re->next = NULL; + re->id.named = 1; + length = getfi_16 (finfo, ers); + re->id.u.n.length = length; + re->id.u.n.name = (unichar *) res_alloc (length * sizeof (unichar)); + for (j = 0; j < length; j++) + re->id.u.n.name[j] = getfi_16 (finfo, ers + j * 2 + 2); + + if (level == 0) + type = &re->id; + + if ((rva & 0x80000000) != 0) + { + rva &=~ 0x80000000; + if (rva >= (size_t) (finfo->data_end - finfo->data)) + overrun (finfo, _("named subdirectory")); + re->subdir = 1; + re->u.dir = read_coff_res_dir (finfo->data + rva, finfo, type, + level + 1); + } + else + { + if (rva >= (size_t) (finfo->data_end - finfo->data)) + overrun (finfo, _("named resource")); + re->subdir = 0; + re->u.res = read_coff_data_entry (finfo->data + rva, finfo, type); + } + + *pp = re; + pp = &re->next; + } + + for (i = 0; i < id_count; i++, ere++) + { + unsigned long name, rva; + struct res_entry *re; + + if ((const bfd_byte *) ere >= finfo->data_end) + overrun (finfo, _("ID directory entry")); + + name = getfi_32 (finfo, ere->name); + rva = getfi_32 (finfo, ere->rva); + + re = (struct res_entry *) res_alloc (sizeof *re); + re->next = NULL; + re->id.named = 0; + re->id.u.id = name; + + if (level == 0) + type = &re->id; + + if ((rva & 0x80000000) != 0) + { + rva &=~ 0x80000000; + if (rva >= (size_t) (finfo->data_end - finfo->data)) + overrun (finfo, _("ID subdirectory")); + re->subdir = 1; + re->u.dir = read_coff_res_dir (finfo->data + rva, finfo, type, + level + 1); + } + else + { + if (rva >= (size_t) (finfo->data_end - finfo->data)) + overrun (finfo, _("ID resource")); + re->subdir = 0; + re->u.res = read_coff_data_entry (finfo->data + rva, finfo, type); + } + + *pp = re; + pp = &re->next; + } + + return rd; +} + +/* Read a resource data entry. */ + +static struct res_resource * +read_coff_data_entry (data, finfo, type) + const bfd_byte *data; + const struct coff_file_info *finfo; + const struct res_id *type; +{ + const struct extern_res_data *erd; + struct res_resource *r; + unsigned long size, rva; + const bfd_byte *resdata; + + if (type == NULL) + fatal (_("resource type unknown")); + + if ((size_t) (finfo->data_end - data) < sizeof (struct extern_res_data)) + overrun (finfo, _("data entry")); + + erd = (const struct extern_res_data *) data; + + size = getfi_32 (finfo, erd->size); + rva = getfi_32 (finfo, erd->rva); + if (rva < finfo->secaddr + || rva - finfo->secaddr >= (size_t) (finfo->data_end - finfo->data)) + overrun (finfo, _("resource data")); + + resdata = finfo->data + (rva - finfo->secaddr); + + if (size > (size_t) (finfo->data_end - resdata)) + overrun (finfo, _("resource data size")); + + r = bin_to_res (*type, resdata, size, finfo->big_endian); + + memset (&r->res_info, 0, sizeof (struct res_res_info)); + r->coff_info.codepage = getfi_32 (finfo, erd->codepage); + r->coff_info.reserved = getfi_32 (finfo, erd->reserved); + + return r; +} + +/* This structure is used to build a list of bindata structures. */ + +struct bindata_build +{ + /* The data. */ + struct bindata *d; + /* The last structure we have added to the list. */ + struct bindata *last; + /* The size of the list as a whole. */ + unsigned long length; +}; + +/* This structure keeps track of information as we build the directory + tree. */ + +struct coff_write_info +{ + /* These fields are based on the BFD. */ + /* The BFD itself. */ + bfd *abfd; + /* Non-zero if the file is big endian. */ + int big_endian; + /* Pointer to section symbol used to build RVA relocs. */ + asymbol **sympp; + + /* These fields are computed initially, and then not changed. */ + /* Length of directory tables and entries. */ + unsigned long dirsize; + /* Length of directory entry strings. */ + unsigned long dirstrsize; + /* Length of resource data entries. */ + unsigned long dataentsize; + + /* These fields are updated as we add data. */ + /* Directory tables and entries. */ + struct bindata_build dirs; + /* Directory entry strings. */ + struct bindata_build dirstrs; + /* Resource data entries. */ + struct bindata_build dataents; + /* Actual resource data. */ + struct bindata_build resources; + /* Relocations. */ + arelent **relocs; + /* Number of relocations. */ + unsigned int reloc_count; +}; + +/* Macros to swap out values. */ + +#define putcwi_16(cwi, v, s) \ + ((cwi->big_endian) ? bfd_putb16 ((v), (s)) : bfd_putl16 ((v), (s))) +#define putcwi_32(cwi, v, s) \ + ((cwi->big_endian) ? bfd_putb32 ((v), (s)) : bfd_putl32 ((v), (s))) + +static void coff_bin_sizes + PARAMS ((const struct res_directory *, struct coff_write_info *)); +static unsigned char *coff_alloc PARAMS ((struct bindata_build *, size_t)); +static void coff_to_bin + PARAMS ((const struct res_directory *, struct coff_write_info *)); +static void coff_res_to_bin + PARAMS ((const struct res_resource *, struct coff_write_info *)); + +/* Write resources to a COFF file. RESOURCES should already be + sorted. + + Right now we always create a new file. Someday we should also + offer the ability to merge resources into an existing file. This + would require doing the basic work of objcopy, just modifying or + adding the .rsrc section. */ + +void +write_coff_file (filename, target, resources) + const char *filename; + const char *target; + const struct res_directory *resources; +{ + bfd *abfd; + asection *sec; + struct coff_write_info cwi; + struct bindata *d; + unsigned long length, offset; + + if (filename == NULL) + fatal (_("filename required for COFF output")); + + abfd = bfd_openw (filename, target); + if (abfd == NULL) + bfd_fatal (filename); + + if (! bfd_set_format (abfd, bfd_object)) + bfd_fatal ("bfd_set_format"); + + /* FIXME: This is obviously i386 specific. */ + if (! bfd_set_arch_mach (abfd, bfd_arch_i386, 0)) + bfd_fatal ("bfd_set_arch_mach"); + + if (! bfd_set_file_flags (abfd, HAS_SYMS | HAS_RELOC)) + bfd_fatal ("bfd_set_file_flags"); + + sec = bfd_make_section (abfd, ".rsrc"); + if (sec == NULL) + bfd_fatal ("bfd_make_section"); + + if (! bfd_set_section_flags (abfd, sec, + (SEC_HAS_CONTENTS | SEC_ALLOC + | SEC_LOAD | SEC_DATA))) + bfd_fatal ("bfd_set_section_flags"); + + if (! bfd_set_symtab (abfd, sec->symbol_ptr_ptr, 1)) + bfd_fatal ("bfd_set_symtab"); + + /* Requiring this is probably a bug in BFD. */ + sec->output_section = sec; + + /* The order of data in the .rsrc section is + resource directory tables and entries + resource directory strings + resource data entries + actual resource data + + We build these different types of data in different lists. */ + + cwi.abfd = abfd; + cwi.big_endian = bfd_big_endian (abfd); + cwi.sympp = sec->symbol_ptr_ptr; + cwi.dirsize = 0; + cwi.dirstrsize = 0; + cwi.dataentsize = 0; + cwi.dirs.d = NULL; + cwi.dirs.last = NULL; + cwi.dirs.length = 0; + cwi.dirstrs.d = NULL; + cwi.dirstrs.last = NULL; + cwi.dirstrs.length = 0; + cwi.dataents.d = NULL; + cwi.dataents.last = NULL; + cwi.dataents.length = 0; + cwi.resources.d = NULL; + cwi.resources.last = NULL; + cwi.resources.length = 0; + cwi.relocs = NULL; + cwi.reloc_count = 0; + + /* Work out the sizes of the resource directory entries, so that we + know the various offsets we will need. */ + coff_bin_sizes (resources, &cwi); + + /* Force the directory strings to be 32 bit aligned. Every other + structure is 32 bit aligned anyhow. */ + cwi.dirstrsize = (cwi.dirstrsize + 3) &~ 3; + + /* Actually convert the resources to binary. */ + coff_to_bin (resources, &cwi); + + /* Add another 2 bytes to the directory strings if needed for + alignment. */ + if ((cwi.dirstrs.length & 3) != 0) + { + unsigned char *ex; + + ex = coff_alloc (&cwi.dirstrs, 2); + ex[0] = 0; + ex[1] = 0; + } + + /* Make sure that the data we built came out to the same size as we + calculated initially. */ + assert (cwi.dirs.length == cwi.dirsize); + assert (cwi.dirstrs.length == cwi.dirstrsize); + assert (cwi.dataents.length == cwi.dataentsize); + + length = (cwi.dirsize + + cwi.dirstrsize + + cwi.dataentsize + + cwi.resources.length); + + if (! bfd_set_section_size (abfd, sec, length)) + bfd_fatal ("bfd_set_section_size"); + + bfd_set_reloc (abfd, sec, cwi.relocs, cwi.reloc_count); + + offset = 0; + for (d = cwi.dirs.d; d != NULL; d = d->next) + { + if (! bfd_set_section_contents (abfd, sec, d->data, offset, d->length)) + bfd_fatal ("bfd_set_section_contents"); + offset += d->length; + } + for (d = cwi.dirstrs.d; d != NULL; d = d->next) + { + if (! bfd_set_section_contents (abfd, sec, d->data, offset, d->length)) + bfd_fatal ("bfd_set_section_contents"); + offset += d->length; + } + for (d = cwi.dataents.d; d != NULL; d = d->next) + { + if (! bfd_set_section_contents (abfd, sec, d->data, offset, d->length)) + bfd_fatal ("bfd_set_section_contents"); + offset += d->length; + } + for (d = cwi.resources.d; d != NULL; d = d->next) + { + if (! bfd_set_section_contents (abfd, sec, d->data, offset, d->length)) + bfd_fatal ("bfd_set_section_contents"); + offset += d->length; + } + + assert (offset == length); + + if (! bfd_close (abfd)) + bfd_fatal ("bfd_close"); + + /* We allocated the relocs array using malloc. */ + free (cwi.relocs); +} + +/* Work out the sizes of the various fixed size resource directory + entries. This updates fields in CWI. */ + +static void +coff_bin_sizes (resdir, cwi) + const struct res_directory *resdir; + struct coff_write_info *cwi; +{ + const struct res_entry *re; + + cwi->dirsize += sizeof (struct extern_res_directory); + + for (re = resdir->entries; re != NULL; re = re->next) + { + cwi->dirsize += sizeof (struct extern_res_entry); + + if (re->id.named) + cwi->dirstrsize += re->id.u.n.length * 2 + 2; + + if (re->subdir) + coff_bin_sizes (re->u.dir, cwi); + else + cwi->dataentsize += sizeof (struct extern_res_data); + } +} + +/* Allocate data for a particular list. */ + +static unsigned char * +coff_alloc (bb, size) + struct bindata_build *bb; + size_t size; +{ + struct bindata *d; + + d = (struct bindata *) reswr_alloc (sizeof *d); + + d->next = NULL; + d->data = (unsigned char *) reswr_alloc (size); + d->length = size; + + if (bb->d == NULL) + bb->d = d; + else + bb->last->next = d; + bb->last = d; + bb->length += size; + + return d->data; +} + +/* Convert the resource directory RESDIR to binary. */ + +static void +coff_to_bin (resdir, cwi) + const struct res_directory *resdir; + struct coff_write_info *cwi; +{ + struct extern_res_directory *erd; + int ci, cn; + const struct res_entry *e; + struct extern_res_entry *ere; + + /* Write out the directory table. */ + + erd = ((struct extern_res_directory *) + coff_alloc (&cwi->dirs, sizeof (*erd))); + + putcwi_32 (cwi, resdir->characteristics, erd->characteristics); + putcwi_32 (cwi, resdir->time, erd->time); + putcwi_16 (cwi, resdir->major, erd->major); + putcwi_16 (cwi, resdir->minor, erd->minor); + + ci = 0; + cn = 0; + for (e = resdir->entries; e != NULL; e = e->next) + { + if (e->id.named) + ++cn; + else + ++ci; + } + + putcwi_16 (cwi, cn, erd->name_count); + putcwi_16 (cwi, ci, erd->id_count); + + /* Write out the data entries. Note that we allocate space for all + the entries before writing them out. That permits a recursive + call to work correctly when writing out subdirectories. */ + + ere = ((struct extern_res_entry *) + coff_alloc (&cwi->dirs, (ci + cn) * sizeof (*ere))); + for (e = resdir->entries; e != NULL; e = e->next, ere++) + { + if (! e->id.named) + putcwi_32 (cwi, e->id.u.id, ere->name); + else + { + unsigned char *str; + int i; + + /* For some reason existing files seem to have the high bit + set on the address of the name, although that is not + documented. */ + putcwi_32 (cwi, + 0x80000000 | (cwi->dirsize + cwi->dirstrs.length), + ere->name); + + str = coff_alloc (&cwi->dirstrs, e->id.u.n.length * 2 + 2); + putcwi_16 (cwi, e->id.u.n.length, str); + for (i = 0; i < e->id.u.n.length; i++) + putcwi_16 (cwi, e->id.u.n.name[i], str + i * 2 + 2); + } + + if (e->subdir) + { + putcwi_32 (cwi, 0x80000000 | cwi->dirs.length, ere->rva); + coff_to_bin (e->u.dir, cwi); + } + else + { + putcwi_32 (cwi, + cwi->dirsize + cwi->dirstrsize + cwi->dataents.length, + ere->rva); + + coff_res_to_bin (e->u.res, cwi); + } + } +} + +/* Convert the resource RES to binary. */ + +static void +coff_res_to_bin (res, cwi) + const struct res_resource *res; + struct coff_write_info *cwi; +{ + arelent *r; + struct extern_res_data *erd; + struct bindata *d; + unsigned long length; + + /* For some reason, although every other address is a section + offset, the address of the resource data itself is an RVA. That + means that we need to generate a relocation for it. We allocate + the relocs array using malloc so that we can use realloc. FIXME: + This relocation handling is correct for the i386, but probably + not for any other target. */ + + r = (arelent *) reswr_alloc (sizeof (arelent)); + r->sym_ptr_ptr = cwi->sympp; + r->address = cwi->dirsize + cwi->dirstrsize + cwi->dataents.length; + r->addend = 0; + r->howto = bfd_reloc_type_lookup (cwi->abfd, BFD_RELOC_RVA); + if (r->howto == NULL) + bfd_fatal (_("can't get BFD_RELOC_RVA relocation type")); + + cwi->relocs = xrealloc (cwi->relocs, + (cwi->reloc_count + 2) * sizeof (arelent *)); + cwi->relocs[cwi->reloc_count] = r; + cwi->relocs[cwi->reloc_count + 1] = NULL; + ++cwi->reloc_count; + + erd = (struct extern_res_data *) coff_alloc (&cwi->dataents, sizeof (*erd)); + + putcwi_32 (cwi, + (cwi->dirsize + + cwi->dirstrsize + + cwi->dataentsize + + cwi->resources.length), + erd->rva); + putcwi_32 (cwi, res->coff_info.codepage, erd->codepage); + putcwi_32 (cwi, res->coff_info.reserved, erd->reserved); + + d = res_to_bin (res, cwi->big_endian); + + if (cwi->resources.d == NULL) + cwi->resources.d = d; + else + cwi->resources.last->next = d; + + length = 0; + for (; d->next != NULL; d = d->next) + length += d->length; + length += d->length; + cwi->resources.last = d; + cwi->resources.length += length; + + putcwi_32 (cwi, length, erd->size); + + /* Force the next resource to have 32 bit alignment. */ + + if ((length & 3) != 0) + { + int add; + unsigned char *ex; + + add = 4 - (length & 3); + + ex = coff_alloc (&cwi->resources, add); + memset (ex, 0, add); + } +} diff --git a/binutils/resrc.c b/binutils/resrc.c new file mode 100644 index 0000000..9ba3c11 --- /dev/null +++ b/binutils/resrc.c @@ -0,0 +1,2265 @@ +/* resrc.c -- read and write Windows rc files. + Copyright 1997, 1998 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Cygnus Support. + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* This file contains functions that read and write Windows rc files. + These are text files that represent resources. */ + +#include "bfd.h" +#include "bucomm.h" +#include "libiberty.h" +#include "windres.h" + +#include <assert.h> +#include <ctype.h> +#include <sys/stat.h> + +#if defined (_WIN32) && ! defined (__CYGWIN32__) +#define popen _popen +#define pclose _pclose +#endif + +/* The default preprocessor. */ + +#define DEFAULT_PREPROCESSOR "gcc -E -xc-header -DRC_INVOKED" + +/* We read the directory entries in a cursor or icon file into + instances of this structure. */ + +struct icondir +{ + /* Width of image. */ + unsigned char width; + /* Height of image. */ + unsigned char height; + /* Number of colors in image. */ + unsigned char colorcount; + union + { + struct + { + /* Color planes. */ + unsigned short planes; + /* Bits per pixel. */ + unsigned short bits; + } icon; + struct + { + /* X coordinate of hotspot. */ + unsigned short xhotspot; + /* Y coordinate of hotspot. */ + unsigned short yhotspot; + } cursor; + } u; + /* Bytes in image. */ + unsigned long bytes; + /* File offset of image. */ + unsigned long offset; +}; + +/* The name of the rc file we are reading. */ + +char *rc_filename; + +/* The line number in the rc file. */ + +int rc_lineno; + +/* The pipe we are reading from, so that we can close it if we exit. */ + +static FILE *cpp_pipe; + +/* As we read the rc file, we attach information to this structure. */ + +static struct res_directory *resources; + +/* The number of cursor resources we have written out. */ + +static int cursors; + +/* The number of font resources we have written out. */ + +static int fonts; + +/* Font directory information. */ + +struct fontdir *fontdirs; + +/* Resource info to use for fontdirs. */ + +struct res_res_info fontdirs_resinfo; + +/* The number of icon resources we have written out. */ + +static int icons; + +/* Local functions. */ + +static void close_pipe PARAMS ((void)); +static void unexpected_eof PARAMS ((const char *)); +static int get_word PARAMS ((FILE *, const char *)); +static unsigned long get_long PARAMS ((FILE *, const char *)); +static void get_data + PARAMS ((FILE *, unsigned char *, unsigned long, const char *)); +static void define_fontdirs PARAMS ((void)); + +/* Read an rc file. */ + +struct res_directory * +read_rc_file (filename, preprocessor, preprocargs, language) + const char *filename; + const char *preprocessor; + const char *preprocargs; + int language; +{ + char *cmd; + + if (preprocessor == NULL) + preprocessor = DEFAULT_PREPROCESSOR; + + if (preprocargs == NULL) + preprocargs = ""; + if (filename == NULL) + filename = "-"; + + cmd = xmalloc (strlen (preprocessor) + + strlen (preprocargs) + + strlen (filename) + + 10); + sprintf (cmd, "%s %s %s", preprocessor, preprocargs, filename); + + cpp_pipe = popen (cmd, FOPEN_RT); + if (cpp_pipe == NULL) + fatal (_("can't popen `%s': %s"), cmd, strerror (errno)); + free (cmd); + + xatexit (close_pipe); + + rc_filename = xstrdup (filename); + rc_lineno = 1; + if (language != -1) + rcparse_set_language (language); + yyin = cpp_pipe; + yyparse (); + + if (pclose (cpp_pipe) != 0) + fprintf (stderr, _("%s: warning: preprocessor failed\n"), program_name); + cpp_pipe = NULL; + + if (fontdirs != NULL) + define_fontdirs (); + + free (rc_filename); + rc_filename = NULL; + + return resources; +} + +/* Close the pipe if it is open. This is called via xatexit. */ + +void +close_pipe () +{ + if (cpp_pipe != NULL) + pclose (cpp_pipe); +} + +/* Report an error while reading an rc file. */ + +void +yyerror (msg) + const char *msg; +{ + fatal ("%s:%d: %s", rc_filename, rc_lineno, msg); +} + +/* Issue a warning while reading an rc file. */ + +void +rcparse_warning (msg) + const char *msg; +{ + fprintf (stderr, "%s:%d: %s\n", rc_filename, rc_lineno, msg); +} + +/* Die if we get an unexpected end of file. */ + +static void +unexpected_eof (msg) + const char *msg; +{ + fatal (_("%s: unexpected EOF"), msg); +} + +/* Read a 16 bit word from a file. The data is assumed to be little + endian. */ + +static int +get_word (e, msg) + FILE *e; + const char *msg; +{ + int b1, b2; + + b1 = getc (e); + b2 = getc (e); + if (feof (e)) + unexpected_eof (msg); + return ((b2 & 0xff) << 8) | (b1 & 0xff); +} + +/* Read a 32 bit word from a file. The data is assumed to be little + endian. */ + +static unsigned long +get_long (e, msg) + FILE *e; + const char *msg; +{ + int b1, b2, b3, b4; + + b1 = getc (e); + b2 = getc (e); + b3 = getc (e); + b4 = getc (e); + if (feof (e)) + unexpected_eof (msg); + return (((((((b4 & 0xff) << 8) + | (b3 & 0xff)) << 8) + | (b2 & 0xff)) << 8) + | (b1 & 0xff)); +} + +/* Read data from a file. This is a wrapper to do error checking. */ + +static void +get_data (e, p, c, msg) + FILE *e; + unsigned char *p; + unsigned long c; + const char *msg; +{ + unsigned long got; + + got = fread (p, 1, c, e); + if (got == c) + return; + + fatal (_("%s: read of %lu returned %lu"), msg, c, got); +} + +/* Define an accelerator resource. */ + +void +define_accelerator (id, resinfo, data) + struct res_id id; + const struct res_res_info *resinfo; + struct accelerator *data; +{ + struct res_resource *r; + + r = define_standard_resource (&resources, RT_ACCELERATOR, id, + resinfo->language, 0); + r->type = RES_TYPE_ACCELERATOR; + r->u.acc = data; + r->res_info = *resinfo; +} + +/* Define a bitmap resource. Bitmap data is stored in a file. The + first 14 bytes of the file are a standard header, which is not + included in the resource data. */ + +#define BITMAP_SKIP (14) + +void +define_bitmap (id, resinfo, filename) + struct res_id id; + const struct res_res_info *resinfo; + const char *filename; +{ + FILE *e; + char *real_filename; + struct stat s; + unsigned char *data; + int i; + struct res_resource *r; + + e = open_file_search (filename, FOPEN_RB, "bitmap file", &real_filename); + + if (stat (real_filename, &s) < 0) + fatal (_("stat failed on bitmap file `%s': %s"), real_filename, + strerror (errno)); + + data = (unsigned char *) res_alloc (s.st_size - BITMAP_SKIP); + + for (i = 0; i < BITMAP_SKIP; i++) + getc (e); + + get_data (e, data, s.st_size - BITMAP_SKIP, real_filename); + + fclose (e); + free (real_filename); + + r = define_standard_resource (&resources, RT_BITMAP, id, + resinfo->language, 0); + + r->type = RES_TYPE_BITMAP; + r->u.data.length = s.st_size - BITMAP_SKIP; + r->u.data.data = data; + r->res_info = *resinfo; +} + +/* Define a cursor resource. A cursor file may contain a set of + bitmaps, each representing the same cursor at various different + resolutions. They each get written out with a different ID. The + real cursor resource is then a group resource which can be used to + select one of the actual cursors. */ + +void +define_cursor (id, resinfo, filename) + struct res_id id; + const struct res_res_info *resinfo; + const char *filename; +{ + FILE *e; + char *real_filename; + int type, count, i; + struct icondir *icondirs; + int first_cursor; + struct res_resource *r; + struct group_cursor *first, **pp; + + e = open_file_search (filename, FOPEN_RB, "cursor file", &real_filename); + + /* A cursor file is basically an icon file. The start of the file + is a three word structure. The first word is ignored. The + second word is the type of data. The third word is the number of + entries. */ + + get_word (e, real_filename); + type = get_word (e, real_filename); + count = get_word (e, real_filename); + if (type != 2) + fatal (_("cursor file `%s' does not contain cursor data"), real_filename); + + /* Read in the icon directory entries. */ + + icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs); + + for (i = 0; i < count; i++) + { + icondirs[i].width = getc (e); + icondirs[i].height = getc (e); + icondirs[i].colorcount = getc (e); + getc (e); + icondirs[i].u.cursor.xhotspot = get_word (e, real_filename); + icondirs[i].u.cursor.yhotspot = get_word (e, real_filename); + icondirs[i].bytes = get_long (e, real_filename); + icondirs[i].offset = get_long (e, real_filename); + + if (feof (e)) + unexpected_eof (real_filename); + } + + /* Define each cursor as a unique resource. */ + + first_cursor = cursors; + + for (i = 0; i < count; i++) + { + unsigned char *data; + struct res_id name; + struct cursor *c; + + if (fseek (e, icondirs[i].offset, SEEK_SET) != 0) + fatal (_("%s: fseek to %lu failed: %s"), real_filename, + icondirs[i].offset, strerror (errno)); + + data = (unsigned char *) res_alloc (icondirs[i].bytes); + + get_data (e, data, icondirs[i].bytes, real_filename); + + c = (struct cursor *) res_alloc (sizeof *c); + c->xhotspot = icondirs[i].u.cursor.xhotspot; + c->yhotspot = icondirs[i].u.cursor.yhotspot; + c->length = icondirs[i].bytes; + c->data = data; + + ++cursors; + + name.named = 0; + name.u.id = cursors; + + r = define_standard_resource (&resources, RT_CURSOR, name, + resinfo->language, 0); + r->type = RES_TYPE_CURSOR; + r->u.cursor = c; + r->res_info = *resinfo; + } + + fclose (e); + free (real_filename); + + /* Define a cursor group resource. */ + + first = NULL; + pp = &first; + for (i = 0; i < count; i++) + { + struct group_cursor *cg; + + cg = (struct group_cursor *) res_alloc (sizeof *cg); + cg->next = NULL; + cg->width = icondirs[i].width; + cg->height = 2 * icondirs[i].height; + + /* FIXME: What should these be set to? */ + cg->planes = 1; + cg->bits = 1; + + cg->bytes = icondirs[i].bytes + 4; + cg->index = first_cursor + i + 1; + + *pp = cg; + pp = &(*pp)->next; + } + + free (icondirs); + + r = define_standard_resource (&resources, RT_GROUP_CURSOR, id, + resinfo->language, 0); + r->type = RES_TYPE_GROUP_CURSOR; + r->u.group_cursor = first; + r->res_info = *resinfo; +} + +/* Define a dialog resource. */ + +void +define_dialog (id, resinfo, dialog) + struct res_id id; + const struct res_res_info *resinfo; + const struct dialog *dialog; +{ + struct dialog *copy; + struct res_resource *r; + + copy = (struct dialog *) res_alloc (sizeof *copy); + *copy = *dialog; + + r = define_standard_resource (&resources, RT_DIALOG, id, + resinfo->language, 0); + r->type = RES_TYPE_DIALOG; + r->u.dialog = copy; + r->res_info = *resinfo; +} + +/* Define a dialog control. This does not define a resource, but + merely allocates and fills in a structure. */ + +struct dialog_control * +define_control (text, id, x, y, width, height, class, style, exstyle) + const char *text; + unsigned long id; + unsigned long x; + unsigned long y; + unsigned long width; + unsigned long height; + unsigned long class; + unsigned long style; + unsigned long exstyle; +{ + struct dialog_control *n; + + n = (struct dialog_control *) res_alloc (sizeof *n); + n->next = NULL; + n->id = id; + n->style = style; + n->exstyle = exstyle; + n->x = x; + n->y = y; + n->width = width; + n->height = height; + n->class.named = 0; + n->class.u.id = class; + if (text != NULL) + res_string_to_id (&n->text, text); + else + { + n->text.named = 0; + n->text.u.id = 0; + } + n->data = NULL; + n->help = 0; + + return n; +} + +/* Define a font resource. */ + +void +define_font (id, resinfo, filename) + struct res_id id; + const struct res_res_info *resinfo; + const char *filename; +{ + FILE *e; + char *real_filename; + struct stat s; + unsigned char *data; + struct res_resource *r; + long offset; + long fontdatalength; + unsigned char *fontdata; + struct fontdir *fd; + const char *device, *face; + struct fontdir **pp; + + e = open_file_search (filename, FOPEN_RB, "font file", &real_filename); + + if (stat (real_filename, &s) < 0) + fatal (_("stat failed on bitmap file `%s': %s"), real_filename, + strerror (errno)); + + data = (unsigned char *) res_alloc (s.st_size); + + get_data (e, data, s.st_size, real_filename); + + fclose (e); + free (real_filename); + + r = define_standard_resource (&resources, RT_FONT, id, + resinfo->language, 0); + + r->type = RES_TYPE_FONT; + r->u.data.length = s.st_size; + r->u.data.data = data; + r->res_info = *resinfo; + + /* For each font resource, we must add an entry in the FONTDIR + resource. The FONTDIR resource includes some strings in the font + file. To find them, we have to do some magic on the data we have + read. */ + + offset = ((((((data[47] << 8) + | data[46]) << 8) + | data[45]) << 8) + | data[44]); + if (offset > 0 && offset < s.st_size) + device = (char *) data + offset; + else + device = ""; + + offset = ((((((data[51] << 8) + | data[50]) << 8) + | data[49]) << 8) + | data[48]); + if (offset > 0 && offset < s.st_size) + face = (char *) data + offset; + else + face = ""; + + ++fonts; + + fontdatalength = 58 + strlen (device) + strlen (face); + fontdata = (unsigned char *) res_alloc (fontdatalength); + memcpy (fontdata, data, 56); + strcpy ((char *) fontdata + 56, device); + strcpy ((char *) fontdata + 57 + strlen (device), face); + + fd = (struct fontdir *) res_alloc (sizeof *fd); + fd->next = NULL; + fd->index = fonts; + fd->length = fontdatalength; + fd->data = fontdata; + + for (pp = &fontdirs; *pp != NULL; pp = &(*pp)->next) + ; + *pp = fd; + + /* For the single fontdirs resource, we always use the resource + information of the last font. I don't know what else to do. */ + fontdirs_resinfo = *resinfo; +} + +/* Define the fontdirs resource. This is called after the entire rc + file has been parsed, if any font resources were seen. */ + +static void +define_fontdirs () +{ + struct res_resource *r; + struct res_id id; + + id.named = 0; + id.u.id = 1; + + r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0); + + r->type = RES_TYPE_FONTDIR; + r->u.fontdir = fontdirs; + r->res_info = fontdirs_resinfo; +} + +/* Define an icon resource. An icon file may contain a set of + bitmaps, each representing the same icon at various different + resolutions. They each get written out with a different ID. The + real icon resource is then a group resource which can be used to + select one of the actual icon bitmaps. */ + +void +define_icon (id, resinfo, filename) + struct res_id id; + const struct res_res_info *resinfo; + const char *filename; +{ + FILE *e; + char *real_filename; + int type, count, i; + struct icondir *icondirs; + int first_icon; + struct res_resource *r; + struct group_icon *first, **pp; + + e = open_file_search (filename, FOPEN_RB, "icon file", &real_filename); + + /* The start of an icon file is a three word structure. The first + word is ignored. The second word is the type of data. The third + word is the number of entries. */ + + get_word (e, real_filename); + type = get_word (e, real_filename); + count = get_word (e, real_filename); + if (type != 1) + fatal (_("icon file `%s' does not contain icon data"), real_filename); + + /* Read in the icon directory entries. */ + + icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs); + + for (i = 0; i < count; i++) + { + icondirs[i].width = getc (e); + icondirs[i].height = getc (e); + icondirs[i].colorcount = getc (e); + getc (e); + icondirs[i].u.icon.planes = get_word (e, real_filename); + icondirs[i].u.icon.bits = get_word (e, real_filename); + icondirs[i].bytes = get_long (e, real_filename); + icondirs[i].offset = get_long (e, real_filename); + + if (feof (e)) + unexpected_eof (real_filename); + } + + /* Define each icon as a unique resource. */ + + first_icon = icons; + + for (i = 0; i < count; i++) + { + unsigned char *data; + struct res_id name; + + if (fseek (e, icondirs[i].offset, SEEK_SET) != 0) + fatal (_("%s: fseek to %lu failed: %s"), real_filename, + icondirs[i].offset, strerror (errno)); + + data = (unsigned char *) res_alloc (icondirs[i].bytes); + + get_data (e, data, icondirs[i].bytes, real_filename); + + ++icons; + + name.named = 0; + name.u.id = icons; + + r = define_standard_resource (&resources, RT_ICON, name, + resinfo->language, 0); + r->type = RES_TYPE_ICON; + r->u.data.length = icondirs[i].bytes; + r->u.data.data = data; + r->res_info = *resinfo; + } + + fclose (e); + free (real_filename); + + /* Define an icon group resource. */ + + first = NULL; + pp = &first; + for (i = 0; i < count; i++) + { + struct group_icon *cg; + + /* For some reason, at least in some files the planes and bits + are zero. We instead set them from the color. This is + copied from rcl. */ + + cg = (struct group_icon *) res_alloc (sizeof *cg); + cg->next = NULL; + cg->width = icondirs[i].width; + cg->height = icondirs[i].height; + cg->colors = icondirs[i].colorcount; + + cg->planes = 1; + cg->bits = 0; + while ((1 << cg->bits) < cg->colors) + ++cg->bits; + + cg->bytes = icondirs[i].bytes; + cg->index = first_icon + i + 1; + + *pp = cg; + pp = &(*pp)->next; + } + + free (icondirs); + + r = define_standard_resource (&resources, RT_GROUP_ICON, id, + resinfo->language, 0); + r->type = RES_TYPE_GROUP_ICON; + r->u.group_icon = first; + r->res_info = *resinfo; +} + +/* Define a menu resource. */ + +void +define_menu (id, resinfo, menuitems) + struct res_id id; + const struct res_res_info *resinfo; + struct menuitem *menuitems; +{ + struct menu *m; + struct res_resource *r; + + m = (struct menu *) res_alloc (sizeof *m); + m->items = menuitems; + m->help = 0; + + r = define_standard_resource (&resources, RT_MENU, id, resinfo->language, 0); + r->type = RES_TYPE_MENU; + r->u.menu = m; + r->res_info = *resinfo; +} + +/* Define a menu item. This does not define a resource, but merely + allocates and fills in a structure. */ + +struct menuitem * +define_menuitem (text, menuid, type, state, help, menuitems) + const char *text; + int menuid; + unsigned long type; + unsigned long state; + unsigned long help; + struct menuitem *menuitems; +{ + struct menuitem *mi; + + mi = (struct menuitem *) res_alloc (sizeof *mi); + mi->next = NULL; + mi->type = type; + mi->state = state; + mi->id = menuid; + if (text == NULL) + mi->text = NULL; + else + unicode_from_ascii ((int *) NULL, &mi->text, text); + mi->help = help; + mi->popup = menuitems; + return mi; +} + +/* Define a messagetable resource. */ + +void +define_messagetable (id, resinfo, filename) + struct res_id id; + const struct res_res_info *resinfo; + const char *filename; +{ + FILE *e; + char *real_filename; + struct stat s; + unsigned char *data; + struct res_resource *r; + + e = open_file_search (filename, FOPEN_RB, "messagetable file", + &real_filename); + + if (stat (real_filename, &s) < 0) + fatal (_("stat failed on bitmap file `%s': %s"), real_filename, + strerror (errno)); + + data = (unsigned char *) res_alloc (s.st_size); + + get_data (e, data, s.st_size, real_filename); + + fclose (e); + free (real_filename); + + r = define_standard_resource (&resources, RT_MESSAGETABLE, id, + resinfo->language, 0); + + r->type = RES_TYPE_MESSAGETABLE; + r->u.data.length = s.st_size; + r->u.data.data = data; + r->res_info = *resinfo; +} + +/* Define an rcdata resource. */ + +void +define_rcdata (id, resinfo, data) + struct res_id id; + const struct res_res_info *resinfo; + struct rcdata_item *data; +{ + struct res_resource *r; + + r = define_standard_resource (&resources, RT_RCDATA, id, + resinfo->language, 0); + r->type = RES_TYPE_RCDATA; + r->u.rcdata = data; + r->res_info = *resinfo; +} + +/* Create an rcdata item holding a string. */ + +struct rcdata_item * +define_rcdata_string (string, len) + const char *string; + unsigned long len; +{ + struct rcdata_item *ri; + char *s; + + ri = (struct rcdata_item *) res_alloc (sizeof *ri); + ri->next = NULL; + ri->type = RCDATA_STRING; + ri->u.string.length = len; + s = (char *) res_alloc (len); + memcpy (s, string, len); + ri->u.string.s = s; + + return ri; +} + +/* Create an rcdata item holding a number. */ + +struct rcdata_item * +define_rcdata_number (val, dword) + unsigned long val; + int dword; +{ + struct rcdata_item *ri; + + ri = (struct rcdata_item *) res_alloc (sizeof *ri); + ri->next = NULL; + ri->type = dword ? RCDATA_DWORD : RCDATA_WORD; + ri->u.word = val; + + return ri; +} + +/* Define a stringtable resource. This is called for each string + which appears in a STRINGTABLE statement. */ + +void +define_stringtable (resinfo, stringid, string) + const struct res_res_info *resinfo; + unsigned long stringid; + const char *string; +{ + struct res_id id; + struct res_resource *r; + + id.named = 0; + id.u.id = (stringid >> 4) + 1; + r = define_standard_resource (&resources, RT_STRING, id, + resinfo->language, 1); + + if (r->type == RES_TYPE_UNINITIALIZED) + { + int i; + + r->type = RES_TYPE_STRINGTABLE; + r->u.stringtable = ((struct stringtable *) + res_alloc (sizeof (struct stringtable))); + for (i = 0; i < 16; i++) + { + r->u.stringtable->strings[i].length = 0; + r->u.stringtable->strings[i].string = NULL; + } + + r->res_info = *resinfo; + } + + unicode_from_ascii (&r->u.stringtable->strings[stringid & 0xf].length, + &r->u.stringtable->strings[stringid & 0xf].string, + string); +} + +/* Define a user data resource where the data is in the rc file. */ + +void +define_user_data (id, type, resinfo, data) + struct res_id id; + struct res_id type; + const struct res_res_info *resinfo; + struct rcdata_item *data; +{ + struct res_id ids[3]; + struct res_resource *r; + + ids[0] = type; + ids[1] = id; + ids[2].named = 0; + ids[2].u.id = resinfo->language; + + r = define_resource (&resources, 3, ids, 0); + r->type = RES_TYPE_USERDATA; + r->u.userdata = data; + r->res_info = *resinfo; +} + +/* Define a user data resource where the data is in a file. */ + +void +define_user_file (id, type, resinfo, filename) + struct res_id id; + struct res_id type; + const struct res_res_info *resinfo; + const char *filename; +{ + FILE *e; + char *real_filename; + struct stat s; + unsigned char *data; + struct res_id ids[3]; + struct res_resource *r; + + e = open_file_search (filename, FOPEN_RB, "font file", &real_filename); + + if (stat (real_filename, &s) < 0) + fatal (_("stat failed on bitmap file `%s': %s"), real_filename, + strerror (errno)); + + data = (unsigned char *) res_alloc (s.st_size); + + get_data (e, data, s.st_size, real_filename); + + fclose (e); + free (real_filename); + + ids[0] = type; + ids[1] = id; + ids[2].named = 0; + ids[2].u.id = resinfo->language; + + r = define_resource (&resources, 3, ids, 0); + r->type = RES_TYPE_USERDATA; + r->u.userdata = ((struct rcdata_item *) + res_alloc (sizeof (struct rcdata_item))); + r->u.userdata->next = NULL; + r->u.userdata->type = RCDATA_BUFFER; + r->u.userdata->u.buffer.length = s.st_size; + r->u.userdata->u.buffer.data = data; + r->res_info = *resinfo; +} + +/* Define a versioninfo resource. */ + +void +define_versioninfo (id, language, fixedverinfo, verinfo) + struct res_id id; + int language; + struct fixed_versioninfo *fixedverinfo; + struct ver_info *verinfo; +{ + struct res_resource *r; + + r = define_standard_resource (&resources, RT_VERSION, id, language, 0); + r->type = RES_TYPE_VERSIONINFO; + r->u.versioninfo = ((struct versioninfo *) + res_alloc (sizeof (struct versioninfo))); + r->u.versioninfo->fixed = fixedverinfo; + r->u.versioninfo->var = verinfo; + r->res_info.language = language; +} + +/* Add string version info to a list of version information. */ + +struct ver_info * +append_ver_stringfileinfo (verinfo, language, strings) + struct ver_info *verinfo; + const char *language; + struct ver_stringinfo *strings; +{ + struct ver_info *vi, **pp; + + vi = (struct ver_info *) res_alloc (sizeof *vi); + vi->next = NULL; + vi->type = VERINFO_STRING; + unicode_from_ascii ((int *) NULL, &vi->u.string.language, language); + vi->u.string.strings = strings; + + for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next) + ; + *pp = vi; + + return verinfo; +} + +/* Add variable version info to a list of version information. */ + +struct ver_info * +append_ver_varfileinfo (verinfo, key, var) + struct ver_info *verinfo; + const char *key; + struct ver_varinfo *var; +{ + struct ver_info *vi, **pp; + + vi = (struct ver_info *) res_alloc (sizeof *vi); + vi->next = NULL; + vi->type = VERINFO_VAR; + unicode_from_ascii ((int *) NULL, &vi->u.var.key, key); + vi->u.var.var = var; + + for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next) + ; + *pp = vi; + + return verinfo; +} + +/* Append version string information to a list. */ + +struct ver_stringinfo * +append_verval (strings, key, value) + struct ver_stringinfo *strings; + const char *key; + const char *value; +{ + struct ver_stringinfo *vs, **pp; + + vs = (struct ver_stringinfo *) res_alloc (sizeof *vs); + vs->next = NULL; + unicode_from_ascii ((int *) NULL, &vs->key, key); + unicode_from_ascii ((int *) NULL, &vs->value, value); + + for (pp = &strings; *pp != NULL; pp = &(*pp)->next) + ; + *pp = vs; + + return strings; +} + +/* Append version variable information to a list. */ + +struct ver_varinfo * +append_vertrans (var, language, charset) + struct ver_varinfo *var; + unsigned long language; + unsigned long charset; +{ + struct ver_varinfo *vv, **pp; + + vv = (struct ver_varinfo *) res_alloc (sizeof *vv); + vv->next = NULL; + vv->language = language; + vv->charset = charset; + + for (pp = &var; *pp != NULL; pp = &(*pp)->next) + ; + *pp = vv; + + return var; +} + +/* Local functions used to write out an rc file. */ + +static void indent PARAMS ((FILE *, int)); +static void write_rc_directory + PARAMS ((FILE *, const struct res_directory *, const struct res_id *, + const struct res_id *, int *, int)); +static void write_rc_subdir + PARAMS ((FILE *, const struct res_entry *, const struct res_id *, + const struct res_id *, int *, int)); +static void write_rc_resource + PARAMS ((FILE *, const struct res_id *, const struct res_id *, + const struct res_resource *, int *)); +static void write_rc_accelerators + PARAMS ((FILE *, const struct accelerator *)); +static void write_rc_cursor PARAMS ((FILE *, const struct cursor *)); +static void write_rc_group_cursor + PARAMS ((FILE *, const struct group_cursor *)); +static void write_rc_dialog PARAMS ((FILE *, const struct dialog *)); +static void write_rc_dialog_control + PARAMS ((FILE *, const struct dialog_control *)); +static void write_rc_fontdir PARAMS ((FILE *, const struct fontdir *)); +static void write_rc_group_icon PARAMS ((FILE *, const struct group_icon *)); +static void write_rc_menu PARAMS ((FILE *, const struct menu *, int)); +static void write_rc_menuitems + PARAMS ((FILE *, const struct menuitem *, int, int)); +static void write_rc_rcdata PARAMS ((FILE *, const struct rcdata_item *, int)); +static void write_rc_stringtable + PARAMS ((FILE *, const struct res_id *, const struct stringtable *)); +static void write_rc_versioninfo PARAMS ((FILE *, const struct versioninfo *)); +static void write_rc_filedata + PARAMS ((FILE *, unsigned long, const unsigned char *)); + +/* Indent a given number of spaces. */ + +static void +indent (e, c) + FILE *e; + int c; +{ + int i; + + for (i = 0; i < c; i++) + putc (' ', e); +} + +/* Dump the resources we have read in the format of an rc file. + + Actually, we don't use the format of an rc file, because it's way + too much of a pain--for example, we'd have to write icon resources + into a file and refer to that file. We just generate a readable + format that kind of looks like an rc file, and is useful for + understanding the contents of a resource file. Someday we may want + to generate an rc file which the rc compiler can read; if that day + comes, this code will have to be fixed up. */ + +void +write_rc_file (filename, resources) + const char *filename; + const struct res_directory *resources; +{ + FILE *e; + int language; + + if (filename == NULL) + e = stdout; + else + { + e = fopen (filename, FOPEN_WT); + if (e == NULL) + fatal (_("can't open `%s' for output: %s"), filename, strerror (errno)); + } + + language = -1; + write_rc_directory (e, resources, (const struct res_id *) NULL, + (const struct res_id *) NULL, &language, 1); +} + +/* Write out a directory. E is the file to write to. RD is the + directory. TYPE is a pointer to the level 1 ID which serves as the + resource type. NAME is a pointer to the level 2 ID which serves as + an individual resource name. LANGUAGE is a pointer to the current + language. LEVEL is the level in the tree. */ + +static void +write_rc_directory (e, rd, type, name, language, level) + FILE *e; + const struct res_directory *rd; + const struct res_id *type; + const struct res_id *name; + int *language; + int level; +{ + const struct res_entry *re; + + /* Print out some COFF information that rc files can't represent. */ + + if (rd->time != 0) + fprintf (e, "// Time stamp: %lu\n", rd->time); + if (rd->characteristics != 0) + fprintf (e, "// Characteristics: %lu\n", rd->characteristics); + if (rd->major != 0 || rd->minor != 0) + fprintf (e, "// Version: %d %d\n", rd->major, rd->minor); + + for (re = rd->entries; re != NULL; re = re->next) + { + switch (level) + { + case 1: + /* If we're at level 1, the key of this resource is the + type. This normally duplicates the information we have + stored with the resource itself, but we need to remember + the type if this is a user define resource type. */ + type = &re->id; + break; + + case 2: + /* If we're at level 2, the key of this resource is the name + we are going to use in the rc printout. */ + name = &re->id; + break; + + case 3: + /* If we're at level 3, then this key represents a language. + Use it to update the current language. */ + if (! re->id.named + && re->id.u.id != (unsigned long) (unsigned int) *language + && (re->id.u.id & 0xffff) == re->id.u.id) + { + fprintf (e, "LANGUAGE %lu, %lu\n", + re->id.u.id & 0xff, (re->id.u.id >> 8) & 0xff); + *language = re->id.u.id; + } + break; + + default: + break; + } + + if (re->subdir) + write_rc_subdir (e, re, type, name, language, level); + else + { + if (level == 3) + { + /* This is the normal case: the three levels are + TYPE/NAME/LANGUAGE. NAME will have been set at level + 2, and represents the name to use. We probably just + set LANGUAGE, and it will probably match what the + resource itself records if anything. */ + write_rc_resource (e, type, name, re->u.res, language); + } + else + { + fprintf (e, "// Resource at unexpected level %d\n", level); + write_rc_resource (e, type, (struct res_id *) NULL, re->u.res, + language); + } + } + } +} + +/* Write out a subdirectory entry. E is the file to write to. RE is + the subdirectory entry. TYPE and NAME are pointers to higher level + IDs, or NULL. LANGUAGE is a pointer to the current language. + LEVEL is the level in the tree. */ + +static void +write_rc_subdir (e, re, type, name, language, level) + FILE *e; + const struct res_entry *re; + const struct res_id *type; + const struct res_id *name; + int *language; + int level; +{ + fprintf (e, "\n"); + switch (level) + { + case 1: + fprintf (e, "// Type: "); + if (re->id.named) + res_id_print (e, re->id, 1); + else + { + const char *s; + + switch (re->id.u.id) + { + case RT_CURSOR: s = "cursor"; break; + case RT_BITMAP: s = "bitmap"; break; + case RT_ICON: s = "icon"; break; + case RT_MENU: s = "menu"; break; + case RT_DIALOG: s = "dialog"; break; + case RT_STRING: s = "stringtable"; break; + case RT_FONTDIR: s = "fontdir"; break; + case RT_FONT: s = "font"; break; + case RT_ACCELERATOR: s = "accelerators"; break; + case RT_RCDATA: s = "rcdata"; break; + case RT_MESSAGETABLE: s = "messagetable"; break; + case RT_GROUP_CURSOR: s = "group cursor"; break; + case RT_GROUP_ICON: s = "group icon"; break; + case RT_VERSION: s = "version"; break; + case RT_DLGINCLUDE: s = "dlginclude"; break; + case RT_PLUGPLAY: s = "plugplay"; break; + case RT_VXD: s = "vxd"; break; + case RT_ANICURSOR: s = "anicursor"; break; + case RT_ANIICON: s = "aniicon"; break; + default: s = NULL; break; + } + + if (s != NULL) + fprintf (e, "%s", s); + else + res_id_print (e, re->id, 1); + } + fprintf (e, "\n"); + break; + + case 2: + fprintf (e, "// Name: "); + res_id_print (e, re->id, 1); + fprintf (e, "\n"); + break; + + case 3: + fprintf (e, "// Language: "); + res_id_print (e, re->id, 1); + fprintf (e, "\n"); + break; + + default: + fprintf (e, "// Level %d: ", level); + res_id_print (e, re->id, 1); + fprintf (e, "\n"); + } + + write_rc_directory (e, re->u.dir, type, name, language, level + 1); +} + +/* Write out a single resource. E is the file to write to. TYPE is a + pointer to the type of the resource. NAME is a pointer to the name + of the resource; it will be NULL if there is a level mismatch. RES + is the resource data. LANGUAGE is a pointer to the current + language. */ + +static void +write_rc_resource (e, type, name, res, language) + FILE *e; + const struct res_id *type; + const struct res_id *name; + const struct res_resource *res; + int *language; +{ + const char *s; + int rt; + int menuex = 0; + + fprintf (e, "\n"); + + switch (res->type) + { + default: + abort (); + + case RES_TYPE_ACCELERATOR: + s = "ACCELERATOR"; + rt = RT_ACCELERATOR; + break; + + case RES_TYPE_BITMAP: + s = "BITMAP"; + rt = RT_BITMAP; + break; + + case RES_TYPE_CURSOR: + s = "CURSOR"; + rt = RT_CURSOR; + break; + + case RES_TYPE_GROUP_CURSOR: + s = "GROUP_CURSOR"; + rt = RT_GROUP_CURSOR; + break; + + case RES_TYPE_DIALOG: + if (extended_dialog (res->u.dialog)) + s = "DIALOGEX"; + else + s = "DIALOG"; + rt = RT_DIALOG; + break; + + case RES_TYPE_FONT: + s = "FONT"; + rt = RT_FONT; + break; + + case RES_TYPE_FONTDIR: + s = "FONTDIR"; + rt = RT_FONTDIR; + break; + + case RES_TYPE_ICON: + s = "ICON"; + rt = RT_ICON; + break; + + case RES_TYPE_GROUP_ICON: + s = "GROUP_ICON"; + rt = RT_GROUP_ICON; + break; + + case RES_TYPE_MENU: + if (extended_menu (res->u.menu)) + { + s = "MENUEX"; + menuex = 1; + } + else + { + s = "MENU"; + menuex = 0; + } + rt = RT_MENU; + break; + + case RES_TYPE_MESSAGETABLE: + s = "MESSAGETABLE"; + rt = RT_MESSAGETABLE; + break; + + case RES_TYPE_RCDATA: + s = "RCDATA"; + rt = RT_RCDATA; + break; + + case RES_TYPE_STRINGTABLE: + s = "STRINGTABLE"; + rt = RT_STRING; + break; + + case RES_TYPE_USERDATA: + s = NULL; + rt = 0; + break; + + case RES_TYPE_VERSIONINFO: + s = "VERSIONINFO"; + rt = RT_VERSION; + break; + } + + if (rt != 0 + && type != NULL + && (type->named || type->u.id != (unsigned long) rt)) + { + fprintf (e, "// Unexpected resource type mismatch: "); + res_id_print (e, *type, 1); + fprintf (e, " != %d", rt); + } + + if (res->coff_info.codepage != 0) + fprintf (e, "// Code page: %lu\n", res->coff_info.codepage); + if (res->coff_info.reserved != 0) + fprintf (e, "// COFF reserved value: %lu\n", res->coff_info.reserved); + + if (name != NULL) + res_id_print (e, *name, 0); + else + fprintf (e, "??Unknown-Name??"); + + fprintf (e, " "); + if (s != NULL) + fprintf (e, "%s", s); + else if (type != NULL) + res_id_print (e, *type, 0); + else + fprintf (e, "??Unknown-Type??"); + + if (res->res_info.memflags != 0) + { + if ((res->res_info.memflags & MEMFLAG_MOVEABLE) != 0) + fprintf (e, " MOVEABLE"); + if ((res->res_info.memflags & MEMFLAG_PURE) != 0) + fprintf (e, " PURE"); + if ((res->res_info.memflags & MEMFLAG_PRELOAD) != 0) + fprintf (e, " PRELOAD"); + if ((res->res_info.memflags & MEMFLAG_DISCARDABLE) != 0) + fprintf (e, " DISCARDABLE"); + } + + if (res->type == RES_TYPE_DIALOG) + { + fprintf (e, " %d, %d, %d, %d", res->u.dialog->x, res->u.dialog->y, + res->u.dialog->width, res->u.dialog->height); + if (res->u.dialog->ex != NULL + && res->u.dialog->ex->help != 0) + fprintf (e, ", %lu", res->u.dialog->ex->help); + } + + fprintf (e, "\n"); + + if ((res->res_info.language != 0 && res->res_info.language != *language) + || res->res_info.characteristics != 0 + || res->res_info.version != 0) + { + int modifiers; + + switch (res->type) + { + case RES_TYPE_ACCELERATOR: + case RES_TYPE_DIALOG: + case RES_TYPE_MENU: + case RES_TYPE_RCDATA: + case RES_TYPE_STRINGTABLE: + modifiers = 1; + break; + + default: + modifiers = 0; + break; + } + + if (res->res_info.language != 0 && res->res_info.language != *language) + fprintf (e, "%sLANGUAGE %d, %d\n", + modifiers ? "// " : "", + res->res_info.language & 0xff, + (res->res_info.language >> 8) & 0xff); + if (res->res_info.characteristics != 0) + fprintf (e, "%sCHARACTERISTICS %lu\n", + modifiers ? "// " : "", + res->res_info.characteristics); + if (res->res_info.version != 0) + fprintf (e, "%sVERSION %lu\n", + modifiers ? "// " : "", + res->res_info.version); + } + + switch (res->type) + { + default: + abort (); + + case RES_TYPE_ACCELERATOR: + write_rc_accelerators (e, res->u.acc); + break; + + case RES_TYPE_CURSOR: + write_rc_cursor (e, res->u.cursor); + break; + + case RES_TYPE_GROUP_CURSOR: + write_rc_group_cursor (e, res->u.group_cursor); + break; + + case RES_TYPE_DIALOG: + write_rc_dialog (e, res->u.dialog); + break; + + case RES_TYPE_FONTDIR: + write_rc_fontdir (e, res->u.fontdir); + break; + + case RES_TYPE_GROUP_ICON: + write_rc_group_icon (e, res->u.group_icon); + break; + + case RES_TYPE_MENU: + write_rc_menu (e, res->u.menu, menuex); + break; + + case RES_TYPE_RCDATA: + write_rc_rcdata (e, res->u.rcdata, 0); + break; + + case RES_TYPE_STRINGTABLE: + write_rc_stringtable (e, name, res->u.stringtable); + break; + + case RES_TYPE_USERDATA: + write_rc_rcdata (e, res->u.userdata, 0); + break; + + case RES_TYPE_VERSIONINFO: + write_rc_versioninfo (e, res->u.versioninfo); + break; + + case RES_TYPE_BITMAP: + case RES_TYPE_FONT: + case RES_TYPE_ICON: + case RES_TYPE_MESSAGETABLE: + write_rc_filedata (e, res->u.data.length, res->u.data.data); + break; + } +} + +/* Write out accelerator information. */ + +static void +write_rc_accelerators (e, accelerators) + FILE *e; + const struct accelerator *accelerators; +{ + const struct accelerator *acc; + + fprintf (e, "BEGIN\n"); + for (acc = accelerators; acc != NULL; acc = acc->next) + { + int printable; + + fprintf (e, " "); + + if ((acc->key & 0x7f) == acc->key + && isprint ((unsigned char) acc->key) + && (acc->flags & ACC_VIRTKEY) == 0) + { + fprintf (e, "\"%c\"", acc->key); + printable = 1; + } + else + { + fprintf (e, "%d", acc->key); + printable = 0; + } + + fprintf (e, ", %d", acc->id); + + if (! printable) + { + if ((acc->flags & ACC_VIRTKEY) != 0) + fprintf (e, ", VIRTKEY"); + else + fprintf (e, ", ASCII"); + } + + if ((acc->flags & ACC_SHIFT) != 0) + fprintf (e, ", SHIFT"); + if ((acc->flags & ACC_CONTROL) != 0) + fprintf (e, ", CONTROL"); + if ((acc->flags & ACC_ALT) != 0) + fprintf (e, ", ALT"); + + fprintf (e, "\n"); + } + + fprintf (e, "END\n"); +} + +/* Write out cursor information. This would normally be in a separate + file, which the rc file would include. */ + +static void +write_rc_cursor (e, cursor) + FILE *e; + const struct cursor *cursor; +{ + fprintf (e, "// Hotspot: x: %d; y: %d\n", cursor->xhotspot, + cursor->yhotspot); + write_rc_filedata (e, cursor->length, cursor->data); +} + +/* Write out group cursor data. This would normally be built from the + cursor data. */ + +static void +write_rc_group_cursor (e, group_cursor) + FILE *e; + const struct group_cursor *group_cursor; +{ + const struct group_cursor *gc; + + for (gc = group_cursor; gc != NULL; gc = gc->next) + { + fprintf (e, "// width: %d; height %d; planes %d; bits %d\n", + gc->width, gc->height, gc->planes, gc->bits); + fprintf (e, "// data bytes: %lu; index: %d\n", + gc->bytes, gc->index); + } +} + +/* Write dialog data. */ + +static void +write_rc_dialog (e, dialog) + FILE *e; + const struct dialog *dialog; +{ + const struct dialog_control *control; + + if (dialog->style != 0) + fprintf (e, "STYLE 0x%lx\n", dialog->style); + if (dialog->exstyle != 0) + fprintf (e, "EXSTYLE 0x%lx\n", dialog->exstyle); + if ((dialog->class.named && dialog->class.u.n.length > 0) + || dialog->class.u.id != 0) + { + fprintf (e, "CLASS "); + res_id_print (e, dialog->class, 0); + fprintf (e, "\n"); + } + if (dialog->caption != NULL) + { + fprintf (e, "CAPTION \""); + unicode_print (e, dialog->caption, -1); + fprintf (e, "\"\n"); + } + if ((dialog->menu.named && dialog->menu.u.n.length > 0) + || dialog->menu.u.id != 0) + { + fprintf (e, "MENU "); + res_id_print (e, dialog->menu, 0); + fprintf (e, "\n"); + } + if (dialog->font != NULL) + { + fprintf (e, "FONT %d, \"", dialog->pointsize); + unicode_print (e, dialog->font, -1); + fprintf (e, "\""); + if (dialog->ex != NULL + && (dialog->ex->weight != 0 || dialog->ex->italic != 0)) + fprintf (e, ", %d, %d", dialog->ex->weight, dialog->ex->italic); + fprintf (e, "\n"); + } + + fprintf (e, "BEGIN\n"); + + for (control = dialog->controls; control != NULL; control = control->next) + write_rc_dialog_control (e, control); + + fprintf (e, "END\n"); +} + +/* For each predefined control keyword, this table provides the class + and the style. */ + +struct control_info +{ + const char *name; + unsigned short class; + unsigned long style; +}; + +static const struct control_info control_info[] = +{ + { "AUTO3STATE", CTL_BUTTON, BS_AUTO3STATE }, + { "AUTOCHECKBOX", CTL_BUTTON, BS_AUTOCHECKBOX }, + { "AUTORADIOBUTTON", CTL_BUTTON, BS_AUTORADIOBUTTON }, + { "CHECKBOX", CTL_BUTTON, BS_CHECKBOX }, + { "COMBOBOX", CTL_COMBOBOX, (unsigned long) -1 }, + { "CTEXT", CTL_STATIC, SS_CENTER }, + { "DEFPUSHBUTTON", CTL_BUTTON, BS_DEFPUSHBUTTON }, + { "EDITTEXT", CTL_EDIT, (unsigned long) -1 }, + { "GROUPBOX", CTL_BUTTON, BS_GROUPBOX }, + { "ICON", CTL_STATIC, SS_ICON }, + { "LISTBOX", CTL_LISTBOX, (unsigned long) -1 }, + { "LTEXT", CTL_STATIC, SS_LEFT }, + { "PUSHBOX", CTL_BUTTON, BS_PUSHBOX }, + { "PUSHBUTTON", CTL_BUTTON, BS_PUSHBUTTON }, + { "RADIOBUTTON", CTL_BUTTON, BS_RADIOBUTTON }, + { "RTEXT", CTL_STATIC, SS_RIGHT }, + { "SCROLLBAR", CTL_SCROLLBAR, (unsigned long) -1 }, + { "STATE3", CTL_BUTTON, BS_3STATE }, + /* It's important that USERBUTTON come after all the other button + types, so that it won't be matched too early. */ + { "USERBUTTON", CTL_BUTTON, (unsigned long) -1 }, + { NULL, 0, 0 } +}; + +/* Write a dialog control. */ + +static void +write_rc_dialog_control (e, control) + FILE *e; + const struct dialog_control *control; +{ + const struct control_info *ci; + + fprintf (e, " "); + + if (control->class.named) + ci = NULL; + else + { + for (ci = control_info; ci->name != NULL; ++ci) + if (ci->class == control->class.u.id + && (ci->style == (unsigned long) -1 + || ci->style == (control->style & 0xff))) + break; + } + if (ci == NULL) + fprintf (e, "CONTROL"); + else if (ci->name != NULL) + fprintf (e, "%s", ci->name); + else + fprintf (e, "CONTROL"); + + if (control->text.named || control->text.u.id != 0) + { + fprintf (e, " "); + res_id_print (e, control->text, 1); + fprintf (e, ","); + } + + fprintf (e, " %d, ", control->id); + + if (ci == NULL) + { + if (control->class.named) + fprintf (e, "\""); + res_id_print (e, control->class, 0); + if (control->class.named) + fprintf (e, "\""); + fprintf (e, ", 0x%lx, ", control->style); + } + + fprintf (e, "%d, %d", control->x, control->y); + + if (control->style != SS_ICON + || control->exstyle != 0 + || control->width != 0 + || control->height != 0 + || control->help != 0) + { + fprintf (e, ", %d, %d", control->width, control->height); + + /* FIXME: We don't need to print the style if it is the default. + More importantly, in certain cases we actually need to turn + off parts of the forced style, by using NOT. */ + fprintf (e, ", 0x%lx", control->style); + + if (control->exstyle != 0 || control->help != 0) + fprintf (e, ", 0x%lx, %lu", control->exstyle, control->help); + } + + fprintf (e, "\n"); + + if (control->data != NULL) + write_rc_rcdata (e, control->data, 2); +} + +/* Write out font directory data. This would normally be built from + the font data. */ + +static void +write_rc_fontdir (e, fontdir) + FILE *e; + const struct fontdir *fontdir; +{ + const struct fontdir *fc; + + for (fc = fontdir; fc != NULL; fc = fc->next) + { + fprintf (e, "// Font index: %d\n", fc->index); + write_rc_filedata (e, fc->length, fc->data); + } +} + +/* Write out group icon data. This would normally be built from the + icon data. */ + +static void +write_rc_group_icon (e, group_icon) + FILE *e; + const struct group_icon *group_icon; +{ + const struct group_icon *gi; + + for (gi = group_icon; gi != NULL; gi = gi->next) + { + fprintf (e, "// width: %d; height %d; colors: %d; planes %d; bits %d\n", + gi->width, gi->height, gi->colors, gi->planes, gi->bits); + fprintf (e, "// data bytes: %lu; index: %d\n", + gi->bytes, gi->index); + } +} + +/* Write out a menu resource. */ + +static void +write_rc_menu (e, menu, menuex) + FILE *e; + const struct menu *menu; + int menuex; +{ + if (menu->help != 0) + fprintf (e, "// Help ID: %lu\n", menu->help); + write_rc_menuitems (e, menu->items, menuex, 0); +} + +/* Write out menuitems. */ + +static void +write_rc_menuitems (e, menuitems, menuex, ind) + FILE *e; + const struct menuitem *menuitems; + int menuex; + int ind; +{ + const struct menuitem *mi; + + indent (e, ind); + fprintf (e, "BEGIN\n"); + + for (mi = menuitems; mi != NULL; mi = mi->next) + { + indent (e, ind + 2); + + if (mi->popup == NULL) + fprintf (e, "MENUITEM"); + else + fprintf (e, "POPUP"); + + if (! menuex + && mi->popup == NULL + && mi->text == NULL + && mi->type == 0 + && mi->id == 0) + { + fprintf (e, " SEPARATOR\n"); + continue; + } + + if (mi->text == NULL) + fprintf (e, " \"\""); + else + { + fprintf (e, " \""); + unicode_print (e, mi->text, -1); + fprintf (e, "\""); + } + + if (! menuex) + { + if (mi->popup == NULL) + fprintf (e, ", %d", mi->id); + + if ((mi->type & MENUITEM_CHECKED) != 0) + fprintf (e, ", CHECKED"); + if ((mi->type & MENUITEM_GRAYED) != 0) + fprintf (e, ", GRAYED"); + if ((mi->type & MENUITEM_HELP) != 0) + fprintf (e, ", HELP"); + if ((mi->type & MENUITEM_INACTIVE) != 0) + fprintf (e, ", INACTIVE"); + if ((mi->type & MENUITEM_MENUBARBREAK) != 0) + fprintf (e, ", MENUBARBREAK"); + if ((mi->type & MENUITEM_MENUBREAK) != 0) + fprintf (e, ", MENUBREAK"); + } + else + { + if (mi->id != 0 || mi->type != 0 || mi->state != 0 || mi->help != 0) + { + fprintf (e, ", %d", mi->id); + if (mi->type != 0 || mi->state != 0 || mi->help != 0) + { + fprintf (e, ", %lu", mi->type); + if (mi->state != 0 || mi->help != 0) + { + fprintf (e, ", %lu", mi->state); + if (mi->help != 0) + fprintf (e, ", %lu", mi->help); + } + } + } + } + + fprintf (e, "\n"); + + if (mi->popup != NULL) + write_rc_menuitems (e, mi->popup, menuex, ind + 2); + } + + indent (e, ind); + fprintf (e, "END\n"); +} + +/* Write out an rcdata resource. This is also used for other types of + resources that need to print arbitrary data. */ + +static void +write_rc_rcdata (e, rcdata, ind) + FILE *e; + const struct rcdata_item *rcdata; + int ind; +{ + const struct rcdata_item *ri; + + indent (e, ind); + fprintf (e, "BEGIN\n"); + + for (ri = rcdata; ri != NULL; ri = ri->next) + { + if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0) + continue; + + indent (e, ind + 2); + + switch (ri->type) + { + default: + abort (); + + case RCDATA_WORD: + fprintf (e, "%d", ri->u.word); + break; + + case RCDATA_DWORD: + fprintf (e, "%luL", ri->u.dword); + break; + + case RCDATA_STRING: + { + const char *s; + unsigned long i; + + fprintf (e, "\""); + s = ri->u.string.s; + for (i = 0; i < ri->u.string.length; i++) + { + if (isprint ((unsigned char) *s)) + putc (*s, e); + else + fprintf (e, "\\%03o", *s); + } + fprintf (e, "\""); + break; + } + + case RCDATA_WSTRING: + fprintf (e, "L\""); + unicode_print (e, ri->u.wstring.w, ri->u.wstring.length); + fprintf (e, "\""); + break; + + case RCDATA_BUFFER: + { + unsigned long i; + int first; + + /* Assume little endian data. */ + + first = 1; + for (i = 0; i + 3 < ri->u.buffer.length; i += 4) + { + unsigned long l; + + l = ((((((ri->u.buffer.data[i + 3] << 8) + | ri->u.buffer.data[i + 2]) << 8) + | ri->u.buffer.data[i + 1]) << 8) + | ri->u.buffer.data[i]); + if (first) + first = 0; + else + { + fprintf (e, ",\n"); + indent (e, ind + 2); + } + fprintf (e, "%luL", l); + } + + if (i + 1 < ri->u.buffer.length) + { + int i; + + i = (ri->u.buffer.data[i + 1] << 8) | ri->u.buffer.data[i]; + if (first) + first = 0; + else + { + fprintf (e, ",\n"); + indent (e, ind + 2); + } + fprintf (e, "%d", i); + i += 2; + } + + if (i < ri->u.buffer.length) + { + if (first) + first = 0; + else + { + fprintf (e, ",\n"); + indent (e, ind + 2); + } + if ((ri->u.buffer.data[i] & 0x7f) == ri->u.buffer.data[i] + && isprint (ri->u.buffer.data[i])) + fprintf (e, "\"%c\"", ri->u.buffer.data[i]); + else + fprintf (e, "\"\%03o\"", ri->u.buffer.data[i]); + } + + break; + } + } + + if (ri->next != NULL) + fprintf (e, ","); + fprintf (e, "\n"); + } + + indent (e, ind); + fprintf (e, "END\n"); +} + +/* Write out a stringtable resource. */ + +static void +write_rc_stringtable (e, name, stringtable) + FILE *e; + const struct res_id *name; + const struct stringtable *stringtable; +{ + unsigned long offset; + int i; + + if (name != NULL && ! name->named) + offset = (name->u.id - 1) << 4; + else + { + fprintf (e, "// %s string table name\n", + name == NULL ? "Missing" : "Invalid"); + offset = 0; + } + + fprintf (e, "BEGIN\n"); + + for (i = 0; i < 16; i++) + { + if (stringtable->strings[i].length != 0) + { + fprintf (e, " %lu, \"", offset + i); + unicode_print (e, stringtable->strings[i].string, + stringtable->strings[i].length); + fprintf (e, "\"\n"); + } + } + + fprintf (e, "END\n"); +} + +/* Write out a versioninfo resource. */ + +static void +write_rc_versioninfo (e, versioninfo) + FILE *e; + const struct versioninfo *versioninfo; +{ + const struct fixed_versioninfo *f; + const struct ver_info *vi; + + f = versioninfo->fixed; + if (f->file_version_ms != 0 || f->file_version_ls != 0) + fprintf (e, " FILEVERSION %lu, %lu, %lu, %lu\n", + (f->file_version_ms >> 16) & 0xffff, + f->file_version_ms & 0xffff, + (f->file_version_ls >> 16) & 0xffff, + f->file_version_ls & 0xffff); + if (f->product_version_ms != 0 || f->product_version_ls != 0) + fprintf (e, " PRODUCTVERSION %lu, %lu, %lu, %lu\n", + (f->product_version_ms >> 16) & 0xffff, + f->product_version_ms & 0xffff, + (f->product_version_ls >> 16) & 0xffff, + f->product_version_ls & 0xffff); + if (f->file_flags_mask != 0) + fprintf (e, " FILEFLAGSMASK 0x%lx\n", f->file_flags_mask); + if (f->file_flags != 0) + fprintf (e, " FILEFLAGS 0x%lx\n", f->file_flags); + if (f->file_os != 0) + fprintf (e, " FILEOS 0x%lx\n", f->file_os); + if (f->file_type != 0) + fprintf (e, " FILETYPE 0x%lx\n", f->file_type); + if (f->file_subtype != 0) + fprintf (e, " FILESUBTYPE 0x%lx\n", f->file_subtype); + if (f->file_date_ms != 0 || f->file_date_ls != 0) + fprintf (e, "// Date: %lu, %lu\n", f->file_date_ms, f->file_date_ls); + + fprintf (e, "BEGIN\n"); + + for (vi = versioninfo->var; vi != NULL; vi = vi->next) + { + switch (vi->type) + { + case VERINFO_STRING: + { + const struct ver_stringinfo *vs; + + fprintf (e, " BLOCK \"StringFileInfo\"\n"); + fprintf (e, " BEGIN\n"); + fprintf (e, " BLOCK \""); + unicode_print (e, vi->u.string.language, -1); + fprintf (e, "\"\n"); + fprintf (e, " BEGIN\n"); + + for (vs = vi->u.string.strings; vs != NULL; vs = vs->next) + { + fprintf (e, " VALUE \""); + unicode_print (e, vs->key, -1); + fprintf (e, "\", \""); + unicode_print (e, vs->value, -1); + fprintf (e, "\"\n"); + } + + fprintf (e, " END\n"); + fprintf (e, " END\n"); + break; + } + + case VERINFO_VAR: + { + const struct ver_varinfo *vv; + + fprintf (e, " BLOCK \"VarFileInfo\"\n"); + fprintf (e, " BEGIN\n"); + fprintf (e, " VALUE \""); + unicode_print (e, vi->u.var.key, -1); + fprintf (e, "\""); + + for (vv = vi->u.var.var; vv != NULL; vv = vv->next) + fprintf (e, ", 0x%x, %d", (unsigned int) vv->language, + vv->charset); + + fprintf (e, "\n END\n"); + + break; + } + } + } + + fprintf (e, "END\n"); +} + +/* Write out data which would normally be read from a file. */ + +static void +write_rc_filedata (e, length, data) + FILE *e; + unsigned long length; + const unsigned char *data; +{ + unsigned long i; + + for (i = 0; i + 15 < length; i += 16) + { + fprintf (e, "// %4lx: ", i); + fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x ", + data[i + 0], data[i + 1], data[i + 2], data[i + 3], + data[i + 4], data[i + 5], data[i + 6], data[i + 7]); + fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x\n", + data[i + 8], data[i + 9], data[i + 10], data[i + 11], + data[i + 12], data[i + 13], data[i + 14], data[i + 15]); + } + + if (i < length) + { + fprintf (e, "// %4lx:", i); + while (i < length) + { + fprintf (e, " %02x", data[i]); + ++i; + } + fprintf (e, "\n"); + } +} diff --git a/binutils/resres.c b/binutils/resres.c new file mode 100644 index 0000000..39264f4 --- /dev/null +++ b/binutils/resres.c @@ -0,0 +1,656 @@ +/* resres.c: read_res_file and write_res_file implementation for windres. + + Copyright 1998, 1999 Free Software Foundation, Inc. + Written by Anders Norlander <anorland@hem2.passagen.se>. + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#include "bfd.h" +#include "bucomm.h" +#include "libiberty.h" +#include "windres.h" + +#include <assert.h> +#include <time.h> + +struct res_hdr + { + unsigned long data_size; + unsigned long header_size; + }; + +static void write_res_directory + PARAMS ((const struct res_directory *, + const struct res_id *, const struct res_id *, + int *, int)); +static void write_res_resource + PARAMS ((const struct res_id *, const struct res_id *, + const struct res_resource *, int *)); +static void write_res_bin + PARAMS ((const struct res_resource *, const struct res_id *, + const struct res_id *, const struct res_res_info *)); + +static void write_res_id PARAMS ((const struct res_id *)); +static void write_res_info PARAMS ((const struct res_res_info *)); +static void write_res_data PARAMS ((const void *, size_t, int)); +static void write_res_header + PARAMS ((unsigned long, const struct res_id *, const struct res_id *, + const struct res_res_info *)); + +static int read_resource_entry PARAMS ((void)); +static void read_res_data PARAMS ((void *, size_t, int)); +static void read_res_id PARAMS ((struct res_id *)); +static unichar *read_unistring PARAMS ((int *)); +static void skip_null_resource PARAMS ((void)); + +static unsigned long get_id_size PARAMS ((const struct res_id *)); +static void res_align_file PARAMS ((void)); + +static void + res_add_resource + PARAMS ((struct res_resource *, const struct res_id *, + const struct res_id *, int, int)); + +void + res_append_resource + PARAMS ((struct res_directory **, struct res_resource *, + int, const struct res_id *, int)); + +static struct res_directory *resources = NULL; + +static FILE *fres; +static const char *filename; + +extern char *program_name; + +/* Read resource file */ +struct res_directory * +read_res_file (fn) + const char *fn; +{ + filename = fn; + fres = fopen (filename, "rb"); + if (fres == NULL) + fatal ("can't open `%s' for output: %s", filename, strerror (errno)); + + skip_null_resource (); + + while (read_resource_entry ()) + ; + + fclose (fres); + + return resources; +} + +/* Write resource file */ +void +write_res_file (fn, resdir) + const char *fn; + const struct res_directory *resdir; +{ + int language; + static const unsigned char sign[] = + {0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + long fpos; + + filename = fn; + + fres = fopen (filename, "wb"); + if (fres == NULL) + fatal ("can't open `%s' for output: %s", filename, strerror (errno)); + + /* Write 32 bit resource signature */ + write_res_data (sign, sizeof (sign), 1); + + /* write resources */ + + language = -1; + write_res_directory (resdir, (const struct res_id *) NULL, + (const struct res_id *) NULL, &language, 1); + + /* end file on DWORD boundary */ + fpos = ftell (fres); + if (fpos % 4) + write_res_data (sign, fpos % 4, 1); + + fclose (fres); +} + +/* Read a resource entry, returns 0 when all resources are read */ +static int +read_resource_entry (void) +{ + struct res_id type; + struct res_id name; + struct res_res_info resinfo; + struct res_hdr reshdr; + long version; + void *buff; + + struct res_resource *r; + + res_align_file (); + + /* Read header */ + if (fread (&reshdr, sizeof (reshdr), 1, fres) != 1) + return 0; + + /* read resource type */ + read_res_id (&type); + /* read resource id */ + read_res_id (&name); + + res_align_file (); + + /* Read additional resource header */ + read_res_data (&resinfo.version, sizeof (resinfo.version), 1); + read_res_data (&resinfo.memflags, sizeof (resinfo.memflags), 1); + read_res_data (&resinfo.language, sizeof (resinfo.language), 1); + read_res_data (&version, sizeof (version), 1); + read_res_data (&resinfo.characteristics, sizeof (resinfo.characteristics), 1); + + res_align_file (); + + /* Allocate buffer for data */ + buff = res_alloc (reshdr.data_size); + /* Read data */ + read_res_data (buff, reshdr.data_size, 1); + /* Convert binary data to resource */ + r = bin_to_res (type, buff, reshdr.data_size, 0); + r->res_info = resinfo; + /* Add resource to resource directory */ + res_add_resource (r, &type, &name, resinfo.language, 0); + + return 1; +} + +/* write resource directory to binary resource file */ +static void +write_res_directory (rd, type, name, language, level) + const struct res_directory *rd; + const struct res_id *type; + const struct res_id *name; + int *language; + int level; +{ + const struct res_entry *re; + + for (re = rd->entries; re != NULL; re = re->next) + { + switch (level) + { + case 1: + /* If we're at level 1, the key of this resource is the + type. This normally duplicates the information we have + stored with the resource itself, but we need to remember + the type if this is a user define resource type. */ + type = &re->id; + break; + + case 2: + /* If we're at level 2, the key of this resource is the name + we are going to use in the rc printout. */ + name = &re->id; + break; + + case 3: + /* If we're at level 3, then this key represents a language. + Use it to update the current language. */ + if (!re->id.named + && re->id.u.id != *language + && (re->id.u.id & 0xffff) == re->id.u.id) + { + *language = re->id.u.id; + } + break; + + default: + break; + } + + if (re->subdir) + write_res_directory (re->u.dir, type, name, language, level + 1); + else + { + if (level == 3) + { + /* This is the normal case: the three levels are + TYPE/NAME/LANGUAGE. NAME will have been set at level + 2, and represents the name to use. We probably just + set LANGUAGE, and it will probably match what the + resource itself records if anything. */ + write_res_resource (type, name, re->u.res, language); + } + else + { + fprintf (stderr, "// Resource at unexpected level %d\n", level); + write_res_resource (type, (struct res_id *) NULL, re->u.res, + language); + } + } + } + +} + +static void +write_res_resource (type, name, res, language) + const struct res_id *type; + const struct res_id *name; + const struct res_resource *res; + int *language; +{ + int rt; + + switch (res->type) + { + default: + abort (); + + case RES_TYPE_ACCELERATOR: + rt = RT_ACCELERATOR; + break; + + case RES_TYPE_BITMAP: + rt = RT_BITMAP; + break; + + case RES_TYPE_CURSOR: + rt = RT_CURSOR; + break; + + case RES_TYPE_GROUP_CURSOR: + rt = RT_GROUP_CURSOR; + break; + + case RES_TYPE_DIALOG: + rt = RT_DIALOG; + break; + + case RES_TYPE_FONT: + rt = RT_FONT; + break; + + case RES_TYPE_FONTDIR: + rt = RT_FONTDIR; + break; + + case RES_TYPE_ICON: + rt = RT_ICON; + break; + + case RES_TYPE_GROUP_ICON: + rt = RT_GROUP_ICON; + break; + + case RES_TYPE_MENU: + rt = RT_MENU; + break; + + case RES_TYPE_MESSAGETABLE: + rt = RT_MESSAGETABLE; + break; + + case RES_TYPE_RCDATA: + rt = RT_RCDATA; + break; + + case RES_TYPE_STRINGTABLE: + rt = RT_STRING; + break; + + case RES_TYPE_USERDATA: + rt = 0; + break; + + case RES_TYPE_VERSIONINFO: + rt = RT_VERSION; + break; + } + + if (rt != 0 + && type != NULL + && (type->named || type->u.id != rt)) + { + fprintf (stderr, "// Unexpected resource type mismatch: "); + res_id_print (stderr, *type, 1); + fprintf (stderr, " != %d", rt); + abort (); + } + + write_res_bin (res, type, name, &res->res_info); + return; +} + +/* Write a resource in binary resource format */ +static void +write_res_bin (res, type, name, resinfo) + const struct res_resource *res; + const struct res_id *type; + const struct res_id *name; + const struct res_res_info *resinfo; +{ + unsigned long datasize = 0; + const struct bindata *bin_rep, *data; + + bin_rep = res_to_bin (res, 0); + for (data = bin_rep; data != NULL; data = data->next) + datasize += data->length; + + write_res_header (datasize, type, name, resinfo); + + for (data = bin_rep; data != NULL; data = data->next) + write_res_data (data->data, data->length, 1); +} + +/* Get number of bytes needed to store an id in binary format */ +static unsigned long +get_id_size (id) + const struct res_id *id; +{ + if (id->named) + return sizeof (unichar) * (id->u.n.length + 1); + else + return sizeof (unichar) * 2; +} + +/* Write a resource header */ +static void +write_res_header (datasize, type, name, resinfo) + unsigned long datasize; + const struct res_id *type; + const struct res_id *name; + const struct res_res_info *resinfo; +{ + struct res_hdr reshdr; + reshdr.data_size = datasize; + reshdr.header_size = 24 + get_id_size (type) + get_id_size (name); + + res_align_file (); + write_res_data (&reshdr, sizeof (reshdr), 1); + write_res_id (type); + write_res_id (name); + + res_align_file (); + + write_res_info (resinfo); + res_align_file (); +} + + +/* Write data to file, abort on failure */ +static void +write_res_data (data, size, count) + const void *data; + size_t size; + int count; +{ + if (fwrite (data, size, count, fres) != count) + fatal ("%s: %s: could not write to file", program_name, filename); +} + +/* Read data from file, abort on failure */ +static void +read_res_data (data, size, count) + void *data; + size_t size; + int count; +{ + if (fread (data, size, count, fres) != count) + fatal ("%s: %s: unexpected end of file", program_name, filename); +} + +/* Write a resource id */ +static void +write_res_id (id) + const struct res_id *id; +{ + if (id->named) + { + unsigned long len = id->u.n.length; + unichar null_term = 0; + write_res_data (id->u.n.name, len * sizeof (unichar), 1); + write_res_data (&null_term, sizeof (null_term), 1); + } + else + { + unsigned short i = 0xFFFF; + write_res_data (&i, sizeof (i), 1); + i = id->u.id; + write_res_data (&i, sizeof (i), 1); + } +} + +/* Write resource info */ +static void +write_res_info (info) + const struct res_res_info *info; +{ + write_res_data (&info->version, sizeof (info->version), 1); + write_res_data (&info->memflags, sizeof (info->memflags), 1); + write_res_data (&info->language, sizeof (info->language), 1); + write_res_data (&info->version, sizeof (info->version), 1); + write_res_data (&info->characteristics, sizeof (info->characteristics), 1); +} + +/* read a resource identifier */ +void +read_res_id (id) + struct res_id *id; +{ + unsigned short ord; + unichar *id_s = NULL; + int len; + + read_res_data (&ord, sizeof (ord), 1); + if (ord == 0xFFFF) /* an ordinal id */ + { + read_res_data (&ord, sizeof (ord), 1); + id->named = 0; + id->u.id = ord; + } + else + /* named id */ + { + if (fseek (fres, -sizeof (ord), SEEK_CUR) != 0) + fatal ("%s: %s: could not seek in file", program_name, filename); + id_s = read_unistring (&len); + id->named = 1; + id->u.n.length = len; + id->u.n.name = id_s; + } +} + +/* Read a null terminated UNICODE string */ +static unichar * +read_unistring (len) + int *len; +{ + unichar *s; + unichar c; + unichar *p; + int l; + + *len = 0; + l = 0; + + /* there are hardly any names longer than 256 characters */ + p = s = (unichar *) xmalloc (sizeof (unichar) * 256); + do + { + read_res_data (&c, sizeof (c), 1); + *p++ = c; + if (c != 0) + l++; + } + while (c != 0); + *len = l; + return s; +} + +/* align file on DWORD boundary */ +static void +res_align_file (void) +{ + if (fseek (fres, ftell (fres) % 4, SEEK_CUR) != 0) + fatal ("%s: %s: unable to align file", program_name, filename); +} + +/* Check if file is a win32 binary resource file, if so + skip past the null resource. Returns 0 if successful, -1 on + error. + */ +static void +skip_null_resource (void) +{ + struct res_hdr reshdr = + {0, 0}; + read_res_data (&reshdr, sizeof (reshdr), 1); + if ((reshdr.data_size != 0) || (reshdr.header_size != 0x20)) + goto skip_err; + + /* Subtract size of HeaderSize and DataSize */ + if (fseek (fres, reshdr.header_size - 8, SEEK_CUR) != 0) + goto skip_err; + + return; + +skip_err: + fprintf (stderr, "%s: %s: Not a valid WIN32 resource file\n", program_name, + filename); + xexit (1); +} + +/* Add a resource to resource directory */ +void +res_add_resource (r, type, id, language, dupok) + struct res_resource *r; + const struct res_id *type; + const struct res_id *id; + int language; + int dupok; +{ + struct res_id a[3]; + + a[0] = *type; + a[1] = *id; + a[2].named = 0; + a[2].u.id = language; + res_append_resource (&resources, r, 3, a, dupok); +} + +/* Append a resource to resource directory. + This is just copied from define_resource + and modified to add an existing resource. + */ +void +res_append_resource (resources, resource, cids, ids, dupok) + struct res_directory **resources; + struct res_resource *resource; + int cids; + const struct res_id *ids; + int dupok; +{ + struct res_entry *re = NULL; + int i; + + assert (cids > 0); + for (i = 0; i < cids; i++) + { + struct res_entry **pp; + + if (*resources == NULL) + { + static unsigned long timeval; + + /* Use the same timestamp for every resource created in a + single run. */ + if (timeval == 0) + timeval = time (NULL); + + *resources = ((struct res_directory *) + res_alloc (sizeof **resources)); + (*resources)->characteristics = 0; + (*resources)->time = timeval; + (*resources)->major = 0; + (*resources)->minor = 0; + (*resources)->entries = NULL; + } + + for (pp = &(*resources)->entries; *pp != NULL; pp = &(*pp)->next) + if (res_id_cmp ((*pp)->id, ids[i]) == 0) + break; + + if (*pp != NULL) + re = *pp; + else + { + re = (struct res_entry *) res_alloc (sizeof *re); + re->next = NULL; + re->id = ids[i]; + if ((i + 1) < cids) + { + re->subdir = 1; + re->u.dir = NULL; + } + else + { + re->subdir = 0; + re->u.res = NULL; + } + + *pp = re; + } + + if ((i + 1) < cids) + { + if (!re->subdir) + { + fprintf (stderr, "%s: ", program_name); + res_ids_print (stderr, i, ids); + fprintf (stderr, ": expected to be a directory\n"); + xexit (1); + } + + resources = &re->u.dir; + } + } + + if (re->subdir) + { + fprintf (stderr, "%s: ", program_name); + res_ids_print (stderr, cids, ids); + fprintf (stderr, ": expected to be a leaf\n"); + xexit (1); + } + + if (re->u.res != NULL) + { + if (dupok) + return; + + fprintf (stderr, "%s: warning: ", program_name); + res_ids_print (stderr, cids, ids); + fprintf (stderr, ": duplicate value\n"); + } + + re->u.res = resource; +} diff --git a/binutils/sanity.sh b/binutils/sanity.sh new file mode 100755 index 0000000..942cabf --- /dev/null +++ b/binutils/sanity.sh @@ -0,0 +1,50 @@ +#!/bin/sh +### quick sanity test for the binutils. +### +### This file was written and is maintained by K. Richard Pixley, +### rich@cygnus.com. + +### fail on errors +set -e + +### first arg is directory in which binaries to be tested reside. +case "$1" in +"") BIN=. ;; +*) BIN="$1" ;; +esac + +### size +for i in size objdump nm ar strip ranlib ; do + ${BIN}/size ${BIN}/$i > /dev/null +done + +### objdump +for i in size objdump nm ar strip ranlib ; do + ${BIN}/objdump -ahifdrtxsl ${BIN}/$i > /dev/null +done + +### nm +for i in size objdump nm ar strip ranlib ; do + ${BIN}/nm ${BIN}/$i > /dev/null +done + +### strip +TMPDIR=./binutils-$$ +mkdir ${TMPDIR} + +cp ${BIN}/strip ${TMPDIR}/strip + +for i in size objdump nm ar ranlib ; do + cp ${BIN}/$i ${TMPDIR}/$i + ${BIN}/strip ${TMPDIR}/$i + cp ${BIN}/$i ${TMPDIR}/$i + ${TMPDIR}/strip ${TMPDIR}/$i +done + +### ar + +### ranlib + +rm -rf ${TMPDIR} + +exit 0 diff --git a/binutils/size.1 b/binutils/size.1 new file mode 100644 index 0000000..3b19bd2 --- /dev/null +++ b/binutils/size.1 @@ -0,0 +1,161 @@ +.\" Copyright (c) 1991 Free Software Foundation +.\" See section COPYING for conditions for redistribution +.TH size 1 "5 November 1991" "cygnus support" "GNU Development Tools" +.de BP +.sp +.ti \-.2i +\(** +.. + +.SH NAME +size \- list section sizes and total size. + +.SH SYNOPSIS +.hy 0 +.na +.TP +.B size +.RB "[\|" \-A \||\| \-B \||\| \c +.BI "\-\-format=" compatibility\c +\&\|] +.RB "[\|" \-\-help "\|]" +.RB "[\|" \-d \||\| \-o \||\| \-x\c +\||\|\c +.BI "\-\-radix=" number\c +\&\|] +.RB "[\|" \c +.BI "\-\-target=" bfdname\c +\&\|] +.RB "[\|" \-V \||\| \-\-version "\|]" +.I objfile\c +\&.\|.\|. +.ad b +.hy 1 +.SH DESCRIPTION +The GNU \c +.B size\c +\& utility lists the section sizes\(em\&and the total +size\(em\&for each of the object files +.I objfile +in its argument list. +By default, one line of output is generated for each object file or each +module in an archive. + +.SH OPTIONS +.TP +.B \-A +.TP +.B \-B +.TP +.BI "\-\-format " "compatibility" +Using one of these options, you can choose whether the output from GNU +\c +.B size\c +\& resembles output from System V \c +.B size\c +\& (using `\|\c +.B \-A\c +\|', +or `\|\c +.B \-\-format=sysv\c +\|'), or Berkeley \c +.B size\c +\& (using `\|\c +.B \-B\c +\|', or +`\|\c +.B \-\-format=berkeley\c +\|'). The default is the one-line format similar to +Berkeley's. + +.TP +.B \-\-help +Show a summary of acceptable arguments and options. + +.TP +.B \-d +.TP +.B \-o +.TP +.B \-x +.TP +.BI "\-\-radix " "number" +Using one of these options, you can control whether the size of each +section is given in decimal (`\|\c +.B \-d\c +\|', or `\|\c +.B \-\-radix 10\c +\|'); octal +(`\|\c +.B \-o\c +\|', or `\|\c +.B \-\-radix 8\c +\|'); or hexadecimal (`\|\c +.B \-x\c +\|', or +`\|\c +.B \-\-radix 16\c +\|'). In `\|\c +.B \-\-radix \c +.I number\c +\&\c +\|', only the three +values (8, 10, 16) are supported. The total size is always given in two +radices; decimal and hexadecimal for `\|\c +.B \-d\c +\|' or `\|\c +.B \-x\c +\|' output, or +octal and hexadecimal if you're using `\|\c +.B \-o\c +\|'. + +.TP +.BI "\-\-target " "bfdname" +You can specify a particular object-code format for \c +.I objfile\c +\& as +\c +.I bfdname\c +\&. This may not be necessary; \c +.I size\c +\& can +automatically recognize many formats. See +.BR objdump ( 1 ) +for information +on listing available formats. + +.TP +.B \-V +.TP +.B \-\-version +Display version number information on \c +.B size\c +\& itself. + +.SH "SEE ALSO" +.RB "`\|" binutils "\|'" +entry in +.BR info ; +.IR "The GNU Binary Utilities" , + Roland H. Pesch (October 1991); +.BR ar "(" 1 ")," +.BR objdump ( 1 ). + +.SH COPYING +Copyright (c) 1991 Free Software Foundation, Inc. +.PP +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. +.PP +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the +entire resulting derived work is distributed under the terms of a +permission notice identical to this one. +.PP +Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be included in +translations approved by the Free Software Foundation instead of in +the original English. diff --git a/binutils/size.c b/binutils/size.c new file mode 100644 index 0000000..f57c7ed --- /dev/null +++ b/binutils/size.c @@ -0,0 +1,515 @@ +/* size.c -- report size of various sections of an executable file. + Copyright 1991, 92, 93, 94, 95, 96, 97, 98, 1999 + Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Extensions/incompatibilities: + o - BSD output has filenames at the end. + o - BSD output can appear in different radicies. + o - SysV output has less redundant whitespace. Filename comes at end. + o - SysV output doesn't show VMA which is always the same as the PMA. + o - We also handle core files. + o - We also handle archives. + If you write shell scripts which manipulate this info then you may be + out of luck; there's no --compatibility or --pedantic option. +*/ + +#include "bfd.h" +#include "getopt.h" +#include "bucomm.h" +#include "libiberty.h" + +#ifndef BSD_DEFAULT +#define BSD_DEFAULT 1 +#endif + +/* Program options. */ + +enum + { + decimal, octal, hex + } radix = decimal; +int berkeley_format = BSD_DEFAULT; /* 0 means use AT&T-style output. */ +int show_version = 0; +int show_help = 0; + +/* Program exit status. */ +int return_code = 0; + +static char *target = NULL; + +/* Static declarations */ + +static void usage PARAMS ((FILE *, int)); +static void display_file PARAMS ((char *filename)); +static void display_bfd PARAMS ((bfd *)); +static void display_archive PARAMS ((bfd *)); +static int size_number PARAMS ((bfd_size_type)); +#if 0 +static void lprint_number PARAMS ((int, bfd_size_type)); +#endif +static void rprint_number PARAMS ((int, bfd_size_type)); +static void print_berkeley_format PARAMS ((bfd *)); +static void sysv_internal_sizer PARAMS ((bfd *, asection *, PTR)); +static void sysv_internal_printer PARAMS ((bfd *, asection *, PTR)); +static void print_sysv_format PARAMS ((bfd *)); +static void print_sizes PARAMS ((bfd * file)); +static void berkeley_sum PARAMS ((bfd *, sec_ptr, PTR)); + +static void +usage (stream, status) + FILE *stream; + int status; +{ + fprintf (stream, _("\ +Usage: %s [-ABdoxV] [--format=berkeley|sysv] [--radix=8|10|16]\n\ + [--target=bfdname] [--version] [--help] [file...]\n"), program_name); +#if BSD_DEFAULT + fputs (_("default is --format=berkeley\n"), stream); +#else + fputs (_("default is --format=sysv\n"), stream); +#endif + list_supported_targets (program_name, stream); + if (status == 0) + fprintf (stream, _("Report bugs to bug-gnu-utils@gnu.org\n")); + exit (status); +} + +struct option long_options[] = +{ + {"format", required_argument, 0, 200}, + {"radix", required_argument, 0, 201}, + {"target", required_argument, 0, 202}, + {"version", no_argument, &show_version, 1}, + {"help", no_argument, &show_help, 1}, + {0, no_argument, 0, 0} +}; + +int +main (argc, argv) + int argc; + char **argv; +{ + int temp; + int c; + +#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) + setlocale (LC_MESSAGES, ""); +#endif + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + + program_name = *argv; + xmalloc_set_program_name (program_name); + + bfd_init (); + set_default_bfd_target (); + + while ((c = getopt_long (argc, argv, "ABVdox", long_options, + (int *) 0)) != EOF) + switch (c) + { + case 200: /* --format */ + switch (*optarg) + { + case 'B': + case 'b': + berkeley_format = 1; + break; + case 'S': + case 's': + berkeley_format = 0; + break; + default: + fprintf (stderr, _("invalid argument to --format: %s\n"), optarg); + usage (stderr, 1); + } + break; + + case 202: /* --target */ + target = optarg; + break; + + case 201: /* --radix */ +#ifdef ANSI_LIBRARIES + temp = strtol (optarg, NULL, 10); +#else + temp = atol (optarg); +#endif + switch (temp) + { + case 10: + radix = decimal; + break; + case 8: + radix = octal; + break; + case 16: + radix = hex; + break; + default: + printf (_("Invalid radix: %s\n"), optarg); + usage (stderr, 1); + } + break; + + case 'A': + berkeley_format = 0; + break; + case 'B': + berkeley_format = 1; + break; + case 'V': + show_version = 1; + break; + case 'd': + radix = decimal; + break; + case 'x': + radix = hex; + break; + case 'o': + radix = octal; + break; + case 0: + break; + case '?': + usage (stderr, 1); + } + + if (show_version) + print_version ("size"); + if (show_help) + usage (stdout, 0); + + if (optind == argc) + display_file ("a.out"); + else + for (; optind < argc;) + display_file (argv[optind++]); + + return return_code; +} + +/* Display stats on file or archive member ABFD. */ + +static void +display_bfd (abfd) + bfd *abfd; +{ + char **matching; + + if (bfd_check_format (abfd, bfd_archive)) + /* An archive within an archive. */ + return; + + if (bfd_check_format_matches (abfd, bfd_object, &matching)) + { + print_sizes (abfd); + printf ("\n"); + return; + } + + if (bfd_get_error () == bfd_error_file_ambiguously_recognized) + { + bfd_nonfatal (bfd_get_filename (abfd)); + list_matching_formats (matching); + free (matching); + return_code = 3; + return; + } + + if (bfd_check_format_matches (abfd, bfd_core, &matching)) + { + CONST char *core_cmd; + + print_sizes (abfd); + fputs (" (core file", stdout); + + core_cmd = bfd_core_file_failing_command (abfd); + if (core_cmd) + printf (" invoked as %s", core_cmd); + + puts (")\n"); + return; + } + + bfd_nonfatal (bfd_get_filename (abfd)); + + if (bfd_get_error () == bfd_error_file_ambiguously_recognized) + { + list_matching_formats (matching); + free (matching); + } + + return_code = 3; +} + +static void +display_archive (file) + bfd *file; +{ + bfd *arfile = (bfd *) NULL; + + for (;;) + { + bfd_set_error (bfd_error_no_error); + + arfile = bfd_openr_next_archived_file (file, arfile); + if (arfile == NULL) + { + if (bfd_get_error () != bfd_error_no_more_archived_files) + { + bfd_nonfatal (bfd_get_filename (file)); + return_code = 2; + } + break; + } + + display_bfd (arfile); + /* Don't close the archive elements; we need them for next_archive */ + } +} + +static void +display_file (filename) + char *filename; +{ + bfd *file = bfd_openr (filename, target); + if (file == NULL) + { + bfd_nonfatal (filename); + return_code = 1; + return; + } + + if (bfd_check_format (file, bfd_archive) == true) + display_archive (file); + else + display_bfd (file); + + if (bfd_close (file) == false) + { + bfd_nonfatal (filename); + return_code = 1; + return; + } +} + +/* This is what lexical functions are for. */ + +static int +size_number (num) + bfd_size_type num; +{ + char buffer[40]; + sprintf (buffer, + (radix == decimal ? "%lu" : + ((radix == octal) ? "0%lo" : "0x%lx")), + (unsigned long) num); + + return strlen (buffer); +} + +#if 0 + +/* This is not used. */ + +static void +lprint_number (width, num) + int width; + bfd_size_type num; +{ + char buffer[40]; + sprintf (buffer, + (radix == decimal ? "%lu" : + ((radix == octal) ? "0%lo" : "0x%lx")), + (unsigned long) num); + + printf ("%-*s", width, buffer); +} + +#endif + +static void +rprint_number (width, num) + int width; + bfd_size_type num; +{ + char buffer[40]; + sprintf (buffer, + (radix == decimal ? "%lu" : + ((radix == octal) ? "0%lo" : "0x%lx")), + (unsigned long) num); + + printf ("%*s", width, buffer); +} + +static bfd_size_type bsssize; +static bfd_size_type datasize; +static bfd_size_type textsize; + +static void +berkeley_sum (abfd, sec, ignore) + bfd *abfd; + sec_ptr sec; + PTR ignore; +{ + flagword flags; + bfd_size_type size; + + flags = bfd_get_section_flags (abfd, sec); + if ((flags & SEC_ALLOC) == 0) + return; + + size = bfd_get_section_size_before_reloc (sec); + if ((flags & SEC_CODE) != 0 || (flags & SEC_READONLY) != 0) + textsize += size; + else if ((flags & SEC_HAS_CONTENTS) != 0) + datasize += size; + else + bsssize += size; +} + +static void +print_berkeley_format (abfd) + bfd *abfd; +{ + static int files_seen = 0; + bfd_size_type total; + + bsssize = 0; + datasize = 0; + textsize = 0; + + bfd_map_over_sections (abfd, berkeley_sum, (PTR) NULL); + + if (files_seen++ == 0) +#if 0 + /* Intel doesn't like bss/stk because they don't have core files. */ + puts ((radix == octal) ? " text\t data\tbss/stk\t oct\t hex\tfilename" : + " text\t data\tbss/stk\t dec\t hex\tfilename"); +#else + puts ((radix == octal) ? " text\t data\t bss\t oct\t hex\tfilename" : + " text\t data\t bss\t dec\t hex\tfilename"); +#endif + + total = textsize + datasize + bsssize; + + rprint_number (7, textsize); + putchar ('\t'); + rprint_number (7, datasize); + putchar ('\t'); + rprint_number (7, bsssize); + printf (((radix == octal) ? "\t%7lo\t%7lx\t" : "\t%7lu\t%7lx\t"), + (unsigned long) total, (unsigned long) total); + + fputs (bfd_get_filename (abfd), stdout); + if (bfd_my_archive (abfd)) + printf (" (ex %s)", bfd_get_filename (bfd_my_archive (abfd))); +} + +/* I REALLY miss lexical functions! */ +bfd_size_type svi_total = 0; +bfd_vma svi_maxvma = 0; +int svi_namelen = 0; +int svi_vmalen = 0; +int svi_sizelen = 0; + +static void +sysv_internal_sizer (file, sec, ignore) + bfd *file; + sec_ptr sec; + PTR ignore; +{ + bfd_size_type size = bfd_section_size (file, sec); + if (!bfd_is_abs_section (sec) + && !bfd_is_com_section (sec) + && !bfd_is_und_section (sec)) + { + int namelen = strlen (bfd_section_name (file, sec)); + if (namelen > svi_namelen) + svi_namelen = namelen; + + svi_total += size; + if (bfd_section_vma (file, sec) > svi_maxvma) + svi_maxvma = bfd_section_vma (file, sec); + } +} + +static void +sysv_internal_printer (file, sec, ignore) + bfd *file; + sec_ptr sec; + PTR ignore; +{ + bfd_size_type size = bfd_section_size (file, sec); + if (!bfd_is_abs_section (sec) + && !bfd_is_com_section (sec) + && !bfd_is_und_section (sec)) + { + svi_total += size; + + printf ("%-*s ", svi_namelen, bfd_section_name (file, sec)); + rprint_number (svi_sizelen, size); + printf (" "); + rprint_number (svi_vmalen, bfd_section_vma (file, sec)); + printf ("\n"); + } +} + +static void +print_sysv_format (file) + bfd *file; +{ + /* size all of the columns */ + svi_total = 0; + svi_maxvma = 0; + svi_namelen = 0; + bfd_map_over_sections (file, sysv_internal_sizer, (PTR) NULL); + svi_vmalen = size_number ((bfd_size_type)svi_maxvma); + if ((size_t) svi_vmalen < sizeof ("addr") - 1) + svi_vmalen = sizeof ("addr")-1; + + svi_sizelen = size_number (svi_total); + if ((size_t) svi_sizelen < sizeof ("size") - 1) + svi_sizelen = sizeof ("size")-1; + + svi_total = 0; + printf ("%s ", bfd_get_filename (file)); + if (bfd_my_archive (file)) + printf (" (ex %s)", bfd_get_filename (bfd_my_archive (file))); + + printf (":\n%-*s %*s %*s\n", svi_namelen, "section", + svi_sizelen, "size", svi_vmalen, "addr"); + bfd_map_over_sections (file, sysv_internal_printer, (PTR) NULL); + + printf ("%-*s ", svi_namelen, "Total"); + rprint_number (svi_sizelen, svi_total); + printf ("\n\n"); +} + +static void +print_sizes (file) + bfd *file; +{ + if (berkeley_format) + print_berkeley_format (file); + else + print_sysv_format (file); +} diff --git a/binutils/srconv.c b/binutils/srconv.c new file mode 100644 index 0000000..8b0f2b7 --- /dev/null +++ b/binutils/srconv.c @@ -0,0 +1,2036 @@ +/* srconv.c -- Sysroff conversion program + Copyright (C) 1994, 95, 96, 98, 1999 Free Software Foundation, Inc. + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* Written by Steve Chamberlain (sac@cygnus.com) + + This program can be used to convert a coff object file + into a Hitachi OM/LM (Sysroff) format. + + All debugging information is preserved */ + +#include <bfd.h> +#include "bucomm.h" +#include "sysroff.h" +#include "coffgrok.h" +#include <libiberty.h> +#include <getopt.h> + +#include "coff/internal.h" +#include "../bfd/libcoff.h" + +#define PROGRAM_VERSION "1.5" +/*#define FOOP1 1 */ + +static int addrsize; +static char *toolname; +static char **rnames; + +static void wr_cs (); +static void walk_tree_scope (); +static void wr_globals (); +static int find_base (); + +static FILE *file; +static bfd *abfd; +static int debug = 0; +static int quick = 0; +static int noprescan = 0; +static struct coff_ofile *tree; +/* Obsolete ?? + static int absolute_p; + */ + +static int segmented_p; +static int code; + +static int ids1[20000]; +static int ids2[20000]; + +static int base1 = 0x18; +static int base2 = 0x2018; + +static int +get_member_id (x) + int x; +{ + if (ids2[x]) + { + return ids2[x]; + } + ids2[x] = base2++; + return ids2[x]; +} + +static int +get_ordinary_id (x) + int x; +{ + if (ids1[x]) + { + return ids1[x]; + } + ids1[x] = base1++; + return ids1[x]; +} +static char * +section_translate (n) + char *n; +{ + if (strcmp (n, ".text") == 0) + return "P"; + if (strcmp (n, ".data") == 0) + return "D"; + if (strcmp (n, ".bss") == 0) + return "B"; + return n; +} + + + +#define DATE "940201073000"; /* Just a time on my birthday */ + + +static +char * +strip_suffix (name) + char *name; +{ + int i; + char *res; + for (i = 0; name[i] != 0 && name[i] != '.'; i++) + ; + res = (char *) xmalloc (i + 1); + memcpy (res, name, i); + res[i] = 0; + return res; +} + + +/* IT LEN stuff CS */ +static void +checksum (file, ptr, size, code) + FILE *file; + char *ptr; + int size; + int code; +{ + int j; + int last; + int sum = 0; + int bytes = size / 8; + last = !(code & 0xff00); + if (size & 0x7) + abort (); + ptr[0] = code | (last ? 0x80 : 0); + ptr[1] = bytes + 1; + + for (j = 0; j < bytes; j++) + { + sum += ptr[j]; + } + /* Glue on a checksum too */ + ptr[bytes] = ~sum; + fwrite (ptr, bytes + 1, 1, file); +} + + + + +static void +writeINT (n, ptr, idx, size, file) + int n; + char *ptr; + int *idx; + int size; + FILE *file; +{ + int byte = *idx / 8; + + if (size == -2) + size = addrsize; + else if (size == -1) + size = 0; + + if (byte > 240) + { + /* Lets write out that record and do another one */ + checksum (file, ptr, *idx, code | 0x1000); + *idx = 16; + byte = *idx / 8; + } + switch (size) + { + case 0: + break; + case 1: + ptr[byte] = n; + break; + case 2: + ptr[byte + 0] = n >> 8; + ptr[byte + 1] = n; + break; + case 4: + ptr[byte + 0] = n >> 24; + ptr[byte + 1] = n >> 16; + ptr[byte + 2] = n >> 8; + ptr[byte + 3] = n >> 0; + break; + default: + abort (); + } + *idx += size * 8; +} + + +static void +writeBITS (val, ptr, idx, size) + int val; + char *ptr; + int *idx; + int size; +{ + int byte = *idx / 8; + int bit = *idx % 8; + int old; + *idx += size; + + old = ptr[byte]; + /* Turn off all about to change bits */ + old &= ~((~0 >> (8 - bit - size)) & ((1 << size) - 1)); + /* Turn on the bits we want */ + old |= (val & ((1 << size) - 1)) << (8 - bit - size); + ptr[byte] = old; +} + +static void +writeBARRAY (data, ptr, idx, size, file) + barray data; + char *ptr; + int *idx; + int size; + FILE *file; +{ + int i; + writeINT (data.len, ptr, idx, 1, file); + for (i = 0; i < data.len; i++) + { + writeINT (data.data[i], ptr, idx, 1, file); + } +} + + +static void +writeCHARS (string, ptr, idx, size, file) + char *string; + char *ptr; + int *idx; + int size; + FILE *file; +{ + int i = *idx / 8; + + if (i > 240) + { + /* Lets write out that record and do another one */ + checksum (file, ptr, *idx, code | 0x1000); + *idx = 16; + i = *idx / 8; + } + + if (size == 0) + { + /* Variable length string */ + size = strlen (string); + ptr[i++] = size; + } + + /* BUG WAITING TO HAPPEN */ + memcpy (ptr + i, string, size); + i += size; + *idx = i * 8; +} + +#define SYSROFF_SWAP_OUT +#include "sysroff.c" + + +static char *rname_sh[] = +{ + "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15" +}; + +static char *rname_h8300[] = +{ + "ER0", "ER1", "ER2", "ER3", "ER4", "ER5", "ER6", "ER7", "PC", "CCR" +}; + +static void +wr_tr () +{ + /* The TR block is not normal - it doesn't have any contents. */ + + static char b[] = { + 0xff, /* IT */ + 0x03, /* RL */ + 0xfd, /* CS */ + }; + fwrite (b, 1, sizeof (b), file); +} + +static void +wr_un (ptr, sfile, first, nsecs) + struct coff_ofile *ptr; + struct coff_sfile *sfile; + int first; + int nsecs; +{ + struct IT_un un; + + struct coff_symbol *s; + + un.spare1 = 0; + + if (bfd_get_file_flags (abfd) & EXEC_P) + un.format = FORMAT_LM; + else + un.format = FORMAT_OM; + un.spare1 = 0; + + +#if 1 + un.nsections = ptr->nsections - 1; /* Don't count the abs section */ +#else + /*NEW - only count sections with size */ + un.nsections = nsecs; +#endif + + un.nextdefs = 0; + un.nextrefs = 0; + /* Count all the undefined and defined variables with global scope */ + + if (first) + { + for (s = ptr->symbol_list_head; s; s = s->next_in_ofile_list) + { + if (s->visible->type == coff_vis_ext_def + || s->visible->type == coff_vis_common) + un.nextdefs++; + + if (s->visible->type == coff_vis_ext_ref) + un.nextrefs++; + } + } + un.tool = toolname; + un.tcd = DATE; + un.linker = "L_GX00"; + un.lcd = DATE; + un.name = sfile->name; + sysroff_swap_un_out (file, &un); +} + + +static void +wr_hd (p) + struct coff_ofile *p; +{ + struct IT_hd hd; + + hd.spare1 = 0; + if (bfd_get_file_flags (abfd) & EXEC_P) + { + hd.mt = MTYPE_ABS_LM; + } + else + { + hd.mt = MTYPE_OMS_OR_LMS; + } + hd.cd = DATE; + + hd.nu = p->nsources; /* Always one unit */ + hd.code = 0; /* Always ASCII */ + hd.ver = "0200"; /* Version 2.00 */ + switch (bfd_get_arch (abfd)) + { + case bfd_arch_h8300: + hd.au = 8; + hd.si = 0; + hd.spcsz = 32; + hd.segsz = 0; + hd.segsh = 0; + switch (bfd_get_mach (abfd)) + { + case bfd_mach_h8300: + hd.cpu = "H8300"; + hd.afl = 2; + addrsize = 2; + toolname = "C_H8/300"; + break; + case bfd_mach_h8300h: + hd.cpu = "H8300H"; + hd.afl = 4; + addrsize = 4; + toolname = "C_H8/300H"; + break; + case bfd_mach_h8300s: + hd.cpu = "H8300S"; + hd.afl = 4; + addrsize = 4; + toolname = "C_H8/300S"; + break; + default: + abort(); + } + rnames = rname_h8300; + break; + case bfd_arch_sh: + hd.au = 8; + hd.si = 0; + hd.afl = 4; + hd.spcsz = 32; + hd.segsz = 0; + hd.segsh = 0; + hd.cpu = "SH"; + addrsize = 4; + toolname = "C_SH"; + rnames = rname_sh; + break; + default: + abort (); + } + + if (! bfd_get_file_flags(abfd) & EXEC_P) + { + hd.ep = 0; + } + else + { + hd.ep = 1; + hd.uan = 0; + hd.sa = 0; + hd.sad = 0; + hd.address = bfd_get_start_address (abfd); + } + + hd.os = ""; + hd.sys = ""; + hd.mn = strip_suffix (bfd_get_filename (abfd)); + + sysroff_swap_hd_out (file, &hd); +} + + +static void +wr_sh (p, sec) + struct coff_ofile *p; + struct coff_section *sec; +{ + struct IT_sh sh; + sh.unit = 0; + sh.section = sec->number; +#ifdef FOOP1 + sh.section = 0; +#endif + sysroff_swap_sh_out (file, &sh); +} + + +static void +wr_ob (p, section) + struct coff_ofile *p; + struct coff_section *section; +{ + bfd_size_type i; + int first = 1; + unsigned char stuff[200]; + + i = 0; + while (i < section->bfd_section->_raw_size) + { + struct IT_ob ob; + int todo = 200; /* Copy in 200 byte lumps */ + ob.spare = 0; + if (i + todo > section->bfd_section->_raw_size) + todo = section->bfd_section->_raw_size - i; + + if (first) + { + ob.saf = 1; + if (bfd_get_file_flags (abfd) & EXEC_P) + ob.address = section->address; + else + ob.address = 0; + + first = 0; + } + else + { + ob.saf = 0; + } + + ob.cpf = 0; /* Never compress */ + ob.data.len = todo; + bfd_get_section_contents (abfd, section->bfd_section, stuff, i, todo); + ob.data.data = stuff; + sysroff_swap_ob_out (file, &ob /*, i + todo < section->size */ ); + i += todo; + } + /* Now fill the rest with blanks */ + while (i < (bfd_size_type) section->size) + { + struct IT_ob ob; + int todo = 200; /* Copy in 200 byte lumps */ + ob.spare = 0; + if (i + todo > (bfd_size_type) section->size) + todo = section->size - i; + ob.saf = 0; + + ob.cpf = 0; /* Never compress */ + ob.data.len = todo; + memset (stuff, 0, todo); + ob.data.data = stuff; + sysroff_swap_ob_out (file, &ob); + i += todo; + } + /* Now fill the rest with blanks */ + +} + +static void +wr_rl (ptr, sec) + struct coff_ofile *ptr; + struct coff_section *sec; +{ + int nr = sec->nrelocs; + int i; + for (i = 0; i < nr; i++) + { + struct coff_reloc *r = sec->relocs + i; + struct coff_symbol *ref; + struct IT_rl rl; + rl.apol = 0; + rl.boundary = 0; + rl.segment = 1; + rl.sign = 0; + rl.check = 0; + rl.addr = r->offset; + rl.bitloc = 0; + rl.flen = 32; /* SH Specific */ + /* What sort of reloc ? Look in the section to find out */ + ref = r->symbol; + if (ref->visible->type == coff_vis_ext_ref) + { + rl.bcount = 4; /* Always 4 for us */ + rl.op = OP_EXT_REF; + rl.symn = ref->er_number; + } + else if (ref->visible->type == coff_vis_common) + { + rl.bcount = 11; /* Always 11 for us */ + rl.op = OP_SEC_REF; + rl.secn = ref->where->section->number; + rl.copcode_is_3 = 3; + rl.alength_is_4 = 4; + rl.addend = ref->where->offset - ref->where->section->address; + rl.aopcode_is_0x20 = 0x20; + } + + else + { + rl.bcount = 11; /* Always 11 for us */ + rl.op = OP_SEC_REF; + rl.secn = ref->where->section->number; + rl.copcode_is_3 = 3; + rl.alength_is_4 = 4; + rl.addend = -ref->where->section->address; + rl.aopcode_is_0x20 = 0x20; + } + rl.end = 0xff; + if (rl.op == OP_SEC_REF + || rl.op == OP_EXT_REF) + { + sysroff_swap_rl_out (file, &rl); + } + } +} + +static void +wr_object_body (p) + struct coff_ofile *p; +{ + int i; + for (i = 1; i < p->nsections; i++) + { + wr_sh (p, p->sections + i); + wr_ob (p, p->sections + i); + wr_rl (p, p->sections + i); + } +} + +static void +wr_dps_start (sfile, section, scope, type, nest) + struct coff_sfile *sfile; + struct coff_section *section; + struct coff_scope *scope; + int type; + int nest; +{ + struct IT_dps dps; + dps.end = 0; + dps.opt = 0; + dps.type = type; + if (scope->sec) + { + dps.san = scope->sec->number; + dps.address = scope->offset - find_base (sfile, scope->sec); + dps.block_size = scope->size; + if (debug) + { + printf ("DPS %s %d %x\n", + sfile->name, + nest, + dps.address); + + } + } + else + { + dps.san = 0; + dps.address = 0; + dps.block_size = 0; + } + + dps.nesting = nest; + dps.neg = 0x1001; + sysroff_swap_dps_out (file, &dps); +} + +static void +wr_dps_end (section, scope, type) + struct coff_section *section; + struct coff_scope *scope; + int type; +{ + struct IT_dps dps; + dps.end = 1; + dps.type = type; + sysroff_swap_dps_out (file, &dps); +} + +static int * +nints (x) + int x; +{ + return (int *) (xcalloc (sizeof (int), x)); +} + +static void walk_tree_symbol (); +static void +walk_tree_type_1 (sfile, symbol, type, nest) + struct coff_sfile *sfile; + struct coff_symbol *symbol; + struct coff_type *type; + int nest; +{ + switch (type->type) + { + case coff_secdef_type: + case coff_basic_type: + { + struct IT_dbt dbt; + + switch (type->u.basic) + { + case T_NULL: + case T_VOID: + dbt.btype = BTYPE_VOID; + dbt.sign = BTYPE_UNSPEC; + dbt.fptype = FPTYPE_NOTSPEC; + break; + case T_CHAR: + dbt.btype = BTYPE_CHAR; + dbt.sign = BTYPE_UNSPEC; + dbt.fptype = FPTYPE_NOTSPEC; + break; + case T_SHORT: + case T_INT: + case T_LONG: + dbt.btype = BTYPE_INT; + dbt.sign = SIGN_SIGNED; + dbt.fptype = FPTYPE_NOTSPEC; + break; + case T_FLOAT: + dbt.btype = BTYPE_FLOAT; + dbt.fptype = FPTYPE_SINGLE; + break; + case T_DOUBLE: + dbt.btype = BTYPE_FLOAT; + dbt.fptype = FPTYPE_DOUBLE; + break; + case T_LNGDBL: + dbt.btype = BTYPE_FLOAT; + dbt.fptype = FPTYPE_EXTENDED; + break; + case T_UCHAR: + dbt.btype = BTYPE_CHAR; + dbt.sign = SIGN_UNSIGNED; + dbt.fptype = FPTYPE_NOTSPEC; + break; + case T_USHORT: + case T_UINT: + case T_ULONG: + dbt.btype = BTYPE_INT; + dbt.sign = SIGN_UNSIGNED; + dbt.fptype = FPTYPE_NOTSPEC; + break; + } + dbt.bitsize = type->size; + dbt.neg = 0x1001; + sysroff_swap_dbt_out (file, &dbt); + break; + } + case coff_pointer_type: + { + struct IT_dpt dpt; + walk_tree_type_1 (sfile, symbol, type->u.pointer.points_to, nest + 1); + dpt.neg = 0x1001; + sysroff_swap_dpt_out (file, &dpt); + break; + } + + case coff_function_type: + { + struct IT_dfp dfp; + struct coff_symbol *param; + dfp.end = 0; + dfp.spare = 0; + dfp.nparams = type->u.function.parameters->nvars; + dfp.neg = 0x1001; + + walk_tree_type_1 (sfile, symbol, type->u.function.function_returns, nest + 1); + + sysroff_swap_dfp_out (file, &dfp); + + for (param = type->u.function.parameters->vars_head; + param; + param = param->next) + { + walk_tree_symbol (sfile, 0, param, nest); + } + dfp.end = 1; + sysroff_swap_dfp_out (file, &dfp); + break; + } + + case coff_structdef_type: + { + struct IT_dbt dbt; + struct IT_dds dds; + struct coff_symbol *member; + dds.spare = 0; + dbt.btype = BTYPE_STRUCT; + dbt.bitsize = type->size; + dbt.sign = SIGN_UNSPEC; + dbt.fptype = FPTYPE_NOTSPEC; + dbt.sid = get_member_id (type->u.astructdef.idx); + dbt.neg = 0x1001; + sysroff_swap_dbt_out (file, &dbt); + dds.end = 0; + dds.neg = 0x1001; + sysroff_swap_dds_out (file, &dds); + for (member = type->u.astructdef.elements->vars_head; + member; + member = member->next) + { + walk_tree_symbol (sfile, 0, member, nest + 1); + } + + dds.end = 1; + sysroff_swap_dds_out (file, &dds); + + } + break; + case coff_structref_type: + { + struct IT_dbt dbt; + dbt.btype = BTYPE_TAG; + dbt.bitsize = type->size; + dbt.sign = SIGN_UNSPEC; + dbt.fptype = FPTYPE_NOTSPEC; + if (type->u.astructref.ref) + { + dbt.sid = get_member_id (type->u.astructref.ref->number); + } + else + { + dbt.sid = 0; + } + + dbt.neg = 0x1001; + sysroff_swap_dbt_out (file, &dbt); + } + break; + case coff_array_type: + { + struct IT_dar dar; + int j; + int dims = 1; /* Only output one dimension at a time */ + dar.dims = dims; + dar.variable = nints (dims); + dar.subtype = nints (dims); + dar.spare = nints (dims); + dar.max_variable = nints (dims); + dar.maxspare = nints (dims); + dar.max = nints (dims); + dar.min_variable = nints (dims); + dar.min = nints (dims); + dar.minspare = nints (dims); + dar.neg = 0x1001; + dar.length = type->size / type->u.array.dim; + for (j = 0; j < dims; j++) + { + dar.variable[j] = VARIABLE_FIXED; + dar.subtype[j] = SUB_INTEGER; + dar.spare[j] = 0; + dar.max_variable[j] = 0; + dar.max[j] = type->u.array.dim; + dar.min_variable[j] = 0; + dar.min[j] = 1; /* Why isn't this 0 ? */ + } + walk_tree_type_1 (sfile, symbol, type->u.array.array_of, nest + 1); + sysroff_swap_dar_out (file, &dar); + } + break; + case coff_enumdef_type: + { + struct IT_dbt dbt; + struct IT_den den; + struct coff_symbol *member; + dbt.btype = BTYPE_ENUM; + dbt.bitsize = type->size; + dbt.sign = SIGN_UNSPEC; + dbt.fptype = FPTYPE_NOTSPEC; + dbt.sid = get_member_id (type->u.aenumdef.idx); + dbt.neg = 0x1001; + sysroff_swap_dbt_out (file, &dbt); + + den.end = 0; + den.neg = 0x1001; + den.spare = 0; + sysroff_swap_den_out (file, &den); + for (member = type->u.aenumdef.elements->vars_head; + member; + member = member->next) + { + walk_tree_symbol (sfile, 0, member, nest + 1); + } + + den.end = 1; + sysroff_swap_den_out (file, &den); + } + break; + + break; + case coff_enumref_type: + { + struct IT_dbt dbt; + dbt.btype = BTYPE_TAG; + dbt.bitsize = type->size; + dbt.sign = SIGN_UNSPEC; + dbt.fptype = FPTYPE_NOTSPEC; + dbt.sid = get_member_id (type->u.aenumref.ref->number); + dbt.neg = 0x1001; + sysroff_swap_dbt_out (file, &dbt); + } + break; + default: + abort (); + } +} + +/* Obsolete ? + static void + dty_start () + { + struct IT_dty dty; + dty.end = 0; + dty.neg = 0x1001; + dty.spare = 0; + sysroff_swap_dty_out (file, &dty); + } + + static void + dty_stop () + { + struct IT_dty dty; + dty.end = 0; + dty.neg = 0x1001; + dty.end = 1; + sysroff_swap_dty_out (file, &dty); + } + + + static void + dump_tree_structure (sfile, symbol, type, nest) + struct coff_sfile *sfile; + struct coff_symbol *symbol; + struct coff_type *type; + int nest; + { + if (symbol->type->type == coff_function_type) + { + + + } + + } + */ + +static void +walk_tree_type (sfile, symbol, type, nest) + + struct + coff_sfile *sfile; + struct coff_symbol *symbol; + struct coff_type *type; + int nest; +{ + if (symbol->type->type == coff_function_type) + { + + struct IT_dty dty; + dty.end = 0; + dty.neg = 0x1001; + + sysroff_swap_dty_out (file, &dty); + walk_tree_type_1 (sfile, symbol, type, nest); + dty.end = 1; + sysroff_swap_dty_out (file, &dty); + + wr_dps_start (sfile, + symbol->where->section, + symbol->type->u.function.code, + BLOCK_TYPE_FUNCTION, nest); + wr_dps_start (sfile, symbol->where->section, + symbol->type->u.function.code, + BLOCK_TYPE_BLOCK, nest); + walk_tree_scope (symbol->where->section, + sfile, + symbol->type->u.function.code, + nest + 1, BLOCK_TYPE_BLOCK); + + wr_dps_end (symbol->where->section, + symbol->type->u.function.code, + BLOCK_TYPE_BLOCK); + wr_dps_end (symbol->where->section, + symbol->type->u.function.code, BLOCK_TYPE_FUNCTION); + + } + else + { + struct IT_dty dty; + dty.end = 0; + dty.neg = 0x1001; + sysroff_swap_dty_out (file, &dty); + walk_tree_type_1 (sfile, symbol, type, nest); + dty.end = 1; + sysroff_swap_dty_out (file, &dty); + } + +} + + + +static void +walk_tree_symbol (sfile, section, symbol, nest) + struct coff_sfile *sfile; + struct coff_section *section; + struct coff_symbol *symbol; + int nest; +{ + struct IT_dsy dsy; + + memset(&dsy, 0, sizeof(dsy)); + dsy.nesting = nest; + + switch (symbol->type->type) + { + case coff_function_type: + dsy.type = STYPE_FUNC; + dsy.assign = 1; + break; + case coff_structref_type: + case coff_pointer_type: + case coff_array_type: + case coff_basic_type: + case coff_enumref_type: + dsy.type = STYPE_VAR; + dsy.assign = 1; + break; + case coff_enumdef_type: + dsy.type = STYPE_TAG; + dsy.assign = 0; + dsy.magic = 2; + break; + case coff_structdef_type: + dsy.type = STYPE_TAG; + dsy.assign = 0; + dsy.magic = symbol->type->u.astructdef.isstruct ? 0 : 1; + break; + case coff_secdef_type: + return; + default: + abort (); + } + + if (symbol->where->where == coff_where_member_of_struct) + { + dsy.assign = 0; + dsy.type = STYPE_MEMBER; + } + if (symbol->where->where == coff_where_member_of_enum) + { + dsy.type = STYPE_ENUM; + dsy.assign = 0; + dsy.evallen = 4; + dsy.evalue = symbol->where->offset; + } + + if (symbol->type->type == coff_structdef_type + || symbol->where->where == coff_where_entag + || symbol->where->where == coff_where_strtag) + { + dsy.snumber = get_member_id (symbol->number); + } + else + { + dsy.snumber = get_ordinary_id (symbol->number); + } + + + dsy.sname = symbol->name[0] == '_' ? symbol->name + 1 : symbol->name; + + switch (symbol->visible->type) + { + case coff_vis_common: + case coff_vis_ext_def: + dsy.ainfo = AINFO_STATIC_EXT_DEF; + break; + case coff_vis_ext_ref: + dsy.ainfo = AINFO_STATIC_EXT_REF; + break; + case coff_vis_int_def: + dsy.ainfo = AINFO_STATIC_INT; + break; + case coff_vis_auto: + case coff_vis_autoparam: + dsy.ainfo = AINFO_AUTO; + break; + case coff_vis_register: + case coff_vis_regparam: + dsy.ainfo = AINFO_REG; + break; + break; + case coff_vis_tag: + case coff_vis_member_of_struct: + case coff_vis_member_of_enum: + break; + default: + abort (); + } + + dsy.dlength = symbol->type->size; + switch (symbol->where->where) + { + case coff_where_memory: + + dsy.section = symbol->where->section->number; +#ifdef FOOP + dsy.section = 0; +#endif + break; + case coff_where_member_of_struct: + case coff_where_member_of_enum: + case coff_where_stack: + case coff_where_register: + case coff_where_unknown: + case coff_where_strtag: + + case coff_where_entag: + case coff_where_typedef: + break; + default: + abort (); + } + + switch (symbol->where->where) + { + case coff_where_memory: + dsy.address = symbol->where->offset - find_base (sfile, symbol->where->section); + break; + case coff_where_stack: + dsy.address = symbol->where->offset; + break; + case coff_where_member_of_struct: + + + if (symbol->where->bitsize) + { + int bits = (symbol->where->offset * 8 + symbol->where->bitoffset); + dsy.bitunit = 1; + dsy.field_len = symbol->where->bitsize; + dsy.field_off = (bits / 32) * 4; + dsy.field_bitoff = bits % 32; + } + else + { + dsy.bitunit = 0; + + dsy.field_len = symbol->type->size; + dsy.field_off = symbol->where->offset; + } + break; + case coff_where_member_of_enum: + /* dsy.bitunit = 0; + dsy.field_len = symbol->type->size; + dsy.field_off = symbol->where->offset; */ + break; + case coff_where_register: + case coff_where_unknown: + case coff_where_strtag: + + case coff_where_entag: + case coff_where_typedef: + break; + default: + abort (); + } + + if (symbol->where->where == coff_where_register) + dsy.reg = rnames[symbol->where->offset]; + + switch (symbol->visible->type) + { + case coff_vis_common: + /* We do this 'cause common C symbols are treated as extdefs */ + case coff_vis_ext_def: + case coff_vis_ext_ref: + + dsy.ename = symbol->name; + break; + + case coff_vis_regparam: + case coff_vis_autoparam: + dsy.type = STYPE_PARAMETER; + break; + + case coff_vis_int_def: + + case coff_vis_auto: + case coff_vis_register: + case coff_vis_tag: + case coff_vis_member_of_struct: + case coff_vis_member_of_enum: + break; + default: + abort (); + } + + dsy.sfn = 0; + dsy.sln = 2; + + dsy.neg = 0x1001; + + + sysroff_swap_dsy_out (file, &dsy); + + walk_tree_type (sfile, symbol, symbol->type, nest); +} + + +static void +walk_tree_scope (section, sfile, scope, nest, type) + struct coff_section *section; + struct coff_sfile *sfile; + struct coff_scope *scope; + int nest; + int type; +{ + struct coff_symbol *vars; + struct coff_scope *child; + + if (scope->vars_head + || (scope->list_head && scope->list_head->vars_head)) + { + wr_dps_start (sfile, section, scope, type, nest); + + if (nest == 0) + wr_globals (tree, sfile, nest + 1); + + for (vars = scope->vars_head; vars; vars = vars->next) + { + walk_tree_symbol (sfile, section, vars, nest); + } + + for (child = scope->list_head; child; child = child->next) + { + walk_tree_scope (section, sfile, child, nest + 1, BLOCK_TYPE_BLOCK); + } + + wr_dps_end (section, scope, type); + } +} +static void +walk_tree_sfile (section, sfile) + struct coff_section *section; + struct coff_sfile *sfile; +{ + walk_tree_scope (section, sfile, sfile->scope, 0, BLOCK_TYPE_COMPUNIT); + +} + +static void +wr_program_structure (p, sfile) + struct coff_ofile *p; + struct coff_sfile *sfile; +{ + + walk_tree_sfile (p->sections + 4, sfile); + +} + +static void +wr_du (p, sfile, n) + struct coff_ofile *p; + struct coff_sfile *sfile; + int n; +{ + struct IT_du du; + int lim; +#if 0 + struct coff_symbol *symbol; + static int incit = 0x500000; + int used = 0; +#endif + int i; + int j; + unsigned int *lowest = (unsigned *) nints (p->nsections); + unsigned int *highest = (unsigned *) nints (p->nsections); + du.format = bfd_get_file_flags (abfd) & EXEC_P ? 0 : 1; + du.optimized = 0; + du.stackfrmt = 0; + du.spare = 0; + du.unit = n; + du.sections = p->nsections - 1; + du.san = (int *) xcalloc (sizeof (int), du.sections); + du.address = nints (du.sections); + du.length = nints (du.sections); + + for (i = 0; i < du.sections; i++) + { + lowest[i] = ~0; + highest[i] = 0; + } + + /* Look through all the symbols and try and work out the extents in this + source file */ +#if 0 + for (symbol = sfile->scope->vars_head; + symbol; + symbol = symbol->next) + { + if (symbol->type->type == coff_secdef_type) + { + unsigned int low = symbol->where->offset; + unsigned int high = symbol->where->offset + symbol->type->size - 1; + struct coff_section *section = symbol->where->section; + + int sn = section->number; + if (low < lowest[sn]) + lowest[sn] = low; + if (high > highest[sn]) + highest[sn] = high; + } + } + + + for (i = 0; i < du.sections; i++) + { + if (highest[i] == 0) + { + lowest[i] = highest[i] = incit; + } + du.san[used] = i; + du.length[used] = highest[i] - lowest[i]; + du.address[used] = bfd_get_file_flags (abfd) & EXEC_P ? lowest[i] : 0; + if (debug) + { + printf (" section %6s 0x%08x..0x%08x\n", + p->sections[i + 1].name, + lowest[i], + highest[i]); + } + used++; + } + +#endif + lim = du.sections; + for (j = 0; j < lim; j++) + { + int src = j; + int dst = j; + du.san[dst] = dst; + if (sfile->section[src].init) + { + du.length[dst] + = sfile->section[src].high - sfile->section[src].low + 1; + du.address[dst] + = sfile->section[src].low; + } + else + { + du.length[dst] = 0; + du.address[dst] = 0; + } + if (debug) + { + if (sfile->section[src].parent) + { + printf (" section %6s 0x%08x..0x%08x\n", + sfile->section[src].parent->name, + du.address[dst], + du.address[dst] + du.length[dst] - 1); + } + } + du.sections = dst + 1; + } + + du.tool = "c_gcc"; + du.date = DATE; + + sysroff_swap_du_out (file, &du); +} + +static void +wr_dus (p, sfile) + struct coff_ofile *p; + struct coff_sfile *sfile; +{ + + struct IT_dus dus; + + dus.efn = 0x1001; + dus.ns = 1; /* p->nsources; sac 14 jul 94 */ + dus.drb = nints (dus.ns); + dus.fname = (char **) xcalloc (sizeof (char *), dus.ns); + dus.spare = nints (dus.ns); + dus.ndir = 0; + /* Find the filenames */ +#if 0 + i = 0; + + for (sfile = p->source_head; + sfile; + sfile = sfile->next) + { + dus.drb[i] = 0; + dus.spare[i] = 0; + dus.fname[i] = sfile->name; + i++; + } +#else + dus.drb[0] = 0; + dus.fname[0] = sfile->name; +#endif + + sysroff_swap_dus_out (file, &dus); + +} + +/* Find the offset of the .text section for this sfile in the + .text section for the output file */ + +static int +find_base (sfile, section) + struct coff_sfile *sfile; + struct coff_section *section; +{ + return sfile->section[section->number].low; +} +static void +wr_dln (p, sfile, n) + struct coff_ofile *p; + struct coff_sfile *sfile; + int n; + +{ +#if 0 + if (n == 0) + { + /* Count up all the linenumbers */ + struct coff_symbol *sy; + int lc = 0; + struct IT_dln dln; + + int idx; + + for (sy = p->symbol_list_head; + sy; + sy = sy->next_in_ofile_list) + { + struct coff_type *t = sy->type; + if (t->type == coff_function_type) + { + struct coff_line *l = t->u.function.lines; + lc += l->nlines; + } + } + + dln.sfn = nints (lc); + dln.sln = nints (lc); + dln.lln = nints (lc); + dln.section = nints (lc); + + dln.from_address = nints (lc); + dln.to_address = nints (lc); + + + dln.neg = 0x1001; + + dln.nln = lc; + + /* Run through once more and fill up the structure */ + idx = 0; + for (sy = p->symbol_list_head; + sy; + sy = sy->next_in_ofile_list) + { + if (sy->type->type == coff_function_type) + { + int i; + struct coff_line *l = sy->type->u.function.lines; + for (i = 0; i < l->nlines; i++) + { + dln.section[idx] = sy->where->section->number; + dln.sfn[idx] = n; + dln.sln[idx] = l->lines[i]; + dln.from_address[idx] = l->addresses[i]; + if (idx) + dln.to_address[idx - 1] = dln.from_address[idx]; + idx++; + } + } + n++; + } + sysroff_swap_dln_out (file, &dln); + } + +#endif +#if 1 + /* Count up all the linenumbers */ + + struct coff_symbol *sy; + int lc = 0; + struct IT_dln dln; + + int idx; + + for (sy = sfile->scope->vars_head; + sy; + sy = sy->next) + { + struct coff_type *t = sy->type; + if (t->type == coff_function_type) + { + struct coff_line *l = t->u.function.lines; + if (l) + lc += l->nlines; + } + } + + dln.sfn = nints (lc); + dln.sln = nints (lc); + dln.cc = nints (lc); + dln.section = nints (lc); + + dln.from_address = nints (lc); + dln.to_address = nints (lc); + + + dln.neg = 0x1001; + + dln.nln = lc; + + /* Run through once more and fill up the structure */ + idx = 0; + for (sy = sfile->scope->vars_head; + sy; + sy = sy->next) + { + if (sy->type->type == coff_function_type) + { + int i; + struct coff_line *l = sy->type->u.function.lines; + if (l) + { + int base = find_base (sfile, sy->where->section); + for (i = 0; i < l->nlines; i++) + { + dln.section[idx] = sy->where->section->number; + dln.sfn[idx] = 0; + dln.sln[idx] = l->lines[i]; + dln.from_address[idx] = + l->addresses[i] + sy->where->section->address - base; + dln.cc[idx] = 0; + if (idx) + dln.to_address[idx - 1] = dln.from_address[idx]; + idx++; + + } + dln.to_address[idx - 1] = dln.from_address[idx - 1] + 2; + } + } + } + if (lc) + sysroff_swap_dln_out (file, &dln); +#endif +} + +/* Write the global symbols out to the debug info */ +static void +wr_globals (p, sfile, n) + struct coff_ofile *p; + struct coff_sfile *sfile; + int n; +{ + struct coff_symbol *sy; + for (sy = p->symbol_list_head; + sy; + sy = sy->next_in_ofile_list) + { + if (sy->visible->type == coff_vis_ext_def + || sy->visible->type == coff_vis_ext_ref) + { + /* Only write out symbols if they belong to + the current source file */ + if (sy->sfile == sfile) + walk_tree_symbol (sfile, 0, sy, 0); + + } + } +} + +static void +wr_debug (p) + struct coff_ofile *p; +{ + struct coff_sfile *sfile; + int n = 0; + for (sfile = p->source_head; + sfile; + sfile = sfile->next) + + { + if (debug) + { + printf ("%s\n", sfile->name); + } + wr_du (p, sfile, n); + wr_dus (p, sfile); + wr_program_structure (p, sfile); + wr_dln (p, sfile, n); + n++; + } +} + +static void +wr_cs () +{ + /* It seems that the CS struct is not normal - the size is wrong + heres one I prepared earlier.. */ + static char b[] = { + 0x80, /* IT */ + 0x21, /* RL */ + 0x00, /* number of chars in variable length part */ + 0x80, /* hd */ + 0x00, /* hs */ + 0x80, /* un */ + 0x00, /* us */ + 0x80, /* sc */ + 0x00, /* ss */ + 0x80, /* er */ + 0x80, /* ed */ + 0x80, /* sh */ + 0x80, /* ob */ + 0x80, /* rl */ + 0x80, /* du */ + 0x80, /* dps */ + 0x80, /* dsy */ + 0x80, /* dty */ + 0x80, /* dln */ + 0x80, /* dso */ + 0x80, /* dus */ + 0x00, /* dss */ + 0x80, /* dbt */ + 0x00, /* dpp */ + 0x80, /* dfp */ + 0x80, /* den */ + 0x80, /* dds */ + 0x80, /* dar */ + 0x80, /* dpt */ + 0x00, /* dul */ + 0x00, /* dse */ + 0x00, /* dot */ + 0xDE /* CS */ + }; + fwrite (b, 1, sizeof (b), file); +} + +/* Write out the SC records for a unit. Create an SC + for all the sections which appear in the output file, even + if there isn't an equivalent one on the input */ + +static int +wr_sc (ptr, sfile) + struct coff_ofile *ptr; + struct coff_sfile *sfile; +{ + int i; +int scount = 0; + /* First work out the total number of sections */ + + int total_sec = ptr->nsections; + + struct myinfo + { + struct coff_section *sec; + struct coff_symbol *symbol; + }; + struct coff_symbol *symbol; + + struct myinfo *info + = (struct myinfo *) calloc (total_sec, sizeof (struct myinfo)); + + + + for (i = 0; i < total_sec; i++) + { + info[i].sec = ptr->sections + i; + info[i].symbol = 0; + } + + for (symbol = sfile->scope->vars_head; + symbol; + symbol = symbol->next) + { + + if (symbol->type->type == coff_secdef_type) + { + for (i = 0; i < total_sec; i++) + { + if (symbol->where->section == info[i].sec) + { + info[i].symbol = symbol; + break; + } + } + } + } + + /* Now output all the section info, and fake up some stuff for sections + we don't have */ + + for (i = 1; i < total_sec; i++) + { + struct IT_sc sc; + char *name; + symbol = info[i].symbol; + sc.spare = 0; + sc.spare1 = 0; + if (!symbol) + { + /* Don't have a symbol set aside for this section, which means that nothing + in this file does anything for the section. */ + sc.format = !(bfd_get_file_flags (abfd) & EXEC_P); + sc.addr = 0; + sc.length = 0; + name = info[i].sec->name; + } + else + { + if (bfd_get_file_flags (abfd) & EXEC_P) + { + sc.format = 0; + sc.addr = symbol->where->offset; + } + else + { + sc.format = 1; + sc.addr = 0; + } + sc.length = symbol->type->size; + name = symbol->name; + } + + sc.align = 4; + + sc.concat = CONCAT_SIMPLE; + sc.read = 3; + sc.write = 3; + sc.exec = 3; + sc.init = 3; + sc.mode = 3; + sc.spare = 0; + sc.segadd = 0; + sc.spare1 = 0; /* If not zero, then it doesn't work */ + sc.name = section_translate (name); + if (strlen (sc.name) == 1) + { + switch (sc.name[0]) + { + case 'D': + case 'B': + sc.contents = CONTENTS_DATA; + break; + default: + sc.contents = CONTENTS_CODE; + } + } + else + { + sc.contents = CONTENTS_CODE; + } +#if 0 + /* NEW */ + if (sc.length) { +#endif + sysroff_swap_sc_out (file, &sc); + scount++; +#if 0 + } +#endif + } +return scount; +} + + +/* Write out the ER records for a unit. */ +static void +wr_er (ptr, sfile, first) + struct coff_ofile *ptr; + struct coff_sfile *sfile; + int first; +{ + int idx = 0; + struct coff_symbol *sym; + if (first) + { + for (sym = ptr->symbol_list_head; sym; sym = sym->next_in_ofile_list) + { + if (sym->visible->type == coff_vis_ext_ref) + { + struct IT_er er; + er.spare = 0; + er.type = ER_NOTSPEC; + er.name = sym->name; + sysroff_swap_er_out (file, &er); + sym->er_number = idx++; + } + } + } +} + +/* Write out the ED records for a unit. */ +static void +wr_ed (ptr, sfile, first) + struct coff_ofile *ptr; + struct coff_sfile *sfile; + int first; +{ + struct coff_symbol *s; + if (first) + { + for (s = ptr->symbol_list_head; s; s = s->next_in_ofile_list) + { + if (s->visible->type == coff_vis_ext_def + || s->visible->type == coff_vis_common) + { + struct IT_ed ed; + + ed.section = s->where->section->number; + ed.spare = 0; + if (s->where->section->data) + { + ed.type = ED_TYPE_DATA; + } + else if (s->where->section->code & SEC_CODE) + { + ed.type = ED_TYPE_ENTRY; + } + else + { + ed.type = ED_TYPE_NOTSPEC; + ed.type = ED_TYPE_DATA; + } + ed.address = s->where->offset - s->where->section->address; + ed.name = s->name; + sysroff_swap_ed_out (file, &ed); + } + } + } +} + +static void +wr_unit_info (ptr) + struct coff_ofile *ptr; +{ + struct coff_sfile *sfile; + int first = 1; + for (sfile = ptr->source_head; + sfile; + sfile = sfile->next) + { + long p1; + long p2; + int nsecs; + p1 = ftell (file); + wr_un (ptr, sfile, first, 0); + nsecs = wr_sc (ptr, sfile); + p2 = ftell (file); + fseek (file, p1, SEEK_SET); + wr_un (ptr, sfile, first, nsecs); + fseek (file, p2, SEEK_SET); + wr_er (ptr, sfile, first); + wr_ed (ptr, sfile, first); + first = 0; + } +} + +static void +wr_module (p) + struct coff_ofile *p; +{ + wr_cs (); + wr_hd (p); + wr_unit_info (p); + wr_object_body (p); + wr_debug (p); + wr_tr (); +} + +static int +align (x) + int x; +{ + return (x + 3) & ~3; +} + +/* Find all the common variables and turn them into + ordinary defs - dunno why, but thats what hitachi does with 'em */ + +static void +prescan (tree) + struct coff_ofile *tree; +{ + struct coff_symbol *s; + struct coff_section *common_section; + /* Find the common section - always section 3 */ + common_section = tree->sections + 3; + for (s = tree->symbol_list_head; + s; + s = s->next_in_ofile_list) + { + if (s->visible->type == coff_vis_common) + { + struct coff_where *w = s->where; + /* s->visible->type = coff_vis_ext_def; leave it as common */ + common_section->size = align (common_section->size); + w->offset = common_section->size + common_section->address; + w->section = common_section; + common_section->size += s->type->size; + common_section->size = align (common_section->size); + } + } +} + +char *program_name; + +static void +show_usage (file, status) + FILE *file; + int status; +{ + fprintf (file, _("Usage: %s [-dhVq] in-file [out-file]\n"), program_name); + exit (status); +} + +static void +show_help () +{ + printf (_("%s: Convert a COFF object file into a SYSROFF object file\n"), + program_name); + show_usage (stdout, 0); +} + + + +int +main (ac, av) + int ac; + char *av[]; +{ + int opt; + static struct option long_options[] = + { + {"debug", no_argument, 0, 'd'}, + {"quick", no_argument, 0, 'q'}, + {"noprescan", no_argument, 0, 'n'}, + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'V'}, + {NULL, no_argument, 0, 0} + }; + char **matching; + char *input_file; + char *output_file; + +#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) + setlocale (LC_MESSAGES, ""); +#endif + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + + program_name = av[0]; + xmalloc_set_program_name (program_name); + + while ((opt = getopt_long (ac, av, "dhVqn", long_options, + (int *) NULL)) + != EOF) + { + switch (opt) + { + case 'q': + quick = 1; + break; + case 'n': + noprescan = 1; + break; + case 'd': + debug = 1; + break; + case 'h': + show_help (); + /*NOTREACHED */ + case 'V': + printf (_("GNU %s version %s\n"), program_name, PROGRAM_VERSION); + exit (0); + /*NOTREACHED */ + case 0: + break; + default: + show_usage (stderr, 1); + /*NOTREACHED */ + } + } + + /* The input and output files may be named on the command line. */ + output_file = NULL; + if (optind < ac) + { + input_file = av[optind]; + ++optind; + if (optind < ac) + { + output_file = av[optind]; + ++optind; + if (optind < ac) + show_usage (stderr, 1); + if (strcmp (input_file, output_file) == 0) + { + fprintf (stderr, + _("%s: input and output files must be different\n"), + program_name); + exit (1); + } + } + } + else + input_file = 0; + + if (!input_file) + { + fprintf (stderr, _("%s: no input file specified\n"), + program_name); + exit (1); + } + + if (!output_file) + { + /* Take a .o off the input file and stick on a .obj. If + it doesn't end in .o, then stick a .obj on anyway */ + + int len = strlen (input_file); + output_file = xmalloc (len + 5); + strcpy (output_file, input_file); + if (len > 3 + && output_file[len - 2] == '.' + && output_file[len - 1] == 'o') + { + output_file[len] = 'b'; + output_file[len + 1] = 'j'; + output_file[len + 2] = 0; + } + else + { + strcat (output_file, ".obj"); + } + } + + abfd = bfd_openr (input_file, 0); + + if (!abfd) + bfd_fatal (input_file); + + if (!bfd_check_format_matches (abfd, bfd_object, &matching)) + { + bfd_nonfatal (input_file); + if (bfd_get_error () == bfd_error_file_ambiguously_recognized) + { + list_matching_formats (matching); + free (matching); + } + exit (1); + } + + file = fopen (output_file, FOPEN_WB); + + if (!file) + { + fprintf (stderr, _("%s: unable to open output file %s\n"), + program_name, output_file); + exit (1); + } + + if (debug) + printf ("ids %d %d\n", base1, base2); + tree = coff_grok (abfd); + if (!noprescan) + prescan (tree); + wr_module (tree); + return 0; +} diff --git a/binutils/stabs.c b/binutils/stabs.c new file mode 100644 index 0000000..a47b3bd --- /dev/null +++ b/binutils/stabs.c @@ -0,0 +1,5188 @@ +/* stabs.c -- Parse stabs debugging information + Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + Written by Ian Lance Taylor <ian@cygnus.com>. + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* This file contains code which parses stabs debugging information. + The organization of this code is based on the gdb stabs reading + code. The job it does is somewhat different, because it is not + trying to identify the correct address for anything. */ + +#include <stdio.h> +#include <ctype.h> + +#include "bfd.h" +#include "bucomm.h" +#include "libiberty.h" +#include "demangle.h" +#include "debug.h" +#include "budbg.h" + +/* Meaningless definition needs by aout64.h. FIXME. */ +#define BYTES_IN_WORD 4 + +#include "aout/aout64.h" +#include "aout/stab_gnu.h" + +#ifndef DIR_SEPARATOR +#ifdef _WIN32 +#define DIR_SEPARATOR '\\' +#else +#define DIR_SEPARATOR '/' +#endif +#endif + +/* The number of predefined XCOFF types. */ + +#define XCOFF_TYPE_COUNT 34 + +/* This structure is used as a handle so that the stab parsing doesn't + need to use any static variables. */ + +struct stab_handle +{ + /* The BFD. */ + bfd *abfd; + /* True if this is stabs in sections. */ + boolean sections; + /* The symbol table. */ + asymbol **syms; + /* The number of symbols. */ + long symcount; + /* The accumulated file name string. */ + char *so_string; + /* The value of the last N_SO symbol. */ + bfd_vma so_value; + /* The value of the start of the file, so that we can handle file + relative N_LBRAC and N_RBRAC symbols. */ + bfd_vma file_start_offset; + /* The offset of the start of the function, so that we can handle + function relative N_LBRAC and N_RBRAC symbols. */ + bfd_vma function_start_offset; + /* The version number of gcc which compiled the current compilation + unit, 0 if not compiled by gcc. */ + int gcc_compiled; + /* Whether an N_OPT symbol was seen that was not generated by gcc, + so that we can detect the SunPRO compiler. */ + boolean n_opt_found; + /* The main file name. */ + char *main_filename; + /* A stack of unfinished N_BINCL files. */ + struct bincl_file *bincl_stack; + /* A list of finished N_BINCL files. */ + struct bincl_file *bincl_list; + /* Whether we are inside a function or not. */ + boolean within_function; + /* The address of the end of the function, used if we have seen an + N_FUN symbol while in a function. This is -1 if we have not seen + an N_FUN (the normal case). */ + bfd_vma function_end; + /* The depth of block nesting. */ + int block_depth; + /* List of pending variable definitions. */ + struct stab_pending_var *pending; + /* Number of files for which we have types. */ + unsigned int files; + /* Lists of types per file. */ + struct stab_types **file_types; + /* Predefined XCOFF types. */ + debug_type xcoff_types[XCOFF_TYPE_COUNT]; + /* Undefined tags. */ + struct stab_tag *tags; + /* Set by parse_stab_type if it sees a structure defined as a cross + reference to itself. Reset by parse_stab_type otherwise. */ + boolean self_crossref; +}; + +/* A list of these structures is used to hold pending variable + definitions seen before the N_LBRAC of a block. */ + +struct stab_pending_var +{ + /* Next pending variable definition. */ + struct stab_pending_var *next; + /* Name. */ + const char *name; + /* Type. */ + debug_type type; + /* Kind. */ + enum debug_var_kind kind; + /* Value. */ + bfd_vma val; +}; + +/* A list of these structures is used to hold the types for a single + file. */ + +struct stab_types +{ + /* Next set of slots for this file. */ + struct stab_types *next; + /* Types indexed by type number. */ +#define STAB_TYPES_SLOTS (16) + debug_type types[STAB_TYPES_SLOTS]; +}; + +/* We keep a list of undefined tags that we encounter, so that we can + fill them in if the tag is later defined. */ + +struct stab_tag +{ + /* Next undefined tag. */ + struct stab_tag *next; + /* Tag name. */ + const char *name; + /* Type kind. */ + enum debug_type_kind kind; + /* Slot to hold real type when we discover it. If we don't, we fill + in an undefined tag type. */ + debug_type slot; + /* Indirect type we have created to point at slot. */ + debug_type type; +}; + +static char *savestring PARAMS ((const char *, int)); +static bfd_vma parse_number PARAMS ((const char **, boolean *)); +static void bad_stab PARAMS ((const char *)); +static void warn_stab PARAMS ((const char *, const char *)); +static boolean parse_stab_string + PARAMS ((PTR, struct stab_handle *, int, int, bfd_vma, const char *)); +static debug_type parse_stab_type + PARAMS ((PTR, struct stab_handle *, const char *, const char **, + debug_type **)); +static boolean parse_stab_type_number + PARAMS ((const char **, int *)); +static debug_type parse_stab_range_type + PARAMS ((PTR, struct stab_handle *, const char *, const char **, + const int *)); +static debug_type parse_stab_sun_builtin_type PARAMS ((PTR, const char **)); +static debug_type parse_stab_sun_floating_type + PARAMS ((PTR, const char **)); +static debug_type parse_stab_enum_type PARAMS ((PTR, const char **)); +static debug_type parse_stab_struct_type + PARAMS ((PTR, struct stab_handle *, const char *, const char **, boolean, + const int *)); +static boolean parse_stab_baseclasses + PARAMS ((PTR, struct stab_handle *, const char **, debug_baseclass **)); +static boolean parse_stab_struct_fields + PARAMS ((PTR, struct stab_handle *, const char **, debug_field **, + boolean *)); +static boolean parse_stab_cpp_abbrev + PARAMS ((PTR, struct stab_handle *, const char **, debug_field *)); +static boolean parse_stab_one_struct_field + PARAMS ((PTR, struct stab_handle *, const char **, const char *, + debug_field *, boolean *)); +static boolean parse_stab_members + PARAMS ((PTR, struct stab_handle *, const char *, const char **, + const int *, debug_method **)); +static debug_type parse_stab_argtypes + PARAMS ((PTR, struct stab_handle *, debug_type, const char *, const char *, + debug_type, const char *, boolean, boolean, const char **)); +static boolean parse_stab_tilde_field + PARAMS ((PTR, struct stab_handle *, const char **, const int *, + debug_type *, boolean *)); +static debug_type parse_stab_array_type + PARAMS ((PTR, struct stab_handle *, const char **, boolean)); +static void push_bincl PARAMS ((struct stab_handle *, const char *, bfd_vma)); +static const char *pop_bincl PARAMS ((struct stab_handle *)); +static boolean find_excl + PARAMS ((struct stab_handle *, const char *, bfd_vma)); +static boolean stab_record_variable + PARAMS ((PTR, struct stab_handle *, const char *, debug_type, + enum debug_var_kind, bfd_vma)); +static boolean stab_emit_pending_vars PARAMS ((PTR, struct stab_handle *)); +static debug_type *stab_find_slot + PARAMS ((struct stab_handle *, const int *)); +static debug_type stab_find_type + PARAMS ((PTR, struct stab_handle *, const int *)); +static boolean stab_record_type + PARAMS ((PTR, struct stab_handle *, const int *, debug_type)); +static debug_type stab_xcoff_builtin_type + PARAMS ((PTR, struct stab_handle *, int)); +static debug_type stab_find_tagged_type + PARAMS ((PTR, struct stab_handle *, const char *, int, + enum debug_type_kind)); +static debug_type *stab_demangle_argtypes + PARAMS ((PTR, struct stab_handle *, const char *, boolean *)); + +/* Save a string in memory. */ + +static char * +savestring (start, len) + const char *start; + int len; +{ + char *ret; + + ret = (char *) xmalloc (len + 1); + memcpy (ret, start, len); + ret[len] = '\0'; + return ret; +} + +/* Read a number from a string. */ + +static bfd_vma +parse_number (pp, poverflow) + const char **pp; + boolean *poverflow; +{ + unsigned long ul; + const char *orig; + + if (poverflow != NULL) + *poverflow = false; + + orig = *pp; + + errno = 0; + ul = strtoul (*pp, (char **) pp, 0); + if (ul + 1 != 0 || errno == 0) + { + /* If bfd_vma is larger than unsigned long, and the number is + meant to be negative, we have to make sure that we sign + extend properly. */ + if (*orig == '-') + return (bfd_vma) (bfd_signed_vma) (long) ul; + return (bfd_vma) ul; + } + + /* Note that even though strtoul overflowed, it should have set *pp + to the end of the number, which is where we want it. */ + + if (sizeof (bfd_vma) > sizeof (unsigned long)) + { + const char *p; + boolean neg; + int base; + bfd_vma over, lastdig; + boolean overflow; + bfd_vma v; + + /* Our own version of strtoul, for a bfd_vma. */ + + p = orig; + + neg = false; + if (*p == '+') + ++p; + else if (*p == '-') + { + neg = true; + ++p; + } + + base = 10; + if (*p == '0') + { + if (p[1] == 'x' || p[1] == 'X') + { + base = 16; + p += 2; + } + else + { + base = 8; + ++p; + } + } + + over = ((bfd_vma) (bfd_signed_vma) -1) / (bfd_vma) base; + lastdig = ((bfd_vma) (bfd_signed_vma) -1) % (bfd_vma) base; + + overflow = false; + v = 0; + while (1) + { + int d; + + d = *p++; + if (isdigit ((unsigned char) d)) + d -= '0'; + else if (isupper ((unsigned char) d)) + d -= 'A'; + else if (islower ((unsigned char) d)) + d -= 'a'; + else + break; + + if (d >= base) + break; + + if (v > over || (v == over && (bfd_vma) d > lastdig)) + { + overflow = true; + break; + } + } + + if (! overflow) + { + if (neg) + v = - v; + return v; + } + } + + /* If we get here, the number is too large to represent in a + bfd_vma. */ + + if (poverflow != NULL) + *poverflow = true; + else + warn_stab (orig, _("numeric overflow")); + + return 0; +} + +/* Give an error for a bad stab string. */ + +static void +bad_stab (p) + const char *p; +{ + fprintf (stderr, _("Bad stab: %s\n"), p); +} + +/* Warn about something in a stab string. */ + +static void +warn_stab (p, err) + const char *p; + const char *err; +{ + fprintf (stderr, _("Warning: %s: %s\n"), err, p); +} + +/* Create a handle to parse stabs symbols with. */ + +/*ARGSUSED*/ +PTR +start_stab (dhandle, abfd, sections, syms, symcount) + PTR dhandle; + bfd *abfd; + boolean sections; + asymbol **syms; + long symcount; +{ + struct stab_handle *ret; + + ret = (struct stab_handle *) xmalloc (sizeof *ret); + memset (ret, 0, sizeof *ret); + ret->abfd = abfd; + ret->sections = sections; + ret->syms = syms; + ret->symcount = symcount; + ret->files = 1; + ret->file_types = (struct stab_types **) xmalloc (sizeof *ret->file_types); + ret->file_types[0] = NULL; + ret->function_end = (bfd_vma) -1; + return (PTR) ret; +} + +/* When we have processed all the stabs information, we need to go + through and fill in all the undefined tags. */ + +boolean +finish_stab (dhandle, handle) + PTR dhandle; + PTR handle; +{ + struct stab_handle *info = (struct stab_handle *) handle; + struct stab_tag *st; + + if (info->within_function) + { + if (! stab_emit_pending_vars (dhandle, info) + || ! debug_end_function (dhandle, info->function_end)) + return false; + info->within_function = false; + info->function_end = (bfd_vma) -1; + } + + for (st = info->tags; st != NULL; st = st->next) + { + enum debug_type_kind kind; + + kind = st->kind; + if (kind == DEBUG_KIND_ILLEGAL) + kind = DEBUG_KIND_STRUCT; + st->slot = debug_make_undefined_tagged_type (dhandle, st->name, kind); + if (st->slot == DEBUG_TYPE_NULL) + return false; + } + + return true; +} + +/* Handle a single stabs symbol. */ + +boolean +parse_stab (dhandle, handle, type, desc, value, string) + PTR dhandle; + PTR handle; + int type; + int desc; + bfd_vma value; + const char *string; +{ + struct stab_handle *info = (struct stab_handle *) handle; + + /* gcc will emit two N_SO strings per compilation unit, one for the + directory name and one for the file name. We just collect N_SO + strings as we see them, and start the new compilation unit when + we see a non N_SO symbol. */ + if (info->so_string != NULL + && (type != N_SO || *string == '\0' || value != info->so_value)) + { + if (! debug_set_filename (dhandle, info->so_string)) + return false; + info->main_filename = info->so_string; + + info->gcc_compiled = 0; + info->n_opt_found = false; + + /* Generally, for stabs in the symbol table, the N_LBRAC and + N_RBRAC symbols are relative to the N_SO symbol value. */ + if (! info->sections) + info->file_start_offset = info->so_value; + + /* We need to reset the mapping from type numbers to types. We + can't free the old mapping, because of the use of + debug_make_indirect_type. */ + info->files = 1; + info->file_types = ((struct stab_types **) + xmalloc (sizeof *info->file_types)); + info->file_types[0] = NULL; + + info->so_string = NULL; + + /* Now process whatever type we just got. */ + } + + switch (type) + { + case N_FN: + case N_FN_SEQ: + break; + + case N_LBRAC: + /* Ignore extra outermost context from SunPRO cc and acc. */ + if (info->n_opt_found && desc == 1) + break; + + if (! info->within_function) + { + fprintf (stderr, _("N_LBRAC not within function\n")); + return false; + } + + /* Start an inner lexical block. */ + if (! debug_start_block (dhandle, + (value + + info->file_start_offset + + info->function_start_offset))) + return false; + + /* Emit any pending variable definitions. */ + if (! stab_emit_pending_vars (dhandle, info)) + return false; + + ++info->block_depth; + break; + + case N_RBRAC: + /* Ignore extra outermost context from SunPRO cc and acc. */ + if (info->n_opt_found && desc == 1) + break; + + /* We shouldn't have any pending variable definitions here, but, + if we do, we probably need to emit them before closing the + block. */ + if (! stab_emit_pending_vars (dhandle, info)) + return false; + + /* End an inner lexical block. */ + if (! debug_end_block (dhandle, + (value + + info->file_start_offset + + info->function_start_offset))) + return false; + + --info->block_depth; + if (info->block_depth < 0) + { + fprintf (stderr, _("Too many N_RBRACs\n")); + return false; + } + break; + + case N_SO: + /* This always ends a function. */ + if (info->within_function) + { + bfd_vma endval; + + endval = value; + if (*string != '\0' + && info->function_end != (bfd_vma) -1 + && info->function_end < endval) + endval = info->function_end; + if (! stab_emit_pending_vars (dhandle, info) + || ! debug_end_function (dhandle, endval)) + return false; + info->within_function = false; + info->function_end = (bfd_vma) -1; + } + + /* An empty string is emitted by gcc at the end of a compilation + unit. */ + if (*string == '\0') + return true; + + /* Just accumulate strings until we see a non N_SO symbol. If + the string starts with a directory separator or some other + form of absolute path specification, we discard the previously + accumulated strings. */ + if (info->so_string == NULL) + info->so_string = xstrdup (string); + else + { + char *f; + + f = info->so_string; + + if ( (string[0] == '/') + || (string[0] == DIR_SEPARATOR) + || ( (DIR_SEPARATOR == '\\') + && (string[1] == ':') + && ( (string[2] == DIR_SEPARATOR) + || (string[2] == '/')))) + info->so_string = xstrdup (string); + else + info->so_string = concat (info->so_string, string, + (const char *) NULL); + free (f); + } + + info->so_value = value; + + break; + + case N_SOL: + /* Start an include file. */ + if (! debug_start_source (dhandle, string)) + return false; + break; + + case N_BINCL: + /* Start an include file which may be replaced. */ + push_bincl (info, string, value); + if (! debug_start_source (dhandle, string)) + return false; + break; + + case N_EINCL: + /* End an N_BINCL include. */ + if (! debug_start_source (dhandle, pop_bincl (info))) + return false; + break; + + case N_EXCL: + /* This is a duplicate of a header file named by N_BINCL which + was eliminated by the linker. */ + if (! find_excl (info, string, value)) + return false; + break; + + case N_SLINE: + if (! debug_record_line (dhandle, desc, + value + info->function_start_offset)) + return false; + break; + + case N_BCOMM: + if (! debug_start_common_block (dhandle, string)) + return false; + break; + + case N_ECOMM: + if (! debug_end_common_block (dhandle, string)) + return false; + break; + + case N_FUN: + if (*string == '\0') + { + if (info->within_function) + { + /* This always marks the end of a function; we don't + need to worry about info->function_end. */ + if (info->sections) + value += info->function_start_offset; + if (! stab_emit_pending_vars (dhandle, info) + || ! debug_end_function (dhandle, value)) + return false; + info->within_function = false; + info->function_end = (bfd_vma) -1; + } + break; + } + + /* A const static symbol in the .text section will have an N_FUN + entry. We need to use these to mark the end of the function, + in case we are looking at gcc output before it was changed to + always emit an empty N_FUN. We can't call debug_end_function + here, because it might be a local static symbol. */ + if (info->within_function + && (info->function_end == (bfd_vma) -1 + || value < info->function_end)) + info->function_end = value; + + /* Fall through. */ + /* FIXME: gdb checks the string for N_STSYM, N_LCSYM or N_ROSYM + symbols, and if it does not start with :S, gdb relocates the + value to the start of the section. gcc always seems to use + :S, so we don't worry about this. */ + /* Fall through. */ + default: + { + const char *colon; + + colon = strchr (string, ':'); + if (colon != NULL + && (colon[1] == 'f' || colon[1] == 'F')) + { + if (info->within_function) + { + bfd_vma endval; + + endval = value; + if (info->function_end != (bfd_vma) -1 + && info->function_end < endval) + endval = info->function_end; + if (! stab_emit_pending_vars (dhandle, info) + || ! debug_end_function (dhandle, endval)) + return false; + info->function_end = (bfd_vma) -1; + } + /* For stabs in sections, line numbers and block addresses + are offsets from the start of the function. */ + if (info->sections) + info->function_start_offset = value; + info->within_function = true; + } + + if (! parse_stab_string (dhandle, info, type, desc, value, string)) + return false; + } + break; + + case N_OPT: + if (string != NULL && strcmp (string, "gcc2_compiled.") == 0) + info->gcc_compiled = 2; + else if (string != NULL && strcmp (string, "gcc_compiled.") == 0) + info->gcc_compiled = 1; + else + info->n_opt_found = true; + break; + + case N_OBJ: + case N_ENDM: + case N_MAIN: + break; + } + + return true; +} + +/* Parse the stabs string. */ + +static boolean +parse_stab_string (dhandle, info, stabtype, desc, value, string) + PTR dhandle; + struct stab_handle *info; + int stabtype; + int desc; + bfd_vma value; + const char *string; +{ + const char *p; + char *name; + int type; + debug_type dtype; + boolean synonym; + boolean self_crossref; + unsigned int lineno; + debug_type *slot; + + p = strchr (string, ':'); + if (p == NULL) + return true; + + while (p[1] == ':') + { + p += 2; + p = strchr (p, ':'); + if (p == NULL) + { + bad_stab (string); + return false; + } + } + + /* GCC 2.x puts the line number in desc. SunOS apparently puts in + the number of bytes occupied by a type or object, which we + ignore. */ + if (info->gcc_compiled >= 2) + lineno = desc; + else + lineno = 0; + + /* FIXME: Sometimes the special C++ names start with '.'. */ + name = NULL; + if (string[0] == '$') + { + switch (string[1]) + { + case 't': + name = "this"; + break; + case 'v': + /* Was: name = "vptr"; */ + break; + case 'e': + name = "eh_throw"; + break; + case '_': + /* This was an anonymous type that was never fixed up. */ + break; + case 'X': + /* SunPRO (3.0 at least) static variable encoding. */ + break; + default: + warn_stab (string, _("unknown C++ encoded name")); + break; + } + } + + if (name == NULL) + { + if (p == string || (string[0] == ' ' && p == string + 1)) + name = NULL; + else + name = savestring (string, p - string); + } + + ++p; + if (isdigit ((unsigned char) *p) || *p == '(' || *p == '-') + type = 'l'; + else + type = *p++; + + switch (type) + { + case 'c': + /* c is a special case, not followed by a type-number. + SYMBOL:c=iVALUE for an integer constant symbol. + SYMBOL:c=rVALUE for a floating constant symbol. + SYMBOL:c=eTYPE,INTVALUE for an enum constant symbol. + e.g. "b:c=e6,0" for "const b = blob1" + (where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;"). */ + if (*p != '=') + { + bad_stab (string); + return false; + } + ++p; + switch (*p++) + { + case 'r': + /* Floating point constant. */ + if (! debug_record_float_const (dhandle, name, atof (p))) + return false; + break; + case 'i': + /* Integer constant. */ + /* Defining integer constants this way is kind of silly, + since 'e' constants allows the compiler to give not only + the value, but the type as well. C has at least int, + long, unsigned int, and long long as constant types; + other languages probably should have at least unsigned as + well as signed constants. */ + if (! debug_record_int_const (dhandle, name, atoi (p))) + return false; + break; + case 'e': + /* SYMBOL:c=eTYPE,INTVALUE for a constant symbol whose value + can be represented as integral. + e.g. "b:c=e6,0" for "const b = blob1" + (where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;"). */ + dtype = parse_stab_type (dhandle, info, (const char *) NULL, + &p, (debug_type **) NULL); + if (dtype == DEBUG_TYPE_NULL) + return false; + if (*p != ',') + { + bad_stab (string); + return false; + } + if (! debug_record_typed_const (dhandle, name, dtype, atoi (p))) + return false; + break; + default: + bad_stab (string); + return false; + } + + break; + + case 'C': + /* The name of a caught exception. */ + dtype = parse_stab_type (dhandle, info, (const char *) NULL, + &p, (debug_type **) NULL); + if (dtype == DEBUG_TYPE_NULL) + return false; + if (! debug_record_label (dhandle, name, dtype, value)) + return false; + break; + + case 'f': + case 'F': + /* A function definition. */ + dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, + (debug_type **) NULL); + if (dtype == DEBUG_TYPE_NULL) + return false; + if (! debug_record_function (dhandle, name, dtype, type == 'F', value)) + return false; + + /* Sun acc puts declared types of arguments here. We don't care + about their actual types (FIXME -- we should remember the whole + function prototype), but the list may define some new types + that we have to remember, so we must scan it now. */ + while (*p == ';') + { + ++p; + if (parse_stab_type (dhandle, info, (const char *) NULL, &p, + (debug_type **) NULL) + == DEBUG_TYPE_NULL) + return false; + } + + break; + + case 'G': + { + char leading; + long c; + asymbol **ps; + + /* A global symbol. The value must be extracted from the + symbol table. */ + dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, + (debug_type **) NULL); + if (dtype == DEBUG_TYPE_NULL) + return false; + leading = bfd_get_symbol_leading_char (info->abfd); + for (c = info->symcount, ps = info->syms; c > 0; --c, ++ps) + { + const char *n; + + n = bfd_asymbol_name (*ps); + if (leading != '\0' && *n == leading) + ++n; + if (*n == *name && strcmp (n, name) == 0) + break; + } + if (c > 0) + value = bfd_asymbol_value (*ps); + if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_GLOBAL, + value)) + return false; + } + break; + + /* This case is faked by a conditional above, when there is no + code letter in the dbx data. Dbx data never actually + contains 'l'. */ + case 'l': + case 's': + dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, + (debug_type **) NULL); + if (dtype == DEBUG_TYPE_NULL) + return false; + if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_LOCAL, + value)) + return false; + break; + + case 'p': + /* A function parameter. */ + if (*p != 'F') + dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, + (debug_type **) NULL); + else + { + /* pF is a two-letter code that means a function parameter in + Fortran. The type-number specifies the type of the return + value. Translate it into a pointer-to-function type. */ + ++p; + dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, + (debug_type **) NULL); + if (dtype != DEBUG_TYPE_NULL) + { + debug_type ftype; + + ftype = debug_make_function_type (dhandle, dtype, + (debug_type *) NULL, false); + dtype = debug_make_pointer_type (dhandle, ftype); + } + } + if (dtype == DEBUG_TYPE_NULL) + return false; + if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_STACK, + value)) + return false; + + /* FIXME: At this point gdb considers rearranging the parameter + address on a big endian machine if it is smaller than an int. + We have no way to do that, since we don't really know much + about the target. */ + + break; + + case 'P': + if (stabtype == N_FUN) + { + /* Prototype of a function referenced by this file. */ + while (*p == ';') + { + ++p; + if (parse_stab_type (dhandle, info, (const char *) NULL, &p, + (debug_type **) NULL) + == DEBUG_TYPE_NULL) + return false; + } + break; + } + /* Fall through. */ + case 'R': + /* Parameter which is in a register. */ + dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, + (debug_type **) NULL); + if (dtype == DEBUG_TYPE_NULL) + return false; + if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REG, + value)) + return false; + break; + + case 'r': + /* Register variable (either global or local). */ + dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, + (debug_type **) NULL); + if (dtype == DEBUG_TYPE_NULL) + return false; + if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_REGISTER, + value)) + return false; + + /* FIXME: At this point gdb checks to combine pairs of 'p' and + 'r' stabs into a single 'P' stab. */ + + break; + + case 'S': + /* Static symbol at top level of file */ + dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, + (debug_type **) NULL); + if (dtype == DEBUG_TYPE_NULL) + return false; + if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_STATIC, + value)) + return false; + break; + + case 't': + /* A typedef. */ + dtype = parse_stab_type (dhandle, info, name, &p, &slot); + if (dtype == DEBUG_TYPE_NULL) + return false; + if (name == NULL) + { + /* A nameless type. Nothing to do. */ + return true; + } + + dtype = debug_name_type (dhandle, name, dtype); + if (dtype == DEBUG_TYPE_NULL) + return false; + + if (slot != NULL) + *slot = dtype; + + break; + + case 'T': + /* Struct, union, or enum tag. For GNU C++, this can be be followed + by 't' which means we are typedef'ing it as well. */ + if (*p != 't') + { + synonym = false; + /* FIXME: gdb sets synonym to true if the current language + is C++. */ + } + else + { + synonym = true; + ++p; + } + + dtype = parse_stab_type (dhandle, info, name, &p, &slot); + if (dtype == DEBUG_TYPE_NULL) + return false; + if (name == NULL) + return true; + + /* INFO->SELF_CROSSREF is set by parse_stab_type if this type is + a cross reference to itself. These are generated by some + versions of g++. */ + self_crossref = info->self_crossref; + + dtype = debug_tag_type (dhandle, name, dtype); + if (dtype == DEBUG_TYPE_NULL) + return false; + if (slot != NULL) + *slot = dtype; + + /* See if we have a cross reference to this tag which we can now + fill in. Avoid filling in a cross reference to ourselves, + because that would lead to circular debugging information. */ + if (! self_crossref) + { + register struct stab_tag **pst; + + for (pst = &info->tags; *pst != NULL; pst = &(*pst)->next) + { + if ((*pst)->name[0] == name[0] + && strcmp ((*pst)->name, name) == 0) + { + (*pst)->slot = dtype; + *pst = (*pst)->next; + break; + } + } + } + + if (synonym) + { + dtype = debug_name_type (dhandle, name, dtype); + if (dtype == DEBUG_TYPE_NULL) + return false; + + if (slot != NULL) + *slot = dtype; + } + + break; + + case 'V': + /* Static symbol of local scope */ + dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, + (debug_type **) NULL); + if (dtype == DEBUG_TYPE_NULL) + return false; + /* FIXME: gdb checks os9k_stabs here. */ + if (! stab_record_variable (dhandle, info, name, dtype, + DEBUG_LOCAL_STATIC, value)) + return false; + break; + + case 'v': + /* Reference parameter. */ + dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, + (debug_type **) NULL); + if (dtype == DEBUG_TYPE_NULL) + return false; + if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REFERENCE, + value)) + return false; + break; + + case 'a': + /* Reference parameter which is in a register. */ + dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, + (debug_type **) NULL); + if (dtype == DEBUG_TYPE_NULL) + return false; + if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REF_REG, + value)) + return false; + break; + + case 'X': + /* This is used by Sun FORTRAN for "function result value". + Sun claims ("dbx and dbxtool interfaces", 2nd ed) + that Pascal uses it too, but when I tried it Pascal used + "x:3" (local symbol) instead. */ + dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, + (debug_type **) NULL); + if (dtype == DEBUG_TYPE_NULL) + return false; + if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_LOCAL, + value)) + return false; + break; + + default: + bad_stab (string); + return false; + } + + /* FIXME: gdb converts structure values to structure pointers in a + couple of cases, depending upon the target. */ + + return true; +} + +/* Parse a stabs type. The typename argument is non-NULL if this is a + typedef or a tag definition. The pp argument points to the stab + string, and is updated. The slotp argument points to a place to + store the slot used if the type is being defined. */ + +static debug_type +parse_stab_type (dhandle, info, typename, pp, slotp) + PTR dhandle; + struct stab_handle *info; + const char *typename; + const char **pp; + debug_type **slotp; +{ + const char *orig; + int typenums[2]; + int size; + boolean stringp; + int descriptor; + debug_type dtype; + + if (slotp != NULL) + *slotp = NULL; + + orig = *pp; + + size = -1; + stringp = false; + + info->self_crossref = false; + + /* Read type number if present. The type number may be omitted. + for instance in a two-dimensional array declared with type + "ar1;1;10;ar1;1;10;4". */ + if (! isdigit ((unsigned char) **pp) && **pp != '(' && **pp != '-') + { + /* 'typenums=' not present, type is anonymous. Read and return + the definition, but don't put it in the type vector. */ + typenums[0] = typenums[1] = -1; + } + else + { + if (! parse_stab_type_number (pp, typenums)) + return DEBUG_TYPE_NULL; + + if (**pp != '=') + { + /* Type is not being defined here. Either it already + exists, or this is a forward reference to it. */ + return stab_find_type (dhandle, info, typenums); + } + + /* Only set the slot if the type is being defined. This means + that the mapping from type numbers to types will only record + the name of the typedef which defines a type. If we don't do + this, then something like + typedef int foo; + int i; + will record that i is of type foo. Unfortunately, stabs + information is ambiguous about variable types. For this code, + typedef int foo; + int i; + foo j; + the stabs information records both i and j as having the same + type. This could be fixed by patching the compiler. */ + if (slotp != NULL && typenums[0] >= 0 && typenums[1] >= 0) + *slotp = stab_find_slot (info, typenums); + + /* Type is being defined here. */ + /* Skip the '='. */ + ++*pp; + + while (**pp == '@') + { + const char *p = *pp + 1; + const char *attr; + + if (isdigit ((unsigned char) *p) || *p == '(' || *p == '-') + { + /* Member type. */ + break; + } + + /* Type attributes. */ + attr = p; + + for (; *p != ';'; ++p) + { + if (*p == '\0') + { + bad_stab (orig); + return DEBUG_TYPE_NULL; + } + } + *pp = p + 1; + + switch (*attr) + { + case 's': + size = atoi (attr + 1); + if (size <= 0) + size = -1; + break; + + case 'S': + stringp = true; + break; + + default: + /* Ignore unrecognized type attributes, so future + compilers can invent new ones. */ + break; + } + } + } + + descriptor = **pp; + ++*pp; + + switch (descriptor) + { + case 'x': + { + enum debug_type_kind code; + const char *q1, *q2, *p; + + /* A cross reference to another type. */ + + switch (**pp) + { + case 's': + code = DEBUG_KIND_STRUCT; + break; + case 'u': + code = DEBUG_KIND_UNION; + break; + case 'e': + code = DEBUG_KIND_ENUM; + break; + default: + /* Complain and keep going, so compilers can invent new + cross-reference types. */ + warn_stab (orig, _("unrecognized cross reference type")); + code = DEBUG_KIND_STRUCT; + break; + } + ++*pp; + + q1 = strchr (*pp, '<'); + p = strchr (*pp, ':'); + if (p == NULL) + { + bad_stab (orig); + return DEBUG_TYPE_NULL; + } + while (q1 != NULL && p > q1 && p[1] == ':') + { + q2 = strchr (q1, '>'); + if (q2 == NULL || q2 < p) + break; + p += 2; + p = strchr (p, ':'); + if (p == NULL) + { + bad_stab (orig); + return DEBUG_TYPE_NULL; + } + } + + /* Some versions of g++ can emit stabs like + fleep:T20=xsfleep: + which define structures in terms of themselves. We need to + tell the caller to avoid building a circular structure. */ + if (typename != NULL + && strncmp (typename, *pp, p - *pp) == 0 + && typename[p - *pp] == '\0') + info->self_crossref = true; + + dtype = stab_find_tagged_type (dhandle, info, *pp, p - *pp, code); + + *pp = p + 1; + } + break; + + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '(': + { + const char *hold; + int xtypenums[2]; + + /* This type is defined as another type. */ + + (*pp)--; + hold = *pp; + + /* Peek ahead at the number to detect void. */ + if (! parse_stab_type_number (pp, xtypenums)) + return DEBUG_TYPE_NULL; + + if (typenums[0] == xtypenums[0] && typenums[1] == xtypenums[1]) + { + /* This type is being defined as itself, which means that + it is void. */ + dtype = debug_make_void_type (dhandle); + } + else + { + *pp = hold; + + /* Go back to the number and have parse_stab_type get it. + This means that we can deal with something like + t(1,2)=(3,4)=... which the Lucid compiler uses. */ + dtype = parse_stab_type (dhandle, info, (const char *) NULL, + pp, (debug_type **) NULL); + if (dtype == DEBUG_TYPE_NULL) + return DEBUG_TYPE_NULL; + } + + if (typenums[0] != -1) + { + if (! stab_record_type (dhandle, info, typenums, dtype)) + return DEBUG_TYPE_NULL; + } + + break; + } + + case '*': + dtype = debug_make_pointer_type (dhandle, + parse_stab_type (dhandle, info, + (const char *) NULL, + pp, + (debug_type **) NULL)); + break; + + case '&': + /* Reference to another type. */ + dtype = (debug_make_reference_type + (dhandle, + parse_stab_type (dhandle, info, (const char *) NULL, pp, + (debug_type **) NULL))); + break; + + case 'f': + /* Function returning another type. */ + /* FIXME: gdb checks os9k_stabs here. */ + dtype = (debug_make_function_type + (dhandle, + parse_stab_type (dhandle, info, (const char *) NULL, pp, + (debug_type **) NULL), + (debug_type *) NULL, false)); + break; + + case 'k': + /* Const qualifier on some type (Sun). */ + /* FIXME: gdb accepts 'c' here if os9k_stabs. */ + dtype = debug_make_const_type (dhandle, + parse_stab_type (dhandle, info, + (const char *) NULL, + pp, + (debug_type **) NULL)); + break; + + case 'B': + /* Volatile qual on some type (Sun). */ + /* FIXME: gdb accepts 'i' here if os9k_stabs. */ + dtype = (debug_make_volatile_type + (dhandle, + parse_stab_type (dhandle, info, (const char *) NULL, pp, + (debug_type **) NULL))); + break; + + case '@': + /* Offset (class & variable) type. This is used for a pointer + relative to an object. */ + { + debug_type domain; + debug_type memtype; + + /* Member type. */ + + domain = parse_stab_type (dhandle, info, (const char *) NULL, pp, + (debug_type **) NULL); + if (domain == DEBUG_TYPE_NULL) + return DEBUG_TYPE_NULL; + + if (**pp != ',') + { + bad_stab (orig); + return DEBUG_TYPE_NULL; + } + ++*pp; + + memtype = parse_stab_type (dhandle, info, (const char *) NULL, pp, + (debug_type **) NULL); + if (memtype == DEBUG_TYPE_NULL) + return DEBUG_TYPE_NULL; + + dtype = debug_make_offset_type (dhandle, domain, memtype); + } + break; + + case '#': + /* Method (class & fn) type. */ + if (**pp == '#') + { + debug_type return_type; + + ++*pp; + return_type = parse_stab_type (dhandle, info, (const char *) NULL, + pp, (debug_type **) NULL); + if (return_type == DEBUG_TYPE_NULL) + return DEBUG_TYPE_NULL; + if (**pp != ';') + { + bad_stab (orig); + return DEBUG_TYPE_NULL; + } + ++*pp; + dtype = debug_make_method_type (dhandle, return_type, + DEBUG_TYPE_NULL, + (debug_type *) NULL, false); + } + else + { + debug_type domain; + debug_type return_type; + debug_type *args; + unsigned int n; + unsigned int alloc; + boolean varargs; + + domain = parse_stab_type (dhandle, info, (const char *) NULL, + pp, (debug_type **) NULL); + if (domain == DEBUG_TYPE_NULL) + return DEBUG_TYPE_NULL; + + if (**pp != ',') + { + bad_stab (orig); + return DEBUG_TYPE_NULL; + } + ++*pp; + + return_type = parse_stab_type (dhandle, info, (const char *) NULL, + pp, (debug_type **) NULL); + if (return_type == DEBUG_TYPE_NULL) + return DEBUG_TYPE_NULL; + + alloc = 10; + args = (debug_type *) xmalloc (alloc * sizeof *args); + n = 0; + while (**pp != ';') + { + if (**pp != ',') + { + bad_stab (orig); + return DEBUG_TYPE_NULL; + } + ++*pp; + + if (n + 1 >= alloc) + { + alloc += 10; + args = ((debug_type *) + xrealloc ((PTR) args, alloc * sizeof *args)); + } + + args[n] = parse_stab_type (dhandle, info, (const char *) NULL, + pp, (debug_type **) NULL); + if (args[n] == DEBUG_TYPE_NULL) + return DEBUG_TYPE_NULL; + ++n; + } + ++*pp; + + /* If the last type is not void, then this function takes a + variable number of arguments. Otherwise, we must strip + the void type. */ + if (n == 0 + || debug_get_type_kind (dhandle, args[n - 1]) != DEBUG_KIND_VOID) + varargs = true; + else + { + --n; + varargs = false; + } + + args[n] = DEBUG_TYPE_NULL; + + dtype = debug_make_method_type (dhandle, return_type, domain, args, + varargs); + } + break; + + case 'r': + /* Range type. */ + dtype = parse_stab_range_type (dhandle, info, typename, pp, typenums); + break; + + case 'b': + /* FIXME: gdb checks os9k_stabs here. */ + /* Sun ACC builtin int type. */ + dtype = parse_stab_sun_builtin_type (dhandle, pp); + break; + + case 'R': + /* Sun ACC builtin float type. */ + dtype = parse_stab_sun_floating_type (dhandle, pp); + break; + + case 'e': + /* Enumeration type. */ + dtype = parse_stab_enum_type (dhandle, pp); + break; + + case 's': + case 'u': + /* Struct or union type. */ + dtype = parse_stab_struct_type (dhandle, info, typename, pp, + descriptor == 's', typenums); + break; + + case 'a': + /* Array type. */ + if (**pp != 'r') + { + bad_stab (orig); + return DEBUG_TYPE_NULL; + } + ++*pp; + + dtype = parse_stab_array_type (dhandle, info, pp, stringp); + break; + + case 'S': + dtype = debug_make_set_type (dhandle, + parse_stab_type (dhandle, info, + (const char *) NULL, + pp, + (debug_type **) NULL), + stringp); + break; + + default: + bad_stab (orig); + return DEBUG_TYPE_NULL; + } + + if (dtype == DEBUG_TYPE_NULL) + return DEBUG_TYPE_NULL; + + if (typenums[0] != -1) + { + if (! stab_record_type (dhandle, info, typenums, dtype)) + return DEBUG_TYPE_NULL; + } + + if (size != -1) + { + if (! debug_record_type_size (dhandle, dtype, (unsigned int) size)) + return false; + } + + return dtype; +} + +/* Read a number by which a type is referred to in dbx data, or + perhaps read a pair (FILENUM, TYPENUM) in parentheses. Just a + single number N is equivalent to (0,N). Return the two numbers by + storing them in the vector TYPENUMS. */ + +static boolean +parse_stab_type_number (pp, typenums) + const char **pp; + int *typenums; +{ + const char *orig; + + orig = *pp; + + if (**pp != '(') + { + typenums[0] = 0; + typenums[1] = (int) parse_number (pp, (boolean *) NULL); + } + else + { + ++*pp; + typenums[0] = (int) parse_number (pp, (boolean *) NULL); + if (**pp != ',') + { + bad_stab (orig); + return false; + } + ++*pp; + typenums[1] = (int) parse_number (pp, (boolean *) NULL); + if (**pp != ')') + { + bad_stab (orig); + return false; + } + ++*pp; + } + + return true; +} + +/* Parse a range type. */ + +static debug_type +parse_stab_range_type (dhandle, info, typename, pp, typenums) + PTR dhandle; + struct stab_handle *info; + const char *typename; + const char **pp; + const int *typenums; +{ + const char *orig; + int rangenums[2]; + boolean self_subrange; + debug_type index_type; + const char *s2, *s3; + bfd_signed_vma n2, n3; + boolean ov2, ov3; + + orig = *pp; + + index_type = DEBUG_TYPE_NULL; + + /* First comes a type we are a subrange of. + In C it is usually 0, 1 or the type being defined. */ + if (! parse_stab_type_number (pp, rangenums)) + return DEBUG_TYPE_NULL; + + self_subrange = (rangenums[0] == typenums[0] + && rangenums[1] == typenums[1]); + + if (**pp == '=') + { + *pp = orig; + index_type = parse_stab_type (dhandle, info, (const char *) NULL, + pp, (debug_type **) NULL); + if (index_type == DEBUG_TYPE_NULL) + return DEBUG_TYPE_NULL; + } + + if (**pp == ';') + ++*pp; + + /* The remaining two operands are usually lower and upper bounds of + the range. But in some special cases they mean something else. */ + s2 = *pp; + n2 = parse_number (pp, &ov2); + if (**pp != ';') + { + bad_stab (orig); + return DEBUG_TYPE_NULL; + } + ++*pp; + + s3 = *pp; + n3 = parse_number (pp, &ov3); + if (**pp != ';') + { + bad_stab (orig); + return DEBUG_TYPE_NULL; + } + ++*pp; + + if (ov2 || ov3) + { + /* gcc will emit range stabs for long long types. Handle this + as a special case. FIXME: This needs to be more general. */ +#define LLLOW "01000000000000000000000;" +#define LLHIGH "0777777777777777777777;" +#define ULLHIGH "01777777777777777777777;" + if (index_type == DEBUG_TYPE_NULL) + { + if (strncmp (s2, LLLOW, sizeof LLLOW - 1) == 0 + && strncmp (s3, LLHIGH, sizeof LLHIGH - 1) == 0) + return debug_make_int_type (dhandle, 8, false); + if (! ov2 + && n2 == 0 + && strncmp (s3, ULLHIGH, sizeof ULLHIGH - 1) == 0) + return debug_make_int_type (dhandle, 8, true); + } + + warn_stab (orig, _("numeric overflow")); + } + + if (index_type == DEBUG_TYPE_NULL) + { + /* A type defined as a subrange of itself, with both bounds 0, + is void. */ + if (self_subrange && n2 == 0 && n3 == 0) + return debug_make_void_type (dhandle); + + /* A type defined as a subrange of itself, with n2 positive and + n3 zero, is a complex type, and n2 is the number of bytes. */ + if (self_subrange && n3 == 0 && n2 > 0) + return debug_make_complex_type (dhandle, n2); + + /* If n3 is zero and n2 is positive, this is a floating point + type, and n2 is the number of bytes. */ + if (n3 == 0 && n2 > 0) + return debug_make_float_type (dhandle, n2); + + /* If the upper bound is -1, this is an unsigned int. */ + if (n2 == 0 && n3 == -1) + { + /* When gcc is used with -gstabs, but not -gstabs+, it will emit + long long int:t6=r1;0;-1; + long long unsigned int:t7=r1;0;-1; + We hack here to handle this reasonably. */ + if (typename != NULL) + { + if (strcmp (typename, "long long int") == 0) + return debug_make_int_type (dhandle, 8, false); + else if (strcmp (typename, "long long unsigned int") == 0) + return debug_make_int_type (dhandle, 8, true); + } + /* FIXME: The size here really depends upon the target. */ + return debug_make_int_type (dhandle, 4, true); + } + + /* A range of 0 to 127 is char. */ + if (self_subrange && n2 == 0 && n3 == 127) + return debug_make_int_type (dhandle, 1, false); + + /* FIXME: gdb checks for the language CHILL here. */ + + if (n2 == 0) + { + if (n3 < 0) + return debug_make_int_type (dhandle, - n3, true); + else if (n3 == 0xff) + return debug_make_int_type (dhandle, 1, true); + else if (n3 == 0xffff) + return debug_make_int_type (dhandle, 2, true); + else if (n3 == 0xffffffff) + return debug_make_int_type (dhandle, 4, true); +#ifdef BFD64 + else if (n3 == ((((bfd_vma) 0xffffffff) << 32) | 0xffffffff)) + return debug_make_int_type (dhandle, 8, true); +#endif + } + else if (n3 == 0 + && n2 < 0 + && (self_subrange || n2 == -8)) + return debug_make_int_type (dhandle, - n2, true); + else if (n2 == - n3 - 1 || n2 == n3 + 1) + { + if (n3 == 0x7f) + return debug_make_int_type (dhandle, 1, false); + else if (n3 == 0x7fff) + return debug_make_int_type (dhandle, 2, false); + else if (n3 == 0x7fffffff) + return debug_make_int_type (dhandle, 4, false); +#ifdef BFD64 + else if (n3 == ((((bfd_vma) 0x7fffffff) << 32) | 0xffffffff)) + return debug_make_int_type (dhandle, 8, false); +#endif + } + } + + /* At this point I don't have the faintest idea how to deal with a + self_subrange type; I'm going to assume that this is used as an + idiom, and that all of them are special cases. So . . . */ + if (self_subrange) + { + bad_stab (orig); + return DEBUG_TYPE_NULL; + } + + index_type = stab_find_type (dhandle, info, rangenums); + if (index_type == DEBUG_TYPE_NULL) + { + /* Does this actually ever happen? Is that why we are worrying + about dealing with it rather than just calling error_type? */ + warn_stab (orig, _("missing index type")); + index_type = debug_make_int_type (dhandle, 4, false); + } + + return debug_make_range_type (dhandle, index_type, n2, n3); +} + +/* Sun's ACC uses a somewhat saner method for specifying the builtin + typedefs in every file (for int, long, etc): + + type = b <signed> <width>; <offset>; <nbits> + signed = u or s. Possible c in addition to u or s (for char?). + offset = offset from high order bit to start bit of type. + width is # bytes in object of this type, nbits is # bits in type. + + The width/offset stuff appears to be for small objects stored in + larger ones (e.g. `shorts' in `int' registers). We ignore it for now, + FIXME. */ + +static debug_type +parse_stab_sun_builtin_type (dhandle, pp) + PTR dhandle; + const char **pp; +{ + const char *orig; + boolean unsignedp; + bfd_vma bits; + + orig = *pp; + + switch (**pp) + { + case 's': + unsignedp = false; + break; + case 'u': + unsignedp = true; + break; + default: + bad_stab (orig); + return DEBUG_TYPE_NULL; + } + ++*pp; + + /* For some odd reason, all forms of char put a c here. This is strange + because no other type has this honor. We can safely ignore this because + we actually determine 'char'acterness by the number of bits specified in + the descriptor. */ + if (**pp == 'c') + ++*pp; + + /* The first number appears to be the number of bytes occupied + by this type, except that unsigned short is 4 instead of 2. + Since this information is redundant with the third number, + we will ignore it. */ + (void) parse_number (pp, (boolean *) NULL); + if (**pp != ';') + { + bad_stab (orig); + return DEBUG_TYPE_NULL; + } + ++*pp; + + /* The second number is always 0, so ignore it too. */ + (void) parse_number (pp, (boolean *) NULL); + if (**pp != ';') + { + bad_stab (orig); + return DEBUG_TYPE_NULL; + } + ++*pp; + + /* The third number is the number of bits for this type. */ + bits = parse_number (pp, (boolean *) NULL); + + /* The type *should* end with a semicolon. If it are embedded + in a larger type the semicolon may be the only way to know where + the type ends. If this type is at the end of the stabstring we + can deal with the omitted semicolon (but we don't have to like + it). Don't bother to complain(), Sun's compiler omits the semicolon + for "void". */ + if (**pp == ';') + ++*pp; + + if (bits == 0) + return debug_make_void_type (dhandle); + + return debug_make_int_type (dhandle, bits / 8, unsignedp); +} + +/* Parse a builtin floating type generated by the Sun compiler. */ + +static debug_type +parse_stab_sun_floating_type (dhandle, pp) + PTR dhandle; + const char **pp; +{ + const char *orig; + bfd_vma details; + bfd_vma bytes; + + orig = *pp; + + /* The first number has more details about the type, for example + FN_COMPLEX. */ + details = parse_number (pp, (boolean *) NULL); + if (**pp != ';') + { + bad_stab (orig); + return DEBUG_TYPE_NULL; + } + + /* The second number is the number of bytes occupied by this type */ + bytes = parse_number (pp, (boolean *) NULL); + if (**pp != ';') + { + bad_stab (orig); + return DEBUG_TYPE_NULL; + } + + if (details == NF_COMPLEX + || details == NF_COMPLEX16 + || details == NF_COMPLEX32) + return debug_make_complex_type (dhandle, bytes); + + return debug_make_float_type (dhandle, bytes); +} + +/* Handle an enum type. */ + +static debug_type +parse_stab_enum_type (dhandle, pp) + PTR dhandle; + const char **pp; +{ + const char *orig; + const char **names; + bfd_signed_vma *values; + unsigned int n; + unsigned int alloc; + + orig = *pp; + + /* FIXME: gdb checks os9k_stabs here. */ + + /* The aix4 compiler emits an extra field before the enum members; + my guess is it's a type of some sort. Just ignore it. */ + if (**pp == '-') + { + while (**pp != ':') + ++*pp; + ++*pp; + } + + /* Read the value-names and their values. + The input syntax is NAME:VALUE,NAME:VALUE, and so on. + A semicolon or comma instead of a NAME means the end. */ + alloc = 10; + names = (const char **) xmalloc (alloc * sizeof *names); + values = (bfd_signed_vma *) xmalloc (alloc * sizeof *values); + n = 0; + while (**pp != '\0' && **pp != ';' && **pp != ',') + { + const char *p; + char *name; + bfd_signed_vma val; + + p = *pp; + while (*p != ':') + ++p; + + name = savestring (*pp, p - *pp); + + *pp = p + 1; + val = (bfd_signed_vma) parse_number (pp, (boolean *) NULL); + if (**pp != ',') + { + bad_stab (orig); + return DEBUG_TYPE_NULL; + } + ++*pp; + + if (n + 1 >= alloc) + { + alloc += 10; + names = ((const char **) + xrealloc ((PTR) names, alloc * sizeof *names)); + values = ((bfd_signed_vma *) + xrealloc ((PTR) values, alloc * sizeof *values)); + } + + names[n] = name; + values[n] = val; + ++n; + } + + names[n] = NULL; + values[n] = 0; + + if (**pp == ';') + ++*pp; + + return debug_make_enum_type (dhandle, names, values); +} + +/* Read the description of a structure (or union type) and return an object + describing the type. + + PP points to a character pointer that points to the next unconsumed token + in the the stabs string. For example, given stabs "A:T4=s4a:1,0,32;;", + *PP will point to "4a:1,0,32;;". */ + +static debug_type +parse_stab_struct_type (dhandle, info, tagname, pp, structp, typenums) + PTR dhandle; + struct stab_handle *info; + const char *tagname; + const char **pp; + boolean structp; + const int *typenums; +{ + const char *orig; + bfd_vma size; + debug_baseclass *baseclasses; + debug_field *fields; + boolean statics; + debug_method *methods; + debug_type vptrbase; + boolean ownvptr; + + orig = *pp; + + /* Get the size. */ + size = parse_number (pp, (boolean *) NULL); + + /* Get the other information. */ + if (! parse_stab_baseclasses (dhandle, info, pp, &baseclasses) + || ! parse_stab_struct_fields (dhandle, info, pp, &fields, &statics) + || ! parse_stab_members (dhandle, info, tagname, pp, typenums, &methods) + || ! parse_stab_tilde_field (dhandle, info, pp, typenums, &vptrbase, + &ownvptr)) + return DEBUG_TYPE_NULL; + + if (! statics + && baseclasses == NULL + && methods == NULL + && vptrbase == DEBUG_TYPE_NULL + && ! ownvptr) + return debug_make_struct_type (dhandle, structp, size, fields); + + return debug_make_object_type (dhandle, structp, size, fields, baseclasses, + methods, vptrbase, ownvptr); +} + +/* The stabs for C++ derived classes contain baseclass information which + is marked by a '!' character after the total size. This function is + called when we encounter the baseclass marker, and slurps up all the + baseclass information. + + Immediately following the '!' marker is the number of base classes that + the class is derived from, followed by information for each base class. + For each base class, there are two visibility specifiers, a bit offset + to the base class information within the derived class, a reference to + the type for the base class, and a terminating semicolon. + + A typical example, with two base classes, would be "!2,020,19;0264,21;". + ^^ ^ ^ ^ ^ ^ ^ + Baseclass information marker __________________|| | | | | | | + Number of baseclasses __________________________| | | | | | | + Visibility specifiers (2) ________________________| | | | | | + Offset in bits from start of class _________________| | | | | + Type number for base class ___________________________| | | | + Visibility specifiers (2) _______________________________| | | + Offset in bits from start of class ________________________| | + Type number of base class ____________________________________| + + Return true for success, false for failure. */ + +static boolean +parse_stab_baseclasses (dhandle, info, pp, retp) + PTR dhandle; + struct stab_handle *info; + const char **pp; + debug_baseclass **retp; +{ + const char *orig; + unsigned int c, i; + debug_baseclass *classes; + + *retp = NULL; + + orig = *pp; + + if (**pp != '!') + { + /* No base classes. */ + return true; + } + ++*pp; + + c = (unsigned int) parse_number (pp, (boolean *) NULL); + + if (**pp != ',') + { + bad_stab (orig); + return false; + } + ++*pp; + + classes = (debug_baseclass *) xmalloc ((c + 1) * sizeof (**retp)); + + for (i = 0; i < c; i++) + { + boolean virtual; + enum debug_visibility visibility; + bfd_vma bitpos; + debug_type type; + + switch (**pp) + { + case '0': + virtual = false; + break; + case '1': + virtual = true; + break; + default: + warn_stab (orig, _("unknown virtual character for baseclass")); + virtual = false; + break; + } + ++*pp; + + switch (**pp) + { + case '0': + visibility = DEBUG_VISIBILITY_PRIVATE; + break; + case '1': + visibility = DEBUG_VISIBILITY_PROTECTED; + break; + case '2': + visibility = DEBUG_VISIBILITY_PUBLIC; + break; + default: + warn_stab (orig, _("unknown visibility character for baseclass")); + visibility = DEBUG_VISIBILITY_PUBLIC; + break; + } + ++*pp; + + /* The remaining value is the bit offset of the portion of the + object corresponding to this baseclass. Always zero in the + absence of multiple inheritance. */ + bitpos = parse_number (pp, (boolean *) NULL); + if (**pp != ',') + { + bad_stab (orig); + return false; + } + ++*pp; + + type = parse_stab_type (dhandle, info, (const char *) NULL, pp, + (debug_type **) NULL); + if (type == DEBUG_TYPE_NULL) + return false; + + classes[i] = debug_make_baseclass (dhandle, type, bitpos, virtual, + visibility); + if (classes[i] == DEBUG_BASECLASS_NULL) + return false; + + if (**pp != ';') + return false; + ++*pp; + } + + classes[i] = DEBUG_BASECLASS_NULL; + + *retp = classes; + + return true; +} + +/* Read struct or class data fields. They have the form: + + NAME : [VISIBILITY] TYPENUM , BITPOS , BITSIZE ; + + At the end, we see a semicolon instead of a field. + + In C++, this may wind up being NAME:?TYPENUM:PHYSNAME; for + a static field. + + The optional VISIBILITY is one of: + + '/0' (VISIBILITY_PRIVATE) + '/1' (VISIBILITY_PROTECTED) + '/2' (VISIBILITY_PUBLIC) + '/9' (VISIBILITY_IGNORE) + + or nothing, for C style fields with public visibility. + + Returns 1 for success, 0 for failure. */ + +static boolean +parse_stab_struct_fields (dhandle, info, pp, retp, staticsp) + PTR dhandle; + struct stab_handle *info; + const char **pp; + debug_field **retp; + boolean *staticsp; +{ + const char *orig; + const char *p; + debug_field *fields; + unsigned int c; + unsigned int alloc; + + *retp = NULL; + *staticsp = false; + + orig = *pp; + + c = 0; + alloc = 10; + fields = (debug_field *) xmalloc (alloc * sizeof *fields); + while (**pp != ';') + { + /* FIXME: gdb checks os9k_stabs here. */ + + p = *pp; + + /* Add 1 to c to leave room for NULL pointer at end. */ + if (c + 1 >= alloc) + { + alloc += 10; + fields = ((debug_field *) + xrealloc ((PTR) fields, alloc * sizeof *fields)); + } + + /* If it starts with CPLUS_MARKER it is a special abbreviation, + unless the CPLUS_MARKER is followed by an underscore, in + which case it is just the name of an anonymous type, which we + should handle like any other type name. We accept either '$' + or '.', because a field name can never contain one of these + characters except as a CPLUS_MARKER. */ + + if ((*p == '$' || *p == '.') && p[1] != '_') + { + ++*pp; + if (! parse_stab_cpp_abbrev (dhandle, info, pp, fields + c)) + return false; + ++c; + continue; + } + + /* Look for the ':' that separates the field name from the field + values. Data members are delimited by a single ':', while member + functions are delimited by a pair of ':'s. When we hit the member + functions (if any), terminate scan loop and return. */ + + p = strchr (p, ':'); + if (p == NULL) + { + bad_stab (orig); + return false; + } + + if (p[1] == ':') + break; + + if (! parse_stab_one_struct_field (dhandle, info, pp, p, fields + c, + staticsp)) + return false; + + ++c; + } + + fields[c] = DEBUG_FIELD_NULL; + + *retp = fields; + + return true; +} + +/* Special GNU C++ name. */ + +static boolean +parse_stab_cpp_abbrev (dhandle, info, pp, retp) + PTR dhandle; + struct stab_handle *info; + const char **pp; + debug_field *retp; +{ + const char *orig; + int cpp_abbrev; + debug_type context; + const char *name; + const char *typename; + debug_type type; + bfd_vma bitpos; + + *retp = DEBUG_FIELD_NULL; + + orig = *pp; + + if (**pp != 'v') + { + bad_stab (*pp); + return false; + } + ++*pp; + + cpp_abbrev = **pp; + ++*pp; + + /* At this point, *pp points to something like "22:23=*22...", where + the type number before the ':' is the "context" and everything + after is a regular type definition. Lookup the type, find it's + name, and construct the field name. */ + + context = parse_stab_type (dhandle, info, (const char *) NULL, pp, + (debug_type **) NULL); + if (context == DEBUG_TYPE_NULL) + return false; + + switch (cpp_abbrev) + { + case 'f': + /* $vf -- a virtual function table pointer. */ + name = "_vptr$"; + break; + case 'b': + /* $vb -- a virtual bsomethingorother */ + typename = debug_get_type_name (dhandle, context); + if (typename == NULL) + { + warn_stab (orig, _("unnamed $vb type")); + typename = "FOO"; + } + name = concat ("_vb$", typename, (const char *) NULL); + break; + default: + warn_stab (orig, _("unrecognized C++ abbreviation")); + name = "INVALID_CPLUSPLUS_ABBREV"; + break; + } + + if (**pp != ':') + { + bad_stab (orig); + return false; + } + ++*pp; + + type = parse_stab_type (dhandle, info, (const char *) NULL, pp, + (debug_type **) NULL); + if (**pp != ',') + { + bad_stab (orig); + return false; + } + ++*pp; + + bitpos = parse_number (pp, (boolean *) NULL); + if (**pp != ';') + { + bad_stab (orig); + return false; + } + ++*pp; + + *retp = debug_make_field (dhandle, name, type, bitpos, 0, + DEBUG_VISIBILITY_PRIVATE); + if (*retp == DEBUG_FIELD_NULL) + return false; + + return true; +} + +/* Parse a single field in a struct or union. */ + +static boolean +parse_stab_one_struct_field (dhandle, info, pp, p, retp, staticsp) + PTR dhandle; + struct stab_handle *info; + const char **pp; + const char *p; + debug_field *retp; + boolean *staticsp; +{ + const char *orig; + char *name; + enum debug_visibility visibility; + debug_type type; + bfd_vma bitpos; + bfd_vma bitsize; + + orig = *pp; + + /* FIXME: gdb checks ARM_DEMANGLING here. */ + + name = savestring (*pp, p - *pp); + + *pp = p + 1; + + if (**pp != '/') + visibility = DEBUG_VISIBILITY_PUBLIC; + else + { + ++*pp; + switch (**pp) + { + case '0': + visibility = DEBUG_VISIBILITY_PRIVATE; + break; + case '1': + visibility = DEBUG_VISIBILITY_PROTECTED; + break; + case '2': + visibility = DEBUG_VISIBILITY_PUBLIC; + break; + default: + warn_stab (orig, _("unknown visibility character for field")); + visibility = DEBUG_VISIBILITY_PUBLIC; + break; + } + ++*pp; + } + + type = parse_stab_type (dhandle, info, (const char *) NULL, pp, + (debug_type **) NULL); + if (type == DEBUG_TYPE_NULL) + return false; + + if (**pp == ':') + { + char *varname; + + /* This is a static class member. */ + ++*pp; + p = strchr (*pp, ';'); + if (p == NULL) + { + bad_stab (orig); + return false; + } + + varname = savestring (*pp, p - *pp); + + *pp = p + 1; + + *retp = debug_make_static_member (dhandle, name, type, varname, + visibility); + *staticsp = true; + + return true; + } + + if (**pp != ',') + { + bad_stab (orig); + return false; + } + ++*pp; + + bitpos = parse_number (pp, (boolean *) NULL); + if (**pp != ',') + { + bad_stab (orig); + return false; + } + ++*pp; + + bitsize = parse_number (pp, (boolean *) NULL); + if (**pp != ';') + { + bad_stab (orig); + return false; + } + ++*pp; + + if (bitpos == 0 && bitsize == 0) + { + /* This can happen in two cases: (1) at least for gcc 2.4.5 or + so, it is a field which has been optimized out. The correct + stab for this case is to use VISIBILITY_IGNORE, but that is a + recent invention. (2) It is a 0-size array. For example + union { int num; char str[0]; } foo. Printing "<no value>" + for str in "p foo" is OK, since foo.str (and thus foo.str[3]) + will continue to work, and a 0-size array as a whole doesn't + have any contents to print. + + I suspect this probably could also happen with gcc -gstabs + (not -gstabs+) for static fields, and perhaps other C++ + extensions. Hopefully few people use -gstabs with gdb, since + it is intended for dbx compatibility. */ + visibility = DEBUG_VISIBILITY_IGNORE; + } + + /* FIXME: gdb does some stuff here to mark fields as unpacked. */ + + *retp = debug_make_field (dhandle, name, type, bitpos, bitsize, visibility); + + return true; +} + +/* Read member function stabs info for C++ classes. The form of each member + function data is: + + NAME :: TYPENUM[=type definition] ARGS : PHYSNAME ; + + An example with two member functions is: + + afunc1::20=##15;:i;2A.;afunc2::20:i;2A.; + + For the case of overloaded operators, the format is op$::*.funcs, where + $ is the CPLUS_MARKER (usually '$'), `*' holds the place for an operator + name (such as `+=') and `.' marks the end of the operator name. */ + +static boolean +parse_stab_members (dhandle, info, tagname, pp, typenums, retp) + PTR dhandle; + struct stab_handle *info; + const char *tagname; + const char **pp; + const int *typenums; + debug_method **retp; +{ + const char *orig; + debug_method *methods; + unsigned int c; + unsigned int alloc; + + *retp = NULL; + + orig = *pp; + + alloc = 0; + methods = NULL; + c = 0; + + while (**pp != ';') + { + const char *p; + char *name; + debug_method_variant *variants; + unsigned int cvars; + unsigned int allocvars; + debug_type look_ahead_type; + + p = strchr (*pp, ':'); + if (p == NULL || p[1] != ':') + break; + + /* FIXME: Some systems use something other than '$' here. */ + if ((*pp)[0] != 'o' || (*pp)[1] != 'p' || (*pp)[2] != '$') + { + name = savestring (*pp, p - *pp); + *pp = p + 2; + } + else + { + /* This is a completely wierd case. In order to stuff in the + names that might contain colons (the usual name delimiter), + Mike Tiemann defined a different name format which is + signalled if the identifier is "op$". In that case, the + format is "op$::XXXX." where XXXX is the name. This is + used for names like "+" or "=". YUUUUUUUK! FIXME! */ + *pp = p + 2; + for (p = *pp; *p != '.' && *p != '\0'; p++) + ; + if (*p != '.') + { + bad_stab (orig); + return false; + } + name = savestring (*pp, p - *pp); + *pp = p + 1; + } + + allocvars = 10; + variants = ((debug_method_variant *) + xmalloc (allocvars * sizeof *variants)); + cvars = 0; + + look_ahead_type = DEBUG_TYPE_NULL; + + do + { + debug_type type; + boolean stub; + char *argtypes; + enum debug_visibility visibility; + boolean constp, volatilep, staticp; + bfd_vma voffset; + debug_type context; + const char *physname; + boolean varargs; + + if (look_ahead_type != DEBUG_TYPE_NULL) + { + /* g++ version 1 kludge */ + type = look_ahead_type; + look_ahead_type = DEBUG_TYPE_NULL; + } + else + { + type = parse_stab_type (dhandle, info, (const char *) NULL, pp, + (debug_type **) NULL); + if (type == DEBUG_TYPE_NULL) + return false; + if (**pp != ':') + { + bad_stab (orig); + return false; + } + } + + ++*pp; + p = strchr (*pp, ';'); + if (p == NULL) + { + bad_stab (orig); + return false; + } + + stub = false; + if (debug_get_type_kind (dhandle, type) == DEBUG_KIND_METHOD + && debug_get_parameter_types (dhandle, type, &varargs) == NULL) + stub = true; + + argtypes = savestring (*pp, p - *pp); + *pp = p + 1; + + switch (**pp) + { + case '0': + visibility = DEBUG_VISIBILITY_PRIVATE; + break; + case '1': + visibility = DEBUG_VISIBILITY_PROTECTED; + break; + default: + visibility = DEBUG_VISIBILITY_PUBLIC; + break; + } + ++*pp; + + constp = false; + volatilep = false; + switch (**pp) + { + case 'A': + /* Normal function. */ + ++*pp; + break; + case 'B': + /* const member function. */ + constp = true; + ++*pp; + break; + case 'C': + /* volatile member function. */ + volatilep = true; + ++*pp; + break; + case 'D': + /* const volatile member function. */ + constp = true; + volatilep = true; + ++*pp; + break; + case '*': + case '?': + case '.': + /* File compiled with g++ version 1; no information. */ + break; + default: + warn_stab (orig, _("const/volatile indicator missing")); + break; + } + + staticp = false; + switch (**pp) + { + case '*': + /* virtual member function, followed by index. The sign + bit is supposedly set to distinguish + pointers-to-methods from virtual function indicies. */ + ++*pp; + voffset = parse_number (pp, (boolean *) NULL); + if (**pp != ';') + { + bad_stab (orig); + return false; + } + ++*pp; + voffset &= 0x7fffffff; + + if (**pp == ';' || *pp == '\0') + { + /* Must be g++ version 1. */ + context = DEBUG_TYPE_NULL; + } + else + { + /* Figure out from whence this virtual function + came. It may belong to virtual function table of + one of its baseclasses. */ + look_ahead_type = parse_stab_type (dhandle, info, + (const char *) NULL, + pp, + (debug_type **) NULL); + if (**pp == ':') + { + /* g++ version 1 overloaded methods. */ + context = DEBUG_TYPE_NULL; + } + else + { + context = look_ahead_type; + look_ahead_type = DEBUG_TYPE_NULL; + if (**pp != ';') + { + bad_stab (orig); + return false; + } + ++*pp; + } + } + break; + + case '?': + /* static member function. */ + ++*pp; + staticp = true; + voffset = 0; + context = DEBUG_TYPE_NULL; + if (strncmp (argtypes, name, strlen (name)) != 0) + stub = true; + break; + + default: + warn_stab (orig, "member function type missing"); + voffset = 0; + context = DEBUG_TYPE_NULL; + break; + + case '.': + ++*pp; + voffset = 0; + context = DEBUG_TYPE_NULL; + break; + } + + /* If the type is not a stub, then the argtypes string is + the physical name of the function. Otherwise the + argtypes string is the mangled form of the argument + types, and the full type and the physical name must be + extracted from them. */ + if (! stub) + physname = argtypes; + else + { + debug_type class_type, return_type; + + class_type = stab_find_type (dhandle, info, typenums); + if (class_type == DEBUG_TYPE_NULL) + return false; + return_type = debug_get_return_type (dhandle, type); + if (return_type == DEBUG_TYPE_NULL) + { + bad_stab (orig); + return false; + } + type = parse_stab_argtypes (dhandle, info, class_type, name, + tagname, return_type, argtypes, + constp, volatilep, &physname); + if (type == DEBUG_TYPE_NULL) + return false; + } + + if (cvars + 1 >= allocvars) + { + allocvars += 10; + variants = ((debug_method_variant *) + xrealloc ((PTR) variants, + allocvars * sizeof *variants)); + } + + if (! staticp) + variants[cvars] = debug_make_method_variant (dhandle, physname, + type, visibility, + constp, volatilep, + voffset, context); + else + variants[cvars] = debug_make_static_method_variant (dhandle, + physname, + type, + visibility, + constp, + volatilep); + if (variants[cvars] == DEBUG_METHOD_VARIANT_NULL) + return false; + + ++cvars; + } + while (**pp != ';' && **pp != '\0'); + + variants[cvars] = DEBUG_METHOD_VARIANT_NULL; + + if (**pp != '\0') + ++*pp; + + if (c + 1 >= alloc) + { + alloc += 10; + methods = ((debug_method *) + xrealloc ((PTR) methods, alloc * sizeof *methods)); + } + + methods[c] = debug_make_method (dhandle, name, variants); + + ++c; + } + + if (methods != NULL) + methods[c] = DEBUG_METHOD_NULL; + + *retp = methods; + + return true; +} + +/* Parse a string representing argument types for a method. Stabs + tries to save space by packing argument types into a mangled + string. This string should give us enough information to extract + both argument types and the physical name of the function, given + the tag name. */ + +static debug_type +parse_stab_argtypes (dhandle, info, class_type, fieldname, tagname, + return_type, argtypes, constp, volatilep, pphysname) + PTR dhandle; + struct stab_handle *info; + debug_type class_type; + const char *fieldname; + const char *tagname; + debug_type return_type; + const char *argtypes; + boolean constp; + boolean volatilep; + const char **pphysname; +{ + boolean is_full_physname_constructor; + boolean is_constructor; + boolean is_destructor; + debug_type *args; + boolean varargs; + + /* Constructors are sometimes handled specially. */ + is_full_physname_constructor = ((argtypes[0] == '_' + && argtypes[1] == '_' + && (isdigit ((unsigned char) argtypes[2]) + || argtypes[2] == 'Q' + || argtypes[2] == 't')) + || strncmp (argtypes, "__ct", 4) == 0); + + is_constructor = (is_full_physname_constructor + || (tagname != NULL + && strcmp (fieldname, tagname) == 0)); + is_destructor = ((argtypes[0] == '_' + && (argtypes[1] == '$' || argtypes[1] == '.') + && argtypes[2] == '_') + || strncmp (argtypes, "__dt", 4) == 0); + + if (is_destructor || is_full_physname_constructor) + *pphysname = argtypes; + else + { + unsigned int len; + const char *const_prefix; + const char *volatile_prefix; + char buf[20]; + unsigned int mangled_name_len; + char *physname; + + len = tagname == NULL ? 0 : strlen (tagname); + const_prefix = constp ? "C" : ""; + volatile_prefix = volatilep ? "V" : ""; + + if (len == 0) + sprintf (buf, "__%s%s", const_prefix, volatile_prefix); + else if (tagname != NULL && strchr (tagname, '<') != NULL) + { + /* Template methods are fully mangled. */ + sprintf (buf, "__%s%s", const_prefix, volatile_prefix); + tagname = NULL; + len = 0; + } + else + sprintf (buf, "__%s%s%d", const_prefix, volatile_prefix, len); + + mangled_name_len = ((is_constructor ? 0 : strlen (fieldname)) + + strlen (buf) + + len + + strlen (argtypes) + + 1); + + if (fieldname[0] == 'o' + && fieldname[1] == 'p' + && (fieldname[2] == '$' || fieldname[2] == '.')) + { + const char *opname; + + opname = cplus_mangle_opname (fieldname + 3, 0); + if (opname == NULL) + { + fprintf (stderr, _("No mangling for \"%s\"\n"), fieldname); + return DEBUG_TYPE_NULL; + } + mangled_name_len += strlen (opname); + physname = (char *) xmalloc (mangled_name_len); + strncpy (physname, fieldname, 3); + strcpy (physname + 3, opname); + } + else + { + physname = (char *) xmalloc (mangled_name_len); + if (is_constructor) + physname[0] = '\0'; + else + strcpy (physname, fieldname); + } + + strcat (physname, buf); + if (tagname != NULL) + strcat (physname, tagname); + strcat (physname, argtypes); + + *pphysname = physname; + } + + if (*argtypes == '\0' || is_destructor) + { + args = (debug_type *) xmalloc (sizeof *args); + *args = NULL; + return debug_make_method_type (dhandle, return_type, class_type, args, + false); + } + + args = stab_demangle_argtypes (dhandle, info, *pphysname, &varargs); + if (args == NULL) + return DEBUG_TYPE_NULL; + + return debug_make_method_type (dhandle, return_type, class_type, args, + varargs); +} + +/* The tail end of stabs for C++ classes that contain a virtual function + pointer contains a tilde, a %, and a type number. + The type number refers to the base class (possibly this class itself) which + contains the vtable pointer for the current class. + + This function is called when we have parsed all the method declarations, + so we can look for the vptr base class info. */ + +static boolean +parse_stab_tilde_field (dhandle, info, pp, typenums, retvptrbase, retownvptr) + PTR dhandle; + struct stab_handle *info; + const char **pp; + const int *typenums; + debug_type *retvptrbase; + boolean *retownvptr; +{ + const char *orig; + const char *hold; + int vtypenums[2]; + + *retvptrbase = DEBUG_TYPE_NULL; + *retownvptr = false; + + orig = *pp; + + /* If we are positioned at a ';', then skip it. */ + if (**pp == ';') + ++*pp; + + if (**pp != '~') + return true; + + ++*pp; + + if (**pp == '=' || **pp == '+' || **pp == '-') + { + /* Obsolete flags that used to indicate the presence of + constructors and/or destructors. */ + ++*pp; + } + + if (**pp != '%') + return true; + + ++*pp; + + hold = *pp; + + /* The next number is the type number of the base class (possibly + our own class) which supplies the vtable for this class. */ + if (! parse_stab_type_number (pp, vtypenums)) + return false; + + if (vtypenums[0] == typenums[0] + && vtypenums[1] == typenums[1]) + *retownvptr = true; + else + { + debug_type vtype; + const char *p; + + *pp = hold; + + vtype = parse_stab_type (dhandle, info, (const char *) NULL, pp, + (debug_type **) NULL); + for (p = *pp; *p != ';' && *p != '\0'; p++) + ; + if (*p != ';') + { + bad_stab (orig); + return false; + } + + *retvptrbase = vtype; + + *pp = p + 1; + } + + return true; +} + +/* Read a definition of an array type. */ + +static debug_type +parse_stab_array_type (dhandle, info, pp, stringp) + PTR dhandle; + struct stab_handle *info; + const char **pp; + boolean stringp; +{ + const char *orig; + const char *p; + int typenums[2]; + debug_type index_type; + boolean adjustable; + bfd_signed_vma lower, upper; + debug_type element_type; + + /* Format of an array type: + "ar<index type>;lower;upper;<array_contents_type>". + OS9000: "arlower,upper;<array_contents_type>". + + Fortran adjustable arrays use Adigits or Tdigits for lower or upper; + for these, produce a type like float[][]. */ + + orig = *pp; + + /* FIXME: gdb checks os9k_stabs here. */ + + /* If the index type is type 0, we take it as int. */ + p = *pp; + if (! parse_stab_type_number (&p, typenums)) + return false; + if (typenums[0] == 0 && typenums[1] == 0 && **pp != '=') + { + index_type = debug_find_named_type (dhandle, "int"); + if (index_type == DEBUG_TYPE_NULL) + { + index_type = debug_make_int_type (dhandle, 4, false); + if (index_type == DEBUG_TYPE_NULL) + return false; + } + *pp = p; + } + else + { + index_type = parse_stab_type (dhandle, info, (const char *) NULL, pp, + (debug_type **) NULL); + } + + if (**pp != ';') + { + bad_stab (orig); + return DEBUG_TYPE_NULL; + } + ++*pp; + + adjustable = false; + + if (! isdigit ((unsigned char) **pp) && **pp != '-') + { + ++*pp; + adjustable = true; + } + + lower = (bfd_signed_vma) parse_number (pp, (boolean *) NULL); + if (**pp != ';') + { + bad_stab (orig); + return false; + } + ++*pp; + + if (! isdigit ((unsigned char) **pp) && **pp != '-') + { + ++*pp; + adjustable = true; + } + + upper = (bfd_signed_vma) parse_number (pp, (boolean *) NULL); + if (**pp != ';') + { + bad_stab (orig); + return false; + } + ++*pp; + + element_type = parse_stab_type (dhandle, info, (const char *) NULL, pp, + (debug_type **) NULL); + if (element_type == DEBUG_TYPE_NULL) + return false; + + if (adjustable) + { + lower = 0; + upper = -1; + } + + return debug_make_array_type (dhandle, element_type, index_type, lower, + upper, stringp); +} + +/* This struct holds information about files we have seen using + N_BINCL. */ + +struct bincl_file +{ + /* The next N_BINCL file. */ + struct bincl_file *next; + /* The next N_BINCL on the stack. */ + struct bincl_file *next_stack; + /* The file name. */ + const char *name; + /* The hash value. */ + bfd_vma hash; + /* The file index. */ + unsigned int file; + /* The list of types defined in this file. */ + struct stab_types *file_types; +}; + +/* Start a new N_BINCL file, pushing it onto the stack. */ + +static void +push_bincl (info, name, hash) + struct stab_handle *info; + const char *name; + bfd_vma hash; +{ + struct bincl_file *n; + + n = (struct bincl_file *) xmalloc (sizeof *n); + n->next = info->bincl_list; + n->next_stack = info->bincl_stack; + n->name = name; + n->hash = hash; + n->file = info->files; + n->file_types = NULL; + info->bincl_list = n; + info->bincl_stack = n; + + ++info->files; + info->file_types = ((struct stab_types **) + xrealloc ((PTR) info->file_types, + (info->files + * sizeof *info->file_types))); + info->file_types[n->file] = NULL; +} + +/* Finish an N_BINCL file, at an N_EINCL, popping the name off the + stack. */ + +static const char * +pop_bincl (info) + struct stab_handle *info; +{ + struct bincl_file *o; + + o = info->bincl_stack; + if (o == NULL) + return info->main_filename; + info->bincl_stack = o->next_stack; + + o->file_types = info->file_types[o->file]; + + if (info->bincl_stack == NULL) + return info->main_filename; + return info->bincl_stack->name; +} + +/* Handle an N_EXCL: get the types from the corresponding N_BINCL. */ + +static boolean +find_excl (info, name, hash) + struct stab_handle *info; + const char *name; + bfd_vma hash; +{ + struct bincl_file *l; + + ++info->files; + info->file_types = ((struct stab_types **) + xrealloc ((PTR) info->file_types, + (info->files + * sizeof *info->file_types))); + + for (l = info->bincl_list; l != NULL; l = l->next) + if (l->hash == hash && strcmp (l->name, name) == 0) + break; + if (l == NULL) + { + warn_stab (name, _("Undefined N_EXCL")); + info->file_types[info->files - 1] = NULL; + return true; + } + + info->file_types[info->files - 1] = l->file_types; + + return true; +} + +/* Handle a variable definition. gcc emits variable definitions for a + block before the N_LBRAC, so we must hold onto them until we see + it. The SunPRO compiler emits variable definitions after the + N_LBRAC, so we can call debug_record_variable immediately. */ + +static boolean +stab_record_variable (dhandle, info, name, type, kind, val) + PTR dhandle; + struct stab_handle *info; + const char *name; + debug_type type; + enum debug_var_kind kind; + bfd_vma val; +{ + struct stab_pending_var *v; + + if ((kind == DEBUG_GLOBAL || kind == DEBUG_STATIC) + || ! info->within_function + || (info->gcc_compiled == 0 && info->n_opt_found)) + return debug_record_variable (dhandle, name, type, kind, val); + + v = (struct stab_pending_var *) xmalloc (sizeof *v); + memset (v, 0, sizeof *v); + + v->next = info->pending; + v->name = name; + v->type = type; + v->kind = kind; + v->val = val; + info->pending = v; + + return true; +} + +/* Emit pending variable definitions. This is called after we see the + N_LBRAC that starts the block. */ + +static boolean +stab_emit_pending_vars (dhandle, info) + PTR dhandle; + struct stab_handle *info; +{ + struct stab_pending_var *v; + + v = info->pending; + while (v != NULL) + { + struct stab_pending_var *next; + + if (! debug_record_variable (dhandle, v->name, v->type, v->kind, v->val)) + return false; + + next = v->next; + free (v); + v = next; + } + + info->pending = NULL; + + return true; +} + +/* Find the slot for a type in the database. */ + +static debug_type * +stab_find_slot (info, typenums) + struct stab_handle *info; + const int *typenums; +{ + int filenum; + int index; + struct stab_types **ps; + + filenum = typenums[0]; + index = typenums[1]; + + if (filenum < 0 || (unsigned int) filenum >= info->files) + { + fprintf (stderr, _("Type file number %d out of range\n"), filenum); + return NULL; + } + if (index < 0) + { + fprintf (stderr, _("Type index number %d out of range\n"), index); + return NULL; + } + + ps = info->file_types + filenum; + + while (index >= STAB_TYPES_SLOTS) + { + if (*ps == NULL) + { + *ps = (struct stab_types *) xmalloc (sizeof **ps); + memset (*ps, 0, sizeof **ps); + } + ps = &(*ps)->next; + index -= STAB_TYPES_SLOTS; + } + if (*ps == NULL) + { + *ps = (struct stab_types *) xmalloc (sizeof **ps); + memset (*ps, 0, sizeof **ps); + } + + return (*ps)->types + index; +} + +/* Find a type given a type number. If the type has not been + allocated yet, create an indirect type. */ + +static debug_type +stab_find_type (dhandle, info, typenums) + PTR dhandle; + struct stab_handle *info; + const int *typenums; +{ + debug_type *slot; + + if (typenums[0] == 0 && typenums[1] < 0) + { + /* A negative type number indicates an XCOFF builtin type. */ + return stab_xcoff_builtin_type (dhandle, info, typenums[1]); + } + + slot = stab_find_slot (info, typenums); + if (slot == NULL) + return DEBUG_TYPE_NULL; + + if (*slot == DEBUG_TYPE_NULL) + return debug_make_indirect_type (dhandle, slot, (const char *) NULL); + + return *slot; +} + +/* Record that a given type number refers to a given type. */ + +static boolean +stab_record_type (dhandle, info, typenums, type) + PTR dhandle; + struct stab_handle *info; + const int *typenums; + debug_type type; +{ + debug_type *slot; + + slot = stab_find_slot (info, typenums); + if (slot == NULL) + return false; + + /* gdb appears to ignore type redefinitions, so we do as well. */ + + *slot = type; + + return true; +} + +/* Return an XCOFF builtin type. */ + +static debug_type +stab_xcoff_builtin_type (dhandle, info, typenum) + PTR dhandle; + struct stab_handle *info; + int typenum; +{ + debug_type rettype; + const char *name; + + if (typenum >= 0 || typenum < -XCOFF_TYPE_COUNT) + { + fprintf (stderr, _("Unrecognized XCOFF type %d\n"), typenum); + return DEBUG_TYPE_NULL; + } + if (info->xcoff_types[-typenum] != NULL) + return info->xcoff_types[-typenum]; + + switch (-typenum) + { + case 1: + /* The size of this and all the other types are fixed, defined + by the debugging format. */ + name = "int"; + rettype = debug_make_int_type (dhandle, 4, false); + break; + case 2: + name = "char"; + rettype = debug_make_int_type (dhandle, 1, false); + break; + case 3: + name = "short"; + rettype = debug_make_int_type (dhandle, 2, false); + break; + case 4: + name = "long"; + rettype = debug_make_int_type (dhandle, 4, false); + break; + case 5: + name = "unsigned char"; + rettype = debug_make_int_type (dhandle, 1, true); + break; + case 6: + name = "signed char"; + rettype = debug_make_int_type (dhandle, 1, false); + break; + case 7: + name = "unsigned short"; + rettype = debug_make_int_type (dhandle, 2, true); + break; + case 8: + name = "unsigned int"; + rettype = debug_make_int_type (dhandle, 4, true); + break; + case 9: + name = "unsigned"; + rettype = debug_make_int_type (dhandle, 4, true); + case 10: + name = "unsigned long"; + rettype = debug_make_int_type (dhandle, 4, true); + break; + case 11: + name = "void"; + rettype = debug_make_void_type (dhandle); + break; + case 12: + /* IEEE single precision (32 bit). */ + name = "float"; + rettype = debug_make_float_type (dhandle, 4); + break; + case 13: + /* IEEE double precision (64 bit). */ + name = "double"; + rettype = debug_make_float_type (dhandle, 8); + break; + case 14: + /* This is an IEEE double on the RS/6000, and different machines + with different sizes for "long double" should use different + negative type numbers. See stabs.texinfo. */ + name = "long double"; + rettype = debug_make_float_type (dhandle, 8); + break; + case 15: + name = "integer"; + rettype = debug_make_int_type (dhandle, 4, false); + break; + case 16: + name = "boolean"; + rettype = debug_make_bool_type (dhandle, 4); + break; + case 17: + name = "short real"; + rettype = debug_make_float_type (dhandle, 4); + break; + case 18: + name = "real"; + rettype = debug_make_float_type (dhandle, 8); + break; + case 19: + /* FIXME */ + name = "stringptr"; + rettype = NULL; + break; + case 20: + /* FIXME */ + name = "character"; + rettype = debug_make_int_type (dhandle, 1, true); + break; + case 21: + name = "logical*1"; + rettype = debug_make_bool_type (dhandle, 1); + break; + case 22: + name = "logical*2"; + rettype = debug_make_bool_type (dhandle, 2); + break; + case 23: + name = "logical*4"; + rettype = debug_make_bool_type (dhandle, 4); + break; + case 24: + name = "logical"; + rettype = debug_make_bool_type (dhandle, 4); + break; + case 25: + /* Complex type consisting of two IEEE single precision values. */ + name = "complex"; + rettype = debug_make_complex_type (dhandle, 8); + break; + case 26: + /* Complex type consisting of two IEEE double precision values. */ + name = "double complex"; + rettype = debug_make_complex_type (dhandle, 16); + break; + case 27: + name = "integer*1"; + rettype = debug_make_int_type (dhandle, 1, false); + break; + case 28: + name = "integer*2"; + rettype = debug_make_int_type (dhandle, 2, false); + break; + case 29: + name = "integer*4"; + rettype = debug_make_int_type (dhandle, 4, false); + break; + case 30: + /* FIXME */ + name = "wchar"; + rettype = debug_make_int_type (dhandle, 2, false); + break; + case 31: + name = "long long"; + rettype = debug_make_int_type (dhandle, 8, false); + break; + case 32: + name = "unsigned long long"; + rettype = debug_make_int_type (dhandle, 8, true); + break; + case 33: + name = "logical*8"; + rettype = debug_make_bool_type (dhandle, 8); + break; + case 34: + name = "integer*8"; + rettype = debug_make_int_type (dhandle, 8, false); + break; + default: + abort (); + } + + rettype = debug_name_type (dhandle, name, rettype); + + info->xcoff_types[-typenum] = rettype; + + return rettype; +} + +/* Find or create a tagged type. */ + +static debug_type +stab_find_tagged_type (dhandle, info, p, len, kind) + PTR dhandle; + struct stab_handle *info; + const char *p; + int len; + enum debug_type_kind kind; +{ + char *name; + debug_type dtype; + struct stab_tag *st; + + name = savestring (p, len); + + /* We pass DEBUG_KIND_ILLEGAL because we want all tags in the same + namespace. This is right for C, and I don't know how to handle + other languages. FIXME. */ + dtype = debug_find_tagged_type (dhandle, name, DEBUG_KIND_ILLEGAL); + if (dtype != DEBUG_TYPE_NULL) + { + free (name); + return dtype; + } + + /* We need to allocate an entry on the undefined tag list. */ + for (st = info->tags; st != NULL; st = st->next) + { + if (st->name[0] == name[0] + && strcmp (st->name, name) == 0) + { + if (st->kind == DEBUG_KIND_ILLEGAL) + st->kind = kind; + free (name); + break; + } + } + if (st == NULL) + { + st = (struct stab_tag *) xmalloc (sizeof *st); + memset (st, 0, sizeof *st); + + st->next = info->tags; + st->name = name; + st->kind = kind; + st->slot = DEBUG_TYPE_NULL; + st->type = debug_make_indirect_type (dhandle, &st->slot, name); + info->tags = st; + } + + return st->type; +} + +/* In order to get the correct argument types for a stubbed method, we + need to extract the argument types from a C++ mangled string. + Since the argument types can refer back to the return type, this + means that we must demangle the entire physical name. In gdb this + is done by calling cplus_demangle and running the results back + through the C++ expression parser. Since we have no expression + parser, we must duplicate much of the work of cplus_demangle here. + + We assume that GNU style demangling is used, since this is only + done for method stubs, and only g++ should output that form of + debugging information. */ + +/* This structure is used to hold a pointer to type information which + demangling a string. */ + +struct stab_demangle_typestring +{ + /* The start of the type. This is not null terminated. */ + const char *typestring; + /* The length of the type. */ + unsigned int len; +}; + +/* This structure is used to hold information while demangling a + string. */ + +struct stab_demangle_info +{ + /* The debugging information handle. */ + PTR dhandle; + /* The stab information handle. */ + struct stab_handle *info; + /* The array of arguments we are building. */ + debug_type *args; + /* Whether the method takes a variable number of arguments. */ + boolean varargs; + /* The array of types we have remembered. */ + struct stab_demangle_typestring *typestrings; + /* The number of typestrings. */ + unsigned int typestring_count; + /* The number of typestring slots we have allocated. */ + unsigned int typestring_alloc; +}; + +static void stab_bad_demangle PARAMS ((const char *)); +static unsigned int stab_demangle_count PARAMS ((const char **)); +static boolean stab_demangle_get_count + PARAMS ((const char **, unsigned int *)); +static boolean stab_demangle_prefix + PARAMS ((struct stab_demangle_info *, const char **)); +static boolean stab_demangle_function_name + PARAMS ((struct stab_demangle_info *, const char **, const char *)); +static boolean stab_demangle_signature + PARAMS ((struct stab_demangle_info *, const char **)); +static boolean stab_demangle_qualified + PARAMS ((struct stab_demangle_info *, const char **, debug_type *)); +static boolean stab_demangle_template + PARAMS ((struct stab_demangle_info *, const char **, char **)); +static boolean stab_demangle_class + PARAMS ((struct stab_demangle_info *, const char **, const char **)); +static boolean stab_demangle_args + PARAMS ((struct stab_demangle_info *, const char **, debug_type **, + boolean *)); +static boolean stab_demangle_arg + PARAMS ((struct stab_demangle_info *, const char **, debug_type **, + unsigned int *, unsigned int *)); +static boolean stab_demangle_type + PARAMS ((struct stab_demangle_info *, const char **, debug_type *)); +static boolean stab_demangle_fund_type + PARAMS ((struct stab_demangle_info *, const char **, debug_type *)); +static boolean stab_demangle_remember_type + PARAMS ((struct stab_demangle_info *, const char *, int)); + +/* Warn about a bad demangling. */ + +static void +stab_bad_demangle (s) + const char *s; +{ + fprintf (stderr, _("bad mangled name `%s'\n"), s); +} + +/* Get a count from a stab string. */ + +static unsigned int +stab_demangle_count (pp) + const char **pp; +{ + unsigned int count; + + count = 0; + while (isdigit ((unsigned char) **pp)) + { + count *= 10; + count += **pp - '0'; + ++*pp; + } + return count; +} + +/* Require a count in a string. The count may be multiple digits, in + which case it must end in an underscore. */ + +static boolean +stab_demangle_get_count (pp, pi) + const char **pp; + unsigned int *pi; +{ + if (! isdigit ((unsigned char) **pp)) + return false; + + *pi = **pp - '0'; + ++*pp; + if (isdigit ((unsigned char) **pp)) + { + unsigned int count; + const char *p; + + count = *pi; + p = *pp; + do + { + count *= 10; + count += *p - '0'; + ++p; + } + while (isdigit ((unsigned char) *p)); + if (*p == '_') + { + *pp = p + 1; + *pi = count; + } + } + + return true; +} + +/* This function demangles a physical name, returning a NULL + terminated array of argument types. */ + +static debug_type * +stab_demangle_argtypes (dhandle, info, physname, pvarargs) + PTR dhandle; + struct stab_handle *info; + const char *physname; + boolean *pvarargs; +{ + struct stab_demangle_info minfo; + + minfo.dhandle = dhandle; + minfo.info = info; + minfo.args = NULL; + minfo.varargs = false; + minfo.typestring_alloc = 10; + minfo.typestrings = ((struct stab_demangle_typestring *) + xmalloc (minfo.typestring_alloc + * sizeof *minfo.typestrings)); + minfo.typestring_count = 0; + + /* cplus_demangle checks for special GNU mangled forms, but we can't + see any of them in mangled method argument types. */ + + if (! stab_demangle_prefix (&minfo, &physname)) + goto error_return; + + if (*physname != '\0') + { + if (! stab_demangle_signature (&minfo, &physname)) + goto error_return; + } + + free (minfo.typestrings); + minfo.typestrings = NULL; + + if (minfo.args == NULL) + fprintf (stderr, _("no argument types in mangled string\n")); + + *pvarargs = minfo.varargs; + return minfo.args; + + error_return: + if (minfo.typestrings != NULL) + free (minfo.typestrings); + return NULL; +} + +/* Demangle the prefix of the mangled name. */ + +static boolean +stab_demangle_prefix (minfo, pp) + struct stab_demangle_info *minfo; + const char **pp; +{ + const char *scan; + unsigned int i; + + /* cplus_demangle checks for global constructors and destructors, + but we can't see them in mangled argument types. */ + + /* Look for `__'. */ + scan = *pp; + do + { + scan = strchr (scan, '_'); + } + while (scan != NULL && *++scan != '_'); + + if (scan == NULL) + { + stab_bad_demangle (*pp); + return false; + } + + --scan; + + /* We found `__'; move ahead to the last contiguous `__' pair. */ + i = strspn (scan, "_"); + if (i > 2) + scan += i - 2; + + if (scan == *pp + && (isdigit ((unsigned char) scan[2]) + || scan[2] == 'Q' + || scan[2] == 't')) + { + /* This is a GNU style constructor name. */ + *pp = scan + 2; + return true; + } + else if (scan == *pp + && ! isdigit ((unsigned char) scan[2]) + && scan[2] != 't') + { + /* Look for the `__' that separates the prefix from the + signature. */ + while (*scan == '_') + ++scan; + scan = strstr (scan, "__"); + if (scan == NULL || scan[2] == '\0') + { + stab_bad_demangle (*pp); + return false; + } + + return stab_demangle_function_name (minfo, pp, scan); + } + else if (scan[2] != '\0') + { + /* The name doesn't start with `__', but it does contain `__'. */ + return stab_demangle_function_name (minfo, pp, scan); + } + else + { + stab_bad_demangle (*pp); + return false; + } + /*NOTREACHED*/ +} + +/* Demangle a function name prefix. The scan argument points to the + double underscore which separates the function name from the + signature. */ + +static boolean +stab_demangle_function_name (minfo, pp, scan) + struct stab_demangle_info *minfo; + const char **pp; + const char *scan; +{ + const char *name; + + /* The string from *pp to scan is the name of the function. We + don't care about the name, since we just looking for argument + types. However, for conversion operators, the name may include a + type which we must remember in order to handle backreferences. */ + + name = *pp; + *pp = scan + 2; + + if (*pp - name >= 5 + && strncmp (name, "type", 4) == 0 + && (name[4] == '$' || name[4] == '.')) + { + const char *tem; + + /* This is a type conversion operator. */ + tem = name + 5; + if (! stab_demangle_type (minfo, &tem, (debug_type *) NULL)) + return false; + } + else if (name[0] == '_' + && name[1] == '_' + && name[2] == 'o' + && name[3] == 'p') + { + const char *tem; + + /* This is a type conversion operator. */ + tem = name + 4; + if (! stab_demangle_type (minfo, &tem, (debug_type *) NULL)) + return false; + } + + return true; +} + +/* Demangle the signature. This is where the argument types are + found. */ + +static boolean +stab_demangle_signature (minfo, pp) + struct stab_demangle_info *minfo; + const char **pp; +{ + const char *orig; + boolean expect_func, func_done; + const char *hold; + + orig = *pp; + + expect_func = false; + func_done = false; + hold = NULL; + + while (**pp != '\0') + { + switch (**pp) + { + case 'Q': + hold = *pp; + if (! stab_demangle_qualified (minfo, pp, (debug_type *) NULL) + || ! stab_demangle_remember_type (minfo, hold, *pp - hold)) + return false; + expect_func = true; + hold = NULL; + break; + + case 'S': + /* Static member function. FIXME: Can this happen? */ + if (hold == NULL) + hold = *pp; + ++*pp; + break; + + case 'C': + /* Const member function. */ + if (hold == NULL) + hold = *pp; + ++*pp; + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + if (hold == NULL) + hold = *pp; + if (! stab_demangle_class (minfo, pp, (const char **) NULL) + || ! stab_demangle_remember_type (minfo, hold, *pp - hold)) + return false; + expect_func = true; + hold = NULL; + break; + + case 'F': + /* Function. I don't know if this actually happens with g++ + output. */ + hold = NULL; + func_done = true; + ++*pp; + if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs)) + return false; + break; + + case 't': + /* Template. */ + if (hold == NULL) + hold = *pp; + if (! stab_demangle_template (minfo, pp, (char **) NULL) + || ! stab_demangle_remember_type (minfo, hold, *pp - hold)) + return false; + hold = NULL; + expect_func = true; + break; + + case '_': + /* At the outermost level, we cannot have a return type + specified, so if we run into another '_' at this point we + are dealing with a mangled name that is either bogus, or + has been mangled by some algorithm we don't know how to + deal with. So just reject the entire demangling. */ + stab_bad_demangle (orig); + return false; + + default: + /* Assume we have stumbled onto the first outermost function + argument token, and start processing args. */ + func_done = true; + if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs)) + return false; + break; + } + + if (expect_func) + { + func_done = true; + if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs)) + return false; + } + } + + if (! func_done) + { + /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and + bar__3fooi is 'foo::bar(int)'. We get here when we find the + first case, and need to ensure that the '(void)' gets added + to the current declp. */ + if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs)) + return false; + } + + return true; +} + +/* Demangle a qualified name, such as "Q25Outer5Inner" which is the + mangled form of "Outer::Inner". */ + +static boolean +stab_demangle_qualified (minfo, pp, ptype) + struct stab_demangle_info *minfo; + const char **pp; + debug_type *ptype; +{ + const char *orig; + const char *p; + unsigned int qualifiers; + debug_type context; + + orig = *pp; + + switch ((*pp)[1]) + { + case '_': + /* GNU mangled name with more than 9 classes. The count is + preceded by an underscore (to distinguish it from the <= 9 + case) and followed by an underscore. */ + p = *pp + 2; + if (! isdigit ((unsigned char) *p) || *p == '0') + { + stab_bad_demangle (orig); + return false; + } + qualifiers = atoi (p); + while (isdigit ((unsigned char) *p)) + ++p; + if (*p != '_') + { + stab_bad_demangle (orig); + return false; + } + *pp = p + 1; + break; + + case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + qualifiers = (*pp)[1] - '0'; + /* Skip an optional underscore after the count. */ + if ((*pp)[2] == '_') + ++*pp; + *pp += 2; + break; + + case '0': + default: + stab_bad_demangle (orig); + return false; + } + + context = DEBUG_TYPE_NULL; + + /* Pick off the names. */ + while (qualifiers-- > 0) + { + if (**pp == '_') + ++*pp; + if (**pp == 't') + { + char *name; + + if (! stab_demangle_template (minfo, pp, + ptype != NULL ? &name : NULL)) + return false; + + if (ptype != NULL) + { + context = stab_find_tagged_type (minfo->dhandle, minfo->info, + name, strlen (name), + DEBUG_KIND_CLASS); + free (name); + if (context == DEBUG_TYPE_NULL) + return false; + } + } + else + { + unsigned int len; + + len = stab_demangle_count (pp); + if (strlen (*pp) < len) + { + stab_bad_demangle (orig); + return false; + } + + if (ptype != NULL) + { + const debug_field *fields; + + fields = NULL; + if (context != DEBUG_TYPE_NULL) + fields = debug_get_fields (minfo->dhandle, context); + + context = DEBUG_TYPE_NULL; + + if (fields != NULL) + { + char *name; + + /* Try to find the type by looking through the + fields of context until we find a field with the + same type. This ought to work for a class + defined within a class, but it won't work for, + e.g., an enum defined within a class. stabs does + not give us enough information to figure out the + latter case. */ + + name = savestring (*pp, len); + + for (; *fields != DEBUG_FIELD_NULL; fields++) + { + debug_type ft; + const char *dn; + + ft = debug_get_field_type (minfo->dhandle, *fields); + if (ft == NULL) + return false; + dn = debug_get_type_name (minfo->dhandle, ft); + if (dn != NULL && strcmp (dn, name) == 0) + { + context = ft; + break; + } + } + + free (name); + } + + if (context == DEBUG_TYPE_NULL) + { + /* We have to fall back on finding the type by name. + If there are more types to come, then this must + be a class. Otherwise, it could be anything. */ + + if (qualifiers == 0) + { + char *name; + + name = savestring (*pp, len); + context = debug_find_named_type (minfo->dhandle, + name); + free (name); + } + + if (context == DEBUG_TYPE_NULL) + { + context = stab_find_tagged_type (minfo->dhandle, + minfo->info, + *pp, len, + (qualifiers == 0 + ? DEBUG_KIND_ILLEGAL + : DEBUG_KIND_CLASS)); + if (context == DEBUG_TYPE_NULL) + return false; + } + } + } + + *pp += len; + } + } + + if (ptype != NULL) + *ptype = context; + + return true; +} + +/* Demangle a template. If PNAME is not NULL, this sets *PNAME to a + string representation of the template. */ + +static boolean +stab_demangle_template (minfo, pp, pname) + struct stab_demangle_info *minfo; + const char **pp; + char **pname; +{ + const char *orig; + unsigned int r, i; + + orig = *pp; + + ++*pp; + + /* Skip the template name. */ + r = stab_demangle_count (pp); + if (r == 0 || strlen (*pp) < r) + { + stab_bad_demangle (orig); + return false; + } + *pp += r; + + /* Get the size of the parameter list. */ + if (stab_demangle_get_count (pp, &r) == 0) + { + stab_bad_demangle (orig); + return false; + } + + for (i = 0; i < r; i++) + { + if (**pp == 'Z') + { + /* This is a type parameter. */ + ++*pp; + if (! stab_demangle_type (minfo, pp, (debug_type *) NULL)) + return false; + } + else + { + const char *old_p; + boolean pointerp, realp, integralp, charp, boolp; + boolean done; + + old_p = *pp; + pointerp = false; + realp = false; + integralp = false; + charp = false; + boolp = false; + done = false; + + /* This is a value parameter. */ + + if (! stab_demangle_type (minfo, pp, (debug_type *) NULL)) + return false; + + while (*old_p != '\0' && ! done) + { + switch (*old_p) + { + case 'P': + case 'p': + case 'R': + pointerp = true; + done = true; + break; + case 'C': /* Const. */ + case 'S': /* Signed. */ + case 'U': /* Unsigned. */ + case 'V': /* Volatile. */ + case 'F': /* Function. */ + case 'M': /* Member function. */ + case 'O': /* ??? */ + ++old_p; + break; + case 'Q': /* Qualified name. */ + integralp = true; + done = true; + break; + case 'T': /* Remembered type. */ + abort (); + case 'v': /* Void. */ + abort (); + case 'x': /* Long long. */ + case 'l': /* Long. */ + case 'i': /* Int. */ + case 's': /* Short. */ + case 'w': /* Wchar_t. */ + integralp = true; + done = true; + break; + case 'b': /* Bool. */ + boolp = true; + done = true; + break; + case 'c': /* Char. */ + charp = true; + done = true; + break; + case 'r': /* Long double. */ + case 'd': /* Double. */ + case 'f': /* Float. */ + realp = true; + done = true; + break; + default: + /* Assume it's a user defined integral type. */ + integralp = true; + done = true; + break; + } + } + + if (integralp) + { + if (**pp == 'm') + ++*pp; + while (isdigit ((unsigned char) **pp)) + ++*pp; + } + else if (charp) + { + unsigned int val; + + if (**pp == 'm') + ++*pp; + val = stab_demangle_count (pp); + if (val == 0) + { + stab_bad_demangle (orig); + return false; + } + } + else if (boolp) + { + unsigned int val; + + val = stab_demangle_count (pp); + if (val != 0 && val != 1) + { + stab_bad_demangle (orig); + return false; + } + } + else if (realp) + { + if (**pp == 'm') + ++*pp; + while (isdigit ((unsigned char) **pp)) + ++*pp; + if (**pp == '.') + { + ++*pp; + while (isdigit ((unsigned char) **pp)) + ++*pp; + } + if (**pp == 'e') + { + ++*pp; + while (isdigit ((unsigned char) **pp)) + ++*pp; + } + } + else if (pointerp) + { + unsigned int len; + + if (! stab_demangle_get_count (pp, &len)) + { + stab_bad_demangle (orig); + return false; + } + *pp += len; + } + } + } + + /* We can translate this to a string fairly easily by invoking the + regular demangling routine. */ + if (pname != NULL) + { + char *s1, *s2, *s3, *s4; + char *from, *to; + + s1 = savestring (orig, *pp - orig); + + s2 = concat ("NoSuchStrinG__", s1, (const char *) NULL); + + free (s1); + + s3 = cplus_demangle (s2, DMGL_ANSI); + + free (s2); + + if (s3 != NULL) + s4 = strstr (s3, "::NoSuchStrinG"); + if (s3 == NULL || s4 == NULL) + { + stab_bad_demangle (orig); + if (s3 != NULL) + free (s3); + return false; + } + + /* Eliminating all spaces, except those between > characters, + makes it more likely that the demangled name will match the + name which g++ used as the structure name. */ + for (from = to = s3; from != s4; ++from) + if (*from != ' ' + || (from[1] == '>' && from > s3 && from[-1] == '>')) + *to++ = *from; + + *pname = savestring (s3, to - s3); + + free (s3); + } + + return true; +} + +/* Demangle a class name. */ + +static boolean +stab_demangle_class (minfo, pp, pstart) + struct stab_demangle_info *minfo; + const char **pp; + const char **pstart; +{ + const char *orig; + unsigned int n; + + orig = *pp; + + n = stab_demangle_count (pp); + if (strlen (*pp) < n) + { + stab_bad_demangle (orig); + return false; + } + + if (pstart != NULL) + *pstart = *pp; + + *pp += n; + + return true; +} + +/* Demangle function arguments. If the pargs argument is not NULL, it + is set to a NULL terminated array holding the arguments. */ + +static boolean +stab_demangle_args (minfo, pp, pargs, pvarargs) + struct stab_demangle_info *minfo; + const char **pp; + debug_type **pargs; + boolean *pvarargs; +{ + const char *orig; + unsigned int alloc, count; + + orig = *pp; + + alloc = 10; + if (pargs != NULL) + { + *pargs = (debug_type *) xmalloc (alloc * sizeof **pargs); + *pvarargs = false; + } + count = 0; + + while (**pp != '_' && **pp != '\0' && **pp != 'e') + { + if (**pp == 'N' || **pp == 'T') + { + char temptype; + unsigned int r, t; + + temptype = **pp; + ++*pp; + + if (temptype == 'T') + r = 1; + else + { + if (! stab_demangle_get_count (pp, &r)) + { + stab_bad_demangle (orig); + return false; + } + } + + if (! stab_demangle_get_count (pp, &t)) + { + stab_bad_demangle (orig); + return false; + } + + if (t >= minfo->typestring_count) + { + stab_bad_demangle (orig); + return false; + } + while (r-- > 0) + { + const char *tem; + + tem = minfo->typestrings[t].typestring; + if (! stab_demangle_arg (minfo, &tem, pargs, &count, &alloc)) + return false; + } + } + else + { + if (! stab_demangle_arg (minfo, pp, pargs, &count, &alloc)) + return false; + } + } + + if (pargs != NULL) + (*pargs)[count] = DEBUG_TYPE_NULL; + + if (**pp == 'e') + { + if (pargs != NULL) + *pvarargs = true; + ++*pp; + } + + return true; +} + +/* Demangle a single argument. */ + +static boolean +stab_demangle_arg (minfo, pp, pargs, pcount, palloc) + struct stab_demangle_info *minfo; + const char **pp; + debug_type **pargs; + unsigned int *pcount; + unsigned int *palloc; +{ + const char *start; + debug_type type; + + start = *pp; + if (! stab_demangle_type (minfo, pp, + pargs == NULL ? (debug_type *) NULL : &type) + || ! stab_demangle_remember_type (minfo, start, *pp - start)) + return false; + + if (pargs != NULL) + { + if (type == DEBUG_TYPE_NULL) + return false; + + if (*pcount + 1 >= *palloc) + { + *palloc += 10; + *pargs = ((debug_type *) + xrealloc (*pargs, *palloc * sizeof **pargs)); + } + (*pargs)[*pcount] = type; + ++*pcount; + } + + return true; +} + +/* Demangle a type. If the ptype argument is not NULL, *ptype is set + to the newly allocated type. */ + +static boolean +stab_demangle_type (minfo, pp, ptype) + struct stab_demangle_info *minfo; + const char **pp; + debug_type *ptype; +{ + const char *orig; + + orig = *pp; + + switch (**pp) + { + case 'P': + case 'p': + /* A pointer type. */ + ++*pp; + if (! stab_demangle_type (minfo, pp, ptype)) + return false; + if (ptype != NULL) + *ptype = debug_make_pointer_type (minfo->dhandle, *ptype); + break; + + case 'R': + /* A reference type. */ + ++*pp; + if (! stab_demangle_type (minfo, pp, ptype)) + return false; + if (ptype != NULL) + *ptype = debug_make_reference_type (minfo->dhandle, *ptype); + break; + + case 'A': + /* An array. */ + { + unsigned long high; + + ++*pp; + high = 0; + while (**pp != '\0' && **pp != '_') + { + if (! isdigit ((unsigned char) **pp)) + { + stab_bad_demangle (orig); + return false; + } + high *= 10; + high += **pp - '0'; + ++*pp; + } + if (**pp != '_') + { + stab_bad_demangle (orig); + return false; + } + ++*pp; + + if (! stab_demangle_type (minfo, pp, ptype)) + return false; + if (ptype != NULL) + { + debug_type int_type; + + int_type = debug_find_named_type (minfo->dhandle, "int"); + if (int_type == NULL) + int_type = debug_make_int_type (minfo->dhandle, 4, false); + *ptype = debug_make_array_type (minfo->dhandle, *ptype, int_type, + 0, high, false); + } + } + break; + + case 'T': + /* A back reference to a remembered type. */ + { + unsigned int i; + const char *p; + + ++*pp; + if (! stab_demangle_get_count (pp, &i)) + { + stab_bad_demangle (orig); + return false; + } + if (i >= minfo->typestring_count) + { + stab_bad_demangle (orig); + return false; + } + p = minfo->typestrings[i].typestring; + if (! stab_demangle_type (minfo, &p, ptype)) + return false; + } + break; + + case 'F': + /* A function. */ + { + debug_type *args; + boolean varargs; + + ++*pp; + if (! stab_demangle_args (minfo, pp, + (ptype == NULL + ? (debug_type **) NULL + : &args), + (ptype == NULL + ? (boolean *) NULL + : &varargs))) + return false; + if (**pp != '_') + { + /* cplus_demangle will accept a function without a return + type, but I don't know when that will happen, or what + to do if it does. */ + stab_bad_demangle (orig); + return false; + } + ++*pp; + if (! stab_demangle_type (minfo, pp, ptype)) + return false; + if (ptype != NULL) + *ptype = debug_make_function_type (minfo->dhandle, *ptype, args, + varargs); + + } + break; + + case 'M': + case 'O': + { + boolean memberp, constp, volatilep; + debug_type *args; + boolean varargs; + unsigned int n; + const char *name; + + memberp = **pp == 'M'; + constp = false; + volatilep = false; + args = NULL; + varargs = false; + + ++*pp; + if (! isdigit ((unsigned char) **pp)) + { + stab_bad_demangle (orig); + return false; + } + n = stab_demangle_count (pp); + if (strlen (*pp) < n) + { + stab_bad_demangle (orig); + return false; + } + name = *pp; + *pp += n; + + if (memberp) + { + if (**pp == 'C') + { + constp = true; + ++*pp; + } + else if (**pp == 'V') + { + volatilep = true; + ++*pp; + } + if (**pp != 'F') + { + stab_bad_demangle (orig); + return false; + } + ++*pp; + if (! stab_demangle_args (minfo, pp, + (ptype == NULL + ? (debug_type **) NULL + : &args), + (ptype == NULL + ? (boolean *) NULL + : &varargs))) + return false; + } + + if (**pp != '_') + { + stab_bad_demangle (orig); + return false; + } + ++*pp; + + if (! stab_demangle_type (minfo, pp, ptype)) + return false; + + if (ptype != NULL) + { + debug_type class_type; + + class_type = stab_find_tagged_type (minfo->dhandle, minfo->info, + name, (int) n, + DEBUG_KIND_CLASS); + if (class_type == DEBUG_TYPE_NULL) + return false; + + if (! memberp) + *ptype = debug_make_offset_type (minfo->dhandle, class_type, + *ptype); + else + { + /* FIXME: We have no way to record constp or + volatilep. */ + *ptype = debug_make_method_type (minfo->dhandle, *ptype, + class_type, args, varargs); + } + } + } + break; + + case 'G': + ++*pp; + if (! stab_demangle_type (minfo, pp, ptype)) + return false; + break; + + case 'C': + ++*pp; + if (! stab_demangle_type (minfo, pp, ptype)) + return false; + if (ptype != NULL) + *ptype = debug_make_const_type (minfo->dhandle, *ptype); + break; + + case 'Q': + { + const char *hold; + + hold = *pp; + if (! stab_demangle_qualified (minfo, pp, ptype)) + return false; + } + break; + + default: + if (! stab_demangle_fund_type (minfo, pp, ptype)) + return false; + break; + } + + return true; +} + +/* Demangle a fundamental type. If the ptype argument is not NULL, + *ptype is set to the newly allocated type. */ + +static boolean +stab_demangle_fund_type (minfo, pp, ptype) + struct stab_demangle_info *minfo; + const char **pp; + debug_type *ptype; +{ + const char *orig; + boolean constp, volatilep, unsignedp, signedp; + boolean done; + + orig = *pp; + + constp = false; + volatilep = false; + unsignedp = false; + signedp = false; + + done = false; + while (! done) + { + switch (**pp) + { + case 'C': + constp = true; + ++*pp; + break; + + case 'U': + unsignedp = true; + ++*pp; + break; + + case 'S': + signedp = true; + ++*pp; + break; + + case 'V': + volatilep = true; + ++*pp; + break; + + default: + done = true; + break; + } + } + + switch (**pp) + { + case '\0': + case '_': + /* cplus_demangle permits this, but I don't know what it means. */ + stab_bad_demangle (orig); + break; + + case 'v': /* void */ + if (ptype != NULL) + { + *ptype = debug_find_named_type (minfo->dhandle, "void"); + if (*ptype == DEBUG_TYPE_NULL) + *ptype = debug_make_void_type (minfo->dhandle); + } + ++*pp; + break; + + case 'x': /* long long */ + if (ptype != NULL) + { + *ptype = debug_find_named_type (minfo->dhandle, + (unsignedp + ? "long long unsigned int" + : "long long int")); + if (*ptype == DEBUG_TYPE_NULL) + *ptype = debug_make_int_type (minfo->dhandle, 8, unsignedp); + } + ++*pp; + break; + + case 'l': /* long */ + if (ptype != NULL) + { + *ptype = debug_find_named_type (minfo->dhandle, + (unsignedp + ? "long unsigned int" + : "long int")); + if (*ptype == DEBUG_TYPE_NULL) + *ptype = debug_make_int_type (minfo->dhandle, 4, unsignedp); + } + ++*pp; + break; + + case 'i': /* int */ + if (ptype != NULL) + { + *ptype = debug_find_named_type (minfo->dhandle, + (unsignedp + ? "unsigned int" + : "int")); + if (*ptype == DEBUG_TYPE_NULL) + *ptype = debug_make_int_type (minfo->dhandle, 4, unsignedp); + } + ++*pp; + break; + + case 's': /* short */ + if (ptype != NULL) + { + *ptype = debug_find_named_type (minfo->dhandle, + (unsignedp + ? "short unsigned int" + : "short int")); + if (*ptype == DEBUG_TYPE_NULL) + *ptype = debug_make_int_type (minfo->dhandle, 2, unsignedp); + } + ++*pp; + break; + + case 'b': /* bool */ + if (ptype != NULL) + { + *ptype = debug_find_named_type (minfo->dhandle, "bool"); + if (*ptype == DEBUG_TYPE_NULL) + *ptype = debug_make_bool_type (minfo->dhandle, 4); + } + ++*pp; + break; + + case 'c': /* char */ + if (ptype != NULL) + { + *ptype = debug_find_named_type (minfo->dhandle, + (unsignedp + ? "unsigned char" + : (signedp + ? "signed char" + : "char"))); + if (*ptype == DEBUG_TYPE_NULL) + *ptype = debug_make_int_type (minfo->dhandle, 1, unsignedp); + } + ++*pp; + break; + + case 'w': /* wchar_t */ + if (ptype != NULL) + { + *ptype = debug_find_named_type (minfo->dhandle, "__wchar_t"); + if (*ptype == DEBUG_TYPE_NULL) + *ptype = debug_make_int_type (minfo->dhandle, 2, true); + } + ++*pp; + break; + + case 'r': /* long double */ + if (ptype != NULL) + { + *ptype = debug_find_named_type (minfo->dhandle, "long double"); + if (*ptype == DEBUG_TYPE_NULL) + *ptype = debug_make_float_type (minfo->dhandle, 8); + } + ++*pp; + break; + + case 'd': /* double */ + if (ptype != NULL) + { + *ptype = debug_find_named_type (minfo->dhandle, "double"); + if (*ptype == DEBUG_TYPE_NULL) + *ptype = debug_make_float_type (minfo->dhandle, 8); + } + ++*pp; + break; + + case 'f': /* float */ + if (ptype != NULL) + { + *ptype = debug_find_named_type (minfo->dhandle, "float"); + if (*ptype == DEBUG_TYPE_NULL) + *ptype = debug_make_float_type (minfo->dhandle, 4); + } + ++*pp; + break; + + case 'G': + ++*pp; + if (! isdigit ((unsigned char) **pp)) + { + stab_bad_demangle (orig); + return false; + } + /* Fall through. */ + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + { + const char *hold; + + if (! stab_demangle_class (minfo, pp, &hold)) + return false; + if (ptype != NULL) + { + char *name; + + name = savestring (hold, *pp - hold); + *ptype = debug_find_named_type (minfo->dhandle, name); + free (name); + if (*ptype == DEBUG_TYPE_NULL) + { + /* FIXME: It is probably incorrect to assume that + undefined types are tagged types. */ + *ptype = stab_find_tagged_type (minfo->dhandle, minfo->info, + hold, *pp - hold, + DEBUG_KIND_ILLEGAL); + if (*ptype == DEBUG_TYPE_NULL) + return false; + } + } + } + break; + + case 't': + { + char *name; + + if (! stab_demangle_template (minfo, pp, + ptype != NULL ? &name : NULL)) + return false; + if (ptype != NULL) + { + *ptype = stab_find_tagged_type (minfo->dhandle, minfo->info, + name, strlen (name), + DEBUG_KIND_CLASS); + free (name); + if (*ptype == DEBUG_TYPE_NULL) + return false; + } + } + break; + + default: + stab_bad_demangle (orig); + return false; + } + + if (ptype != NULL) + { + if (constp) + *ptype = debug_make_const_type (minfo->dhandle, *ptype); + if (volatilep) + *ptype = debug_make_volatile_type (minfo->dhandle, *ptype); + } + + return true; +} + +/* Remember a type string in a demangled string. */ + +static boolean +stab_demangle_remember_type (minfo, p, len) + struct stab_demangle_info *minfo; + const char *p; + int len; +{ + if (minfo->typestring_count >= minfo->typestring_alloc) + { + minfo->typestring_alloc += 10; + minfo->typestrings = ((struct stab_demangle_typestring *) + xrealloc (minfo->typestrings, + (minfo->typestring_alloc + * sizeof *minfo->typestrings))); + } + + minfo->typestrings[minfo->typestring_count].typestring = p; + minfo->typestrings[minfo->typestring_count].len = (unsigned int) len; + ++minfo->typestring_count; + + return true; +} diff --git a/binutils/stamp-h.in b/binutils/stamp-h.in new file mode 100644 index 0000000..9788f70 --- /dev/null +++ b/binutils/stamp-h.in @@ -0,0 +1 @@ +timestamp diff --git a/binutils/strings.1 b/binutils/strings.1 new file mode 100644 index 0000000..408de29 --- /dev/null +++ b/binutils/strings.1 @@ -0,0 +1,151 @@ +.\" Copyright (c) 1993 Free Software Foundation +.\" See section COPYING for conditions for redistribution +.TH strings 1 "25 June 1993" "cygnus support" "GNU Development Tools" +.de BP +.sp +.ti \-.2i +\(** +.. + +.SH NAME +strings \- print the strings of printable characters in files + +.SH SYNOPSIS +.hy 0 +.na +.TP +.B strings +.RB "[\|" \-a | \-\c +.RB | \-\-all "\|]" +.RB "[\|" \-f | \-\-print\-file\-name "\|]" +.RB "[\|" \-o "\|]" +.RB "[\|" \-\-help "\|]" +.RB "[\|" \-v | \-\-version "\|]" +.RB "[\|" \-n +.I min\-len\c +.RI | \-min\-len\c +.RB | "\-\-bytes="\c +.I min\-len\c +\&\|] +.RB "[\|" \-t +.I {o,x,d}\c +.RB "[\|" "\-\-target=\fIbfdname" "\|]" +.RB | "\-\-radix="\c +.I {o,x,d}\c +\&\|] +.I file\c +.ad b +.hy 1 +.SH DESCRIPTION +For each +.I file +given, GNU \c +.B strings +prints the printable character sequences that are at least 4 +characters long (or the number given with the options below) and are +followed by an unprintable character. By default, it only prints the +strings from the initialized and loaded sections of object files; for +other types of files, it prints the strings from the whole file. + +.PP +.B strings +is mainly useful for determining the contents of non-text files. + +.SH OPTIONS +The long and short forms of options, shown here as alternatives, are +equivalent. + +.TP +.B \-a +.TP +.B \-\-all +.TP +.B \- +Do not scan only the initialized and loaded sections of object files; +scan the whole files. + +.TP +.B \-f +.TP +.B \-\-print\-file\-name +Print the name of the file before each string. + +.TP +.B \-\-help +Print a summary of the options to +.B strings +on the standard output and exit. + +.TP +.B \-v +.TP +.B \-\-version +Print the version number +of +.B strings +on the standard output and exit. + +.TP +.B "\-n \fImin\-len\fP" +.TP +.B "\-\fImin\-len\fP" +.TP +.B "\-bytes=\fImin\-len\fP" +Print sequences of characters that are at least +.I min\-len +characters long, instead of the default 4. + +.TP +.BR "\-t " {o,x,d} +.TP +.BR "\-\-radix=" {o,x,d} +Print the offset within the file before each string. The single +character argument specifies the radix of the offset\(emoctal, +hexadecimal, or decimal. + +.TP +.BI "\-\-target=" "bfdname" +Specify an object code format other than your system's default format. +See +.BR objdump ( 1 ), +for information on listing available formats. + +.TP +.B \-o +Like +.BR "\-t o" . + +.PP + +.SH "SEE ALSO" +.RB "`\|" binutils "\|'" +entry in +.B +info\c +\&; +.I +The GNU Binary Utilities\c +\&, Roland H. Pesch (October 1991); +.BR ar ( 1 ), +.BR nm ( 1 ), +.BR objdump ( 1 ), +.BR ranlib ( 1 ). + + +.SH COPYING +Copyright (c) 1993 Free Software Foundation, Inc. +.PP +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. +.PP +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the +entire resulting derived work is distributed under the terms of a +permission notice identical to this one. +.PP +Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be included in +translations approved by the Free Software Foundation instead of in +the original English. diff --git a/binutils/strings.c b/binutils/strings.c new file mode 100644 index 0000000..8ffe6a1 --- /dev/null +++ b/binutils/strings.c @@ -0,0 +1,514 @@ +/* strings -- print the strings of printable characters in files + Copyright (C) 1993, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* Usage: strings [options] file... + + Options: + --all + -a + - Do not scan only the initialized data section of object files. + + --print-file-name + -f Print the name of the file before each string. + + --bytes=min-len + -n min-len + -min-len Print graphic char sequences, MIN-LEN or more bytes long, + that are followed by a NUL or a newline. Default is 4. + + --radix={o,x,d} + -t {o,x,d} Print the offset within the file before each string, + in octal/hex/decimal. + + -o Like -to. (Some other implementations have -o like -to, + others like -td. We chose one arbitrarily.) + + --target=BFDNAME + Specify a non-default object file format. + + --help + -h Print the usage message on the standard output. + + --version + -v Print the program version number. + + Written by Richard Stallman <rms@gnu.ai.mit.edu> + and David MacKenzie <djm@gnu.ai.mit.edu>. */ + +#include "bfd.h" +#include <stdio.h> +#include <getopt.h> +#include <ctype.h> +#include <errno.h> +#include "bucomm.h" +#include "libiberty.h" + +#ifdef isascii +#define isgraphic(c) (isascii (c) && isprint (c)) +#else +#define isgraphic(c) (isprint (c)) +#endif + +#ifndef errno +extern int errno; +#endif + +/* The BFD section flags that identify an initialized data section. */ +#define DATA_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS) + +/* Radix for printing addresses (must be 8, 10 or 16). */ +static int address_radix; + +/* Minimum length of sequence of graphic chars to trigger output. */ +static int string_min; + +/* true means print address within file for each string. */ +static boolean print_addresses; + +/* true means print filename for each string. */ +static boolean print_filenames; + +/* true means for object files scan only the data section. */ +static boolean datasection_only; + +/* true if we found an initialized data section in the current file. */ +static boolean got_a_section; + +/* The BFD object file format. */ +static char *target; + +static struct option long_options[] = +{ + {"all", no_argument, NULL, 'a'}, + {"print-file-name", no_argument, NULL, 'f'}, + {"bytes", required_argument, NULL, 'n'}, + {"radix", required_argument, NULL, 't'}, + {"target", required_argument, NULL, 'T'}, + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'v'}, + {NULL, 0, NULL, 0} +}; + +static void strings_a_section PARAMS ((bfd *, asection *, PTR)); +static boolean strings_object_file PARAMS ((const char *)); +static boolean strings_file PARAMS ((char *file)); +static int integer_arg PARAMS ((char *s)); +static void print_strings PARAMS ((const char *filename, FILE *stream, + file_ptr address, int stop_point, + int magiccount, char *magic)); +static void usage PARAMS ((FILE *stream, int status)); + +int +main (argc, argv) + int argc; + char **argv; +{ + int optc; + int exit_status = 0; + boolean files_given = false; + +#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) + setlocale (LC_MESSAGES, ""); +#endif + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + + program_name = argv[0]; + xmalloc_set_program_name (program_name); + string_min = -1; + print_addresses = false; + print_filenames = false; + datasection_only = true; + target = NULL; + + while ((optc = getopt_long (argc, argv, "afn:ot:v0123456789", + long_options, (int *) 0)) != EOF) + { + switch (optc) + { + case 'a': + datasection_only = false; + break; + + case 'f': + print_filenames = true; + break; + + case 'h': + usage (stdout, 0); + + case 'n': + string_min = integer_arg (optarg); + if (string_min < 1) + { + fprintf (stderr, _("%s: invalid number %s\n"), + program_name, optarg); + exit (1); + } + break; + + case 'o': + print_addresses = true; + address_radix = 8; + break; + + case 't': + print_addresses = true; + if (optarg[1] != '\0') + usage (stderr, 1); + switch (optarg[0]) + { + case 'o': + address_radix = 8; + break; + + case 'd': + address_radix = 10; + break; + + case 'x': + address_radix = 16; + break; + + default: + usage (stderr, 1); + } + break; + + case 'T': + target = optarg; + break; + + case 'v': + print_version ("strings"); + break; + + case '?': + usage (stderr, 1); + + default: + if (string_min < 0) + string_min = optc; + else + string_min = string_min * 10 + optc - '0'; + break; + } + } + + if (string_min < 0) + string_min = 4; + + bfd_init (); + set_default_bfd_target (); + + if (optind >= argc) + { + datasection_only = false; + print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL); + files_given = true; + } + else + { + for (; optind < argc; ++optind) + { + if (strcmp (argv[optind], "-") == 0) + datasection_only = false; + else + { + files_given = true; + exit_status |= (strings_file (argv[optind]) == false); + } + } + } + + if (files_given == false) + usage (stderr, 1); + + return (exit_status); +} + +/* Scan section SECT of the file ABFD, whose printable name is FILE. + If it contains initialized data, + set `got_a_section' and print the strings in it. */ + +static void +strings_a_section (abfd, sect, filearg) + bfd *abfd; + asection *sect; + PTR filearg; +{ + const char *file = (const char *) filearg; + + if ((sect->flags & DATA_FLAGS) == DATA_FLAGS) + { + bfd_size_type sz = bfd_get_section_size_before_reloc (sect); + PTR mem = xmalloc (sz); + if (bfd_get_section_contents (abfd, sect, mem, (file_ptr) 0, sz)) + { + got_a_section = true; + print_strings (file, (FILE *) NULL, sect->filepos, 0, sz, mem); + } + free (mem); + } +} + +/* Scan all of the sections in FILE, and print the strings + in the initialized data section(s). + + Return true if successful, + false if not (such as if FILE is not an object file). */ + +static boolean +strings_object_file (file) + const char *file; +{ + bfd *abfd = bfd_openr (file, target); + + if (abfd == NULL) + { + /* Treat the file as a non-object file. */ + return false; + } + + /* This call is mainly for its side effect of reading in the sections. + We follow the traditional behavior of `strings' in that we don't + complain if we don't recognize a file to be an object file. */ + if (bfd_check_format (abfd, bfd_object) == false) + { + bfd_close (abfd); + return false; + } + + got_a_section = false; + bfd_map_over_sections (abfd, strings_a_section, (PTR) file); + + if (!bfd_close (abfd)) + { + bfd_nonfatal (file); + return false; + } + + return got_a_section; +} + +/* Print the strings in FILE. Return true if ok, false if an error occurs. */ + +static boolean +strings_file (file) + char *file; +{ + /* If we weren't told to scan the whole file, + try to open it as an object file and only look at + initialized data sections. If that fails, fall back to the + whole file. */ + if (!datasection_only || !strings_object_file (file)) + { + FILE *stream; + + stream = fopen (file, "rb"); + /* Not all systems permit "rb", so try "r" if it failed. */ + if (stream == NULL) + stream = fopen (file, "r"); + if (stream == NULL) + { + fprintf (stderr, "%s: ", program_name); + perror (file); + return false; + } + + print_strings (file, stream, (file_ptr) 0, 0, 0, (char *) 0); + + if (fclose (stream) == EOF) + { + fprintf (stderr, "%s: ", program_name); + perror (file); + return false; + } + } + + return true; +} + +/* Find the strings in file FILENAME, read from STREAM. + Assume that STREAM is positioned so that the next byte read + is at address ADDRESS in the file. + Stop reading at address STOP_POINT in the file, if nonzero. + + If STREAM is NULL, do not read from it. + The caller can supply a buffer of characters + to be processed before the data in STREAM. + MAGIC is the address of the buffer and + MAGICCOUNT is how many characters are in it. + Those characters come at address ADDRESS and the data in STREAM follow. */ + +static void +print_strings (filename, stream, address, stop_point, magiccount, magic) + const char *filename; + FILE *stream; + file_ptr address; + int stop_point; + int magiccount; + char *magic; +{ + char *buf = (char *) xmalloc (string_min + 1); + + while (1) + { + file_ptr start; + int i; + int c; + + /* See if the next `string_min' chars are all graphic chars. */ + tryline: + if (stop_point && address >= stop_point) + break; + start = address; + for (i = 0; i < string_min; i++) + { + if (magiccount) + { + magiccount--; + c = *magic++; + } + else + { + if (stream == NULL) + return; + c = getc (stream); + if (c == EOF) + return; + } + address++; + if (!isgraphic (c)) + /* Found a non-graphic. Try again starting with next char. */ + goto tryline; + buf[i] = c; + } + + /* We found a run of `string_min' graphic characters. Print up + to the next non-graphic character. */ + + if (print_filenames) + printf ("%s: ", filename); + if (print_addresses) + switch (address_radix) + { + case 8: + printf ("%7lo ", (unsigned long) start); + break; + + case 10: + printf ("%7ld ", (long) start); + break; + + case 16: + printf ("%7lx ", (unsigned long) start); + break; + } + + buf[i] = '\0'; + fputs (buf, stdout); + + while (1) + { + if (magiccount) + { + magiccount--; + c = *magic++; + } + else + { + if (stream == NULL) + break; + c = getc (stream); + if (c == EOF) + break; + } + address++; + if (! isgraphic (c)) + break; + putchar (c); + } + + putchar ('\n'); + } +} + +/* Parse string S as an integer, using decimal radix by default, + but allowing octal and hex numbers as in C. */ + +static int +integer_arg (s) + char *s; +{ + int value; + int radix = 10; + char *p = s; + int c; + + if (*p != '0') + radix = 10; + else if (*++p == 'x') + { + radix = 16; + p++; + } + else + radix = 8; + + value = 0; + while (((c = *p++) >= '0' && c <= '9') + || (radix == 16 && (c & ~40) >= 'A' && (c & ~40) <= 'Z')) + { + value *= radix; + if (c >= '0' && c <= '9') + value += c - '0'; + else + value += (c & ~40) - 'A'; + } + + if (c == 'b') + value *= 512; + else if (c == 'B') + value *= 1024; + else + p--; + + if (*p) + { + fprintf (stderr, _("%s: invalid integer argument %s\n"), program_name, s); + exit (1); + } + return value; +} + +static void +usage (stream, status) + FILE *stream; + int status; +{ + fprintf (stream, _("\ +Usage: %s [-afov] [-n min-len] [-min-len] [-t {o,x,d}] [-]\n\ + [--all] [--print-file-name] [--bytes=min-len] [--radix={o,x,d}]\n\ + [--target=bfdname] [--help] [--version] file...\n"), + program_name); + list_supported_targets (program_name, stream); + if (status == 0) + fprintf (stream, _("Report bugs to bug-gnu-utils@gnu.org\n")); + exit (status); +} diff --git a/binutils/strip.1 b/binutils/strip.1 new file mode 100644 index 0000000..708817d --- /dev/null +++ b/binutils/strip.1 @@ -0,0 +1,185 @@ +.\" Copyright (c) 1991, 92, 93, 94, 95, 96, 97, 1998 Free Software Foundation +.\" See section COPYING for conditions for redistribution +.TH strip 1 "5 November 1991" "cygnus support" "GNU Development Tools" +.de BP +.sp +.ti \-.2i +\(** +.. + +.SH NAME +strip \- Discard symbols from object files. + +.SH SYNOPSIS +.hy 0 +.na +.TP +.B strip +.RB "[\|" \-F\ \fIbfdname\fR\ |\ \fB\-\-target=\fIbfdname\fP "\|]" +.RB "[\|" \-I\ \fIbfdname\fR\ |\ \fB\-\-input\-target=\fIbfdname\fP "\|]" +.RB "[\|" \-O\ \fIbfdname\fR\ |\ \fB\-\-output\-target=\fIbfdname\fP "\|]" +.RB "[\|" \-R\ \fIsectionname\fR\ |\ \fB\-\-remove\-section=\fIsectionname\fP "\|]" +.RB "[\|" \-s\fR\ |\ \fB\-\-strip\-all "\|]" +.RB "[\|" \-S\fR\ |\ \fB\-g\fR\ |\ \fB\-\-strip\-debug "\|]" +.RB "[\|" \-\-strip\-unneeded\fR "\|]" +.RB "[\|" \-x\fR\ |\ \fB\-\-discard\-all "\|]" +.RB "[\|" \-X\fR\ |\ \fB\-\-discard\-locals "\|]" +.RB "[\|" \-K\ \fIsymbolname\fR\ |\ \fB\-\-keep\-symbol=\fIsymbolname\fR "\|]" +.RB "[\|" \-N\ \fIsymbolname\fR\ |\ \fB\-\-strip\-symbol=\fIsymbolname\fR "\|]" +.RB "[\|" \-o\ \fIfile\f\R "\|]" +.RB "[\|" \-p\fR\ |\ \fB\-\-preserve\-dates "\|]" +.RB "[\|" \-v\fR\ |\ \fB\-\-verbose "\|]" +.RB "[\|" \-V\fR\ |\ \fB\-\-version "\|]" +.RB "[\|" \-V\fR\ |\ \fB\-\-help "\|]" +.I objfile\c +\&.\|.\|. + +.SH DESCRIPTION +GNU +.B strip +discards all symbols from the object files +.IR objfile . +The list of object files may include archives. +At least one object file must be given. + +.P +.B strip +modifies the files named in its argument, +rather than writing modified copies under different names. + +.SH OPTIONS +.TP +.B "\-F \fIbfdname" +.TP +.B "\-\-target=\fIbfdname" +Treat the original \fIobjfile\fP as a file with the object +code format \fIbfdname\fP, and rewrite it in the same format. + +.TP +.B \-\-help +Show a summary of the options to +.B strip +and exit. + +.TP +.B "\-I \fIbfdname +.TP +.B "\-\-input\-target=\fIbfdname" +Treat the original \fIobjfile\fP as a file with the object +code format \fIbfdname\fP. + +.TP +.B "\-O \fIbfdname\fP" +.TP +.B "\-\-output\-target=\fIbfdname" +Replace \fIobjfile\fP with a file in the output format \fIbfdname\fP. + +.TP +.B "\-R \fIsectionname\fP" +.TP +.B "\-\-remove\-section=\fIsectionname" +Remove the named section from the file. This option may be given more +than once. Note that using this option inappropriately may make the +object file unusable. + +.TP +.B \-s +.TP +.B \-\-strip\-all +Remove all symbols. + +.TP +.B \-S +.TP +.B \-g +.TP +.B \-\-strip\-debug +Remove debugging symbols only. + +.TP +.B \-\-strip\-unneeded +Strip all symbols that are not needed for relocation processing. + +.TP +.B \-N \fIsymbolname\fR +.TP +.B \-\-strip\-symbol=\fIsymbolname +Remove symbol \fIsymbolname\fP from the source file. This option +may be given more than once, and may be combined with other strip +options. + +.TP +.B \-o \fIfile\fR +Put the stripped output in \fIfile\fR, rather than replacing the +existing file. When this argument is used, only one \fIobjfile\fR +argument may be specified. + +.TP +.B \-p +.TP +.B \-\-preserve-dates +Preserve the access and modification dates of the file. + +.TP +.B \-x +.TP +.B \-\-discard\-all +Remove non-global symbols. + +.TP +.B \-X +.TP +.B \-\-discard\-locals +Remove compiler-generated local symbols. +(These usually start with ``L'' or ``.''.) + +.TP +.B \-K \fIsymbolname\fR, \fB\-\-keep\-symbol=\fIsymbolname +Copy only symbol \fIsymbolname\fP from the source file. This option +may be given more than once. + +.TP +.B \-N \fIsymbolname\fR, \fB\-\-strip\-symbol=\fIsymbolname +Do not copy symbol \fIsymbolname\fP from the source file. This option +may be given more than once, and may be combined with strip options +other than \fB\-K\fR. + +.TP +.B \-v +.TP +.B \-\-verbose +Verbose output: list all object files modified. In the case of +archives, +.B "strip \-v" +lists all members of the archive. + +.TP +.B \-V +.TP +.B \-\-version +Show the version number for \fBstrip\fP and exit. + +.SH "SEE ALSO" +.RB "`\|" binutils "\|'" +entry in +.BR info ; +.IR "The GNU Binary Utilities" , +Roland H. Pesch (October 1991). + +.SH COPYING +Copyright (c) 1991 Free Software Foundation, Inc. +.PP +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. +.PP +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the +entire resulting derived work is distributed under the terms of a +permission notice identical to this one. +.PP +Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be included in +translations approved by the Free Software Foundation instead of in +the original English. diff --git a/binutils/sysdump.c b/binutils/sysdump.c new file mode 100644 index 0000000..c821e8c --- /dev/null +++ b/binutils/sysdump.c @@ -0,0 +1,790 @@ +/* Sysroff object format dumper. + Copyright (C) 1994, 95, 98, 1999 Free Software Foundation, Inc. + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + + +/* Written by Steve Chamberlain <sac@cygnus.com>. + + This program reads a SYSROFF object file and prints it in an + almost human readable form to stdout. */ + +#include "bfd.h" +#include "bucomm.h" + +#include <stdio.h> +#include <ctype.h> +#include <libiberty.h> +#include <getopt.h> +#include "sysroff.h" + +#define PROGRAM_VERSION "1.0" + +static int dump = 1; +static int segmented_p; +static int code; +static int addrsize = 4; +static FILE *file; + +char * +getCHARS (ptr, idx, size, max) + unsigned char *ptr; + int *idx; + int size; + int max; +{ + int oc = *idx / 8; + char *r; + int b = size; + if (b >= max) + { + return "*undefined*"; + } + + if (b == 0) + { + /* Got to work out the length of the string from self */ + b = ptr[oc++]; + (*idx) += 8; + } + + *idx += b * 8; + r = xcalloc (b + 1, 1); + memcpy (r, ptr + oc, b); + r[b] = 0; + return r; +} + +static void +dh (ptr, size) + unsigned char *ptr; + int size; +{ + int i; + int j; + int span = 16; + + printf ("\n************************************************************\n"); + + for (i = 0; i < size; i += span) + { + for (j = 0; j < span; j++) + { + if (j + i < size) + printf ("%02x ", ptr[i + j]); + else + printf (" "); + } + + for (j = 0; j < span && j + i < size; j++) + { + int c = ptr[i + j]; + if (c < 32 || c > 127) + c = '.'; + printf ("%c", c); + } + printf ("\n"); + } +} + +int +fillup (ptr) + char *ptr; +{ + int size; + int sum; + int i; + size = getc (file) - 2; + fread (ptr, 1, size, file); + sum = code + size + 2; + for (i = 0; i < size; i++) + { + sum += ptr[i]; + } + + if ((sum & 0xff) != 0xff) + { + printf ("SUM IS %x\n", sum); + } + if (dump) + dh (ptr, size); + + return size - 1; +} + +barray +getBARRAY (ptr, idx, dsize, max) + unsigned char *ptr; + int *idx; + int dsize; + int max; +{ + barray res; + int i; + int byte = *idx / 8; + int size = ptr[byte++]; + res.len = size; + res.data = (unsigned char *) xmalloc (size); + for (i = 0; i < size; i++) + { + res.data[i] = ptr[byte++]; + } + return res; +} + +int +getINT (ptr, idx, size, max) + unsigned char *ptr; + int *idx; + int size; + int max; +{ + int n = 0; + int byte = *idx / 8; + + if (byte >= max) + { + return 0; + } + if (size == -2) + size = addrsize; + if (size == -1) + size = 0; + switch (size) + { + case 0: + return 0; + case 1: + n = (ptr[byte]); + break; + case 2: + n = (ptr[byte + 0] << 8) + ptr[byte + 1]; + break; + case 4: + n = (ptr[byte + 0] << 24) + (ptr[byte + 1] << 16) + (ptr[byte + 2] << 8) + (ptr[byte + 3]); + break; + default: + abort (); + } + *idx += size * 8; + return n; +} + +int +getBITS (ptr, idx, size, max) + char *ptr; + int *idx; + int size, max; +{ + int byte = *idx / 8; + int bit = *idx % 8; + + if (byte >= max) + return 0; + + *idx += size; + + return (ptr[byte] >> (8 - bit - size)) & ((1 << size) - 1); +} + +static void +itheader (name, code) + char *name; + int code; +{ + printf ("\n%s 0x%02x\n", name, code); +} + +static int indent; +static void +p () +{ + int i; + for (i = 0; i < indent; i++) + { + printf ("| "); + } + printf ("> "); +} + +static void +tabout () +{ + p (); +} + +static void +pbarray (y) + barray *y; +{ + int x; + printf ("%d (", y->len); + for (x = 0; x < y->len; x++) + { + printf ("(%02x %c)", y->data[x], isprint (y->data[x]) ? y->data[x] : '.'); + } + printf (")\n"); +} + +#define SYSROFF_PRINT +#define SYSROFF_SWAP_IN + +#include "sysroff.c" + +/* + * FIXME: sysinfo, which generates sysroff.[ch] from sysroff.info, can't + * hack the special case of the tr block, which has no contents. So we + * implement our own functions for reading in and printing out the tr + * block. + */ + +#define IT_tr_CODE 0x7f +void +sysroff_swap_tr_in() +{ + char raw[255]; + + memset(raw, 0, 255); + fillup(raw); +} + +void +sysroff_print_tr_out() +{ + itheader("tr", IT_tr_CODE); +} + +static int +getone (type) + int type; +{ + int c = getc (file); + code = c; + + if ((c & 0x7f) != type) + { + ungetc (c, file); + return 0; + } + + switch (c & 0x7f) + { + case IT_cs_CODE: + { + struct IT_cs dummy; + sysroff_swap_cs_in (&dummy); + sysroff_print_cs_out (&dummy); + } + break; + case IT_dln_CODE: + { + struct IT_dln dummy; + sysroff_swap_dln_in (&dummy); + sysroff_print_dln_out (&dummy); + } + break; + case IT_hd_CODE: + { + struct IT_hd dummy; + sysroff_swap_hd_in (&dummy); + addrsize = dummy.afl; + sysroff_print_hd_out (&dummy); + } + break; + case IT_dar_CODE: + { + struct IT_dar dummy; + sysroff_swap_dar_in (&dummy); + sysroff_print_dar_out (&dummy); + } + break; + case IT_dsy_CODE: + { + struct IT_dsy dummy; + sysroff_swap_dsy_in (&dummy); + sysroff_print_dsy_out (&dummy); + } + break; + case IT_dfp_CODE: + { + struct IT_dfp dummy; + sysroff_swap_dfp_in (&dummy); + sysroff_print_dfp_out (&dummy); + } + break; + case IT_dso_CODE: + { + struct IT_dso dummy; + sysroff_swap_dso_in (&dummy); + sysroff_print_dso_out (&dummy); + } + break; + case IT_dpt_CODE: + { + struct IT_dpt dummy; + sysroff_swap_dpt_in (&dummy); + sysroff_print_dpt_out (&dummy); + } + break; + case IT_den_CODE: + { + struct IT_den dummy; + sysroff_swap_den_in (&dummy); + sysroff_print_den_out (&dummy); + } + break; + case IT_dbt_CODE: + { + struct IT_dbt dummy; + sysroff_swap_dbt_in (&dummy); + sysroff_print_dbt_out (&dummy); + } + break; + case IT_dty_CODE: + { + struct IT_dty dummy; + sysroff_swap_dty_in (&dummy); + sysroff_print_dty_out (&dummy); + } + break; + case IT_un_CODE: + { + struct IT_un dummy; + sysroff_swap_un_in (&dummy); + sysroff_print_un_out (&dummy); + } + break; + case IT_sc_CODE: + { + struct IT_sc dummy; + sysroff_swap_sc_in (&dummy); + sysroff_print_sc_out (&dummy); + } + break; + case IT_er_CODE: + { + struct IT_er dummy; + sysroff_swap_er_in (&dummy); + sysroff_print_er_out (&dummy); + } + break; + case IT_ed_CODE: + { + struct IT_ed dummy; + sysroff_swap_ed_in (&dummy); + sysroff_print_ed_out (&dummy); + } + break; + case IT_sh_CODE: + { + struct IT_sh dummy; + sysroff_swap_sh_in (&dummy); + sysroff_print_sh_out (&dummy); + } + break; + case IT_ob_CODE: + { + struct IT_ob dummy; + sysroff_swap_ob_in (&dummy); + sysroff_print_ob_out (&dummy); + } + break; + case IT_rl_CODE: + { + struct IT_rl dummy; + sysroff_swap_rl_in (&dummy); + sysroff_print_rl_out (&dummy); + } + break; + case IT_du_CODE: + { + struct IT_du dummy; + sysroff_swap_du_in (&dummy); + + sysroff_print_du_out (&dummy); + } + break; + case IT_dus_CODE: + { + struct IT_dus dummy; + sysroff_swap_dus_in (&dummy); + sysroff_print_dus_out (&dummy); + } + break; + case IT_dul_CODE: + { + struct IT_dul dummy; + sysroff_swap_dul_in (&dummy); + sysroff_print_dul_out (&dummy); + } + break; + case IT_dss_CODE: + { + struct IT_dss dummy; + sysroff_swap_dss_in (&dummy); + sysroff_print_dss_out (&dummy); + } + break; + case IT_hs_CODE: + { + struct IT_hs dummy; + sysroff_swap_hs_in (&dummy); + sysroff_print_hs_out (&dummy); + } + break; + case IT_dps_CODE: + { + struct IT_dps dummy; + sysroff_swap_dps_in (&dummy); + sysroff_print_dps_out (&dummy); + } + break; + case IT_tr_CODE: + { + sysroff_swap_tr_in (); + sysroff_print_tr_out (); + } + break; + case IT_dds_CODE: + { + struct IT_dds dummy; + sysroff_swap_dds_in (&dummy); + sysroff_print_dds_out (&dummy); + } + break; + default: + printf ("GOT A %x\n", c); + return 0; + break; + } + return 1; +} + +static int +opt (x) + int x; +{ + return getone (x); +} + +#if 0 + +/* This is no longer used. */ + +static void +unit_info_list () +{ + while (opt (IT_un_CODE)) + { + getone (IT_us_CODE); + + while (getone (IT_sc_CODE)) + getone (IT_ss_CODE); + + while (getone (IT_er_CODE)) + ; + + while (getone (IT_ed_CODE)) + ; + } +} + +#endif + +#if 0 + +/* This is no longer used. */ + +static void +object_body_list () +{ + while (getone (IT_sh_CODE)) + { + while (getone (IT_ob_CODE)) + ; + while (getone (IT_rl_CODE)) + ; + } +} + +#endif + +static void +must (x) + int x; +{ + if (!getone (x)) + { + printf ("WANTED %x!!\n", x); + } +} + +static void +tab (i, s) + int i; + char *s; +{ + indent += i; + if (s) + { + p (); + printf (s); + printf ("\n"); + } +} + +static void derived_type (); + +static void +dump_symbol_info () +{ + tab (1, "SYMBOL INFO"); + while (opt (IT_dsy_CODE)) + { + if (opt (IT_dty_CODE)) + { + must (IT_dbt_CODE); + derived_type (); + must (IT_dty_CODE); + } + } + tab (-1, ""); +} + +static void +derived_type () +{ + tab (1, "DERIVED TYPE"); + while (1) + { + if (opt (IT_dpp_CODE)) + { + dump_symbol_info (); + must (IT_dpp_CODE); + } + else if (opt (IT_dfp_CODE)) + { + dump_symbol_info (); + must (IT_dfp_CODE); + } + else if (opt (IT_den_CODE)) + { + dump_symbol_info (); + must (IT_den_CODE); + } + else if (opt (IT_den_CODE)) + { + dump_symbol_info (); + must (IT_den_CODE); + } + else if (opt (IT_dds_CODE)) + { + dump_symbol_info (); + must (IT_dds_CODE); + } + else if (opt (IT_dar_CODE)) + { + } + else if (opt (IT_dpt_CODE)) + { + } + else if (opt (IT_dul_CODE)) + { + } + else if (opt (IT_dse_CODE)) + { + } + else if (opt (IT_dot_CODE)) + { + } + else + break; + } + + tab (-1, ""); +} + +#if 0 + +/* This is no longer used. */ + +static void +program_structure () +{ + tab (1, "PROGRAM STRUCTURE"); + while (opt (IT_dps_CODE)) + { + must (IT_dso_CODE); + opt (IT_dss_CODE); + dump_symbol_info (); + must (IT_dps_CODE); + } + tab (-1, ""); +} + +#endif + +#if 0 + +/* This is no longer used. */ + +static void +debug_list () +{ + tab (1, "DEBUG LIST"); + + must (IT_du_CODE); + opt (IT_dus_CODE); + program_structure (); + must (IT_dln_CODE); + + tab (-1, ""); +} + +#endif + +static void +module () +{ + int c = 0; + int l = 0; + + tab (1, "MODULE***\n"); + + do + { + c = getc (file); + ungetc (c, file); + + c &= 0x7f; + } + while (getone (c) && c != IT_tr_CODE); + +#if 0 + must (IT_cs_CODE); + must (IT_hd_CODE); + opt (IT_hs_CODE); + + unit_info_list (); + object_body_list (); + debug_list (); + + must (IT_tr_CODE); +#endif + tab (-1, ""); + + c = getc (file); + while (c != EOF) + { + printf ("%02x ", c); + l++; + if (l == 32) + { + printf ("\n"); + l = 0; + } + c = getc (file); + } +} + +char *program_name; + +static void +show_usage (file, status) + FILE *file; + int status; +{ + fprintf (file, _("Usage: %s [-hV] in-file\n"), program_name); + exit (status); +} + +static void +show_help () +{ + printf (_("%s: Print a human readable interpretation of a SYSROFF object file\n"), + program_name); + show_usage (stdout, 0); +} + +int +main (ac, av) + int ac; + char **av; +{ + char *input_file = NULL; + int opt; + static struct option long_options[] = + { + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'V'}, + {NULL, no_argument, 0, 0} + }; + +#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) + setlocale (LC_MESSAGES, ""); +#endif + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + + program_name = av[0]; + xmalloc_set_program_name (program_name); + + while ((opt = getopt_long (ac, av, "hV", long_options, (int *) NULL)) != EOF) + { + switch (opt) + { + case 'h': + show_help (); + /*NOTREACHED*/ + case 'V': + printf (_("GNU %s version %s\n"), program_name, PROGRAM_VERSION); + exit (0); + /*NOTREACHED*/ + case 0: + break; + default: + show_usage (stderr, 1); + /*NOTREACHED*/ + } + } + + /* The input and output files may be named on the command line. */ + + if (optind < ac) + { + input_file = av[optind]; + } + + if (!input_file) + { + fprintf (stderr, _("%s: no input file specified\n"), + program_name); + exit (1); + } + + file = fopen (input_file, FOPEN_RB); + if (!file) + { + fprintf (stderr, _("%s: cannot open input file %s\n"), + program_name, input_file); + exit (1); + } + + module (); + return 0; +} diff --git a/binutils/sysinfo.y b/binutils/sysinfo.y new file mode 100644 index 0000000..0aa8737 --- /dev/null +++ b/binutils/sysinfo.y @@ -0,0 +1,415 @@ +%{ +#include <stdio.h> +#include <stdlib.h> + +extern char *word; +extern char writecode; +extern int number; +extern int unit; +char nice_name[1000]; +char *it; +int sofar; +int width; +int code; +char * repeat; +char *oldrepeat; +char *name; +int rdepth; +char *loop [] = {"","n","m","/*BAD*/"}; +char *names[] = {" ","[n]","[n][m]"}; +char *pnames[]= {"","*","**"}; +%} + + +%union { + int i; + char *s; +} +%token COND +%token REPEAT +%token '(' ')' +%token <s> TYPE +%token <s> NAME +%token <i> NUMBER UNIT +%type <i> attr_size +%type <s> attr_desc attr_id attr_type +%% + +top: { + switch (writecode) + { + case 'i': + printf("#ifdef SYSROFF_SWAP_IN\n"); + break; + case 'p': + printf("#ifdef SYSROFF_p\n"); + break; + case 'd': + break; + case 'g': + printf("#ifdef SYSROFF_SWAP_OUT\n"); + break; + case 'c': + printf("#ifdef SYSROFF_PRINT\n"); + printf("#include <stdio.h>\n"); + printf("#include <stdlib.h>\n"); + break; + } + } +it_list { + switch (writecode) { + case 'i': + case 'p': + case 'g': + case 'c': + printf("#endif\n"); + break; + case 'd': + break; + } +} + + ; + + +it_list: it it_list + | + ; + +it: + '(' NAME NUMBER + { + it = $2; code = $3; + switch (writecode) + { + case 'd': + printf("\n\n\n#define IT_%s_CODE 0x%x\n", it,code); + printf("struct IT_%s { \n", it); + break; + case 'i': + printf("void sysroff_swap_%s_in(ptr)\n",$2); + printf("struct IT_%s *ptr;\n", it); + printf("{\n"); + printf("char raw[255];\n"); + printf("\tint idx = 0 ;\n"); + printf("\tint size;\n"); + printf("memset(raw,0,255);\n"); + printf("memset(ptr,0,sizeof(*ptr));\n"); + printf("size = fillup(raw);\n"); + break; + case 'g': + printf("void sysroff_swap_%s_out(file,ptr)\n",$2); + printf("FILE * file;\n"); + printf("struct IT_%s *ptr;\n", it); + printf("{\n"); + printf("\tchar raw[255];\n"); + printf("\tint idx = 16 ;\n"); + printf("\tmemset (raw, 0, 255);\n"); + printf("\tcode = IT_%s_CODE;\n", it); + break; + case 'o': + printf("void sysroff_swap_%s_out(abfd,ptr)\n",$2); + printf("bfd * abfd;\n"); + printf("struct IT_%s *ptr;\n",it); + printf("{\n"); + printf("int idx = 0 ;\n"); + break; + case 'c': + printf("void sysroff_print_%s_out(ptr)\n",$2); + printf("struct IT_%s *ptr;\n", it); + printf("{\n"); + printf("itheader(\"%s\", IT_%s_CODE);\n",$2,$2); + break; + + case 't': + break; + } + + } + it_field_list +')' +{ + switch (writecode) { + case 'd': + printf("};\n"); + break; + case 'g': + printf("\tchecksum(file,raw, idx, IT_%s_CODE);\n", it); + + case 'i': + + case 'o': + case 'c': + printf("}\n"); + } +} +; + + + +it_field_list: + it_field it_field_list + | cond_it_field it_field_list + | repeat_it_field it_field_list + | + ; + +repeat_it_field: '(' REPEAT NAME + { + rdepth++; + switch (writecode) + { + case 'c': + if (rdepth==1) + printf("\tprintf(\"repeat %%d\\n\", %s);\n",$3); + if (rdepth==2) + printf("\tprintf(\"repeat %%d\\n\", %s[n]);\n",$3); + case 'i': + case 'g': + case 'o': + + if (rdepth==1) + { + printf("\t{ int n; for (n = 0; n < %s; n++) {\n", $3); + } + if (rdepth == 2) { + printf("\t{ int m; for (m = 0; m < %s[n]; m++) {\n", $3); + } + + break; + } + + oldrepeat = repeat; + repeat = $3; + } + + it_field_list ')' + + { + repeat = oldrepeat; + oldrepeat =0; + rdepth--; + switch (writecode) + { + case 'i': + case 'g': + case 'o': + case 'c': + printf("\t}}\n"); + } + } + ; + + +cond_it_field: '(' COND NAME + { + switch (writecode) + { + case 'i': + case 'g': + case 'o': + case 'c': + printf("\tif (%s) {\n", $3); + break; + } + } + + it_field_list ')' + { + switch (writecode) + { + case 'i': + case 'g': + case 'o': + case 'c': + printf("\t}\n"); + } + } + ; + +it_field: + '(' attr_desc '(' attr_type attr_size ')' attr_id + {name = $7; } + enums ')' + { + char *desc = $2; + char *type = $4; + int size = $5; + char *id = $7; +char *p = names[rdepth]; +char *ptr = pnames[rdepth]; + switch (writecode) + { + case 'g': + if (size % 8) + { + + printf("\twriteBITS(ptr->%s%s,raw,&idx,%d);\n", + id, + names[rdepth], size); + + } + else { + printf("\twrite%s(ptr->%s%s,raw,&idx,%d,file);\n", + type, + id, + names[rdepth],size/8); + } + break; + case 'i': + { + + if (rdepth >= 1) + + { + printf("if (!ptr->%s) ptr->%s = (%s*)xcalloc(%s, sizeof(ptr->%s[0]));\n", + id, + id, + type, + repeat, + id); + } + + if (rdepth == 2) + { + printf("if (!ptr->%s[n]) ptr->%s[n] = (%s**)xcalloc(%s[n], sizeof(ptr->%s[n][0]));\n", + id, + id, + type, + repeat, + id); + } + + } + + if (size % 8) + { + printf("\tptr->%s%s = getBITS(raw,&idx, %d,size);\n", + id, + names[rdepth], + size); + } + else { + printf("\tptr->%s%s = get%s(raw,&idx, %d,size);\n", + id, + names[rdepth], + type, + size/8); + } + break; + case 'o': + printf("\tput%s(raw,%d,%d,&idx,ptr->%s%s);\n", type,size/8,size%8,id,names[rdepth]); + break; + case 'd': + if (repeat) + printf("\t/* repeat %s */\n", repeat); + + if (type[0] == 'I') { + printf("\tint %s%s; \t/* %s */\n",ptr,id, desc); + } + else if (type[0] =='C') { + printf("\tchar %s*%s;\t /* %s */\n",ptr,id, desc); + } + else { + printf("\tbarray %s%s;\t /* %s */\n",ptr,id, desc); + } + break; + case 'c': + printf("tabout();\n"); + printf("\tprintf(\"/*%-30s*/ ptr->%s = \");\n", desc, id); + + if (type[0] == 'I') + printf("\tprintf(\"%%d\\n\",ptr->%s%s);\n", id,p); + else if (type[0] == 'C') + printf("\tprintf(\"%%s\\n\",ptr->%s%s);\n", id,p); + + else if (type[0] == 'B') + { + printf("\tpbarray(&ptr->%s%s);\n", id,p); + } + else abort(); + break; + } + } + + ; + + +attr_type: + TYPE { $$ = $1; } + | { $$ = "INT";} + ; + +attr_desc: + '(' NAME ')' + { $$ = $2; } + ; + +attr_size: + NUMBER UNIT + { $$ = $1 * $2; } + ; + + +attr_id: + '(' NAME ')' { $$ = $2; } + | { $$ = "dummy";} + ; + +enums: + | '(' enum_list ')' ; + +enum_list: + | + enum_list '(' NAME NAME ')' { + switch (writecode) + { + case 'd': + printf("#define %s %s\n", $3,$4); + break; + case 'c': + printf("if (ptr->%s%s == %s) { tabout(); printf(\"%s\\n\");}\n", name, names[rdepth],$4,$3); + } + } + + ; + + + +%% +/* four modes + + -d write structure defintions for sysroff in host format + -i write functions to swap into sysroff format in + -o write functions to swap into sysroff format out + -c write code to print info in human form */ + +int yydebug; +char writecode; + +int +main(ac,av) +int ac; +char **av; +{ + yydebug=0; + if (ac > 1) + writecode = av[1][1]; +if (writecode == 'd') + { + printf("typedef struct { unsigned char *data; int len; } barray; \n"); + printf("typedef int INT;\n"); + printf("typedef char * CHARS;\n"); + + } + yyparse(); +return 0; +} + +int +yyerror(s) + char *s; +{ + fprintf(stderr, "%s\n" , s); + return 0; +} diff --git a/binutils/syslex.l b/binutils/syslex.l new file mode 100644 index 0000000..a394842 --- /dev/null +++ b/binutils/syslex.l @@ -0,0 +1,51 @@ +%{ +#include "sysinfo.h" +char *word; +int number; +int unit; + +#ifndef yywrap +static int yywrap () { return 1; } +#endif +%} +%% +"(" { return '(';} +")" { return ')';} +"[" { return '[';} +"]" { return ']';} +" " { ; } +";".* { ; } +"\t" { ; } +"\n" { ; } +"\""[^\"]*"\"" { +yylval.s = malloc(strlen (yytext)); +strcpy(yylval.s, yytext+1); +yylval.s[strlen(yylval.s)-1] = 0; + return NAME; + } + +0x[0-9a-f]+ { + yylval.i = strtol(yytext,0,16); + return NUMBER; + } + +[0-9]+ { + yylval.i = atoi(yytext); + return NUMBER; + } + + +"bits" { yylval.i =1 ;return UNIT;} +"bit" { yylval.i = 1; return UNIT;} +"bytes" { yylval.i= 8; return UNIT;} +"byte" { yylval.i = 8; return UNIT;} + +"int" { yylval.s = "INT"; return TYPE;} +"barray" { yylval.s = "BARRAY"; return TYPE;} +"chars" { yylval.s = "CHARS"; return TYPE;} +"variable" { yylval.i = 0; return NUMBER;} +"counted" { yylval.i = -4; return NUMBER;} +"addrsize" { yylval.i = -2; return NUMBER; } +"segsize" { yylval.i = -1; return NUMBER; } +"cond" { return COND;} +"repeat" { return REPEAT;} diff --git a/binutils/sysroff.info b/binutils/sysroff.info new file mode 100644 index 0000000..3af001a --- /dev/null +++ b/binutils/sysroff.info @@ -0,0 +1,504 @@ +("cs" 0x0 + (("size") (1 byte) ("size")) + + (("hd") (1 byte) ("hd")) + (("hs") (1 byte) ("hs")) + (("un") (1 byte) ("un")) + (("us") (1 byte) ("us")) + + (("sc") (1 byte) ("sc")) + (("ss") (1 byte) ("ss")) + (("er") (1 byte) ("er")) + (("ed") (1 byte) ("ed")) + + (("sh") (1 byte) ("sh")) + (("ob") (1 byte) ("ob")) + (("rl") (1 byte) ("rl")) + (("du") (1 byte) ("du")) + + (("dps") (1 byte) ("dps")) + (("dsy") (1 byte) ("dsy")) + (("dty") (1 byte) ("dty")) + (("dln") (1 byte) ("dln")) + + (("dso") (1 byte) ("dso")) + (("dus") (1 byte) ("dus")) + (("dss") (1 byte) ("dss")) + (("dbt") (1 byte) ("dbt")) + + (("dpp") (1 byte) ("dpp")) + (("dfp") (1 byte) ("dfp")) + (("den") (1 byte) ("den")) + (("dds") (1 byte) ("dds")) + + (("dar") (1 byte) ("dar")) + (("dpt") (1 byte) ("dpt")) + (("dul") (1 byte) ("dul")) + (("dse") (1 byte) ("dse")) + + (("dot") (1 byte) ("dot"))) + + +("hd" 0x04 + (("module type") (4 bits) ("mt") + (("MTYPE_ABS_LM" "0") + ("MTYPE_REL_LM" "1") + ("MTYPE_OMS_OR_LMS" "2") + ("MTYPE_UNSPEC" "0xf"))) + (("spare")(4 bits) ("spare1")) + (("creation date")( chars 12 bytes)( "cd")) + (("number of units") (2 bytes) ("nu")) + (("code") (1 byte) ("code")) + (("version") (chars 4 bytes) ("ver")) + (("address update") (1 byte) ("au")) + (("segment identifier") (1 bit) ("si")) + (("address field length") (4 bits) ("afl")) + (("spare")(3 bits) ("spare2")) + (("space size within segment") (1 byte) ("spcsz")) + (("segment size") (1 byte) ("segsz")) + (("segment shift") (1 byte) ("segsh")) + (("entry point") (1 byte) ("ep")) + (cond "ptr->ep" + (cond "ptr->mt != MTYPE_ABS_LM" + (("unit appearance number") (2 bytes) ("uan")) + (("section appearance number") (2 bytes) ("sa"))) + (cond "segmented_p" + (("segment address") (segsize bytes) ("sad"))) + (("address") (addrsize bytes) ("address"))) + (("os name") (chars variable bytes) ("os")) + (("sys name") (chars variable bytes) ("sys")) + (("module name") (chars variable bytes) ("mn")) + (("cpu") (chars variable bytes) ("cpu"))) + + +("hs" 0x05 + (("neg number") (2 bytes) ("neg"))) + + +("un" 0x06 + (("format") (2 bits) ("format") + (("FORMAT_LM" "0") + ("FORMAT_OM" "1") + ("FORMAT_OMS_OR_LMS" "2"))) + (("spare") (6 bits) ("spare1")) + (("number of sections") (2 bytes) ("nsections")) + (("number of external refs") (2 bytes) ("nextrefs")) + (("number of external defs") (2 bytes) ("nextdefs")) + (("unit name") (chars variable byte) ("name")) + (("tool name") (chars variable byte) ("tool")) + (("creation date") (chars 12 bytes) ("tcd")) + (("linker name") (chars variable byte) ("linker")) + (("creation date") (chars 12 bytes) ("lcd"))) + + +("us" 0x07 + (("negotiation number") (2 bytes) ("neg"))) + + +("sc" 0x08 + (("format") (2 bits) ("format")) + (("spare") (6 bits) ("spare")) + (("segment address") (segsize bytes) ("segadd")) + (("address") (addrsize bytes) ("addr")) + (("length") (addrsize bytes) ("length")) + (("alignment") (addrsize bytes) ("align")) + (("contents") (4 bits) ("contents") + (("CONTENTS_CODE" "0") + ("CONTENTS_DATA" "1") + ("CONTENTS_STACK" "2") + ("CONTENTS_DUMMY" "3") + ("CONTENTS_SPECIAL" "4") + ("CONTENTS_NONSPEC" "0xf"))) + (("concat") (4 bits) ("concat") + (("CONCAT_SIMPLE" "0") + ("CONCAT_SHAREDC" "1") + ("CONCAT_DUMMY" "2") + ("CONCAT_GROUP" "3") + ("CONCAT_SHARED" "4") + ("CONCAT_PRIVATE" "5") + ("CONCAT_UNSPEC" "0xf"))) + (("read") (2 bits) ("read")) + (("write") (2 bits) ("write")) + (("exec") (2 bits) ("exec")) + (("initialized") (2 bits) ("init")) + (("mode") (2 bits) ("mode")) + (("spare") (6 bits) ("spare1")) + (("name") (chars variable byte) ("name"))) + + +("ss" 0x09 + (("neg number") (2 bytes) ("neg"))) + + +("er" 0x0c + (("symbol type") (2 bits) ("type") + (("ER_ENTRY" "0") + ("ER_DATA" "1") + ("ER_NOTDEF" "2") + ("ER_NOTSPEC" "3"))) + (("spare") (6 bits) ("spare")) + (("symbol name") (chars variable byte) ("name"))) + + +("ed" 0x14 + (("section appearance number") (2 bytes) ("section")) + (("symbol type") (3 bits) ("type") + (("ED_TYPE_ENTRY" "0") + ("ED_TYPE_DATA" "1") + ("ED_TYPE_CONST" "2") + ("ED_TYPE_NOTSPEC" "7"))) + (("spare") (5 bits) ("spare")) + (cond "ptr->type==ED_TYPE_ENTRY || ptr->type==ED_TYPE_DATA" + (("symbol address") (addrsize bytes) ("address"))) + (cond "ptr->type==ED_TYPE_CONST" + (("constant value") (addrsize bytes) ("constant"))) + (("symbol name") (chars variable byte) ("name"))) + + +("sh" 0x1a + (("unit appearance number") (2 bytes) ("unit")) + (("section appearance number") (2 bytes) ("section"))) + + +("ob" 0x1c + (("starting address flag") (1 bit) ("saf")) + (("compression flag") (1 bit) ("cpf")) + (("spare") (6 bits) ("spare")) + (cond "ptr->saf" + ( ("starting address") (addrsize bytes) ("address"))) + (cond "ptr->cpf" + (("comp reps") (addrsize bytes) ("compreps"))) + (("data") (barray counted byte) ("data"))) + + +("rl" 0x20 + (("boundary of relocateable area") (4 bits) ("boundary")) + (("address polarity") (1 bit) ("apol")) + (("segment number") (1 bit) ("segment")) + (("sign of relocation") (1 bit) ("sign")) + (("check range") (1 bit) ("check")) + (("reloc address") (addrsize bytes) ("addr")) + + (("bit loc") (1 byte) ("bitloc")) + (("field length") (1 byte) ("flen")) + (("bcount") (1 byte) ("bcount")) + (("operator") (1 byte) ("op") + (("OP_RELOC_ADDR" "1") + ("OP_SEC_REF" "0") + ("OP_EXT_REF" "2"))) + (cond "ptr->op == OP_EXT_REF" + (("symbol number") (2 bytes) ("symn")) ) + + (cond "ptr->op == OP_SEC_REF" + (("section number") (2 bytes) ("secn")) + (("const opcode") (1 byte) ("copcode_is_3")) + (("addend length") (1 byte) ("alength_is_4")) + (("addend") (4 byte) ("addend")) + (("plus opcode") (1 byte) ("aopcode_is_0x20"))) + + (cond "ptr->op == OP_RELOC_ADDR" + (("dunno") (2 bytes) ("dunno"))) + + (("end") (1 byte) ("end"))) + + +("du" 0x30 + (("format") (2 bits) ("format")) + (("optimized") (1 bit) ("optimized")) + (("stackfrmt") (2 bits) ("stackfrmt")) + (("spare") (3 bits) ("spare")) + (("unit number") (2 bytes) ("unit")) + (("sections") (2 bytes) ("sections")) + (repeat "ptr->sections" + (("section appearance number") (2 bytes) ("san")) + (("address") (addrsize bytes) ("address")) + (("section length") (addrsize bytes) ("length"))) + (("tool name") (chars variable byte) ("tool")) + (("creation date") (chars 12 bytes) ("date"))) + + +("dsy" 0x34 + (("symbol type") (7 bits) ("type") + (("STYPE_VAR" "0") + ("STYPE_LAB" "1") + ("STYPE_PROC" "2") + ("STYPE_FUNC" "3") + ("STYPE_TYPE" "4") + ("STYPE_CONST" "5") + ("STYPE_ENTRY" "6") + ("STYPE_MEMBER" "7") + ("STYPE_ENUM" "8") + ("STYPE_TAG" "9") + ("STYPE_PACKAGE" "10") + ("STYPE_GENERIC" "11") + ("STYPE_TASK" "12") + ("STYPE_EXCEPTION" "13") + ("STYPE_PARAMETER" "14") + ("STYPE_EQUATE" "15") + ("STYPE_UNSPEC" "0x7f"))) + (("assignment info") (1 bit) ("assign")) + (("symbol id") (2 bytes) ("snumber")) + (("symbol name") (chars variable bytes) ("sname")) + (("nesting level") (2 bytes) ("nesting")) + (cond "ptr->assign" + (("assignment type") (1 byte) ("ainfo") + (("AINFO_REG" "1") + ("AINFO_STATIC_EXT_DEF" "2") + ("AINFO_STATIC_EXT_REF" "3") + ("AINFO_STATIC_INT" "4") + ("AINFO_STATIC_COM" "5") + ("AINFO_AUTO" "6") + ("AINFO_CONST" "7") + ("AINFO_UNSPEC" "0xff"))) + (("data length") (addrsize bytes) ("dlength")) + (cond "ptr->ainfo == AINFO_STATIC_EXT_DEF + || ptr->ainfo == AINFO_STATIC_INT + || ptr->ainfo == AINFO_STATIC_COM" + (("section number") (2 bytes) ("section"))) + (cond "ptr->ainfo == AINFO_STATIC_EXT_DEF + || ptr->ainfo == AINFO_STATIC_INT + || ptr->ainfo == AINFO_STATIC_COM + || ptr->ainfo == AINFO_AUTO" + (("address") (addrsize bytes) ("address"))) + (cond "ptr->ainfo == AINFO_REG" + (("register name") (chars variable bytes) ("reg"))) + (cond "ptr->ainfo == AINFO_STATIC_EXT_DEF + || ptr->ainfo == AINFO_STATIC_EXT_REF" + (("external name") (chars variable bytes) ("ename"))) + (cond "ptr->ainfo == AINFO_CONST" + (("constant") (chars variable bytes) ("constant")))) + (cond "ptr->type == STYPE_MEMBER" + (("assignment unit") (1 bit) ("bitunit")) + (("spare") (7 bits) ("spare2")) + (("field length") (addrsize bytes) ("field_len")) + (("field offset") (addrsize bytes) ("field_off")) + (cond "ptr->bitunit" + (("bit offset") (addrsize bytes) ("field_bitoff")))) + (cond "ptr->type== STYPE_ENUM" + (("value length") (1 byte) ("evallen")) + (("value") (4 bytes) ("evalue"))) + (cond "ptr->type == STYPE_CONST" + (("value") (chars variable bytes) ("cvalue"))) + (cond "ptr->type == STYPE_EQUATE" + (("value length") (1 byte) ("qvallen")) + (("value") (4 bytes) ("qvalue")) + (("basic type") (1 byte) ("btype")) + (("size information") (addrsize bytes) ("sizeinfo")) + (("sign") (2 bits) ("sign")) + (("floating point type") (6 bits) ("flt_type"))) + (("source file number") (2 bytes) ("sfn")) + (("source line number") (2 bytes) ("sln")) + (("negotiation number") (2 bytes) ("neg")) + (cond "ptr->type == STYPE_TAG" + (("magic") (1 byte) ("magic")))) + + + +("dul" 0x52 + (("max declaration type flag") (1 bit) ("max_variable")) + (("max spare") (7 bits) ("maxspare")) + (cond "ptr->max_variable == 0" + (("maximum") (addrsize bytes) ("max")) + (("max mode") (chars variable bytes) ("maxmode"))) + + (("min declaration type flag") (1 bit) ("min_variable")) + (("min spare") (7 bits) ("minspare")) + (cond "ptr->min_variable == 0" + (("minimum") (addrsize bytes) ("min")) + (("min mode") (chars variable bytes) ("minmode")))) + + +("dty" 0x36 + (("end flag") (1 bit) ("end")) + (("spare") (7 bits) ("spare")) + (cond "!ptr->end" + (("negotiation") (2 bytes) ("neg")))) + + +("dbt" 0x44 + (("basic type") (1 byte) ("btype") + (("BTYPE_VOID" "0") + ("BTYPE_UNDEF" "1") + ("BTYPE_CHAR" "2") + ("BTYPE_INT" "3") + ("BTYPE_FLOAT" "4") + ("BTYPE_BIT" "5") + ("BTYPE_STRING" "6") + ("BTYPE_DECIMAL" "7") + ("BTYPE_ENUM" "8") + ("BTYPE_STRUCT" "9") + ("BTYPE_TYPE" "10") + ("BTYPE_TAG" "11") + ("BTYPE_UNSPEC" "0xff"))) + (("size info") (addrsize bytes) ("bitsize")) + (("sign") (2 bits) ("sign") + (("SIGN_SIGNED" "0") + ("SIGN_UNSIGNED" "1") + ("SIGN_UNSPEC" "3"))) + (("floating point type") (6 bits) ("fptype") + (("FPTYPE_SINGLE" "0") + ("FPTYPE_DOUBLE" "1") + ("FPTYPE_EXTENDED" "2") + ("FPTYPE_NOTSPEC" "0x3f"))) + (cond "ptr->btype==BTYPE_TAG || ptr->btype == BTYPE_TYPE" + (("symbol id") (2 bytes) ("sid"))) + (("negotiation") (2 bytes) ("neg"))) + +("dar" 0x4e + (("element length" ) (addrsize bytes) ("length")) + (("dims") (1 byte) ("dims")) + (repeat "ptr->dims" + (("variable flag") (1 bit) ("variable") + (("VARIABLE_FIXED" "0") + ("VARIABLE_VARIABLE" "1"))) + + (("subscript type") (1 bit) ("subtype") + (("SUB_INTEGER" "0") + ("SUB_TYPE" "1"))) + + (("spare") (6 bits) ("spare")) + + (cond "ptr->subtype[n] == SUB_TYPE" + (("sub symbol id") (2 bytes) ("sid"))) + + (cond "ptr->subtype[n] == SUB_INTEGER" + (("max declaration type flag") (1 bit) ("max_variable")) + (("max spare") (7 bits) ("maxspare")) + ;; FIXME: next field should be conditional on max_variable, + (("maximum") (addrsize bytes) ("max")) + + (("min declaration type flag") (1 bit) ("min_variable")) + (("min spare") (7 bits) ("minspare")) + ;; FIXME: next field should be conditional on min_variable + (("minimum") (addrsize bytes) ("min")))) + (("negotiation") (2 bytes) ("neg"))) + + +("dso" 0x3a + (("function name") (2 bytes) ("sid")) + (("sp update count") (4 bytes) ("spupdates")) + (repeat "ptr->spupdates" + (("update address") (addrsize bytes) ("address")) + (("offset") (addrsize bytes) ("offset")))) + +("dln" 0x38 + (("number of lines") (2 bytes) ("nln")) + (repeat "ptr->nln" + (("source file number") (2 bytes) ("sfn")) + (("source line number") (2 bytes) ("sln")) + (("section number") (2 bytes) ("section")) + (("from address") (addrsize bytes) ("from_address")) + (("to address") (addrsize bytes) ("to_address")) + (("call count") (2 bytes) ("cc")) + ) + (("neg") (2 bytes) ("neg"))) + +("dpp" 0x46 + (("start/end") (1 bit) ("end")) + (("spare") (7 bits) ("spare")) + (cond "!ptr->end" + (("params") (1 byte) ("params")) + (("neg number") (2 bytes) ("neg")))) + +("den" 0x4a + (("start/end") (1 bit) ("end")) + (("spare") (7 bits) ("spare")) + (cond "!ptr->end" + (("neg number") (2 bytes) ("neg")))) + +("dfp" 0x48 + (("start/end flag") (1 bit) ("end")) + (("spare") (7 bits) ("spare")) + (cond "!ptr->end" + (("number of parameters") (1 byte) ("nparams")) + (("neg number") (2 bytes) ("neg")))) + +("dds" 0x4c + (("start/end") (1 bit) ("end")) + (("spare") (7 bits) ("spare")) + (cond "!ptr->end" + (("neg number") (2 bytes) ("neg")))) + +("dpt" 0x50 + (("neg number") (2 bytes) ("neg")) + (("dunno") (1 byte) ("dunno"))) + +("dse" 0x54 + (("neg number") (2 bytes) ("neg")) + (("dunno") (1 byte) ("dunno"))) + +("dot" 0x56 + (("unknown") (1 byte) ("unknown"))) +; FIXME: unknown field should be repeated symbol number? + + +("dss" 0x42 + (("type") (1 byte) ("type")) + (("external/internal") (1 bit) ("internal")) + (("spare") (7 bits) ("spare")) + (cond "!ptr->internal" + ( ("package name") (chars variable byte) ("package"))) + (cond "ptr->internal" + (("symbol id") (2 bytes) ("id"))) + (("record type") (2 bytes) ("record")) + (("rules") (chars variable byte) ("rules")) + (("number of symbols") (2 bytes) ("nsymbols")) + (("unknown" ) (2 bytes) ("fixme"))) + +("pss" 0x40 + (("negotiation number") (2 bytes) ("efn")) + (("number of source files") (2 bytes) ("ns")) + (repeat "ptr->ns" + (("directory reference bit") (1 bit) ("drb")) + (("spare") (7 bits) ("spare")) + (("completed file name") (chars variable byte) ("fname")) + (cond "ptr->drb[n]" + (("directory apperance number") (2 bytes) ("dan")))) + + (("number of directories") (2 bytes) ("ndir")) + (repeat "ptr->ndir" + (("directory name") (chars variable bytes) ("dname")))) + + +; FIXME: the tr block has no contents. sysinfo, etc. aren't prepared +; to deal with that. +; ("tr" 0x7f) + + +("dus" 0x40 + (("negotiation number") (2 bytes) ("efn")) + (("number of source files") (2 bytes) ("ns")) + (repeat "ptr->ns" + (("directory reference bit") (1 bit) ("drb")) + (("spare") (7 bits) ("spare")) + (("completed file name") (chars variable byte) ("fname")) + (cond "ptr->drb[n]" + (("directory apperance number") (2 bytes) ("dan")))) + (("number of directories") (2 bytes) ("ndir")) + (repeat "ptr->ndir" + (("directory name") (chars variable bytes) ("dname")))) + + +("dps" 0x32 + (("start/end flag") (1 bit) ("end")) + (("block type") (7 bits) ("type") + (("BLOCK_TYPE_COMPUNIT" "0") + ("BLOCK_TYPE_PROCEDURE" "2") + ("BLOCK_TYPE_FUNCTION" "3") + ("BLOCK_TYPE_BLOCK" "4") + ("BLOCK_TYPE_BASIC" "9"))) + (cond "!ptr->end" + (("optimization") (1 byte) ("opt")) + (("section number") (2 bytes) ("san")) + (("address") (addrsize bytes) ("address")) + (("block size") (addrsize bytes) ("block_size")) + (("nesting") (1 byte) ("nesting")) + (cond "ptr->type == BLOCK_TYPE_PROCEDURE + || ptr->type == BLOCK_TYPE_FUNCTION" + (("return address") (1 bit) ("retaddr")) + (("interrupt function flag") (1 bit) ("intrflag")) + (("stack update flag") (1 bit) ("stackflag")) + (("intra page JMP") (1 bit) ("intrpagejmp")) + (("spare") (4 bits) ("spare"))) + (("neg number") (2 bytes) ("neg")))) + diff --git a/binutils/testsuite/ChangeLog b/binutils/testsuite/ChangeLog new file mode 100644 index 0000000..15a0577 --- /dev/null +++ b/binutils/testsuite/ChangeLog @@ -0,0 +1,585 @@ +1999-03-12 Nick Clifton <nickc@cygnus.com> + + * binutils-all/readelf.wi: Remove FR30 specific componnts. + * binutils-all/readelf.s: Remove RELA specific components. + +1999-02-16 Nick Clifton <nickc@cygnus.com> + + * binutils-all/readelf.s: Do not assume section alignment is 4. + * binutils-all/readelf.r: Do not assume rela's are being used. + * binutils-all/readelf.exp: disable tests for non ELF based + targets. + +1999-02-02 Nick Clifton <nickc@cygnus.com> + + * binutils-all/readelf.wi: Amend to match new readelf output. + * binutils-all/readelf.r: Do not assume that RELAs will be used. + +1999-01-29 Nick Clifton <nickc@cygnus.com> + + * config/default.exp: Add definitions of READELF and READELFFLAGS. + + * binutils-all/readelf.exp: New file: Readelf tests + * binutils-all/readelf.h: New file: Expected results for 'readelf -h' + * binutils-all/readelf.s: New file: Expected results for 'readelf -S' + * binutils-all/readelf.ss: New file: Expected results for 'readelf -s' + * binutils-all/readelf.r: New file: Expected results for 'readelf -r' + * binutils-all/readelf.wi: New file: Expected results for 'readelf -wi' + +Wed Dec 9 19:11:39 1998 Jeffrey A Law (law@cygnus.com) + + * binutils-all/objcopy.exp (copy_executable): Expect comparison + failure for mips*-*-elf. + +Fri Oct 16 22:57:12 1998 Felix Lee <flee@cygnus.com> + + * binutils-all/objcopy.exp: fix "no symbols" message. + +Tue Jul 28 15:14:04 1998 Jeffrey A Law (law@cygnus.com) + + * binutils-all/objcopy.exp: Keep "main" and "_main" for strip with + saving symbol tests. Look for either "main" or "_main" in the output + file. Fix test for "no symbols" in the output file. + +1998-07-22 Vladimir N. Makarov <vmakarov@cygnus.com> + + * binutils-all/objcopy.exp: Polish output about fail for objcopy + (simple copy), strip with/without saving a symbol for object file + and executable. + +Wed Jul 1 16:27:40 1998 Nick Clifton <nickc@cygnus.com> + + * binutils-all/objcopy.exp: ARM simple objcopy now passes. + +Wed Jun 24 09:20:21 1998 Nick Clifton <nickc@cygnus.com> + + * binutils-all/objdump.exp: Look for '.data' rather than 'data' + when parsing output of objdump -h. + * binutils-all/size.exp: Look for '.data' rather than 'data' when + parsing output of size -A. + +1998-07-20 Vladimir N. Makarov <vmakarov@cygnus.com> + + * objcopy.exp: Two new tests - strip object file with saving a + symbol and strip executable file with saving a symbol. + +Fri May 29 14:50:24 1998 Ian Lance Taylor <ian@cygnus.com> + + * binutils-all/objcopy.exp: Don't xfail the simple objcopy test + when cross compiling. + +Thu Nov 6 14:32:37 1997 Bob Manson <manson@charmed.cygnus.com> + + * lib/utils-lib.exp: Temporary definition of target_assemble and + default_target_assemble so that testing can work with older + dejagnu versions. + +Wed Sep 24 12:09:15 1997 Bob Manson <manson@charmed.cygnus.com> + + * binutils-all/objcopy.exp(strip_executable): Make a new copy of + the executable being tested. + +Mon Sep 15 21:25:20 1997 Bob Manson <manson@charmed.cygnus.com> + + * binutils-all/objcopy.exp: Compile the executables to be tested + on the target with a status wrapper (as necessary). + + * binutils-all/ar.exp: If testing on a remote host, don't bother + looking on the local host for the program being tested. Use the + correct filenames on the remote host. + + * binutils-all/nm.exp: Ditto. + + * binutils-all/size.exp: Ditto. + + * binutils-all/objdump.exp: Ditto. + (cpus_expected): Add the target CPU to the regexp of CPUs to be + expected, if it's not already there. + +Thu Aug 28 09:57:27 1997 Doug Evans <dje@canuck.cygnus.com> + + * binutils-all/objdump.exp (cpus_expected): Add arc. + +Tue Aug 5 00:03:20 1997 Ian Lance Taylor <ian@cygnus.com> + + * config/default.exp: Look for nm-new and strip-new. + +Tue Jun 3 17:12:54 1997 Bob Manson <manson@charmed.cygnus.com> + + * config/default.exp: Remove expect_before statement. + + * binutils-all/objcopy.exp: Don't use global exec_output variable; + the output is returned from remote_load instead. + +Mon May 12 22:14:20 1997 Bob Manson <manson@charmed.cygnus.com> + + * binutils-all/objcopy.exp(strip_test): Tests that + fail to compile are untested, not unresolved. + (copy_setup): Ditto. + + * lib/utils-lib.exp(default_binutils_assemble): Call + target_assemble instead of target_compile. + +Wed Apr 30 20:37:51 1997 Bob Manson <manson@charmed.cygnus.com> + + Changes to support multilib and remote hosted testing, along with + general cleanups and simplifications. + + * lib/utils-lib.exp(binutil_version): Use remote_exec. + (default_binutils_run): Ditto. + (default_binutils_assemble): Remove first argument; call + target_compile to actually do the assembly. + (default_binutils_compile,default_binutils_remove,prune_warnings): + Delete. + + * config/default.exp: Remove AS and ASFLAGS. + (binutils_compile,binutils_remove): Delete. + (binutils_assemble): Remove first argument. + + * binutils-all/ar.exp: See if we're running the tests on + a remote host, and download/upload files as appropriate. + Replace calls to binutils_remove with remote_file. Replace + calls to binutils_compile with target_compile. Remove initial + argument to binutils_assemble. Use remote_load to execute + programs on the target. + * binutils-all/nm.exp: Ditto. + * binutils-all/objcopy.exp: Ditto. + * binutils-all/objdump.exp: Ditto. + * binutils-all/size.exp: Ditto. + +Mon Apr 14 12:36:41 1997 Ian Lance Taylor <ian@cygnus.com> + + * binutils-all/ar.exp (long_filenames): Check for a file system + with a 14 character file name length limit. + +Tue Apr 1 09:52:15 1997 Jeffrey A Law (law@cygnus.com) + + * binutils-all/objdump.exp: Handle d10v. + +Fri Feb 7 16:45:34 1997 Bob Manson <manson@charmed.cygnus.com> + + * binutils-all/ar.exp: Use prune_warnings instead of + prune_system_crud. + * binutils-all/objcopy.exp: Ditto. + +Wed Jan 29 00:16:43 1997 Bob Manson <manson@charmed.cygnus.com> + + * binutils-all/nm.exp: Use / between $srcdir and $subdir. + * binutils-all/objcopy.exp: Ditto. + * binutils-all/objdump.exp: Ditto. + * binutils-all/size.exp: Ditto. + * binutils-all/hppa/objdump.exp: Ditto. + + +Wed Oct 16 22:57:59 1996 Jeffrey A Law (law@cygnus.com) + + * binutils-all/objdump.exp: Add mn10200 and mn10300 to expected + cpus list. + +Tue Oct 1 15:06:55 1996 Ian Lance Taylor <ian@cygnus.com> + + * lib/utils-lib.exp (binutil_version): Fix for current version + printing. + +Sun Aug 4 22:25:40 1996 Ian Lance Taylor <ian@cygnus.com> + + * binutils-all/objcopy.exp: Fix end of line matching in srec tests + to work with TCL 7.5. + +Sat Jun 29 12:51:30 1996 Ian Lance Taylor <ian@cygnus.com> + + * binutils-all/objcopy.exp: Simple copy test works for i960 b.out + targets. + +Mon Jun 24 14:33:04 1996 Ian Lance Taylor <ian@cygnus.com> + + * binutils-all/objcopy.exp: On OSF/1, the simple copy test will + succeed with gas, and fail with /bin/as, so mark it as an expected + failure only if it fails. + +Tue Mar 26 16:55:08 1996 Jeffrey A Law (law@cygnus.com) + + * binutils-all/objcopy.exp: No longer expect adjust-section-vma + test to fail for hppa*-*-proelf*. + +Mon Mar 11 08:25:14 1996 Jeffrey A Law (law@cygnus.com) + + * binutils-all/objdump.exp: Look for "$CODE$", not just "CODE". + +Wed Jan 31 11:55:13 1996 Jeffrey A Law (law@cygnus.com) + + * binutils-all/objcopy.exp: Expect adjust-section-vma tests to + fail for hppa*-*-proelf* targets. + +Thu Jan 25 13:53:04 1996 Ian Lance Taylor <ian@cygnus.com> + + * binutils-all/objdump.exp: Update for objdump -h format change. + * binutils-all/objcopy.exp: Likewise. + +Mon Jan 15 18:14:14 1996 Ian Lance Taylor <ian@cygnus.com> + + * binutils-all/objcopy.exp: Use the lma, not the vma, when testing + address adjustments. + +Fri Dec 15 16:31:55 1995 Ian Lance Taylor <ian@cygnus.com> + + * binutils-all/objdump.exp: Update objdump -i test for current + objdump output. + +Mon Nov 27 15:15:09 1995 Ian Lance Taylor <ian@cygnus.com> + + * binutils-all/objcopy.exp: Correct fail calls to always use the + same string as the pass call. + +Wed Nov 22 13:18:58 1995 Ian Lance Taylor <ian@cygnus.com> + + * lib/utils-lib.exp (prune_system_crud): Discard -g -O warnings + from native compilers on OSF/1 and SunOS. + +Fri Nov 17 10:36:09 1995 Ian Lance Taylor <ian@cygnus.com> + + * lib/utils-lib.exp (default_binutils_compiler: Change error + message to say compilation rather than assembly. + +Wed Nov 15 18:34:42 1995 Ken Raeburn <raeburn@cygnus.com> + + * binutils-all/objcopy.exp: Simple copy test does appear to work + on i*86-svr4. + +Wed Nov 15 12:19:28 1995 Ian Lance Taylor <ian@cygnus.com> + + * binutils-all/objcopy.exp: If assembly fails, call unresolved. + Test running objcopy and strip on a final executable. + * binutils-all/testprog.c: New file. + * config/default.exp (STRIP, STRIPFLAGS): Define. + (binutils_compile): New procedure. + * lib/utils-lib.exp (default_binutils_compile): New procedure. + +Fri Nov 3 13:22:33 1995 Ian Lance Taylor <ian@cygnus.com> + + * lib/utils-lib.exp (default_binutils_run): Don't use verbose + -log, reverting part of Oct 2 change. + +Wed Nov 1 15:09:57 1995 Manfred Hollstein KS/EF4A 60/1F/110 #40283 <manfred@lts.sel.alcatel.de> + + * binutils-all/objcopy.exp: Add setup_xfails for + m68*-motorola-sysv* and m88*-motorola-sysv*. + +Wed Oct 4 14:38:31 1995 Ian Lance Taylor <ian@cygnus.com> + + * binutils-all/nm.exp: Add setup_xfails for XCOFF. + +Mon Oct 2 12:41:48 1995 Ian Lance Taylor <ian@cygnus.com> + + * binutils-all/ar.exp: New file. + * binutils-all/bintest.s: Make text_symbol and data_symbol global. + Add new static symbols static_text_symbol and static_data_symbol. + * binutils-all/nm.exp: Adjust accordingly. + * config/default.exp (AR): Set if not set. + (binutils_remove): New procedure. + * lib/utils-lib.exp (default_binutils_run): Call + prune_system_crud on program output. Use verbose -log instead of + both verbose and send_log. + (default_binutils_remove): New procedure. + + * lib/utils-lib.exp (default_binutils_assemble): Call + prune_system_crud on assembler output. + +Tue Sep 26 14:07:05 1995 Ian Lance Taylor <ian@cygnus.com> + + * binutils-all/objcopy.exp: Add setup_xfails for simple copy test + for i386 COFF targets. + +Wed Sep 13 13:20:21 1995 Ian Lance Taylor <ian@cygnus.com> + + * lib/utils-lib.exp (prune_system_crud): Define if not defined. + * binutils-all/objcopy.exp: Call prune_system_crud on cmp output. + +Sat Aug 19 17:38:06 1995 Ian Lance Taylor <ian@cygnus.com> + + * binutils-all/objcopy.exp: Add xfail for i*86-*-aout* for simple + copy test. + +Wed Aug 16 16:52:53 1995 Ian Lance Taylor <ian@cygnus.com> + + * binutils-all/nm.exp: Add setup_xfail for mips*-sony-bsd* for + tests which fail on ECOFF targets. + + * binutils-all/objcopy.exp: Change i*86-*-linux xfail for simple + copy test to check for i*86-*-linuxaout* instead. + +Tue Aug 8 17:48:37 1995 Ian Lance Taylor <ian@cygnus.com> + + * binutils-all/objcopy.exp: Add setup_xfail for a29k-*-vxworks* + for simple copy test. + +Tue Jul 25 11:57:12 1995 Ian Lance Taylor <ian@cygnus.com> + + * binutils-all/objcopy.exp: Change setup_xfail for simple copy + test from i960-*-vxworks5.1 to i960-*-vxworks*. + +Mon Jul 10 12:25:46 1995 Ian Lance Taylor <ian@cygnus.com> + + * binutils-all/objcopy.exp: Add setup_xfail for z8*-*-coff for + simple copy test. + * binutils-all/objdump.exp (cpus_expected): Add z8001 and z8002. + +Sun May 21 20:32:53 1995 Jeff Law (law@snake.cs.utah.edu) + + * binutils-all/hppa/objdump.exp (addendbug): Handle PA ELF targets + too. + * binutils-all/objcopy.exp (simple copy): Don't expect PA ELF + targets to fail. + +Tue Apr 4 14:52:08 1995 Jeff Law (law@snake.cs.utah.edu) + + * binutils-all/hppa: Renamed from binutils-hppa. + +Wed Mar 29 12:02:43 1995 Ian Lance Taylor <ian@cygnus.com> + + * binutils-all/objcopy.exp: Add setup_xfail for simple copy test + for h8500-*-hms and h8500-*-coff. + +Tue Mar 28 11:18:28 1995 Ian Lance Taylor <ian@cygnus.com> + + * binutils-all/objcopy.exp: Add setup_xfail for simple copy test + for m68*-ericsson-ose and m88*-*-coff. + +Mon Mar 27 11:27:31 1995 Ian Lance Taylor <ian@cygnus.com> + + * binutils-all/objcopy.exp: Add setup_xfail for simple copy test + for m68*-*-vxworks*. + +Fri Mar 24 11:44:25 1995 Ian Lance Taylor <ian@cygnus.com> + + * binutils-hppa/objdump.exp: Correct hppa*-*-* check. + +Tue Mar 21 10:48:45 1995 Jeff Law (law@snake.cs.utah.edu) + + * binutils-hppa/addendbug.s: New testcase. + * binutils-hppa/objdump.exp: Run it. + +Mon Mar 20 11:31:05 1995 Ian Lance Taylor <ian@cygnus.com> + + * lib/utils-lib.exp (default_binutils_run): Quote any dollar signs + in progargs before passing it to exec. + +Fri Mar 17 16:39:31 1995 Jeff Law (law@snake.cs.utah.edu) + + * config/hppa.sed: Sed script to transform bintest.s into proper + PA assembly code. + * binutils-all/nm.exp: Enable these tests on the PA. + * binutils-all/objcopy.exp: Enable these tests on the PA. Expect + simple copy to fail. + * binutils-all/objdump.exp: Enable these tests on the PA. Handle + "CODE" as a section name. + * binutils-all/size.exp: Enable these tests on the PA. + * lib/utils-lib.exp (default_binutils_assemble): For "hppa*-*-*", + run the assembly through a sed script before passing it to the + assembler. + +Wed Mar 15 16:47:13 1995 Ian Lance Taylor <ian@cygnus.com> + + * binutils-all/objdump.exp: Force section sizes to be interpreted + in hex. Change objdump -h failure mode to always use the same + string. + +Thu Jan 5 13:01:43 1995 Ian Lance Taylor <ian@cygnus.com> + + * binutils-all/nm.exp: Just check for irix4*, rather than + irix\[0-4\]*, to avoid DejaGnu bug. + +Thu Dec 15 19:35:31 1994 Ken Raeburn <raeburn@cujo.cygnus.com> + + * binutils-all/objcopy.exp: Expect simple-objcopy test to fail + for various other targets for which gas doesn't use bfd: sh-hms, + m68k-hpux, m68k-sunos, m68k-coff, i386-linux, a29k-udi, a29k-coff, + i960-vxworks5.1, i960-coff, h8300-hms, h8300-coff. + +Wed Dec 14 15:54:46 1994 Ken Raeburn <raeburn@cujo.cygnus.com> + + * binutils-all/size.exp: Skip tests requiring bintest.o on hppa, + since it (correctly) generates syntax errors on that platform. + * binutils-all/objdump.exp: Ditto. + * binutils-all/nm.exp: Ditto. + * binutils-all/objcopy.exp: Ditto. Also, move setup_xfail for + sh-coff to branch where objcopy execution produced no error + messages. Expect failure for hp300 also. + +Thu Dec 8 14:36:15 1994 Ken Raeburn <raeburn@cujo.cygnus.com> + + * binutils-all/objdump.exp (cpus_expected): New variable, taken + from objdump -i test, added ns32k and powerpc, sorted. + (objdump -i, -f tests): Use $cpus_expected. + + * binutils-all/objcopy.exp: For simple-copy test, expect failure + for sh-coff. + +Tue Oct 25 16:00:14 1994 Ian Lance Taylor <ian@sanguine.cygnus.com> + + * binutils-all/objcopy.exp: Adjust --adjust-section-vma tests for + new S-record section handling. + +Tue Oct 18 11:18:21 1994 Ian Lance Taylor <ian@sanguine.cygnus.com> + + * binutils-all/nm.exp: nm with no arguments and nm -P do not work + as expected on ECOFF targets; add calls to setup_xfail. + + * binutils-all/objcopy.exp: New file. + * config/default.exp: Initialize OBJCOPY and OBJCOPYFLAGS. + +Fri Oct 14 14:46:22 1994 Ian Lance Taylor <ian@sanguine.cygnus.com> + + Rewrite testsuite. + * configure.in, Makefile.in: Remove. + * binutils-all/configure.in, binutils-all/Makefile.in: Remove. + * binutils-all/bintest.c: Remove. + * binutils-all/bintest.s: New file. + * binutils-all/nm.exp, binutils-all/objdump.exp: Rewrite. + * binutils-all/size.exp: Rewrite. + * config/default.exp: Load utils-lib.exp. Set AS and ASFLAGS. + Don't go up one directory from $base_dir. Create tmpdir. + (binutils_run, binutils-assemble): New procedures. + * config/unix.exp: Remove. + * config/mt-a29k-udi, config/mt-i386-aout: Remove. + * config/mt-i960-nindy, config/mt-lynx, config/mt-m68k: Remove. + * config/mt-mips-ecoff, config/mt-slite: Remove. + * config/mt-sparc-aout, config/mt-vxworks: Remove. + * lib/utils-lib.exp (binutil_version): Don't redirect standard + input when getting version. Don't unset errorInfo. + (default_binutils_run): New procedure. + (default_binutils_assemble): New procedure. + +Thu Sep 29 12:45:39 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * VMS does not permit `.' in directory names: renamed binutils.all + to binutils-all. + * configure.in (configdirs): Change binutils.all to binutils-all. + +Fri Sep 23 16:01:14 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * configure.in: Use mt-m68k for m68k*-*-aout* and m68k*-*-coff*, + not for m68k-*-*. + +Fri Sep 23 13:54:50 1994 Ken Raeburn <raeburn@cujo.cygnus.com> + + * binutils.all/objdump.exp: Added ARM to list of CPU types. + +Thu Sep 22 11:04:50 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * binutils.all/objdump.exp: Update for new usage message. + * binutils.all/size.exp: Use a double backslash in the string to + get a single backslash to the regexp matcher. Accept $TEXT$, + $DATA$ and $BSS$ as well as .text, .data and .bss, for HP/UX. + +Fri Sep 2 12:53:10 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * config/unix.exp: If nm.new does not exist, use [transform nm]. + * config/default.exp: Likewise. + +Wed Aug 24 12:41:37 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) + + * configure.in, binutils.all/configure.in: Change i386 to + i[345]86. + +Tue Jul 19 15:23:53 1994 Bill Cox (bill@rtl.cygnus.com) + + * config/mt-mips-ecoff: Add -Tidp.ld option. + +Thu Jun 30 12:41:55 1994 J.T. Conklin (jtc@phishhead.cygnus.com) + + * config/default.exp: Use nm.new, not nm, from newly built tree. + +Tue May 17 14:04:05 1994 Bill Cox (bill@rtl.cygnus.com) + + * config/default.exp, config/unix.exp: Replace error + proc calls with perror. + +Tue May 10 11:20:54 1994 Stan Shebs (shebs@andros.cygnus.com) + + * configure.in (sparclite): Match on sparclite*-*-*. + +Wed Apr 13 18:25:19 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * config/unix.exp: Use nm.new, not nm, from newly built tree. + + * binutils.all/objdump.exp: Add more wildcards to list of + single-letter options in pattern for usage message. + + * binutils.all/nm.exp: Deleted debug-symbols test, since it only + works for a.out/stabs systems. Fixed regexps to make underscores + optional, since some C compilers don't prepend them. Deleted + check for foo.o symbol, since again some systems don't generate + it. + +Mon Apr 11 10:31:00 1994 Bill Cox (bill@rtl.cygnus.com) + + * Makefile.in (check): Set TCL_LIBRARY for runtest. + +Mon Feb 14 19:34:03 1994 Rob Savoye (rob@darkstar.cygnus.com) + + * Makefile.in: Use new config features of DejaGnu in site.exp + file. "Make check" should now work for all crosses. + +Fri Jan 28 18:00:29 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * binutils.all/objdump.exp: In usage message, accept + "section-name" as well as "section_name". + +Mon Jan 17 16:57:02 1994 Ken Raeburn (raeburn@cujo.cygnus.com) + + * binutils.all/objdump.exp: Trim list of format names expected, + and accept any known CPU type. + +Thu Dec 2 20:50:24 1993 Rob Savoye (rob@darkstar.cygnus.com) + + * Makefile.in: Remove some stuff from the site.exp file. + * config/unix.exp: Add global before seeing if the variables for + nm, objdump, and size exist. + +Wed Nov 3 11:12:32 1993 Rob Savoye (rob@darkstar.cygnus.com) + + * config/udi.exp,unix.exp: Transform tool name. + * binutils.all/*.exp: Clear errorInfo after exec. + +Fri Jul 2 12:41:20 1993 Ian Lance Taylor (ian@cygnus.com) + + * binutils.all/*.exp: Use -- for long arguments rather than +. + +Fri Jun 4 10:52:29 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * configure.in: change srctrigger to Makefile.in + +Wed May 26 17:27:46 1993 Ian Lance Taylor (ian@cygnus.com) + + * Makefile.in (FLAGS_TO_PASS): Pass down CC and CFLAGS. + +Fri May 7 13:58:44 1993 Ian Lance Taylor (ian@cygnus.com) + + * binutils.all/objdump.exp: Update for new usage message. + +Mon Apr 19 14:08:52 1993 Rob Savoye (rob@darkstar.cygnus.com) + + * binutils.all/*.exp: Use the new util_test proc. + * Makefile.in: Create a local site.exp file with config info. + +Thu Mar 25 05:38:47 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com) + + * nm.all/configure.in (srcname): Delete extra quote. + +Mon Feb 22 07:54:03 1993 Mike Werner (mtw@poseidon.cygnus.com) + + * binutils/testsuite: made modifications to testcases, etc., to allow + them to work properly given the reorganization of deja-gnu and the + relocation of the testcases from deja-gnu to a "tool" subdirectory. + +Sun Feb 21 10:55:55 1993 Mike Werner (mtw@poseidon.cygnus.com) + + * binutils/testsuite: Initial creation of binutils/testsuite. + Migrated dejagnu testcases and support files for testing nm to + binutils/testsuite from deja-gnu. These files were moved "as is" + with no modifications. This migration is part of a major overhaul + of dejagnu. The modifications to these testcases, etc., which + will allow them to work with the new version of dejagnu will be + made in a future update. + diff --git a/binutils/testsuite/binutils-all/ar.exp b/binutils/testsuite/binutils-all/ar.exp new file mode 100644 index 0000000..4b38c6b --- /dev/null +++ b/binutils/testsuite/binutils-all/ar.exp @@ -0,0 +1,219 @@ +# Copyright (C) 1995, 1997 Free Software Foundation, Inc. + +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-dejagnu@prep.ai.mit.edu + +# Written by Ian Lance Taylor <ian@cygnus.com> + +if ![is_remote host] { + if {[which $AR] == 0} then { + perror "$AR does not exist" + return + } +} + +# send_user "Version [binutil_version $AR]" + +# Test long file name support + +proc long_filenames { } { + global AR + global host_triplet + + set testname "ar long file names" + + set n1 "abcdefghijklmnopqrstuvwxyz1" + set n2 "abcdefghijklmnopqrstuvwxyz2" + set file1 tmpdir/$n1 + set file2 tmpdir/$n2 + + remote_file build delete $file1 + + # Some file systems truncate file names at 14 characters, which + # makes it impossible to run this test. Check for that now. + set status [catch "set f [open tmpdir/$n1 w]" errs] + if { $status != 0 } { + verbose -log "open tmpdir/$n1 returned $errs" + unsupported $testname + return + } + puts $f "first" + close $f + + + remote_file build delete $file2 + + set status [catch "set f [open tmpdir/$n2 w]" errs] + if { $status != 0 } { + verbose -log "open tmpdir/$n2 returned $errs" + unsupported $testname + return + } + puts $f "second" + close $f + + if [is_remote host] { + set file1 [remote_download host $file1]; + set file2 [remote_download host $file2]; + set dest artest.a + } else { + set dest tmpdir/artest.a + } + + remote_file host delete $dest; + + set got [binutils_run $AR "rc $dest $file1 $file2"] + if [is_remote host] { + remote_upload host $file1 tmpdir/$n1 + } + + set f [open tmpdir/$n1 r] + gets $f string + close $f + if ![string match "first" $string] { + verbose -log "reading tmpdir/$n1 returned $string" + unsupported $testname + return + } + + remote_file host delete $dest; + set got [binutils_run $AR "rc $dest $file1 $file2"] + + if ![string match "" $got] { + fail $testname + return + } + + remote_file build delete tmpdir/$n1 + remote_file build delete tmpdir/$n2 + + set got [binutils_run $AR "t $dest"] + regsub "\[\r\n \t\]*$" "$got" "" got; + if ![string match "$n1*$n2" $got] { + fail $testname + return + } + + if [is_remote host] { + remote_file host delete $file1; + remote_file host delete $file2; + } + + verbose -log "$AR x $dest" + set exec_output [binutils_run $AR "x $dest"] + set exec_output [prune_warnings $exec_output] + if ![string match "" $exec_output] { + verbose -log $exec_output + fail $testname + return + } + + if [is_remote host] { + remote_upload host $n1 tmpdir/$n1; + remote_upload host $n2 tmpdir/$n2; + set file1 tmpdir/$n1 + set file2 tmpdir/$n2 + } else { + set file1 $n1 + set file2 $n2 + } + + if ![file exists $file1] { + verbose -log "$file1 does not exist" + fail $testname + return + } + if ![file exists $file2] { + verbose -log "$file2 does not exist" + fail $testname + return + } + + set f [open $file1 r] + if { [gets $f line] == -1 || $line != "first" } { + verbose -log "$file1 contents:" + verbose -log "$line" + close $f + fail $testname + return + } + close $f + + set f [open $file2 r] + if { [gets $f line] == -1 || $line != "second" } { + verbose -log "$file2 contents:" + verbose -log "$line" + close $f + fail $testname + return + } + close $f + + pass $testname +} + +# Test building the symbol table. + +proc symbol_table { } { + global AR + global AS + global NM + global srcdir + global subdir + + set testname "ar symbol table" + + if ![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o] { + unresolved $testname + return + } + + if [is_remote host] { + set archive artest.a + set objfile [remote_download host tmpdir/bintest.o] + remote_file host delete $archive + } else { + set archive tmpdir/artest.a + set objfile tmpdir/bintest.o + } + + remote_file build delete tmpdir/artest.a + + set got [binutils_run $AR "rc $archive ${objfile}"] + if ![string match "" $got] { + fail $testname + return + } + + set got [binutils_run $NM "--print-armap $archive"] + if { ![string match "*text_symbol in bintest.o*" $got] \ + || ![string match "*data_symbol in bintest.o*" $got] \ + || ![string match "*common_symbol in bintest.o*" $got] \ + || [string match "*static_text_symbol in bintest.o*" $got] \ + || [string match "*static_data_symbol in bintest.o*" $got] \ + || [string match "*external_symbol in bintest.o*" $got] } { + fail $testname + return + } + + pass $testname +} + +# Run the tests. + +long_filenames +symbol_table diff --git a/binutils/testsuite/binutils-all/bintest.s b/binutils/testsuite/binutils-all/bintest.s new file mode 100644 index 0000000..9e00650 --- /dev/null +++ b/binutils/testsuite/binutils-all/bintest.s @@ -0,0 +1,12 @@ + .globl text_symbol + .text +text_symbol: +static_text_symbol: + .long 1 + .long external_symbol + .globl data_symbol + .data +data_symbol: +static_data_symbol: + .long 2 + .comm common_symbol,4 diff --git a/binutils/testsuite/binutils-all/hppa/addendbug.s b/binutils/testsuite/binutils-all/hppa/addendbug.s new file mode 100644 index 0000000..659306f --- /dev/null +++ b/binutils/testsuite/binutils-all/hppa/addendbug.s @@ -0,0 +1,23 @@ + .SPACE $PRIVATE$ + .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31 + .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82 + .SPACE $TEXT$ + .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44 + .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY + .IMPORT $global$,DATA + .IMPORT $$dyncall,MILLICODE +; gcc_compiled.: + .SPACE $TEXT$ + .SUBSPA $CODE$ + + .align 4 + .EXPORT initialize_char_syntax,CODE + .EXPORT initialize_char_syntax,ENTRY,PRIV_LEV=3,RTNVAL=GR +initialize_char_syntax + .PROC + .CALLINFO FRAME=64,NO_CALLS,SAVE_SP,ENTRY_GR=3 + .ENTRY + addil L'is_idchar-$global$-32,%r27 + .EXIT + .PROCEND +is_idchar .comm 256 diff --git a/binutils/testsuite/binutils-all/hppa/objdump.exp b/binutils/testsuite/binutils-all/hppa/objdump.exp new file mode 100644 index 0000000..a46b289 --- /dev/null +++ b/binutils/testsuite/binutils-all/hppa/objdump.exp @@ -0,0 +1,59 @@ +# Copyright (C) 1993, 1994, 1996, 1997 Free Software Foundation, Inc. + +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-dejagnu@prep.ai.mit.edu + +# This file was written by Rob Savoye <rob@cygnus.com> +# and rewritten by Ian Lance Taylor <ian@cygnus.com> + +if ![istarget hppa*-*-*] then { + return +} + +if {[which $OBJDUMP] == 0} then { + perror "$OBJDUMP does not exist" + return +} + +send_user "Version [binutil_version $OBJDUMP]" + +if {![binutils_assemble $srcdir/$subdir/addendbug.s tmpdir/addendbug.o]} then { + return +} + +if [is_remote host] { + set objfile [remote_download host tmpdir/addendbug.o] +} else { + set objfile tmpdir/addendbug.o +} + +# Make sure the SOM BFD code sign extends constants in R_DATA_OVERRIDE fixups. + +set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -r $objfile"] + +if [istarget hppa*-*-*elf*] then { + set want "00000000 R_PARISC_DPREL21L\[ \]+is_idchar\\+0xffffffe0.*" +} else { + set want "00000000 R_DP_RELATIVE\[ \]+is_idchar\\+0xffffffe0.*" +} + + +if [regexp $want $got] then { + pass "addendbug test" +} else { + fail "addendbug test" +} diff --git a/binutils/testsuite/binutils-all/nm.exp b/binutils/testsuite/binutils-all/nm.exp new file mode 100644 index 0000000..76c7c5f --- /dev/null +++ b/binutils/testsuite/binutils-all/nm.exp @@ -0,0 +1,123 @@ +# Copyright (C) 1993, 1994, 1996, 1997 Free Software Foundation, Inc. + +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-dejagnu@prep.ai.mit.edu + +# This file was written by Rob Savoye <rob@cygnus.com> +# and rewritten by Ian Lance Taylor <ian@cygnus.com> + +if ![is_remote host] { + if {[which $NM] == 0} then { + perror "$NM does not exist" + return + } +} + +send_user "Version [binutil_version $NM]" + + +if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then { + return +} + +if [is_remote host] { + set tempfile [remote_download host tmpdir/bintest.o] +} else { + set tempfile tmpdir/bintest.o +} + +# Test nm with no arguments. + +# This test does not work correctly on ECOFF targets, because ECOFF +# stores most symbols twice, which messes up the nm output. +setup_xfail "alpha*-*-osf*" "alpha*-*-netware*" +setup_xfail "mips*-*-ultrix*" "mips*-*-ecoff*" "mips*-*-irix4*" +setup_xfail "mips*-*-riscos*" "mips*-*-sysv3*" "mips*-sony-bsd*" + +# This test does not work correctly on XCOFF targets, because XCOFF +# does not enter static symbols in the symbol table. +setup_xfail "*-*-aix*" + +set got [binutils_run $NM "$NMFLAGS $tempfile"] + +if [info exists vars] then { unset vars } +while {[regexp "(\[a-zA-Z\]) (\[a-z_\]*_symbol)(.*)" $got all type symbol rest]} { + set vars($symbol) $type + set got $rest +} + +if {![info exists vars(text_symbol)] \ + || $vars(text_symbol) != "T" \ + || ![info exists vars(data_symbol)] \ + || $vars(data_symbol) != "D" \ + || ![info exists vars(common_symbol)] \ + || $vars(common_symbol) != "C" \ + || ![info exists vars(external_symbol)] \ + || $vars(external_symbol) != "U" \ + || ![info exists vars(static_text_symbol)] \ + || $vars(static_text_symbol) != "t" \ + || ![info exists vars(static_data_symbol)] \ + || $vars(static_data_symbol) != "d"} { + fail "nm (no arguments)" +} else { + pass "nm (no arguments)" +} + +# Test nm -g + +set got [binutils_run $NM "$NMFLAGS -g $tempfile"] + +if [info exists vars] then { unset vars } +while {[regexp "(\[a-z_\]*_symbol)(.*)" $got all symbol rest]} { + set vars($symbol) 1 + set got $rest +} + +if {![info exists vars(text_symbol)] \ + || ![info exists vars(data_symbol)] \ + || ![info exists vars(common_symbol)] \ + || ![info exists vars(external_symbol)] \ + || [info exists vars(static_text_symbol)] \ + || [info exists vars(static_data_symbol)]} { + fail "nm -g" +} else { + pass "nm -g" +} + +# Test nm -P + +# This test does not work correctly on ECOFF targets, because ECOFF +# stores most symbols twice, which messes up the nm output. +setup_xfail "alpha*-*-osf*" "alpha*-*-netware*" +setup_xfail "mips*-*-ultrix*" "mips*-*-ecoff*" "mips*-*-irix4*" +setup_xfail "mips*-*-riscos*" "mips*-*-sysv3*" "mips*-sony-bsd*" + +# This test does not work correctly on XCOFF targets, because XCOFF +# does not enter static symbols in the symbol table. +setup_xfail "*-*-aix*" + +set got [binutils_run $NM "$NMFLAGS -P $tempfile"] + +set want "common_symbol C \[0\]*4.*data_symbol D \[0-9a-fA-F\]*.*external_symbol U.*static_data_symbol d \[0-9a-fA-F\]*.*static_text_symbol t \[0-9a-fA-F\]*.*text_symbol T \[0-9a-fA-F\]*" + +if [regexp $want $got] then { + pass "nm -P" +} else { + fail "nm -P" +} + +# There are certainly other tests that could be run. diff --git a/binutils/testsuite/binutils-all/objcopy.exp b/binutils/testsuite/binutils-all/objcopy.exp new file mode 100644 index 0000000..78972f1 --- /dev/null +++ b/binutils/testsuite/binutils-all/objcopy.exp @@ -0,0 +1,591 @@ +# Copyright (C) 1994, 95, 96, 97, 1998 Free Software Foundation, Inc. + +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-dejagnu@prep.ai.mit.edu + +# Written by Ian Lance Taylor <ian@cygnus.com> + +if ![is_remote host] { + if {[which $OBJCOPY] == 0} then { + perror "$OBJCOPY does not exist" + return + } +} + +send_user "Version [binutil_version $OBJCOPY]" + +if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then { + perror "unresolved 1" + unresolved "objcopy (simple copy)" + return +} + +if ![is_remote host] { + set tempfile tmpdir/bintest.o; + set copyfile tmpdir/copy; +} else { + set tempfile [remote_download host tmpdir/bintest.o] + set copyfile copy +} + +# Test that objcopy does not modify a file when copying it. + +set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS $tempfile ${copyfile}.o"] + +if ![string match "" $got] then { + fail "objcopy (simple copy)" +} else { + send_log "cmp $tempfile ${copyfile}.o\n" + verbose "cmp $tempfile ${copyfile}.o" + if [is_remote host] { + set src1 tmpdir/bintest.o + set src2 tmpdir/copy.o + remote_upload host $tempfile $src1; + remote_upload host ${copyfile}.o $src2; + } else { + set src1 ${tempfile} + set src2 ${copyfile}.o + } + set status [remote_exec build cmp "${src1} ${src2}"]; + set exec_output [lindex $status 1]; + set exec_output [prune_warnings $exec_output] + + # On some systems the result of objcopy will not be identical. + # Usually this is just because gas isn't using bfd to write the files + # in the first place, and may order things a little differently. + # Those systems should use setup_xfail here. + + setup_xfail "sh-*-coff" "sh-*-hms" + setup_xfail "m68*-*-hpux*" "m68*-*-sunos*" "m68*-*-coff" "m68*-*-vxworks*" + setup_xfail "m68*-ericsson-ose" "m68k*-motorola-sysv*" + setup_xfail "i*86-*-linuxaout*" "i*86-*-aout*" + setup_xfail "i*86-*-sysv3" "i*86-*-isc*" "i*86-*-sco*" "i*86-*-coff" + setup_xfail "i*86-*-aix*" "i*86-*-go32*" + setup_xfail "a29k-*-udi" "a29k-*-coff" "a29k-*-vxworks*" + setup_xfail "i960-*-coff" + setup_xfail "h8300-*-hms" "h8300-*-coff" + setup_xfail "h8500-*-hms" "h8500-*-coff" + setup_xfail "hppa*-*-*" + clear_xfail "hppa*-*-*elf*" + setup_xfail "m88*-*-coff" "m88*-motorola-sysv*" + setup_xfail "z8*-*-coff" + + if [string match "" $exec_output] then { + pass "objcopy (simple copy)" + } else { + send_log "$exec_output\n" + verbose "$exec_output" 1 + + # On OSF/1, this succeeds with gas and fails with /bin/as. + setup_xfail "alpha*-*-osf*" + + # This fails for COFF i960-vxworks targets. + setup_xfail "i960-*-vxworks*" + + fail "objcopy (simple copy)" + } +} + +# Test generating S records. + +# We make the srec filename 8.3 compatible. Note that the header string +# matched against depends on the name of the file. Ugh. + +if [is_remote host] { + set srecfile copy.sre + set header_string S00B0000636F70792E737265C1 +} else { + set srecfile ${copyfile}.srec + set header_string S0130000746D706469722F636F70792E7372656397 +} + +set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS -O srec $tempfile ${srecfile}"] + +if ![string match "" $got] then { + fail "objcopy -O srec" +} else { + if [is_remote host] { + remote_upload host ${srecfile} tmpdir/copy.srec; + set srecfile tmpdir/copy.srec; + } + set file [open ${srecfile} r] + + # The first S record is fixed by the file name we are using. + gets $file line + send_log "$line\n" + verbose $line + if ![regexp "$header_string.*" $line] { + send_log "bad header\n" + fail "objcopy -O srec" + } else { + while {[gets $file line] != -1 \ + && [regexp "^S\[123\]\[0-9a-fA-F\]+\[\r\n\]*$" $line]} { + send_log "$line\n" + verbose $line + set line "**EOF**" + } + send_log "$line\n" + verbose $line + if ![regexp "^S\[789\]\[0-9a-fA-F\]+\[\r\n\]*$" $line] then { + send_log "bad trailer\n" + fail "objcopy -O srec" + } else { + if {[gets $file line] != -1} then { + send_log "garbage at end\n" + send_log "$line\n" + verbose $line + fail "objcopy -O srec" + } else { + set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -f ${copyfile}.srec"] + if ![regexp "file format srec" $got] then { + send_log "objdump failed\n" + fail "objcopy -O srec" + } else { + pass "objcopy -O srec" + } + } + } + } + + close $file +} + +# Test setting and adjusting the start address. We only test this +# while generating S records, because we may not be able to set the +# start address for other object file formats, and the S record case +# is the only useful one anyhow. + +set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -f $tempfile"] +if ![regexp "start address (\[0-9a-fA-FxX\]+)" $got all origstart] then { + perror "objdump can not recognize bintest.o" + set origstart "" +} else { + set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS -O srec $tempfile ${copyfile}.srec --set-start 0x7654"] + if ![string match "" $got] then { + fail "objcopy --set-start" + } else { + set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -f ${copyfile}.srec"] + if ![regexp "file format srec.*start address (\[0-9a-fA-FxX\]+)" $got all srecstart] then { + fail "objcopy --set-start" + } else { + if {$srecstart != 0x7654} then { + send_log "$srecstart != 0x7654\n" + fail "objcopy --set-start" + } else { + pass "objcopy --set-start" + } + } + } + + set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS -O srec $tempfile ${copyfile}.srec --adjust-start 0x123"] + if ![string match "" $got] then { + fail "objcopy --adjust-start" + } else { + set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -f ${copyfile}.srec"] + if ![regexp "file format srec.*start address (\[0-9a-fA-FxX\]+)" $got all srecstart] then { + fail "objcopy --adjust-start" + } else { + if {$srecstart != $origstart + 0x123} then { + send_log "$srecstart != $origstart + 0x123\n" + fail "objcopy --adjust-start" + } else { + pass "objcopy --adjust-start" + } + } + } +} + +# Test adjusting the overall VMA, and adjusting the VMA of a +# particular section. We again only test this when generating S +# records. + +set low "" +set lowname "" + +set headers [binutils_run $OBJDUMP "$OBJDUMPFLAGS -h $tempfile"] + +set headers_regexp "\[ 0-9\]+(\[^ \]+)\[ \]*(\[0-9a-fA-F\]+)\[ \]+\[0-9a-fA-F\]+\[ \]+(\[0-9a-fA-F\]+)\[ \]+\[0-9a-fA-F\]+\[ \]+2\[*\]\[*\]\[0-9\]+(.*)" + +set got $headers +while {[regexp $headers_regexp $got all name size vma rest]} { + set vma 0x$vma + set size 0x$size + if {$size != 0} { + if {$low == "" || $vma < $low} { + set low $vma + set lowname $name + } + } + set got $rest +} + +if {$low == "" || $origstart == ""} then { + perror "objdump can not recognize bintest.o" +} else { + set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS -O srec $tempfile ${copyfile}.srec --adjust-vma 0x123"] + if ![string match "" $got] then { + fail "objcopy --adjust-vma" + } else { + set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -fh ${copyfile}.srec"] + set want "file format srec.*start address\[ \]*(\[0-9a-fA-FxX\]+).*sec1\[ \]+\[0-9a-fA-F\]+\[ \]+(\[0-9a-fA-F\]+)" + if ![regexp $want $got all start vma] then { + fail "objcopy --adjust-vma" + } else { + set vma 0x$vma + if {$vma != $low + 0x123} then { + send_log "$vma != $low + 0x123\n" + fail "objcopy --adjust-vma" + } else { + if {$start != $origstart + 0x123} then { + send_log "$start != $origstart + 0x123\n" + fail "objcopy --adjust-vma" + } else { + pass "objcopy --adjust-vma" + } + } + } + } + + set arg "" + set got $headers + while {[regexp $headers_regexp $got all name size vma rest]} { + set vma 0x$vma + if {$vma == $low} then { + set arg "$arg --adjust-section-vma $name+4" + } + set got $rest + } + + set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS -O srec $tempfile ${copyfile}.srec $arg"] + if ![string match "" $got] then { + fail "objcopy --adjust-section-vma +" + } else { + set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -h ${copyfile}.srec"] + set want "file format srec.*sec1\[ \]+\[0-9a-fA-F\]+\[ \]+(\[0-9a-fA-F\]+)" + if ![regexp $want $got all vma] then { + fail "objcopy --adjust-section-vma +" + } else { + set vma 0x$vma + if {$vma != $low + 4} then { + send_log "$vma != $low + 4\n" + fail "objcopy --adjust-section-vma +" + } else { + pass "objcopy --adjust-section-vma +" + } + } + } + + regsub -all "\\+4" $arg "=[expr $low + 4]" argeq + set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS -O srec $tempfile ${copyfile}.srec $argeq"] + if ![string match "" $got] then { + fail "objcopy --adjust-section-vma =" + } else { + set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -h ${copyfile}.srec"] + set want "file format srec.*sec1\[ \]+\[0-9a-fA-F\]+\[ \]+(\[0-9a-fA-F\]+)" + if ![regexp $want $got all vma] then { + fail "objcopy --adjust-section-vma =" + } else { + set vma 0x$vma + if {$vma != $low + 4} then { + send_log "$vma != $low + 4\n" + fail "objcopy --adjust-section-vma =" + } else { + pass "objcopy --adjust-section-vma =" + } + } + } +} + +# Test stripping an object. + +proc strip_test { } { + global CC + global STRIP + global STRIPFLAGS + global NM + global NMFLAGS + global srcdir + global subdir + + set test "strip" + + if { [target_compile $srcdir/$subdir/testprog.c tmpdir/testprog.o object debug] != "" } { + untested $test + return + } + + if [is_remote host] { + set objfile [remote_download host tmpdir/testprog.o]; + } else { + set objfile tmpdir/testprog.o + } + + set exec_output [binutils_run $STRIP "$STRIPFLAGS $objfile"] + if ![string match "" $exec_output] { + fail $test + return + } + + set exec_output [binutils_run $NM "-a $NMFLAGS $objfile"] + if ![string match "*: no symbols*" $exec_output] { + fail $test + return + } + + pass $test +} + +strip_test + +# Test stripping an object file with saving a symbol + +proc strip_test_with_saving_a_symbol { } { + global CC + global STRIP + global STRIPFLAGS + global NM + global NMFLAGS + global srcdir + global subdir + + set test "strip with saving a symbol" + + if { [target_compile $srcdir/$subdir/testprog.c tmpdir/testprog.o object debug] != "" } { + untested $test + return + } + + if [is_remote host] { + set objfile [remote_download host tmpdir/testprog.o]; + } else { + set objfile tmpdir/testprog.o + } + + set exec_output [binutils_run $STRIP "$STRIPFLAGS -K main -K _main $objfile"] + if ![string match "" $exec_output] { + fail $test + return + } + + set exec_output [binutils_run $NM "$NMFLAGS $objfile"] + if {![regexp {^([0-9a-fA-F]+)?[ ]+T main} $exec_output] \ + && ![regexp {^([0-9a-fA-F]+)?[ ]+T _main} $exec_output]} { + fail $test + return + } + + pass $test +} + +strip_test_with_saving_a_symbol + +# Build a final executable. + +proc copy_setup { } { + global srcdir + global subdir + + set res [build_wrapper testglue.o]; + set flags { debug }; + + if { $res != "" } { + lappend flags "additional_flags=[lindex $res 1]"; + set add_libs "testglue.o"; + } else { + set add_libs ""; + } + + if { [target_compile "$srcdir/$subdir/testprog.c $add_libs" tmpdir/testprog executable $flags] != "" } { + return 2 + } + + set result [remote_load target tmpdir/testprog]; + set status [lindex $result 0]; + + if { $status != "pass" } { + perror "unresolved setup, status = $status" + return 3 + } + + return 0 +} + +# Test copying an executable. + +proc copy_executable { prog flags test1 test2 } { + + if [is_remote host] { + set testfile [remote_download host tmpdir/testprog]; + set testcopy copyprog + } else { + set testfile tmpdir/testprog + set testcopy tmpdir/copyprog + } + remote_file host delete $testcopy; + + set exec_output [binutils_run $prog "$flags $testfile $testcopy"] + + if ![string match "" $exec_output] { + fail $test1 + fail $test2 + return + } + + if [is_remote host] { + remote_upload host $testcopy tmpdir/copyprog + } + + set status [remote_exec build "cmp" "tmpdir/testprog tmpdir/copyprog"] + set exec_output [lindex $status 1]; + + if [string match "" $exec_output] then { + pass $test1 + } else { + send_log "$exec_output\n" + verbose "$exec_output" + + # This will fail for many reasons. For example, it will most + # likely fail if a non-GNU linker is used. Therefore, we do + # not insist that it pass. If you are using an assembler and + # linker based on the same BFD as objcopy, it is worth + # investigating to see why this failure occurs. If we are + # cross compiling, we assume that a GNU linker is being used, + # and expect it to succeed. + if {[isnative]} then { + setup_xfail "*-*-*" + } + + # This also fails for mips*-*-elf targets. See elf32-mips.c + # mips_elf_sym_is_global. + setup_xfail "mips*-*-elf" + + fail $test1 + } + + set output [remote_load target tmpdir/copyprog] + set status [lindex $output 0]; + if { $status != "pass" } { + fail $test2 + } else { + pass $test2 + } +} + +# Test stripping an executable + +proc strip_executable { prog flags test } { + global NM + global NMFLAGS + + remote_download build tmpdir/copyprog tmpdir/striprog + if [is_remote host] { + set copyfile [remote_download host tmpdir/striprog]; + } else { + set copyfile tmpdir/striprog + } + + set exec_output [binutils_run $prog "$flags ${copyfile}"] + if ![string match "" $exec_output] { + fail $test + return + } + + if [is_remote host] { + remote_upload host ${copyfile} tmpdir/striprog; + } + + set result [remote_load target tmpdir/striprog] + set status [lindex $result 0]; + if { $status != "pass" } { + fail $test + return + } + + set exec_output [binutils_run $NM "$NMFLAGS ${copyfile}"] + if ![string match "*: no symbols*" $exec_output] { + fail $test + return + } + pass $test +} + +# Test stripping an executable with saving a symbol + +proc strip_executable_with_saving_a_symbol { prog flags test } { + global NM + global NMFLAGS + + remote_download build tmpdir/copyprog tmpdir/striprog + if [is_remote host] { + set copyfile [remote_download host tmpdir/striprog]; + } else { + set copyfile tmpdir/striprog + } + + set exec_output [binutils_run $prog "$flags ${copyfile}"] + if ![string match "" $exec_output] { + fail $test + return + } + + if [is_remote host] { + remote_upload host ${copyfile} tmpdir/striprog; + } + + set result [remote_load target tmpdir/striprog] + set status [lindex $result 0]; + if { $status != "pass" } { + fail $test + return + } + + set exec_output [binutils_run $NM "$NMFLAGS ${copyfile}"] + if {![regexp {^[0-9a-fA-F]+ T main} $exec_output] \ + && ![regexp {^[0-9a-fA-F]+ T _main} $exec_output]} { + fail $test + return + } + pass $test +} + +set test1 "simple objcopy of executable" +set test2 "run objcopy of executable" +set test3 "run stripped executable" +set test4 "run stripped executable with saving a symbol" + +switch [copy_setup] { + "1" { + # do nothing + } + "2" { + untested $test1 + untested $test2 + untested $test3 + untested $test4 + } + "3" { + unresolved $test1 + unresolved $test2 + unresolved $test3 + unresolved $test4 + } + "0" { + copy_executable "$OBJCOPY" "$OBJCOPYFLAGS" "$test1" "$test2" + strip_executable "$STRIP" "$STRIPFLAGS" "$test3" + strip_executable_with_saving_a_symbol "$STRIP" "-K main -K _main $STRIPFLAGS" "$test4" + } +} diff --git a/binutils/testsuite/binutils-all/objdump.exp b/binutils/testsuite/binutils-all/objdump.exp new file mode 100644 index 0000000..7c50f02 --- /dev/null +++ b/binutils/testsuite/binutils-all/objdump.exp @@ -0,0 +1,140 @@ +# Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-dejagnu@prep.ai.mit.edu + +# This file was written by Rob Savoye <rob@cygnus.com> +# and rewritten by Ian Lance Taylor <ian@cygnus.com> + +if ![is_remote host] { + if {[which $OBJDUMP] == 0} then { + perror "$OBJDUMP does not exist" + return + } +} + +send_user "Version [binutil_version $OBJDUMP]" + +# Simple test of objdump -i + +set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -i"] + +set cpus_expected "(a29k|alliant|alpha|arc|arm|convex|d10v|d30v|h8|hppa|i386|i860|i960|m32r|m68k|m88k|mips|mn10200|mn10300|ns32k|powerpc|pyramid|romp|rs6000|sh|sparc|tahoe|v850|vax|we32k|z8k|z8001|z8002)" + +# Make sure the target CPU shows up in the list. +if ![regexp $cpus_expected $target_cpu] { + regsub "^\[(\]" "$cpus_expected" "(${target_cpu}|" cpus_expected; +} + +set want "BFD header file version.*srec.*header .* endian.*, data .* endian.*$cpus_expected" + +if [regexp $want $got] then { + pass "objdump -i" +} else { + fail "objdump -i" +} + +# The remaining tests require a test file. + + +if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then { + return +} +if [is_remote host] { + set testfile [remote_download host tmpdir/bintest.o] +} else { + set testfile tmpdir/bintest.o +} + +# Test objdump -f + +set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -f $testfile"] + +set want "$testfile:\[ \]*file format.*architecture:\[ \]*${cpus_expected}.*HAS_RELOC.*HAS_SYMS" + +if ![regexp $want $got] then { + fail "objdump -f" +} else { + pass "objdump -f" +} + +# Test objdump -h + +set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -h $testfile"] + +set want "$testfile:\[ \]*file format.*Sections.*\[0-9\]+\[ \]+\[^ \]*(text|TEXT|\\\$CODE\\\$)\[^ \]*\[ \]*(\[0-9a-fA-F\]+).*\[0-9\]+\[ \]+\[^ \]*(\\.data|DATA)\[^ \]*\[ \]*(\[0-9a-fA-F\]+)" + +if ![regexp $want $got all text_name text_size data_name data_size] then { + fail "objdump -h" +} else { + verbose "text name is $text_name size is $text_size" + verbose "data name is $data_name size is $data_size" + if {[expr "0x$text_size"] < 8 || [expr "0x$data_size"] < 4} then { + send_log "sizes too small\n" + fail "objdump -h" + } else { + pass "objdump -h" + } +} + +# Test objdump -t + +set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -t $testfile"] + +if [info exists vars] then { unset vars } +while {[regexp "(\[a-z\]*_symbol)(.*)" $got all symbol rest]} { + set vars($symbol) 1 + set got $rest +} + +if {![info exists vars(text_symbol)] \ + || ![info exists vars(data_symbol)] \ + || ![info exists vars(common_symbol)] \ + || ![info exists vars(external_symbol)]} then { + fail "objdump -t" +} else { + pass "objdump -t" +} + +# Test objdump -r + +set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -r $testfile"] + +set want "$testfile:\[ \]*file format.*RELOCATION RECORDS FOR \\\[\[^\]\]*(text|TEXT|\\\$CODE\\\$)\[^\]\]*\\\].*external_symbol" + +if [regexp $want $got] then { + pass "objdump -r" +} else { + fail "objdump -r" +} + +# Test objdump -s + +set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -s $testfile"] + +set want "$testfile:\[ \]*file format.*Contents.*(text|TEXT|\\\$CODE\\\$)\[^0-9\]*\[ \]*\[0-9a-fA-F\]*\[ \]*(00000001|01000000).*Contents.*(data|DATA)\[^0-9\]*\[ \]*\[0-9a-fA-F\]*\[ \]*(00000002|02000000)" + +if [regexp $want $got] then { + pass "objdump -s" +} else { + fail "objdump -s" +} + +# Options which are not tested: -a -d -D -R -T -x -l --stabs +# I don't see any generic way to test any of these other than -a. +# Tests could be written for specific targets, and that should be done +# if specific problems are found. diff --git a/binutils/testsuite/binutils-all/readelf.exp b/binutils/testsuite/binutils-all/readelf.exp new file mode 100644 index 0000000..b2f744c --- /dev/null +++ b/binutils/testsuite/binutils-all/readelf.exp @@ -0,0 +1,217 @@ +# Copyright (C) 1999 Free Software Foundation, Inc. + +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-dejagnu@prep.ai.mit.edu + +# Written by Nick Clifto <nickc@cygnus.com> +# Based on scripts written by Ian Lance Taylor <ian@cygnus.com> +# and Ken Raeburn <raeburn@cygnus.com>. + +# First some helpful procedures, then the tests themselves + +# Return the contents of the filename given +proc file_contents { filename } { + set file [open $filename r] + set contents [read $file] + close $file + return $contents +} + +# regexp_diff, based on simple_diff taken from ld test suite +# compares two files line-by-line +# file1 contains strings, file2 contains regexps and #-comments +# blank lines are ignored in either file +# returns non-zero if differences exist +# +proc regexp_diff { file_1 file_2 } { + + set eof -1 + set end_1 0 + set end_2 0 + set differences 0 + set diff_pass 0 + + if [file exists $file_1] then { + set file_a [open $file_1 r] + } else { + warning "$file_1 doesn't exist" + return 1 + } + + if [file exists $file_2] then { + set file_b [open $file_2 r] + } else { + fail "$file_2 doesn't exist" + close $file_a + return 1 + } + + verbose " Regexp-diff'ing: $file_1 $file_2" 2 + + while { 1 } { + set line_a "" + set line_b "" + while { [string length $line_a] == 0 } { + if { [gets $file_a line_a] == $eof } { + set end_1 1 + break + } + } + while { [string length $line_b] == 0 || [string match "#*" $line_b] } { + if [ string match "#pass" $line_b ] { + set end_2 1 + set diff_pass 1 + break + } + if { [gets $file_b line_b] == $eof } { + set end_2 1 + break + } + } + + if { $diff_pass } { + break + } elseif { $end_1 && $end_2 } { + break + } elseif { $end_1 } { + send_log "extra regexps in $file_2 starting with \"^$line_b$\"\nEOF from $file_1\n" + verbose "extra regexps in $file_2 starting with \"^$line_b$\"\nEOF from $file_1" 3 + set differences 1 + break + } elseif { $end_2 } { + send_log "extra lines in $file_1 starting with \"^$line_a$\"\nEOF from $file_2\n" + verbose "extra lines in $file_1 starting with \"^$line_a$\"\nEOF from $file_2\n" 3 + set differences 1 + break + } else { + verbose "regexp \"^$line_b$\"\nline \"$line_a\"" 3 + if ![regexp "^$line_b$" "$line_a"] { + send_log "regexp_diff match failure\n" + send_log "regexp \"^$line_b$\"\nline \"$line_a\"\n" + set differences 1 + break + } + } + } + + if { $differences == 0 && !$diff_pass && [eof $file_a] != [eof $file_b] } { + send_log "$file_1 and $file_2 are different lengths\n" + verbose "$file_1 and $file_2 are different lengths" 3 + set differences 1 + } + + close $file_a + close $file_b + + return $differences +} + +# Run an individual readelf test. +# Basically readelf is run on the binary_file with the given options. +# Readelf's output is captured and then compared against the contents +# of the regexp_file. + +proc readelf_test { options binary_file regexp_file xfails } { + + global READELF + global READELFFLAGS + global srcdir + global subdir + + send_log "exec $READELF $READELFFLAGS $options $binary_file > readelf.out" + catch "exec $READELF $READELFFLAGS $options $binary_file > readelf.out" got + + if { [llength $xfails] != 0 } then { + setup_xfail $xfails + } + + if ![string match "" $got] then { + send_log $got + fail "readelf $options" + return + } + + if { [regexp_diff readelf.out $srcdir/$subdir/$regexp_file] } then { + fail "readelf $options" + verbose "output is \n[file_contents readelf.out]" 2 + return + } + + pass "readelf $options" +} + + + +# Only ELF based toolchains need readelf. +# For now be paranoid and assume that if ELF is not mentioned +# in the target string, then the target is not an ELF based port. + +if ![istarget "*-*elf"] then { + verbose "$READELF is only intenteded for ELF targets" 2 + return +} + +if ![is_remote host] { + if {[which $READELF] == 0} then { + perror "$READELF does not exist" + return + } +} + +send_user "Version [binutil_version $READELF]" + +# Assemle the test file. +if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then { + perror "unresolved 1" + unresolved "readelf - failed to assemble" + return +} + +if ![is_remote host] { + set tempfile tmpdir/bintest.o; +} else { + set tempfile [remote_download host tmpdir/bintest.o] +} + +# Run the tests +readelf_test -h $tempfile readelf.h {} + +# The v850 fails the next two tests because it creates two special +# sections of its own: .call_table_data and .call_table_text +# The regexp scripts are not expecting these sections... + +readelf_test -S $tempfile readelf.s {v850*-*-*} +readelf_test -s $tempfile readelf.ss {v850*-*-*} +readelf_test -r $tempfile readelf.r {} + + +# Compile the second test file. +if { [target_compile $srcdir/$subdir/testprog.c tmpdir/testprog.o object debug] != "" } { + untested "readelf -w" + return +} + +if [is_remote host] { + set tempfile [remote_download host tmpdir/testprog.o]; +} else { + set tempfile tmpdir/testprog.o +} + +# The xfail targets here do not default to DWARF2 format debug information +# The symptom is that the output of 'readelf -wi' is empty. + +readelf_test -wi $tempfile readelf.wi {v850*-*-*} diff --git a/binutils/testsuite/binutils-all/readelf.h b/binutils/testsuite/binutils-all/readelf.h new file mode 100644 index 0000000..555afe9 --- /dev/null +++ b/binutils/testsuite/binutils-all/readelf.h @@ -0,0 +1,16 @@ +ELF Header: + Magic: 7f 45 4c 46 0[12] 0[12] 01 00 00 00 00 00 00 00 00 00 + Type: REL \(Relocatable file\) + Machine: .* + Version: 0x1 + Data: ELFDATA.* endian\) + Entry point address: 0x0 + Start of program headers: 0 \(bytes into file\) + Start of section headers: .* \(bytes into file\) + Flags: .* + Size of this header: .* \(bytes\) + Size of program headers: 0 \(bytes\) + Number of program headers: 0 + Size of section headers: .* \(bytes\) + Number of section headers: .* + Section header string table index: .* diff --git a/binutils/testsuite/binutils-all/readelf.r b/binutils/testsuite/binutils-all/readelf.r new file mode 100644 index 0000000..4bea721 --- /dev/null +++ b/binutils/testsuite/binutils-all/readelf.r @@ -0,0 +1,4 @@ + +Relocation section '.rel.*text' at offset 0x.* contains 1 entries: + Offset Info Type Symbol's Value Symbol's Name.* + 00000004 00.* R_.* 00000000 external_symbol.* diff --git a/binutils/testsuite/binutils-all/readelf.s b/binutils/testsuite/binutils-all/readelf.s new file mode 100644 index 0000000..58b1245 --- /dev/null +++ b/binutils/testsuite/binutils-all/readelf.s @@ -0,0 +1,13 @@ +There are .* section headers, starting at offset .*: + +Section Headers: + \[Nr\] Name Type Addr Off Size ES Flg Lk Inf Al + \[ 0\] NULL 00000000 000000 000000 00 0 0 0 + \[ 1\] .text PROGBITS 00000000 000034 000008 00 AX 0 0 . + \[ 2\] .rel.+text +REL. +0+ 0+.* 00000. 0. . 1 4 + \[ 3\] .data PROGBITS 00000000 00003c 000004 00 WA 0 0 . + \[ 4\] .bss NOBITS 00000000 000040 000000 00 WA 0 0 . + \[ 5\] .shstrtab STRTAB 00000000 000040 0000.* 00 0 0 . + \[ 6\] .symtab SYMTAB 00000000 0+.* 0+.* 10 7 6 4 + \[ 7\] .strtab STRTAB 00000000 0+.* 0+.* 00 0 0 1 + diff --git a/binutils/testsuite/binutils-all/readelf.ss b/binutils/testsuite/binutils-all/readelf.ss new file mode 100644 index 0000000..3760b38 --- /dev/null +++ b/binutils/testsuite/binutils-all/readelf.ss @@ -0,0 +1,13 @@ + +Symbol table '.symtab' contains .* entries: + Num: Value Size Type Bind Ot Ndx Name + 0: 0 0 NOTYPE LOCAL 0 UND + 1: 0 0 SECTION LOCAL 0 1 + 2: 0 0 SECTION LOCAL 0 3 + 3: 0 0 SECTION LOCAL 0 4 + 4: 0 0 NOTYPE LOCAL 0 1 static_text_symbol + 5: 0 0 NOTYPE LOCAL 0 3 static_data_symbol + .: 0 0 NOTYPE GLOBAL 0 1 text_symbol + .: 0 0 NOTYPE GLOBAL 0 UND external_symbol + .*: 0 0 NOTYPE GLOBAL 0 3 data_symbol + .*: 4 4 OBJECT GLOBAL 0 COM common_symbol diff --git a/binutils/testsuite/binutils-all/readelf.wi b/binutils/testsuite/binutils-all/readelf.wi new file mode 100644 index 0000000..3cb2ecc --- /dev/null +++ b/binutils/testsuite/binutils-all/readelf.wi @@ -0,0 +1,78 @@ +The section .debug_info contains: + + Compilation Unit: + Length: .* + Version: 2 + Abbrev Offset: 0 + Pointer Size: 4 + Abbrev Number: 1 \(DW_TAG_compile_unit\) + DW_AT_name : .*/testprog.c + DW_AT_comp_dir : .*/binutils + DW_AT_producer : GNU C .* + DW_AT_language : 1 \(ANSI C\) + DW_AT_low_pc : 0 + DW_AT_high_pc : .* + DW_AT_stmt_list : 0 + Abbrev Number: 2 \(DW_TAG_subprogram\) + DW_AT_external : 1 + DW_AT_name : fn + DW_AT_decl_file : 1 + DW_AT_decl_line : a + DW_AT_type : .* + DW_AT_low_pc : 0 + DW_AT_high_pc : .* + DW_AT_frame_base : 1 byte block: .* + Abbrev Number: 3 \(DW_TAG_base_type\) + DW_AT_name : int + DW_AT_byte_size : 4 + DW_AT_encoding : 5 \(signed\) + Abbrev Number: 4 \(DW_TAG_subprogram\) + DW_AT_sibling : .* + DW_AT_external : 1 + DW_AT_name : main + DW_AT_decl_file : 1 + DW_AT_decl_line : 10 + DW_AT_type : .* + DW_AT_low_pc : .* + DW_AT_high_pc : .* + DW_AT_frame_base : 1 byte block: .* + Abbrev Number: 5 \(DW_TAG_lexical_block\) + DW_AT_low_pc : .* + DW_AT_high_pc : .* + + Extra data at end of comp unit: + .*: Abbrev Number: 6 \(DW_TAG_variable\) + DW_AT_name : common + DW_AT_decl_file : 1 + DW_AT_decl_line : 3 + DW_AT_type : .* + DW_AT_external : 1 + DW_AT_location : 5 byte block: 3 . 0 0 0 \(DW_OP_addr: 0\) + .*: Abbrev Number: 6 \(DW_TAG_variable\) + DW_AT_name : global + DW_AT_decl_file : 1 + DW_AT_decl_line : 4 + DW_AT_type : .* + DW_AT_external : 1 + DW_AT_location : 5 byte block: 3 . 0 0 0 \(DW_OP_addr: 0\) + .*: Abbrev Number: 7 \(DW_TAG_variable\) + DW_AT_name : local + DW_AT_decl_file : 1 + DW_AT_decl_line : 5 + DW_AT_type : .* + DW_AT_location : 5 byte block: 3 . 0 0 . \(DW_OP_addr: .\) + .*: Abbrev Number: 8 \(DW_TAG_array_type\) + DW_AT_sibling : .* + DW_AT_type : .* + .*: Abbrev Number: 9 \(DW_TAG_subrange_type\) + DW_AT_upper_bound : 6 + .*: Abbrev Number: 3 \(DW_TAG_base_type\) + DW_AT_name : char + DW_AT_byte_size : 1 + DW_AT_encoding : . \(.* char\) + .*: Abbrev Number: 7 \(DW_TAG_variable\) + DW_AT_name : string + DW_AT_decl_file : 1 + DW_AT_decl_line : 6 + DW_AT_type : .* + DW_AT_location : 5 byte block: 3 . 0 0 . \(DW_OP_addr: .\) diff --git a/binutils/testsuite/binutils-all/size.exp b/binutils/testsuite/binutils-all/size.exp new file mode 100644 index 0000000..b908c91 --- /dev/null +++ b/binutils/testsuite/binutils-all/size.exp @@ -0,0 +1,78 @@ +# Copyright (C) 1993, 1994, 1996, 1997 Free Software Foundation, Inc. + +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-dejagnu@prep.ai.mit.edu + +# This file was written by Rob Savoye <rob@cygnus.com> +# and rewritten by Ian Lance Taylor <ian@cygnus.com> + +if ![is_remote host] { + if {[which $SIZE] == 0} then { + perror "$SIZE does not exist" + return + } +} + +send_user "Version [binutil_version $SIZE]" + + +if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then { + return +} + +if [is_remote host] { + set testfile [remote_download host tmpdir/bintest.o] +} else { + set testfile tmpdir/bintest.o +} + +set dec "\[0-9\]+" +set hex "\[0-9a-fA-F\]+" + +# Test size with no arguments + +set got [binutils_run $SIZE "$SIZEFLAGS $testfile"] + +set want "($dec)\[ \]+($dec)\[ \]+($dec)\[ \]+($dec)\[ \]+($hex)\[ \]+${testfile}" + +if ![regexp $want $got all text data bss dtot hextot] then { + fail "size (no arguments)" +} else { + if {$text < 8 || $data < 4} then { + fail "size (no arguments)" + } else { + pass "size (no arguments)" + } +} + +# Test size -A + +set got [binutils_run $SIZE "$SIZEFLAGS -A ${testfile}"] + +set want "${testfile}.*(text|TEXT)\[^\n\r\]*\[ \]($dec)\[ \]+$dec.*(\\.data|DATA)\[^\n\r\]*\[ \]($dec)\[ \]+$dec" + +if ![regexp $want $got all textname textsize dataname datasize] then { + fail "size -A" +} else { + verbose "text size: $textsize" + verbose "data size: $datasize" + if {$textsize < 8 || $datasize < 4} then { + fail "size -A" + } else { + pass "size -A" + } +} diff --git a/binutils/testsuite/binutils-all/testprog.c b/binutils/testsuite/binutils-all/testprog.c new file mode 100644 index 0000000..210656b --- /dev/null +++ b/binutils/testsuite/binutils-all/testprog.c @@ -0,0 +1,28 @@ +/* This program is used to test objcopy and strip. */ + +int common; +int global = 1; +static int local = 2; +static char string[] = "string"; + +int +fn () +{ + return 3; +} + +int +main () +{ + if (common != 0 + || global != 1 + || local != 2 + || strcmp (string, "string") != 0) + { + printf ("failed\n"); + exit (1); + } + + printf ("ok\n"); + exit (0); +} diff --git a/binutils/testsuite/config/default.exp b/binutils/testsuite/config/default.exp new file mode 100644 index 0000000..2a2802e --- /dev/null +++ b/binutils/testsuite/config/default.exp @@ -0,0 +1,88 @@ +# Copyright (C) 1993, 1994, 1996, 1997 Free Software Foundation, Inc. + +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-dejagnu@prep.ai.mit.edu + +# This file was written by Rob Savoye. (rob@cygnus.com) + +load_lib util-defs.exp +load_lib utils-lib.exp + +if ![info exists NM] then { + set NM [findfile $base_dir/nm-new $base_dir/nm-new [transform nm]] +} +if ![info exists NMFLAGS] then { + set NMFLAGS "" +} + +if ![info exists SIZE] then { + set SIZE [findfile $base_dir/size] +} +if ![info exists SIZEFLAGS] then { + set SIZEFLAGS "" +} + +if ![info exists OBJDUMP] then { + set OBJDUMP [findfile $base_dir/objdump] +} +if ![info exists OBJDUMPFLAGS] then { + set OBJDUMPFLAGS "" +} + +if ![info exists OBJCOPY] then { + set OBJCOPY [findfile $base_dir/objcopy] +} +if ![info exists OBJCOPYFLAGS] then { + set OBJCOPYFLAGS "" +} + +if ![info exists AR] then { + set AR [findfile $base_dir/ar] +} + +if ![info exists STRIP] then { + set STRIP [findfile $base_dir/strip-new $base_dir/strip-new [transform strip]] +} +if ![info exists STRIPFLAGS] then { + set STRIPFLAGS "" +} + +if ![info exists READELF] then { + set READELF [findfile $base_dir/readelf] +} +if ![info exists READELFFLAGS] then { + set READELFFLAGS "" +} + +if ![file isdirectory tmpdir] {catch "exec mkdir tmpdir" status} + +# +# binutils_run +# run a program, returning the output +# sets binutils_run_failed if the program does not exist +# +proc binutils_run { prog progargs } { + default_binutils_run $prog $progargs +} + +# +# binutils_assemble +# assemble a file +# +proc binutils_assemble { source object } { + default_binutils_assemble $source $object +} diff --git a/binutils/testsuite/config/hppa.sed b/binutils/testsuite/config/hppa.sed new file mode 100644 index 0000000..d8607d8 --- /dev/null +++ b/binutils/testsuite/config/hppa.sed @@ -0,0 +1,4 @@ +s/# Old OSF sed blows up if you have a sed command starting with "#"// +s/# Avoid it by putting the comments within real sed commands.// +s/# Fix the definition of common_symbol to be correct for the PA assebmlers.// +s/ \.comm common_symbol,4/common_symbol .comm 4/ diff --git a/binutils/testsuite/lib/utils-lib.exp b/binutils/testsuite/lib/utils-lib.exp new file mode 100644 index 0000000..e27f217 --- /dev/null +++ b/binutils/testsuite/lib/utils-lib.exp @@ -0,0 +1,161 @@ +# Copyright (C) 1993, 1994, 1997 Free Software Foundation, Inc. + +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-dejagnu@prep.ai.mit.edu + +# This file was written by Rob Savoye <rob@cygnus.com> +# and extended by Ian Lance Taylor <ian@cygnus.com> + +proc binutil_version { prog } { + if ![is_remote host] { + set path [which $prog]; + if {$path == 0} then { + perror "$prog can't be run, file not found." + return "" + } + } else { + set path $prog + } + set state [remote_exec host $prog --version]; + set tmp "[lindex $state 1]\n"; + # Should find a way to discard constant parts, keep whatever's + # left, so the version string could be almost anything at all... + regexp "\[^\n\]* (cygnus-|)(\[-0-9.a-zA-Z-\]+)\[\r\n\].*" "$tmp" version cyg number + if ![info exists number] then { + return "$path (no version number)\n" + } + return "$path $number\n" +} + +# +# default_binutils_run +# run a program, returning the output +# sets binutils_run_failed if the program does not exist +# +proc default_binutils_run { prog progargs } { + global binutils_run_failed + global host_triplet + + set binutils_run_failed 0 + + if ![is_remote host] { + if {[which $prog] == 0} then { + perror "$prog does not exist" + set binutils_run_failed 1 + return "" + } + } + + send_log "$prog $progargs\n" + verbose "$prog $progargs" + + # Gotta quote dollar-signs because they get mangled by the + # shell otherwise. + regsub -all "\\$" "$progargs" "\\$" progargs + + set state [remote_exec host $prog $progargs] + set exec_output [prune_warnings [lindex $state 1]]; + if {![string match "" $exec_output]} then { + send_log "$exec_output\n" + verbose "$exec_output" + } + return $exec_output +} + +# +# default_binutils_assemble +# assemble a file +# +proc default_binutils_assemble { source object } { + global srcdir + global host_triplet + + # The HPPA assembler syntax is a little different than most, to make + # the test source file assemble we need to run it through sed. + # + # This is a hack in that it won't scale well if other targets need + # similar transformations to assemble. We'll generalize the hack + # if/when other targets need similar handling. + if [istarget "hppa*-*-*" ] then { + send_log "sed -f $srcdir/config/hppa.sed < $source > asm.s\n" + verbose "sed -f $srcdir/config/hppa.sed < $source > asm.s" + catch "exec sed -f $srcdir/config/hppa.sed < $source > asm.s"; + set source asm.s + } + + set exec_output [target_assemble $source $object ""]; + set exec_output [prune_warnings $exec_output] + + if [string match "" $exec_output] { + return 1 + } else { + send_log "$exec_output\n" + verbose "$exec_output" + perror "$source: assembly failed" + return 0 + } +} + +if ![info exists target_assemble] { +# +# Stolen from dejagnu/lib/target.exp--please remove after 1/1/98. +# +uplevel #0 { + proc target_assemble { source destfile flags } { + return [default_target_assemble $source $destfile $flags]; + } + + proc default_target_assemble { source destfile flags } { + global AS_FOR_TARGET; + global ASFLAGS_FOR_TARGET; + + if [info exists AS_FOR_TARGET] { + set AS "$AS_FOR_TARGET"; + } else { + if ![board_info target exists assembler] { + set AS [find_gas]; + } else { + set AS [board_info target assembler]; + } + } + + if [info exists ASFLAGS_FOR_TARGET] { + append flags " $ASFLAGS_FOR_TARGET"; + } + + if [is_remote host] { + set source [remote_download host $source]; + set dest "a.out" + } else { + set dest $destfile + } + set status [remote_exec host "$AS $source $flags -o $dest"] + if [is_remote host] { + remote_upload host $dest $destfile + } + + set comp_output [prune_warnings [lindex $status 1]]; + if { [lindex $status 0] != 0 } { + verbose -log "assembler exited with status [lindex $status 0]"; + } + if { [lindex $status 1] != "" } { + verbose -log "assembler output is:\n[lindex $status 1]" 2; + } + return ${comp_output}; +} +} +} diff --git a/binutils/version.c b/binutils/version.c new file mode 100644 index 0000000..1055939 --- /dev/null +++ b/binutils/version.c @@ -0,0 +1,44 @@ +/* version.c -- binutils version information + Copyright 1991, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +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, 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <stdio.h> +#include "bfd.h" +#include "bucomm.h" + +/* This is the version numbers for the binutils. They all change in + lockstep -- it's easier that way. */ + +const char *program_version = VERSION; + +/* Print the version number and copyright information, and exit. This + implements the --version option for the various programs. */ + +void +print_version (name) + const char *name; +{ + /* This output is intended to follow the GNU standards document. */ + /* xgettext:c-format */ + printf ("GNU %s %s\n", name, program_version); + printf (_("Copyright 1997, 1998, 1999 Free Software Foundation, Inc.\n")); + printf (_("\ +This program is free software; you may redistribute it under the terms of\n\ +the GNU General Public License. This program has absolutely no warranty.\n")); + exit (0); +} diff --git a/binutils/windres.c b/binutils/windres.c new file mode 100644 index 0000000..7de28c2 --- /dev/null +++ b/binutils/windres.c @@ -0,0 +1,947 @@ +/* windres.c -- a program to manipulate Windows resources + Copyright 1997, 1998, 1999 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Cygnus Support. + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* This program can read and write Windows resources in various + formats. In particular, it can act like the rc resource compiler + program, and it can act like the cvtres res to COFF conversion + program. + + It is based on information taken from the following sources: + + * Microsoft documentation. + + * The rcl program, written by Gunther Ebert + <gunther.ebert@ixos-leipzig.de>. + + * The res2coff program, written by Pedro A. Aranda <paag@tid.es>. + + */ + +#include "bfd.h" +#include "getopt.h" +#include "bucomm.h" +#include "libiberty.h" +#include "obstack.h" +#include "windres.h" + +#include <assert.h> +#include <ctype.h> +#include <time.h> + +/* An enumeration of format types. */ + +enum res_format +{ + /* Unknown format. */ + RES_FORMAT_UNKNOWN, + /* Textual RC file. */ + RES_FORMAT_RC, + /* Binary RES file. */ + RES_FORMAT_RES, + /* COFF file. */ + RES_FORMAT_COFF +}; + +/* A structure used to map between format types and strings. */ + +struct format_map +{ + const char *name; + enum res_format format; +}; + +/* A mapping between names and format types. */ + +static const struct format_map format_names[] = +{ + { "rc", RES_FORMAT_RC }, + { "res", RES_FORMAT_RES }, + { "coff", RES_FORMAT_COFF }, + { NULL, RES_FORMAT_UNKNOWN } +}; + +/* A mapping from file extensions to format types. */ + +static const struct format_map format_fileexts[] = +{ + { "rc", RES_FORMAT_RC }, + { "res", RES_FORMAT_RES }, + { "exe", RES_FORMAT_COFF }, + { "obj", RES_FORMAT_COFF }, + { "o", RES_FORMAT_COFF }, + { NULL, RES_FORMAT_UNKNOWN } +}; + +/* A list of include directories. */ + +struct include_dir +{ + struct include_dir *next; + char *dir; +}; + +static struct include_dir *include_dirs; + +/* Long options. */ + +/* 150 isn't special; it's just an arbitrary non-ASCII char value. */ + +#define OPTION_DEFINE 150 +#define OPTION_HELP (OPTION_DEFINE + 1) +#define OPTION_INCLUDE_DIR (OPTION_HELP + 1) +#define OPTION_LANGUAGE (OPTION_INCLUDE_DIR + 1) +#define OPTION_PREPROCESSOR (OPTION_LANGUAGE + 1) +#define OPTION_VERSION (OPTION_PREPROCESSOR + 1) +#define OPTION_YYDEBUG (OPTION_VERSION + 1) + +static const struct option long_options[] = +{ + {"define", required_argument, 0, OPTION_DEFINE}, + {"help", no_argument, 0, OPTION_HELP}, + {"include-dir", required_argument, 0, OPTION_INCLUDE_DIR}, + {"input-format", required_argument, 0, 'I'}, + {"language", required_argument, 0, OPTION_LANGUAGE}, + {"output-format", required_argument, 0, 'O'}, + {"preprocessor", required_argument, 0, OPTION_PREPROCESSOR}, + {"target", required_argument, 0, 'F'}, + {"version", no_argument, 0, OPTION_VERSION}, + {"yydebug", no_argument, 0, OPTION_YYDEBUG}, + {0, no_argument, 0, 0} +}; + +/* Static functions. */ + +static void res_init PARAMS ((void)); +static int extended_menuitems PARAMS ((const struct menuitem *)); +static enum res_format format_from_name PARAMS ((const char *)); +static enum res_format format_from_filename PARAMS ((const char *, int)); +static void usage PARAMS ((FILE *, int)); +static int cmp_res_entry PARAMS ((const PTR, const PTR)); +static struct res_directory *sort_resources PARAMS ((struct res_directory *)); + +/* When we are building a resource tree, we allocate everything onto + an obstack, so that we can free it all at once if we want. */ + +#define obstack_chunk_alloc xmalloc +#define obstack_chunk_free free + +/* The resource building obstack. */ + +static struct obstack res_obstack; + +/* Initialize the resource building obstack. */ + +static void +res_init () +{ + obstack_init (&res_obstack); +} + +/* Allocate space on the resource building obstack. */ + +PTR +res_alloc (bytes) + size_t bytes; +{ + return (PTR) obstack_alloc (&res_obstack, bytes); +} + +/* We also use an obstack to save memory used while writing out a set + of resources. */ + +static struct obstack reswr_obstack; + +/* Initialize the resource writing obstack. */ + +static void +reswr_init () +{ + obstack_init (&reswr_obstack); +} + +/* Allocate space on the resource writing obstack. */ + +PTR +reswr_alloc (bytes) + size_t bytes; +{ + return (PTR) obstack_alloc (&reswr_obstack, bytes); +} + +/* Open a file using the include directory search list. */ + +FILE * +open_file_search (filename, mode, errmsg, real_filename) + const char *filename; + const char *mode; + const char *errmsg; + char **real_filename; +{ + FILE *e; + struct include_dir *d; + + e = fopen (filename, mode); + if (e != NULL) + { + *real_filename = xstrdup (filename); + return e; + } + + if (errno == ENOENT) + { + for (d = include_dirs; d != NULL; d = d->next) + { + char *n; + + n = (char *) xmalloc (strlen (d->dir) + strlen (filename) + 2); + sprintf (n, "%s/%s", d->dir, filename); + e = fopen (n, mode); + if (e != NULL) + { + *real_filename = n; + return e; + } + + if (errno != ENOENT) + break; + } + } + + fatal (_("can't open %s `%s': %s"), errmsg, filename, strerror (errno)); + + /* Return a value to avoid a compiler warning. */ + return NULL; +} + +/* Compare two resource ID's. We consider name entries to come before + numeric entries, because that is how they appear in the COFF .rsrc + section. */ + +int +res_id_cmp (a, b) + struct res_id a; + struct res_id b; +{ + if (! a.named) + { + if (b.named) + return 1; + if (a.u.id > b.u.id) + return 1; + else if (a.u.id < b.u.id) + return -1; + else + return 0; + } + else + { + unichar *as, *ase, *bs, *bse; + + if (! b.named) + return -1; + + as = a.u.n.name; + ase = as + a.u.n.length; + bs = b.u.n.name; + bse = bs + b.u.n.length; + + while (as < ase) + { + int i; + + if (bs >= bse) + return 1; + i = (int) *as - (int) *bs; + if (i != 0) + return i; + ++as; + ++bs; + } + + if (bs < bse) + return -1; + + return 0; + } +} + +/* Print a resource ID. */ + +void +res_id_print (stream, id, quote) + FILE *stream; + struct res_id id; + int quote; +{ + if (! id.named) + fprintf (stream, "%lu", id.u.id); + else + { + if (quote) + putc ('"', stream); + unicode_print (stream, id.u.n.name, id.u.n.length); + if (quote) + putc ('"', stream); + } +} + +/* Print a list of resource ID's. */ + +void +res_ids_print (stream, cids, ids) + FILE *stream; + int cids; + const struct res_id *ids; +{ + int i; + + for (i = 0; i < cids; i++) + { + res_id_print (stream, ids[i], 1); + if (i + 1 < cids) + fprintf (stream, ": "); + } +} + +/* Convert an ASCII string to a resource ID. */ + +void +res_string_to_id (res_id, string) + struct res_id *res_id; + const char *string; +{ + res_id->named = 1; + unicode_from_ascii (&res_id->u.n.length, &res_id->u.n.name, string); +} + +/* Define a resource. The arguments are the resource tree, RESOURCES, + and the location at which to put it in the tree, CIDS and IDS. + This returns a newly allocated res_resource structure, which the + caller is expected to initialize. If DUPOK is non-zero, then if a + resource with this ID exists, it is returned. Otherwise, a warning + is issued, and a new resource is created replacing the existing + one. */ + +struct res_resource * +define_resource (resources, cids, ids, dupok) + struct res_directory **resources; + int cids; + const struct res_id *ids; + int dupok; +{ + struct res_entry *re = NULL; + int i; + + assert (cids > 0); + for (i = 0; i < cids; i++) + { + struct res_entry **pp; + + if (*resources == NULL) + { + static unsigned long timeval; + + /* Use the same timestamp for every resource created in a + single run. */ + if (timeval == 0) + timeval = time (NULL); + + *resources = ((struct res_directory *) + res_alloc (sizeof **resources)); + (*resources)->characteristics = 0; + (*resources)->time = timeval; + (*resources)->major = 0; + (*resources)->minor = 0; + (*resources)->entries = NULL; + } + + for (pp = &(*resources)->entries; *pp != NULL; pp = &(*pp)->next) + if (res_id_cmp ((*pp)->id, ids[i]) == 0) + break; + + if (*pp != NULL) + re = *pp; + else + { + re = (struct res_entry *) res_alloc (sizeof *re); + re->next = NULL; + re->id = ids[i]; + if ((i + 1) < cids) + { + re->subdir = 1; + re->u.dir = NULL; + } + else + { + re->subdir = 0; + re->u.res = NULL; + } + + *pp = re; + } + + if ((i + 1) < cids) + { + if (! re->subdir) + { + fprintf (stderr, "%s: ", program_name); + res_ids_print (stderr, i, ids); + fprintf (stderr, _(": expected to be a directory\n")); + xexit (1); + } + + resources = &re->u.dir; + } + } + + if (re->subdir) + { + fprintf (stderr, "%s: ", program_name); + res_ids_print (stderr, cids, ids); + fprintf (stderr, _(": expected to be a leaf\n")); + xexit (1); + } + + if (re->u.res != NULL) + { + if (dupok) + return re->u.res; + + fprintf (stderr, _("%s: warning: "), program_name); + res_ids_print (stderr, cids, ids); + fprintf (stderr, _(": duplicate value\n")); + } + + re->u.res = ((struct res_resource *) + res_alloc (sizeof (struct res_resource))); + + re->u.res->type = RES_TYPE_UNINITIALIZED; + memset (&re->u.res->res_info, 0, sizeof (struct res_res_info)); + memset (&re->u.res->coff_info, 0, sizeof (struct res_coff_info)); + + return re->u.res; +} + +/* Define a standard resource. This is a version of define_resource + that just takes type, name, and language arguments. */ + +struct res_resource * +define_standard_resource (resources, type, name, language, dupok) + struct res_directory **resources; + int type; + struct res_id name; + int language; + int dupok; +{ + struct res_id a[3]; + + a[0].named = 0; + a[0].u.id = type; + a[1] = name; + a[2].named = 0; + a[2].u.id = language; + return define_resource (resources, 3, a, dupok); +} + +/* Comparison routine for resource sorting. */ + +static int +cmp_res_entry (p1, p2) + const PTR p1; + const PTR p2; +{ + const struct res_entry **re1, **re2; + + re1 = (const struct res_entry **) p1; + re2 = (const struct res_entry **) p2; + return res_id_cmp ((*re1)->id, (*re2)->id); +} + +/* Sort the resources. */ + +static struct res_directory * +sort_resources (resdir) + struct res_directory *resdir; +{ + int c, i; + struct res_entry *re; + struct res_entry **a; + + if (resdir->entries == NULL) + return resdir; + + c = 0; + for (re = resdir->entries; re != NULL; re = re->next) + ++c; + + /* This is a recursive routine, so using xmalloc is probably better + than alloca. */ + a = (struct res_entry **) xmalloc (c * sizeof (struct res_entry *)); + + for (i = 0, re = resdir->entries; re != NULL; re = re->next, i++) + a[i] = re; + + qsort (a, c, sizeof (struct res_entry *), cmp_res_entry); + + resdir->entries = a[0]; + for (i = 0; i < c - 1; i++) + a[i]->next = a[i + 1]; + a[i]->next = NULL; + + free (a); + + /* Now sort the subdirectories. */ + + for (re = resdir->entries; re != NULL; re = re->next) + if (re->subdir) + re->u.dir = sort_resources (re->u.dir); + + return resdir; +} + +/* Return whether the dialog resource DIALOG is a DIALOG or a + DIALOGEX. */ + +int +extended_dialog (dialog) + const struct dialog *dialog; +{ + const struct dialog_control *c; + + if (dialog->ex != NULL) + return 1; + + for (c = dialog->controls; c != NULL; c = c->next) + if (c->data != NULL || c->help != 0) + return 1; + + return 0; +} + +/* Return whether MENUITEMS are a MENU or a MENUEX. */ + +int +extended_menu (menu) + const struct menu *menu; +{ + return extended_menuitems (menu->items); +} + +static int +extended_menuitems (menuitems) + const struct menuitem *menuitems; +{ + const struct menuitem *mi; + + for (mi = menuitems; mi != NULL; mi = mi->next) + { + if (mi->help != 0 || mi->state != 0) + return 1; + if (mi->popup != NULL && mi->id != 0) + return 1; + if ((mi->type + & ~ (MENUITEM_CHECKED + | MENUITEM_GRAYED + | MENUITEM_HELP + | MENUITEM_INACTIVE + | MENUITEM_MENUBARBREAK + | MENUITEM_MENUBREAK)) + != 0) + return 1; + if (mi->popup != NULL) + { + if (extended_menuitems (mi->popup)) + return 1; + } + } + + return 0; +} + +/* Convert a string to a format type, or exit if it can't be done. */ + +static enum res_format +format_from_name (name) + const char *name; +{ + const struct format_map *m; + + for (m = format_names; m->name != NULL; m++) + if (strcasecmp (m->name, name) == 0) + break; + + if (m->name == NULL) + { + fprintf (stderr, _("%s: unknown format type `%s'\n"), program_name, name); + fprintf (stderr, _("%s: supported formats:"), program_name); + for (m = format_names; m->name != NULL; m++) + fprintf (stderr, " %s", m->name); + fprintf (stderr, "\n"); + xexit (1); + } + + return m->format; +} + +/* Work out a format type given a file name. If INPUT is non-zero, + it's OK to look at the file itself. */ + +static enum res_format +format_from_filename (filename, input) + const char *filename; + int input; +{ + const char *ext; + FILE *e; + unsigned char b1, b2, b3, b4, b5; + int magic; + + /* If we have an extension, see if we recognize it as implying a + particular format. */ + ext = strrchr (filename, '.'); + if (ext != NULL) + { + const struct format_map *m; + + ++ext; + for (m = format_fileexts; m->name != NULL; m++) + if (strcasecmp (m->name, ext) == 0) + return m->format; + } + + /* If we don't recognize the name of an output file, assume it's a + COFF file. */ + + if (! input) + return RES_FORMAT_COFF; + + /* Read the first few bytes of the file to see if we can guess what + it is. */ + + e = fopen (filename, FOPEN_RB); + if (e == NULL) + fatal ("%s: %s", filename, strerror (errno)); + + b1 = getc (e); + b2 = getc (e); + b3 = getc (e); + b4 = getc (e); + b5 = getc (e); + + fclose (e); + + /* A PE executable starts with 0x4d 0x5a. */ + if (b1 == 0x4d && b2 == 0x5a) + return RES_FORMAT_COFF; + + /* A COFF .o file starts with a COFF magic number. */ + magic = (b2 << 8) | b1; + switch (magic) + { + case 0x14c: /* i386 */ + case 0x166: /* MIPS */ + case 0x184: /* Alpha */ + case 0x268: /* 68k */ + case 0x1f0: /* PowerPC */ + case 0x290: /* PA */ + return RES_FORMAT_COFF; + } + + /* A RES file starts with 0x0 0x0 0x0 0x0 0x20 0x0 0x0 0x0. */ + if (b1 == 0 && b2 == 0 && b3 == 0 && b4 == 0 && b5 == 0x20) + return RES_FORMAT_RES; + + /* If every character is printable or space, assume it's an RC file. */ + if ((isprint (b1) || isspace (b1)) + && (isprint (b2) || isspace (b2)) + && (isprint (b3) || isspace (b3)) + && (isprint (b4) || isspace (b4)) + && (isprint (b5) || isspace (b5))) + return RES_FORMAT_RC; + + /* Otherwise, we give up. */ + fatal (_("can not determine type of file `%s'; use the -I option"), + filename); + + /* Return something to silence the compiler warning. */ + return RES_FORMAT_UNKNOWN; +} + +/* Print a usage message and exit. */ + +static void +usage (stream, status) + FILE *stream; + int status; +{ + fprintf (stream, _("Usage: %s [options] [input-file] [output-file]\n"), + program_name); + fprintf (stream, _("\ +Options:\n\ + -i FILE, --input FILE Name input file\n\ + -o FILE, --output FILE Name output file\n\ + -I FORMAT, --input-format FORMAT\n\ + Specify input format\n\ + -O FORMAT, --output-format FORMAT\n\ + Specify output format\n\ + -F TARGET, --target TARGET Specify COFF target\n\ + --preprocessor PROGRAM Program to use to preprocess rc file\n\ + --include-dir DIR Include directory when preprocessing rc file\n\ + --define SYM[=VAL] Define SYM when preprocessing rc file\n\ + --language VAL Set language when reading rc file\n")); +#ifdef YYDEBUG + fprintf (stream, _("\ + --yydebug Turn on parser debugging\n")); +#endif + fprintf (stream, _("\ + --help Print this help message\n\ + --version Print version information\n")); + fprintf (stream, _("\ +FORMAT is one of rc, res, or coff, and is deduced from the file name\n\ +extension if not specified. A single file name is an input file.\n\ +No input-file is stdin, default rc. No output-file is stdout, default rc.\n")); + list_supported_targets (program_name, stream); + if (status == 0) + fprintf (stream, _("Report bugs to bug-gnu-utils@gnu.org\n")); + exit (status); +} + +/* The main function. */ + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + char *input_filename; + char *output_filename; + enum res_format input_format; + enum res_format output_format; + char *target; + char *preprocessor; + char *preprocargs; + int language; + struct res_directory *resources; + +#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) + setlocale (LC_MESSAGES, ""); +#endif + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + + program_name = argv[0]; + xmalloc_set_program_name (program_name); + + bfd_init (); + set_default_bfd_target (); + + res_init (); + + input_filename = NULL; + output_filename = NULL; + input_format = RES_FORMAT_UNKNOWN; + output_format = RES_FORMAT_UNKNOWN; + target = NULL; + preprocessor = NULL; + preprocargs = NULL; + language = -1; + + while ((c = getopt_long (argc, argv, "i:o:I:O:F:", long_options, + (int *) 0)) != EOF) + { + switch (c) + { + case 'i': + input_filename = optarg; + break; + + case 'o': + output_filename = optarg; + break; + + case 'I': + input_format = format_from_name (optarg); + break; + + case 'O': + output_format = format_from_name (optarg); + break; + + case 'F': + target = optarg; + break; + + case OPTION_PREPROCESSOR: + preprocessor = optarg; + break; + + case OPTION_DEFINE: + if (preprocargs == NULL) + { + preprocargs = xmalloc (strlen (optarg) + 3); + sprintf (preprocargs, "-D%s", optarg); + } + else + { + char *n; + + n = xmalloc (strlen (preprocargs) + strlen (optarg) + 4); + sprintf (n, "%s -D%s", preprocargs, optarg); + free (preprocargs); + preprocargs = n; + } + break; + + case OPTION_INCLUDE_DIR: + if (preprocargs == NULL) + { + preprocargs = xmalloc (strlen (optarg) + 3); + sprintf (preprocargs, "-I%s", optarg); + } + else + { + char *n; + + n = xmalloc (strlen (preprocargs) + strlen (optarg) + 4); + sprintf (n, "%s -I%s", preprocargs, optarg); + free (preprocargs); + preprocargs = n; + } + + { + struct include_dir *n, **pp; + + n = (struct include_dir *) xmalloc (sizeof *n); + n->next = NULL; + n->dir = optarg; + + for (pp = &include_dirs; *pp != NULL; pp = &(*pp)->next) + ; + *pp = n; + } + + break; + + case OPTION_LANGUAGE: + language = strtol (optarg, (char **) NULL, 16); + break; + +#ifdef YYDEBUG + case OPTION_YYDEBUG: + yydebug = 1; + break; +#endif + + case OPTION_HELP: + usage (stdout, 0); + break; + + case OPTION_VERSION: + print_version ("windres"); + break; + + default: + usage (stderr, 1); + break; + } + } + + if (input_filename == NULL && optind < argc) + { + input_filename = argv[optind]; + ++optind; + } + + if (output_filename == NULL && optind < argc) + { + output_filename = argv[optind]; + ++optind; + } + + if (argc != optind) + usage (stderr, 1); + + if (input_format == RES_FORMAT_UNKNOWN) + { + if (input_filename == NULL) + input_format = RES_FORMAT_RC; + else + input_format = format_from_filename (input_filename, 1); + } + + if (output_format == RES_FORMAT_UNKNOWN) + { + if (output_filename == NULL) + output_format = RES_FORMAT_RC; + else + output_format = format_from_filename (output_filename, 0); + } + + /* Read the input file. */ + + switch (input_format) + { + default: + abort (); + case RES_FORMAT_RC: + resources = read_rc_file (input_filename, preprocessor, preprocargs, + language); + break; + case RES_FORMAT_RES: + resources = read_res_file (input_filename); + break; + case RES_FORMAT_COFF: + resources = read_coff_rsrc (input_filename, target); + break; + } + + if (resources == NULL) + fatal (_("no resources")); + + /* Sort the resources. This is required for COFF, convenient for + rc, and unimportant for res. */ + + resources = sort_resources (resources); + + /* Write the output file. */ + + reswr_init (); + + switch (output_format) + { + default: + abort (); + case RES_FORMAT_RC: + write_rc_file (output_filename, resources); + break; + case RES_FORMAT_RES: + write_res_file (output_filename, resources); + break; + case RES_FORMAT_COFF: + write_coff_file (output_filename, target, resources); + break; + } + + xexit (0); + return 0; +} + diff --git a/binutils/windres.h b/binutils/windres.h new file mode 100644 index 0000000..a3c789a --- /dev/null +++ b/binutils/windres.h @@ -0,0 +1,847 @@ +/* windres.h -- header file for windres program. + Copyright 1997, 1998 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Cygnus Support. + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#include <ansidecl.h> + +/* This is the header file for the windres program. It defines + structures and declares functions used within the program. */ + +#include "winduni.h" + +/* We represent resources internally as a tree, similar to the tree + used in the .rsrc section of a COFF file. The root is a + res_directory structure. */ + +struct res_directory +{ + /* Resource flags. According to the MS docs, this is currently + always zero. */ + unsigned long characteristics; + /* Time/date stamp. */ + unsigned long time; + /* Major version number. */ + unsigned short major; + /* Minor version number. */ + unsigned short minor; + /* Directory entries. */ + struct res_entry *entries; +}; + +/* A resource ID is stored in a res_id structure. */ + +struct res_id +{ + /* Non-zero if this entry has a name rather than an ID. */ + unsigned int named : 1; + union + { + /* If the named field is non-zero, this is the name. */ + struct + { + /* Length of the name. */ + int length; + /* Pointer to the name, which is a Unicode string. */ + unichar *name; + } n; + /* If the named field is zero, this is the ID. */ + unsigned long id; + } u; +}; + +/* Each entry in the tree is a res_entry structure. We mix + directories and resources because in a COFF file all entries in a + directory are sorted together, whether the entries are + subdirectories or resources. */ + +struct res_entry +{ + /* Next entry. */ + struct res_entry *next; + /* Resource ID. */ + struct res_id id; + /* Non-zero if this entry is a subdirectory rather than a leaf. */ + unsigned int subdir : 1; + union + { + /* If the subdir field is non-zero, this is a pointer to the + subdirectory. */ + struct res_directory *dir; + /* If the subdir field is zero, this is a pointer to the resource + data. */ + struct res_resource *res; + } u; +}; + +/* Types of resources. */ + +enum res_type +{ + RES_TYPE_UNINITIALIZED, + RES_TYPE_ACCELERATOR, + RES_TYPE_BITMAP, + RES_TYPE_CURSOR, + RES_TYPE_GROUP_CURSOR, + RES_TYPE_DIALOG, + RES_TYPE_FONT, + RES_TYPE_FONTDIR, + RES_TYPE_ICON, + RES_TYPE_GROUP_ICON, + RES_TYPE_MENU, + RES_TYPE_MESSAGETABLE, + RES_TYPE_RCDATA, + RES_TYPE_STRINGTABLE, + RES_TYPE_USERDATA, + RES_TYPE_VERSIONINFO +}; + +/* A res file and a COFF file store information differently. The + res_info structures holds data which in a res file is stored with + each resource, but in a COFF file is stored elsewhere. */ + +struct res_res_info +{ + /* Language. In a COFF file, the third level of the directory is + keyed by the language, so the language of a resource is defined + by its location in the resource tree. */ + unsigned short language; + /* Characteristics of the resource. Entirely user defined. In a + COFF file, the res_directory structure has a characteristics + field, but I don't know if it's related to the one in the res + file. */ + unsigned long characteristics; + /* Version of the resource. Entirely user defined. In a COFF file, + the res_directory structure has a characteristics field, but I + don't know if it's related to the one in the res file. */ + unsigned long version; + /* Memory flags. This is a combination of the MEMFLAG values + defined below. Most of these values are historical, and are not + meaningful for win32. I don't think there is any way to store + this information in a COFF file. */ + unsigned short memflags; +}; + +/* Each resource in a COFF file has some information which can does + not appear in a res file. */ + +struct res_coff_info +{ + /* The code page used for the data. I don't really know what this + should be. */ + unsigned long codepage; + /* A resource entry in a COFF file has a reserved field, which we + record here when reading a COFF file. When writing a COFF file, + we set this field to zero. */ + unsigned long reserved; +}; + +/* Resource data is stored in a res_resource structure. */ + +struct res_resource +{ + /* The type of resource. */ + enum res_type type; + /* The data for the resource. */ + union + { + struct + { + unsigned long length; + const unsigned char *data; + } data; + struct accelerator *acc; + struct cursor *cursor; + struct group_cursor *group_cursor; + struct dialog *dialog; + struct fontdir *fontdir; + struct group_icon *group_icon; + struct menu *menu; + struct rcdata_item *rcdata; + struct stringtable *stringtable; + struct rcdata_item *userdata; + struct versioninfo *versioninfo; + } u; + /* Information from a res file. */ + struct res_res_info res_info; + /* Information from a COFF file. */ + struct res_coff_info coff_info; +}; + +/* Memory flags in the memflags field of a struct res_resource. */ + +#define MEMFLAG_MOVEABLE 0x10 +#define MEMFLAG_PURE 0x20 +#define MEMFLAG_PRELOAD 0x40 +#define MEMFLAG_DISCARDABLE 0x1000 + +/* Standard resource type codes. These are used in the ID field of a + res_entry structure. */ + +#define RT_CURSOR 1 +#define RT_BITMAP 2 +#define RT_ICON 3 +#define RT_MENU 4 +#define RT_DIALOG 5 +#define RT_STRING 6 +#define RT_FONTDIR 7 +#define RT_FONT 8 +#define RT_ACCELERATOR 9 +#define RT_RCDATA 10 +#define RT_MESSAGETABLE 11 +#define RT_GROUP_CURSOR 12 +#define RT_GROUP_ICON 14 +#define RT_VERSION 16 +#define RT_DLGINCLUDE 17 +#define RT_PLUGPLAY 19 +#define RT_VXD 20 +#define RT_ANICURSOR 21 +#define RT_ANIICON 22 + +/* An accelerator resource is a linked list of these structures. */ + +struct accelerator +{ + /* Next accelerator. */ + struct accelerator *next; + /* Flags. A combination of the ACC values defined below. */ + unsigned short flags; + /* Key value. */ + unsigned short key; + /* Resource ID. */ + unsigned short id; +}; + +/* Accelerator flags in the flags field of a struct accelerator. + These are the same values that appear in a res file. I hope. */ + +#define ACC_VIRTKEY 0x01 +#define ACC_NOINVERT 0x02 +#define ACC_SHIFT 0x04 +#define ACC_CONTROL 0x08 +#define ACC_ALT 0x10 +#define ACC_LAST 0x80 + +/* A cursor resource. */ + +struct cursor +{ + /* X coordinate of hotspot. */ + short xhotspot; + /* Y coordinate of hotspot. */ + short yhotspot; + /* Length of bitmap data. */ + unsigned long length; + /* Data. */ + const unsigned char *data; +}; + +/* A group_cursor resource is a list of group_cursor structures. */ + +struct group_cursor +{ + /* Next cursor in group. */ + struct group_cursor *next; + /* Width. */ + unsigned short width; + /* Height. */ + unsigned short height; + /* Planes. */ + unsigned short planes; + /* Bits per pixel. */ + unsigned short bits; + /* Number of bytes in cursor resource. */ + unsigned long bytes; + /* Index of cursor resource. */ + unsigned short index; +}; + +/* A dialog resource. */ + +struct dialog +{ + /* Basic window style. */ + unsigned long style; + /* Extended window style. */ + unsigned long exstyle; + /* X coordinate. */ + unsigned short x; + /* Y coordinate. */ + unsigned short y; + /* Width. */ + unsigned short width; + /* Height. */ + unsigned short height; + /* Menu name. */ + struct res_id menu; + /* Class name. */ + struct res_id class; + /* Caption. */ + unichar *caption; + /* Font point size. */ + unsigned short pointsize; + /* Font name. */ + unichar *font; + /* Extended information for a dialogex. */ + struct dialog_ex *ex; + /* Controls. */ + struct dialog_control *controls; +}; + +/* An extended dialog has additional information. */ + +struct dialog_ex +{ + /* Help ID. */ + unsigned long help; + /* Font weight. */ + unsigned short weight; + /* Whether the font is italic. */ + unsigned short italic; +}; + +/* Window style flags, from the winsup Defines.h header file. These + can appear in the style field of a struct dialog or a struct + dialog_control. */ + +#define CW_USEDEFAULT (0x80000000) +#define WS_BORDER (0x800000L) +#define WS_CAPTION (0xc00000L) +#define WS_CHILD (0x40000000L) +#define WS_CHILDWINDOW (0x40000000L) +#define WS_CLIPCHILDREN (0x2000000L) +#define WS_CLIPSIBLINGS (0x4000000L) +#define WS_DISABLED (0x8000000L) +#define WS_DLGFRAME (0x400000L) +#define WS_GROUP (0x20000L) +#define WS_HSCROLL (0x100000L) +#define WS_ICONIC (0x20000000L) +#define WS_MAXIMIZE (0x1000000L) +#define WS_MAXIMIZEBOX (0x10000L) +#define WS_MINIMIZE (0x20000000L) +#define WS_MINIMIZEBOX (0x20000L) +#define WS_OVERLAPPED (0L) +#define WS_OVERLAPPEDWINDOW (0xcf0000L) +#define WS_POPUP (0x80000000L) +#define WS_POPUPWINDOW (0x80880000L) +#define WS_SIZEBOX (0x40000L) +#define WS_SYSMENU (0x80000L) +#define WS_TABSTOP (0x10000L) +#define WS_THICKFRAME (0x40000L) +#define WS_TILED (0L) +#define WS_TILEDWINDOW (0xcf0000L) +#define WS_VISIBLE (0x10000000L) +#define WS_VSCROLL (0x200000L) +#define MDIS_ALLCHILDSTYLES (0x1) +#define BS_3STATE (0x5L) +#define BS_AUTO3STATE (0x6L) +#define BS_AUTOCHECKBOX (0x3L) +#define BS_AUTORADIOBUTTON (0x9L) +#define BS_BITMAP (0x80L) +#define BS_BOTTOM (0x800L) +#define BS_CENTER (0x300L) +#define BS_CHECKBOX (0x2L) +#define BS_DEFPUSHBUTTON (0x1L) +#define BS_GROUPBOX (0x7L) +#define BS_ICON (0x40L) +#define BS_LEFT (0x100L) +#define BS_LEFTTEXT (0x20L) +#define BS_MULTILINE (0x2000L) +#define BS_NOTIFY (0x4000L) +#define BS_OWNERDRAW (0xbL) +#define BS_PUSHBOX (0xcL) /* FIXME! What should this be? */ +#define BS_PUSHBUTTON (0L) +#define BS_PUSHLIKE (0x1000L) +#define BS_RADIOBUTTON (0x4L) +#define BS_RIGHT (0x200L) +#define BS_RIGHTBUTTON (0x20L) +#define BS_TEXT (0L) +#define BS_TOP (0x400L) +#define BS_USERBUTTON (0x8L) +#define BS_VCENTER (0xc00L) +#define CBS_AUTOHSCROLL (0x40L) +#define CBS_DISABLENOSCROLL (0x800L) +#define CBS_DROPDOWN (0x2L) +#define CBS_DROPDOWNLIST (0x3L) +#define CBS_HASSTRINGS (0x200L) +#define CBS_LOWERCASE (0x4000L) +#define CBS_NOINTEGRALHEIGHT (0x400L) +#define CBS_OEMCONVERT (0x80L) +#define CBS_OWNERDRAWFIXED (0x10L) +#define CBS_OWNERDRAWVARIABLE (0x20L) +#define CBS_SIMPLE (0x1L) +#define CBS_SORT (0x100L) +#define CBS_UPPERCASE (0x2000L) +#define ES_AUTOHSCROLL (0x80L) +#define ES_AUTOVSCROLL (0x40L) +#define ES_CENTER (0x1L) +#define ES_LEFT (0L) +#define ES_LOWERCASE (0x10L) +#define ES_MULTILINE (0x4L) +#define ES_NOHIDESEL (0x100L) +#define ES_NUMBER (0x2000L) +#define ES_OEMCONVERT (0x400L) +#define ES_PASSWORD (0x20L) +#define ES_READONLY (0x800L) +#define ES_RIGHT (0x2L) +#define ES_UPPERCASE (0x8L) +#define ES_WANTRETURN (0x1000L) +#define LBS_DISABLENOSCROLL (0x1000L) +#define LBS_EXTENDEDSEL (0x800L) +#define LBS_HASSTRINGS (0x40L) +#define LBS_MULTICOLUMN (0x200L) +#define LBS_MULTIPLESEL (0x8L) +#define LBS_NODATA (0x2000L) +#define LBS_NOINTEGRALHEIGHT (0x100L) +#define LBS_NOREDRAW (0x4L) +#define LBS_NOSEL (0x4000L) +#define LBS_NOTIFY (0x1L) +#define LBS_OWNERDRAWFIXED (0x10L) +#define LBS_OWNERDRAWVARIABLE (0x20L) +#define LBS_SORT (0x2L) +#define LBS_STANDARD (0xa00003L) +#define LBS_USETABSTOPS (0x80L) +#define LBS_WANTKEYBOARDINPUT (0x400L) +#define SBS_BOTTOMALIGN (0x4L) +#define SBS_HORZ (0L) +#define SBS_LEFTALIGN (0x2L) +#define SBS_RIGHTALIGN (0x4L) +#define SBS_SIZEBOX (0x8L) +#define SBS_SIZEBOXBOTTOMRIGHTALIGN (0x4L) +#define SBS_SIZEBOXTOPLEFTALIGN (0x2L) +#define SBS_SIZEGRIP (0x10L) +#define SBS_TOPALIGN (0x2L) +#define SBS_VERT (0x1L) +#define SS_BITMAP (0xeL) +#define SS_BLACKFRAME (0x7L) +#define SS_BLACKRECT (0x4L) +#define SS_CENTER (0x1L) +#define SS_CENTERIMAGE (0x200L) +#define SS_ENHMETAFILE (0xfL) +#define SS_ETCHEDFRAME (0x12L) +#define SS_ETCHEDHORZ (0x10L) +#define SS_ETCHEDVERT (0x11L) +#define SS_GRAYFRAME (0x8L) +#define SS_GRAYRECT (0x5L) +#define SS_ICON (0x3L) +#define SS_LEFT (0L) +#define SS_LEFTNOWORDWRAP (0xcL) +#define SS_NOPREFIX (0x80L) +#define SS_NOTIFY (0x100L) +#define SS_OWNERDRAW (0xdL) +#define SS_REALSIZEIMAGE (0x800L) +#define SS_RIGHT (0x2L) +#define SS_RIGHTJUST (0x400L) +#define SS_SIMPLE (0xbL) +#define SS_SUNKEN (0x1000L) +#define SS_USERITEM (0xaL) +#define SS_WHITEFRAME (0x9L) +#define SS_WHITERECT (0x6L) +#define DS_3DLOOK (0x4L) +#define DS_ABSALIGN (0x1L) +#define DS_CENTER (0x800L) +#define DS_CENTERMOUSE (0x1000L) +#define DS_CONTEXTHELP (0x2000L) +#define DS_CONTROL (0x400L) +#define DS_FIXEDSYS (0x8L) +#define DS_LOCALEDIT (0x20L) +#define DS_MODALFRAME (0x80L) +#define DS_NOFAILCREATE (0x10L) +#define DS_NOIDLEMSG (0x100L) +#define DS_SETFONT (0x40L) +#define DS_SETFOREGROUND (0x200L) +#define DS_SYSMODAL (0x2L) + +/* A dialog control. */ + +struct dialog_control +{ + /* Next control. */ + struct dialog_control *next; + /* ID. */ + unsigned short id; + /* Style. */ + unsigned long style; + /* Extended style. */ + unsigned long exstyle; + /* X coordinate. */ + unsigned short x; + /* Y coordinate. */ + unsigned short y; + /* Width. */ + unsigned short width; + /* Height. */ + unsigned short height; + /* Class name. */ + struct res_id class; + /* Associated text. */ + struct res_id text; + /* Extra data for the window procedure. */ + struct rcdata_item *data; + /* Help ID. Only used in an extended dialog. */ + unsigned long help; +}; + +/* Control classes. These can be used as the ID field in a struct + dialog_control. */ + +#define CTL_BUTTON 0x80 +#define CTL_EDIT 0x81 +#define CTL_STATIC 0x82 +#define CTL_LISTBOX 0x83 +#define CTL_SCROLLBAR 0x84 +#define CTL_COMBOBOX 0x85 + +/* A fontdir resource is a list of fontdir structures. */ + +struct fontdir +{ + struct fontdir *next; + /* Index of font entry. */ + short index; + /* Length of font information. */ + unsigned long length; + /* Font information. */ + const unsigned char *data; +}; + +/* A group_icon resource is a list of group_icon structures. */ + +struct group_icon +{ + /* Next icon in group. */ + struct group_icon *next; + /* Width. */ + unsigned char width; + /* Height. */ + unsigned char height; + /* Color count. */ + unsigned char colors; + /* Planes. */ + unsigned short planes; + /* Bits per pixel. */ + unsigned short bits; + /* Number of bytes in cursor resource. */ + unsigned long bytes; + /* Index of cursor resource. */ + unsigned short index; +}; + +/* A menu resource. */ + +struct menu +{ + /* List of menuitems. */ + struct menuitem *items; + /* Help ID. I don't think there is any way to set this in an rc + file, but it can appear in the binary format. */ + unsigned long help; +}; + +/* A menu resource is a list of menuitem structures. */ + +struct menuitem +{ + /* Next menuitem. */ + struct menuitem *next; + /* Type. In a normal menu, rather than a menuex, this is the flags + field. */ + unsigned long type; + /* State. This is only used in a menuex. */ + unsigned long state; + /* Id. */ + unsigned short id; + /* Unicode text. */ + unichar *text; + /* Popup menu items for a popup. */ + struct menuitem *popup; + /* Help ID. This is only used in a menuex. */ + unsigned long help; +}; + +/* Menu item flags. These can appear in the flags field of a struct + menuitem. */ + +#define MENUITEM_GRAYED 0x001 +#define MENUITEM_INACTIVE 0x002 +#define MENUITEM_BITMAP 0x004 +#define MENUITEM_OWNERDRAW 0x100 +#define MENUITEM_CHECKED 0x008 +#define MENUITEM_POPUP 0x010 +#define MENUITEM_MENUBARBREAK 0x020 +#define MENUITEM_MENUBREAK 0x040 +#define MENUITEM_ENDMENU 0x080 +#define MENUITEM_HELP 0x4000 + +/* An rcdata resource is a pointer to a list of rcdata_item + structures. */ + +struct rcdata_item +{ + /* Next data item. */ + struct rcdata_item *next; + /* Type of data. */ + enum + { + RCDATA_WORD, + RCDATA_DWORD, + RCDATA_STRING, + RCDATA_WSTRING, + RCDATA_BUFFER + } type; + union + { + unsigned int word; + unsigned long dword; + struct + { + unsigned long length; + const char *s; + } string; + struct + { + unsigned long length; + const unichar *w; + } wstring; + struct + { + unsigned long length; + const unsigned char *data; + } buffer; + } u; +}; + +/* A stringtable resource is a pointer to a stringtable structure. */ + +struct stringtable +{ + /* Each stringtable resource is a list of 16 unicode strings. */ + struct + { + /* Length of string. */ + int length; + /* String data if length > 0. */ + unichar *string; + } strings[16]; +}; + +/* A versioninfo resource points to a versioninfo structure. */ + +struct versioninfo +{ + /* Fixed version information. */ + struct fixed_versioninfo *fixed; + /* Variable version information. */ + struct ver_info *var; +}; + +/* The fixed portion of a versioninfo resource. */ + +struct fixed_versioninfo +{ + /* The file version, which is two 32 bit integers. */ + unsigned long file_version_ms; + unsigned long file_version_ls; + /* The product version, which is two 32 bit integers. */ + unsigned long product_version_ms; + unsigned long product_version_ls; + /* The file flags mask. */ + unsigned long file_flags_mask; + /* The file flags. */ + unsigned long file_flags; + /* The OS type. */ + unsigned long file_os; + /* The file type. */ + unsigned long file_type; + /* The file subtype. */ + unsigned long file_subtype; + /* The date, which in Windows is two 32 bit integers. */ + unsigned long file_date_ms; + unsigned long file_date_ls; +}; + +/* A list of variable version information. */ + +struct ver_info +{ + /* Next item. */ + struct ver_info *next; + /* Type of data. */ + enum { VERINFO_STRING, VERINFO_VAR } type; + union + { + /* StringFileInfo data. */ + struct + { + /* Language. */ + unichar *language; + /* Strings. */ + struct ver_stringinfo *strings; + } string; + /* VarFileInfo data. */ + struct + { + /* Key. */ + unichar *key; + /* Values. */ + struct ver_varinfo *var; + } var; + } u; +}; + +/* A list of string version information. */ + +struct ver_stringinfo +{ + /* Next string. */ + struct ver_stringinfo *next; + /* Key. */ + unichar *key; + /* Value. */ + unichar *value; +}; + +/* A list of variable version information. */ + +struct ver_varinfo +{ + /* Next item. */ + struct ver_varinfo *next; + /* Language ID. */ + unsigned short language; + /* Character set ID. */ + unsigned short charset; +}; + +/* This structure is used when converting resource information to + binary. */ + +struct bindata +{ + /* Next data. */ + struct bindata *next; + /* Length of data. */ + unsigned long length; + /* Data. */ + unsigned char *data; +}; + +/* Function declarations. */ + +extern struct res_directory *read_rc_file + PARAMS ((const char *, const char *, const char *, int)); +extern struct res_directory *read_res_file PARAMS ((const char *)); +extern struct res_directory *read_coff_rsrc + PARAMS ((const char *, const char *)); +extern void write_rc_file + PARAMS ((const char *, const struct res_directory *)); +extern void write_res_file + PARAMS ((const char *, const struct res_directory *)); +extern void write_coff_file + PARAMS ((const char *, const char *, const struct res_directory *)); + +extern struct res_resource *bin_to_res + PARAMS ((struct res_id, const unsigned char *, unsigned long, int)); +extern struct bindata *res_to_bin PARAMS ((const struct res_resource *, int)); + +extern FILE *open_file_search + PARAMS ((const char *, const char *, const char *, char **)); + +extern PTR res_alloc PARAMS ((size_t)); +extern PTR reswr_alloc PARAMS ((size_t)); + +/* Resource ID handling. */ + +extern int res_id_cmp PARAMS ((struct res_id, struct res_id)); +extern void res_id_print PARAMS ((FILE *, struct res_id, int)); +extern void res_ids_print PARAMS ((FILE *, int, const struct res_id *)); +extern void res_string_to_id PARAMS ((struct res_id *, const char *)); + +/* Manipulation of the resource tree. */ + +extern struct res_resource *define_resource + PARAMS ((struct res_directory **, int, const struct res_id *, int)); +extern struct res_resource *define_standard_resource + PARAMS ((struct res_directory **, int, struct res_id, int, int)); + +extern int extended_dialog PARAMS ((const struct dialog *)); +extern int extended_menu PARAMS ((const struct menu *)); + +/* Communication between the rc file support and the parser and lexer. */ + +extern int yydebug; +extern FILE *yyin; +extern char *rc_filename; +extern int rc_lineno; +extern int yyparse PARAMS ((void)); +extern int yylex PARAMS ((void)); +extern void yyerror PARAMS ((const char *)); +extern void rcparse_warning PARAMS ((const char *)); +extern void rcparse_set_language PARAMS ((int)); +extern void rcparse_discard_strings PARAMS ((void)); +extern void rcparse_rcdata PARAMS ((void)); +extern void rcparse_normal PARAMS ((void)); + +extern void define_accelerator + PARAMS ((struct res_id, const struct res_res_info *, struct accelerator *)); +extern void define_bitmap + PARAMS ((struct res_id, const struct res_res_info *, const char *)); +extern void define_cursor + PARAMS ((struct res_id, const struct res_res_info *, const char *)); +extern void define_dialog + PARAMS ((struct res_id, const struct res_res_info *, const struct dialog *)); +extern struct dialog_control *define_control + PARAMS ((const char *, unsigned long, unsigned long, unsigned long, + unsigned long, unsigned long, unsigned long, unsigned long, + unsigned long)); +extern void define_font + PARAMS ((struct res_id, const struct res_res_info *, const char *)); +extern void define_icon + PARAMS ((struct res_id, const struct res_res_info *, const char *)); +extern void define_menu + PARAMS ((struct res_id, const struct res_res_info *, struct menuitem *)); +extern struct menuitem *define_menuitem + PARAMS ((const char *, int, unsigned long, unsigned long, unsigned long, + struct menuitem *)); +extern void define_messagetable + PARAMS ((struct res_id, const struct res_res_info *, const char *)); +extern void define_rcdata + PARAMS ((struct res_id, const struct res_res_info *, struct rcdata_item *)); +extern struct rcdata_item *define_rcdata_string + PARAMS ((const char *, unsigned long)); +extern struct rcdata_item *define_rcdata_number PARAMS ((unsigned long, int)); +extern void define_stringtable + PARAMS ((const struct res_res_info *, unsigned long, const char *)); +extern void define_user_data + PARAMS ((struct res_id, struct res_id, const struct res_res_info *, + struct rcdata_item *)); +extern void define_user_file + PARAMS ((struct res_id, struct res_id, const struct res_res_info *, + const char *)); +extern void define_versioninfo + PARAMS ((struct res_id, int, struct fixed_versioninfo *, + struct ver_info *)); +extern struct ver_info *append_ver_stringfileinfo + PARAMS ((struct ver_info *, const char *, struct ver_stringinfo *)); +extern struct ver_info *append_ver_varfileinfo + PARAMS ((struct ver_info *, const char *, struct ver_varinfo *)); +extern struct ver_stringinfo *append_verval + PARAMS ((struct ver_stringinfo *, const char *, const char *)); +extern struct ver_varinfo *append_vertrans + PARAMS ((struct ver_varinfo *, unsigned long, unsigned long)); diff --git a/binutils/winduni.c b/binutils/winduni.c new file mode 100644 index 0000000..d79f47a --- /dev/null +++ b/binutils/winduni.c @@ -0,0 +1,147 @@ +/* winduni.c -- unicode support for the windres program. + Copyright 1997, 1998 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Cygnus Support. + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* This file contains unicode support routines for the windres + program. Ideally, we would have generic unicode support which + would work on all systems. However, we don't. Instead, on a + Windows host, we are prepared to call some Windows routines. This + means that we will generate different output on Windows and Unix + hosts, but that seems better than not really supporting unicode at + all. */ + +#include "bfd.h" +#include "bucomm.h" +#include "winduni.h" + +#include <ctype.h> + +#ifdef _WIN32 +#include <windows.h> +#endif + +/* Convert an ASCII string to a unicode string. We just copy it, + expanding chars to shorts, rather than doing something intelligent. */ + +void +unicode_from_ascii (length, unicode, ascii) + int *length; + unichar **unicode; + const char *ascii; +{ + int len; + const char *s; + unsigned short *w; + + len = strlen (ascii); + + if (length != NULL) + *length = len; + + *unicode = ((unichar *) res_alloc ((len + 1) * sizeof (unichar))); + +#ifdef _WIN32 + /* FIXME: On Windows, we should be using MultiByteToWideChar to set + the length. */ + MultiByteToWideChar (CP_ACP, 0, ascii, len + 1, *unicode, len + 1); +#else + for (s = ascii, w = *unicode; *s != '\0'; s++, w++) + *w = *s & 0xff; + *w = 0; +#endif +} + +/* Print the unicode string UNICODE to the file E. LENGTH is the + number of characters to print, or -1 if we should print until the + end of the string. FIXME: On a Windows host, we should be calling + some Windows function, probably WideCharToMultiByte. */ + +void +unicode_print (e, unicode, length) + FILE *e; + const unichar *unicode; + int length; +{ + while (1) + { + unichar ch; + + if (length == 0) + return; + if (length > 0) + --length; + + ch = *unicode; + + if (ch == 0 && length < 0) + return; + + ++unicode; + + if ((ch & 0x7f) == ch) + { + if (ch == '\\') + fputs ("\\", e); + else if (isprint (ch)) + putc (ch, e); + else + { + switch (ch) + { + case ESCAPE_A: + fputs ("\\a", e); + break; + + case ESCAPE_B: + fputs ("\\b", e); + break; + + case ESCAPE_F: + fputs ("\\f", e); + break; + + case ESCAPE_N: + fputs ("\\n", e); + break; + + case ESCAPE_R: + fputs ("\\r", e); + break; + + case ESCAPE_T: + fputs ("\\t", e); + break; + + case ESCAPE_V: + fputs ("\\v", e); + break; + + default: + fprintf (e, "\\%03o", (unsigned int) ch); + break; + } + } + } + else if ((ch & 0xff) == ch) + fprintf (e, "\\%03o", (unsigned int) ch); + else + fprintf (e, "\\x%x", (unsigned int) ch); + } +} diff --git a/binutils/winduni.h b/binutils/winduni.h new file mode 100644 index 0000000..13a9af2 --- /dev/null +++ b/binutils/winduni.h @@ -0,0 +1,60 @@ +/* winduni.h -- header file for unicode support for windres program. + Copyright 1997, 1998 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Cygnus Support. + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#include <ansidecl.h> + +/* This header file declares the types and functions we use for + unicode support in windres. Our unicode support is very limited at + present. + + We don't put this stuff in windres.h so that winduni.c doesn't have + to include windres.h. winduni.c needs to includes windows.h, and + that would conflict with the definitions of Windows macros we + already have in windres.h. */ + +/* We use this type to hold a unicode character. */ + +typedef unsigned short unichar; + +/* Escape character translations. */ + +#define ESCAPE_A (007) +#define ESCAPE_B (010) +#define ESCAPE_F (014) +#define ESCAPE_N (012) +#define ESCAPE_R (015) +#define ESCAPE_T (011) +#define ESCAPE_V (013) + +/* Convert an ASCII string to a unicode string. */ + +extern void unicode_from_ascii + PARAMS ((int *, unichar **, const char *)); + +/* Print a unicode string to a file. */ + +extern void unicode_print PARAMS ((FILE *, const unichar *, int)); + +/* Windres support routine called by unicode_from_ascii. This is both + here and in windres.h. It should probably be in a separate header + file, but it hardly seems worth it for one function. */ + +extern PTR res_alloc PARAMS ((size_t)); diff --git a/binutils/wrstabs.c b/binutils/wrstabs.c new file mode 100644 index 0000000..e428174 --- /dev/null +++ b/binutils/wrstabs.c @@ -0,0 +1,2416 @@ +/* wrstabs.c -- Output stabs debugging information + Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + Written by Ian Lance Taylor <ian@cygnus.com>. + + This file is part of GNU Binutils. + + 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., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* This file contains code which writes out stabs debugging + information. */ + +#include <stdio.h> +#include <ctype.h> +#include <assert.h> + +#include "bfd.h" +#include "bucomm.h" +#include "libiberty.h" +#include "debug.h" +#include "budbg.h" + +/* Meaningless definition needs by aout64.h. FIXME. */ +#define BYTES_IN_WORD 4 + +#include "aout/aout64.h" +#include "aout/stab_gnu.h" + +/* The size of a stabs symbol. This presumes 32 bit values. */ + +#define STAB_SYMBOL_SIZE (12) + +/* An entry in a string hash table. */ + +struct string_hash_entry +{ + struct bfd_hash_entry root; + /* Next string in this table. */ + struct string_hash_entry *next; + /* Index in string table. */ + long index; + /* Size of type if this is a typedef. */ + unsigned int size; +}; + +/* A string hash table. */ + +struct string_hash_table +{ + struct bfd_hash_table table; +}; + +/* The type stack. Each element on the stack is a string. */ + +struct stab_type_stack +{ + /* The next element on the stack. */ + struct stab_type_stack *next; + /* This element as a string. */ + char *string; + /* The type index of this element. */ + long index; + /* The size of the type. */ + unsigned int size; + /* Whether type string defines a new type. */ + boolean definition; + /* String defining struct fields. */ + char *fields; + /* NULL terminated array of strings defining base classes for a + class. */ + char **baseclasses; + /* String defining class methods. */ + char *methods; + /* String defining vtable pointer for a class. */ + char *vtable; +}; + +/* This structure is used to keep track of type indices for tagged + types. */ + +struct stab_tag +{ + /* The type index. */ + long index; + /* The tag name. */ + const char *tag; + /* The kind of type. This is set to DEBUG_KIND_ILLEGAL when the + type is defined. */ + enum debug_type_kind kind; + /* The size of the struct. */ + unsigned int size; +}; + +/* We remember various sorts of type indices. They are not related, + but, for convenience, we keep all the information in this + structure. */ + +struct stab_type_cache +{ + /* The void type index. */ + long void_type; + /* Signed integer type indices, indexed by size - 1. */ + long signed_integer_types[8]; + /* Unsigned integer type indices, indexed by size - 1. */ + long unsigned_integer_types[8]; + /* Floating point types, indexed by size - 1. */ + long float_types[16]; + /* Pointers to types, indexed by the type index. */ + long *pointer_types; + size_t pointer_types_alloc; + /* Functions returning types, indexed by the type index. */ + long *function_types; + size_t function_types_alloc; + /* References to types, indexed by the type index. */ + long *reference_types; + size_t reference_types_alloc; + /* Struct/union/class type indices, indexed by the struct id. */ + struct stab_tag *struct_types; + size_t struct_types_alloc; +}; + +/* This is the handle passed through debug_write. */ + +struct stab_write_handle +{ + /* The BFD. */ + bfd *abfd; + /* This buffer holds the symbols. */ + bfd_byte *symbols; + size_t symbols_size; + size_t symbols_alloc; + /* This is a list of hash table entries for the strings. */ + struct string_hash_entry *strings; + /* The last string hash table entry. */ + struct string_hash_entry *last_string; + /* The size of the strings. */ + size_t strings_size; + /* This hash table eliminates duplicate strings. */ + struct string_hash_table strhash; + /* The type stack. */ + struct stab_type_stack *type_stack; + /* The next type index. */ + long type_index; + /* The type cache. */ + struct stab_type_cache type_cache; + /* A mapping from typedef names to type indices. */ + struct string_hash_table typedef_hash; + /* If this is not -1, it is the offset to the most recent N_SO + symbol, and the value of that symbol needs to be set. */ + long so_offset; + /* If this is not -1, it is the offset to the most recent N_FUN + symbol, and the value of that symbol needs to be set. */ + long fun_offset; + /* The last text section address seen. */ + bfd_vma last_text_address; + /* The block nesting depth. */ + unsigned int nesting; + /* The function address. */ + bfd_vma fnaddr; + /* A pending LBRAC symbol. */ + bfd_vma pending_lbrac; + /* The current line number file name. */ + const char *lineno_filename; +}; + +static struct bfd_hash_entry *string_hash_newfunc + PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); +static boolean stab_write_symbol + PARAMS ((struct stab_write_handle *, int, int, bfd_vma, const char *)); +static boolean stab_push_string + PARAMS ((struct stab_write_handle *, const char *, long, boolean, + unsigned int)); +static boolean stab_push_defined_type + PARAMS ((struct stab_write_handle *, long, unsigned int)); +static char *stab_pop_type PARAMS ((struct stab_write_handle *)); +static boolean stab_modify_type + PARAMS ((struct stab_write_handle *, int, unsigned int, long **, size_t *)); +static long stab_get_struct_index + PARAMS ((struct stab_write_handle *, const char *, unsigned int, + enum debug_type_kind, unsigned int *)); +static boolean stab_class_method_var + PARAMS ((struct stab_write_handle *, const char *, enum debug_visibility, + boolean, boolean, boolean, bfd_vma, boolean)); + +static boolean stab_start_compilation_unit PARAMS ((PTR, const char *)); +static boolean stab_start_source PARAMS ((PTR, const char *)); +static boolean stab_empty_type PARAMS ((PTR)); +static boolean stab_void_type PARAMS ((PTR)); +static boolean stab_int_type PARAMS ((PTR, unsigned int, boolean)); +static boolean stab_float_type PARAMS ((PTR, unsigned int)); +static boolean stab_complex_type PARAMS ((PTR, unsigned int)); +static boolean stab_bool_type PARAMS ((PTR, unsigned int)); +static boolean stab_enum_type + PARAMS ((PTR, const char *, const char **, bfd_signed_vma *)); +static boolean stab_pointer_type PARAMS ((PTR)); +static boolean stab_function_type PARAMS ((PTR, int, boolean)); +static boolean stab_reference_type PARAMS ((PTR)); +static boolean stab_range_type PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma)); +static boolean stab_array_type + PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma, boolean)); +static boolean stab_set_type PARAMS ((PTR, boolean)); +static boolean stab_offset_type PARAMS ((PTR)); +static boolean stab_method_type PARAMS ((PTR, boolean, int, boolean)); +static boolean stab_const_type PARAMS ((PTR)); +static boolean stab_volatile_type PARAMS ((PTR)); +static boolean stab_start_struct_type + PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int)); +static boolean stab_struct_field + PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility)); +static boolean stab_end_struct_type PARAMS ((PTR)); +static boolean stab_start_class_type + PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int, boolean, + boolean)); +static boolean stab_class_static_member + PARAMS ((PTR, const char *, const char *, enum debug_visibility)); +static boolean stab_class_baseclass + PARAMS ((PTR, bfd_vma, boolean, enum debug_visibility)); +static boolean stab_class_start_method PARAMS ((PTR, const char *)); +static boolean stab_class_method_variant + PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean, + bfd_vma, boolean)); +static boolean stab_class_static_method_variant + PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean)); +static boolean stab_class_end_method PARAMS ((PTR)); +static boolean stab_end_class_type PARAMS ((PTR)); +static boolean stab_typedef_type PARAMS ((PTR, const char *)); +static boolean stab_tag_type + PARAMS ((PTR, const char *, unsigned int, enum debug_type_kind)); +static boolean stab_typdef PARAMS ((PTR, const char *)); +static boolean stab_tag PARAMS ((PTR, const char *)); +static boolean stab_int_constant PARAMS ((PTR, const char *, bfd_vma)); +static boolean stab_float_constant PARAMS ((PTR, const char *, double)); +static boolean stab_typed_constant PARAMS ((PTR, const char *, bfd_vma)); +static boolean stab_variable + PARAMS ((PTR, const char *, enum debug_var_kind, bfd_vma)); +static boolean stab_start_function PARAMS ((PTR, const char *, boolean)); +static boolean stab_function_parameter + PARAMS ((PTR, const char *, enum debug_parm_kind, bfd_vma)); +static boolean stab_start_block PARAMS ((PTR, bfd_vma)); +static boolean stab_end_block PARAMS ((PTR, bfd_vma)); +static boolean stab_end_function PARAMS ((PTR)); +static boolean stab_lineno + PARAMS ((PTR, const char *, unsigned long, bfd_vma)); + +static const struct debug_write_fns stab_fns = +{ + stab_start_compilation_unit, + stab_start_source, + stab_empty_type, + stab_void_type, + stab_int_type, + stab_float_type, + stab_complex_type, + stab_bool_type, + stab_enum_type, + stab_pointer_type, + stab_function_type, + stab_reference_type, + stab_range_type, + stab_array_type, + stab_set_type, + stab_offset_type, + stab_method_type, + stab_const_type, + stab_volatile_type, + stab_start_struct_type, + stab_struct_field, + stab_end_struct_type, + stab_start_class_type, + stab_class_static_member, + stab_class_baseclass, + stab_class_start_method, + stab_class_method_variant, + stab_class_static_method_variant, + stab_class_end_method, + stab_end_class_type, + stab_typedef_type, + stab_tag_type, + stab_typdef, + stab_tag, + stab_int_constant, + stab_float_constant, + stab_typed_constant, + stab_variable, + stab_start_function, + stab_function_parameter, + stab_start_block, + stab_end_block, + stab_end_function, + stab_lineno +}; + +/* Routine to create an entry in a string hash table. */ + +static struct bfd_hash_entry * +string_hash_newfunc (entry, table, string) + struct bfd_hash_entry *entry; + struct bfd_hash_table *table; + const char *string; +{ + struct string_hash_entry *ret = (struct string_hash_entry *) entry; + + /* Allocate the structure if it has not already been allocated by a + subclass. */ + if (ret == (struct string_hash_entry *) NULL) + ret = ((struct string_hash_entry *) + bfd_hash_allocate (table, sizeof (struct string_hash_entry))); + if (ret == (struct string_hash_entry *) NULL) + return NULL; + + /* Call the allocation method of the superclass. */ + ret = ((struct string_hash_entry *) + bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); + + if (ret) + { + /* Initialize the local fields. */ + ret->next = NULL; + ret->index = -1; + ret->size = 0; + } + + return (struct bfd_hash_entry *) ret; +} + +/* Look up an entry in a string hash table. */ + +#define string_hash_lookup(t, string, create, copy) \ + ((struct string_hash_entry *) \ + bfd_hash_lookup (&(t)->table, (string), (create), (copy))) + +/* Add a symbol to the stabs debugging information we are building. */ + +static boolean +stab_write_symbol (info, type, desc, value, string) + struct stab_write_handle *info; + int type; + int desc; + bfd_vma value; + const char *string; +{ + bfd_size_type strx; + bfd_byte sym[STAB_SYMBOL_SIZE]; + + if (string == NULL) + strx = 0; + else + { + struct string_hash_entry *h; + + h = string_hash_lookup (&info->strhash, string, true, true); + if (h == NULL) + { + fprintf (stderr, _("string_hash_lookup failed: %s\n"), + bfd_errmsg (bfd_get_error ())); + return false; + } + if (h->index != -1) + strx = h->index; + else + { + strx = info->strings_size; + h->index = strx; + if (info->last_string == NULL) + info->strings = h; + else + info->last_string->next = h; + info->last_string = h; + info->strings_size += strlen (string) + 1; + } + } + + /* This presumes 32 bit values. */ + bfd_put_32 (info->abfd, strx, sym); + bfd_put_8 (info->abfd, type, sym + 4); + bfd_put_8 (info->abfd, 0, sym + 5); + bfd_put_16 (info->abfd, desc, sym + 6); + bfd_put_32 (info->abfd, value, sym + 8); + + if (info->symbols_size + STAB_SYMBOL_SIZE > info->symbols_alloc) + { + info->symbols_alloc *= 2; + info->symbols = (bfd_byte *) xrealloc (info->symbols, + info->symbols_alloc); + } + + memcpy (info->symbols + info->symbols_size, sym, STAB_SYMBOL_SIZE); + + info->symbols_size += STAB_SYMBOL_SIZE; + + return true; +} + +/* Push a string on to the type stack. */ + +static boolean +stab_push_string (info, string, index, definition, size) + struct stab_write_handle *info; + const char *string; + long index; + boolean definition; + unsigned int size; +{ + struct stab_type_stack *s; + + s = (struct stab_type_stack *) xmalloc (sizeof *s); + s->string = xstrdup (string); + s->index = index; + s->definition = definition; + s->size = size; + + s->fields = NULL; + s->baseclasses = NULL; + s->methods = NULL; + s->vtable = NULL; + + s->next = info->type_stack; + info->type_stack = s; + + return true; +} + +/* Push a type index which has already been defined. */ + +static boolean +stab_push_defined_type (info, index, size) + struct stab_write_handle *info; + long index; + unsigned int size; +{ + char buf[20]; + + sprintf (buf, "%ld", index); + return stab_push_string (info, buf, index, false, size); +} + +/* Pop a type off the type stack. The caller is responsible for + freeing the string. */ + +static char * +stab_pop_type (info) + struct stab_write_handle *info; +{ + struct stab_type_stack *s; + char *ret; + + s = info->type_stack; + assert (s != NULL); + + info->type_stack = s->next; + + ret = s->string; + + free (s); + + return ret; +} + +/* The general routine to write out stabs in sections debugging + information. This accumulates the stabs symbols and the strings in + two obstacks. We can't easily write out the information as we go + along, because we need to know the section sizes before we can + write out the section contents. ABFD is the BFD and DHANDLE is the + handle for the debugging information. This sets *PSYMS to point to + the symbols, *PSYMSIZE the size of the symbols, *PSTRINGS to the + strings, and *PSTRINGSIZE to the size of the strings. */ + +boolean +write_stabs_in_sections_debugging_info (abfd, dhandle, psyms, psymsize, + pstrings, pstringsize) + bfd *abfd; + PTR dhandle; + bfd_byte **psyms; + bfd_size_type *psymsize; + bfd_byte **pstrings; + bfd_size_type *pstringsize; +{ + struct stab_write_handle info; + struct string_hash_entry *h; + bfd_byte *p; + + info.abfd = abfd; + + info.symbols_size = 0; + info.symbols_alloc = 500; + info.symbols = (bfd_byte *) xmalloc (info.symbols_alloc); + + info.strings = NULL; + info.last_string = NULL; + /* Reserve 1 byte for a null byte. */ + info.strings_size = 1; + + if (! bfd_hash_table_init (&info.strhash.table, string_hash_newfunc) + || ! bfd_hash_table_init (&info.typedef_hash.table, string_hash_newfunc)) + { + fprintf (stderr, "bfd_hash_table_init_failed: %s\n", + bfd_errmsg (bfd_get_error ())); + return false; + } + + info.type_stack = NULL; + info.type_index = 1; + memset (&info.type_cache, 0, sizeof info.type_cache); + info.so_offset = -1; + info.fun_offset = -1; + info.last_text_address = 0; + info.nesting = 0; + info.fnaddr = 0; + info.pending_lbrac = (bfd_vma) -1; + + /* The initial symbol holds the string size. */ + if (! stab_write_symbol (&info, 0, 0, 0, (const char *) NULL)) + return false; + + /* Output an initial N_SO symbol. */ + info.so_offset = info.symbols_size; + if (! stab_write_symbol (&info, N_SO, 0, 0, bfd_get_filename (abfd))) + return false; + + if (! debug_write (dhandle, &stab_fns, (PTR) &info)) + return false; + + assert (info.pending_lbrac == (bfd_vma) -1); + + /* Output a trailing N_SO. */ + if (! stab_write_symbol (&info, N_SO, 0, info.last_text_address, + (const char *) NULL)) + return false; + + /* Put the string size in the initial symbol. */ + bfd_put_32 (abfd, info.strings_size, info.symbols + 8); + + *psyms = info.symbols; + *psymsize = info.symbols_size; + + *pstringsize = info.strings_size; + *pstrings = (bfd_byte *) xmalloc (info.strings_size); + + p = *pstrings; + *p++ = '\0'; + for (h = info.strings; h != NULL; h = h->next) + { + strcpy ((char *) p, h->root.string); + p += strlen ((char *) p) + 1; + } + + return true; +} + +/* Start writing out information for a compilation unit. */ + +static boolean +stab_start_compilation_unit (p, filename) + PTR p; + const char *filename; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + + /* We would normally output an N_SO symbol here. However, that + would force us to reset all of our type information. I think we + will be better off just outputting an N_SOL symbol, and not + worrying about splitting information between files. */ + + info->lineno_filename = filename; + + return stab_write_symbol (info, N_SOL, 0, 0, filename); +} + +/* Start writing out information for a particular source file. */ + +static boolean +stab_start_source (p, filename) + PTR p; + const char *filename; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + + /* FIXME: The symbol's value is supposed to be the text section + address. However, we would have to fill it in later, and gdb + doesn't care, so we don't bother with it. */ + + info->lineno_filename = filename; + + return stab_write_symbol (info, N_SOL, 0, 0, filename); +} + +/* Push an empty type. This shouldn't normally happen. We just use a + void type. */ + +static boolean +stab_empty_type (p) + PTR p; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + + /* We don't call stab_void_type if the type is not yet defined, + because that might screw up the typedef. */ + + if (info->type_cache.void_type != 0) + return stab_push_defined_type (info, info->type_cache.void_type, 0); + else + { + long index; + char buf[40]; + + index = info->type_index; + ++info->type_index; + + sprintf (buf, "%ld=%ld", index, index); + + return stab_push_string (info, buf, index, false, 0); + } +} + +/* Push a void type. */ + +static boolean +stab_void_type (p) + PTR p; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + + if (info->type_cache.void_type != 0) + return stab_push_defined_type (info, info->type_cache.void_type, 0); + else + { + long index; + char buf[40]; + + index = info->type_index; + ++info->type_index; + + info->type_cache.void_type = index; + + sprintf (buf, "%ld=%ld", index, index); + + return stab_push_string (info, buf, index, true, 0); + } +} + +/* Push an integer type. */ + +static boolean +stab_int_type (p, size, unsignedp) + PTR p; + unsigned int size; + boolean unsignedp; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + long *cache; + + if (size <= 0 || (size > sizeof (long) && size != 8)) + { + fprintf (stderr, _("stab_int_type: bad size %u\n"), size); + return false; + } + + if (unsignedp) + cache = info->type_cache.signed_integer_types; + else + cache = info->type_cache.unsigned_integer_types; + + if (cache[size - 1] != 0) + return stab_push_defined_type (info, cache[size - 1], size); + else + { + long index; + char buf[100]; + + index = info->type_index; + ++info->type_index; + + cache[size - 1] = index; + + sprintf (buf, "%ld=r%ld;", index, index); + if (unsignedp) + { + strcat (buf, "0;"); + if (size < sizeof (long)) + sprintf (buf + strlen (buf), "%ld;", ((long) 1 << (size * 8)) - 1); + else if (size == sizeof (long)) + strcat (buf, "-1;"); + else if (size == 8) + strcat (buf, "01777777777777777777777;"); + else + abort (); + } + else + { + if (size <= sizeof (long)) + sprintf (buf + strlen (buf), "%ld;%ld;", + (long) - ((unsigned long) 1 << (size * 8 - 1)), + (long) (((unsigned long) 1 << (size * 8 - 1)) - 1)); + else if (size == 8) + strcat (buf, "01000000000000000000000;0777777777777777777777;"); + else + abort (); + } + + return stab_push_string (info, buf, index, true, size); + } +} + +/* Push a floating point type. */ + +static boolean +stab_float_type (p, size) + PTR p; + unsigned int size; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + + if (size > 0 + && size - 1 < (sizeof info->type_cache.float_types + / sizeof info->type_cache.float_types[0]) + && info->type_cache.float_types[size - 1] != 0) + return stab_push_defined_type (info, + info->type_cache.float_types[size - 1], + size); + else + { + long index; + char *int_type; + char buf[50]; + + /* Floats are defined as a subrange of int. */ + if (! stab_int_type (info, 4, false)) + return false; + int_type = stab_pop_type (info); + + index = info->type_index; + ++info->type_index; + + if (size > 0 + && size - 1 < (sizeof info->type_cache.float_types + / sizeof info->type_cache.float_types[0])) + info->type_cache.float_types[size - 1] = index; + + sprintf (buf, "%ld=r%s;%u;0;", index, int_type, size); + + free (int_type); + + return stab_push_string (info, buf, index, true, size); + } +} + +/* Push a complex type. */ + +static boolean +stab_complex_type (p, size) + PTR p; + unsigned int size; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + char buf[50]; + long index; + + index = info->type_index; + ++info->type_index; + + sprintf (buf, "%ld=r%ld;%u;0;", index, index, size); + + return stab_push_string (info, buf, index, true, size * 2); +} + +/* Push a boolean type. We use an XCOFF predefined type, since gdb + always recognizes them. */ + +static boolean +stab_bool_type (p, size) + PTR p; + unsigned int size; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + long index; + + switch (size) + { + case 1: + index = -21; + break; + + case 2: + index = -22; + break; + + default: + case 4: + index = -16; + break; + + case 8: + index = -33; + break; + } + + return stab_push_defined_type (info, index, size); +} + +/* Push an enum type. */ + +static boolean +stab_enum_type (p, tag, names, vals) + PTR p; + const char *tag; + const char **names; + bfd_signed_vma *vals; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + size_t len; + const char **pn; + char *buf; + long index = 0; + bfd_signed_vma *pv; + + if (names == NULL) + { + assert (tag != NULL); + + buf = (char *) xmalloc (10 + strlen (tag)); + sprintf (buf, "xe%s:", tag); + /* FIXME: The size is just a guess. */ + if (! stab_push_string (info, buf, 0, false, 4)) + return false; + free (buf); + return true; + } + + len = 10; + if (tag != NULL) + len += strlen (tag); + for (pn = names; *pn != NULL; pn++) + len += strlen (*pn) + 20; + + buf = (char *) xmalloc (len); + + if (tag == NULL) + strcpy (buf, "e"); + else + { + index = info->type_index; + ++info->type_index; + sprintf (buf, "%s:T%ld=e", tag, index); + } + + for (pn = names, pv = vals; *pn != NULL; pn++, pv++) + sprintf (buf + strlen (buf), "%s:%ld,", *pn, (long) *pv); + strcat (buf, ";"); + + if (tag == NULL) + { + /* FIXME: The size is just a guess. */ + if (! stab_push_string (info, buf, 0, false, 4)) + return false; + } + else + { + /* FIXME: The size is just a guess. */ + if (! stab_write_symbol (info, N_LSYM, 0, 0, buf) + || ! stab_push_defined_type (info, index, 4)) + return false; + } + + free (buf); + + return true; +} + +/* Push a modification of the top type on the stack. Cache the + results in CACHE and CACHE_ALLOC. */ + +static boolean +stab_modify_type (info, mod, size, cache, cache_alloc) + struct stab_write_handle *info; + int mod; + unsigned int size; + long **cache; + size_t *cache_alloc; +{ + long targindex; + long index; + char *s, *buf; + + assert (info->type_stack != NULL); + targindex = info->type_stack->index; + + if (targindex <= 0 + || cache == NULL) + { + boolean definition; + + /* Either the target type has no index, or we aren't caching + this modifier. Either way we have no way of recording the + new type, so we don't bother to define one. */ + definition = info->type_stack->definition; + s = stab_pop_type (info); + buf = (char *) xmalloc (strlen (s) + 2); + sprintf (buf, "%c%s", mod, s); + free (s); + if (! stab_push_string (info, buf, 0, definition, size)) + return false; + free (buf); + } + else + { + if ((size_t) targindex >= *cache_alloc) + { + size_t alloc; + + alloc = *cache_alloc; + if (alloc == 0) + alloc = 10; + while ((size_t) targindex >= alloc) + alloc *= 2; + *cache = (long *) xrealloc (*cache, alloc * sizeof (long)); + memset (*cache + *cache_alloc, 0, + (alloc - *cache_alloc) * sizeof (long)); + *cache_alloc = alloc; + } + + index = (*cache)[targindex]; + if (index != 0 && ! info->type_stack->definition) + { + /* We have already defined a modification of this type, and + the entry on the type stack is not a definition, so we + can safely discard it (we may have a definition on the + stack, even if we already defined a modification, if it + is a struct which we did not define at the time it was + referenced). */ + free (stab_pop_type (info)); + if (! stab_push_defined_type (info, index, size)) + return false; + } + else + { + index = info->type_index; + ++info->type_index; + + s = stab_pop_type (info); + buf = (char *) xmalloc (strlen (s) + 20); + sprintf (buf, "%ld=%c%s", index, mod, s); + free (s); + + (*cache)[targindex] = index; + + if (! stab_push_string (info, buf, index, true, size)) + return false; + + free (buf); + } + } + + return true; +} + +/* Push a pointer type. */ + +static boolean +stab_pointer_type (p) + PTR p; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + + /* FIXME: The size should depend upon the architecture. */ + return stab_modify_type (info, '*', 4, &info->type_cache.pointer_types, + &info->type_cache.pointer_types_alloc); +} + +/* Push a function type. */ + +static boolean +stab_function_type (p, argcount, varargs) + PTR p; + int argcount; + boolean varargs; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + int i; + + /* We have no way to represent the argument types, so we just + discard them. However, if they define new types, we must output + them. We do this by producing empty typedefs. */ + for (i = 0; i < argcount; i++) + { + if (! info->type_stack->definition) + free (stab_pop_type (info)); + else + { + char *s, *buf; + + s = stab_pop_type (info); + + buf = (char *) xmalloc (strlen (s) + 3); + sprintf (buf, ":t%s", s); + free (s); + + if (! stab_write_symbol (info, N_LSYM, 0, 0, buf)) + return false; + + free (buf); + } + } + + return stab_modify_type (info, 'f', 0, &info->type_cache.function_types, + &info->type_cache.function_types_alloc); +} + +/* Push a reference type. */ + +static boolean +stab_reference_type (p) + PTR p; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + + /* FIXME: The size should depend upon the architecture. */ + return stab_modify_type (info, '&', 4, &info->type_cache.reference_types, + &info->type_cache.reference_types_alloc); +} + +/* Push a range type. */ + +static boolean +stab_range_type (p, low, high) + PTR p; + bfd_signed_vma low; + bfd_signed_vma high; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + boolean definition; + unsigned int size; + char *s, *buf; + + definition = info->type_stack->definition; + size = info->type_stack->size; + + s = stab_pop_type (info); + buf = (char *) xmalloc (strlen (s) + 100); + sprintf (buf, "r%s;%ld;%ld;", s, (long) low, (long) high); + free (s); + + if (! stab_push_string (info, buf, 0, definition, size)) + return false; + + free (buf); + + return true; +} + +/* Push an array type. */ + +static boolean +stab_array_type (p, low, high, stringp) + PTR p; + bfd_signed_vma low; + bfd_signed_vma high; + boolean stringp; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + boolean definition; + unsigned int element_size; + char *range, *element, *buf; + long index; + unsigned int size; + + definition = info->type_stack->definition; + range = stab_pop_type (info); + + definition = definition || info->type_stack->definition; + element_size = info->type_stack->size; + element = stab_pop_type (info); + + buf = (char *) xmalloc (strlen (range) + strlen (element) + 100); + + if (! stringp) + { + index = 0; + *buf = '\0'; + } + else + { + /* We need to define a type in order to include the string + attribute. */ + index = info->type_index; + ++info->type_index; + definition = true; + sprintf (buf, "%ld=@S;", index); + } + + sprintf (buf + strlen (buf), "ar%s;%ld;%ld;%s", + range, (long) low, (long) high, element); + free (range); + free (element); + + if (high < low) + size = 0; + else + size = element_size * ((high - low) + 1); + if (! stab_push_string (info, buf, index, definition, size)) + return false; + + free (buf); + + return true; +} + +/* Push a set type. */ + +static boolean +stab_set_type (p, bitstringp) + PTR p; + boolean bitstringp; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + boolean definition; + char *s, *buf; + long index; + + definition = info->type_stack->definition; + + s = stab_pop_type (info); + buf = (char *) xmalloc (strlen (s) + 30); + + if (! bitstringp) + { + *buf = '\0'; + index = 0; + } + else + { + /* We need to define a type in order to include the string + attribute. */ + index = info->type_index; + ++info->type_index; + definition = true; + sprintf (buf, "%ld=@S;", index); + } + + sprintf (buf + strlen (buf), "S%s", s); + free (s); + + if (! stab_push_string (info, buf, index, definition, 0)) + return false; + + free (buf); + + return true; +} + +/* Push an offset type. */ + +static boolean +stab_offset_type (p) + PTR p; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + boolean definition; + char *target, *base, *buf; + + definition = info->type_stack->definition; + target = stab_pop_type (info); + + definition = definition || info->type_stack->definition; + base = stab_pop_type (info); + + buf = (char *) xmalloc (strlen (target) + strlen (base) + 3); + sprintf (buf, "@%s,%s", base, target); + free (base); + free (target); + + if (! stab_push_string (info, buf, 0, definition, 0)) + return false; + + free (buf); + + return true; +} + +/* Push a method type. */ + +static boolean +stab_method_type (p, domainp, argcount, varargs) + PTR p; + boolean domainp; + int argcount; + boolean varargs; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + boolean definition; + char *domain, *return_type, *buf; + char **args; + int i; + size_t len; + + /* We don't bother with stub method types, because that would + require a mangler for C++ argument types. This will waste space + in the debugging output. */ + + /* We need a domain. I'm not sure DOMAINP can ever be false, + anyhow. */ + if (! domainp) + { + if (! stab_empty_type (p)) + return false; + } + + definition = info->type_stack->definition; + domain = stab_pop_type (info); + + /* A non-varargs function is indicated by making the last parameter + type be void. */ + + if (argcount < 0) + { + args = NULL; + argcount = 0; + } + else if (argcount == 0) + { + if (varargs) + args = NULL; + else + { + args = (char **) xmalloc (1 * sizeof (*args)); + if (! stab_empty_type (p)) + return false; + definition = definition || info->type_stack->definition; + args[0] = stab_pop_type (info); + argcount = 1; + } + } + else + { + args = (char **) xmalloc ((argcount + 1) * sizeof (*args)); + for (i = argcount - 1; i >= 0; i--) + { + definition = definition || info->type_stack->definition; + args[i] = stab_pop_type (info); + } + if (! varargs) + { + if (! stab_empty_type (p)) + return false; + definition = definition || info->type_stack->definition; + args[argcount] = stab_pop_type (info); + ++argcount; + } + } + + definition = definition || info->type_stack->definition; + return_type = stab_pop_type (info); + + len = strlen (domain) + strlen (return_type) + 10; + for (i = 0; i < argcount; i++) + len += strlen (args[i]); + + buf = (char *) xmalloc (len); + + sprintf (buf, "#%s,%s", domain, return_type); + free (domain); + free (return_type); + for (i = 0; i < argcount; i++) + { + strcat (buf, ","); + strcat (buf, args[i]); + free (args[i]); + } + strcat (buf, ";"); + + if (args != NULL) + free (args); + + if (! stab_push_string (info, buf, 0, definition, 0)) + return false; + + free (buf); + + return true; +} + +/* Push a const version of a type. */ + +static boolean +stab_const_type (p) + PTR p; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + + return stab_modify_type (info, 'k', info->type_stack->size, + (long **) NULL, (size_t *) NULL); +} + +/* Push a volatile version of a type. */ + +static boolean +stab_volatile_type (p) + PTR p; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + + return stab_modify_type (info, 'B', info->type_stack->size, + (long **) NULL, (size_t *) NULL); +} + +/* Get the type index to use for a struct/union/class ID. This should + return -1 if it fails. */ + +static long +stab_get_struct_index (info, tag, id, kind, psize) + struct stab_write_handle *info; + const char *tag; + unsigned int id; + enum debug_type_kind kind; + unsigned int *psize; +{ + if (id >= info->type_cache.struct_types_alloc) + { + size_t alloc; + + alloc = info->type_cache.struct_types_alloc; + if (alloc == 0) + alloc = 10; + while (id >= alloc) + alloc *= 2; + info->type_cache.struct_types = + (struct stab_tag *) xrealloc (info->type_cache.struct_types, + alloc * sizeof (struct stab_tag)); + memset ((info->type_cache.struct_types + + info->type_cache.struct_types_alloc), + 0, + ((alloc - info->type_cache.struct_types_alloc) + * sizeof (struct stab_tag))); + info->type_cache.struct_types_alloc = alloc; + } + + if (info->type_cache.struct_types[id].index == 0) + { + info->type_cache.struct_types[id].index = info->type_index; + ++info->type_index; + info->type_cache.struct_types[id].tag = tag; + info->type_cache.struct_types[id].kind = kind; + } + + if (kind == DEBUG_KIND_ILLEGAL) + { + /* This is a definition of the struct. */ + info->type_cache.struct_types[id].kind = kind; + info->type_cache.struct_types[id].size = *psize; + } + else + *psize = info->type_cache.struct_types[id].size; + + return info->type_cache.struct_types[id].index; +} + +/* Start outputting a struct. We ignore the tag, and handle it in + stab_tag. */ + +/*ARGSUSED*/ +static boolean +stab_start_struct_type (p, tag, id, structp, size) + PTR p; + const char *tag; + unsigned int id; + boolean structp; + unsigned int size; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + long index; + boolean definition; + char *buf; + + buf = (char *) xmalloc (40); + + if (id == 0) + { + index = 0; + *buf = '\0'; + definition = false; + } + else + { + index = stab_get_struct_index (info, tag, id, DEBUG_KIND_ILLEGAL, + &size); + if (index < 0) + return false; + sprintf (buf, "%ld=", index); + definition = true; + } + + sprintf (buf + strlen (buf), "%c%u", + structp ? 's' : 'u', + size); + + if (! stab_push_string (info, buf, index, definition, size)) + return false; + + info->type_stack->fields = (char *) xmalloc (1); + info->type_stack->fields[0] = '\0'; + + return true; +} + +/* Add a field to a struct. */ + +static boolean +stab_struct_field (p, name, bitpos, bitsize, visibility) + PTR p; + const char *name; + bfd_vma bitpos; + bfd_vma bitsize; + enum debug_visibility visibility; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + boolean definition; + unsigned int size; + char *s, *n; + const char *vis; + + definition = info->type_stack->definition; + size = info->type_stack->size; + s = stab_pop_type (info); + + /* Add this field to the end of the current struct fields, which is + currently on the top of the stack. */ + + assert (info->type_stack->fields != NULL); + n = (char *) xmalloc (strlen (info->type_stack->fields) + + strlen (name) + + strlen (s) + + 50); + + switch (visibility) + { + default: + abort (); + + case DEBUG_VISIBILITY_PUBLIC: + vis = ""; + break; + + case DEBUG_VISIBILITY_PRIVATE: + vis = "/0"; + break; + + case DEBUG_VISIBILITY_PROTECTED: + vis = "/1"; + break; + } + + if (bitsize == 0) + { + bitsize = size * 8; + if (bitsize == 0) + fprintf (stderr, + _("%s: warning: unknown size for field `%s' in struct\n"), + bfd_get_filename (info->abfd), name); + } + + sprintf (n, "%s%s:%s%s,%ld,%ld;", info->type_stack->fields, name, vis, s, + (long) bitpos, (long) bitsize); + + free (info->type_stack->fields); + info->type_stack->fields = n; + + if (definition) + info->type_stack->definition = true; + + return true; +} + +/* Finish up a struct. */ + +static boolean +stab_end_struct_type (p) + PTR p; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + boolean definition; + long index; + unsigned int size; + char *fields, *first, *buf; + + assert (info->type_stack != NULL && info->type_stack->fields != NULL); + + definition = info->type_stack->definition; + index = info->type_stack->index; + size = info->type_stack->size; + fields = info->type_stack->fields; + first = stab_pop_type (info); + + buf = (char *) xmalloc (strlen (first) + strlen (fields) + 2); + sprintf (buf, "%s%s;", first, fields); + free (first); + free (fields); + + if (! stab_push_string (info, buf, index, definition, size)) + return false; + + free (buf); + + return true; +} + +/* Start outputting a class. */ + +static boolean +stab_start_class_type (p, tag, id, structp, size, vptr, ownvptr) + PTR p; + const char *tag; + unsigned int id; + boolean structp; + unsigned int size; + boolean vptr; + boolean ownvptr; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + boolean definition; + char *vstring; + + if (! vptr || ownvptr) + { + definition = false; + vstring = NULL; + } + else + { + definition = info->type_stack->definition; + vstring = stab_pop_type (info); + } + + if (! stab_start_struct_type (p, tag, id, structp, size)) + return false; + + if (vptr) + { + char *vtable; + + if (ownvptr) + { + assert (info->type_stack->index > 0); + vtable = (char *) xmalloc (20); + sprintf (vtable, "~%%%ld", info->type_stack->index); + } + else + { + vtable = (char *) xmalloc (strlen (vstring) + 3); + sprintf (vtable, "~%%%s", vstring); + free (vstring); + } + + info->type_stack->vtable = vtable; + } + + if (definition) + info->type_stack->definition = true; + + return true; +} + +/* Add a static member to the class on the type stack. */ + +static boolean +stab_class_static_member (p, name, physname, visibility) + PTR p; + const char *name; + const char *physname; + enum debug_visibility visibility; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + boolean definition; + char *s, *n; + const char *vis; + + definition = info->type_stack->definition; + s = stab_pop_type (info); + + /* Add this field to the end of the current struct fields, which is + currently on the top of the stack. */ + + assert (info->type_stack->fields != NULL); + n = (char *) xmalloc (strlen (info->type_stack->fields) + + strlen (name) + + strlen (s) + + strlen (physname) + + 10); + + switch (visibility) + { + default: + abort (); + + case DEBUG_VISIBILITY_PUBLIC: + vis = ""; + break; + + case DEBUG_VISIBILITY_PRIVATE: + vis = "/0"; + break; + + case DEBUG_VISIBILITY_PROTECTED: + vis = "/1"; + break; + } + + sprintf (n, "%s%s:%s%s:%s;", info->type_stack->fields, name, vis, s, + physname); + + free (info->type_stack->fields); + info->type_stack->fields = n; + + if (definition) + info->type_stack->definition = true; + + return true; +} + +/* Add a base class to the class on the type stack. */ + +static boolean +stab_class_baseclass (p, bitpos, virtual, visibility) + PTR p; + bfd_vma bitpos; + boolean virtual; + enum debug_visibility visibility; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + boolean definition; + char *s; + char *buf; + unsigned int c; + char **baseclasses; + + definition = info->type_stack->definition; + s = stab_pop_type (info); + + /* Build the base class specifier. */ + + buf = (char *) xmalloc (strlen (s) + 25); + buf[0] = virtual ? '1' : '0'; + switch (visibility) + { + default: + abort (); + + case DEBUG_VISIBILITY_PRIVATE: + buf[1] = '0'; + break; + + case DEBUG_VISIBILITY_PROTECTED: + buf[1] = '1'; + break; + + case DEBUG_VISIBILITY_PUBLIC: + buf[1] = '2'; + break; + } + + sprintf (buf + 2, "%ld,%s;", (long) bitpos, s); + free (s); + + /* Add the new baseclass to the existing ones. */ + + assert (info->type_stack != NULL && info->type_stack->fields != NULL); + + if (info->type_stack->baseclasses == NULL) + c = 0; + else + { + c = 0; + while (info->type_stack->baseclasses[c] != NULL) + ++c; + } + + baseclasses = (char **) xrealloc (info->type_stack->baseclasses, + (c + 2) * sizeof (*baseclasses)); + baseclasses[c] = buf; + baseclasses[c + 1] = NULL; + + info->type_stack->baseclasses = baseclasses; + + if (definition) + info->type_stack->definition = true; + + return true; +} + +/* Start adding a method to the class on the type stack. */ + +static boolean +stab_class_start_method (p, name) + PTR p; + const char *name; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + char *m; + + assert (info->type_stack != NULL && info->type_stack->fields != NULL); + + if (info->type_stack->methods == NULL) + { + m = (char *) xmalloc (strlen (name) + 3); + *m = '\0'; + } + else + { + m = (char *) xrealloc (info->type_stack->methods, + (strlen (info->type_stack->methods) + + strlen (name) + + 4)); + } + + sprintf (m + strlen (m), "%s::", name); + + info->type_stack->methods = m; + + return true; +} + +/* Add a variant, either static or not, to the current method. */ + +static boolean +stab_class_method_var (info, physname, visibility, staticp, constp, volatilep, + voffset, contextp) + struct stab_write_handle *info; + const char *physname; + enum debug_visibility visibility; + boolean staticp; + boolean constp; + boolean volatilep; + bfd_vma voffset; + boolean contextp; +{ + boolean definition; + char *type; + char *context = NULL; + char visc, qualc, typec; + + definition = info->type_stack->definition; + type = stab_pop_type (info); + + if (contextp) + { + definition = definition || info->type_stack->definition; + context = stab_pop_type (info); + } + + assert (info->type_stack != NULL && info->type_stack->methods != NULL); + + switch (visibility) + { + default: + abort (); + + case DEBUG_VISIBILITY_PRIVATE: + visc = '0'; + break; + + case DEBUG_VISIBILITY_PROTECTED: + visc = '1'; + break; + + case DEBUG_VISIBILITY_PUBLIC: + visc = '2'; + break; + } + + if (constp) + { + if (volatilep) + qualc = 'D'; + else + qualc = 'B'; + } + else + { + if (volatilep) + qualc = 'C'; + else + qualc = 'A'; + } + + if (staticp) + typec = '?'; + else if (! contextp) + typec = '.'; + else + typec = '*'; + + info->type_stack->methods = + (char *) xrealloc (info->type_stack->methods, + (strlen (info->type_stack->methods) + + strlen (type) + + strlen (physname) + + (contextp ? strlen (context) : 0) + + 40)); + + sprintf (info->type_stack->methods + strlen (info->type_stack->methods), + "%s:%s;%c%c%c", type, physname, visc, qualc, typec); + free (type); + + if (contextp) + { + sprintf (info->type_stack->methods + strlen (info->type_stack->methods), + "%ld;%s;", (long) voffset, context); + free (context); + } + + if (definition) + info->type_stack->definition = true; + + return true; +} + +/* Add a variant to the current method. */ + +static boolean +stab_class_method_variant (p, physname, visibility, constp, volatilep, + voffset, contextp) + PTR p; + const char *physname; + enum debug_visibility visibility; + boolean constp; + boolean volatilep; + bfd_vma voffset; + boolean contextp; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + + return stab_class_method_var (info, physname, visibility, false, constp, + volatilep, voffset, contextp); +} + +/* Add a static variant to the current method. */ + +static boolean +stab_class_static_method_variant (p, physname, visibility, constp, volatilep) + PTR p; + const char *physname; + enum debug_visibility visibility; + boolean constp; + boolean volatilep; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + + return stab_class_method_var (info, physname, visibility, true, constp, + volatilep, 0, false); +} + +/* Finish up a method. */ + +static boolean +stab_class_end_method (p) + PTR p; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + + assert (info->type_stack != NULL && info->type_stack->methods != NULL); + + /* We allocated enough room on info->type_stack->methods to add the + trailing semicolon. */ + strcat (info->type_stack->methods, ";"); + + return true; +} + +/* Finish up a class. */ + +static boolean +stab_end_class_type (p) + PTR p; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + size_t len; + unsigned int i = 0; + char *buf; + + assert (info->type_stack != NULL && info->type_stack->fields != NULL); + + /* Work out the size we need to allocate for the class definition. */ + + len = (strlen (info->type_stack->string) + + strlen (info->type_stack->fields) + + 10); + if (info->type_stack->baseclasses != NULL) + { + len += 20; + for (i = 0; info->type_stack->baseclasses[i] != NULL; i++) + len += strlen (info->type_stack->baseclasses[i]); + } + if (info->type_stack->methods != NULL) + len += strlen (info->type_stack->methods); + if (info->type_stack->vtable != NULL) + len += strlen (info->type_stack->vtable); + + /* Build the class definition. */ + + buf = (char *) xmalloc (len); + + strcpy (buf, info->type_stack->string); + + if (info->type_stack->baseclasses != NULL) + { + sprintf (buf + strlen (buf), "!%u,", i); + for (i = 0; info->type_stack->baseclasses[i] != NULL; i++) + { + strcat (buf, info->type_stack->baseclasses[i]); + free (info->type_stack->baseclasses[i]); + } + free (info->type_stack->baseclasses); + info->type_stack->baseclasses = NULL; + } + + strcat (buf, info->type_stack->fields); + free (info->type_stack->fields); + info->type_stack->fields = NULL; + + if (info->type_stack->methods != NULL) + { + strcat (buf, info->type_stack->methods); + free (info->type_stack->methods); + info->type_stack->methods = NULL; + } + + strcat (buf, ";"); + + if (info->type_stack->vtable != NULL) + { + strcat (buf, info->type_stack->vtable); + free (info->type_stack->vtable); + info->type_stack->vtable = NULL; + } + + /* Replace the string on the top of the stack with the complete + class definition. */ + free (info->type_stack->string); + info->type_stack->string = buf; + + return true; +} + +/* Push a typedef which was previously defined. */ + +static boolean +stab_typedef_type (p, name) + PTR p; + const char *name; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + struct string_hash_entry *h; + + h = string_hash_lookup (&info->typedef_hash, name, false, false); + assert (h != NULL && h->index > 0); + + return stab_push_defined_type (info, h->index, h->size); +} + +/* Push a struct, union or class tag. */ + +static boolean +stab_tag_type (p, name, id, kind) + PTR p; + const char *name; + unsigned int id; + enum debug_type_kind kind; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + long index; + unsigned int size; + + index = stab_get_struct_index (info, name, id, kind, &size); + if (index < 0) + return false; + + return stab_push_defined_type (info, index, size); +} + +/* Define a typedef. */ + +static boolean +stab_typdef (p, name) + PTR p; + const char *name; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + long index; + unsigned int size; + char *s, *buf; + struct string_hash_entry *h; + + index = info->type_stack->index; + size = info->type_stack->size; + s = stab_pop_type (info); + + buf = (char *) xmalloc (strlen (name) + strlen (s) + 20); + + if (index > 0) + sprintf (buf, "%s:t%s", name, s); + else + { + index = info->type_index; + ++info->type_index; + sprintf (buf, "%s:t%ld=%s", name, index, s); + } + + free (s); + + if (! stab_write_symbol (info, N_LSYM, 0, 0, buf)) + return false; + + free (buf); + + h = string_hash_lookup (&info->typedef_hash, name, true, false); + if (h == NULL) + { + fprintf (stderr, _("string_hash_lookup failed: %s\n"), + bfd_errmsg (bfd_get_error ())); + return false; + } + + /* I don't think we care about redefinitions. */ + + h->index = index; + h->size = size; + + return true; +} + +/* Define a tag. */ + +static boolean +stab_tag (p, tag) + PTR p; + const char *tag; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + char *s, *buf; + + s = stab_pop_type (info); + + buf = (char *) xmalloc (strlen (tag) + strlen (s) + 3); + + sprintf (buf, "%s:T%s", tag, s); + free (s); + + if (! stab_write_symbol (info, N_LSYM, 0, 0, buf)) + return false; + + free (buf); + + return true; +} + +/* Define an integer constant. */ + +static boolean +stab_int_constant (p, name, val) + PTR p; + const char *name; + bfd_vma val; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + char *buf; + + buf = (char *) xmalloc (strlen (name) + 20); + sprintf (buf, "%s:c=i%ld", name, (long) val); + + if (! stab_write_symbol (info, N_LSYM, 0, 0, buf)) + return false; + + free (buf); + + return true; +} + +/* Define a floating point constant. */ + +static boolean +stab_float_constant (p, name, val) + PTR p; + const char *name; + double val; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + char *buf; + + buf = (char *) xmalloc (strlen (name) + 20); + sprintf (buf, "%s:c=f%g", name, val); + + if (! stab_write_symbol (info, N_LSYM, 0, 0, buf)) + return false; + + free (buf); + + return true; +} + +/* Define a typed constant. */ + +static boolean +stab_typed_constant (p, name, val) + PTR p; + const char *name; + bfd_vma val; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + char *s, *buf; + + s = stab_pop_type (info); + + buf = (char *) xmalloc (strlen (name) + strlen (s) + 20); + sprintf (buf, "%s:c=e%s,%ld", name, s, (long) val); + free (s); + + if (! stab_write_symbol (info, N_LSYM, 0, 0, buf)) + return false; + + free (buf); + + return true; +} + +/* Record a variable. */ + +static boolean +stab_variable (p, name, kind, val) + PTR p; + const char *name; + enum debug_var_kind kind; + bfd_vma val; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + char *s, *buf; + int stab_type; + const char *kindstr; + + s = stab_pop_type (info); + + switch (kind) + { + default: + abort (); + + case DEBUG_GLOBAL: + stab_type = N_GSYM; + kindstr = "G"; + break; + + case DEBUG_STATIC: + stab_type = N_STSYM; + kindstr = "S"; + break; + + case DEBUG_LOCAL_STATIC: + stab_type = N_STSYM; + kindstr = "V"; + break; + + case DEBUG_LOCAL: + stab_type = N_LSYM; + kindstr = ""; + + /* Make sure that this is a type reference or definition. */ + if (! isdigit ((unsigned char) *s)) + { + char *n; + long index; + + index = info->type_index; + ++info->type_index; + n = (char *) xmalloc (strlen (s) + 20); + sprintf (n, "%ld=%s", index, s); + free (s); + s = n; + } + break; + + case DEBUG_REGISTER: + stab_type = N_RSYM; + kindstr = "r"; + break; + } + + buf = (char *) xmalloc (strlen (name) + strlen (s) + 3); + sprintf (buf, "%s:%s%s", name, kindstr, s); + free (s); + + if (! stab_write_symbol (info, stab_type, 0, val, buf)) + return false; + + free (buf); + + return true; +} + +/* Start outputting a function. */ + +static boolean +stab_start_function (p, name, globalp) + PTR p; + const char *name; + boolean globalp; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + char *rettype, *buf; + + assert (info->nesting == 0 && info->fun_offset == -1); + + rettype = stab_pop_type (info); + + buf = (char *) xmalloc (strlen (name) + strlen (rettype) + 3); + sprintf (buf, "%s:%c%s", name, + globalp ? 'F' : 'f', + rettype); + + /* We don't know the value now, so we set it in start_block. */ + info->fun_offset = info->symbols_size; + + if (! stab_write_symbol (info, N_FUN, 0, 0, buf)) + return false; + + free (buf); + + return true; +} + +/* Output a function parameter. */ + +static boolean +stab_function_parameter (p, name, kind, val) + PTR p; + const char *name; + enum debug_parm_kind kind; + bfd_vma val; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + char *s, *buf; + int stab_type; + char kindc; + + s = stab_pop_type (info); + + switch (kind) + { + default: + abort (); + + case DEBUG_PARM_STACK: + stab_type = N_PSYM; + kindc = 'p'; + break; + + case DEBUG_PARM_REG: + stab_type = N_RSYM; + kindc = 'P'; + break; + + case DEBUG_PARM_REFERENCE: + stab_type = N_PSYM; + kindc = 'v'; + break; + + case DEBUG_PARM_REF_REG: + stab_type = N_RSYM; + kindc = 'a'; + break; + } + + buf = (char *) xmalloc (strlen (name) + strlen (s) + 3); + sprintf (buf, "%s:%c%s", name, kindc, s); + free (s); + + if (! stab_write_symbol (info, stab_type, 0, val, buf)) + return false; + + free (buf); + + return true; +} + +/* Start a block. */ + +static boolean +stab_start_block (p, addr) + PTR p; + bfd_vma addr; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + + /* Fill in any slots which have been waiting for the first known + text address. */ + + if (info->so_offset != -1) + { + bfd_put_32 (info->abfd, addr, info->symbols + info->so_offset + 8); + info->so_offset = -1; + } + + if (info->fun_offset != -1) + { + bfd_put_32 (info->abfd, addr, info->symbols + info->fun_offset + 8); + info->fun_offset = -1; + } + + ++info->nesting; + + /* We will be called with a top level block surrounding the + function, but stabs information does not output that block, so we + ignore it. */ + + if (info->nesting == 1) + { + info->fnaddr = addr; + return true; + } + + /* We have to output the LBRAC symbol after any variables which are + declared inside the block. We postpone the LBRAC until the next + start_block or end_block. */ + + /* If we have postponed an LBRAC, output it now. */ + if (info->pending_lbrac != (bfd_vma) -1) + { + if (! stab_write_symbol (info, N_LBRAC, 0, info->pending_lbrac, + (const char *) NULL)) + return false; + } + + /* Remember the address and output it later. */ + + info->pending_lbrac = addr - info->fnaddr; + + return true; +} + +/* End a block. */ + +static boolean +stab_end_block (p, addr) + PTR p; + bfd_vma addr; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + + if (addr > info->last_text_address) + info->last_text_address = addr; + + /* If we have postponed an LBRAC, output it now. */ + if (info->pending_lbrac != (bfd_vma) -1) + { + if (! stab_write_symbol (info, N_LBRAC, 0, info->pending_lbrac, + (const char *) NULL)) + return false; + info->pending_lbrac = (bfd_vma) -1; + } + + assert (info->nesting > 0); + + --info->nesting; + + /* We ignore the outermost block. */ + if (info->nesting == 0) + return true; + + return stab_write_symbol (info, N_RBRAC, 0, addr - info->fnaddr, + (const char *) NULL); +} + +/* End a function. */ + +/*ARGSUSED*/ +static boolean +stab_end_function (p) + PTR p; +{ + return true; +} + +/* Output a line number. */ + +static boolean +stab_lineno (p, file, lineno, addr) + PTR p; + const char *file; + unsigned long lineno; + bfd_vma addr; +{ + struct stab_write_handle *info = (struct stab_write_handle *) p; + + assert (info->lineno_filename != NULL); + + if (addr > info->last_text_address) + info->last_text_address = addr; + + if (strcmp (file, info->lineno_filename) != 0) + { + if (! stab_write_symbol (info, N_SOL, 0, addr, file)) + return false; + info->lineno_filename = file; + } + + return stab_write_symbol (info, N_SLINE, lineno, addr - info->fnaddr, + (const char *) NULL); +} |