summaryrefslogtreecommitdiff
path: root/binutils
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>1999-05-03 07:29:11 +0000
committerRichard Henderson <rth@redhat.com>1999-05-03 07:29:11 +0000
commitaa2289c2a3faf0f198e47943dcb29e0c16223be8 (patch)
tree1af963bfd8d3e55167b81def4207f175eaff3a56 /binutils
downloadbinutils-redhat-aa2289c2a3faf0f198e47943dcb29e0c16223be8.tar.gz
Initial revision
Diffstat (limited to 'binutils')
-rw-r--r--binutils/ChangeLog6404
-rw-r--r--binutils/Makefile.am495
-rw-r--r--binutils/Makefile.in1358
-rw-r--r--binutils/NEWS163
-rw-r--r--binutils/README189
-rw-r--r--binutils/acinclude.m41
-rw-r--r--binutils/aclocal.m41120
-rw-r--r--binutils/addr2line.1127
-rw-r--r--binutils/addr2line.c335
-rw-r--r--binutils/ar.1509
-rw-r--r--binutils/ar.c1338
-rw-r--r--binutils/arlex.l83
-rw-r--r--binutils/arparse.y202
-rw-r--r--binutils/arsup.c456
-rw-r--r--binutils/arsup.h75
-rw-r--r--binutils/binutils.texi2904
-rw-r--r--binutils/bucomm.c266
-rw-r--r--binutils/bucomm.h183
-rw-r--r--binutils/budbg.h58
-rw-r--r--binutils/coffdump.c541
-rw-r--r--binutils/coffgrok.c737
-rw-r--r--binutils/coffgrok.h206
-rw-r--r--binutils/config.in183
-rwxr-xr-xbinutils/configure5567
-rwxr-xr-xbinutils/configure.bat63
-rw-r--r--binutils/configure.com76
-rw-r--r--binutils/configure.in221
-rw-r--r--binutils/cxxfilt.man114
-rw-r--r--binutils/debug.c3568
-rw-r--r--binutils/debug.h798
-rw-r--r--binutils/deflex.l86
-rw-r--r--binutils/defparse.y157
-rw-r--r--binutils/dep-in.sed17
-rw-r--r--binutils/dlltool.c3199
-rw-r--r--binutils/dlltool.h42
-rw-r--r--binutils/dllwrap.c1050
-rw-r--r--binutils/dyn-string.c107
-rw-r--r--binutils/dyn-string.h34
-rw-r--r--binutils/filemode.c266
-rw-r--r--binutils/ieee.c7609
-rw-r--r--binutils/is-ranlib.c3
-rw-r--r--binutils/is-strip.c4
-rw-r--r--binutils/mac-binutils.r42
-rw-r--r--binutils/makefile.vms-in98
-rw-r--r--binutils/maybe-ranlib.c4
-rw-r--r--binutils/maybe-strip.c4
-rw-r--r--binutils/mpw-config.in27
-rw-r--r--binutils/mpw-make.sed115
-rw-r--r--binutils/nlmconv.1110
-rw-r--r--binutils/nlmconv.c2212
-rw-r--r--binutils/nlmconv.h84
-rw-r--r--binutils/nlmheader.y978
-rw-r--r--binutils/nm.1230
-rw-r--r--binutils/nm.c1558
-rw-r--r--binutils/not-ranlib.c3
-rw-r--r--binutils/not-strip.c4
-rw-r--r--binutils/objcopy.1319
-rw-r--r--binutils/objcopy.c2029
-rw-r--r--binutils/objdump.1412
-rw-r--r--binutils/objdump.c2829
-rw-r--r--binutils/po/Make-in251
-rw-r--r--binutils/po/POTFILES.in52
-rw-r--r--binutils/po/binutils.pot3443
-rw-r--r--binutils/prdbg.c1862
-rw-r--r--binutils/ranlib.183
-rwxr-xr-xbinutils/ranlib.sh3
-rw-r--r--binutils/rclex.l465
-rw-r--r--binutils/rcparse.y1617
-rw-r--r--binutils/rdcoff.c889
-rw-r--r--binutils/rddbg.c448
-rw-r--r--binutils/readelf.c5682
-rw-r--r--binutils/rename.c210
-rw-r--r--binutils/resbin.c2387
-rw-r--r--binutils/rescoff.c776
-rw-r--r--binutils/resrc.c2265
-rw-r--r--binutils/resres.c656
-rwxr-xr-xbinutils/sanity.sh50
-rw-r--r--binutils/size.1161
-rw-r--r--binutils/size.c515
-rw-r--r--binutils/srconv.c2036
-rw-r--r--binutils/stabs.c5188
-rw-r--r--binutils/stamp-h.in1
-rw-r--r--binutils/strings.1151
-rw-r--r--binutils/strings.c514
-rw-r--r--binutils/strip.1185
-rw-r--r--binutils/sysdump.c790
-rw-r--r--binutils/sysinfo.y415
-rw-r--r--binutils/syslex.l51
-rw-r--r--binutils/sysroff.info504
-rw-r--r--binutils/testsuite/ChangeLog585
-rw-r--r--binutils/testsuite/binutils-all/ar.exp219
-rw-r--r--binutils/testsuite/binutils-all/bintest.s12
-rw-r--r--binutils/testsuite/binutils-all/hppa/addendbug.s23
-rw-r--r--binutils/testsuite/binutils-all/hppa/objdump.exp59
-rw-r--r--binutils/testsuite/binutils-all/nm.exp123
-rw-r--r--binutils/testsuite/binutils-all/objcopy.exp591
-rw-r--r--binutils/testsuite/binutils-all/objdump.exp140
-rw-r--r--binutils/testsuite/binutils-all/readelf.exp217
-rw-r--r--binutils/testsuite/binutils-all/readelf.h16
-rw-r--r--binutils/testsuite/binutils-all/readelf.r4
-rw-r--r--binutils/testsuite/binutils-all/readelf.s13
-rw-r--r--binutils/testsuite/binutils-all/readelf.ss13
-rw-r--r--binutils/testsuite/binutils-all/readelf.wi78
-rw-r--r--binutils/testsuite/binutils-all/size.exp78
-rw-r--r--binutils/testsuite/binutils-all/testprog.c28
-rw-r--r--binutils/testsuite/config/default.exp88
-rw-r--r--binutils/testsuite/config/hppa.sed4
-rw-r--r--binutils/testsuite/lib/utils-lib.exp161
-rw-r--r--binutils/version.c44
-rw-r--r--binutils/windres.c947
-rw-r--r--binutils/windres.h847
-rw-r--r--binutils/winduni.c147
-rw-r--r--binutils/winduni.h60
-rw-r--r--binutils/wrstabs.c2416
114 files changed, 90535 insertions, 0 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
new file mode 100644
index 0000000000..b8a3d2725a
--- /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 0000000000..4f3014f328
--- /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 0000000000..c32ae4d723
--- /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 0000000000..76dcebdda0
--- /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 0000000000..4b2d277244
--- /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 0000000000..71b09b9f6a
--- /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 0000000000..88a1565f2b
--- /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 0000000000..87ce103f8e
--- /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 0000000000..3cee867f3e
--- /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 0000000000..e4e8cff813
--- /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 0000000000..c951ef7b45
--- /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 0000000000..74e13d13df
--- /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 0000000000..d6c7600a87
--- /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 0000000000..38fd6953c8
--- /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 0000000000..f54a34bcf3
--- /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 0000000000..5f7c646b27
--- /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 0000000000..a5b0054887
--- /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 0000000000..36e6a7959e
--- /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 0000000000..d8ee8895e7
--- /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 0000000000..dc84d50917
--- /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 0000000000..8c4e6c9c98
--- /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 0000000000..c0ade42a61
--- /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 0000000000..38272ddfa5
--- /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 0000000000..594e154f30
--- /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 0000000000..f7d70f1150
--- /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 0000000000..99463d5ecd
--- /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 0000000000..298dcd89c6
--- /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 0000000000..a4d5d45106
--- /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 0000000000..173d627388
--- /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 = &top;
+
+ 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 0000000000..1b890b234f
--- /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 0000000000..e7fa362639
--- /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 0000000000..1cb6360961
--- /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 0000000000..f61921a482
--- /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 0000000000..ed5cf5e3fc
--- /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 0000000000..b4167c897f
--- /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 0000000000..574611b3dd
--- /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 0000000000..a4a304343c
--- /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 0000000000..a22bbbf654
--- /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 0000000000..58b52ba748
--- /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 0000000000..17a5b88213
--- /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, &sectype)
+ || ! 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 0000000000..fde72a43da
--- /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 0000000000..215341a325
--- /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 0000000000..7b1a3035e2
--- /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 0000000000..a809d1b13c
--- /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 0000000000..f37bc0ff21
--- /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 0000000000..6467c99e93
--- /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 0000000000..21a067ddd6
--- /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 0000000000..03abffe18f
--- /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 0000000000..cbc3aedd10
--- /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 0000000000..f1c8b6c268
--- /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 = &copyright_hdr_struct;
+ memset ((PTR) &copyright_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 0000000000..c92a557bb7
--- /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 0000000000..0f1e22aa5e
--- /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 0000000000..c2ad99e559
--- /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 0000000000..c51b7fbcc4
--- /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 0000000000..afb9ceb3d6
--- /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 0000000000..98093ce391
--- /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 0000000000..aee7760149
--- /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 0000000000..5fd77775d7
--- /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 0000000000..ddc153ed8a
--- /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 0000000000..3f9e8c4c3f
--- /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 0000000000..0552db1fee
--- /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 0000000000..47f38608ca
--- /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 0000000000..beeb383aeb
--- /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 0000000000..958cbd2c6b
--- /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 0000000000..7efb5c8e85
--- /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 0000000000..2b6fbc479c
--- /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 0000000000..06a66077f2
--- /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 0000000000..67079a5fd8
--- /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 0000000000..ee68bc6d44
--- /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 0000000000..9428c37ad5
--- /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 0000000000..549bf1a68b
--- /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 0000000000..fdc7263d1f
--- /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 0000000000..8fc07fbb29
--- /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 0000000000..9a028c7305
--- /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 0000000000..9ba3c11780
--- /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 0000000000..39264f445a
--- /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 0000000000..942cabf9ac
--- /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 0000000000..3b19bd2593
--- /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 0000000000..f57c7eda9b
--- /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 0000000000..8b0f2b7b5e
--- /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 0000000000..a47b3bd4ca
--- /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 0000000000..9788f70238
--- /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 0000000000..408de29400
--- /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 0000000000..8ffe6a1662
--- /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 0000000000..708817ded1
--- /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 0000000000..c821e8cf45
--- /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 0000000000..0aa87375dd
--- /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 0000000000..a39484287a
--- /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 0000000000..3af001a101
--- /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 0000000000..15a0577791
--- /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 0000000000..4b38c6b066
--- /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 0000000000..9e00650221
--- /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 0000000000..659306f074
--- /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 0000000000..a46b289769
--- /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 0000000000..76c7c5f38c
--- /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 0000000000..78972f1c0c
--- /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 0000000000..7c50f02fb6
--- /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 0000000000..b2f744c7e1
--- /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 0000000000..555afe9a7a
--- /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 0000000000..4bea721451
--- /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 0000000000..58b1245e9a
--- /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 0000000000..3760b38427
--- /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 0000000000..3cb2eccf01
--- /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 0000000000..b908c9198b
--- /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 0000000000..210656b448
--- /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 0000000000..2a2802e3a1
--- /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 0000000000..d8607d85d0
--- /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 0000000000..e27f21710c
--- /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 0000000000..105593997a
--- /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 0000000000..7de28c259e
--- /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 0000000000..a3c789abd0
--- /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 0000000000..d79f47a3d7
--- /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 0000000000..13a9af2e73
--- /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 0000000000..e428174f5b
--- /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);
+}