diff options
| author | gwr <gwr@NetBSD.org> | 1997-09-24 15:39:15 +0000 |
|---|---|---|
| committer | gwr <gwr@NetBSD.org> | 1997-09-24 15:39:15 +0000 |
| commit | 32adbb9246dd39a63b93a047dff437771d65eb46 (patch) | |
| tree | 0a26f54105a4c63fd4b849bc1ef86fba500ef449 /gnu/dist/binutils | |
| parent | 2d32cc76585a6bb97caf0093cff05d8b94881139 (diff) | |
stock binutils-2.8
Diffstat (limited to 'gnu/dist/binutils')
99 files changed, 71690 insertions, 0 deletions
diff --git a/gnu/dist/binutils/ChangeLog b/gnu/dist/binutils/ChangeLog new file mode 100644 index 00000000000..b3976a51f80 --- /dev/null +++ b/gnu/dist/binutils/ChangeLog @@ -0,0 +1,4845 @@ +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. + +Mon Apr 14 11:52:39 1997 Ian Lance Taylor <ian@cygnus.com> + + 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 18:53:31 1997 Ian Lance Taylor <ian@cygnus.com> + + * Makefile.in (VERSION): Set to 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/gnu/dist/binutils/Makefile.in b/gnu/dist/binutils/Makefile.in new file mode 100644 index 00000000000..5e3916e6985 --- /dev/null +++ b/gnu/dist/binutils/Makefile.in @@ -0,0 +1,748 @@ +# Makefile for GNU binary-file utilities +# Copyright (C) 1992, 93, 94, 95, 96, 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. + +VPATH = @srcdir@ +srcdir = @srcdir@ + +target_alias = @target_alias@ +prefix = @prefix@ + +program_transform_name = @program_transform_name@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +libdir = @libdir@ +tooldir = $(exec_prefix)/$(target_alias) + +datadir = @datadir@ +mandir = @mandir@ +man1dir = $(mandir)/man1 +man2dir = $(mandir)/man2 +man3dir = $(mandir)/man3 +man4dir = $(mandir)/man4 +man5dir = $(mandir)/man5 +man6dir = $(mandir)/man6 +man7dir = $(mandir)/man7 +man8dir = $(mandir)/man8 +man9dir = $(mandir)/man9 +infodir = @infodir@ +includedir = @includedir@ + +SHELL = /bin/sh + +INSTALL = `cd $(srcdir)/..;pwd`/install.sh -c +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_XFORM = $(INSTALL) -t='$(program_transform_name)' +INSTALL_XFORM1 = $(INSTALL_XFORM) -b=.1 -m 644 + +AR = ar +AR_FLAGS = rc +CC = @CC@ +CFLAGS = @CFLAGS@ +LDFLAGS = @LDFLAGS@ +HLDFLAGS = @HLDFLAGS@ +HLDENV = @HLDENV@ +RPATH_ENVVAR = @RPATH_ENVVAR@ +MAKEINFO = makeinfo +TEXI2DVI = texi2dvi +RANLIB = ranlib +BISONFLAGS = -d +TEXI2ROFF=texi2roff +MAKEOVERRIDES= +CC_FOR_BUILD = @CC_FOR_BUILD@ +NM_FOR_TARGET = nm +NM = $(NM_FOR_TARGET) +SYMLINK = ln -s + +BISON = bison -y +LEX_OPTIONS = +LEX = `if [ -f ../flex/flex ] ; then echo ../flex/flex ; else echo flex ; fi` + +# Distribution version +VERSION=2.8 +# Distribution name +DIST_NAME=binutils-${VERSION} + +# Where to find texinfo.tex to format docn with TeX +TEXIDIR = $(srcdir)/../texinfo + +# 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 + +# 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 + +SRCONV_PROG=srconv sysdump coffdump + +MANPAGES= ar nm objdump ranlib size strings strip objcopy addr2line nlmconv + +PROGS = $(SIZE_PROG) $(OBJDUMP_PROG) $(NM_PROG) $(AR_PROG) $(STRINGS_PROG) $(STRIP_PROG) $(RANLIB_PROG) $(DEMANGLER_PROG) $(OBJCOPY_PROG) $(ADDR2LINE_PROG) @BUILD_NLMCONV@ @BUILD_SRCONV@ @BUILD_DLLTOOL@ +STAGESTUFF = $(PROGS) *.o +# Files that can be generated, but should be in the distribution. +# Don't build $(DEMANGLER_PROG).1, since its name may vary with the +# configuration. +DISTSTUFF=arparse.c arparse.h arlex.c nlmheader.c sysinfo.c sysinfo.h \ + syslex.c deflex.c + +# Stuff that goes in tooldir/ if appropriate +TOOL_PROGS = nm.new strip.new ar ranlib $(DLLTOOL_PROG) + +BASEDIR = $(srcdir)/.. +BFDDIR = $(BASEDIR)/bfd +INCDIR = $(BASEDIR)/include +INCLUDES = -I. -I$(srcdir) -I../bfd -I$(BFDDIR) -I$(INCDIR) +DEP = mkdep + +ALL_CFLAGS = -D_GNU_SOURCE $(INCLUDES) @HDEFINES@ $(CFLAGS) + +HFILES = arsup.h bucomm.h budbg.h coffgrok.h debug.h nlmconv.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 + +GENERATED_CFILES = \ + underscore.c arparse.c arlex.c sysroff.c sysinfo.c syslex.c \ + defparse.c deflex.c nlmheader.c + +.c.o: + $(CC) -c $(ALL_CFLAGS) $< + +DEBUG_OBJS = rddbg.o debug.o stabs.o ieee.o rdcoff.o +WRITE_DEBUG_OBJS = $(DEBUG_OBJS) wrstabs.o + +LIBIBERTY = ../libiberty/libiberty.a + +# Code shared by all the binutils. +BULIBS = bucomm.o version.o filemode.o + +BFDLIB_DEP = ../bfd/libbfd.a +BFDLIB = @BFDLIB@ + +OPCODES_DEP = ../opcodes/libopcodes.a +OPCODES = @OPCODES@ + +ADDL_DEPS = $(BULIBS) $(BFDLIB_DEP) $(LIBIBERTY) +ADDL_LIBS = $(BULIBS) $(BFDLIB) $(LIBIBERTY) + +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` +RUNTESTFLAGS = + +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 '$(program_transform_name)'; \ + fi; \ + fi` + +FLAGS_TO_PASS = \ + "CC=$(CC)" \ + "CFLAGS=$(CFLAGS)" \ + "RUNTEST=$(RUNTEST)" \ + "RUNTESTFLAGS=$(RUNTESTFLAGS)" +# +## The rules + +all: $(ADDL_DEPS) $(PROGS) + +# These targets are for the dejagnu testsuites. The file site.exp +# contains global variables that all the testsuites will use. + +site.exp: ./config.status Makefile + @echo "Making a new config file..." + @rm -f ./tmp? + @touch site.exp + @mv site.exp site.bak + @echo "## variables are automatically generated by make ##" > ./tmp0 + @echo "# Do not edit here. If you wish to override these" >> ./tmp0 + @echo "# values, add them to the last section" >> ./tmp0 + @echo "# HOST AND TARGET INFO" >> ./tmp0 + @echo "set host_os @host_os@" >> ./tmp0 + @echo "set host_alias @host_alias@" >> ./tmp0 + @echo "set host_cpu @host_cpu@" >> ./tmp0 + @echo "set host_vendor @host_vendor@" >> ./tmp0 + @echo "set target_os @target_os@" >> ./tmp0 + @echo "set target_alias @target_alias@" >> ./tmp0 + @echo "set target_cpu @target_cpu@" >> ./tmp0 + @echo "set target_vendor @target_vendor@" >> ./tmp0 + @echo "set host_triplet @host@" >> ./tmp0 + @echo "set target_triplet @target@" >> ./tmp0 + @echo "# DIRECTORY INFO" >> ./tmp0 + @echo "set objdir `pwd`" >> ./tmp0 + @echo "" >> ./tmp0 + @echo "## Variables generated by configure. Do Not Edit ##" >> ./tmp0 + @cat ./tmp0 > site.exp + @cat site.bak | sed \ + -e '1,/^## Variables generated by.*##/ d' >> site.exp + -@rm -f ./tmp? + +check: site.exp + r=`pwd`; export r ; \ + srcroot=`cd ${srcdir}; pwd` ; export srcroot ; \ + EXPECT=${EXPECT} ; export EXPECT ; \ + $(RPATH_ENVVAR)=$$r/../bfd:$$r/../opcodes:$$$(RPATH_ENVVAR); \ + export $(RPATH_ENVVAR); \ + if [ -f $$r/../expect/expect ] ; then \ + TCL_LIBRARY=$${srcroot}/../tcl/library ; \ + export TCL_LIBRARY ; else true; fi ; \ + $(RUNTEST) --tool binutils --srcdir $(srcdir)/testsuite \ + $(RUNTESTFLAGS) CC="$(CC_FOR_TARGET)" CFLAGS="$(CFLAGS)" + +installcheck: + /bin/sh $(srcdir)/sanity.sh $(bindir) + +info: binutils.info + +dvi: binutils.dvi + +$(SIZE_PROG): $(ADDL_DEPS) size.o + $(HLDENV) $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $(SIZE_PROG) size.o $(ADDL_LIBS) $(EXTRALIBS) + +$(OBJCOPY_PROG): $(ADDL_DEPS) objcopy.o not-strip.o $(WRITE_DEBUG_OBJS) + $(HLDENV) $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $(OBJCOPY_PROG) objcopy.o not-strip.o $(WRITE_DEBUG_OBJS) $(ADDL_LIBS) $(EXTRALIBS) + +$(STRINGS_PROG): $(ADDL_DEPS) strings.o + $(HLDENV) $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $(STRINGS_PROG) strings.o $(ADDL_LIBS) $(EXTRALIBS) + +$(STRIP_PROG): $(ADDL_DEPS) objcopy.o is-strip.o $(WRITE_DEBUG_OBJS) + $(HLDENV) $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $(STRIP_PROG) objcopy.o is-strip.o $(WRITE_DEBUG_OBJS) $(ADDL_LIBS) $(EXTRALIBS) + +$(NM_PROG): $(ADDL_DEPS) nm.o + $(HLDENV) $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $(NM_PROG) nm.o $(ADDL_LIBS) $(EXTRALIBS) + +$(OBJDUMP_PROG): $(ADDL_DEPS) objdump.o prdbg.o $(DEBUG_OBJS) $(OPCODES_DEP) + $(HLDENV) $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $(OBJDUMP_PROG) objdump.o prdbg.o $(DEBUG_OBJS) $(OPCODES) $(ADDL_LIBS) $(EXTRALIBS) + +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 + +version.o: version.c Makefile + $(CC) -DVERSION='"$(VERSION)"' $(ALL_CFLAGS) -c $(srcdir)/version.c + +bucomm.o: bucomm.c Makefile + $(CC) -DTARGET='"@target@"' $(ALL_CFLAGS) -c $(srcdir)/bucomm.c + +cplus-dem.o: $(BASEDIR)/libiberty/cplus-dem.c $(INCDIR)/getopt.h + $(CC) -c -DMAIN -DVERSION='"$(VERSION)"' $(ALL_CFLAGS) $(BASEDIR)/libiberty/cplus-dem.c + +$(DEMANGLER_PROG): cplus-dem.o $(LIBIBERTY) underscore.o $(DEMANGLER_PROG).1 + $(HLDENV) $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $(DEMANGLER_PROG) cplus-dem.o $(LIBIBERTY) $(EXTRALIBS) underscore.o + +arparse.c: arparse.y + $(BISON) $(BISONFLAGS) $(srcdir)/arparse.y + mv -f y.tab.c arparse.c + mv -f y.tab.h arparse.h + +# Separate from arparse.c so that a parallel make doesn't try to build +# both arparse.c and arparse.h simultaneously. +arparse.h: arparse.c + +arlex.c: arlex.l + $(LEX) $(LEX_OPTIONS) $(srcdir)/arlex.l + mv lex.yy.c arlex.c + +$(AR_PROG): $(ADDL_DEPS) ar.o arparse.o arlex.o not-ranlib.o arsup.o + $(HLDENV) $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $(AR_PROG) ar.o arparse.o arlex.o arsup.o not-ranlib.o $(ADDL_LIBS) $(EXTRALIBS) + +$(RANLIB_PROG): $(ADDL_DEPS) ar.o is-ranlib.o arparse.o arlex.o arsup.o + $(HLDENV) $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $(RANLIB_PROG) ar.o arparse.o arlex.o arsup.o is-ranlib.o $(ADDL_LIBS) $(EXTRALIBS) + +$(ADDR2LINE_PROG): $(ADDL_DEPS) addr2line.o + $(HLDENV) $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $(ADDR2LINE_PROG) addr2line.o $(ADDL_LIBS) $(EXTRALIBS) + +# 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 sysroff.info + ./sysinfo -c <$(srcdir)/sysroff.info >sysroff.c + ./sysinfo -i <$(srcdir)/sysroff.info >>sysroff.c + ./sysinfo -g <$(srcdir)/sysroff.info >>sysroff.c + +sysroff.h: sysinfo sysroff.info + ./sysinfo -d <$(srcdir)/sysroff.info >sysroff.h + +# Depend upon arparse.c to avoid building both arparse.c and sysinfo.c +# simultaneously. +sysinfo.c: sysinfo.y arparse.c + $(BISON) -tvd $(srcdir)/sysinfo.y + rm -f sysinfo.c + mv -f y.tab.c sysinfo.c + mv -f y.tab.h sysinfo.h + +# Separate from sysinfo.c so that a parallel make doesn't try to build +# both sysinfo.c and sysinfo.h simultaneously. +sysinfo.h: sysinfo.c + +syslex.c : syslex.l + $(LEX) $(LEX_OPTIONS) $(srcdir)/syslex.l + mv lex.yy.c syslex.c + +sysinfo: 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: srconv.o coffgrok.o $(ADDL_DEPS) + $(HLDENV) $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ srconv.o coffgrok.o $(ADDL_LIBS) $(EXTRALIBS) + +dlltool: dlltool.o defparse.o deflex.o cplus-dem.o $(ADDL_DEPS) + $(HLDENV) $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ dlltool.o defparse.o deflex.o $(ADDL_LIBS) $(EXTRALIBS) + +defparse.c:defparse.y + $(BISON) $(BISONFLAGS) $(srcdir)/defparse.y + mv -f y.tab.c defparse.c + mv -f y.tab.h defparse.h + +defparse.h: defparse.c + +deflex.c:deflex.l + $(LEX) $(LEX_OPTIONS) $(srcdir)/deflex.l + mv lex.yy.c deflex.c + +dlltool.o:dlltool.c + $(CC) -c @DLLTOOL_DEFS@ $(ALL_CFLAGS) $(srcdir)/dlltool.c + +coffdump: coffdump.o coffgrok.o $(ADDL_DEPS) + $(HLDENV) $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ coffdump.o coffgrok.o $(ADDL_LIBS) $(EXTRALIBS) + +sysdump: sysdump.o $(ADDL_DEPS) + $(HLDENV) $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ sysdump.o $(ADDL_LIBS) $(EXTRALIBS) + +# Depend upon sysinfo.c to avoid building both nlmheader.c and sysinfo.c +# simultaneously. +nlmheader.c: nlmheader.y sysinfo.c + $(BISON) $(srcdir)/nlmheader.y + rm -f nlmheader.c + mv -f y.tab.c nlmheader.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 '$(program_transform_name)'`; \ + $(CC) -c -DLD_NAME="\"$${ldname}\"" @NLMCONV_DEFS@ $(ALL_CFLAGS) $(srcdir)/nlmconv.c + +$(NLMCONV_PROG): nlmconv.o nlmheader.o $(ADDL_DEPS) + $(HLDENV) $(CC) $(HLDFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ nlmconv.o nlmheader.o $(ADDL_LIBS) $(EXTRALIBS) + +# 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 $(ALL_CFLAGS) $? + $(SHELL) $(srcdir)/../move-if-change .dep2 .dep1 + +dep.sed: dep-in.sed config.status + sed <$(srcdir)/dep-in.sed >dep.sed \ + -e 's!@INCDIR@!$(INCDIR)!' \ + -e 's!@BFDDIR@!$(BFDDIR)!' \ + -e 's!@SRCDIR@!$(srcdir)!' + +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 + +.PHONY: dep dep-in + +### +# DOCUMENTATION TARGETS +config.texi: Makefile + rm -f config.texi + echo '@set VERSION $(VERSION)' > config.texi +# TeX output +binutils.dvi: $(srcdir)/binutils.texi config.texi + TEXINPUTS=$(TEXIDIR):$$TEXINPUTS $(TEXI2DVI) $(srcdir)/binutils.texi + +# info file for online browsing +binutils.info: $(srcdir)/binutils.texi config.texi + $(MAKEINFO) -o binutils.info $(srcdir)/binutils.texi + +$(DEMANGLER_PROG).1: cxxfilt.man Makefile + sed -e 's/@PROGRAM@/$(DEMANGLER_PROG)/' < $(srcdir)/cxxfilt.man \ + > $(DEMANGLER_PROG).1 + +# different targets for -ms, -mm, -me +# Try to use a recent texi2roff. v2 was put on prep in jan91. +# If you want an index, see texi2roff doc for postprocessing +# and add -i to texi2roff invocations below. +# Workarounds for texi2roff-2 (probably fixed in later texi2roff's, delete +# corresponding -e lines when later texi2roff's are current) +# + @ifinfo's deleted explicitly due to texi2roff-2 bug w nested constructs. +# + @c's deleted explicitly because texi2roff sees texinfo commands in them +# + @ (that's at-BLANK) not recognized by texi2roff, turned into blank +# + @alphaenumerate is ridiculously new, turned into @enumerate + +# roff output (-ms) +binutils.ms: $(srcdir)/binutils.texi + sed -e '/\\input texinfo/d' \ + -e '/@c TEXI2ROFF-KILL/,/@c END TEXI2ROFF-KILL/d' \ + -e '/^@ifinfo/,/^@end ifinfo/d' \ + -e '/^@c/d' \ + -e 's/{.*,,/{/' \ + -e 's/@ / /g' \ + -e 's/^@alphaenumerate/@enumerate/g' \ + -e 's/^@end alphaenumerate/@end enumerate/g' \ + $(srcdir)/binutils.texi | \ + $(TEXI2ROFF) -ms | \ + sed -e 's/---/\\(em/g' \ + >binutils.ms + +# roff output (-mm) +# '@noindent's removed due to texi2roff-2 mm bug; if yours is newer, +# try leaving them in +binutils.mm: $(srcdir)/binutils.texi + sed -e '/\\input texinfo/d' \ + -e '/@c TEXI2ROFF-KILL/,/@c END TEXI2ROFF-KILL/d' \ + -e '/^@ifinfo/,/^@end ifinfo/d' \ + -e '/^@c/d' \ + -e 's/{.*,,/{/' \ + -e '/@noindent/d' \ + -e 's/@ / /g' \ + -e 's/^@alphaenumerate/@enumerate/g' \ + -e 's/^@end alphaenumerate/@end enumerate/g' \ + $(srcdir)/binutils.texi | \ + $(TEXI2ROFF) -mm | \ + sed -e 's/---/\\(em/g' \ + >binutils.mm + +# roff output (-me) +binutils.me: $(srcdir)/binutils.texi + sed -e '/\\input texinfo/d' \ + -e '/@c TEXI2ROFF-KILL/,/@c END TEXI2ROFF-KILL/d' \ + -e '/^@ifinfo/,/^@end ifinfo/d' \ + -e '/^@c/d' \ + -e 's/{.*,,/{/' \ + -e 's/@ / /g' \ + -e 's/^@alphaenumerate/@enumerate/g' \ + -e 's/^@end alphaenumerate/@end enumerate/g' \ + $(srcdir)/binutils.texi | \ + $(TEXI2ROFF) -me | \ + sed -e 's/---/\\(em/g' \ + >binutils.me + + +### + +mostlyclean: + -rm -f *.o *~ \#* core binutils.?? binutils.??? y.output + -rm -rf tmpdir +clean: mostlyclean + -rm -f $(PROGS) $(DEMANGLER_PROG).1 stamp-under + -rm -f underscore.c sysroff sysroff.c sysroff.h sysinfo dep.sed +distclean: + -rm -f Makefile config.status *.o *~ \#* core y.* + -rm -f binutils.?? binutils.??? binutils.aux binutils.log binutils.toc + -rm -f $(PROGS) underscore.c config.h stamp-h config.cache config.log + -rm -f dep.sed stamp-under $(DEMANGLER_PROG).1 site.bak site.exp + -rm -f sysroff sysroff.c sysroff.h sysinfo + -rm -rf tmpdir +maintainer-clean realclean: clean distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + -rm -f $(DISTSTUFF) binutils.info* TAGS + +etags tags: TAGS + +TAGS: force + etags $(INCDIR)/*.h $(srcdir)/*.[hc] + +install: all + for i in $(PROGS) ; do \ + $(INSTALL_XFORM) $$i $(bindir)/`echo $$i | sed -e 's/.new//'` ; \ + done + for i in $(MANPAGES) ; do \ + $(INSTALL_XFORM1) $(srcdir)/$$i.1 $(man1dir)/$$i.1 ; \ + done + if [ x$(DEMANGLER_PROG) != x ]; then \ + $(INSTALL_XFORM1) $(DEMANGLER_PROG).1 $(man1dir)/$(DEMANGLER_PROG).1; \ + fi + test -d $(tooldir) || mkdir $(tooldir) + test -d $(tooldir)/bin || mkdir $(tooldir)/bin + for i in $(TOOL_PROGS) ; do \ + if [ -f $$i ]; then \ + j=`echo $$i | sed -e 's/.new//'`; \ + rm -f $(tooldir)/bin/$$j; \ + k=`echo $$j | sed '$(program_transform_name)'`; \ + ln $(bindir)/$$k $(tooldir)/bin/$$j >/dev/null 2>/dev/null \ + || $(INSTALL_PROGRAM) $$i $(tooldir)/bin/$$j; \ + else true; \ + fi; \ + done + +# This little path search is required because in the FSF net releases, +# the info files are included in the source tree, and that may not be +# the same as the build directory. +install-info: binutils.info + if [ -r binutils.info ]; then \ + dir=. ; \ + else \ + dir=$(srcdir) ; \ + fi ; \ + for i in `cd $$dir; echo binutils.info*` ; do \ + $(INSTALL_DATA) $$dir/$$i $(infodir)/$$i ; \ + done + +clean-info: + -rm -rf *.info* + +# Making a dist: +# cvs rtag binutils-x-yy ld+utils +# cvs co -r binutils-x-yy ld+utils +# cd {HERE}; make dist [-f Makefile.in] + +dist: $(DIST_NAME).tar.z + +diststuff: $(DISTSTUFF) info + +$(DIST_NAME).tar.z: + cd ../..; rm -f $(DIST_NAME); ln -s devo $(DIST_NAME) + make diststuff -f Makefile.in + cd ../ld; make diststuff -f Makefile.in + cd ../gprof; make diststuff -f Makefile.in + cd ../texinfo; mv texinfo.tex ..; rm -rf *; mv ../texinfo.tex . + # Take out texinfo from configurable dirs + mv ../configure.in tmp; \ + sed -e '/^host_tools=/s/texinfo //' <tmp >../configure.in; rm tmp + cd ..; chmod og=u `find . -print` + cd ../..; tar chf - $(DIST_NAME) | gzip >$(DIST_NAME).tar.z + rm -rf ../../$(DIST_NAME) + +#----------------------------------------------------------------------------- +# 'STANDARD' GNU/960 TARGETS BELOW THIS POINT +# +# 'VERSION' file must be present and contain a string of the form "x.y" +#----------------------------------------------------------------------------- + +ver960.c: FORCE + rm -f ver960.c + echo "char ${TARG}_ver[]= \"${TARG} `cat VERSION`, `date`\";" > ver960.c + + +# Dummy target to force execution of dependent targets. +# +force: + +# Target to uncomment host-specific lines in this makefile. Such lines must +# have the following string beginning in column 1: #__<hostname>__# +# Original Makefile is backed up as 'Makefile.old'. +# +# Invoke with: make make HOST=xxx +# +make: + -@if test $(HOST)x = x ; then \ + echo 'Specify "make make HOST=???"'; \ + exit 1; \ + fi ; \ + grep -s "^#The next line was generated by 'make make'" Makefile; \ + if test $$? = 0 ; then \ + echo "Makefile has already been processed with 'make make'";\ + exit 1; \ + fi ; \ + mv -f Makefile Makefile.old; \ + echo "#The next line was generated by 'make make'" >Makefile ; \ + echo "HOST=$(HOST)" >>Makefile ; \ + echo >>Makefile ; \ + sed "s/^#__$(HOST)__#//" < Makefile.old >>Makefile + +Makefile: Makefile.in config.status + CONFIG_FILES=Makefile CONFIG_HEADERS= $(SHELL) ./config.status + +config.h: stamp-h ; @true +stamp-h: config.in config.status + CONFIG_FILES= CONFIG_HEADERS=config.h:config.in $(SHELL) ./config.status + +config.status: configure $(srcdir)/../bfd/configure.host $(srcdir)/../bfd/config.bfd + $(SHELL) ./config.status --recheck + +# 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 +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 +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 +deflex.o: deflex.c defparse.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 + +# IF YOU PUT ANYTHING HERE IT WILL GO AWAY diff --git a/gnu/dist/binutils/NEWS b/gnu/dist/binutils/NEWS new file mode 100644 index 00000000000..1caa151972b --- /dev/null +++ b/gnu/dist/binutils/NEWS @@ -0,0 +1,135 @@ +-*- text -*- + +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/gnu/dist/binutils/README b/gnu/dist/binutils/README new file mode 100644 index 00000000000..4ae93cddad4 --- /dev/null +++ b/gnu/dist/binutils/README @@ -0,0 +1,107 @@ +This is a beta release of a completely rewritten binutils distribution. +(Rewritten since binutils 1.x, that is.) + +The linker (ld) has been moved into 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.8.tar.gz file, you'll get a directory +called something like `binutils-2.8', 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.8 + ./configure [ --enable-targets='target1,target2...' ] + 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. + +The --enable-targets option adds support for more binary file +formats besides the default. By default, support for only the +selected target file format is compiled in. To add support for more +formats, 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 + +The binutils can be used in a cross-development environment. +The file etc/configure.texi contains more information. + +You can also specify the --enable-shared option when you run +configure. This will build the BFD and opcodes libraries as shared +libraries. This will only work on certain systems, and currently will +only work when compiling with gcc. 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. + +If you specify --enable-commonbfdlib as well as --enable-shared, then +a single shared library will be built containing the bfd, opcodes, and +libiberty libraries. It will be installed as libbfd. This option +will make the binutils programs as small as possible. + +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=${MAKE-make} +${MAKE} $* AR=true all-libiberty +${MAKE} $* AR=true all-bfd +cd binutils +${MAKE} $* ADDL_DEPS='$(BULIBS)' ADDL_LIBS='$(BULIBS) ../bfd/*.o `cat ../libiberty/required-list ../libiberty/needed-list | sed -e "s,\([^ ][^ ]*\),../libiberty/\1,g"`' 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.8 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@prep.ai.mit.edu. 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. diff --git a/gnu/dist/binutils/acconfig.h b/gnu/dist/binutils/acconfig.h new file mode 100644 index 00000000000..6ae3d768c35 --- /dev/null +++ b/gnu/dist/binutils/acconfig.h @@ -0,0 +1,25 @@ + +/* Whether strstr must be declared even if <string.h> is included. */ +#undef NEED_DECLARATION_STRSTR + +/* Whether fprintf must be declared even if <stdio.h> is included. */ +#undef NEED_DECLARATION_FPRINTF + +/* Whether sbrk must be declared even if <unistd.h> is included. */ +#undef NEED_DECLARATION_SBRK + +/* Whether getenv must be declared even if <stdlib.h> is included. */ +#undef NEED_DECLARATION_GETENV +@TOP@ + +/* 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 + +/* Do we need to use the b modifier when opening binary files? */ +#undef USE_BINARY_FOPEN diff --git a/gnu/dist/binutils/aclocal.m4 b/gnu/dist/binutils/aclocal.m4 new file mode 100644 index 00000000000..7adc0045571 --- /dev/null +++ b/gnu/dist/binutils/aclocal.m4 @@ -0,0 +1 @@ +sinclude(../bfd/aclocal.m4) diff --git a/gnu/dist/binutils/addr2line.1 b/gnu/dist/binutils/addr2line.1 new file mode 100644 index 00000000000..87ce103f8e3 --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/addr2line.c b/gnu/dist/binutils/addr2line.c new file mode 100644 index 00000000000..7fbbdd855df --- /dev/null +++ b/gnu/dist/binutils/addr2line.c @@ -0,0 +1,324 @@ +/* addr2line.c -- convert addresses to line number and function name + Copyright 1997 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@prep.ai.mit.edu\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; + + 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; + + 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 = strtol (addr_hex, NULL, 16); + } + else + { + if (naddr <= 0) + break; + --naddr; + pc = strtol (*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 == '\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) + { + char *h; + + h = strrchr (filename, '/'); + if (h != NULL) + filename = h + 1; + } + + printf ("%s:%u\n", 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; + + 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/gnu/dist/binutils/ar.1 b/gnu/dist/binutils/ar.1 new file mode 100644 index 00000000000..a138e4ac061 --- /dev/null +++ b/gnu/dist/binutils/ar.1 @@ -0,0 +1,487 @@ +.\" 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}[abcilosuvV] \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. + +.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 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/gnu/dist/binutils/ar.c b/gnu/dist/binutils/ar.c new file mode 100644 index 00000000000..ceed38e67a8 --- /dev/null +++ b/gnu/dist/binutils/ar.c @@ -0,0 +1,1299 @@ +/* ar.c - Archive modify and extract. + Copyright 1991, 92, 93, 94, 95, 96, 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. */ + +/* + 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 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 */ + +#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, 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)); + +/* 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) + 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) + fprintf (s, "\ +Usage: %s [-]{dmpqrtx}[abcilosuvV] [member-name] archive-file file...\n\ + %s -M [<mri-script]\n", + program_name, program_name); + else + 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@prep.ai.mit.edu\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; + + 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 '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: + 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: + 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) + fatal ("internal stat error on %s", bfd_get_filename (abfd)); + + if (verbose) + 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) + 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; + int ncopied = 0; + long size; + struct stat buf; + if (bfd_stat_arch_elt (abfd, &buf) != 0) + fatal ("internal stat error on %s", bfd_get_filename (abfd)); + size = buf.st_size; + + if (verbose) + printf ("x - %s\n", bfd_get_filename (abfd)); + + bfd_seek (abfd, 0, SEEK_SET); + + ostream = 0; + 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) + { + 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) + fatal ("%s is not a valid archive", + bfd_get_filename (bfd_my_archive (abfd))); + + /* See comment above; this saves disk arm motion */ + if (!ostream) + { + /* 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) + { + perror (bfd_get_filename (abfd)); + xexit (1); + } + + output_file = ostream; + } + fwrite (cbuf, 1, nread, ostream); + ncopied += tocopy; + } + + fclose (ostream); + + output_file = NULL; + output_filename = NULL; + + chmod (bfd_get_filename (abfd), buf.st_mode); + + if (preserve_dates) + { +#ifdef HAVE_GOOD_UTIME_H + struct utimbuf tb; + tb.actime = buf.st_mtime; + tb.modtime = buf.st_mtime; + utime (bfd_get_filename (abfd), &tb); /* FIXME check result */ +#else /* ! HAVE_GOOD_UTIME_H */ +#ifndef HAVE_UTIMES + long tb[2]; + tb[0] = buf.st_mtime; + tb[1] = buf.st_mtime; + utime (bfd_get_filename (abfd), tb); /* FIXME check result */ +#else /* HAVE_UTIMES */ + struct timeval tv[2]; + tv[0].tv_sec = buf.st_mtime; + tv[0].tv_usec = 0; + tv[1].tv_sec = buf.st_mtime; + tv[1].tv_usec = 0; + utimes (bfd_get_filename (abfd), tv); /* FIXME check result */ +#endif /* HAVE_UTIMES */ +#endif /* ! HAVE_GOOD_UTIME_H */ + } +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) + fatal ("%s is not an archive", archive_filename); + } + else + { + fwrite (ARMAG, 1, SARMAG, ofile); + if (!silent_create) + 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); + unlink (old_name); + + if (rename (new_name, old_name) != 0) + bfd_fatal (old_name); +} + +/* 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) + bfd **contents; + enum pos default_pos; +{ + bfd **after_bfd = contents; + enum pos realpos = (postype == pos_default ? default_pos : postype); + + 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, posname)) + { + 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) + { + 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); + 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); + } + 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) + fatal ("internal stat error on %s", current->filename); + + if (fsbuf.st_mtime <= asbuf.st_mtime) + goto next_file; + } + + /* snip out this entry from the chain */ + *current_ptr = current->next; + + after_bfd = get_pos_bfd (&arch->next, pos_end); + 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; + + 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); + 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)) + 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/gnu/dist/binutils/arlex.c b/gnu/dist/binutils/arlex.c new file mode 100644 index 00000000000..a752b21c929 --- /dev/null +++ b/gnu/dist/binutils/arlex.c @@ -0,0 +1,1803 @@ +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header: /cvsroot/src/gnu/dist/binutils/Attic/arlex.c,v 1.1.1.1 1997/09/24 15:39:19 gwr Exp $ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include <stdio.h> + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include <stdlib.h> +#include <unistd.h> + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include <io.h> +#include <stdlib.h> +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 40 +#define YY_END_OF_BUFFER 41 +static yyconst short int yy_accept[177] = + { 0, + 0, 0, 41, 40, 39, 38, 35, 32, 33, 36, + 40, 34, 37, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 36, 31, 37, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 7, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 22, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + + 35, 35, 35, 10, 11, 12, 35, 15, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 25, 26, 27, + 35, 30, 35, 35, 35, 3, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 18, 35, 35, 35, 35, + 35, 35, 35, 1, 2, 4, 5, 35, 35, 35, + 35, 35, 16, 17, 19, 20, 35, 35, 35, 35, + 35, 35, 8, 9, 13, 14, 35, 23, 24, 28, + 29, 35, 35, 6, 21, 0 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 3, 1, 1, 1, 4, 1, 1, 1, 5, + 6, 7, 8, 9, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 10, 1, + 1, 1, 1, 1, 11, 12, 13, 14, 15, 16, + 4, 17, 18, 4, 4, 19, 20, 21, 22, 23, + 4, 24, 25, 26, 27, 28, 4, 29, 30, 4, + 1, 1, 1, 1, 4, 1, 31, 32, 33, 34, + + 35, 36, 4, 37, 38, 4, 4, 39, 40, 41, + 42, 43, 4, 44, 45, 46, 47, 48, 4, 49, + 50, 4, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[51] = + { 0, + 1, 2, 1, 3, 1, 1, 1, 1, 1, 1, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 + } ; + +static yyconst short int yy_base[180] = + { 0, + 0, 0, 193, 194, 194, 194, 0, 194, 194, 0, + 190, 194, 0, 177, 32, 37, 32, 163, 174, 170, + 164, 171, 174, 169, 149, 15, 22, 17, 135, 146, + 142, 136, 143, 146, 141, 0, 0, 194, 0, 161, + 159, 158, 153, 147, 156, 143, 149, 148, 141, 150, + 141, 135, 138, 127, 125, 124, 119, 113, 122, 109, + 115, 114, 107, 116, 107, 101, 104, 43, 136, 135, + 130, 129, 0, 119, 123, 118, 114, 118, 119, 122, + 124, 25, 104, 103, 98, 97, 0, 87, 91, 86, + 82, 86, 87, 90, 92, 105, 100, 97, 94, 93, + + 105, 106, 102, 0, 0, 0, 104, 0, 92, 75, + 70, 67, 64, 63, 75, 76, 72, 0, 0, 0, + 74, 0, 62, 91, 88, 0, 86, 85, 73, 85, + 79, 83, 70, 62, 59, 0, 57, 56, 44, 56, + 50, 54, 41, 0, 0, 0, 0, 63, 58, 59, + 67, 66, 0, 0, 0, 0, 38, 33, 34, 42, + 41, 51, 0, 0, 0, 0, 30, 0, 0, 0, + 0, 43, 21, 0, 0, 194, 65, 66, 69 + } ; + +static yyconst short int yy_def[180] = + { 0, + 176, 1, 176, 176, 176, 176, 177, 176, 176, 178, + 176, 176, 179, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 178, 176, 179, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 0, 176, 176, 176 + } ; + +static yyconst short int yy_nxt[245] = + { 0, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 7, 15, 16, 17, 18, 19, 7, 20, 7, + 7, 21, 7, 22, 23, 7, 7, 24, 7, 7, + 25, 7, 26, 27, 28, 29, 30, 7, 31, 7, + 7, 32, 7, 33, 34, 7, 7, 35, 7, 7, + 41, 43, 45, 55, 44, 42, 57, 59, 56, 58, + 46, 96, 97, 110, 111, 60, 37, 36, 37, 39, + 175, 39, 174, 173, 172, 171, 170, 169, 168, 167, + 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, + 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, + + 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, + 136, 135, 134, 133, 132, 131, 130, 129, 128, 127, + 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, + 116, 115, 114, 113, 112, 109, 108, 107, 106, 105, + 104, 103, 102, 101, 100, 99, 98, 95, 94, 93, + 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, + 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, + 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, + 62, 61, 54, 53, 52, 51, 50, 49, 48, 47, + 40, 38, 176, 3, 176, 176, 176, 176, 176, 176, + + 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, + 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, + 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, + 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, + 176, 176, 176, 176 + } ; + +static yyconst short int yy_chk[245] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 15, 16, 17, 26, 16, 15, 27, 28, 26, 27, + 17, 68, 68, 82, 82, 28, 178, 177, 178, 179, + 173, 179, 172, 167, 162, 161, 160, 159, 158, 157, + 152, 151, 150, 149, 148, 143, 142, 141, 140, 139, + 138, 137, 135, 134, 133, 132, 131, 130, 129, 128, + + 127, 125, 124, 123, 121, 117, 116, 115, 114, 113, + 112, 111, 110, 109, 107, 103, 102, 101, 100, 99, + 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, + 88, 86, 85, 84, 83, 81, 80, 79, 78, 77, + 76, 75, 74, 72, 71, 70, 69, 67, 66, 65, + 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, + 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, + 44, 43, 42, 41, 40, 35, 34, 33, 32, 31, + 30, 29, 25, 24, 23, 22, 21, 20, 19, 18, + 14, 11, 3, 176, 176, 176, 176, 176, 176, 176, + + 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, + 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, + 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, + 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, + 176, 176, 176, 176 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +char *yytext; +#line 1 "./arlex.l" +#define INITIAL 0 +#line 2 "./arlex.l" +/* 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; +#line 503 "lex.yy.c" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include <stdlib.h> +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 34 "./arlex.l" + + +#line 653 "lex.yy.c" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 177 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 194 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 36 "./arlex.l" +{ return ADDLIB; } + YY_BREAK +case 2: +YY_RULE_SETUP +#line 37 "./arlex.l" +{ return ADDMOD; } + YY_BREAK +case 3: +YY_RULE_SETUP +#line 38 "./arlex.l" +{ return CLEAR; } + YY_BREAK +case 4: +YY_RULE_SETUP +#line 39 "./arlex.l" +{ return CREATE; } + YY_BREAK +case 5: +YY_RULE_SETUP +#line 40 "./arlex.l" +{ return DELETE; } + YY_BREAK +case 6: +YY_RULE_SETUP +#line 41 "./arlex.l" +{ return DIRECTORY; } + YY_BREAK +case 7: +YY_RULE_SETUP +#line 42 "./arlex.l" +{ return END; } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 43 "./arlex.l" +{ return EXTRACT; } + YY_BREAK +case 9: +YY_RULE_SETUP +#line 44 "./arlex.l" +{ return FULLDIR; } + YY_BREAK +case 10: +YY_RULE_SETUP +#line 45 "./arlex.l" +{ return HELP; } + YY_BREAK +case 11: +YY_RULE_SETUP +#line 46 "./arlex.l" +{ return LIST; } + YY_BREAK +case 12: +YY_RULE_SETUP +#line 47 "./arlex.l" +{ return OPEN; } + YY_BREAK +case 13: +YY_RULE_SETUP +#line 48 "./arlex.l" +{ return REPLACE; } + YY_BREAK +case 14: +YY_RULE_SETUP +#line 49 "./arlex.l" +{ return VERBOSE; } + YY_BREAK +case 15: +YY_RULE_SETUP +#line 50 "./arlex.l" +{ return SAVE; } + YY_BREAK +case 16: +YY_RULE_SETUP +#line 51 "./arlex.l" +{ return ADDLIB; } + YY_BREAK +case 17: +YY_RULE_SETUP +#line 52 "./arlex.l" +{ return ADDMOD; } + YY_BREAK +case 18: +YY_RULE_SETUP +#line 53 "./arlex.l" +{ return CLEAR; } + YY_BREAK +case 19: +YY_RULE_SETUP +#line 54 "./arlex.l" +{ return CREATE; } + YY_BREAK +case 20: +YY_RULE_SETUP +#line 55 "./arlex.l" +{ return DELETE; } + YY_BREAK +case 21: +YY_RULE_SETUP +#line 56 "./arlex.l" +{ return DIRECTORY; } + YY_BREAK +case 22: +YY_RULE_SETUP +#line 57 "./arlex.l" +{ return END; } + YY_BREAK +case 23: +YY_RULE_SETUP +#line 58 "./arlex.l" +{ return EXTRACT; } + YY_BREAK +case 24: +YY_RULE_SETUP +#line 59 "./arlex.l" +{ return FULLDIR; } + YY_BREAK +case 25: +YY_RULE_SETUP +#line 60 "./arlex.l" +{ return HELP; } + YY_BREAK +case 26: +YY_RULE_SETUP +#line 61 "./arlex.l" +{ return LIST; } + YY_BREAK +case 27: +YY_RULE_SETUP +#line 62 "./arlex.l" +{ return OPEN; } + YY_BREAK +case 28: +YY_RULE_SETUP +#line 63 "./arlex.l" +{ return REPLACE; } + YY_BREAK +case 29: +YY_RULE_SETUP +#line 64 "./arlex.l" +{ return VERBOSE; } + YY_BREAK +case 30: +YY_RULE_SETUP +#line 65 "./arlex.l" +{ return SAVE; } + YY_BREAK +case 31: +YY_RULE_SETUP +#line 66 "./arlex.l" +{ linenumber ++; } + YY_BREAK +case 32: +YY_RULE_SETUP +#line 67 "./arlex.l" +{ return '('; } + YY_BREAK +case 33: +YY_RULE_SETUP +#line 68 "./arlex.l" +{ return ')'; } + YY_BREAK +case 34: +YY_RULE_SETUP +#line 69 "./arlex.l" +{ return ','; } + YY_BREAK +case 35: +YY_RULE_SETUP +#line 70 "./arlex.l" +{ + yylval.name = xstrdup (yytext); + return FILENAME; + } + YY_BREAK +case 36: +YY_RULE_SETUP +#line 74 "./arlex.l" +{ } + YY_BREAK +case 37: +YY_RULE_SETUP +#line 75 "./arlex.l" +{ } + YY_BREAK +case 38: +YY_RULE_SETUP +#line 76 "./arlex.l" +{ } + YY_BREAK +case 39: +YY_RULE_SETUP +#line 77 "./arlex.l" +{ linenumber ++; return NEWLINE; } + YY_BREAK +case 40: +YY_RULE_SETUP +#line 79 "./arlex.l" +ECHO; + YY_BREAK +#line 939 "lex.yy.c" +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a singled characater, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 177 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 177 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 176); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + yytext_ptr = yy_c_buf_p; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + { + yy_c_buf_p = + yytext_ptr + YY_MORE_ADJ; + return EOF; + } + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + break; + + case EOB_ACT_LAST_MATCH: +#ifdef __cplusplus + YY_FATAL_ERROR( + "unexpected last match in yyinput()" ); +#else + YY_FATAL_ERROR( + "unexpected last match in input()" ); +#endif + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + + return c; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +extern int isatty YY_PROTO(( int )); +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *str ) +#else +YY_BUFFER_STATE yy_scan_string( str ) +yyconst char *str; +#endif + { + int len; + for ( len = 0; str[len]; ++len ) + ; + + return yy_scan_bytes( str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n - YY_MORE_ADJ; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 79 "./arlex.l" + +#ifndef yywrap +/* Needed for lex, though not flex. */ +int yywrap() { return 1; } +#endif diff --git a/gnu/dist/binutils/arlex.l b/gnu/dist/binutils/arlex.l new file mode 100644 index 00000000000..74e13d13dfe --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/arparse.c b/gnu/dist/binutils/arparse.c new file mode 100644 index 00000000000..12969050abd --- /dev/null +++ b/gnu/dist/binutils/arparse.c @@ -0,0 +1,1027 @@ + +/* A Bison parser, made from ./arparse.y with Bison version GNU Bison version 1.24 + */ + +#define YYBISON 1 /* Identify Bison output. */ + +#define NEWLINE 258 +#define VERBOSE 259 +#define FILENAME 260 +#define ADDLIB 261 +#define LIST 262 +#define ADDMOD 263 +#define CLEAR 264 +#define CREATE 265 +#define DELETE 266 +#define DIRECTORY 267 +#define END 268 +#define EXTRACT 269 +#define FULLDIR 270 +#define HELP 271 +#define QUIT 272 +#define REPLACE 273 +#define SAVE 274 +#define OPEN 275 + +#line 1 "./arparse.y" + +/* arparse.y - Stange script language parser */ + +/* Copyright (C) 1992, 93, 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 "bfd.h" +#include "bucomm.h" +#include "arsup.h" +extern int verbose; +static int yyerror PARAMS ((const char *)); + +#line 35 "./arparse.y" +typedef union { + char *name; +struct list *list ; + +} YYSTYPE; + +#ifndef YYLTYPE +typedef + struct yyltype + { + int timestamp; + int first_line; + int first_column; + int last_line; + int last_column; + char *text; + } + yyltype; + +#define YYLTYPE yyltype +#endif + +#include <stdio.h> + +#ifndef __cplusplus +#ifndef __STDC__ +#define const +#endif +#endif + + + +#define YYFINAL 53 +#define YYFLAG -32768 +#define YYNTBASE 24 + +#define YYTRANSLATE(x) ((unsigned)(x) <= 275 ? yytranslate[x] : 45) + +static const char yytranslate[] = { 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 21, + 22, 2, 2, 23, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20 +}; + +#if YYDEBUG != 0 +static const short yyprhs[] = { 0, + 0, 1, 4, 7, 8, 11, 13, 15, 17, 19, + 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, + 41, 42, 45, 48, 50, 53, 56, 58, 60, 63, + 66, 70, 75, 77, 78, 82, 83, 87, 88, 90, + 91 +}; + +static const short yyrhs[] = { -1, + 25, 26, 0, 26, 27, 0, 0, 28, 3, 0, + 36, 0, 37, 0, 44, 0, 39, 0, 38, 0, + 31, 0, 33, 0, 35, 0, 29, 0, 30, 0, + 32, 0, 34, 0, 13, 0, 1, 0, 5, 0, + 0, 14, 42, 0, 18, 42, 0, 9, 0, 11, + 42, 0, 8, 42, 0, 7, 0, 19, 0, 20, + 5, 0, 10, 5, 0, 6, 5, 41, 0, 12, + 5, 41, 40, 0, 5, 0, 0, 21, 42, 22, + 0, 0, 42, 43, 5, 0, 0, 23, 0, 0, + 4, 0 +}; + +#endif + +#if YYDEBUG != 0 +static const short yyrline[] = { 0, + 65, 67, 69, 71, 74, 77, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, + 93, 97, 102, 107, 112, 116, 121, 126, 133, 138, + 144, 148, 155, 158, 161, 164, 168, 175, 179, 181, + 185 +}; + +static const char * const yytname[] = { "$","error","$undefined.","NEWLINE", +"VERBOSE","FILENAME","ADDLIB","LIST","ADDMOD","CLEAR","CREATE","DELETE","DIRECTORY", +"END","EXTRACT","FULLDIR","HELP","QUIT","REPLACE","SAVE","OPEN","'('","')'", +"','","start","@1","session","command_line","command","extract_command","replace_command", +"clear_command","delete_command","addmod_command","list_command","save_command", +"open_command","create_command","addlib_command","directory_command","optional_filename", +"modulelist","modulename","optcomma","verbose_command","" +}; +#endif + +static const short yyr1[] = { 0, + 25, 24, 26, 26, 27, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 40, 41, 41, 42, 42, 43, 43, + 44 +}; + +static const short yyr2[] = { 0, + 0, 2, 2, 0, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 2, 2, 1, 2, 2, 1, 1, 2, 2, + 3, 4, 1, 0, 3, 0, 3, 0, 1, 0, + 1 +}; + +static const short yydefact[] = { 1, + 4, 0, 19, 41, 20, 0, 27, 38, 24, 0, + 38, 0, 18, 38, 38, 28, 0, 3, 0, 14, + 15, 11, 16, 12, 17, 13, 6, 7, 10, 9, + 8, 36, 26, 30, 25, 36, 22, 23, 29, 5, + 38, 31, 39, 0, 34, 40, 37, 33, 32, 35, + 0, 0, 0 +}; + +static const short yydefgoto[] = { 51, + 1, 2, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 49, 42, 33, 44, 31 +}; + +static const short yypact[] = {-32768, +-32768, 5,-32768,-32768,-32768, -4,-32768,-32768,-32768, 2, +-32768, 21,-32768,-32768,-32768,-32768, 22,-32768, 25,-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, +-32768, 8, -3,-32768, -3, 8, -3, -3,-32768,-32768, +-32768,-32768,-32768, 26, 27, -1,-32768,-32768,-32768,-32768, + 33, 34,-32768 +}; + +static const short yypgoto[] = {-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, +-32768,-32768,-32768,-32768,-32768,-32768, 0, -11,-32768,-32768 +}; + + +#define YYLAST 36 + + +static const short yytable[] = { 35, + 32, -40, 37, 38, -2, 3, 34, -21, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 43, + 50, 43, 15, 16, 17, 36, 39, 40, 41, 46, + 47, 48, 52, 53, 0, 45 +}; + +static const short yycheck[] = { 11, + 5, 5, 14, 15, 0, 1, 5, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 23, + 22, 23, 18, 19, 20, 5, 5, 3, 21, 41, + 5, 5, 0, 0, -1, 36 +}; +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ +#line 3 "/usr/unsupported/share/bison.simple" + +/* Skeleton output parser for bison, + Copyright (C) 1984, 1989, 1990 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +#ifndef alloca +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not GNU C. */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) +#include <alloca.h> +#else /* not sparc */ +#if defined (MSDOS) && !defined (__TURBOC__) +#include <malloc.h> +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +#include <malloc.h> + #pragma alloca +#else /* not MSDOS, __TURBOC__, or _AIX */ +#ifdef __hpux +#ifdef __cplusplus +extern "C" { +void *alloca (unsigned int); +}; +#else /* not __cplusplus */ +void *alloca (); +#endif /* not __cplusplus */ +#endif /* __hpux */ +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc. */ +#endif /* not GNU C. */ +#endif /* alloca not defined. */ + +/* This is the parser code that is written into each bison parser + when the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +/* Note: there must be only one dollar sign in this file. + It is replaced by the list of actions, each action + as one case of the switch. */ + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT return(0) +#define YYABORT return(1) +#define YYERROR goto yyerrlab1 +/* Like YYERROR except do call yyerror. + This remains here temporarily to ease the + transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ +#define YYFAIL goto yyerrlab +#define YYRECOVERING() (!!yyerrstatus) +#define YYBACKUP(token, value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { yychar = (token), yylval = (value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { yyerror ("syntax error: cannot back up"); YYERROR; } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +#ifndef YYPURE +#define YYLEX yylex() +#endif + +#ifdef YYPURE +#ifdef YYLSP_NEEDED +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval, &yylloc) +#endif +#else /* not YYLSP_NEEDED */ +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval) +#endif +#endif /* not YYLSP_NEEDED */ +#endif + +/* If nonreentrant, generate the variables here */ + +#ifndef YYPURE + +int yychar; /* the lookahead symbol */ +YYSTYPE yylval; /* the semantic value of the */ + /* lookahead symbol */ + +#ifdef YYLSP_NEEDED +YYLTYPE yylloc; /* location data for the lookahead */ + /* symbol */ +#endif + +int yynerrs; /* number of parse errors so far */ +#endif /* not YYPURE */ + +#if YYDEBUG != 0 +int yydebug; /* nonzero means print parse trace */ +/* Since this is uninitialized, it does not stop multiple parsers + from coexisting. */ +#endif + +/* YYINITDEPTH indicates the initial size of the parser's stacks */ + +#ifndef YYINITDEPTH +#define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH is the maximum size the stacks can grow to + (effective only if the built-in stack extension method is used). */ + +#if YYMAXDEPTH == 0 +#undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 10000 +#endif + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +int yyparse (void); +#endif + +#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ +#define __yy_memcpy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT) +#else /* not GNU C or C++ */ +#ifndef __cplusplus + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (from, to, count) + char *from; + char *to; + int count; +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#else /* __cplusplus */ + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (char *from, char *to, int count) +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#endif +#endif + +#line 192 "/usr/unsupported/share/bison.simple" + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +#else +#define YYPARSE_PARAM +#define YYPARSE_PARAM_DECL +#endif + +int +yyparse(YYPARSE_PARAM) + YYPARSE_PARAM_DECL +{ + register int yystate; + register int yyn; + register short *yyssp; + register YYSTYPE *yyvsp; + int yyerrstatus; /* number of tokens to shift before error messages enabled */ + int yychar1 = 0; /* lookahead token as an internal (translated) token number */ + + short yyssa[YYINITDEPTH]; /* the state stack */ + YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ + + short *yyss = yyssa; /* refer to the stacks thru separate pointers */ + YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ + +#ifdef YYLSP_NEEDED + YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; + +#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else +#define YYPOPSTACK (yyvsp--, yyssp--) +#endif + + int yystacksize = YYINITDEPTH; + +#ifdef YYPURE + int yychar; + YYSTYPE yylval; + int yynerrs; +#ifdef YYLSP_NEEDED + YYLTYPE yylloc; +#endif +#endif + + YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ + + int yylen; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Starting parse\n"); +#endif + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss - 1; + yyvsp = yyvs; +#ifdef YYLSP_NEEDED + yylsp = yyls; +#endif + +/* Push a new state, which is found in yystate . */ +/* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. */ +yynewstate: + + *++yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Give user a chance to reallocate the stack */ + /* Use copies of these so that the &'s don't force the real ones into memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; +#ifdef YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; +#endif + + /* Get the current used size of the three stacks, in elements. */ + int size = yyssp - yyss + 1; + +#ifdef yyoverflow + /* Each stack pointer address is followed by the size of + the data in use in that stack, in bytes. */ +#ifdef YYLSP_NEEDED + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yyls1, size * sizeof (*yylsp), + &yystacksize); +#else + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yystacksize); +#endif + + yyss = yyss1; yyvs = yyvs1; +#ifdef YYLSP_NEEDED + yyls = yyls1; +#endif +#else /* no yyoverflow */ + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + { + yyerror("parser stack overflow"); + return 2; + } + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; + yyss = (short *) alloca (yystacksize * sizeof (*yyssp)); + __yy_memcpy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp)); + yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp)); + __yy_memcpy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp)); +#ifdef YYLSP_NEEDED + yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp)); + __yy_memcpy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp)); +#endif +#endif /* no yyoverflow */ + + yyssp = yyss + size - 1; + yyvsp = yyvs + size - 1; +#ifdef YYLSP_NEEDED + yylsp = yyls + size - 1; +#endif + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Stack size increased to %d\n", yystacksize); +#endif + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Entering state %d\n", yystate); +#endif + + goto yybackup; + yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Reading a token: "); +#endif + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Now at end of input.\n"); +#endif + } + else + { + yychar1 = YYTRANSLATE(yychar); + +#if YYDEBUG != 0 + if (yydebug) + { + fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise meaning + of a token, for further debugging info. */ +#ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +#endif + fprintf (stderr, ")\n"); + } +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); +#endif + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* count tokens shifted since error; after three, turn off error status. */ + if (yyerrstatus) yyerrstatus--; + + yystate = yyn; + goto yynewstate; + +/* Do the default action for the current state. */ +yydefault: + + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + +/* Do a reduction. yyn is the number of a rule to reduce with. */ +yyreduce: + yylen = yyr2[yyn]; + if (yylen > 0) + yyval = yyvsp[1-yylen]; /* implement default value of the action */ + +#if YYDEBUG != 0 + if (yydebug) + { + int i; + + fprintf (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) + fprintf (stderr, "%s ", yytname[yyrhs[i]]); + fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + + + switch (yyn) { + +case 1: +#line 66 "./arparse.y" +{ prompt(); ; + break;} +case 5: +#line 75 "./arparse.y" +{ prompt(); ; + break;} +case 18: +#line 90 "./arparse.y" +{ ar_end(); return 0; ; + break;} +case 20: +#line 92 "./arparse.y" +{ yyerror("foo"); ; + break;} +case 22: +#line 99 "./arparse.y" +{ ar_extract(yyvsp[0].list); ; + break;} +case 23: +#line 104 "./arparse.y" +{ ar_replace(yyvsp[0].list); ; + break;} +case 24: +#line 109 "./arparse.y" +{ ar_clear(); ; + break;} +case 25: +#line 114 "./arparse.y" +{ ar_delete(yyvsp[0].list); ; + break;} +case 26: +#line 118 "./arparse.y" +{ ar_addmod(yyvsp[0].list); ; + break;} +case 27: +#line 123 "./arparse.y" +{ ar_list(); ; + break;} +case 28: +#line 128 "./arparse.y" +{ ar_save(); ; + break;} +case 29: +#line 135 "./arparse.y" +{ ar_open(yyvsp[0].name,0); ; + break;} +case 30: +#line 140 "./arparse.y" +{ ar_open(yyvsp[0].name,1); ; + break;} +case 31: +#line 146 "./arparse.y" +{ ar_addlib(yyvsp[-1].name,yyvsp[0].list); ; + break;} +case 32: +#line 150 "./arparse.y" +{ ar_directory(yyvsp[-2].name, yyvsp[-1].list, yyvsp[0].name); ; + break;} +case 33: +#line 157 "./arparse.y" +{ yyval.name = yyvsp[0].name; ; + break;} +case 34: +#line 158 "./arparse.y" +{ yyval.name = 0; ; + break;} +case 35: +#line 163 "./arparse.y" +{ yyval.list = yyvsp[-1].list; ; + break;} +case 36: +#line 165 "./arparse.y" +{ yyval.list = 0; ; + break;} +case 37: +#line 170 "./arparse.y" +{ struct list *n = (struct list *) malloc(sizeof(struct list)); + n->next = yyvsp[-2].list; + n->name = yyvsp[0].name; + yyval.list = n; + ; + break;} +case 38: +#line 175 "./arparse.y" +{ yyval.list = 0; ; + break;} +case 41: +#line 187 "./arparse.y" +{ verbose = !verbose; ; + break;} +} + /* the action file gets copied in in place of this dollarsign */ +#line 487 "/usr/unsupported/share/bison.simple" + + yyvsp -= yylen; + yyssp -= yylen; +#ifdef YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + +#ifdef YYLSP_NEEDED + yylsp++; + if (yylen == 0) + { + yylsp->first_line = yylloc.first_line; + yylsp->first_column = yylloc.first_column; + yylsp->last_line = (yylsp-1)->last_line; + yylsp->last_column = (yylsp-1)->last_column; + yylsp->text = 0; + } + else + { + yylsp->last_line = (yylsp+yylen-1)->last_line; + yylsp->last_column = (yylsp+yylen-1)->last_column; + } +#endif + + /* Now "shift" the result of the reduction. + Determine what state that goes to, + based on the state we popped back to + and the rule number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + +yyerrlab: /* here on detecting error */ + + if (! yyerrstatus) + /* If not already recovering from an error, report this error. */ + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + int size = 0; + char *msg; + int x, count; + + count = 0; + /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + size += strlen(yytname[x]) + 15, count++; + msg = (char *) malloc(size + 15); + if (msg != 0) + { + strcpy(msg, "parse error"); + + if (count < 5) + { + count = 0; + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + { + strcat(msg, count == 0 ? ", expecting `" : " or `"); + strcat(msg, yytname[x]); + strcat(msg, "'"); + count++; + } + } + yyerror(msg); + free(msg); + } + else + yyerror ("parse error; also virtual memory exceeded"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror("parse error"); + } + + goto yyerrlab1; +yyerrlab1: /* here on error raised explicitly by an action */ + + if (yyerrstatus == 3) + { + /* if just tried and failed to reuse lookahead token after an error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); +#endif + + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token + after shifting the error token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + +yyerrdefault: /* current state does not do anything special for the error token. */ + +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ + if (yyn) goto yydefault; +#endif + +yyerrpop: /* pop the current state because it cannot handle the error token */ + + if (yyssp == yyss) YYABORT; + yyvsp--; + yystate = *--yyssp; +#ifdef YYLSP_NEEDED + yylsp--; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "Error: state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + +yyerrhandle: + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting error token, "); +#endif + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; +} +#line 191 "./arparse.y" + + +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/gnu/dist/binutils/arparse.h b/gnu/dist/binutils/arparse.h new file mode 100644 index 00000000000..3212fe3af24 --- /dev/null +++ b/gnu/dist/binutils/arparse.h @@ -0,0 +1,26 @@ +typedef union { + char *name; +struct list *list ; + +} YYSTYPE; +#define NEWLINE 258 +#define VERBOSE 259 +#define FILENAME 260 +#define ADDLIB 261 +#define LIST 262 +#define ADDMOD 263 +#define CLEAR 264 +#define CREATE 265 +#define DELETE 266 +#define DIRECTORY 267 +#define END 268 +#define EXTRACT 269 +#define FULLDIR 270 +#define HELP 271 +#define QUIT 272 +#define REPLACE 273 +#define SAVE 274 +#define OPEN 275 + + +extern YYSTYPE yylval; diff --git a/gnu/dist/binutils/arparse.y b/gnu/dist/binutils/arparse.y new file mode 100644 index 00000000000..e8457f6a908 --- /dev/null +++ b/gnu/dist/binutils/arparse.y @@ -0,0 +1,201 @@ +%{ +/* arparse.y - Stange script language parser */ + +/* Copyright (C) 1992, 93, 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 "bfd.h" +#include "bucomm.h" +#include "arsup.h" +extern int verbose; +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/gnu/dist/binutils/arsup.c b/gnu/dist/binutils/arsup.c new file mode 100644 index 00000000000..6e022838a26 --- /dev/null +++ b/gnu/dist/binutils/arsup.c @@ -0,0 +1,456 @@ +/* arsup.c - Archive support for MRI compatibility + Copyright (C) 1992, 93, 94, 95, 96, 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 + +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/gnu/dist/binutils/arsup.h b/gnu/dist/binutils/arsup.h new file mode 100644 index 00000000000..f54a34bcf35 --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/binutils.info b/gnu/dist/binutils/binutils.info new file mode 100644 index 00000000000..ac708e68057 --- /dev/null +++ b/gnu/dist/binutils/binutils.info @@ -0,0 +1,56 @@ +This is Info file binutils.info, produced by Makeinfo-1.64 from the +input file ./binutils.texi. + +START-INFO-DIR-ENTRY +* Binutils: (binutils). The GNU binary utilities "ar", "objcopy", + "objdump", "nm", "nlmconv", "size", + "strings", "strip", and "ranlib". +END-INFO-DIR-ENTRY + + Copyright (C) 1991, 92, 93, 94, 95, 96, 1997 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. + + +Indirect: +binutils.info-1: 969 +binutils.info-2: 49335 + +Tag Table: +(Indirect) +Node: Top969 +Node: ar2006 +Node: ar cmdline4172 +Node: ar scripts10932 +Node: nm16613 +Node: objcopy23161 +Node: objdump32838 +Node: ranlib41125 +Node: size41859 +Node: strings44526 +Node: strip46351 +Node: c++filt49335 +Node: addr2line51896 +Node: nlmconv54293 +Node: Selecting The Target System56918 +Node: Target Selection57935 +Node: Architecture Selection60635 +Node: Linker Emulation Selection61867 +Node: Reporting Bugs62745 +Node: Bug Criteria63496 +Node: Bug Reporting64042 +Node: Index71031 + +End Tag Table diff --git a/gnu/dist/binutils/binutils.info-1 b/gnu/dist/binutils/binutils.info-1 new file mode 100644 index 00000000000..aa7ff88f42b --- /dev/null +++ b/gnu/dist/binutils/binutils.info-1 @@ -0,0 +1,1347 @@ +This is Info file binutils.info, produced by Makeinfo-1.64 from the +input file ./binutils.texi. + +START-INFO-DIR-ENTRY +* Binutils: (binutils). The GNU binary utilities "ar", "objcopy", + "objdump", "nm", "nlmconv", "size", + "strings", "strip", and "ranlib". +END-INFO-DIR-ENTRY + + Copyright (C) 1991, 92, 93, 94, 95, 96, 1997 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. + + +File: binutils.info, Node: Top, Next: ar, Up: (dir) + +Introduction +************ + + This brief manual contains preliminary documentation for the GNU +binary utilities (collectively version 2.8): + +* 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 +* 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 +* Selecting The Target System:: How these utilities determine the target. +* Reporting Bugs:: Reporting Bugs +* Index:: Index + + +File: binutils.info, Node: ar, Next: nm, Prev: Top, Up: Top + +ar +** + + ar [-]P[MOD [RELPOS]] ARCHIVE [MEMBER...] + ar -M [ <mri-script ] + + The GNU `ar' program creates, modifies, and extracts from archives. +An "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 "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. + + GNU `ar' can maintain archives whose members have names of any +length; however, depending on how `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). + + `ar' is considered a binary utility because archives of this sort +are most often used as "libraries" holding commonly needed subroutines. + + `ar' creates an index to the symbols defined in relocatable object +modules in the archive when you specify the modifier `s'. Once +created, this index is updated in the archive whenever `ar' makes a +change to its contents (save for the `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 `nm -s' or `nm --print-armap' to list this index table. +If an archive lacks the table, another form of `ar' called `ranlib' can +be used to add just the table. + + GNU `ar' is designed to be compatible with two different facilities. +You can control its activity using command-line options, like the +different varieties of `ar' on Unix systems; or, if you specify the +single command-line option `-M', you can control it with a script +supplied via standard input, like the MRI "librarian" program. + +* Menu: + +* ar cmdline:: Controlling `ar' on the command line +* ar scripts:: Controlling `ar' with a script + + +File: binutils.info, Node: ar cmdline, Next: ar scripts, Up: ar + +Controlling `ar' on the command line +==================================== + + ar [-]P[MOD [RELPOS]] ARCHIVE [MEMBER...] + + When you use `ar' in the Unix style, `ar' insists on at least two +arguments to execute: one keyletter specifying the *operation* +(optionally accompanied by other keyletters specifying *modifiers*), +and the archive name to act on. + + Most operations can also accept further MEMBER arguments, specifying +particular files to operate on. + + GNU `ar' allows you to mix the operation code P and modifier flags +MOD in any order, within the first command-line argument. + + If you wish, you may begin the first command-line argument with a +dash. + + The P keyletter specifies what operation to execute; it may be any +of the following, but you must specify only one of them: + +`d' + *Delete* modules from the archive. Specify the names of modules to + be deleted as MEMBER...; the archive is untouched if you specify + no files to delete. + + If you specify the `v' modifier, `ar' lists each module as it is + deleted. + +`m' + Use this operation to *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 `m', any members you name in the + MEMBER arguments are moved to the *end* of the archive; you can + use the `a', `b', or `i' modifiers to move them to a specified + place instead. + +`p' + *Print* the specified members of the archive, to the standard + output file. If the `v' modifier is specified, show the member + name before copying its contents to standard output. + + If you specify no MEMBER arguments, all the files in the archive + are printed. + +`q' + *Quick append*; add the files MEMBER... to the end of ARCHIVE, + without checking for replacement. + + The modifiers `a', `b', and `i' do *not* affect this operation; + new members are always placed at the end of the archive. + + The modifier `v' makes `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 `ar s' or `ranlib' explicitly to update the symbol table index. + +`r' + Insert the files MEMBER... into ARCHIVE (with *replacement*). This + operation differs from `q' in that any previously existing members + are deleted if their names match those being added. + + If one of the files named in MEMBER... does not exist, `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 `a', `b', or `i' to request placement + relative to some existing member. + + The modifier `v' used with this operation elicits a line of output + for each file inserted, along with one of the letters `a' or `r' + to indicate whether the file was appended (no old member deleted) + or replaced. + +`t' + Display a *table* listing the contents of ARCHIVE, or those of the + files listed in MEMBER... 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 `v' modifier. + + If you do not specify a MEMBER, all files in the archive are + listed. + + If there is more than one file with the same name (say, `fie') in + an archive (say `b.a'), `ar t b.a fie' lists only the first + instance; to see them all, you must ask for a complete listing--in + our example, `ar t b.a'. + +`x' + *Extract* members (named MEMBER) from the archive. You can use + the `v' modifier with this operation, to request that `ar' list + each name as it extracts it. + + If you do not specify a MEMBER, all files in the archive are + extracted. + + A number of modifiers (MOD) may immediately follow the P keyletter, +to specify variations on an operation's behavior: + +`a' + Add new files *after* an existing member of the archive. If you + use the modifier `a', the name of an existing archive member must + be present as the RELPOS argument, before the ARCHIVE + specification. + +`b' + Add new files *before* an existing member of the archive. If you + use the modifier `b', the name of an existing archive member must + be present as the RELPOS argument, before the ARCHIVE + specification. (same as `i'). + +`c' + *Create* the archive. The specified 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. + +`f' + Truncate names in the archive. GNU `ar' will normally permit file + names of any length. This will cause it to create archives which + are not compatible with the native `ar' program on some systems. + If this is a concern, the `f' modifier may be used to truncate file + names when putting them in the archive. + +`i' + Insert new files *before* an existing member of the archive. If + you use the modifier `i', the name of an existing archive member + must be present as the RELPOS argument, before the ARCHIVE + specification. (same as `b'). + +`l' + This modifier is accepted but not used. + +`o' + Preserve the *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. + +`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 + `ar s' on an archive is equivalent to running `ranlib' on it. + +`u' + Normally, `ar r'... inserts all files listed into the archive. If + you would like to insert *only* those of the files you list that + are newer than existing members of the same names, use this + modifier. The `u' modifier is allowed only for the operation `r' + (replace). In particular, the combination `qu' is not allowed, + since checking the timestamps would lose any speed advantage from + the operation `q'. + +`v' + This modifier requests the *verbose* version of an operation. Many + operations display additional information, such as filenames + processed, when the modifier `v' is appended. + +`V' + This modifier shows the version number of `ar'. + + +File: binutils.info, Node: ar scripts, Prev: ar cmdline, Up: ar + +Controlling `ar' with a script +============================== + + ar -M [ <SCRIPT ] + + If you use the single command-line option `-M' with `ar', you can +control its operation with a rudimentary command language. This form +of `ar' operates interactively if standard input is coming directly +from a terminal. During interactive use, `ar' prompts for input (the +prompt is `AR >'), and continues executing even after errors. If you +redirect standard input to a script file, no prompts are issued, and +`ar' abandons execution (with a nonzero exit code) on any error. + + The `ar' command language is *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 GNU `ar' for developers who already have scripts written +for the MRI "librarian" program. + + The syntax for the `ar' command language is straightforward: + * commands are recognized in upper or lower case; for example, `LIST' + is the same as `list'. In the following descriptions, commands are + shown in upper case for clarity. + + * a single command may appear on each line; it is the first word on + the line. + + * empty lines are allowed, and have no effect. + + * comments are allowed; text after either of the characters `*' or + `;' is ignored. + + * Whenever you use a list of names as part of the argument to an `ar' + command, you can separate the individual names with either commas + or blanks. Commas are shown in the explanations below, for + clarity. + + * `+' is used as a line continuation character; if `+' appears at + the end of a line, the text on the following line is considered + part of the current command. + + Here are the commands you can use in `ar' scripts, or when using +`ar' interactively. Three of them have special significance: + + `OPEN' or `CREATE' specify a "current archive", which is a temporary +file required for most of the other commands. + + `SAVE' commits the changes so far specified by the script. Prior to +`SAVE', commands affect only the temporary copy of the current archive. + +`ADDLIB ARCHIVE' +`ADDLIB ARCHIVE (MODULE, MODULE, ... MODULE)' + Add all the contents of ARCHIVE (or, if specified, each named + MODULE from ARCHIVE) to the current archive. + + Requires prior use of `OPEN' or `CREATE'. + +`ADDMOD MEMBER, MEMBER, ... MEMBER' + Add each named MEMBER as a module in the current archive. + + Requires prior use of `OPEN' or `CREATE'. + +`CLEAR' + Discard the contents of the current archive, cancelling the effect + of any operations since the last `SAVE'. May be executed (with no + effect) even if no current archive is specified. + +`CREATE 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 ARCHIVE until you use `SAVE'. + You can overwrite existing archives; similarly, the contents of any + existing file named ARCHIVE will not be destroyed until `SAVE'. + +`DELETE MODULE, MODULE, ... MODULE' + Delete each listed MODULE from the current archive; equivalent to + `ar -d ARCHIVE MODULE ... MODULE'. + + Requires prior use of `OPEN' or `CREATE'. + +`DIRECTORY ARCHIVE (MODULE, ... MODULE)' +`DIRECTORY ARCHIVE (MODULE, ... MODULE) OUTPUTFILE' + List each named MODULE present in ARCHIVE. The separate command + `VERBOSE' specifies the form of the output: when verbose output is + off, output is like that of `ar -t ARCHIVE MODULE...'. When + verbose output is on, the listing is like `ar -tv ARCHIVE + MODULE...'. + + Output normally goes to the standard output stream; however, if you + specify OUTPUTFILE as a final argument, `ar' directs the output to + that file. + +`END' + Exit from `ar', with a `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 `SAVE' command, + those changes are lost. + +`EXTRACT MODULE, MODULE, ... MODULE' + Extract each named MODULE from the current archive, writing them + into the current directory as separate files. Equivalent to `ar -x + ARCHIVE MODULE...'. + + Requires prior use of `OPEN' or `CREATE'. + +`LIST' + Display full contents of the current archive, in "verbose" style + regardless of the state of `VERBOSE'. The effect is like `ar tv + ARCHIVE'). (This single command is a GNU `ld' enhancement, rather + than present for MRI compatibility.) + + Requires prior use of `OPEN' or `CREATE'. + +`OPEN 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 ARCHIVE until you next use + `SAVE'. + +`REPLACE MODULE, MODULE, ... MODULE' + In the current archive, replace each existing MODULE (named in the + `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 `OPEN' or `CREATE'. + +`VERBOSE' + Toggle an internal flag governing the output from `DIRECTORY'. + When the flag is on, `DIRECTORY' output matches output from `ar + -tv '.... + +`SAVE' + Commit your changes to the current archive, and actually save it + as a file with the name specified in the last `CREATE' or `OPEN' + command. + + Requires prior use of `OPEN' or `CREATE'. + + +File: binutils.info, Node: nm, Next: objcopy, Prev: ar, Up: Top + +nm +** + + 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 RADIX | --radix=RADIX ] [ -P | --portability ] + [ --target=BFDNAME ] [ -f FORMAT | --format=FORMAT ] + [ --defined-only ] [-l | --line-numbers ] + [ --no-demangle ] [ -V | --version ] [ --help ] [ OBJFILE... ] + + GNU `nm' lists the symbols from object files OBJFILE.... If no +object files are listed as arguments, `nm' assumes `a.out'. + + For each symbol, `nm' shows: + + * The symbol value, in the radix selected by options (see below), or + hexadecimal by default. + + * 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). + + `A' + The symbol's value is absolute, and will not be changed by + further linking. + + `B' + The symbol is in the uninitialized data section (known as + BSS). + + `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 *Note Linker options: (ld.info)Options. + + `D' + The symbol is in the initialized data section. + + `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. + + `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. + + `N' + The symbol is a debugging symbol. + + `R' + The symbol is in a read only data section. + + `S' + The symbol is in an uninitialized data section for small + objects. + + `T' + The symbol is in the text (code) section. + + `U' + The symbol is undefined. + + `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. + + `-' + 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 + *Note Stabs: (stabs.info)Top. + + `?' + The symbol type is unknown, or object file format specific. + + * The symbol name. + + The long and short forms of options, shown here as alternatives, are +equivalent. + +`-A' +`-o' +`--print-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. + +`-a' +`--debug-syms' + Display all symbols, even debugger-only symbols; normally these + are not listed. + +`-B' + The same as `--format=bsd' (for compatibility with the MIPS `nm'). + +`-C' +`--demangle' + Decode ("demangle") low-level symbol names into user-level names. + Besides removing any initial underscore prepended by the system, + this makes C++ function names readable. *Note c++filt::, for more + information on demangling. + +`--no-demangle' + Do not demangle low-level symbol names. This is the default. + +`-D' +`--dynamic' + Display the dynamic symbols rather than the normal symbols. This + is only meaningful for dynamic objects, such as certain types of + shared libraries. + +`-f FORMAT' +`--format=FORMAT' + Use the output format FORMAT, which can be `bsd', `sysv', or + `posix'. The default is `bsd'. Only the first character of + FORMAT is significant; it can be either upper or lower case. + +`-g' +`--extern-only' + Display only external symbols. + +`-l' +`--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. + +`-n' +`-v' +`--numeric-sort' + Sort symbols numerically by their addresses, rather than + alphabetically by their names. + +`-p' +`--no-sort' + Do not bother to sort the symbols in any order; print them in the + order encountered. + +`-P' +`--portability' + Use the POSIX.2 standard output format instead of the default + format. Equivalent to `-f posix'. + +`-s' +`--print-armap' + When listing symbols from archive members, include the index: a + mapping (stored in the archive by `ar' or `ranlib') of which + modules contain definitions for which names. + +`-r' +`--reverse-sort' + Reverse the order of the sort (whether numeric or alphabetic); let + the last come first. + +`--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. + +`-t RADIX' +`--radix=RADIX' + Use RADIX as the radix for printing the symbol values. It must be + `d' for decimal, `o' for octal, or `x' for hexadecimal. + +`--target=BFDNAME' + Specify an object code format other than your system's default + format. *Note Target Selection::, for more information. + +`-u' +`--undefined-only' + Display only undefined symbols (those external to each object + file). + +`--defined-only' + Display only defined symbols for each object file. + +`-V' +`--version' + Show the version number of `nm' and exit. + +`--help' + Show a summary of the options to `nm' and exit. + + +File: binutils.info, Node: objcopy, Next: objdump, Prev: nm, Up: Top + +objcopy +******* + + objcopy [ -F BFDNAME | --target=BFDNAME ] + [ -I BFDNAME | --input-target=BFDNAME ] + [ -O BFDNAME | --output-target=BFDNAME ] + [ -S | --strip-all ] [ -g | --strip-debug ] + [ -K SYMBOLNAME | --keep-symbol=SYMBOLNAME ] + [ -N SYMBOLNAME | --strip-symbol=SYMBOLNAME ] + [ -x | --discard-all ] [ -X | --discard-locals ] + [ -b BYTE | --byte=BYTE ] + [ -i INTERLEAVE | --interleave=INTERLEAVE ] + [ -R SECTIONNAME | --remove-section=SECTIONNAME ] + [ -p | --preserve-dates ] [ --debugging ] + [ --gap-fill=VAL ] [ --pad-to=ADDRESS ] + [ --set-start=VAL ] [ --adjust-start=INCR ] + [ --adjust-vma=INCR ] + [ --adjust-section-vma=SECTION{=,+,-}VAL ] + [ --adjust-warnings ] [ --no-adjust-warnings ] + [ --set-section-flags=SECTION=FLAGS ] + [ --add-section=SECTIONNAME=FILENAME ] + [ --change-leading-char ] [ --remove-leading-char ] + [ --weaken ] + [ -v | --verbose ] [ -V | --version ] [ --help ] + INFILE [OUTFILE] + + The GNU `objcopy' utility copies the contents of an object file to +another. `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 +`objcopy' is controlled by command-line options. + + `objcopy' creates temporary files to do its translations and deletes +them afterward. `objcopy' uses BFD to do all its translation work; it +has access to all the formats described in BFD and thus is able to +recognize most formats without being told explicitly. *Note BFD: +(ld.info)BFD. + + `objcopy' can be used to generate S-records by using an output +target of `srec' (e.g., use `-O srec'). + + `objcopy' can be used to generate a raw binary file by using an +output target of `binary' (e.g., use `-O binary'). When `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 `-S' to remove sections containing debugging information. In +some cases `-R' will be useful to remove sections which contain +information which is not needed by the binary file. + +`INFILE' +`OUTFILE' + The source and output files, respectively. If you do not specify + OUTFILE, `objcopy' creates a temporary file and destructively + renames the result with the name of INFILE. + +`-I BFDNAME' +`--input-target=BFDNAME' + Consider the source file's object format to be BFDNAME, rather than + attempting to deduce it. *Note Target Selection::, for more + information. + +`-O BFDNAME' +`--output-target=BFDNAME' + Write the output file using the object format BFDNAME. *Note + Target Selection::, for more information. + +`-F BFDNAME' +`--target=BFDNAME' + Use 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. *Note Target Selection::, for more information. + +`-R SECTIONNAME' +`--remove-section=SECTIONNAME' + Remove any section named 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. + +`-S' +`--strip-all' + Do not copy relocation and symbol information from the source file. + +`-g' +`--strip-debug' + Do not copy debugging symbols from the source file. + +`--strip-unneeded' + Strip all symbols that are not needed for relocation processing. + +`-K SYMBOLNAME' +`--keep-symbol=SYMBOLNAME' + Copy only symbol SYMBOLNAME from the source file. This option may + be given more than once. + +`-N SYMBOLNAME' +`--strip-symbol=SYMBOLNAME' + Do not copy symbol SYMBOLNAME from the source file. This option + may be given more than once, and may be combined with strip options + other than `-K'. + +`-x' +`--discard-all' + Do not copy non-global symbols from the source file. + +`-X' +`--discard-locals' + Do not copy compiler-generated local symbols. (These usually + start with `L' or `.'.) + +`-b BYTE' +`--byte=BYTE' + Keep only every BYTEth byte of the input file (header data is not + affected). BYTE can be in the range from 0 to INTERLEAVE-1, where + INTERLEAVE is given by the `-i' or `--interleave' option, or the + default of 4. This option is useful for creating files to program + ROM. It is typically used with an `srec' output target. + +`-i INTERLEAVE' +`--interleave=INTERLEAVE' + Only copy one out of every INTERLEAVE bytes. Select which byte to + copy with the -B or `--byte' option. The default is 4. `objcopy' + ignores this option if you do not specify either `-b' or `--byte'. + +`-p' +`--preserve-dates' + Set the access and modification dates of the output file to be the + same as those of the input file. + +`--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. + +`--gap-fill VAL' + Fill gaps between sections with VAL. This is done by increasing + the size of the section with the lower address, and filling in the + extra space created with VAL. + +`--pad-to ADDRESS' + Pad the output file up to the virtual address ADDRESS. This is + done by increasing the size of the last section. The extra space + is filled in with the value specified by `--gap-fill' (default + zero). + +`--set-start VAL' + Set the address of the new file to VAL. Not all object file + formats support setting the start address. + +`--adjust-start INCR' + Adjust the start address by adding INCR. Not all object file + formats support setting the start address. + +`--adjust-vma INCR' + Adjust the address of all sections, as well as the start address, + by adding 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. + +`--adjust-section-vma SECTION{=,+,-}VAL' + Set or adjust the address of the named SECTION. If `=' is used, + the section address is set to VAL. Otherwise, VAL is added to or + subtracted from the section address. See the comments under + `--adjust-vma', above. If SECTION does not exist in the input + file, a warning will be issued, unless `--no-adjust-warnings' is + used. + +`--adjust-warnings' + If `--adjust-section-vma' is used, and the named section does not + exist, issue a warning. This is the default. + +`--no-adjust-warnings' + Do not issue a warning if `--adjust-section-vma' is used, even if + the named section does not exist. + +`--set-section-flags SECTION=FLAGS' + Set the flags for the named section. The FLAGS argument is a + comma separated string of flag names. The recognized names are + `alloc', `load', `readonly', `code', `data', and `rom'. Not all + flags are meaningful for all object file formats. + +`--add-section SECTIONNAME=FILENAME' + Add a new section named SECTIONNAME while copying the file. The + contents of the new section are taken from the file 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. + +`--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 + `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. + +`--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 `--change-leading-char' + because it always changes the symbol name when appropriate, + regardless of the object file format of the output file. + +`--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 `-R' option to the linker. This option is only + effective when using an object file format which supports weak + symbols. + +`-V' +`--version' + Show the version number of `objcopy'. + +`-v' +`--verbose' + Verbose output: list all object files modified. In the case of + archives, `objcopy -V' lists all members of the archive. + +`--help' + Show a summary of the options to `objcopy'. + + +File: binutils.info, Node: objdump, Next: ranlib, Prev: objcopy, Up: Top + +objdump +******* + + objdump [ -a | --archive-headers ] + [ -b BFDNAME | --target=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 SECTION | --section=SECTION ] + [ -l | --line-numbers ] [ -S | --source ] + [ -m MACHINE | --architecture=MACHINE ] + [ -r | --reloc ] [ -R | --dynamic-reloc ] + [ -s | --full-contents ] [ --stabs ] + [ -t | --syms ] [ -T | --dynamic-syms ] [ -x | --all-headers ] + [ -w | --wide ] [ --start-address=ADDRESS ] + [ --stop-address=ADDRESS ] + [ --prefix-addresses] [ --[no-]show-raw-insn ] + [ --adjust-vma=OFFSET ] + [ --version ] [ --help ] + OBJFILE... + + `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. + + OBJFILE... are the object files to be examined. When you specify +archives, `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 `-l' must be given. + +`-a' +`--archive-header' + If any of the OBJFILE files are archives, display the archive + header information (in a format similar to `ls -l'). Besides the + information you could list with `ar tv', `objdump -a' shows the + object file format of each archive member. + +`--adjust-vma=OFFSET' + When dumping information, first add 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. + +`-b BFDNAME' +`--target=BFDNAME' + Specify that the object-code format for the object files is + BFDNAME. This option may not be necessary; OBJDUMP can + automatically recognize many formats. + + For example, + objdump -b oasys -m vax -h fu.o + + displays summary information from the section headers (`-h') of + `fu.o', which is explicitly identified (`-m') as a VAX object file + in the format produced by Oasys compilers. You can list the + formats available with the `-i' option. *Note Target Selection::, + for more information. + +`-C' +`--demangle' + Decode ("demangle") low-level symbol names into user-level names. + Besides removing any initial underscore prepended by the system, + this makes C++ function names readable. *Note c++filt::, for more + information on demangling. + +`--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. + +`-d' +`--disassemble' + Display the assembler mnemonics for the machine instructions from + OBJFILE. This option only disassembles those sections which are + expected to contain instructions. + +`-D' +`--disassemble-all' + Like `-d', but disassemble the contents of all sections, not just + those expected to contain instructions. + +`--prefix-addresses' + When disassembling, print the complete address on each line. This + is the older disassembly format. + +`--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. + +`-EB' +`-EL' +`--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. + +`-f' +`--file-header' + Display summary information from the overall header of each of the + OBJFILE files. + +`-h' +`--section-header' +`--header' + Display summary information from the section headers of the object + file. + + File segments may be relocated to nonstandard addresses, for + example by using the `-Ttext', `-Tdata', or `-Tbss' options to + `ld'. However, some object file formats, such as a.out, do not + store the starting address of the file segments. In those + situations, although `ld' relocates the sections correctly, using + `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. + +`--help' + Print a summary of the options to `objdump' and exit. + +`-i' +`--info' + Display a list showing all architectures and object formats + available for specification with `-b' or `-m'. + +`-j NAME' +`--section=NAME' + Display information only for section NAME. + +`-l' +`--line-numbers' + Label the display (using debugging information) with the filename + and source line numbers corresponding to the object code or relocs + shown. Only useful with `-d', `-D', or `-r'. + +`-m MACHINE' +`--architecture=MACHINE' + Specify the architecture to use when disassembling object files. + This can be useful when disasembling object files which do not + describe architecture information, such as S-records. You can + list the available architectures with the `-i' option. + +`-r' +`--reloc' + Print the relocation entries of the file. If used with `-d' or + `-D', the relocations are printed interspersed with the + disassembly. + +`-R' +`--dynamic-reloc' + Print the dynamic relocation entries of the file. This is only + meaningful for dynamic objects, such as certain types of shared + libraries. + +`-s' +`--full-contents' + Display the full contents of any sections requested. + +`-S' +`--source' + Display source code intermixed with disassembly, if possible. + Implies `-d'. + +`--show-raw-insn' + When disassembling instructions, print the instruction in hex as + well as in symbolic form. This is the default except when + `--prefix-addresses' is used. + +`--no-show-raw-insn' + When disassembling instructions, do not print the instruction + bytes. This is the default when `--prefix-addresses' is used. + +`--stabs' + 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 `.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 `--syms' output. For more information on stabs symbols, see + *Note Stabs: (stabs.info)Top. + +`--start-address=ADDRESS' + Start displaying data at the specified address. This affects the + output of the `-d', `-r' and `-s' options. + +`--stop-address=ADDRESS' + Stop displaying data at the specified address. This affects the + output of the `-d', `-r' and `-s' options. + +`-t' +`--syms' + Print the symbol table entries of the file. This is similar to + the information provided by the `nm' program. + +`-T' +`--dynamic-syms' + 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 `nm' + program when given the `-D' (`--dynamic') option. + +`--version' + Print the version number of `objdump' and exit. + +`-x' +`--all-header' + Display all available header information, including the symbol + table and relocation entries. Using `-x' is equivalent to + specifying all of `-a -f -h -r -t'. + +`-w' +`--wide' + Format some lines for output devices that have more than 80 + columns. + + +File: binutils.info, Node: ranlib, Next: size, Prev: objdump, Up: Top + +ranlib +****** + + ranlib [-vV] ARCHIVE + + `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 `nm -s' or `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 GNU `ranlib' program is another form of GNU `ar'; running +`ranlib' is completely equivalent to executing `ar -s'. *Note ar::. + +`-v' +`-V' + Show the version number of `ranlib'. + + +File: binutils.info, Node: size, Next: strings, Prev: ranlib, Up: Top + +size +**** + + size [ -A | -B | --format=COMPATIBILITY ] + [ --help ] [ -d | -o | -x | --radix=NUMBER ] + [ --target=BFDNAME ] [ -V | --version ] + OBJFILE... + + The GNU `size' utility lists the section sizes--and the total +size--for each of the object or archive files OBJFILE in its argument +list. By default, one line of output is generated for each object file +or each module in an archive. + + OBJFILE... are the object files to be examined. + + The command line options have the following meanings: + +`-A' +`-B' +`--format=COMPATIBILITY' + Using one of these options, you can choose whether the output from + GNU `size' resembles output from System V `size' (using `-A', or + `--format=sysv'), or Berkeley `size' (using `-B', or + `--format=berkeley'). The default is the one-line format similar + to Berkeley's. + + Here is an example of the Berkeley (default) format of output from + `size': + size --format=Berkeley ranlib size + text data bss dec hex filename + 294880 81920 11592 388392 5ed28 ranlib + 294880 81920 11888 388688 5ee50 size + + This is the same data, but displayed closer to System V + conventions: + + 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 + +`--help' + Show a summary of acceptable arguments and options. + +`-d' +`-o' +`-x' +`--radix=NUMBER' + Using one of these options, you can control whether the size of + each section is given in decimal (`-d', or `--radix=10'); octal + (`-o', or `--radix=8'); or hexadecimal (`-x', or `--radix=16'). + In `--radix=NUMBER', only the three values (8, 10, 16) are + supported. The total size is always given in two radices; decimal + and hexadecimal for `-d' or `-x' output, or octal and hexadecimal + if you're using `-o'. + +`--target=BFDNAME' + Specify that the object-code format for OBJFILE is BFDNAME. This + option may not be necessary; `size' can automatically recognize + many formats. *Note Target Selection::, for more information. + +`-V' +`--version' + Display the version number of `size'. + + +File: binutils.info, Node: strings, Next: strip, Prev: size, Up: Top + +strings +******* + + strings [-afov] [-MIN-LEN] [-n MIN-LEN] [-t RADIX] [-] + [--all] [--print-file-name] [--bytes=MIN-LEN] + [--radix=RADIX] [--target=BFDNAME] + [--help] [--version] FILE... + + For each FILE given, GNU `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. + + `strings' is mainly useful for determining the contents of non-text +files. + +`-a' +`--all' +`-' + Do not scan only the initialized and loaded sections of object + files; scan the whole files. + +`-f' +`--print-file-name' + Print the name of the file before each string. + +`--help' + Print a summary of the program usage on the standard output and + exit. + +`-MIN-LEN' +`-n MIN-LEN' +`--bytes=MIN-LEN' + Print sequences of characters that are at least MIN-LEN characters + long, instead of the default 4. + +`-o' + Like `-t o'. Some other versions of `strings' have `-o' act like + `-t d' instead. Since we can not be compatible with both ways, we + simply chose one. + +`-t RADIX' +`--radix=RADIX' + Print the offset within the file before each string. The single + character argument specifies the radix of the offset--`o' for + octal, `x' for hexadecimal, or `d' for decimal. + +`--target=BFDNAME' + Specify an object code format other than your system's default + format. *Note Target Selection::, for more information. + +`-v' +`--version' + Print the program version number on the standard output and exit. + + +File: binutils.info, Node: strip, Next: c++filt, Prev: strings, Up: Top + +strip +***** + + strip [ -F BFDNAME | --target=BFDNAME | --target=BFDNAME ] + [ -I BFDNAME | --input-target=BFDNAME ] + [ -O BFDNAME | --output-target=BFDNAME ] + [ -s | --strip-all ] [ -S | -g | --strip-debug ] + [ -K SYMBOLNAME | --keep-symbol=SYMBOLNAME ] + [ -N SYMBOLNAME | --strip-symbol=SYMBOLNAME ] + [ -x | --discard-all ] [ -X | --discard-locals ] + [ -R SECTIONNAME | --remove-section=SECTIONNAME ] + [ -o FILE ] [ -p | --preserve-dates ] + [ -v | --verbose ] [ -V | --version ] [ --help ] + OBJFILE... + + GNU `strip' discards all symbols from object files OBJFILE. The +list of object files may include archives. At least one object file +must be given. + + `strip' modifies the files named in its argument, rather than +writing modified copies under different names. + +`-F BFDNAME' +`--target=BFDNAME' + Treat the original OBJFILE as a file with the object code format + BFDNAME, and rewrite it in the same format. *Note Target + Selection::, for more information. + +`--help' + Show a summary of the options to `strip' and exit. + +`-I BFDNAME' +`--input-target=BFDNAME' + Treat the original OBJFILE as a file with the object code format + BFDNAME. *Note Target Selection::, for more information. + +`-O BFDNAME' +`--output-target=BFDNAME' + Replace OBJFILE with a file in the output format BFDNAME. *Note + Target Selection::, for more information. + +`-R SECTIONNAME' +`--remove-section=SECTIONNAME' + Remove any section named 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. + +`-s' +`--strip-all' + Remove all symbols. + +`-g' +`-S' +`--strip-debug' + Remove debugging symbols only. + +`--strip-unneeded' + Remove all symbols that are not needed for relocation processing. + +`-K SYMBOLNAME' +`--keep-symbol=SYMBOLNAME' + Keep only symbol SYMBOLNAME from the source file. This option may + be given more than once. + +`-N SYMBOLNAME' +`--strip-symbol=SYMBOLNAME' + Remove symbol SYMBOLNAME from the source file. This option may be + given more than once, and may be combined with strip options other + than `-K'. + +`-o FILE' + Put the stripped output in FILE, rather than replacing the + existing file. When this argument is used, only one OBJFILE + argument may be specified. + +`-p' +`--preserve-dates' + Preserve the access and modification dates of the file. + +`-x' +`--discard-all' + Remove non-global symbols. + +`-X' +`--discard-locals' + Remove compiler-generated local symbols. (These usually start + with `L' or `.'.) + +`-V' +`--version' + Show the version number for `strip'. + +`-v' +`--verbose' + Verbose output: list all object files modified. In the case of + archives, `strip -v' lists all members of the archive. + diff --git a/gnu/dist/binutils/binutils.info-2 b/gnu/dist/binutils/binutils.info-2 new file mode 100644 index 00000000000..4adbdd5944c --- /dev/null +++ b/gnu/dist/binutils/binutils.info-2 @@ -0,0 +1,771 @@ +This is Info file binutils.info, produced by Makeinfo-1.64 from the +input file ./binutils.texi. + +START-INFO-DIR-ENTRY +* Binutils: (binutils). The GNU binary utilities "ar", "objcopy", + "objdump", "nm", "nlmconv", "size", + "strings", "strip", and "ranlib". +END-INFO-DIR-ENTRY + + Copyright (C) 1991, 92, 93, 94, 95, 96, 1997 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. + + +File: binutils.info, Node: c++filt, Next: addr2line, Prev: strip, Up: Top + +c++filt +******* + + c++filt [ -_ | --strip-underscores ] + [ -n | --no-strip-underscores ] + [ -s FORMAT | --format=FORMAT ] + [ --help ] [ --version ] [ SYMBOL... ] + + 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 "mangling"). +The `c++filt' program does the inverse mapping: it decodes +("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 `c++filt' to decipher individual symbols: + + c++filt SYMBOL + + If no SYMBOL arguments are given, `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. + +`-_' +`--strip-underscores' + On some systems, both the C and C++ compilers put an underscore in + front of every name. For example, the C name `foo' gets the + low-level name `_foo'. This option removes the initial + underscore. Whether `c++filt' removes the underscore by default + is target dependent. + +`-n' +`--no-strip-underscores' + Do not remove the initial underscore. + +`-s FORMAT' +`--format=FORMAT' + GNU `nm' can decode three different methods of mangling, used by + different C++ compilers. The argument to this option selects which + method it uses: + + `gnu' + the one used by the GNU compiler (the default method) + + `lucid' + the one used by the Lucid compiler + + `arm' + the one specified by the C++ Annotated Reference Manual + +`--help' + Print a summary of the options to `c++filt' and exit. + +`--version' + Print the version number of `c++filt' and exit. + + *Warning:* `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, + + c++filt SYMBOL + + may in a future release become + + c++filt OPTION SYMBOL + + +File: binutils.info, Node: addr2line, Next: nlmconv, Prev: c++filt, Up: Top + +addr2line +********* + + addr2line [ -b BFDNAME | --target=BFDNAME ] + [ -C | --demangle ] + [ -e FILENAME | --exe=FILENAME ] + [ -f | --functions ] [ -s | --basename ] + [ -H | --help ] [ -V | --version ] + [ addr addr ... ] + + `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 `-e' option. The +default is `a.out'. + + `addr2line' has two modes of operation. + + In the first, hexadecimal addresses are specified on the command +line, and `addr2line' displays the file name and line number for each +address. + + In the second, `addr2line' reads hexadecimal addresses from standard +input, and prints the file name and line number for each address on +standard output. In this mode, `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 +`-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, `addr2line' +will print two question marks in their place. If the line number can +not be determined, `addr2line' will print 0. + + The long and short forms of options, shown here as alternatives, are +equivalent. + +`-b BFDNAME' +`--target=BFDNAME' + Specify that the object-code format for the object files is + BFDNAME. + +`-C' +`--demangle' + Decode ("demangle") low-level symbol names into user-level names. + Besides removing any initial underscore prepended by the system, + this makes C++ function names readable. *Note c++filt::, for more + information on demangling. + +`-e FILENAME' +`--exe=FILENAME' + Specify the name of the executable for which addresses should be + translated. The default file is `a.out'. + +`-f' +`--functions' + Display function names as well as file and line number information. + +`-s' +`--basenames' + Display only the base of each file name. + + +File: binutils.info, Node: nlmconv, Next: Selecting The Target System, Prev: addr2line, Up: Top + +nlmconv +******* + + `nlmconv' converts a relocatable object file into a NetWare Loadable +Module. + + *Warning:* `nlmconv' is not always built as part of the binary + utilities, since it is only useful for NLM targets. + + nlmconv [ -I BFDNAME | --input-target=BFDNAME ] + [ -O BFDNAME | --output-target=BFDNAME ] + [ -T HEADERFILE | --header-file=HEADERFILE ] + [ -d | --debug] [ -l LINKER | --linker=LINKER ] + [ -h | --help ] [ -V | --version ] + INFILE OUTFILE + + `nlmconv' converts the relocatable `i386' object file INFILE into +the NetWare Loadable Module OUTFILE, optionally reading HEADERFILE for +NLM header information. For instructions on writing the NLM command +file language used in header files, see the `linkers' section, +`NLMLINK' in particular, of the `NLM Development and Tools Overview', +which is part of the NLM Software Developer's Kit ("NLM SDK"), +available from Novell, Inc. `nlmconv' uses the GNU Binary File +Descriptor library to read INFILE; see *Note BFD: (ld.info)BFD, for +more information. + + `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, `nlmconv' calls the linker for you. + +`-I BFDNAME' +`--input-target=BFDNAME' + Object format of the input file. `nlmconv' can usually determine + the format of a given file (so no default is necessary). *Note + Target Selection::, for more information. + +`-O BFDNAME' +`--output-target=BFDNAME' + Object format of the output file. `nlmconv' infers the output + format based on the input format, e.g. for a `i386' input file the + output format is `nlm32-i386'. *Note Target Selection::, for more + information. + +`-T HEADERFILE' +`--header-file=HEADERFILE' + Reads HEADERFILE for NLM header information. For instructions on + writing the NLM command file language used in header files, see + see the `linkers' section, of the `NLM Development and Tools + Overview', which is part of the NLM Software Developer's Kit, + available from Novell, Inc. + +`-d' +`--debug' + Displays (on standard error) the linker command line used by + `nlmconv'. + +`-l LINKER' +`--linker=LINKER' + Use LINKER for any linking. LINKER can be an abosolute or a + relative pathname. + +`-h' +`--help' + Prints a usage summary. + +`-V' +`--version' + Prints the version number for `nlmconv'. + + +File: binutils.info, Node: Selecting The Target System, Next: Reporting Bugs, Prev: nlmconv, Up: Top + +Selecting the target system +*************************** + + You can specify three aspects of the target system to the GNU binary +file utilities, each in several ways: + + * the target + + * the architecture + + * the linker emulation (which applies to the linker only) + + 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 +`--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 "native" (on hosts with the +same type as the target system). + +* Menu: + +* Target Selection:: +* Architecture Selection:: +* Linker Emulation Selection:: + + +File: binutils.info, Node: Target Selection, Next: Architecture Selection, Up: Selecting The Target System + +Target Selection +================ + + A "target" is an object file format. A given target may be +supported for multiple architectures (*note Architecture Selection::.). +A target selection may also have variations for different operating +systems or architectures. + + The command to list valid target values is `objdump -i' (the first +column of output contains the relevant information). + + Some sample values are: `a.out-hp300bsd', `ecoff-littlemips', +`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 `config.sub' which is included with the +sources. + + Some sample configuration triplets are: `m68k-hp-bsd', +`mips-dec-ultrix', `sparc-sun-sunos'. + +`objdump' Target +---------------- + + Ways to specify: + + 1. command line option: `-b' or `--target' + + 2. environment variable `GNUTARGET' + + 3. deduced from the input file + +`objcopy' and `strip' Input Target +---------------------------------- + + Ways to specify: + + 1. command line options: `-I' or `--input-target', or `-F' or + `--target' + + 2. environment variable `GNUTARGET' + + 3. deduced from the input file + +`objcopy' and `strip' Output Target +----------------------------------- + + Ways to specify: + + 1. command line options: `-O' or `--output-target', or `-F' or + `--target' + + 2. the input target (see "`objcopy' and `strip' Input Target" above) + + 3. environment variable `GNUTARGET' + + 4. deduced from the input file + +`nm', `size', and `strings' Target +---------------------------------- + + Ways to specify: + + 1. command line option: `--target' + + 2. environment variable `GNUTARGET' + + 3. deduced from the input file + +Linker Input Target +------------------- + + Ways to specify: + + 1. command line option: `-b' or `--format' (*note Options: + (ld.info)Options.) + + 2. script command `TARGET' (*note Option Commands: (ld.info)Option + Commands.) + + 3. environment variable `GNUTARGET' (*note Environment: + (ld.info)Environment.) + + 4. the default target of the selected linker emulation (*note Linker + Emulation Selection::.) + +Linker Output Target +-------------------- + + Ways to specify: + + 1. command line option: `-oformat' (*note Options: (ld.info)Options.) + + 2. script command `OUTPUT_FORMAT' (*note Option Commands: + (ld.info)Option Commands.) + + 3. the linker input target (see "Linker Input Target" above) + + +File: binutils.info, Node: Architecture Selection, Next: Linker Emulation Selection, Prev: Target Selection, Up: Selecting The Target System + +Architecture selection +====================== + + An "architecture" is a type of 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 CPU. + + The command to list valid architecture values is `objdump -i' (the +second column contains the relevant information). + + Sample values: `m68k:68020', `mips:3000', `sparc'. + +`objdump' Architecture +---------------------- + + Ways to specify: + + 1. command line option: `-m' or `--architecture' + + 2. deduced from the input file + +`objcopy', `nm', `size', `strings' Architecture +----------------------------------------------- + + Ways to specify: + + 1. deduced from the input file + +Linker Input Architecture +------------------------- + + Ways to specify: + + 1. deduced from the input file + +Linker Output Architecture +-------------------------- + + Ways to specify: + + 1. script command `OUTPUT_ARCH' (*note Option Commands: + (ld.info)Option Commands.) + + 2. the default architecture from the linker output target (*note + Target Selection::.) + + +File: binutils.info, Node: Linker Emulation Selection, Prev: Architecture Selection, Up: Selecting The Target System + +Linker emulation selection +========================== + + A linker "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 + + * the linker script + + * the target + + * several "hook" functions that are run at certain stages of the + linking process to do special things that some targets require + + The command to list valid linker emulation values is `ld -V'. + + Sample values: `hp300bsd', `mipslit', `sun4'. + + Ways to specify: + + 1. command line option: `-m' (*note Options: (ld.info)Options.) + + 2. environment variable `LDEMULATION' + + 3. compiled-in `DEFAULT_EMULATION' from `Makefile', which comes from + `EMUL' in `config/TARGET.mt' + + +File: binutils.info, Node: Reporting Bugs, Next: Index, Prev: Selecting The Target System, Up: Top + +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 + + +File: binutils.info, Node: Bug Criteria, Next: Bug Reporting, Up: Reporting Bugs + +Have you found a bug? +===================== + + If you are not sure whether you have found a bug, here are some +guidelines: + + * If a binary utility gets a fatal signal, for any input whatever, + that is a bug. Reliable utilities never crash. + + * If a binary utility produces an error message for valid input, + that is a bug. + + * If you are an experienced user of binary utilities, your + suggestions for improvement are welcome in any case. + + +File: binutils.info, Node: Bug Reporting, Prev: Bug Criteria, Up: Reporting Bugs + +How to report bugs +================== + + A number of companies and individuals offer support for 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 `etc/SERVICE' in the GNU Emacs distribution. + + In any event, we also recommend that you send bug reports for the +binary utilities to `bug-gnu-utils@prep.ai.mit.edu'. + + The fundamental principle of reporting bugs usefully is this: +*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 *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: + + * The version of the utility. Each utility announces it if you + start it with the `--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. + + * Any patches you may have applied to the source, including any + patches made to the `BFD' library. + + * The type of machine you are using, and the operating system name + and version number. + + * What compiler (and its version) was used to compile the + utilities--e.g. "`gcc-2.7'". + + * 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. + + * 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 GNU programs + (e.g., `gcc', `gas', and/or the GNU `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 `gcc', or whatever, was + used to produce the object files. Also say how `gcc', or + whatever, was configured. + + * 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. + + * If you wish to suggest changes to the source, send us context + diffs, as generated by `diff' with the `-u', `-c', or `-p' option. + Always send diffs from the old file to the new file. If you even + discuss something in the `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. + + Here are some things that are not necessary: + + * 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 *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. + + * 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. + + * 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. + + +File: binutils.info, Node: Index, Prev: Reporting Bugs, Up: Top + +Index +***** + +* Menu: + +* .stab: objdump. +* ar compatibility: ar. +* nm compatibility: nm. +* nm format: nm. +* size display format: size. +* size number format: size. +* addr2line: addr2line. +* address to file name and line number: addr2line. +* all header information, object file: objdump. +* ar: ar. +* architecture: objdump. +* architectures available: objdump. +* archive contents: ranlib. +* archive headers: objdump. +* archives: ar. +* bug criteria: Bug Criteria. +* bug reports: Bug Reporting. +* bugs: Reporting Bugs. +* bugs, reporting: Bug Reporting. +* c++filt: c++filt. +* collections of files: ar. +* compatibility, ar: ar. +* contents of archive: ar cmdline. +* crash: Bug Criteria. +* creating archives: ar cmdline. +* dates in archive: ar cmdline. +* debug symbols: objdump. +* debugging symbols: nm. +* deleting from archive: ar cmdline. +* demangling C++ symbols: c++filt. +* demangling in nm: nm. +* demangling in objdump <1>: objdump. +* demangling in objdump: addr2line. +* disassembling object code: objdump. +* disassembly architecture: objdump. +* disassembly endianness: objdump. +* disassembly, with source: objdump. +* discarding symbols: strip. +* dynamic relocation entries, in object file: objdump. +* dynamic symbol table entries, printing: objdump. +* dynamic symbols: nm. +* ELF object file format: objdump. +* endianness: objdump. +* error on valid input: Bug Criteria. +* external symbols: nm. +* extract from archive: ar cmdline. +* fatal signal: Bug Criteria. +* file name: nm. +* header information, all: objdump. +* input file name: nm. +* libraries: ar. +* listings strings: strings. +* machine instructions: objdump. +* moving in archive: ar cmdline. +* MRI compatibility, ar: ar scripts. +* name duplication in archive: ar cmdline. +* name length: ar. +* nm: nm. +* objdump: objdump. +* object code format <1>: objdump. +* object code format <2>: strings. +* object code format <3>: nm. +* object code format <4>: size. +* object code format: addr2line. +* object file header: objdump. +* object file information: objdump. +* object file sections: objdump. +* object formats available: objdump. +* operations on archive: ar cmdline. +* printing from archive: ar cmdline. +* printing strings: strings. +* quick append to archive: ar cmdline. +* radix for section sizes: size. +* ranlib: ranlib. +* relative placement in archive: ar cmdline. +* relocation entries, in object file: objdump. +* removing symbols: strip. +* repeated names in archive: ar cmdline. +* replacement in archive: ar cmdline. +* reporting bugs: Reporting Bugs. +* scripts, ar: ar scripts. +* section addresses in objdump: objdump. +* section headers: objdump. +* section information: objdump. +* section sizes: size. +* sections, full contents: objdump. +* size: size. +* sorting symbols: nm. +* source disassembly: objdump. +* source file name: nm. +* source filenames for object files: objdump. +* stab: objdump. +* start-address: objdump. +* stop-address: objdump. +* strings: strings. +* strings, printing: strings. +* strip: strip. +* symbol index <1>: ranlib. +* symbol index: ar. +* symbol index, listing: nm. +* symbol line numbers: nm. +* symbol table entries, printing: objdump. +* symbols: nm. +* symbols, discarding: strip. +* undefined symbols: nm. +* Unix compatibility, ar: ar cmdline. +* updating an archive: ar cmdline. +* version: Top. +* VMA in objdump: objdump. +* wide output, printing: objdump. +* writing archive index: ar cmdline. + + diff --git a/gnu/dist/binutils/binutils.texi b/gnu/dist/binutils/binutils.texi new file mode 100644 index 00000000000..c2891195b53 --- /dev/null +++ b/gnu/dist/binutils/binutils.texi @@ -0,0 +1,2319 @@ +\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", + "strings", "strip", and "ranlib". +END-INFO-DIR-ENTRY +@end format +@end ifinfo + +@ifinfo +Copyright @copyright{} 1991, 92, 93, 94, 95, 96, 1997 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", and "ranlib". +@c +@c Copyright (C) 1991, 92, 93, 94, 95, 96, 1997 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, 1997 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 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 +@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 +* 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 +* 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}; 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. + +@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 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, cancelling 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} ] + [ -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} ] + [ --adjust-vma=@var{incr} ] + [ --adjust-section-vma=@var{section}@{=,+,-@}@var{val} ] + [ --adjust-warnings ] [ --no-adjust-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, and may be combined with strip options +other than @code{-K}. + +@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 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 virtual 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 --adjust-start @var{incr} +Adjust the start address by adding @var{incr}. Not all object file +formats support setting the start address. + +@item --adjust-vma @var{incr} +Adjust the address 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 --adjust-section-vma @var{section}@{=,+,-@}@var{val} +Set or adjust the 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{--adjust-vma}, above. If @var{section} does not exist in the +input file, a warning will be issued, unless @samp{--no-adjust-warnings} +is used. + +@item --adjust-warnings +If @samp{--adjust-section-vma} is used, and the named section does not +exist, issue a warning. This is the default. + +@item --no-adjust-warnings +Do not issue a warning if @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{load}, @samp{readonly}, @samp{code}, @samp{data}, +and @samp{rom}. 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} ] + [ -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 disasembling object files which do not describe +architecture information, such as S-records. You can list the available +architectures with the @samp{-i} option. + +@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 +@item --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. + +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. + +@itemx -@var{min-len} +@item -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} | --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 ] + [ -n | --no-strip-underscores ] + [ -s @var{format} | --format=@var{format} ] + [ --help ] [ --version ] [ @var{symbol}@dots{} ] +@end smallexample + +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 +@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 -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 +@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 abosolute 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 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@@prep.ai.mit.edu}. + +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/gnu/dist/binutils/bucomm.c b/gnu/dist/binutils/bucomm.c new file mode 100644 index 00000000000..b23d9e63a5a --- /dev/null +++ b/gnu/dist/binutils/bucomm.c @@ -0,0 +1,237 @@ +/* bucomm.c -- Bin Utils COMmon code. + Copyright (C) 1991, 92, 93, 94, 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. */ + +/* 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 + +char *target = NULL; /* default as late as possible */ + +/* 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); +} + +#ifdef ANSI_PROTOTYPES +void +fatal (const char *format, ...) +{ + va_list args; + + fprintf (stderr, "%s: ", program_name); + va_start (args, format); + vfprintf (stderr, format, args); + va_end (args); + putc ('\n', stderr); + xexit (1); +} +#else +void +fatal (va_alist) + va_dcl +{ + char *Format; + va_list args; + + fprintf (stderr, "%s: ", program_name); + va_start (args); + Format = va_arg (args, char *); + vfprintf (stderr, Format, args); + va_end (args); + putc ('\n', stderr); + xexit (1); +} +#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)) + { + char *errmsg; + + errmsg = (char *) xmalloc (100 + strlen (target)); + sprintf (errmsg, "can't set BFD default target to `%s'", target); + bfd_fatal (errmsg); + } +} + +/* 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++); + fprintf(stderr, "\n"); +} + +/* 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 (slash != (char *) NULL) + { + *slash = 0; + tmpname = xmalloc (strlen (filename) + sizeof (template) + 1); + strcpy (tmpname, filename); + strcat (tmpname, "/"); + strcat (tmpname, template); + mktemp (tmpname); + *slash = '/'; + } + 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') + { + fprintf (stderr, "%s: %s: bad number: %s\n", program_name, arg, s); + exit (1); + } + return ret; +} diff --git a/gnu/dist/binutils/bucomm.h b/gnu/dist/binutils/bucomm.h new file mode 100644 index 00000000000..6279a8decef --- /dev/null +++ b/gnu/dist/binutils/bucomm.h @@ -0,0 +1,148 @@ +/* bucomm.h -- binutils common include file. + Copyright (C) 1992, 93, 94, 95, 96, 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. */ + +#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 + +#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 + +#ifdef __GNUC__ +# undef alloca +# define alloca __builtin_alloca +#else +# if HAVE_ALLOCA_H +# 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 + +/* bucomm.c */ +void bfd_nonfatal PARAMS ((CONST char *)); + +void bfd_fatal PARAMS ((CONST char *)); + +void 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 *)); + +/* libiberty */ +PTR xmalloc PARAMS ((size_t)); + +PTR xrealloc PARAMS ((PTR, size_t)); + +#endif /* _BUCOMM_H */ diff --git a/gnu/dist/binutils/budbg.h b/gnu/dist/binutils/budbg.h new file mode 100644 index 00000000000..d8ee8895e76 --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/coffdump.c b/gnu/dist/binutils/coffdump.c new file mode 100644 index 00000000000..bae1e138ea7 --- /dev/null +++ b/gnu/dist/binutils/coffdump.c @@ -0,0 +1,544 @@ +/* Coff file dumper. + Copyright (C) 1994 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" + +char *xcalloc(a,b) +int a; +int b; +{ + char *r = xmalloc(a*b); + memset (r, 0, a * b); + return r; +} + +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 } + }; + + 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/gnu/dist/binutils/coffgrok.c b/gnu/dist/binutils/coffgrok.c new file mode 100644 index 00000000000..07259863488 --- /dev/null +++ b/gnu/dist/binutils/coffgrok.c @@ -0,0 +1,735 @@ +/* coffgrok.c + Copyright (C) 1994, 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. */ + +/* 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->vma; + 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) + { + 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; + 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/gnu/dist/binutils/coffgrok.h b/gnu/dist/binutils/coffgrok.h new file mode 100644 index 00000000000..c0ade42a61f --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/config.in b/gnu/dist/binutils/config.in new file mode 100644 index 00000000000..0aa5a6471ea --- /dev/null +++ b/gnu/dist/binutils/config.in @@ -0,0 +1,86 @@ +/* config.in. Generated automatically from configure.in by autoheader. */ + +/* Whether strstr must be declared even if <string.h> is included. */ +#undef NEED_DECLARATION_STRSTR + +/* Whether fprintf must be declared even if <stdio.h> is included. */ +#undef NEED_DECLARATION_FPRINTF + +/* Whether sbrk must be declared even if <unistd.h> is included. */ +#undef NEED_DECLARATION_SBRK + +/* Whether getenv must be declared even if <stdlib.h> is included. */ +#undef NEED_DECLARATION_GETENV + +/* Define if using alloca.c. */ +#undef C_ALLOCA + +/* 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 <sys/wait.h> that is POSIX.1 compatible. */ +#undef HAVE_SYS_WAIT_H + +/* Define if you have <vfork.h>. */ +#undef HAVE_VFORK_H + +/* Define to `int' if <sys/types.h> doesn't define. */ +#undef pid_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 vfork as fork if vfork does not work. */ +#undef vfork + +/* 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 + +/* 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 + +/* Define if you have the utimes function. */ +#undef HAVE_UTIMES + +/* Define if you have the <fcntl.h> header file. */ +#undef HAVE_FCNTL_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 <unistd.h> header file. */ +#undef HAVE_UNISTD_H diff --git a/gnu/dist/binutils/config.texi b/gnu/dist/binutils/config.texi new file mode 100644 index 00000000000..f85179ee66e --- /dev/null +++ b/gnu/dist/binutils/config.texi @@ -0,0 +1 @@ +@set VERSION 2.8 diff --git a/gnu/dist/binutils/configure b/gnu/dist/binutils/configure new file mode 100644 index 00000000000..00acafdbc38 --- /dev/null +++ b/gnu/dist/binutils/configure @@ -0,0 +1,2630 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.12 +# 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-targets alternative target configurations" +ac_help="$ac_help + --enable-shared build shared BFD library" +ac_help="$ac_help + --enable-commonbfdlib build shared BFD/opcodes/libiberty library" + +# 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= +# 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.12" + 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 $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +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 + + + +# 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-shared or --disable-shared was given. +if test "${enable_shared+set}" = set; then + enableval="$enable_shared" + case "${enableval}" in + yes) shared=true shared_bfd=true shared_opcodes=true ;; + no) shared=false ;; + *bfd*opcodes*) shared=true shared_bfd=true shared_opcodes=true ;; + *opcodes*bfd*) shared=true shared_bfd=true shared_opcodes=true ;; + *bfd*) shared=true shared_bfd=true ;; + *opcodes*) shared=true shared_opcodes=true ;; + *) shared=false ;; +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 + + + +ac_aux_dir= +for ac_dir in `cd $srcdir/..; pwd` $srcdir/`cd $srcdir/..; pwd`; 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 `cd $srcdir/..; pwd` $srcdir/`cd $srcdir/..; pwd`" 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 $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:611: checking host system type" >&5 + +host_alias=$host +case "$host_alias" in +NONE) + case $nonopt in + NONE) + if host_alias=`$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=`$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:632: 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=`$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:650: 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=`$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}- + +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 +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," + + +# host-specific stuff: + +HDEFINES= +HLDFLAGS= +HLDENV= +RPATH_ENVVAR=LD_LIBRARY_PATH + +# 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:708: 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="${IFS}:" + for ac_dir in $PATH; 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:737: 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="${IFS}:" + ac_prog_rejected=no + for ac_dir in $PATH; 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 + + 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:785: 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 $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext <<EOF +#line 795 "configure" +#include "confdefs.h" +main(){return(0);} +EOF +if { (eval echo configure:799: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; 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* + +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:819: 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:824: 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:833: \"$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 + 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:848: 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 + CFLAGS="-g -O2" + else + CFLAGS="-O2" + fi +else + GCC= + test "${CFLAGS+set}" = set || CFLAGS="-g" +fi + + +. ${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:887: 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="${IFS}:" + for ac_dir in $PATH; 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 +# 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:924: 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="${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. + for ac_prog in ginstall installbsd 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. + # OSF/1 installbsd also uses dspmsg, but is usable. + : + 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_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + +# For most hosts we can use a simple definition to pick up the BFD and +# opcodes libraries. However, if we are building shared libraries, we +# need to handle some hosts specially. +BFDLIB='-L../bfd -lbfd' +OPCODES='-L../opcodes -lopcodes' + +case "${host}" in +*-*-sunos*) + # On SunOS, we must link against the name we are going to install, + # not -lbfd, since SunOS does not support SONAME. + if test "${shared_bfd}" = "true"; then + BFDLIB='-L../bfd -l`echo bfd | sed '"'"'$(program_transform_name)'"'"'`' + fi + if test "${shared_opcodes}" = "true"; then + OPCODES='-L../opcodes -l`echo opcodes | sed '"'"'$(program_transform_name)'"'"'`' + fi + ;; +alpha*-*-osf*) + # On Alpha OSF/1, the native linker searches all the -L + # directories for any LIB.so files, and only then searches for any + # LIB.a files. That means that if there is an installed + # libbfd.so, but this build is not done with --enable-shared, the + # link will wind up being against the install libbfd.so rather + # than the newly built libbfd. To avoid this, we must explicitly + # link against libbfd.a when --enable-shared is not used. + if test "${shared_bfd}" != "true"; then + BFDLIB='../bfd/libbfd.a' + fi + if test "${shared_opcodes}" != "true"; then + OPCODES='../opcodes/libopcodes.a' + fi + ;; +esac + +if test "${commonbfdlib}" = "true"; then + # when a shared libbfd is built with --enable-commonbfdlib, + # all of libopcodes is available in libbfd.so + OPCODES= +fi + + + + +# 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 + + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:1028: 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 1043 "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:1049: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +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 1060 "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:1066: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +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* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + +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:1092: 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 1097 "configure" +#include "confdefs.h" +#include <$ac_hdr> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1102: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +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:1129: 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 1134 "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:1150: \"$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:1173: 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 1178 "configure" +#include "confdefs.h" +#include <alloca.h> +int main() { +char *p = alloca(2 * sizeof(int)); +; return 0; } +EOF +if { (eval echo configure:1185: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; 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:1206: 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 1211 "configure" +#include "confdefs.h" + +#ifdef __GNUC__ +# define alloca __builtin_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 + +int main() { +char *p = (char *) alloca(1); +; return 0; } +EOF +if { (eval echo configure:1234: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; 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.o + cat >> confdefs.h <<\EOF +#define C_ALLOCA 1 +EOF + + +echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 +echo "configure:1266: 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 1271 "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:1296: 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 1301 "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:1324: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; 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:1351: 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 1359 "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:1378: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./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:1402: 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 1407 "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:1430: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; 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 "x$cross_compiling" = "xno"; then + echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 +echo "configure:1456: 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 1461 "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:1469: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +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 1486 "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 1504 "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 1525 "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:1536: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./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 pid_t""... $ac_c" 1>&6 +echo "configure:1560: checking for pid_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1565 "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 "pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_pid_t=yes +else + rm -rf conftest* + ac_cv_type_pid_t=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_type_pid_t" 1>&6 +if test $ac_cv_type_pid_t = no; then + cat >> confdefs.h <<\EOF +#define pid_t int +EOF + +fi + +ac_safe=`echo "vfork.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for vfork.h""... $ac_c" 1>&6 +echo "configure:1594: checking for vfork.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 1599 "configure" +#include "confdefs.h" +#include <vfork.h> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1604: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +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 + cat >> confdefs.h <<\EOF +#define HAVE_VFORK_H 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi + +echo $ac_n "checking for working vfork""... $ac_c" 1>&6 +echo "configure:1629: checking for working vfork" >&5 +if eval "test \"`echo '$''{'ac_cv_func_vfork_works'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + echo $ac_n "checking for vfork""... $ac_c" 1>&6 +echo "configure:1635: checking for vfork" >&5 +if eval "test \"`echo '$''{'ac_cv_func_vfork'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1640 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char vfork(); 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 vfork(); + +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_vfork) || defined (__stub___vfork) +choke me +#else +vfork(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1663: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_vfork=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_vfork=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'vfork`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +fi + +else + cat > conftest.$ac_ext <<EOF +#line 1684 "configure" +#include "confdefs.h" +/* Thanks to Paul Eggert for this test. */ +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_VFORK_H +#include <vfork.h> +#endif +/* On some sparc systems, changes by the child to local and incoming + argument registers are propagated back to the parent. + The compiler is told about this with #include <vfork.h>, + but some compilers (e.g. gcc -O) don't grok <vfork.h>. + Test for this by using a static variable whose address + is put into a register that is clobbered by the vfork. */ +static +#ifdef __cplusplus +sparc_address_test (int arg) +#else +sparc_address_test (arg) int arg; +#endif +{ + static pid_t child; + if (!child) { + child = vfork (); + if (child < 0) { + perror ("vfork"); + _exit(2); + } + if (!child) { + arg = getpid(); + write(-1, "", 0); + _exit (arg); + } + } +} +main() { + pid_t parent = getpid (); + pid_t child; + + sparc_address_test (); + + child = vfork (); + + if (child == 0) { + /* Here is another test for sparc vfork register problems. + This test uses lots of local variables, at least + as many local variables as main has allocated so far + including compiler temporaries. 4 locals are enough for + gcc 1.40.3 on a Solaris 4.1.3 sparc, but we use 8 to be safe. + A buggy compiler should reuse the register of parent + for one of the local variables, since it will think that + parent can't possibly be used any more in this routine. + Assigning to the local variable will thus munge parent + in the parent process. */ + pid_t + p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(), + p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid(); + /* Convince the compiler that p..p7 are live; otherwise, it might + use the same hardware register for all 8 local variables. */ + if (p != p1 || p != p2 || p != p3 || p != p4 + || p != p5 || p != p6 || p != p7) + _exit(1); + + /* On some systems (e.g. IRIX 3.3), + vfork doesn't separate parent from child file descriptors. + If the child closes a descriptor before it execs or exits, + this munges the parent's descriptor as well. + Test for this by closing stdout in the child. */ + _exit(close(fileno(stdout)) != 0); + } else { + int status; + struct stat st; + + while (wait(&status) != child) + ; + exit( + /* Was there some problem with vforking? */ + child < 0 + + /* Did the child fail? (This shouldn't happen.) */ + || status + + /* Did the vfork/compiler bug occur? */ + || parent != getpid() + + /* Did the file descriptor bug occur? */ + || fstat(fileno(stdout), &st) != 0 + ); + } +} +EOF +if { (eval echo configure:1779: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + ac_cv_func_vfork_works=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_func_vfork_works=no +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$ac_cv_func_vfork_works" 1>&6 +if test $ac_cv_func_vfork_works = no; then + cat >> confdefs.h <<\EOF +#define vfork fork +EOF + +fi + +else + echo $ac_n "checking for vfork""... $ac_c" 1>&6 +echo "configure:1803: checking for vfork" >&5 +if eval "test \"`echo '$''{'ac_cv_func_vfork'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1808 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char vfork(); 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 vfork(); + +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_vfork) || defined (__stub___vfork) +choke me +#else +vfork(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1831: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_vfork=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_vfork=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'vfork`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +cat >> confdefs.h <<\EOF +#define vfork fork +EOF + +fi + +fi + +echo $ac_n "checking for time_t in time.h""... $ac_c" 1>&6 +echo "configure:1857: 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 1862 "configure" +#include "confdefs.h" +#include <time.h> +int main() { +time_t i; +; return 0; } +EOF +if { (eval echo configure:1869: \"$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:1890: 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 1895 "configure" +#include "confdefs.h" +#include <sys/types.h> +int main() { +time_t i; +; return 0; } +EOF +if { (eval echo configure:1902: \"$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:1925: 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 1930 "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:1941: \"$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:1962: 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 1967 "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:1988: \"$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 + bfd_tr_decl=NEED_DECLARATION_`echo fprintf | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $bfd_tr_decl 1 +EOF + +fi + +echo $ac_n "checking whether strstr must be declared""... $ac_c" 1>&6 +echo "configure:2010: 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 2015 "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:2036: \"$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 + bfd_tr_decl=NEED_DECLARATION_`echo strstr | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $bfd_tr_decl 1 +EOF + +fi + +echo $ac_n "checking whether sbrk must be declared""... $ac_c" 1>&6 +echo "configure:2058: 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 2063 "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:2084: \"$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 + bfd_tr_decl=NEED_DECLARATION_`echo sbrk | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $bfd_tr_decl 1 +EOF + +fi + +echo $ac_n "checking whether getenv must be declared""... $ac_c" 1>&6 +echo "configure:2106: 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 2111 "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:2132: \"$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 + bfd_tr_decl=NEED_DECLARATION_`echo getenv | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $bfd_tr_decl 1 +EOF + +fi + + + +case "${host}" in +i[345]86-*-msdos* | i[345]86-*-go32* | *-*-cygwin32 | *-*-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= + +for targ in $target $canon_targets +do + if test "x$targ" = "xall"; then + all_targets=true + BUILD_NLMCONV='$(NLMCONV_PROG)' + 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)' + NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_I386" + ;; + alpha*-*-netware*) + BUILD_NLMCONV='$(NLMCONV_PROG)' + NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_ALPHA" + ;; + powerpc*-*-netware*) + BUILD_NLMCONV='$(NLMCONV_PROG)' + NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_POWERPC" + ;; + sparc*-*-netware*) + BUILD_NLMCONV='$(NLMCONV_PROG)' + 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)' + DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_ARM" + ;; + i[3-6]86-*pe* | i[3-6]86-*-cygwin32) + BUILD_DLLTOOL='$(DLLTOOL_PROG)' + DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_I386" + ;; + powerpc*-*-*pe* | powerpc*-*-cygwin32) + BUILD_DLLTOOL='$(DLLTOOL_PROG)' + DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_PPC" + ;; + esac + fi +done + + + + + + + +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) 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.12" + 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 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%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%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%@CC@%$CC%g +s%@HDEFINES@%$HDEFINES%g +s%@HLDFLAGS@%$HLDFLAGS%g +s%@HLDENV@%$HLDENV%g +s%@RPATH_ENVVAR@%$RPATH_ENVVAR%g +s%@AR@%$AR%g +s%@RANLIB@%$RANLIB%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@BFDLIB@%$BFDLIB%g +s%@OPCODES@%$OPCODES%g +s%@CC_FOR_BUILD@%$CC_FOR_BUILD%g +s%@CPP@%$CPP%g +s%@ALLOCA@%$ALLOCA%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%@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"} +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 +case x$CONFIG_HEADERS in xconfig.h:config.in) echo > stamp-h ;; 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/gnu/dist/binutils/configure.bat b/gnu/dist/binutils/configure.bat new file mode 100644 index 00000000000..f7d70f1150b --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/configure.com b/gnu/dist/binutils/configure.com new file mode 100644 index 00000000000..9e35c766297 --- /dev/null +++ b/gnu/dist/binutils/configure.com @@ -0,0 +1,78 @@ +$! +$! 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@progis.de) +$! +$arch_indx = 1 + ((f$getsyi("CPU").ge.128).and.1) ! vax==1, alpha==2 +$arch = f$element(arch_indx,"|","|VAX|Alpha|") +$if arch .eqs. "VAX" +$then +$ write sys$output "Target VAX not supported." +$ exit 2 +$endif +$! +$! +$! 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. */ +#define 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 +$! +$ edit/tpu/nojournal/nosection/nodisplay/command=sys$input - + []makefile.vms /output=[]makefile.vms +$DECK +! +! Get VERSION from Makefile.in +! + mfile := CREATE_BUFFER("mfile", "Makefile.in"); + rang := CREATE_RANGE(BEGINNING_OF(mfile), END_OF(mfile)); + v_pos := SEARCH_QUIETLY('VERSION=', FORWARD, EXACT, rang); + POSITION(BEGINNING_OF(v_pos)); + vers := CURRENT_LINE; + IF match_pos <> 0 THEN; + 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_LINE; + COPY_TEXT(vers); + SPLIT_LINE; + ENDIF; + WRITE_FILE(file, GET_INFO(COMMAND_LINE, "output_file")); + QUIT +$ EOD +$ write sys$output "Patched `makefile.vms'" diff --git a/gnu/dist/binutils/configure.in b/gnu/dist/binutils/configure.in new file mode 100644 index 00000000000..33f1094a06e --- /dev/null +++ b/gnu/dist/binutils/configure.in @@ -0,0 +1,252 @@ +dnl Process this file with autoconf to produce a configure script. +dnl +AC_PREREQ(2.5) +AC_INIT(ar.c) + +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(shared, +[ --enable-shared build shared BFD library], +[case "${enableval}" in + yes) shared=true shared_bfd=true shared_opcodes=true ;; + no) shared=false ;; + *bfd*opcodes*) shared=true shared_bfd=true shared_opcodes=true ;; + *opcodes*bfd*) shared=true shared_bfd=true shared_opcodes=true ;; + *bfd*) shared=true shared_bfd=true ;; + *opcodes*) shared=true shared_opcodes=true ;; + *) shared=false ;; +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 + +AC_CONFIG_HEADER(config.h:config.in) + +AC_CONFIG_AUX_DIR(`cd $srcdir/..; pwd`) +AC_CANONICAL_SYSTEM +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_ARG_PROGRAM + +# host-specific stuff: + +HDEFINES= +HLDFLAGS= +HLDENV= +RPATH_ENVVAR=LD_LIBRARY_PATH + +AC_PROG_CC + +. ${srcdir}/../bfd/configure.host + +AC_SUBST(HDEFINES) +AC_SUBST(HLDFLAGS) +AC_SUBST(HLDENV) +AC_SUBST(RPATH_ENVVAR) +AR=${AR-ar} +AC_SUBST(AR) +AC_PROG_RANLIB +AC_PROG_INSTALL + +# For most hosts we can use a simple definition to pick up the BFD and +# opcodes libraries. However, if we are building shared libraries, we +# need to handle some hosts specially. +BFDLIB='-L../bfd -lbfd' +OPCODES='-L../opcodes -lopcodes' + +case "${host}" in +*-*-sunos*) + # On SunOS, we must link against the name we are going to install, + # not -lbfd, since SunOS does not support SONAME. + if test "${shared_bfd}" = "true"; then + BFDLIB='-L../bfd -l`echo bfd | sed '"'"'$(program_transform_name)'"'"'`' + fi + if test "${shared_opcodes}" = "true"; then + OPCODES='-L../opcodes -l`echo opcodes | sed '"'"'$(program_transform_name)'"'"'`' + fi + ;; +alpha*-*-osf*) + # On Alpha OSF/1, the native linker searches all the -L + # directories for any LIB.so files, and only then searches for any + # LIB.a files. That means that if there is an installed + # libbfd.so, but this build is not done with --enable-shared, the + # link will wind up being against the install libbfd.so rather + # than the newly built libbfd. To avoid this, we must explicitly + # link against libbfd.a when --enable-shared is not used. + if test "${shared_bfd}" != "true"; then + BFDLIB='../bfd/libbfd.a' + fi + if test "${shared_opcodes}" != "true"; then + OPCODES='../opcodes/libopcodes.a' + fi + ;; +esac + +if test "${commonbfdlib}" = "true"; then + # when a shared libbfd is built with --enable-commonbfdlib, + # all of libopcodes is available in libbfd.so + OPCODES= +fi + +AC_SUBST(BFDLIB) +AC_SUBST(OPCODES) + +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) +dnl Temporary workaround for bug in autoconf 2.12. When the bug is +dnl fixed, we can just call AC_FUNC_VFORK in all cases. +if test "x$cross_compiling" = "xno"; then + AC_FUNC_VFORK +else + AC_CHECK_FUNC(vfork, , AC_DEFINE(vfork, fork)) +fi + +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]) +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]) +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) +fi + +BFD_NEED_DECLARATION(fprintf) +BFD_NEED_DECLARATION(strstr) +BFD_NEED_DECLARATION(sbrk) +BFD_NEED_DECLARATION(getenv) + +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= + +for targ in $target $canon_targets +do + if test "x$targ" = "xall"; then + all_targets=true + BUILD_NLMCONV='$(NLMCONV_PROG)' + 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)' + NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_I386" + ;; + alpha*-*-netware*) + BUILD_NLMCONV='$(NLMCONV_PROG)' + NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_ALPHA" + ;; + powerpc*-*-netware*) + BUILD_NLMCONV='$(NLMCONV_PROG)' + NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_POWERPC" + ;; + sparc*-*-netware*) + BUILD_NLMCONV='$(NLMCONV_PROG)' + 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)' + DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_ARM" + ;; +changequote(,)dnl + i[3-6]86-*pe* | i[3-6]86-*-cygwin32) +changequote([,])dnl + BUILD_DLLTOOL='$(DLLTOOL_PROG)' + DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_I386" + ;; + powerpc*-*-*pe* | powerpc*-*-cygwin32) + BUILD_DLLTOOL='$(DLLTOOL_PROG)' + DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_PPC" + ;; + esac + fi +done + +AC_SUBST(NLMCONV_DEFS) +AC_SUBST(BUILD_NLMCONV) +AC_SUBST(BUILD_SRCONV) +AC_SUBST(BUILD_DLLTOOL) +AC_SUBST(DLLTOOL_DEFS) + +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, +[case x$CONFIG_HEADERS in xconfig.h:config.in) echo > stamp-h ;; esac]) diff --git a/gnu/dist/binutils/cxxfilt.man b/gnu/dist/binutils/cxxfilt.man new file mode 100644 index 00000000000..a4d5d45106b --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/debug.c b/gnu/dist/binutils/debug.c new file mode 100644 index 00000000000..3b9b2b6990a --- /dev/null +++ b/gnu/dist/binutils/debug.c @@ -0,0 +1,3506 @@ +/* debug.c -- Handle 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 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; +}; + +/* 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)); +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 false; + } + + 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. */ + +static struct debug_type * +debug_get_real_type (handle, type) + PTR handle; + debug_type type; +{ + switch (type->kind) + { + default: + return type; + case DEBUG_KIND_INDIRECT: + if (*type->u.kindirect->slot != NULL) + return debug_get_real_type (handle, *type->u.kindirect->slot); + return type; + case DEBUG_KIND_NAMED: + case DEBUG_KIND_TAGGED: + return debug_get_real_type (handle, type->u.knamed->type); + } + /*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); + 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); + 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); + 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); + 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); + 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); + id = 0; + if ((real->kind == DEBUG_KIND_STRUCT + || real->kind == DEBUG_KIND_UNION + || real->kind == DEBUG_KIND_CLASS + || real->kind == DEBUG_KIND_UNION_CLASS) + && real->u.kclass != NULL) + { + if (real->u.kclass->id <= info->base_id) + { + if (! debug_set_class_id (info, + type->u.knamed->name->name, + real)) + return false; + } + id = real->u.kclass->id; + } + + return (*fns->tag_type) (fhandle, type->u.knamed->name->name, id, + real->kind); + } + } + + /* Mark the name after we have already looked for a known name, so + that we don't just define a type in terms of itself. We need to + mark the name here so that a struct containing a pointer to + itself will work. */ + if (name != NULL) + name->mark = info->mark; + + tag = NULL; + if (name != NULL + && type->kind != DEBUG_KIND_NAMED + && type->kind != DEBUG_KIND_TAGGED) + { + assert (name->kind == DEBUG_OBJECT_TAG); + tag = name->name; + } + + switch (type->kind) + { + case DEBUG_KIND_ILLEGAL: + debug_error ("debug_write_type: illegal type encountered"); + return false; + case DEBUG_KIND_INDIRECT: + if (*type->u.kindirect->slot == DEBUG_TYPE_NULL) + return (*fns->empty_type) (fhandle); + return debug_write_type (info, fns, fhandle, *type->u.kindirect->slot, + name); + case DEBUG_KIND_VOID: + return (*fns->void_type) (fhandle); + case DEBUG_KIND_INT: + return (*fns->int_type) (fhandle, type->size, type->u.kint); + case DEBUG_KIND_FLOAT: + return (*fns->float_type) (fhandle, type->size); + case DEBUG_KIND_COMPLEX: + return (*fns->complex_type) (fhandle, type->size); + case DEBUG_KIND_BOOL: + return (*fns->bool_type) (fhandle, type->size); + case DEBUG_KIND_STRUCT: + case DEBUG_KIND_UNION: + if (type->u.kclass != NULL) + { + if (type->u.kclass->id <= info->base_id) + { + if (! debug_set_class_id (info, tag, type)) + return false; + } + + if (info->mark == type->u.kclass->mark) + { + /* We are currently outputting this struct, or we have + already output it. I don't know if this can happen, + but it can happen for a class. */ + assert (type->u.kclass->id > info->base_id); + return (*fns->tag_type) (fhandle, tag, type->u.kclass->id, + type->kind); + } + type->u.kclass->mark = info->mark; + } + + if (! (*fns->start_struct_type) (fhandle, tag, + (type->u.kclass != NULL + ? type->u.kclass->id + : 0), + type->kind == DEBUG_KIND_STRUCT, + type->size)) + return false; + if (type->u.kclass != NULL + && type->u.kclass->fields != NULL) + { + for (i = 0; type->u.kclass->fields[i] != NULL; i++) + { + struct debug_field *f; + + f = type->u.kclass->fields[i]; + if (! debug_write_type (info, fns, fhandle, f->type, + (struct debug_name *) NULL) + || ! (*fns->struct_field) (fhandle, f->name, f->u.f.bitpos, + f->u.f.bitsize, f->visibility)) + return false; + } + } + return (*fns->end_struct_type) (fhandle); + case DEBUG_KIND_CLASS: + case DEBUG_KIND_UNION_CLASS: + return debug_write_class_type (info, fns, fhandle, type, tag); + case DEBUG_KIND_ENUM: + if (type->u.kenum == NULL) + return (*fns->enum_type) (fhandle, tag, (const char **) NULL, + (bfd_signed_vma *) NULL); + return (*fns->enum_type) (fhandle, tag, type->u.kenum->names, + type->u.kenum->values); + case DEBUG_KIND_POINTER: + if (! debug_write_type (info, fns, fhandle, type->u.kpointer, + (struct debug_name *) NULL)) + return false; + return (*fns->pointer_type) (fhandle); + case DEBUG_KIND_FUNCTION: + if (! debug_write_type (info, fns, fhandle, + type->u.kfunction->return_type, + (struct debug_name *) NULL)) + return false; + if (type->u.kfunction->arg_types == NULL) + is = -1; + else + { + for (is = 0; type->u.kfunction->arg_types[is] != NULL; is++) + if (! debug_write_type (info, fns, fhandle, + type->u.kfunction->arg_types[is], + (struct debug_name *) NULL)) + return false; + } + return (*fns->function_type) (fhandle, is, + type->u.kfunction->varargs); + case DEBUG_KIND_REFERENCE: + if (! debug_write_type (info, fns, fhandle, type->u.kreference, + (struct debug_name *) NULL)) + return false; + return (*fns->reference_type) (fhandle); + case DEBUG_KIND_RANGE: + if (! debug_write_type (info, fns, fhandle, type->u.krange->type, + (struct debug_name *) NULL)) + return false; + return (*fns->range_type) (fhandle, type->u.krange->lower, + type->u.krange->upper); + case DEBUG_KIND_ARRAY: + if (! debug_write_type (info, fns, fhandle, type->u.karray->element_type, + (struct debug_name *) NULL) + || ! debug_write_type (info, fns, fhandle, + type->u.karray->range_type, + (struct debug_name *) NULL)) + return false; + return (*fns->array_type) (fhandle, type->u.karray->lower, + type->u.karray->upper, + type->u.karray->stringp); + case DEBUG_KIND_SET: + if (! debug_write_type (info, fns, fhandle, type->u.kset->type, + (struct debug_name *) NULL)) + return false; + return (*fns->set_type) (fhandle, type->u.kset->bitstringp); + case DEBUG_KIND_OFFSET: + if (! debug_write_type (info, fns, fhandle, type->u.koffset->base_type, + (struct debug_name *) NULL) + || ! debug_write_type (info, fns, fhandle, + type->u.koffset->target_type, + (struct debug_name *) NULL)) + return false; + return (*fns->offset_type) (fhandle); + case DEBUG_KIND_METHOD: + if (! debug_write_type (info, fns, fhandle, + type->u.kmethod->return_type, + (struct debug_name *) NULL)) + return false; + if (type->u.kmethod->arg_types == NULL) + is = -1; + else + { + for (is = 0; type->u.kmethod->arg_types[is] != NULL; is++) + if (! debug_write_type (info, fns, fhandle, + type->u.kmethod->arg_types[is], + (struct debug_name *) NULL)) + return false; + } + if (type->u.kmethod->domain_type != NULL) + { + if (! debug_write_type (info, fns, fhandle, + type->u.kmethod->domain_type, + (struct debug_name *) NULL)) + return false; + } + return (*fns->method_type) (fhandle, + type->u.kmethod->domain_type != NULL, + is, + type->u.kmethod->varargs); + case DEBUG_KIND_CONST: + if (! debug_write_type (info, fns, fhandle, type->u.kconst, + (struct debug_name *) NULL)) + return false; + return (*fns->const_type) (fhandle); + case DEBUG_KIND_VOLATILE: + if (! debug_write_type (info, fns, fhandle, type->u.kvolatile, + (struct debug_name *) NULL)) + return false; + return (*fns->volatile_type) (fhandle); + case DEBUG_KIND_NAMED: + return debug_write_type (info, fns, fhandle, type->u.knamed->type, + (struct debug_name *) NULL); + case DEBUG_KIND_TAGGED: + return debug_write_type (info, fns, fhandle, type->u.knamed->type, + type->u.knamed->name); + default: + abort (); + return false; + } +} + +/* Write out a class type. */ + +static boolean +debug_write_class_type (info, fns, fhandle, type, tag) + struct debug_handle *info; + const struct debug_write_fns *fns; + PTR fhandle; + struct debug_type *type; + const char *tag; +{ + unsigned int i; + unsigned int id; + struct debug_type *vptrbase; + + if (type->u.kclass == NULL) + { + id = 0; + vptrbase = NULL; + } + else + { + if (type->u.kclass->id <= info->base_id) + { + if (! debug_set_class_id (info, tag, type)) + return false; + } + + if (info->mark == type->u.kclass->mark) + { + /* We are currently outputting this class, or we have + already output it. This can happen when there are + methods for an anonymous class. */ + assert (type->u.kclass->id > info->base_id); + return (*fns->tag_type) (fhandle, tag, type->u.kclass->id, + type->kind); + } + type->u.kclass->mark = info->mark; + id = type->u.kclass->id; + + vptrbase = type->u.kclass->vptrbase; + if (vptrbase != NULL && vptrbase != type) + { + if (! debug_write_type (info, fns, fhandle, vptrbase, + (struct debug_name *) NULL)) + return false; + } + } + + if (! (*fns->start_class_type) (fhandle, tag, id, + type->kind == DEBUG_KIND_CLASS, + type->size, + vptrbase != NULL, + vptrbase == type)) + return false; + + if (type->u.kclass != NULL) + { + if (type->u.kclass->fields != NULL) + { + for (i = 0; type->u.kclass->fields[i] != NULL; i++) + { + struct debug_field *f; + + f = type->u.kclass->fields[i]; + if (! debug_write_type (info, fns, fhandle, f->type, + (struct debug_name *) NULL)) + return false; + if (f->static_member) + { + if (! (*fns->class_static_member) (fhandle, f->name, + f->u.s.physname, + f->visibility)) + return false; + } + else + { + if (! (*fns->struct_field) (fhandle, f->name, f->u.f.bitpos, + f->u.f.bitsize, f->visibility)) + return false; + } + } + } + + if (type->u.kclass->baseclasses != NULL) + { + for (i = 0; type->u.kclass->baseclasses[i] != NULL; i++) + { + struct debug_baseclass *b; + + b = type->u.kclass->baseclasses[i]; + if (! debug_write_type (info, fns, fhandle, b->type, + (struct debug_name *) NULL)) + return false; + if (! (*fns->class_baseclass) (fhandle, b->bitpos, b->virtual, + b->visibility)) + return false; + } + } + + if (type->u.kclass->methods != NULL) + { + for (i = 0; type->u.kclass->methods[i] != NULL; i++) + { + struct debug_method *m; + unsigned int j; + + m = type->u.kclass->methods[i]; + if (! (*fns->class_start_method) (fhandle, m->name)) + return false; + for (j = 0; m->variants[j] != NULL; j++) + { + struct debug_method_variant *v; + + v = m->variants[j]; + if (v->context != NULL) + { + if (! debug_write_type (info, fns, fhandle, v->context, + (struct debug_name *) NULL)) + return false; + } + if (! debug_write_type (info, fns, fhandle, v->type, + (struct debug_name *) NULL)) + return false; + if (v->voffset != VOFFSET_STATIC_METHOD) + { + if (! (*fns->class_method_variant) (fhandle, v->physname, + v->visibility, + v->constp, + v->volatilep, + v->voffset, + v->context != NULL)) + return false; + } + else + { + if (! (*fns->class_static_method_variant) (fhandle, + v->physname, + v->visibility, + v->constp, + v->volatilep)) + return false; + } + } + if (! (*fns->class_end_method) (fhandle)) + return false; + } + } + } + + return (*fns->end_class_type) (fhandle); +} + +/* Write out information for a function. */ + +static boolean +debug_write_function (info, fns, fhandle, name, linkage, function) + struct debug_handle *info; + const struct debug_write_fns *fns; + PTR fhandle; + const char *name; + enum debug_object_linkage linkage; + struct debug_function *function; +{ + struct debug_parameter *p; + struct debug_block *b; + + if (! debug_write_linenos (info, fns, fhandle, function->blocks->start)) + return false; + + if (! debug_write_type (info, fns, fhandle, function->return_type, + (struct debug_name *) NULL)) + return false; + + if (! (*fns->start_function) (fhandle, name, + linkage == DEBUG_LINKAGE_GLOBAL)) + return false; + + for (p = function->parameters; p != NULL; p = p->next) + { + if (! debug_write_type (info, fns, fhandle, p->type, + (struct debug_name *) NULL) + || ! (*fns->function_parameter) (fhandle, p->name, p->kind, p->val)) + return false; + } + + for (b = function->blocks; b != NULL; b = b->next) + { + if (! debug_write_block (info, fns, fhandle, b)) + return false; + } + + return (*fns->end_function) (fhandle); +} + +/* Write out information for a block. */ + +static boolean +debug_write_block (info, fns, fhandle, block) + struct debug_handle *info; + const struct debug_write_fns *fns; + PTR fhandle; + struct debug_block *block; +{ + struct debug_name *n; + struct debug_block *b; + + if (! debug_write_linenos (info, fns, fhandle, block->start)) + return false; + + /* I can't see any point to writing out a block with no local + variables, so we don't bother, except for the top level block. */ + if (block->locals != NULL || block->parent == NULL) + { + if (! (*fns->start_block) (fhandle, block->start)) + return false; + } + + if (block->locals != NULL) + { + for (n = block->locals->list; n != NULL; n = n->next) + { + if (! debug_write_name (info, fns, fhandle, n)) + return false; + } + } + + for (b = block->children; b != NULL; b = b->next) + { + if (! debug_write_block (info, fns, fhandle, b)) + return false; + } + + if (! debug_write_linenos (info, fns, fhandle, block->end)) + return false; + + if (block->locals != NULL || block->parent == NULL) + { + if (! (*fns->end_block) (fhandle, block->end)) + return false; + } + + return true; +} + +/* Write out line number information up to ADDRESS. */ + +static boolean +debug_write_linenos (info, fns, fhandle, address) + struct debug_handle *info; + const struct debug_write_fns *fns; + PTR fhandle; + bfd_vma address; +{ + while (info->current_write_lineno != NULL) + { + struct debug_lineno *l; + + l = info->current_write_lineno; + + while (info->current_write_lineno_index < DEBUG_LINENO_COUNT) + { + if (l->linenos[info->current_write_lineno_index] + == (unsigned long) -1) + break; + + if (l->addrs[info->current_write_lineno_index] >= address) + return true; + + if (! (*fns->lineno) (fhandle, l->file->filename, + l->linenos[info->current_write_lineno_index], + l->addrs[info->current_write_lineno_index])) + return false; + + ++info->current_write_lineno_index; + } + + info->current_write_lineno = l->next; + info->current_write_lineno_index = 0; + } + + return true; +} + +/* Get the ID number for a class. If during the same call to + debug_write we find a struct with the same definition with the same + name, we use the same ID. This type of things happens because the + same struct will be defined by multiple compilation units. */ + +static boolean +debug_set_class_id (info, tag, type) + struct debug_handle *info; + const char *tag; + struct debug_type *type; +{ + struct debug_class_type *c; + struct debug_class_id *l; + + assert (type->kind == DEBUG_KIND_STRUCT + || type->kind == DEBUG_KIND_UNION + || type->kind == DEBUG_KIND_CLASS + || type->kind == DEBUG_KIND_UNION_CLASS); + + c = type->u.kclass; + + if (c->id > info->base_id) + return true; + + for (l = info->id_list; l != NULL; l = l->next) + { + if (l->type->kind != type->kind) + continue; + + if (tag == NULL) + { + if (l->tag != NULL) + continue; + } + else + { + if (l->tag == NULL + || l->tag[0] != tag[0] + || strcmp (l->tag, tag) != 0) + continue; + } + + if (debug_type_samep (info, l->type, type)) + { + c->id = l->type->u.kclass->id; + return true; + } + } + + /* There are no identical types. Use a new ID, and add it to the + list. */ + ++info->class_id; + c->id = info->class_id; + + l = (struct debug_class_id *) xmalloc (sizeof *l); + memset (l, 0, sizeof *l); + + l->type = type; + l->tag = tag; + + l->next = info->id_list; + info->id_list = l; + + return true; +} + +/* See if two types are the same. At this point, we don't care about + tags and the like. */ + +static boolean +debug_type_samep (info, t1, t2) + struct debug_handle *info; + struct debug_type *t1; + struct debug_type *t2; +{ + struct debug_type_compare_list *l; + struct debug_type_compare_list top; + boolean ret; + + if (t1 == NULL) + return t2 == NULL; + if (t2 == NULL) + return false; + + while (t1->kind == DEBUG_KIND_INDIRECT) + { + t1 = *t1->u.kindirect->slot; + if (t1 == NULL) + return false; + } + while (t2->kind == DEBUG_KIND_INDIRECT) + { + t2 = *t2->u.kindirect->slot; + if (t2 == NULL) + return false; + } + + if (t1 == t2) + return true; + + /* As a special case, permit a typedef to match a tag, since C++ + debugging output will sometimes add a typedef where C debugging + output will not. */ + if (t1->kind == DEBUG_KIND_NAMED + && t2->kind == DEBUG_KIND_TAGGED) + return debug_type_samep (info, t1->u.knamed->type, t2); + else if (t1->kind == DEBUG_KIND_TAGGED + && t2->kind == DEBUG_KIND_NAMED) + return debug_type_samep (info, t1, t2->u.knamed->type); + + if (t1->kind != t2->kind + || t1->size != t2->size) + return false; + + /* Get rid of the trivial cases first. */ + switch (t1->kind) + { + default: + break; + case DEBUG_KIND_VOID: + case DEBUG_KIND_FLOAT: + case DEBUG_KIND_COMPLEX: + case DEBUG_KIND_BOOL: + return true; + case DEBUG_KIND_INT: + return t1->u.kint == t2->u.kint; + } + + /* We have to avoid an infinite recursion. We do this by keeping a + list of types which we are comparing. We just keep the list on + the stack. If we encounter a pair of types we are currently + comparing, we just assume that they are equal. */ + for (l = info->compare_list; l != NULL; l = l->next) + { + if (l->t1 == t1 && l->t2 == t2) + return true; + } + + top.t1 = t1; + top.t2 = t2; + top.next = info->compare_list; + info->compare_list = ⊤ + + switch (t1->kind) + { + default: + abort (); + ret = false; + break; + + case DEBUG_KIND_STRUCT: + case DEBUG_KIND_UNION: + case DEBUG_KIND_CLASS: + case DEBUG_KIND_UNION_CLASS: + if (t1->u.kclass == NULL) + ret = t2->u.kclass == NULL; + else if (t2->u.kclass == NULL) + ret = false; + else if (t1->u.kclass->id > info->base_id + && t1->u.kclass->id == t2->u.kclass->id) + ret = true; + else + ret = debug_class_type_samep (info, t1, t2); + break; + + case DEBUG_KIND_ENUM: + if (t1->u.kenum == NULL) + ret = t2->u.kenum == NULL; + else if (t2->u.kenum == NULL) + ret = false; + else + { + const char **pn1, **pn2; + bfd_signed_vma *pv1, *pv2; + + pn1 = t1->u.kenum->names; + pn2 = t2->u.kenum->names; + pv1 = t1->u.kenum->values; + pv2 = t2->u.kenum->values; + while (*pn1 != NULL && *pn2 != NULL) + { + if (**pn1 != **pn2 + || *pv1 != *pv2 + || strcmp (*pn1, *pn2) != 0) + break; + ++pn1; + ++pn2; + ++pv1; + ++pv2; + } + ret = *pn1 == NULL && *pn2 == NULL; + } + break; + + case DEBUG_KIND_POINTER: + ret = debug_type_samep (info, t1->u.kpointer, t2->u.kpointer); + break; + + case DEBUG_KIND_FUNCTION: + if (t1->u.kfunction->varargs != t2->u.kfunction->varargs + || ! debug_type_samep (info, t1->u.kfunction->return_type, + t2->u.kfunction->return_type) + || ((t1->u.kfunction->arg_types == NULL) + != (t2->u.kfunction->arg_types == NULL))) + ret = false; + else if (t1->u.kfunction->arg_types == NULL) + ret = true; + else + { + struct debug_type **a1, **a2; + + a1 = t1->u.kfunction->arg_types; + a2 = t2->u.kfunction->arg_types; + while (*a1 != NULL && *a2 != NULL) + if (! debug_type_samep (info, *a1, *a2)) + break; + 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; + 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), + debug_get_real_type ((PTR) info, + f2->type))) + 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/gnu/dist/binutils/debug.h b/gnu/dist/binutils/debug.h new file mode 100644 index 00000000000..1b890b234f1 --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/deflex.c b/gnu/dist/binutils/deflex.c new file mode 100644 index 00000000000..2f6604a7408 --- /dev/null +++ b/gnu/dist/binutils/deflex.c @@ -0,0 +1,1747 @@ +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header: /cvsroot/src/gnu/dist/binutils/Attic/deflex.c,v 1.1.1.1 1997/09/24 15:39:23 gwr Exp $ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include <stdio.h> + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include <stdlib.h> +#include <unistd.h> + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include <io.h> +#include <stdlib.h> +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 32 +#define YY_END_OF_BUFFER 33 +static yyconst short int yy_accept[135] = + { 0, + 0, 0, 33, 32, 26, 27, 25, 32, 32, 32, + 23, 31, 29, 19, 24, 28, 30, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, + 21, 20, 0, 22, 23, 19, 24, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 12, 6, 20, 7, 20, 20, 20, 20, 20, + 20, 1, 20, 15, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + + 20, 16, 20, 20, 20, 20, 20, 20, 20, 14, + 20, 18, 20, 20, 20, 20, 17, 9, 20, 10, + 2, 20, 20, 11, 13, 20, 5, 8, 20, 20, + 4, 20, 3, 0 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 4, 1, 5, 1, 6, 1, 1, 7, 1, + 1, 8, 1, 9, 6, 10, 11, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 6, 13, 1, + 14, 1, 1, 15, 16, 17, 18, 19, 20, 21, + 6, 22, 23, 6, 24, 25, 26, 27, 28, 29, + 6, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 1, 1, 1, 1, 6, 1, 21, 21, 21, 21, + + 21, 21, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 21, + 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[39] = + { 0, + 1, 1, 2, 1, 1, 3, 1, 1, 1, 1, + 3, 4, 1, 1, 3, 4, 4, 4, 4, 4, + 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3 + } ; + +static yyconst short int yy_base[141] = + { 0, + 0, 0, 156, 157, 157, 157, 157, 150, 0, 147, + 0, 157, 157, 0, 0, 157, 157, 137, 124, 23, + 115, 130, 123, 125, 24, 127, 22, 126, 115, 139, + 157, 0, 136, 157, 0, 0, 0, 111, 22, 109, + 109, 26, 123, 109, 120, 110, 108, 118, 115, 116, + 115, 100, 106, 108, 107, 95, 109, 106, 105, 94, + 92, 92, 89, 98, 101, 97, 83, 84, 95, 81, + 79, 0, 0, 78, 0, 79, 75, 77, 75, 75, + 88, 0, 77, 0, 79, 81, 76, 76, 78, 81, + 73, 63, 62, 70, 60, 61, 70, 61, 69, 56, + + 58, 0, 58, 55, 63, 51, 43, 49, 42, 0, + 51, 0, 54, 49, 43, 42, 0, 0, 51, 0, + 0, 36, 15, 0, 0, 28, 0, 0, 30, 20, + 0, 20, 0, 157, 55, 57, 61, 65, 41, 69 + } ; + +static yyconst short int yy_def[141] = + { 0, + 134, 1, 134, 134, 134, 134, 134, 135, 136, 137, + 138, 134, 134, 139, 140, 134, 134, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 135, + 134, 136, 137, 134, 138, 139, 140, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 0, 134, 134, 134, 134, 134, 134 + } ; + +static yyconst short int yy_nxt[196] = + { 0, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 4, 14, 15, 16, 17, 9, 18, 19, 20, 21, + 9, 22, 23, 9, 24, 9, 25, 9, 9, 26, + 27, 9, 9, 28, 29, 9, 9, 9, 40, 46, + 55, 49, 41, 50, 36, 59, 133, 132, 56, 131, + 130, 47, 129, 51, 60, 30, 30, 30, 30, 32, + 32, 33, 33, 33, 33, 35, 128, 35, 35, 37, + 127, 37, 37, 126, 125, 124, 123, 122, 121, 120, + 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, + 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, + + 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, + 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, + 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, + 69, 68, 67, 66, 65, 64, 63, 62, 61, 58, + 57, 54, 34, 31, 53, 52, 48, 45, 44, 43, + 42, 39, 38, 34, 31, 134, 3, 134, 134, 134, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 134 + + } ; + +static yyconst short int yy_chk[196] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 20, 25, + 39, 27, 20, 27, 139, 42, 132, 130, 39, 129, + 126, 25, 123, 27, 42, 135, 135, 135, 135, 136, + 136, 137, 137, 137, 137, 138, 122, 138, 138, 140, + 119, 140, 140, 116, 115, 114, 113, 111, 109, 108, + 107, 106, 105, 104, 103, 101, 100, 99, 98, 97, + 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, + + 86, 85, 83, 81, 80, 79, 78, 77, 76, 74, + 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, + 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, + 51, 50, 49, 48, 47, 46, 45, 44, 43, 41, + 40, 38, 33, 30, 29, 28, 26, 24, 23, 22, + 21, 19, 18, 10, 8, 3, 134, 134, 134, 134, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 134 + + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +char *yytext; +#line 1 "./deflex.l" +#define INITIAL 0 +#line 2 "./deflex.l" +/* deflex.l - Lexer for .def files */ + +/* Copyright (C) 1995 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 "defparse.h" +extern char *strdup(); +int linenumber; + +#line 479 "lex.yy.c" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include <stdlib.h> +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 33 "./deflex.l" + +#line 628 "lex.yy.c" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 135 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 157 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 34 "./deflex.l" +{ return NAME;} + YY_BREAK +case 2: +YY_RULE_SETUP +#line 35 "./deflex.l" +{ return LIBRARY;} + YY_BREAK +case 3: +YY_RULE_SETUP +#line 36 "./deflex.l" +{ return DESCRIPTION;} + YY_BREAK +case 4: +YY_RULE_SETUP +#line 37 "./deflex.l" +{ return STACKSIZE;} + YY_BREAK +case 5: +YY_RULE_SETUP +#line 38 "./deflex.l" +{ return HEAPSIZE;} + YY_BREAK +case 6: +YY_RULE_SETUP +#line 39 "./deflex.l" +{ return CODE;} + YY_BREAK +case 7: +YY_RULE_SETUP +#line 40 "./deflex.l" +{ return DATA;} + YY_BREAK +case 8: +YY_RULE_SETUP +#line 41 "./deflex.l" +{ return SECTIONS;} + YY_BREAK +case 9: +YY_RULE_SETUP +#line 42 "./deflex.l" +{ return EXPORTS;} + YY_BREAK +case 10: +YY_RULE_SETUP +#line 43 "./deflex.l" +{ return IMPORTS;} + YY_BREAK +case 11: +YY_RULE_SETUP +#line 44 "./deflex.l" +{ return VERSION;} + YY_BREAK +case 12: +YY_RULE_SETUP +#line 45 "./deflex.l" +{ return BASE;} + YY_BREAK +case 13: +YY_RULE_SETUP +#line 46 "./deflex.l" +{ return CONSTANT; } + YY_BREAK +case 14: +YY_RULE_SETUP +#line 47 "./deflex.l" +{ return NONAME; } + YY_BREAK +case 15: +YY_RULE_SETUP +#line 48 "./deflex.l" +{ return READ;} + YY_BREAK +case 16: +YY_RULE_SETUP +#line 49 "./deflex.l" +{ return WRITE;} + YY_BREAK +case 17: +YY_RULE_SETUP +#line 50 "./deflex.l" +{ return EXECUTE;} + YY_BREAK +case 18: +YY_RULE_SETUP +#line 51 "./deflex.l" +{ return SHARED;} + YY_BREAK +case 19: +YY_RULE_SETUP +#line 53 "./deflex.l" +{ yylval.number = strtol (yytext,0,0); + return NUMBER; } + YY_BREAK +case 20: +YY_RULE_SETUP +#line 56 "./deflex.l" +{ + yylval.id = strdup(yytext); + return ID; + } + YY_BREAK +case 21: +YY_RULE_SETUP +#line 61 "./deflex.l" +{ + yylval.id = strdup (yytext+1); + yylval.id[yyleng-2] = 0; + return ID; + } + YY_BREAK +case 22: +YY_RULE_SETUP +#line 67 "./deflex.l" +{ + yylval.id = strdup (yytext+1); + yylval.id[yyleng-2] = 0; + return ID; + } + YY_BREAK +case 23: +YY_RULE_SETUP +#line 72 "./deflex.l" +{ } + YY_BREAK +case 24: +YY_RULE_SETUP +#line 73 "./deflex.l" +{ } + YY_BREAK +case 25: +YY_RULE_SETUP +#line 74 "./deflex.l" +{ } + YY_BREAK +case 26: +YY_RULE_SETUP +#line 75 "./deflex.l" +{ } + YY_BREAK +case 27: +YY_RULE_SETUP +#line 76 "./deflex.l" +{ linenumber ++ ;} + YY_BREAK +case 28: +YY_RULE_SETUP +#line 77 "./deflex.l" +{ return '=';} + YY_BREAK +case 29: +YY_RULE_SETUP +#line 78 "./deflex.l" +{ return '.';} + YY_BREAK +case 30: +YY_RULE_SETUP +#line 79 "./deflex.l" +{ return '@';} + YY_BREAK +case 31: +YY_RULE_SETUP +#line 80 "./deflex.l" +{ return ',';} + YY_BREAK +case 32: +YY_RULE_SETUP +#line 81 "./deflex.l" +ECHO; + YY_BREAK +#line 883 "lex.yy.c" +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a singled characater, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 135 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 135 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 134); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + yytext_ptr = yy_c_buf_p; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + { + yy_c_buf_p = + yytext_ptr + YY_MORE_ADJ; + return EOF; + } + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + break; + + case EOB_ACT_LAST_MATCH: +#ifdef __cplusplus + YY_FATAL_ERROR( + "unexpected last match in yyinput()" ); +#else + YY_FATAL_ERROR( + "unexpected last match in input()" ); +#endif + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + + return c; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +extern int isatty YY_PROTO(( int )); +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *str ) +#else +YY_BUFFER_STATE yy_scan_string( str ) +yyconst char *str; +#endif + { + int len; + for ( len = 0; str[len]; ++len ) + ; + + return yy_scan_bytes( str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n - YY_MORE_ADJ; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 81 "./deflex.l" + +#ifndef yywrap +/* Needed for lex, though not flex. */ +int yywrap() { return 1; } +#endif diff --git a/gnu/dist/binutils/deflex.l b/gnu/dist/binutils/deflex.l new file mode 100644 index 00000000000..6ce50adb260 --- /dev/null +++ b/gnu/dist/binutils/deflex.l @@ -0,0 +1,85 @@ +%{ +/* deflex.l - Lexer for .def files */ + +/* Copyright (C) 1995 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 "defparse.h" +extern char *strdup(); +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 VERSION;} +"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 = strdup(yytext); + return ID; + } + +"\""[^\"]*"\"" { + yylval.id = strdup (yytext+1); + yylval.id[yyleng-2] = 0; + return ID; + } + +"\'"[^\']*"\'" { + yylval.id = strdup (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/gnu/dist/binutils/defparse.y b/gnu/dist/binutils/defparse.y new file mode 100644 index 00000000000..8a0f844458e --- /dev/null +++ b/gnu/dist/binutils/defparse.y @@ -0,0 +1,132 @@ +/* defparse.y - parser for .def files */ + +/* Copyright (C) 1995 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. */ + + +%union { + char *id; + int number; +}; + +%token NAME, LIBRARY, DESCRIPTION, STACKSIZE, HEAPSIZE, CODE, DATA +%token SECTIONS, EXPORTS, IMPORTS, VERSION, BASE, CONSTANT +%token READ WRITE EXECUTE SHARED NONAME +%token <id> ID +%token <number> NUMBER +%type <number> opt_base opt_ordinal opt_NONAME opt_CONSTANT 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 + | VERSION NUMBER { def_version ($2,0);} + | VERSION NUMBER '.' NUMBER { def_version ($2,$4);} + ; + + +explist: + explist expline + | expline + ; + +expline: + ID opt_equal_name opt_ordinal opt_NONAME opt_CONSTANT + { def_exports ($1, $2, $3, $4, $5);} + ; +implist: + implist impline + | impline + ; + +impline: + ID '=' ID '.' ID { def_import ($1,$3,$5);} + | ID '.' ID { def_import (0, $1,$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_name: ID { $$ =$1; } + | { $$=""; } + ; + +opt_ordinal: + '@' NUMBER { $$=$2;} + | { $$=-1;} + ; + +opt_equal_name: + '=' ID { $$ = $2; } + | { $$ = 0; } + ; + +opt_base: BASE '=' NUMBER { $$= $3;} + | { $$=-1;} + ; + + + diff --git a/gnu/dist/binutils/dep-in.sed b/gnu/dist/binutils/dep-in.sed new file mode 100644 index 00000000000..278f2534068 --- /dev/null +++ b/gnu/dist/binutils/dep-in.sed @@ -0,0 +1,16 @@ +:loop +/\\$/N +/\\$/b loop + +s!@INCDIR@!$(INCDIR)!g +s!@BFDDIR@!$(BFDDIR)!g +s!@SRCDIR@/!!g + +s/\\\n */ /g + +s/ *$// +s/ */ /g +/:$/d + +s/\(.\{50\}[^ ]*\) /\1 \\\ + /g diff --git a/gnu/dist/binutils/dlltool.c b/gnu/dist/binutils/dlltool.c new file mode 100644 index 00000000000..c5530bd1d5f --- /dev/null +++ b/gnu/dist/binutils/dlltool.c @@ -0,0 +1,2358 @@ +/* dlltool.c -- tool to generate stuff for PE style DLLs + Copyright (C) 1995, 96, 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. */ + + +/* + 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] ) * + Declares name1 as an exported symbol from the + DLL, with optional ordinal number <integer> + + IMPORTS ( [ <name> = ] <name> . <name> ) * + Ignored for compatibility + + 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\""); + + adef(char *s) + { + printf("hello from the dll %s\n",s); + } + + 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\""); + cdef(char *s) + { + printf("hello from the dll %s\n",s); + } + + ddef(char *s) + { + printf("hello from the dll and the other entry point %s\n",s); + } + + printf() + { + return 9; + } + + main.c + + 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 Characteristics; - 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. */ +/* 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 <ctype.h> +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#else +#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 +#endif + +#ifdef HAVE_VFORK_H +#include <vfork.h> +#endif + +char *as_name = "as"; + +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; + +int yyparse(); +int yydebug; +static char *def_file; + +static char *program_name; +char *strrchr (); +char *strdup (); + +static int machine; +int killat; +static int verbose; +FILE *output_def; +FILE *base_file; + +#ifdef DLLTOOL_ARM +static char *mname = "arm"; +#endif + +#ifdef DLLTOOL_I386 +static char *mname = "i386"; +#endif + +#ifdef DLLTOOL_PPC +static char *mname = "ppc"; +#endif + +#define PATHMAX 250 /* What's the right name for this ? */ + +/* This bit of assemly does jmp * .... +s set how_jtab_roff to mark where the 32bit abs branch should go */ +unsigned char i386_jtab[] = { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90}; + + +unsigned char arm_jtab[] = { 0x00, 0xc0, 0x9f, 0xe5, + 0x00, 0xf0, 0x9c, 0xe5, + 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. */ +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 */ +}; + +/* the glue instruction, picks up the toc from the stw in */ +/* the above code: "lwz r2,4(r1)" */ +bfd_vma ppc_glue_insn = 0x80410004; + + +char outfile[PATHMAX]; +struct mac + { + char *type; + char *how_byte; + char *how_short; + char *how_long; + char *how_asciz; + char *how_comment; + char *how_jump; + char *how_global; + char *how_space; + char *how_align_short; + char *how_align_long; + char *how_bfd_target; + enum bfd_architecture how_bfd_arch; + 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 */ + } +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, + } + , +{ 0} +}; + + +char * +rvaafter (machine) + int machine; +{ + switch (machine) + { + case MARM: + return ""; + case M386: + return ""; + case MPPC: + return ""; + } +return ""; +} + +char * +rvabefore (machine) + int machine; +{ + switch (machine) + { + case MARM: + return ".rva\t"; + case M386: + return ".rva\t"; + case MPPC: + return ".rva\t"; + } +return ""; +} + +char * +asm_prefix (machine) +int machine; +{ + switch (machine) + { + case MARM: + return ""; + case M386: + return "_"; + case MPPC: + return ""; + } +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; + + +FILE *yyin; /* communications with flex */ +extern int linenumber; +void +process_def_file (name) + char *name; +{ + FILE *f = fopen (name, FOPEN_RT); + if (!f) + { + fprintf (stderr, "%s: Can't open def file %s\n", program_name, name); + exit (1); + } + + yyin = f; + + yyparse (); +} + +/**********************************************************************/ + +/* Communications with the parser */ + + +typedef struct dlist +{ + char *text; + struct dlist *next; +} +dlist_type; + +typedef struct export + { + char *name; + char *internal_name; + int ordinal; + int constant; + int noname; + int hint; + struct export *next; + } +export_type; + +static 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 () +{ + fprintf (stderr, "%s: Syntax error in def file %s:%d\n", + program_name, def_file, linenumber); + return 0; +} + +void +def_exports (name, internal_name, ordinal, noname, constant) + char *name; + char *internal_name; + int ordinal; + int noname; + int constant; +{ + 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->next = d_exports; + d_exports = p; + d_nfuncs++; +} + + +void +def_name (name, base) + char *name; + int base; +{ + if (verbose) + fprintf (stderr, "%s NAME %s base %x\n", program_name, name, base); + if (d_is_dll) + { + fprintf (stderr, "Can't have LIBRARY and NAME\n"); + } + d_name = name; + d_is_exe = 1; +} + +void +def_library (name, base) + char *name; + int base; +{ + if (verbose) + printf ("%s: LIBRARY %s base %x\n", program_name, name, base); + if (d_is_exe) + { + fprintf (stderr, "%s: Can't have LIBRARY and NAME\n", program_name); + } + d_name = name; + d_is_dll = 1; +} + +void +def_description (desc) + char *desc; +{ + dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type)); + d->text = strdup (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 = strdup (dir); + d->next = a_list; + a_list = d; +} + +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 (strdup (b)); +} + +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 (strdup (b)); +} + + +void +def_import (internal, module, entry) + char *internal; + char *module; + char *entry; +{ + if (verbose) + fprintf (stderr, "%s: IMPORTS are ignored", program_name); +} + +void +def_version (major, minor) +int major; +int minor; +{ + printf ("VERSION %d.%d\n", major, minor); +} + + +void +def_section (name, attr) + 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 (strdup (buf)); +} +void +def_code (attr) + int attr; +{ + + def_section ("CODE", attr); +} + +void +def_data (attr) + int attr; +{ + def_section ("DATA", attr); +} + + +/**********************************************************************/ + +void +run (what, args) + char *what; + char *args; +{ + char *s; + int pid; + int i; + char **argv; + extern char **environ; + if (verbose) + 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) + { + argv[i++] = s; + while (*s != ' ' && *s != 0) + s++; + if (*s == 0) + break; + *s++ = 0; + } + argv[i++] = 0; + + + pid = vfork (); + + if (pid == 0) + { + execvp (what, argv); + fprintf (stderr, "%s: can't exec %s\n", program_name, what); + exit (1); + } + else if (pid == -1) + { + extern int errno; + fprintf (stderr, "%s: vfork failed, %d\n", program_name, errno); + exit (1); + } + else + { + int status; + waitpid (pid, &status, 0); + if (status) + { + if (WIFSIGNALED (status)) + { + fprintf (stderr, "%s: %s %s terminated with signal %d\n", + program_name, what, args, WTERMSIG (status)); + exit (1); + } + + if (WIFEXITED (status)) + { + fprintf (stderr, "%s: %s %s terminated with exit status %d\n", + program_name, what, args, WEXITSTATUS (status)); + exit (1); + } + } + } +} + +/* read in and block out the base relocations */ +static void +basenames (abfd) + bfd *abfd; +{ + + + + +} + +void +scan_open_obj_file (abfd) + bfd *abfd; +{ + /* Look for .drectve's */ + asection *s = bfd_get_section_by_name (abfd, ".drectve"); + if (s) + { + int size = bfd_get_section_size_before_reloc (s); + char *buf = xmalloc (size); + char *p; + char *e; + bfd_get_section_contents (abfd, s, buf, 0, size); + if (verbose) + fprintf (stderr, "%s: Sucking in info from %s\n", + program_name, + 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); + } + else + p++; + } + free (buf); + } + + basenames (abfd); + + if (verbose) + fprintf (stderr, "%s: Done readin\n", + program_name); +} + + +void +scan_obj_file (filename) + char *filename; +{ + bfd *f = bfd_openr (filename, 0); + + if (!f) + { + fprintf (stderr, "%s: Unable to open object file %s\n", + program_name, + filename); + exit (1); + } + 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); +} + +/**********************************************************************/ + + + +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\n", + ASM_C, + i, + exp->name, + exp->internal_name, + exp->ordinal, + exp->noname ? "NONAME " : "", + exp->constant ? "CONSTANT" : ""); + } +} +/* Generate the .exp file */ + +int +sfunc (a, b) + long *a; + long *b; +{ + return *a - *b; +} + + + +static void +flush_page (f, need, page_addr, on_page) + FILE *f; + int *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%x\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); + +} + + +void +gen_def_file () +{ + int i; + export_type *exp; + + 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, '.') ? "\"" : ""; + fprintf (output_def, "\t%s%s%s @ %d%s ; %s\n", + quote, + exp->name, + quote, + exp->ordinal, + exp->noname ? " NONAME" : "", + cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS)); + } +} +void +gen_exp_file () +{ + FILE *f; + int i; + export_type *exp; + dlist_type *dl; + + + sprintf (outfile, "t%s", exp_name); + + if (verbose) + fprintf (stderr, "%s: Generate exp file %s\n", + program_name, exp_name); + + f = fopen (outfile, FOPEN_WT); + if (!f) + { + fprintf (stderr, "%s: Unable to open output file %s\n", program_name, outfile); + exit (1); + } + if (verbose) + { + fprintf (stderr, "%s: Opened file %s\n", + program_name, outfile); + } + + 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%x %s Time and date\n", ASM_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) + { + fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, 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; + 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++) + { + addr = copy[j]; + if ((addr & PAGE_MASK) != page_addr) + { + flush_page (f, need, page_addr, on_page); + on_page = 0; + page_addr = addr & PAGE_MASK; + } + need[on_page++] = addr; + } + flush_page (f, need, page_addr, on_page); + +/* fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/ + } + } + + fclose (f); + + /* assemble the file */ + sprintf (outfile, "-o %s t%s", exp_name, exp_name); + run (as_name, outfile); + if (dontdeltemps == 0) + { + sprintf (outfile, "t%s", exp_name); + unlink (outfile); + } +} + +static char * +xlate (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; +} + +/**********************************************************************/ + +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); + } +} + + + +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 PDATA 7 +#define RDATA 8 + +#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 + + .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%d.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, "%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); + + 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, "-o %ss%d.o %ss%d.s", prefix, i, prefix, i); + + run (as_name, outfile); + + } + else + { + + bfd *abfd; + + asymbol *exp_label; + asymbol *iname; + asymbol *iname_lab; + asymbol **iname_lab_pp; + asymbol **iname_pp; + + /* Extra Symbols for PPC */ +#ifdef DLLTOOL_PPC +#define EXTRA 2 +#else +#define EXTRA 0 +#endif + + asymbol *function_name; /* ".." functionName */ + asymbol **fn_pp; + asymbol *toc_symbol; /* The .toc symbol */ + asymbol **toc_pp; + + /* one symbol for each section, 2 extra + a null */ + asymbol *ptrs[NSECS+3+EXTRA+1]; + + char *outname = xmalloc (10); + int oidx = 0; + sprintf (outname, "ds%d.o", i); + abfd = bfd_openw (outname, HOW_BFD_TARGET); + if (!abfd) + { + fprintf (stderr, "%s: bfd_open failed open output file %s\n", + program_name, outname); + exit (1); + } + + bfd_set_format (abfd, bfd_object); + bfd_set_arch_mach (abfd, HOW_BFD_ARCH, 0); + + + /* 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; + + oidx++; + } + + 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 + */ + if (machine == MPPC) + exp_label->section = secdata[RDATA].sec; + else + exp_label->section = secdata[TEXT].sec; + + exp_label->flags = BSF_GLOBAL; + exp_label->value = 0; + + ptrs[oidx++] = exp_label; + + 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; + + + 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; + + iname_lab_pp = ptrs + oidx; + ptrs[oidx++] = iname_lab; + +#ifdef DLLTOOL_PPC + /* The symbol refering to the code (.text) */ + 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 */ + 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: + 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) + { + int idx = exp->hint + 1; + 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; + + 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; + } + } + + { + 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; + } + +} + + +static bfd * +make_head() +{ + FILE * f = fopen ("dh.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, "-o dh.o dh.s"); + run (as_name, outfile); + + return bfd_openr ("dh.o", HOW_BFD_TARGET); +} + +static bfd * +make_tail() +{ + FILE * f = fopen ("dt.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, "-o dt.o dt.s"); + run (as_name, outfile); + return bfd_openr ("dt.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) + { + fprintf (stderr, "%s: Can't open .lib file %s\n", program_name, imp_name); + exit (1); + } + 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(); + + 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; + + bfd_set_archive_head (outarch, head); + bfd_close (outarch); + + /* Delete all the temp files */ + + if (dontdeltemps == 0) + { + sprintf (outfile, "dh.o"); + unlink (outfile); + sprintf (outfile, "dh.s"); + unlink (outfile); + sprintf (outfile, "dt.o"); + unlink (outfile); + sprintf (outfile, "dt.s"); + unlink (outfile); + } + + if (dontdeltemps < 2) + for (i = 0, exp = d_exports; exp; i++, exp = exp->next) + { + sprintf (outfile, "ds%d.o",i); + unlink (outfile); + } + +} +/**********************************************************************/ + +/* Run through the information gathered from the .o files and the + .def file and work out the best stuff */ +int +pfunc (a, b) + void *a; + 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); +} + + +int +nfunc (a, b) + void *a; + 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\n", + i, ptr[i]->name, ptr[i]->ordinal, + ptr[i]->noname ? "NONAME " : "", + ptr[i]->constant ? "CONSTANT" : ""); + } + 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; + if (verbose) + fprintf (stderr, "Warning, ignoring duplicate EXPORT %s %d,%d\n", + a->name, + a->ordinal, + b->ordinal); + if (a->ordinal != -1 + && b->ordinal != -1) + { + + fprintf (stderr, "Error, duplicate EXPORT with oridinals %s\n", + a->name); + exit (1); + } + /* Merge attributes */ + b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal; + b->constant |= a->constant; + b->noname |= a->noname; + 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; + } +} + +int alphafunc(av,bv) +void *av; +void *bv; +{ + export_type **a = av; + export_type **b = bv; + + return strcmp ((*a)->name, (*b)->name); +} + +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); + + 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++; + } + +} + + + + + + +/**********************************************************************/ + +void +usage (file, status) + FILE *file; + int status; +{ + fprintf (file, "Usage %s <options> <object-files>\n", program_name); + 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, " --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, " -v Verbose\n"); + fprintf (file, " -U Add underscores to .lib\n"); + fprintf (file, " -k Kill @<n> from exported names\n"); + fprintf (file, " --as <name> Use <name> for assembler\n"); + fprintf (file, " --nodelete Keep temp files.\n"); + exit (status); +} + +#define OPTION_NO_IDATA4 'x' +#define OPTION_NO_IDATA5 'c' +static struct option long_options[] = +{ + {"nodelete", 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'}, + {"output-lib", required_argument, NULL, 'l'}, + {"def", required_argument, NULL, 'd'}, + {"add-underscore", no_argument, NULL, 'U'}, + {"killat", no_argument, NULL, 'k'}, + {"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'}, + {0} +}; + + + +int +main (ac, av) + int ac; + char **av; +{ + int c; + int i; + char *firstarg = 0; + program_name = av[0]; + oav = av; + + while ((c = getopt_long (ac, av, "xcz:S:R:A:puaD:l:e:nkvbUh?m:yd:", long_options, 0)) + != EOF) + { + switch (c) + { + case OPTION_NO_IDATA4: + no_idata4 = 1; + break; + case OPTION_NO_IDATA5: + no_idata5 = 1; + break; + case 'S': + as_name = 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': + case '?': + usage (stderr, 0); + break; + case 'm': + mname = optarg; + break; + case 'v': + verbose = 1; + break; + case 'y': + yydebug = 1; + break; + case 'U': + add_underscore = 1; + break; + case 'k': + killat = 1; + break; + case 'd': + def_file = optarg; + break; + case 'n': + dontdeltemps++; + break; + case 'b': + base_file = fopen (optarg, FOPEN_RB); + if (!base_file) + { + fprintf (stderr, "%s: Unable to open base-file %s\n", + av[0], + optarg); + exit (1); + } + break; + default: + usage (stderr, 1); + } + } + + + for (i = 0; mtable[i].type; i++) + { + if (strcmp (mtable[i].type, mname) == 0) + break; + } + + if (!mtable[i].type) + { + fprintf (stderr, "Machine not supported\n"); + exit (1); + } + machine = i; + + + if (!dll_name && exp_name) + { + char len = strlen (exp_name) + 5; + dll_name = xmalloc (len); + strcpy (dll_name, exp_name); + strcat (dll_name, ".dll"); + } + + 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 = strdup (imp_name); + for (p = imp_name_lab; *p; *p++) + { + if (!isalpha (*p) && !isdigit (*p)) + *p = '_'; + } + head_label = make_label("_head_", imp_name_lab); + gen_lib_file (); + } + if (output_def) + gen_def_file (); + + return 0; +} diff --git a/gnu/dist/binutils/filemode.c b/gnu/dist/binutils/filemode.c new file mode 100644 index 00000000000..58b52ba7489 --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/ieee.c b/gnu/dist/binutils/ieee.c new file mode 100644 index 00000000000..180b97aacd5 --- /dev/null +++ b/gnu/dist/binutils/ieee.c @@ -0,0 +1,7602 @@ +/* ieee.c -- Read and write IEEE-695 debugging information. + Copyright (C) 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 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.types.alloc = 0; + info.types.types = NULL; + info.tags = NULL; + for (i = 0; i < BUILTIN_TYPE_COUNT; i++) + info.types.builtins[i] = DEBUG_TYPE_NULL; + + p = bytes; + pend = info.pend; + while (p < pend) + { + const bfd_byte *record_start; + ieee_record_enum_type c; + + record_start = p; + + c = (ieee_record_enum_type) *p++; + + if (c == ieee_at_record_enum) + c = (ieee_record_enum_type) (((unsigned int) c << 8) | *p++); + + if (c <= ieee_number_repeat_end_enum) + { + ieee_error (&info, record_start, "unexpected number"); + return false; + } + + switch (c) + { + default: + ieee_error (&info, record_start, "unexpected record type"); + return false; + + case ieee_bb_record_enum: + if (! parse_ieee_bb (&info, &p)) + return false; + break; + + case ieee_be_record_enum: + if (! parse_ieee_be (&info, &p)) + return false; + break; + + case ieee_nn_record: + if (! parse_ieee_nn (&info, &p)) + return false; + break; + + case ieee_ty_record_enum: + if (! parse_ieee_ty (&info, &p)) + return false; + break; + + case ieee_atn_record_enum: + if (! parse_ieee_atn (&info, &p)) + return false; + break; + } + } + + if (info.blockstack.bsp != info.blockstack.stack) + { + ieee_error (&info, (const bfd_byte *) NULL, + "blocks left on stack at end"); + return false; + } + + return true; +} + +/* Handle an IEEE BB record. */ + +static boolean +parse_ieee_bb (info, pp) + struct ieee_info *info; + const bfd_byte **pp; +{ + const bfd_byte *block_start; + bfd_byte b; + bfd_vma size; + const char *name; + unsigned long namlen; + char *namcopy = NULL; + unsigned int fnindx; + boolean skip; + + block_start = *pp; + + b = **pp; + ++*pp; + + if (! ieee_read_number (info, pp, &size) + || ! ieee_read_id (info, pp, &name, &namlen)) + return false; + + fnindx = (unsigned int) -1; + skip = false; + + switch (b) + { + case 1: + /* BB1: Type definitions local to a module. */ + namcopy = savestring (name, namlen); + if (namcopy == NULL) + return false; + if (! debug_set_filename (info->dhandle, namcopy)) + return false; + info->saw_filename = true; + + /* Discard any variables or types we may have seen before. */ + if (info->vars.vars != NULL) + free (info->vars.vars); + info->vars.vars = NULL; + info->vars.alloc = 0; + if (info->types.types != NULL) + free (info->types.types); + info->types.types = NULL; + info->types.alloc = 0; + + /* Initialize the types to the global types. */ + if (info->global_types != NULL) + { + info->types.alloc = info->global_types->alloc; + info->types.types = ((struct ieee_type *) + xmalloc (info->types.alloc + * sizeof (*info->types.types))); + memcpy (info->types.types, info->global_types->types, + info->types.alloc * sizeof (*info->types.types)); + } + + break; + + case 2: + /* BB2: Global type definitions. The name is supposed to be + empty, but we don't check. */ + if (! debug_set_filename (info->dhandle, "*global*")) + return false; + info->saw_filename = true; + break; + + case 3: + /* BB3: High level module block begin. We don't have to do + anything here. The name is supposed to be the same as for + the BB1, but we don't check. */ + break; + + case 4: + /* BB4: Global function. */ + { + bfd_vma stackspace, typindx, offset; + debug_type return_type; + + if (! ieee_read_number (info, pp, &stackspace) + || ! ieee_read_number (info, pp, &typindx) + || ! ieee_read_expression (info, pp, &offset)) + return false; + + /* We have no way to record the stack space. FIXME. */ + + if (typindx < 256) + { + return_type = ieee_builtin_type (info, block_start, typindx); + if (return_type == DEBUG_TYPE_NULL) + return false; + } + else + { + typindx -= 256; + if (! ieee_alloc_type (info, typindx, true)) + return false; + fnindx = typindx; + return_type = info->types.types[typindx].type; + if (debug_get_type_kind (info->dhandle, return_type) + == DEBUG_KIND_FUNCTION) + return_type = debug_get_return_type (info->dhandle, + return_type); + } + + namcopy = savestring (name, namlen); + if (namcopy == NULL) + return false; + if (! debug_record_function (info->dhandle, namcopy, return_type, + true, offset)) + return false; + } + break; + + case 5: + /* BB5: File name for source line numbers. */ + { + unsigned int i; + + /* We ignore the date and time. FIXME. */ + for (i = 0; i < 6; i++) + { + bfd_vma ignore; + boolean present; + + if (! ieee_read_optional_number (info, pp, &ignore, &present)) + return false; + if (! present) + break; + } + + namcopy = savestring (name, namlen); + if (namcopy == NULL) + return false; + if (! debug_start_source (info->dhandle, namcopy)) + return false; + } + break; + + case 6: + /* BB6: Local function or block. */ + { + bfd_vma stackspace, typindx, offset; + + if (! ieee_read_number (info, pp, &stackspace) + || ! ieee_read_number (info, pp, &typindx) + || ! ieee_read_expression (info, pp, &offset)) + return false; + + /* We have no way to record the stack space. FIXME. */ + + if (namlen == 0) + { + if (! debug_start_block (info->dhandle, offset)) + return false; + /* Change b to indicate that this is a block + rather than a function. */ + b = 0x86; + } + else + { + /* The MRI C++ compiler will output a fake function named + __XRYCPP to hold C++ debugging information. We skip + that function. This is not crucial, but it makes + converting from IEEE to other debug formats work + better. */ + if (strncmp (name, "__XRYCPP", namlen) == 0) + skip = true; + else + { + debug_type return_type; + + if (typindx < 256) + { + return_type = ieee_builtin_type (info, block_start, + typindx); + if (return_type == NULL) + return false; + } + else + { + typindx -= 256; + if (! ieee_alloc_type (info, typindx, true)) + return false; + fnindx = typindx; + return_type = info->types.types[typindx].type; + if (debug_get_type_kind (info->dhandle, return_type) + == DEBUG_KIND_FUNCTION) + return_type = debug_get_return_type (info->dhandle, + return_type); + } + + namcopy = savestring (name, namlen); + if (namcopy == NULL) + return false; + if (! debug_record_function (info->dhandle, namcopy, + return_type, false, offset)) + return false; + } + } + } + break; + + case 10: + /* BB10: Assembler module scope. In the normal case, we + completely ignore all this information. FIXME. */ + { + const char *inam, *vstr; + unsigned long inamlen, vstrlen; + bfd_vma tool_type; + boolean present; + unsigned int i; + + if (! info->saw_filename) + { + namcopy = savestring (name, namlen); + if (namcopy == NULL) + return false; + if (! debug_set_filename (info->dhandle, namcopy)) + return false; + info->saw_filename = true; + } + + if (! ieee_read_id (info, pp, &inam, &inamlen) + || ! ieee_read_number (info, pp, &tool_type) + || ! ieee_read_optional_id (info, pp, &vstr, &vstrlen, &present)) + return false; + for (i = 0; i < 6; i++) + { + bfd_vma ignore; + + if (! ieee_read_optional_number (info, pp, &ignore, &present)) + return false; + if (! present) + break; + } + } + break; + + case 11: + /* BB11: Module section. We completely ignore all this + information. FIXME. */ + { + bfd_vma sectype, secindx, offset, map; + boolean present; + + if (! ieee_read_number (info, pp, §ype) + || ! ieee_read_number (info, pp, &secindx) + || ! ieee_read_expression (info, pp, &offset) + || ! ieee_read_optional_number (info, pp, &map, &present)) + return false; + } + break; + + default: + ieee_error (info, block_start, "unknown BB type"); + return false; + } + + + /* Push this block on the block stack. */ + + if (info->blockstack.bsp >= info->blockstack.stack + BLOCKSTACK_SIZE) + { + ieee_error (info, (const bfd_byte *) NULL, "stack overflow"); + return false; + } + + info->blockstack.bsp->kind = b; + if (b == 5) + info->blockstack.bsp->filename = namcopy; + info->blockstack.bsp->fnindx = fnindx; + info->blockstack.bsp->skip = skip; + ++info->blockstack.bsp; + + return true; +} + +/* Handle an IEEE BE record. */ + +static boolean +parse_ieee_be (info, pp) + struct ieee_info *info; + const bfd_byte **pp; +{ + bfd_vma offset; + + if (info->blockstack.bsp <= info->blockstack.stack) + { + ieee_error (info, *pp, "stack underflow"); + return false; + } + --info->blockstack.bsp; + + switch (info->blockstack.bsp->kind) + { + case 2: + /* When we end the global typedefs block, we copy out the the + contents of info->vars. This is because the variable indices + may be reused in the local blocks. However, we need to + preserve them so that we can locate a function returning a + reference variable whose type is named in the global typedef + block. */ + info->global_vars = ((struct ieee_vars *) + xmalloc (sizeof *info->global_vars)); + info->global_vars->alloc = info->vars.alloc; + info->global_vars->vars = ((struct ieee_var *) + xmalloc (info->vars.alloc + * sizeof (*info->vars.vars))); + memcpy (info->global_vars->vars, info->vars.vars, + info->vars.alloc * sizeof (*info->vars.vars)); + + /* We also copy out the non builtin parts of info->types, since + the types are discarded when we start a new block. */ + info->global_types = ((struct ieee_types *) + xmalloc (sizeof *info->global_types)); + info->global_types->alloc = info->types.alloc; + info->global_types->types = ((struct ieee_type *) + xmalloc (info->types.alloc + * sizeof (*info->types.types))); + memcpy (info->global_types->types, info->types.types, + info->types.alloc * sizeof (*info->types.types)); + memset (info->global_types->builtins, 0, + sizeof (info->global_types->builtins)); + + break; + + case 4: + case 6: + if (! ieee_read_expression (info, pp, &offset)) + return false; + if (! info->blockstack.bsp->skip) + { + if (! debug_end_function (info->dhandle, offset + 1)) + return false; + } + break; + + case 0x86: + /* This is BE6 when BB6 started a block rather than a local + function. */ + if (! ieee_read_expression (info, pp, &offset)) + return false; + if (! debug_end_block (info->dhandle, offset + 1)) + return false; + break; + + case 5: + /* When we end a BB5, we look up the stack for the last BB5, if + there is one, so that we can call debug_start_source. */ + if (info->blockstack.bsp > info->blockstack.stack) + { + struct ieee_block *bl; + + bl = info->blockstack.bsp; + do + { + --bl; + if (bl->kind == 5) + { + if (! debug_start_source (info->dhandle, bl->filename)) + return false; + break; + } + } + while (bl != info->blockstack.stack); + } + break; + + case 11: + if (! ieee_read_expression (info, pp, &offset)) + return false; + /* We just ignore the module size. FIXME. */ + break; + + default: + /* Other block types do not have any trailing information. */ + break; + } + + return true; +} + +/* Parse an NN record. */ + +static boolean +parse_ieee_nn (info, pp) + struct ieee_info *info; + const bfd_byte **pp; +{ + const bfd_byte *nn_start; + bfd_vma varindx; + const char *name; + unsigned long namlen; + + nn_start = *pp; + + if (! ieee_read_number (info, pp, &varindx) + || ! ieee_read_id (info, pp, &name, &namlen)) + return false; + + if (varindx < 32) + { + ieee_error (info, nn_start, "illegal variable index"); + return false; + } + varindx -= 32; + + if (varindx >= info->vars.alloc) + { + unsigned int alloc; + + alloc = info->vars.alloc; + if (alloc == 0) + alloc = 4; + while (varindx >= alloc) + alloc *= 2; + info->vars.vars = ((struct ieee_var *) + xrealloc (info->vars.vars, + alloc * sizeof *info->vars.vars)); + memset (info->vars.vars + info->vars.alloc, 0, + (alloc - info->vars.alloc) * sizeof *info->vars.vars); + info->vars.alloc = alloc; + } + + info->vars.vars[varindx].name = name; + info->vars.vars[varindx].namlen = namlen; + + return true; +} + +/* Parse a TY record. */ + +static boolean +parse_ieee_ty (info, pp) + struct ieee_info *info; + const bfd_byte **pp; +{ + const bfd_byte *ty_start, *ty_var_start, *ty_code_start; + bfd_vma typeindx, varindx, tc; + PTR dhandle; + boolean tag, typdef; + debug_type *arg_slots; + unsigned long type_bitsize; + debug_type type; + + ty_start = *pp; + + if (! ieee_read_number (info, pp, &typeindx)) + return false; + + if (typeindx < 256) + { + ieee_error (info, ty_start, "illegal type index"); + return false; + } + + typeindx -= 256; + if (! ieee_alloc_type (info, typeindx, false)) + return false; + + if (**pp != 0xce) + { + ieee_error (info, *pp, "unknown TY code"); + return false; + } + ++*pp; + + ty_var_start = *pp; + + if (! ieee_read_number (info, pp, &varindx)) + return false; + + if (varindx < 32) + { + ieee_error (info, ty_var_start, "illegal variable index"); + return false; + } + varindx -= 32; + + if (varindx >= info->vars.alloc || info->vars.vars[varindx].name == NULL) + { + ieee_error (info, ty_var_start, "undefined variable in TY"); + return false; + } + + ty_code_start = *pp; + + if (! ieee_read_number (info, pp, &tc)) + return false; + + dhandle = info->dhandle; + + tag = false; + typdef = false; + arg_slots = NULL; + type_bitsize = 0; + switch (tc) + { + default: + ieee_error (info, ty_code_start, "unknown TY code"); + return false; + + case '!': + /* Unknown type, with size. We treat it as int. FIXME. */ + { + bfd_vma size; + + if (! ieee_read_number (info, pp, &size)) + return false; + type = debug_make_int_type (dhandle, size, false); + } + break; + + case 'A': /* Array. */ + case 'a': /* FORTRAN array in column/row order. FIXME: Not + distinguished from normal array. */ + { + debug_type ele_type; + bfd_vma lower, upper; + + if (! ieee_read_type_index (info, pp, &ele_type) + || ! ieee_read_number (info, pp, &lower) + || ! ieee_read_number (info, pp, &upper)) + return false; + type = debug_make_array_type (dhandle, ele_type, + ieee_builtin_type (info, ty_code_start, + ((unsigned int) + builtin_int)), + (bfd_signed_vma) lower, + (bfd_signed_vma) upper, + false); + } + break; + + case 'E': + /* Simple enumeration. */ + { + bfd_vma size; + unsigned int alloc; + const char **names; + unsigned int c; + bfd_signed_vma *vals; + unsigned int i; + + if (! ieee_read_number (info, pp, &size)) + return false; + /* FIXME: we ignore the enumeration size. */ + + alloc = 10; + names = (const char **) xmalloc (alloc * sizeof *names); + memset (names, 0, alloc * sizeof *names); + c = 0; + while (1) + { + const char *name; + unsigned long namlen; + boolean present; + + if (! ieee_read_optional_id (info, pp, &name, &namlen, &present)) + return false; + if (! present) + break; + + if (c + 1 >= alloc) + { + alloc += 10; + names = ((const char **) + xrealloc (names, alloc * sizeof *names)); + } + + names[c] = savestring (name, namlen); + if (names[c] == NULL) + return false; + ++c; + } + + names[c] = NULL; + + vals = (bfd_signed_vma *) xmalloc (c * sizeof *vals); + for (i = 0; i < c; i++) + vals[i] = i; + + type = debug_make_enum_type (dhandle, names, vals); + tag = true; + } + break; + + case 'G': + /* Struct with bit fields. */ + { + bfd_vma size; + unsigned int alloc; + debug_field *fields; + unsigned int c; + + if (! ieee_read_number (info, pp, &size)) + return false; + + alloc = 10; + fields = (debug_field *) xmalloc (alloc * sizeof *fields); + c = 0; + while (1) + { + const char *name; + unsigned long namlen; + boolean present; + debug_type ftype; + bfd_vma bitpos, bitsize; + + if (! ieee_read_optional_id (info, pp, &name, &namlen, &present)) + return false; + if (! present) + break; + if (! ieee_read_type_index (info, pp, &ftype) + || ! ieee_read_number (info, pp, &bitpos) + || ! ieee_read_number (info, pp, &bitsize)) + return false; + + if (c + 1 >= alloc) + { + alloc += 10; + fields = ((debug_field *) + xrealloc (fields, alloc * sizeof *fields)); + } + + fields[c] = debug_make_field (dhandle, savestring (name, namlen), + ftype, bitpos, bitsize, + DEBUG_VISIBILITY_PUBLIC); + if (fields[c] == NULL) + return false; + ++c; + } + + fields[c] = NULL; + + type = debug_make_struct_type (dhandle, true, size, fields); + tag = true; + } + break; + + case 'N': + /* Enumeration. */ + { + unsigned int alloc; + const char **names; + bfd_signed_vma *vals; + unsigned int c; + + alloc = 10; + names = (const char **) xmalloc (alloc * sizeof *names); + vals = (bfd_signed_vma *) xmalloc (alloc * sizeof *names); + c = 0; + while (1) + { + const char *name; + unsigned long namlen; + boolean present; + bfd_vma val; + + if (! ieee_read_optional_id (info, pp, &name, &namlen, &present)) + return false; + if (! present) + break; + if (! ieee_read_number (info, pp, &val)) + return false; + + /* If the length of the name is zero, then the value is + actually the size of the enum. We ignore this + information. FIXME. */ + if (namlen == 0) + continue; + + if (c + 1 >= alloc) + { + alloc += 10; + names = ((const char **) + xrealloc (names, alloc * sizeof *names)); + vals = ((bfd_signed_vma *) + xrealloc (vals, alloc * sizeof *vals)); + } + + names[c] = savestring (name, namlen); + if (names[c] == NULL) + return false; + vals[c] = (bfd_signed_vma) val; + ++c; + } + + names[c] = NULL; + + type = debug_make_enum_type (dhandle, names, vals); + tag = true; + } + break; + + case 'O': /* Small pointer. We don't distinguish small and large + pointers. FIXME. */ + case 'P': /* Large pointer. */ + { + debug_type t; + + if (! ieee_read_type_index (info, pp, &t)) + return false; + type = debug_make_pointer_type (dhandle, t); + } + break; + + case 'R': + /* Range. */ + { + bfd_vma low, high, signedp, size; + + if (! ieee_read_number (info, pp, &low) + || ! ieee_read_number (info, pp, &high) + || ! ieee_read_number (info, pp, &signedp) + || ! ieee_read_number (info, pp, &size)) + return false; + + type = debug_make_range_type (dhandle, + debug_make_int_type (dhandle, size, + ! signedp), + (bfd_signed_vma) low, + (bfd_signed_vma) high); + } + break; + + case 'S': /* Struct. */ + case 'U': /* Union. */ + { + bfd_vma size; + unsigned int alloc; + debug_field *fields; + unsigned int c; + + if (! ieee_read_number (info, pp, &size)) + return false; + + alloc = 10; + fields = (debug_field *) xmalloc (alloc * sizeof *fields); + c = 0; + while (1) + { + const char *name; + unsigned long namlen; + boolean present; + bfd_vma tindx; + bfd_vma offset; + debug_type ftype; + bfd_vma bitsize; + + if (! ieee_read_optional_id (info, pp, &name, &namlen, &present)) + return false; + if (! present) + break; + if (! ieee_read_number (info, pp, &tindx) + || ! ieee_read_number (info, pp, &offset)) + return false; + + if (tindx < 256) + { + ftype = ieee_builtin_type (info, ty_code_start, tindx); + bitsize = 0; + offset *= 8; + } + else + { + struct ieee_type *t; + + tindx -= 256; + if (! ieee_alloc_type (info, tindx, true)) + return false; + t = info->types.types + tindx; + ftype = t->type; + bitsize = t->bitsize; + if (bitsize == 0) + offset *= 8; + } + + if (c + 1 >= alloc) + { + alloc += 10; + fields = ((debug_field *) + xrealloc (fields, alloc * sizeof *fields)); + } + + fields[c] = debug_make_field (dhandle, savestring (name, namlen), + ftype, offset, bitsize, + DEBUG_VISIBILITY_PUBLIC); + if (fields[c] == NULL) + return false; + ++c; + } + + fields[c] = NULL; + + type = debug_make_struct_type (dhandle, tc == 'S', size, fields); + tag = true; + } + break; + + case 'T': + /* Typedef. */ + if (! ieee_read_type_index (info, pp, &type)) + return false; + typdef = true; + break; + + case 'X': + /* Procedure. FIXME: This is an extern declaration, which we + have no way of representing. */ + { + bfd_vma attr; + debug_type rtype; + bfd_vma nargs; + boolean present; + struct ieee_var *pv; + + /* FIXME: We ignore the attribute and the argument names. */ + + if (! ieee_read_number (info, pp, &attr) + || ! ieee_read_type_index (info, pp, &rtype) + || ! ieee_read_number (info, pp, &nargs)) + return false; + do + { + const char *name; + unsigned long namlen; + + if (! ieee_read_optional_id (info, pp, &name, &namlen, &present)) + return false; + } + while (present); + + pv = info->vars.vars + varindx; + pv->kind = IEEE_EXTERNAL; + if (pv->namlen > 0 + && debug_get_type_kind (dhandle, rtype) == DEBUG_KIND_POINTER) + { + /* Set up the return type as an indirect type pointing to + the variable slot, so that we can change it to a + reference later if appropriate. */ + pv->pslot = (debug_type *) xmalloc (sizeof *pv->pslot); + *pv->pslot = rtype; + rtype = debug_make_indirect_type (dhandle, pv->pslot, + (const char *) NULL); + } + + type = debug_make_function_type (dhandle, rtype, (debug_type *) NULL, + false); + } + break; + + case 'V': + /* Void. This is not documented, but the MRI compiler emits it. */ + type = debug_make_void_type (dhandle); + break; + + case 'Z': + /* Array with 0 lower bound. */ + { + debug_type etype; + bfd_vma high; + + if (! ieee_read_type_index (info, pp, &etype) + || ! ieee_read_number (info, pp, &high)) + return false; + + type = debug_make_array_type (dhandle, etype, + ieee_builtin_type (info, ty_code_start, + ((unsigned int) + builtin_int)), + 0, (bfd_signed_vma) high, false); + } + break; + + case 'c': /* Complex. */ + case 'd': /* Double complex. */ + { + const char *name; + unsigned long namlen; + + /* FIXME: I don't know what the name means. */ + + if (! ieee_read_id (info, pp, &name, &namlen)) + return false; + + type = debug_make_complex_type (dhandle, tc == 'c' ? 4 : 8); + } + break; + + case 'f': + /* Pascal file name. FIXME. */ + ieee_error (info, ty_code_start, "Pascal file name not supported"); + return false; + + case 'g': + /* Bitfield type. */ + { + bfd_vma signedp, bitsize, dummy; + const bfd_byte *hold; + boolean present; + + if (! ieee_read_number (info, pp, &signedp) + || ! ieee_read_number (info, pp, &bitsize)) + return false; + + /* I think the documentation says that there is a type index, + but some actual files do not have one. */ + hold = *pp; + if (! ieee_read_optional_number (info, pp, &dummy, &present)) + return false; + if (! present) + { + /* FIXME: This is just a guess. */ + type = debug_make_int_type (dhandle, 4, + signedp ? false : true); + } + else + { + *pp = hold; + if (! ieee_read_type_index (info, pp, &type)) + return false; + } + type_bitsize = bitsize; + } + break; + + case 'n': + /* Qualifier. */ + { + bfd_vma kind; + debug_type t; + + if (! ieee_read_number (info, pp, &kind) + || ! ieee_read_type_index (info, pp, &t)) + return false; + + switch (kind) + { + default: + ieee_error (info, ty_start, "unsupported qualifer"); + return false; + + case 1: + type = debug_make_const_type (dhandle, t); + break; + + case 2: + type = debug_make_volatile_type (dhandle, t); + break; + } + } + break; + + case 's': + /* Set. */ + { + bfd_vma size; + debug_type etype; + + if (! ieee_read_number (info, pp, &size) + || ! ieee_read_type_index (info, pp, &etype)) + return false; + + /* FIXME: We ignore the size. */ + + type = debug_make_set_type (dhandle, etype, false); + } + break; + + case 'x': + /* Procedure with compiler dependencies. */ + { + struct ieee_var *pv; + bfd_vma attr, frame_type, push_mask, nargs, level, father; + debug_type rtype; + debug_type *arg_types; + boolean varargs; + boolean present; + + /* FIXME: We ignore some of this information. */ + + pv = info->vars.vars + varindx; + + if (! ieee_read_number (info, pp, &attr) + || ! ieee_read_number (info, pp, &frame_type) + || ! ieee_read_number (info, pp, &push_mask) + || ! ieee_read_type_index (info, pp, &rtype) + || ! ieee_read_number (info, pp, &nargs)) + return false; + if (nargs == (bfd_vma) -1) + { + arg_types = NULL; + varargs = false; + } + else + { + unsigned int i; + + arg_types = ((debug_type *) + xmalloc ((nargs + 1) * sizeof *arg_types)); + for (i = 0; i < nargs; i++) + if (! ieee_read_type_index (info, pp, arg_types + i)) + return false; + + /* If the last type is pointer to void, this is really a + varargs function. */ + varargs = false; + if (nargs > 0) + { + debug_type last; + + last = arg_types[nargs - 1]; + if (debug_get_type_kind (dhandle, last) == DEBUG_KIND_POINTER + && (debug_get_type_kind (dhandle, + debug_get_target_type (dhandle, + last)) + == DEBUG_KIND_VOID)) + { + --nargs; + varargs = true; + } + } + + /* If there are any pointer arguments, turn them into + indirect types in case we later need to convert them to + reference types. */ + for (i = 0; i < nargs; i++) + { + if (debug_get_type_kind (dhandle, arg_types[i]) + == DEBUG_KIND_POINTER) + { + if (arg_slots == NULL) + { + arg_slots = ((debug_type *) + xmalloc (nargs * sizeof *arg_slots)); + memset (arg_slots, 0, nargs * sizeof *arg_slots); + } + arg_slots[i] = arg_types[i]; + arg_types[i] = + debug_make_indirect_type (dhandle, + arg_slots + i, + (const char *) NULL); + } + } + + arg_types[nargs] = DEBUG_TYPE_NULL; + } + if (! ieee_read_number (info, pp, &level) + || ! ieee_read_optional_number (info, pp, &father, &present)) + return false; + + /* We can't distinguish between a global function and a static + function. */ + pv->kind = IEEE_FUNCTION; + + if (pv->namlen > 0 + && debug_get_type_kind (dhandle, rtype) == DEBUG_KIND_POINTER) + { + /* Set up the return type as an indirect type pointing to + the variable slot, so that we can change it to a + reference later if appropriate. */ + pv->pslot = (debug_type *) xmalloc (sizeof *pv->pslot); + *pv->pslot = rtype; + rtype = debug_make_indirect_type (dhandle, pv->pslot, + (const char *) NULL); + } + + type = debug_make_function_type (dhandle, rtype, arg_types, varargs); + } + break; + } + + /* Record the type in the table. */ + + if (type == DEBUG_TYPE_NULL) + return false; + + info->vars.vars[varindx].type = type; + + if ((tag || typdef) + && info->vars.vars[varindx].namlen > 0) + { + const char *name; + + name = savestring (info->vars.vars[varindx].name, + info->vars.vars[varindx].namlen); + if (typdef) + type = debug_name_type (dhandle, name, type); + else if (tc == 'E' || tc == 'N') + type = debug_tag_type (dhandle, name, type); + else + { + struct ieee_tag *it; + + /* We must allocate all struct tags as indirect types, so + that if we later see a definition of the tag as a C++ + record we can update the indirect slot and automatically + change all the existing references. */ + it = (struct ieee_tag *) xmalloc (sizeof *it); + memset (it, 0, sizeof *it); + it->next = info->tags; + info->tags = it; + it->name = name; + it->slot = type; + + type = debug_make_indirect_type (dhandle, &it->slot, name); + type = debug_tag_type (dhandle, name, type); + + it->type = type; + } + if (type == NULL) + return false; + } + + info->types.types[typeindx].type = type; + info->types.types[typeindx].arg_slots = arg_slots; + info->types.types[typeindx].bitsize = type_bitsize; + + /* We may have already allocated type as an indirect type pointing + to slot. It does no harm to replace the indirect type with the + real type. Filling in slot as well handles the indirect types + which are already hanging around. */ + if (info->types.types[typeindx].pslot != NULL) + *info->types.types[typeindx].pslot = type; + + return true; +} + +/* Parse an ATN record. */ + +static boolean +parse_ieee_atn (info, pp) + struct ieee_info *info; + const bfd_byte **pp; +{ + const bfd_byte *atn_start, *atn_code_start; + bfd_vma varindx; + struct ieee_var *pvar; + debug_type type; + bfd_vma atn_code; + PTR dhandle; + bfd_vma v, v2, v3, v4, v5; + const char *name; + unsigned long namlen; + char *namcopy; + boolean present; + int blocktype; + + atn_start = *pp; + + if (! ieee_read_number (info, pp, &varindx) + || ! ieee_read_type_index (info, pp, &type)) + return false; + + atn_code_start = *pp; + + if (! ieee_read_number (info, pp, &atn_code)) + return false; + + if (varindx == 0) + { + pvar = NULL; + name = ""; + namlen = 0; + } + else if (varindx < 32) + { + 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/gnu/dist/binutils/is-ranlib.c b/gnu/dist/binutils/is-ranlib.c new file mode 100644 index 00000000000..fde72a43da5 --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/is-strip.c b/gnu/dist/binutils/is-strip.c new file mode 100644 index 00000000000..215341a325c --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/mac-binutils.r b/gnu/dist/binutils/mac-binutils.r new file mode 100644 index 00000000000..7b1a3035e28 --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/makefile.vms b/gnu/dist/binutils/makefile.vms new file mode 100644 index 00000000000..5e9b2df7629 --- /dev/null +++ b/gnu/dist/binutils/makefile.vms @@ -0,0 +1,93 @@ +# +# Makefile for binutils under openVMS/Alpha +# +# For use with gnu-make for vms +# +# Created by Klaus K"ampf, kkaempf@progis.de +# +# + +# Distribution version, filled in by configure.com +VERSION= + +TARGET=""evax-alpha"" + +ifeq ($(CC),gcc) +CFLAGS=/include=([],[-.include],[-.bfd])$(DEFS) +DEFS=/define=("TARGET=$(TARGET)") +LIBS=,GNU:[000000]libgcc/lib,sys$$library:vaxcrtl.olb/lib,GNU:[000000]crt0.obj +else +CFLAGS=/noopt/debug/include=([],[-.include],[-.bfd])$(DEFS)/warnings=disable=(missingreturn,implicitfunc) +DEFS=/define=("TARGET=$(TARGET)",\ +"const=","unlink=remove",\ +"_bfd_generic_get_section_contents_in_window"="_bfd_generic_get_win_section_cont",\ +"_bfd_elf_section_from_bfd_section"="_bfd_elf_sec_from_bfd_sec") +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 + +[-.bfd]libbfd.olb: + $(CD) [-.bfd] + $(MAKE) -f makefile.vms + $(CD) [-.binutils] + +[-.libiberty]libiberty.olb: + $(CD) [-.libiberty] + $(MAKE) -f makefile.vms + $(CD) [-.binutils] + +[-.opcodes]libopcodes.olb: + $(CD) [-.opcodes] + $(MAKE) -f makefile.vms + $(CD) [-.binutils] + +clean: + $$ purge + $(RM) *.obj; + $(RM) *.exe; + $(RM) config.h; diff --git a/gnu/dist/binutils/maybe-ranlib.c b/gnu/dist/binutils/maybe-ranlib.c new file mode 100644 index 00000000000..f37bc0ff216 --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/maybe-strip.c b/gnu/dist/binutils/maybe-strip.c new file mode 100644 index 00000000000..6467c99e935 --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/mpw-config.in b/gnu/dist/binutils/mpw-config.in new file mode 100644 index 00000000000..21a067ddd6b --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/mpw-make.sed b/gnu/dist/binutils/mpw-make.sed new file mode 100644 index 00000000000..03abffe18f8 --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/nlmconv.1 b/gnu/dist/binutils/nlmconv.1 new file mode 100644 index 00000000000..cbc3aedd101 --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/nlmconv.c b/gnu/dist/binutils/nlmconv.c new file mode 100644 index 00000000000..df993f85424 --- /dev/null +++ b/gnu/dist/binutils/nlmconv.c @@ -0,0 +1,2294 @@ +/* nlmconv.c -- NLM conversion program + Copyright (C) 1993, 94, 95, 96, 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. */ + +/* 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> + +#ifdef HAVE_VFORK_H +#include <vfork.h> +#endif + +/* 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 *)); +static int pexecute PARAMS ((char *, 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, *help_data, *message_data, *rpc_data, *shared_data; + size_t custom_size, help_size, message_size, module_size, rpc_size; + asection *custom_section, *help_section, *message_section, *module_section; + asection *rpc_section, *shared_section; + bfd *sharedbfd; + size_t shared_offset, shared_size; + Nlm_Internal_Fixed_Header sharedhdr; + int len; + char *modname; + char **matching; + + program_name = argv[0]; + xmalloc_set_program_name (program_name); + + bfd_init (); + set_default_bfd_target (); + + while ((opt = getopt_long (argc, argv, "dhI:l:O:T:V", long_options, + (int *) NULL)) + != EOF) + { + switch (opt) + { + case 'd': + debug = 1; + break; + case 'h': + show_help (); + /*NOTREACHED*/ + case 'I': + input_format = optarg; + break; + case 'l': + ld_arg = optarg; + break; + case 'O': + output_format = optarg; + break; + case 'T': + header_file = optarg; + break; + case 'V': + print_version ("nlmconv"); + /*NOTREACHED*/ + case 0: + break; + default: + show_usage (stderr, 1); + /*NOTREACHED*/ + } + } + + /* The input and output files may be named on the command line. */ + output_file = NULL; + if (optind < argc) + { + input_file = argv[optind]; + ++optind; + if (optind < argc) + { + output_file = argv[optind]; + ++optind; + if (optind < argc) + show_usage (stderr, 1); + if (strcmp (input_file, output_file) == 0) + { + fprintf (stderr, + "%s: input and output files must be different\n", + program_name); + exit (1); + } + } + } + + /* Initialize the header information to default values. */ + fixed_hdr = &fixed_hdr_struct; + memset ((PTR) &fixed_hdr_struct, 0, sizeof fixed_hdr_struct); + var_hdr = &var_hdr_struct; + memset ((PTR) &var_hdr_struct, 0, sizeof var_hdr_struct); + version_hdr = &version_hdr_struct; + memset ((PTR) &version_hdr_struct, 0, sizeof version_hdr_struct); + copyright_hdr = ©right_hdr_struct; + memset ((PTR) ©right_hdr_struct, 0, sizeof copyright_hdr_struct); + extended_hdr = &extended_hdr_struct; + memset ((PTR) &extended_hdr_struct, 0, sizeof extended_hdr_struct); + check_procedure = NULL; + custom_file = NULL; + debug_info = false; + exit_procedure = "_Stop"; + export_symbols = NULL; + map_file = NULL; + full_map = false; + help_file = NULL; + import_symbols = NULL; + message_file = NULL; + modules = NULL; + sharelib_file = NULL; + start_procedure = "_Prelude"; + verbose = false; + rpc_file = NULL; + + parse_errors = 0; + + /* Parse the header file (if there is one). */ + if (header_file != NULL) + { + if (! nlmlex_file (header_file) + || yyparse () != 0 + || parse_errors != 0) + exit (1); + } + + if (input_files != NULL) + { + if (input_file != NULL) + { + fprintf (stderr, + "%s: input file named both on command line and with INPUT\n", + program_name); + exit (1); + } + if (input_files->next == NULL) + input_file = input_files->string; + else + input_file = link_inputs (input_files, ld_arg); + } + else if (input_file == NULL) + { + fprintf (stderr, "%s: no input file\n", program_name); + show_usage (stderr, 1); + } + + inbfd = bfd_openr (input_file, input_format); + if (inbfd == NULL) + bfd_fatal (input_file); + + if (! bfd_check_format_matches (inbfd, bfd_object, &matching)) + { + bfd_nonfatal (input_file); + if (bfd_get_error () == bfd_error_file_ambiguously_recognized) + { + list_matching_formats (matching); + free (matching); + } + exit (1); + } + + if (output_format == NULL) + output_format = select_output_format (bfd_get_arch (inbfd), + bfd_get_mach (inbfd), + bfd_big_endian (inbfd)); + + assert (output_format != NULL); + + /* Use the output file named on the command line if it exists. + Otherwise use the file named in the OUTPUT statement. */ + if (output_file == NULL) + { + fprintf (stderr, "%s: no name for output file\n", + program_name); + show_usage (stderr, 1); + } + + outbfd = bfd_openw (output_file, output_format); + if (outbfd == NULL) + bfd_fatal (output_file); + if (! bfd_set_format (outbfd, bfd_object)) + bfd_fatal (output_file); + + assert (bfd_get_flavour (outbfd) == bfd_target_nlm_flavour); + + if (bfd_arch_get_compatible (inbfd, outbfd) == NULL) + fprintf (stderr, + "%s: warning:input and output formats are not compatible\n", + program_name); + + /* Move the values read from the command file into outbfd. */ + *nlm_fixed_header (outbfd) = fixed_hdr_struct; + *nlm_variable_header (outbfd) = var_hdr_struct; + *nlm_version_header (outbfd) = version_hdr_struct; + *nlm_copyright_header (outbfd) = copyright_hdr_struct; + *nlm_extended_header (outbfd) = extended_hdr_struct; + + /* Start copying the input BFD to the output BFD. */ + if (! bfd_set_file_flags (outbfd, bfd_get_file_flags (inbfd))) + bfd_fatal (bfd_get_filename (outbfd)); + + symsize = bfd_get_symtab_upper_bound (inbfd); + if (symsize < 0) + bfd_fatal (input_file); + symbols = (asymbol **) xmalloc (symsize); + symcount = bfd_canonicalize_symtab (inbfd, symbols); + if (symcount < 0) + bfd_fatal (input_file); + + /* Make sure we have a .bss section. */ + bss_sec = bfd_get_section_by_name (outbfd, NLM_UNINITIALIZED_DATA_NAME); + if (bss_sec == NULL) + { + bss_sec = bfd_make_section (outbfd, NLM_UNINITIALIZED_DATA_NAME); + if (bss_sec == NULL + || ! bfd_set_section_flags (outbfd, bss_sec, SEC_ALLOC) + || ! bfd_set_section_alignment (outbfd, bss_sec, 1)) + bfd_fatal ("make .bss section"); + } + + /* We store the original section names in the .nlmsections section, + so that programs which understand it can resurrect the original + sections from the NLM. We will put a pointer to .nlmsections in + the NLM header area. */ + secsec = bfd_make_section (outbfd, ".nlmsections"); + if (secsec == NULL) + bfd_fatal ("make .nlmsections section"); + if (! bfd_set_section_flags (outbfd, secsec, SEC_HAS_CONTENTS)) + bfd_fatal ("set .nlmsections flags"); + +#ifdef NLMCONV_POWERPC + /* For PowerPC NetWare we need to build stubs for calls to undefined + symbols. Because each stub requires an entry in the TOC section + which must be at the same location as other entries in the TOC + section, we must do this before determining where the TOC section + goes in setup_sections. */ + if (bfd_get_arch (inbfd) == bfd_arch_powerpc) + powerpc_build_stubs (inbfd, outbfd, &symbols, &symcount); +#endif + + /* Set up the sections. */ + bfd_map_over_sections (inbfd, setup_sections, (PTR) outbfd); + + text_sec = bfd_get_section_by_name (outbfd, NLM_CODE_NAME); + + /* The .bss section immediately follows the .data section. */ + data_sec = bfd_get_section_by_name (outbfd, NLM_INITIALIZED_DATA_NAME); + if (data_sec != NULL) + { + bfd_size_type add; + + vma = bfd_get_section_size_before_reloc (data_sec); + align = 1 << bss_sec->alignment_power; + add = ((vma + align - 1) &~ (align - 1)) - vma; + vma += add; + if (! bfd_set_section_vma (outbfd, bss_sec, vma)) + bfd_fatal ("set .bss vma"); + if (add != 0) + { + bfd_size_type data_size; + + data_size = bfd_get_section_size_before_reloc (data_sec); + if (! bfd_set_section_size (outbfd, data_sec, data_size + add)) + bfd_fatal ("set .data size"); + } + } + + /* Adjust symbol information. */ + inlead = bfd_get_symbol_leading_char (inbfd); + outlead = bfd_get_symbol_leading_char (outbfd); + gotstart = false; + gotexit = false; + gotcheck = false; + newsymalloc = 10; + newsyms = (asymbol **) xmalloc (newsymalloc * sizeof (asymbol *)); + newsymcount = 0; + endsym = NULL; + for (i = 0; i < symcount; i++) + { + register asymbol *sym; + + sym = symbols[i]; + + /* Add or remove a leading underscore. */ + if (inlead != outlead) + { + if (inlead != '\0') + { + if (bfd_asymbol_name (sym)[0] == inlead) + { + if (outlead == '\0') + ++sym->name; + else + { + char *new; + + new = xmalloc (strlen (bfd_asymbol_name (sym)) + 1); + new[0] = outlead; + strcpy (new + 1, bfd_asymbol_name (sym) + 1); + sym->name = new; + } + } + } + else + { + char *new; + + new = xmalloc (strlen (bfd_asymbol_name (sym)) + 2); + new[0] = outlead; + strcpy (new + 1, bfd_asymbol_name (sym)); + sym->name = new; + } + } + + /* NLM's have an uninitialized data section, but they do not + have a common section in the Unix sense. Move all common + symbols into the .bss section, and mark them as exported. */ + if (bfd_is_com_section (bfd_get_section (sym))) + { + bfd_vma size; + + sym->section = bss_sec; + size = sym->value; + sym->value = bss_sec->_raw_size; + bss_sec->_raw_size += size; + align = 1 << bss_sec->alignment_power; + bss_sec->_raw_size = (bss_sec->_raw_size + align - 1) &~ (align - 1); + sym->flags |= BSF_EXPORT | BSF_GLOBAL; + } + else if (bfd_get_section (sym)->output_section != NULL) + { + /* Move the symbol into the output section. */ + sym->value += bfd_get_section (sym)->output_offset; + sym->section = bfd_get_section (sym)->output_section; + /* This is no longer a section symbol. */ + sym->flags &=~ BSF_SECTION_SYM; + } + + /* Force _edata and _end to be defined. This would normally be + done by the linker, but the manipulation of the common + symbols will confuse it. */ + if ((sym->flags & BSF_DEBUGGING) == 0 + && bfd_asymbol_name (sym)[0] == '_' + && bfd_is_und_section (bfd_get_section (sym))) + { + if (strcmp (bfd_asymbol_name (sym), "_edata") == 0) + { + sym->section = bss_sec; + sym->value = 0; + } + if (strcmp (bfd_asymbol_name (sym), "_end") == 0) + { + sym->section = bss_sec; + endsym = sym; + } + +#ifdef NLMCONV_POWERPC + /* For PowerPC NetWare, we define __GOT0. This is the start + of the .got section. */ + if (bfd_get_arch (inbfd) == bfd_arch_powerpc + && strcmp (bfd_asymbol_name (sym), "__GOT0") == 0) + { + asection *got_sec; + + got_sec = bfd_get_section_by_name (inbfd, ".got"); + assert (got_sec != (asection *) NULL); + sym->value = got_sec->output_offset; + sym->section = got_sec->output_section; + } +#endif + } + + /* If this is a global symbol, check the export list. */ + if ((sym->flags & (BSF_EXPORT | BSF_GLOBAL)) != 0) + { + register struct string_list *l; + int found_simple; + + /* Unfortunately, a symbol can appear multiple times on the + export list, with and without prefixes. */ + found_simple = 0; + for (l = export_symbols; l != NULL; l = l->next) + { + if (strcmp (l->string, bfd_asymbol_name (sym)) == 0) + found_simple = 1; + else + { + char *zbase; + + zbase = strchr (l->string, '@'); + if (zbase != NULL + && strcmp (zbase + 1, bfd_asymbol_name (sym)) == 0) + { + /* We must add a symbol with this prefix. */ + if (newsymcount >= newsymalloc) + { + newsymalloc += 10; + newsyms = ((asymbol **) + xrealloc ((PTR) newsyms, + (newsymalloc + * sizeof (asymbol *)))); + } + newsyms[newsymcount] = + (asymbol *) xmalloc (sizeof (asymbol)); + *newsyms[newsymcount] = *sym; + newsyms[newsymcount]->name = l->string; + ++newsymcount; + } + } + } + if (! found_simple) + { + /* The unmodified symbol is actually not exported at + all. */ + sym->flags &=~ (BSF_GLOBAL | BSF_EXPORT); + sym->flags |= BSF_LOCAL; + } + } + + /* If it's an undefined symbol, see if it's on the import list. + Change the prefix if necessary. */ + if (bfd_is_und_section (bfd_get_section (sym))) + { + register struct string_list *l; + + for (l = import_symbols; l != NULL; l = l->next) + { + if (strcmp (l->string, bfd_asymbol_name (sym)) == 0) + break; + else + { + char *zbase; + + zbase = strchr (l->string, '@'); + if (zbase != NULL + && strcmp (zbase + 1, bfd_asymbol_name (sym)) == 0) + { + sym->name = l->string; + break; + } + } + } + if (l == NULL) + fprintf (stderr, + "%s: warning: symbol %s imported but not in import list\n", + program_name, bfd_asymbol_name (sym)); + } + + /* See if it's one of the special named symbols. */ + if ((sym->flags & BSF_DEBUGGING) == 0) + { + bfd_vma val; + + /* FIXME: If these symbols are not in the .text section, we + add the .text section size to the value. This may not be + correct for all targets. I'm not sure how this should + really be handled. */ + if (strcmp (bfd_asymbol_name (sym), start_procedure) == 0) + { + val = bfd_asymbol_value (sym); + if (bfd_get_section (sym) == data_sec + && text_sec != (asection *) NULL) + val += bfd_section_size (outbfd, text_sec); + if (! bfd_set_start_address (outbfd, val)) + bfd_fatal ("set start address"); + gotstart = true; + } + if (strcmp (bfd_asymbol_name (sym), exit_procedure) == 0) + { + val = bfd_asymbol_value (sym); + if (bfd_get_section (sym) == data_sec + && text_sec != (asection *) NULL) + val += bfd_section_size (outbfd, text_sec); + nlm_fixed_header (outbfd)->exitProcedureOffset = val; + gotexit = true; + } + if (check_procedure != NULL + && strcmp (bfd_asymbol_name (sym), check_procedure) == 0) + { + val = bfd_asymbol_value (sym); + if (bfd_get_section (sym) == data_sec + && text_sec != (asection *) NULL) + val += bfd_section_size (outbfd, text_sec); + nlm_fixed_header (outbfd)->checkUnloadProcedureOffset = val; + gotcheck = true; + } + } + } + + if (endsym != NULL) + { + endsym->value = bfd_get_section_size_before_reloc (bss_sec); + + /* FIXME: If any relocs referring to _end use inplace addends, + then I think they need to be updated. This is handled by + i386_mangle_relocs. Is it needed for any other object + formats? */ + } + + if (newsymcount == 0) + outsyms = symbols; + else + { + outsyms = (asymbol **) xmalloc ((symcount + newsymcount + 1) + * sizeof (asymbol *)); + memcpy (outsyms, symbols, symcount * sizeof (asymbol *)); + memcpy (outsyms + symcount, newsyms, newsymcount * sizeof (asymbol *)); + outsyms[symcount + newsymcount] = NULL; + } + + bfd_set_symtab (outbfd, outsyms, symcount + newsymcount); + + if (! gotstart) + fprintf (stderr, "%s: warning: START procedure %s not defined\n", + program_name, start_procedure); + if (! gotexit) + fprintf (stderr, "%s: warning: EXIT procedure %s not defined\n", + program_name, exit_procedure); + if (check_procedure != NULL + && ! gotcheck) + fprintf (stderr, "%s: warning: CHECK procedure %s not defined\n", + program_name, check_procedure); + + /* Add additional sections required for the header information. */ + if (custom_file != NULL) + { + custom_data = fopen (custom_file, "r"); + if (custom_data == NULL + || fstat (fileno (custom_data), &st) < 0) + { + fprintf (stderr, "%s:%s: %s\n", program_name, custom_file, + strerror (errno)); + custom_file = NULL; + } + else + { + custom_size = st.st_size; + custom_section = bfd_make_section (outbfd, ".nlmcustom"); + if (custom_section == NULL + || ! bfd_set_section_size (outbfd, custom_section, custom_size) + || ! bfd_set_section_flags (outbfd, custom_section, + SEC_HAS_CONTENTS)) + bfd_fatal ("custom section"); + } + } + if (help_file != NULL) + { + help_data = fopen (help_file, "r"); + if (help_data == NULL + || fstat (fileno (help_data), &st) < 0) + { + fprintf (stderr, "%s:%s: %s\n", program_name, help_file, + strerror (errno)); + help_file = NULL; + } + else + { + help_size = st.st_size; + help_section = bfd_make_section (outbfd, ".nlmhelp"); + if (help_section == NULL + || ! bfd_set_section_size (outbfd, help_section, help_size) + || ! bfd_set_section_flags (outbfd, help_section, + SEC_HAS_CONTENTS)) + bfd_fatal ("help section"); + strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8); + } + } + if (message_file != NULL) + { + message_data = fopen (message_file, "r"); + if (message_data == NULL + || fstat (fileno (message_data), &st) < 0) + { + fprintf (stderr, "%s:%s: %s\n", program_name, message_file, + strerror (errno)); + message_file = NULL; + } + else + { + message_size = st.st_size; + message_section = bfd_make_section (outbfd, ".nlmmessages"); + if (message_section == NULL + || ! bfd_set_section_size (outbfd, message_section, message_size) + || ! bfd_set_section_flags (outbfd, message_section, + SEC_HAS_CONTENTS)) + bfd_fatal ("message section"); + strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8); + } + } + if (modules != NULL) + { + struct string_list *l; + + module_size = 0; + for (l = modules; l != NULL; l = l->next) + module_size += strlen (l->string) + 1; + module_section = bfd_make_section (outbfd, ".nlmmodules"); + if (module_section == NULL + || ! bfd_set_section_size (outbfd, module_section, module_size) + || ! bfd_set_section_flags (outbfd, module_section, + SEC_HAS_CONTENTS)) + bfd_fatal ("module section"); + } + if (rpc_file != NULL) + { + rpc_data = fopen (rpc_file, "r"); + if (rpc_data == NULL + || fstat (fileno (rpc_data), &st) < 0) + { + fprintf (stderr, "%s:%s: %s\n", program_name, rpc_file, + strerror (errno)); + rpc_file = NULL; + } + else + { + rpc_size = st.st_size; + rpc_section = bfd_make_section (outbfd, ".nlmrpc"); + if (rpc_section == NULL + || ! bfd_set_section_size (outbfd, rpc_section, rpc_size) + || ! bfd_set_section_flags (outbfd, rpc_section, + SEC_HAS_CONTENTS)) + bfd_fatal ("rpc section"); + strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8); + } + } + if (sharelib_file != NULL) + { + sharedbfd = bfd_openr (sharelib_file, output_format); + if (sharedbfd == NULL + || ! bfd_check_format (sharedbfd, bfd_object)) + { + fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file, + bfd_errmsg (bfd_get_error ())); + sharelib_file = NULL; + } + else + { + sharedhdr = *nlm_fixed_header (sharedbfd); + bfd_close (sharedbfd); + shared_data = fopen (sharelib_file, "r"); + if (shared_data == NULL + || (fstat (fileno (shared_data), &st) < 0)) + { + fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file, + strerror (errno)); + sharelib_file = NULL; + } + else + { + /* If we were clever, we could just copy out the + sections of the shared library which we actually + need. However, we would have to figure out the sizes + of the external and public information, and that can + not be done without reading through them. */ + if (sharedhdr.uninitializedDataSize > 0) + { + /* There is no place to record this information. */ + fprintf (stderr, + "%s:%s: warning: shared libraries can not have uninitialized data\n", + program_name, sharelib_file); + } + shared_offset = st.st_size; + if (shared_offset > sharedhdr.codeImageOffset) + shared_offset = sharedhdr.codeImageOffset; + if (shared_offset > sharedhdr.dataImageOffset) + shared_offset = sharedhdr.dataImageOffset; + if (shared_offset > sharedhdr.relocationFixupOffset) + shared_offset = sharedhdr.relocationFixupOffset; + if (shared_offset > sharedhdr.externalReferencesOffset) + shared_offset = sharedhdr.externalReferencesOffset; + if (shared_offset > 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 (*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@prep.ai.mit.edu\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 < 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; + + 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); + + if (waitpid (pid, &status, 0) < 0) + { + perror ("waitpid"); + 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; +} + +/* Execute a job. Stolen from gcc.c. */ + +#ifndef OS2 +#ifdef __MSDOS__ + +static int +pexecute (program, argv) + char *program; + char *argv[]; +{ + char *scmd, *rf; + FILE *argfile; + int i; + + scmd = (char *) xmalloc (strlen (program) + strlen (temp_filename) + 10); + rf = scmd + strlen(program) + 2 + el; + sprintf (scmd, "%s.exe @%s.gp", program, temp_filename); + argfile = fopen (rf, "w"); + if (argfile == 0) + pfatal_with_name (rf); + + for (i=1; argv[i]; i++) + { + char *cp; + for (cp = argv[i]; *cp; cp++) + { + if (*cp == '"' || *cp == '\'' || *cp == '\\' || isspace (*cp)) + fputc ('\\', argfile); + fputc (*cp, argfile); + } + fputc ('\n', argfile); + } + fclose (argfile); + + i = system (scmd); + + remove (rf); + + if (i == -1) + { + perror (program); + return MIN_FATAL_STATUS << 8; + } + + return i << 8; +} + +#else /* not __MSDOS__ */ + +static int +pexecute (program, argv) + char *program; + char *argv[]; +{ + int pid; + int retries, sleep_interval; + + /* Fork a subprocess; wait and retry if it fails. */ + sleep_interval = 1; + for (retries = 0; retries < 4; retries++) + { + pid = vfork (); + if (pid >= 0) + break; + sleep (sleep_interval); + sleep_interval *= 2; + } + + switch (pid) + { + case -1: +#ifdef vfork + perror ("fork"); +#else + perror ("vfork"); +#endif + exit (1); + /* NOTREACHED */ + return 0; + + case 0: /* child */ + /* Exec the program. */ + execvp (program, argv); + perror (program); + exit (1); + /* NOTREACHED */ + return 0; + + default: + /* Return child's process number. */ + return pid; + } +} + +#endif /* not __MSDOS__ */ +#else /* not OS2 */ + +static int +pexecute (program, argv) + char *program; + char *argv[]; +{ + return spawnvp (1, program, argv); +} +#endif /* not OS2 */ diff --git a/gnu/dist/binutils/nlmconv.h b/gnu/dist/binutils/nlmconv.h new file mode 100644 index 00000000000..c92a557bb7f --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/nlmheader.c b/gnu/dist/binutils/nlmheader.c new file mode 100644 index 00000000000..73b564da0a6 --- /dev/null +++ b/gnu/dist/binutils/nlmheader.c @@ -0,0 +1,1930 @@ + +/* A Bison parser, made from ./nlmheader.y with Bison version GNU Bison version 1.24 + */ + +#define YYBISON 1 /* Identify Bison output. */ + +#define CHECK 258 +#define CODESTART 259 +#define COPYRIGHT 260 +#define CUSTOM 261 +#define DATE 262 +#define DEBUG 263 +#define DESCRIPTION 264 +#define EXIT 265 +#define EXPORT 266 +#define FLAG_ON 267 +#define FLAG_OFF 268 +#define FULLMAP 269 +#define HELP 270 +#define IMPORT 271 +#define INPUT 272 +#define MAP 273 +#define MESSAGES 274 +#define MODULE 275 +#define MULTIPLE 276 +#define OS_DOMAIN 277 +#define OUTPUT 278 +#define PSEUDOPREEMPTION 279 +#define REENTRANT 280 +#define SCREENNAME 281 +#define SHARELIB 282 +#define STACK 283 +#define START 284 +#define SYNCHRONIZE 285 +#define THREADNAME 286 +#define TYPE 287 +#define VERBOSE 288 +#define VERSION 289 +#define XDCDATA 290 +#define STRING 291 +#define QUOTED_STRING 292 + +#line 1 "./nlmheader.y" +/* nlmheader.y - parse NLM header specification keywords. + 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>. + + 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 *)); + + +#line 112 "./nlmheader.y" +typedef union +{ + char *string; + struct string_list *list; +} YYSTYPE; + +#ifndef YYLTYPE +typedef + struct yyltype + { + int timestamp; + int first_line; + int first_column; + int last_line; + int last_column; + char *text; + } + yyltype; + +#define YYLTYPE yyltype +#endif + +#include <stdio.h> + +#ifndef __cplusplus +#ifndef __STDC__ +#define const +#endif +#endif + + + +#define YYFINAL 82 +#define YYFLAG -32768 +#define YYNTBASE 40 + +#define YYTRANSLATE(x) ((unsigned)(x) <= 292 ? yytranslate[x] : 50) + +static const char yytranslate[] = { 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 38, + 39, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37 +}; + +#if YYDEBUG != 0 +static const short yyprhs[] = { 0, + 0, 2, 3, 6, 9, 12, 15, 18, 23, 25, + 28, 31, 32, 36, 39, 42, 44, 47, 50, 51, + 55, 58, 60, 63, 66, 69, 71, 73, 76, 78, + 80, 83, 86, 89, 92, 94, 97, 100, 102, 107, + 111, 114, 115, 117, 119, 121, 124, 127, 131, 133, + 134 +}; + +static const short yyrhs[] = { 41, + 0, 0, 42, 41, 0, 3, 36, 0, 4, 36, + 0, 5, 37, 0, 6, 36, 0, 7, 36, 36, + 36, 0, 8, 0, 9, 37, 0, 10, 36, 0, + 0, 11, 43, 45, 0, 12, 36, 0, 13, 36, + 0, 14, 0, 14, 36, 0, 15, 36, 0, 0, + 16, 44, 45, 0, 17, 49, 0, 18, 0, 18, + 36, 0, 19, 36, 0, 20, 49, 0, 21, 0, + 22, 0, 23, 36, 0, 24, 0, 25, 0, 26, + 37, 0, 27, 36, 0, 28, 36, 0, 29, 36, + 0, 30, 0, 31, 37, 0, 32, 36, 0, 33, + 0, 34, 36, 36, 36, 0, 34, 36, 36, 0, + 35, 36, 0, 0, 46, 0, 48, 0, 47, 0, + 46, 48, 0, 46, 47, 0, 38, 36, 39, 0, + 36, 0, 0, 36, 49, 0 +}; + +#endif + +#if YYDEBUG != 0 +static const short yyrline[] = { 0, + 143, 149, 151, 156, 161, 166, 183, 187, 205, 209, + 225, 229, 234, 237, 242, 247, 252, 257, 261, 266, + 269, 273, 277, 281, 285, 289, 293, 297, 304, 308, + 312, 328, 332, 337, 341, 345, 361, 366, 370, 394, + 410, 418, 423, 433, 438, 442, 446, 454, 465, 481, + 486 +}; + +static const char * const yytname[] = { "$","error","$undefined.","CHECK", +"CODESTART","COPYRIGHT","CUSTOM","DATE","DEBUG","DESCRIPTION","EXIT","EXPORT", +"FLAG_ON","FLAG_OFF","FULLMAP","HELP","IMPORT","INPUT","MAP","MESSAGES","MODULE", +"MULTIPLE","OS_DOMAIN","OUTPUT","PSEUDOPREEMPTION","REENTRANT","SCREENNAME", +"SHARELIB","STACK","START","SYNCHRONIZE","THREADNAME","TYPE","VERBOSE","VERSION", +"XDCDATA","STRING","QUOTED_STRING","'('","')'","file","commands","command","@1", +"@2","symbol_list_opt","symbol_list","symbol_prefix","symbol","string_list", +"" +}; +#endif + +static const short yyr1[] = { 0, + 40, 41, 41, 42, 42, 42, 42, 42, 42, 42, + 42, 43, 42, 42, 42, 42, 42, 42, 44, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 45, 45, 46, 46, 46, 46, 47, 48, 49, + 49 +}; + +static const short yyr2[] = { 0, + 1, 0, 2, 2, 2, 2, 2, 4, 1, 2, + 2, 0, 3, 2, 2, 1, 2, 2, 0, 3, + 2, 1, 2, 2, 2, 1, 1, 2, 1, 1, + 2, 2, 2, 2, 1, 2, 2, 1, 4, 3, + 2, 0, 1, 1, 1, 2, 2, 3, 1, 0, + 2 +}; + +static const short yydefact[] = { 2, + 0, 0, 0, 0, 0, 9, 0, 0, 12, 0, + 0, 16, 0, 19, 50, 22, 0, 50, 26, 27, + 0, 29, 30, 0, 0, 0, 0, 35, 0, 0, + 38, 0, 0, 1, 2, 4, 5, 6, 7, 0, + 10, 11, 42, 14, 15, 17, 18, 42, 50, 21, + 23, 24, 25, 28, 31, 32, 33, 34, 36, 37, + 0, 41, 3, 0, 49, 0, 13, 43, 45, 44, + 20, 51, 40, 8, 0, 47, 46, 39, 48, 0, + 0, 0 +}; + +static const short yydefgoto[] = { 80, + 34, 35, 43, 48, 67, 68, 69, 70, 50 +}; + +static const short yypact[] = { -3, + -1, 1, 2, 4, 5,-32768, 6, 8,-32768, 9, + 10, 11, 12,-32768, 13, 14, 16, 13,-32768,-32768, + 17,-32768,-32768, 18, 20, 21, 22,-32768, 23, 25, +-32768, 26, 27,-32768, -3,-32768,-32768,-32768,-32768, 29, +-32768,-32768, -2,-32768,-32768,-32768,-32768, -2, 13,-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, + 30,-32768,-32768, 31,-32768, 32,-32768, -2,-32768,-32768, +-32768,-32768, 33,-32768, 3,-32768,-32768,-32768,-32768, 38, + 51,-32768 +}; + +static const short yypgoto[] = {-32768, + 19,-32768,-32768,-32768, 24,-32768, -9, 7, 15 +}; + + +#define YYLAST 75 + + +static const short yytable[] = { 1, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 53, 65, 36, 66, 37, 81, 38, 39, + 40, 79, 41, 42, 44, 45, 46, 47, 49, 51, + 82, 52, 54, 63, 55, 56, 57, 58, 76, 59, + 60, 61, 62, 72, 64, 73, 74, 75, 78, 0, + 0, 71, 0, 0, 77 +}; + +static const short yycheck[] = { 3, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 18, 36, 36, 38, 36, 0, 37, 36, + 36, 39, 37, 36, 36, 36, 36, 36, 36, 36, + 0, 36, 36, 35, 37, 36, 36, 36, 68, 37, + 36, 36, 36, 49, 36, 36, 36, 36, 36, -1, + -1, 48, -1, -1, 68 +}; +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ +#line 3 "/usr/unsupported/share/bison.simple" + +/* Skeleton output parser for bison, + Copyright (C) 1984, 1989, 1990 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +#ifndef alloca +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not GNU C. */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) +#include <alloca.h> +#else /* not sparc */ +#if defined (MSDOS) && !defined (__TURBOC__) +#include <malloc.h> +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +#include <malloc.h> + #pragma alloca +#else /* not MSDOS, __TURBOC__, or _AIX */ +#ifdef __hpux +#ifdef __cplusplus +extern "C" { +void *alloca (unsigned int); +}; +#else /* not __cplusplus */ +void *alloca (); +#endif /* not __cplusplus */ +#endif /* __hpux */ +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc. */ +#endif /* not GNU C. */ +#endif /* alloca not defined. */ + +/* This is the parser code that is written into each bison parser + when the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +/* Note: there must be only one dollar sign in this file. + It is replaced by the list of actions, each action + as one case of the switch. */ + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT return(0) +#define YYABORT return(1) +#define YYERROR goto yyerrlab1 +/* Like YYERROR except do call yyerror. + This remains here temporarily to ease the + transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ +#define YYFAIL goto yyerrlab +#define YYRECOVERING() (!!yyerrstatus) +#define YYBACKUP(token, value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { yychar = (token), yylval = (value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { yyerror ("syntax error: cannot back up"); YYERROR; } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +#ifndef YYPURE +#define YYLEX yylex() +#endif + +#ifdef YYPURE +#ifdef YYLSP_NEEDED +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval, &yylloc) +#endif +#else /* not YYLSP_NEEDED */ +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval) +#endif +#endif /* not YYLSP_NEEDED */ +#endif + +/* If nonreentrant, generate the variables here */ + +#ifndef YYPURE + +int yychar; /* the lookahead symbol */ +YYSTYPE yylval; /* the semantic value of the */ + /* lookahead symbol */ + +#ifdef YYLSP_NEEDED +YYLTYPE yylloc; /* location data for the lookahead */ + /* symbol */ +#endif + +int yynerrs; /* number of parse errors so far */ +#endif /* not YYPURE */ + +#if YYDEBUG != 0 +int yydebug; /* nonzero means print parse trace */ +/* Since this is uninitialized, it does not stop multiple parsers + from coexisting. */ +#endif + +/* YYINITDEPTH indicates the initial size of the parser's stacks */ + +#ifndef YYINITDEPTH +#define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH is the maximum size the stacks can grow to + (effective only if the built-in stack extension method is used). */ + +#if YYMAXDEPTH == 0 +#undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 10000 +#endif + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +int yyparse (void); +#endif + +#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ +#define __yy_memcpy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT) +#else /* not GNU C or C++ */ +#ifndef __cplusplus + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (from, to, count) + char *from; + char *to; + int count; +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#else /* __cplusplus */ + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (char *from, char *to, int count) +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#endif +#endif + +#line 192 "/usr/unsupported/share/bison.simple" + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +#else +#define YYPARSE_PARAM +#define YYPARSE_PARAM_DECL +#endif + +int +yyparse(YYPARSE_PARAM) + YYPARSE_PARAM_DECL +{ + register int yystate; + register int yyn; + register short *yyssp; + register YYSTYPE *yyvsp; + int yyerrstatus; /* number of tokens to shift before error messages enabled */ + int yychar1 = 0; /* lookahead token as an internal (translated) token number */ + + short yyssa[YYINITDEPTH]; /* the state stack */ + YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ + + short *yyss = yyssa; /* refer to the stacks thru separate pointers */ + YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ + +#ifdef YYLSP_NEEDED + YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; + +#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else +#define YYPOPSTACK (yyvsp--, yyssp--) +#endif + + int yystacksize = YYINITDEPTH; + +#ifdef YYPURE + int yychar; + YYSTYPE yylval; + int yynerrs; +#ifdef YYLSP_NEEDED + YYLTYPE yylloc; +#endif +#endif + + YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ + + int yylen; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Starting parse\n"); +#endif + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss - 1; + yyvsp = yyvs; +#ifdef YYLSP_NEEDED + yylsp = yyls; +#endif + +/* Push a new state, which is found in yystate . */ +/* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. */ +yynewstate: + + *++yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Give user a chance to reallocate the stack */ + /* Use copies of these so that the &'s don't force the real ones into memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; +#ifdef YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; +#endif + + /* Get the current used size of the three stacks, in elements. */ + int size = yyssp - yyss + 1; + +#ifdef yyoverflow + /* Each stack pointer address is followed by the size of + the data in use in that stack, in bytes. */ +#ifdef YYLSP_NEEDED + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yyls1, size * sizeof (*yylsp), + &yystacksize); +#else + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yystacksize); +#endif + + yyss = yyss1; yyvs = yyvs1; +#ifdef YYLSP_NEEDED + yyls = yyls1; +#endif +#else /* no yyoverflow */ + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + { + yyerror("parser stack overflow"); + return 2; + } + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; + yyss = (short *) alloca (yystacksize * sizeof (*yyssp)); + __yy_memcpy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp)); + yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp)); + __yy_memcpy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp)); +#ifdef YYLSP_NEEDED + yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp)); + __yy_memcpy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp)); +#endif +#endif /* no yyoverflow */ + + yyssp = yyss + size - 1; + yyvsp = yyvs + size - 1; +#ifdef YYLSP_NEEDED + yylsp = yyls + size - 1; +#endif + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Stack size increased to %d\n", yystacksize); +#endif + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Entering state %d\n", yystate); +#endif + + goto yybackup; + yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Reading a token: "); +#endif + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Now at end of input.\n"); +#endif + } + else + { + yychar1 = YYTRANSLATE(yychar); + +#if YYDEBUG != 0 + if (yydebug) + { + fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise meaning + of a token, for further debugging info. */ +#ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +#endif + fprintf (stderr, ")\n"); + } +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); +#endif + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* count tokens shifted since error; after three, turn off error status. */ + if (yyerrstatus) yyerrstatus--; + + yystate = yyn; + goto yynewstate; + +/* Do the default action for the current state. */ +yydefault: + + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + +/* Do a reduction. yyn is the number of a rule to reduce with. */ +yyreduce: + yylen = yyr2[yyn]; + if (yylen > 0) + yyval = yyvsp[1-yylen]; /* implement default value of the action */ + +#if YYDEBUG != 0 + if (yydebug) + { + int i; + + fprintf (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) + fprintf (stderr, "%s ", yytname[yyrhs[i]]); + fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + + + switch (yyn) { + +case 4: +#line 158 "./nlmheader.y" +{ + check_procedure = yyvsp[0].string; + ; + break;} +case 5: +#line 162 "./nlmheader.y" +{ + nlmheader_warn ("CODESTART is not implemented; sorry", -1); + free (yyvsp[0].string); + ; + break;} +case 6: +#line 167 "./nlmheader.y" +{ + int len; + + strncpy (copyright_hdr->stamp, "CoPyRiGhT=", 10); + len = strlen (yyvsp[0].string); + 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, yyvsp[0].string, len); + copyright_hdr->copyrightMessage[len] = '\0'; + free (yyvsp[0].string); + ; + break;} +case 7: +#line 184 "./nlmheader.y" +{ + custom_file = yyvsp[0].string; + ; + break;} +case 8: +#line 188 "./nlmheader.y" +{ + /* 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 (yyvsp[-2].string); + version_hdr->day = nlmlex_get_number (yyvsp[-1].string); + version_hdr->year = nlmlex_get_number (yyvsp[0].string); + free (yyvsp[-2].string); + free (yyvsp[-1].string); + free (yyvsp[0].string); + 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); + ; + break;} +case 9: +#line 206 "./nlmheader.y" +{ + debug_info = true; + ; + break;} +case 10: +#line 210 "./nlmheader.y" +{ + int len; + + len = strlen (yyvsp[0].string); + 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, yyvsp[0].string, len); + var_hdr->descriptionText[len] = '\0'; + free (yyvsp[0].string); + ; + break;} +case 11: +#line 226 "./nlmheader.y" +{ + exit_procedure = yyvsp[0].string; + ; + break;} +case 12: +#line 230 "./nlmheader.y" +{ + symbol_prefix = NULL; + ; + break;} +case 13: +#line 234 "./nlmheader.y" +{ + export_symbols = string_list_append (export_symbols, yyvsp[0].list); + ; + break;} +case 14: +#line 238 "./nlmheader.y" +{ + fixed_hdr->flags |= nlmlex_get_number (yyvsp[0].string); + free (yyvsp[0].string); + ; + break;} +case 15: +#line 243 "./nlmheader.y" +{ + fixed_hdr->flags &=~ nlmlex_get_number (yyvsp[0].string); + free (yyvsp[0].string); + ; + break;} +case 16: +#line 248 "./nlmheader.y" +{ + map_file = ""; + full_map = true; + ; + break;} +case 17: +#line 253 "./nlmheader.y" +{ + map_file = yyvsp[0].string; + full_map = true; + ; + break;} +case 18: +#line 258 "./nlmheader.y" +{ + help_file = yyvsp[0].string; + ; + break;} +case 19: +#line 262 "./nlmheader.y" +{ + symbol_prefix = NULL; + ; + break;} +case 20: +#line 266 "./nlmheader.y" +{ + import_symbols = string_list_append (import_symbols, yyvsp[0].list); + ; + break;} +case 21: +#line 270 "./nlmheader.y" +{ + input_files = string_list_append (input_files, yyvsp[0].list); + ; + break;} +case 22: +#line 274 "./nlmheader.y" +{ + map_file = ""; + ; + break;} +case 23: +#line 278 "./nlmheader.y" +{ + map_file = yyvsp[0].string; + ; + break;} +case 24: +#line 282 "./nlmheader.y" +{ + message_file = yyvsp[0].string; + ; + break;} +case 25: +#line 286 "./nlmheader.y" +{ + modules = string_list_append (modules, yyvsp[0].list); + ; + break;} +case 26: +#line 290 "./nlmheader.y" +{ + fixed_hdr->flags |= 0x2; + ; + break;} +case 27: +#line 294 "./nlmheader.y" +{ + fixed_hdr->flags |= 0x10; + ; + break;} +case 28: +#line 298 "./nlmheader.y" +{ + if (output_file == NULL) + output_file = yyvsp[0].string; + else + nlmheader_warn ("ignoring duplicate OUTPUT statement", -1); + ; + break;} +case 29: +#line 305 "./nlmheader.y" +{ + fixed_hdr->flags |= 0x8; + ; + break;} +case 30: +#line 309 "./nlmheader.y" +{ + fixed_hdr->flags |= 0x1; + ; + break;} +case 31: +#line 313 "./nlmheader.y" +{ + int len; + + len = strlen (yyvsp[0].string); + 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, yyvsp[0].string, len); + var_hdr->screenName[NLM_MAX_SCREEN_NAME_LENGTH] = '\0'; + free (yyvsp[0].string); + ; + break;} +case 32: +#line 329 "./nlmheader.y" +{ + sharelib_file = yyvsp[0].string; + ; + break;} +case 33: +#line 333 "./nlmheader.y" +{ + var_hdr->stackSize = nlmlex_get_number (yyvsp[0].string); + free (yyvsp[0].string); + ; + break;} +case 34: +#line 338 "./nlmheader.y" +{ + start_procedure = yyvsp[0].string; + ; + break;} +case 35: +#line 342 "./nlmheader.y" +{ + fixed_hdr->flags |= 0x4; + ; + break;} +case 36: +#line 346 "./nlmheader.y" +{ + int len; + + len = strlen (yyvsp[0].string); + 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, yyvsp[0].string, len); + var_hdr->threadName[len] = '\0'; + free (yyvsp[0].string); + ; + break;} +case 37: +#line 362 "./nlmheader.y" +{ + fixed_hdr->moduleType = nlmlex_get_number (yyvsp[0].string); + free (yyvsp[0].string); + ; + break;} +case 38: +#line 367 "./nlmheader.y" +{ + verbose = true; + ; + break;} +case 39: +#line 371 "./nlmheader.y" +{ + long val; + + strncpy (version_hdr->stamp, "VeRsIoN#", 8); + version_hdr->majorVersion = nlmlex_get_number (yyvsp[-2].string); + val = nlmlex_get_number (yyvsp[-1].string); + 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 (yyvsp[0].string); + 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 (yyvsp[-2].string); + free (yyvsp[-1].string); + free (yyvsp[0].string); + ; + break;} +case 40: +#line 395 "./nlmheader.y" +{ + long val; + + strncpy (version_hdr->stamp, "VeRsIoN#", 8); + version_hdr->majorVersion = nlmlex_get_number (yyvsp[-1].string); + val = nlmlex_get_number (yyvsp[0].string); + 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 (yyvsp[-1].string); + free (yyvsp[0].string); + ; + break;} +case 41: +#line 411 "./nlmheader.y" +{ + rpc_file = yyvsp[0].string; + ; + break;} +case 42: +#line 420 "./nlmheader.y" +{ + yyval.list = NULL; + ; + break;} +case 43: +#line 424 "./nlmheader.y" +{ + yyval.list = yyvsp[0].list; + ; + break;} +case 44: +#line 435 "./nlmheader.y" +{ + yyval.list = string_list_cons (yyvsp[0].string, NULL); + ; + break;} +case 45: +#line 439 "./nlmheader.y" +{ + yyval.list = NULL; + ; + break;} +case 46: +#line 443 "./nlmheader.y" +{ + yyval.list = string_list_append1 (yyvsp[-1].list, yyvsp[0].string); + ; + break;} +case 47: +#line 447 "./nlmheader.y" +{ + yyval.list = yyvsp[-1].list; + ; + break;} +case 48: +#line 456 "./nlmheader.y" +{ + if (symbol_prefix != NULL) + free (symbol_prefix); + symbol_prefix = yyvsp[-1].string; + ; + break;} +case 49: +#line 467 "./nlmheader.y" +{ + if (symbol_prefix == NULL) + yyval.string = yyvsp[0].string; + else + { + yyval.string = xmalloc (strlen (symbol_prefix) + strlen (yyvsp[0].string) + 2); + sprintf (yyval.string, "%s@%s", symbol_prefix, yyvsp[0].string); + free (yyvsp[0].string); + } + ; + break;} +case 50: +#line 483 "./nlmheader.y" +{ + yyval.list = NULL; + ; + break;} +case 51: +#line 487 "./nlmheader.y" +{ + yyval.list = string_list_cons (yyvsp[-1].string, yyvsp[0].list); + ; + break;} +} + /* the action file gets copied in in place of this dollarsign */ +#line 487 "/usr/unsupported/share/bison.simple" + + yyvsp -= yylen; + yyssp -= yylen; +#ifdef YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + +#ifdef YYLSP_NEEDED + yylsp++; + if (yylen == 0) + { + yylsp->first_line = yylloc.first_line; + yylsp->first_column = yylloc.first_column; + yylsp->last_line = (yylsp-1)->last_line; + yylsp->last_column = (yylsp-1)->last_column; + yylsp->text = 0; + } + else + { + yylsp->last_line = (yylsp+yylen-1)->last_line; + yylsp->last_column = (yylsp+yylen-1)->last_column; + } +#endif + + /* Now "shift" the result of the reduction. + Determine what state that goes to, + based on the state we popped back to + and the rule number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + +yyerrlab: /* here on detecting error */ + + if (! yyerrstatus) + /* If not already recovering from an error, report this error. */ + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + int size = 0; + char *msg; + int x, count; + + count = 0; + /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + size += strlen(yytname[x]) + 15, count++; + msg = (char *) malloc(size + 15); + if (msg != 0) + { + strcpy(msg, "parse error"); + + if (count < 5) + { + count = 0; + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + { + strcat(msg, count == 0 ? ", expecting `" : " or `"); + strcat(msg, yytname[x]); + strcat(msg, "'"); + count++; + } + } + yyerror(msg); + free(msg); + } + else + yyerror ("parse error; also virtual memory exceeded"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror("parse error"); + } + + goto yyerrlab1; +yyerrlab1: /* here on error raised explicitly by an action */ + + if (yyerrstatus == 3) + { + /* if just tried and failed to reuse lookahead token after an error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); +#endif + + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token + after shifting the error token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + +yyerrdefault: /* current state does not do anything special for the error token. */ + +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ + if (yyn) goto yydefault; +#endif + +yyerrpop: /* pop the current state because it cannot handle the error token */ + + if (yyssp == yyss) YYABORT; + yyvsp--; + yystate = *--yyssp; +#ifdef YYLSP_NEEDED + yylsp--; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "Error: state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + +yyerrhandle: + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting error token, "); +#endif + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; +} +#line 492 "./nlmheader.y" + + +/* 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", VERSION }, + { "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 + { + 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/gnu/dist/binutils/nlmheader.y b/gnu/dist/binutils/nlmheader.y new file mode 100644 index 00000000000..4a92dbfdc5a --- /dev/null +++ b/gnu/dist/binutils/nlmheader.y @@ -0,0 +1,978 @@ +%{/* nlmheader.y - parse NLM header specification keywords. + 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>. + + 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 VERSION 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; + } + | VERSION 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); + } + | VERSION 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", VERSION }, + { "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 + { + 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/gnu/dist/binutils/nm.1 b/gnu/dist/binutils/nm.1 new file mode 100644 index 00000000000..c2ad99e559a --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/nm.c b/gnu/dist/binutils/nm.c new file mode 100644 index 00000000000..1f5d1c756b2 --- /dev/null +++ b/gnu/dist/binutils/nm.c @@ -0,0 +1,1539 @@ +/* nm.c -- Describe symbol table of a rel file. + Copyright 1991, 92, 93, 94, 95, 96, 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. */ + +#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"; + +/* IMPORT */ +extern char *program_name; +extern char *target; + +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@prep.ai.mit.edu\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; + + 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) + { + extern char **environ; + 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); + last_arfile = arfile; + } + + if (last_arfile != NULL) + bfd_close (last_arfile); +} + +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); + + 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; + 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)) + { + printf ("No symbols in \"%s\".\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 bfd *cache_bfd; + 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 != 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)); + cache_bfd = abfd; + } + + if (bfd_is_und_section (bfd_get_section (sym))) + { + static bfd *cache_rel_bfd; + static asection **secs; + static arelent ***relocs; + static long *relcount; + unsigned int seccount, 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. */ + + seccount = bfd_count_sections (abfd); + + if (abfd != 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; + + 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); + cache_rel_bfd = abfd; + } + + symname = bfd_asymbol_name (sym); + for (i = 0; i < seccount; i++) + { + unsigned int 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/gnu/dist/binutils/not-ranlib.c b/gnu/dist/binutils/not-ranlib.c new file mode 100644 index 00000000000..afb9ceb3d67 --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/not-strip.c b/gnu/dist/binutils/not-strip.c new file mode 100644 index 00000000000..98093ce391a --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/objcopy.1 b/gnu/dist/binutils/objcopy.1 new file mode 100644 index 00000000000..d3b8bb37256 --- /dev/null +++ b/gnu/dist/binutils/objcopy.1 @@ -0,0 +1,292 @@ +.\" Copyright (c) 1991, 93, 94, 95, 96, 1997 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 "[\|" \-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 "[\|" \-\-adjust\-start=\fIincr\fR "\|]" +.RB "[\|" \-\-adjust\-vma=\fIincr\fR "\|]" +.RB "[\|" \-\-adjust\-section\-vma=\fIsection{=,+,-}val\fR "\|]" +.RB "[\|" \-\-adjust\-warnings\fR "\|]" +.RB "[\|" \-\-no\-adjust\-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, and may be combined with strip options +other than \fB\-K\fR. +.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 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 virtual 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\-\-adjust\-start=\fIincr +Adjust the start address by adding \fIincr\fP. Not all object file +formats support setting the start address. +.TP +.B \fB\-\-adjust\-vma=\fIincr +Adjust 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\-\-adjust\-section\-vma=\fIsection{=,+,-}val +Set or adjust the 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\-\-adjust\-vma\fP, above. If \fIsection\fP does not exist +in the input file, a warning will be issued, unless +\fB\-\-no\-adjust\-warnings\fP is used. +.TP +.B \fB\-\-adjust\-warnings +If \fB\-\-adjust\-section\-vma\fP is used, and the named section does +not exist, issue a warning. This is the default. +.TP +.B \fB\-\-no\-adjust\-warnings +Do not issue a warning if \fB\-\-adjust\-section\-vma\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 +@code{--change-leading-char} 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/gnu/dist/binutils/objcopy.c b/gnu/dist/binutils/objcopy.c new file mode 100644 index 00000000000..8f24e493972 --- /dev/null +++ b/gnu/dist/binutils/objcopy.c @@ -0,0 +1,2113 @@ +/* objcopy.c -- copy object file from input to output, optionally massaging it. + Copyright (C) 1991, 92, 93, 94, 95, 96, 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. */ + +#include "bfd.h" +#include "progress.h" +#include "bucomm.h" +#include "getopt.h" +#include "libiberty.h" +#include "budbg.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 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_vma PARAMS ((const PTR, const PTR)); +static void add_strip_symbol PARAMS ((const char *)); +static boolean is_strip_symbol PARAMS ((const char *)); +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 simple_copy PARAMS ((const char *, const char *)); +static int smart_rename PARAMS ((const char *, const char *)); +static void make_same_dates PARAMS ((const char *, const char *)); +static int strip_main PARAMS ((int, char **)); +static int copy_main PARAMS ((int, char **)); + +#define 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 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; + +/* Structure used to hold lists of sections and actions to take. */ + +struct section_list +{ + /* Next section to adjust. */ + struct section_list *next; + /* Section name. */ + const char *name; + /* Whether this entry was used. */ + boolean used; + /* Whether to remove this section. */ + boolean remove; + /* Whether to adjust or set VMA. */ + enum { ignore_vma, adjust_vma, set_vma } adjust; + /* Amount to adjust by or set to. */ + bfd_vma val; + /* Whether to set the section flags. */ + boolean set_flags; + /* What to set the section flags to. */ + flagword flags; +}; + +static struct section_list *adjust_sections; +static boolean sections_removed; + +/* Adjustments to the start address. */ +static bfd_vma adjust_start = 0; +static boolean set_start_set = false; +static bfd_vma set_start; + +/* Adjustments to section VMA's. */ +static bfd_vma adjust_section_vma = 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; + +/* 150 isn't special; it's just an arbitrary non-ASCII char value. */ + +#define OPTION_ADD_SECTION 150 +#define OPTION_ADJUST_START (OPTION_ADD_SECTION + 1) +#define OPTION_ADJUST_VMA (OPTION_ADJUST_START + 1) +#define OPTION_ADJUST_SECTION_VMA (OPTION_ADJUST_VMA + 1) +#define OPTION_ADJUST_WARNINGS (OPTION_ADJUST_SECTION_VMA + 1) +#define OPTION_CHANGE_LEADING_CHAR (OPTION_ADJUST_WARNINGS + 1) +#define OPTION_DEBUGGING (OPTION_CHANGE_LEADING_CHAR + 1) +#define OPTION_GAP_FILL (OPTION_DEBUGGING + 1) +#define OPTION_NO_ADJUST_WARNINGS (OPTION_GAP_FILL + 1) +#define OPTION_PAD_TO (OPTION_NO_ADJUST_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_ADJUST_START}, + {"adjust-vma", required_argument, 0, OPTION_ADJUST_VMA}, + {"adjust-section-vma", required_argument, 0, OPTION_ADJUST_SECTION_VMA}, + {"adjust-warnings", no_argument, 0, OPTION_ADJUST_WARNINGS}, + {"byte", required_argument, 0, 'b'}, + {"change-leading-char", no_argument, 0, OPTION_CHANGE_LEADING_CHAR}, + {"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_ADJUST_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'}, + {"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}, + {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] [--adjust-start=incr]\n\ + [--adjust-vma=incr] [--adjust-section-vma=section{=,+,-}val]\n\ + [--adjust-warnings] [--no-adjust-warnings]\n\ + [--set-section-flags=section=flags] [--add-section=sectionname=filename]\n\ + [--keep-symbol symbol] [-K symbol] [--strip-symbol symbol] [-N symbol]\n\ + [--change-leading-char] [--remove-leading-char] [--weaken] [--verbose]\n\ + [--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@prep.ai.mit.edu\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@prep.ai.mit.edu\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; + } + +#define PARSE_FLAG(fname,fval) if (strncmp (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); +#undef PARSE_FLAG + + s = snext; + } + while (s != NULL); + + return ret; +} + +/* Find and optionally add an entry in the adjust_sections list. */ + +static struct section_list * +find_section_list (name, add) + const char *name; + boolean add; +{ + register struct section_list *p; + + for (p = adjust_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->adjust = ignore_vma; + p->val = 0; + p->set_flags = false; + p->flags = 0; + + p->next = adjust_sections; + adjust_sections = p; + + return p; +} + +/* Make 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; +}; + +/* List of symbols to strip. */ + +static struct symlist *strip_specific_list = NULL; + +/* If this is false, we strip the symbols in strip_specific_list. + Otherwise, we keep only the symbols in the list. */ + +static boolean keep_symbols = false; + +/* If this is true, we weaken global symbols (set BSF_WEAK). */ + +static boolean weaken = false; + +/* Add a symbol to strip_specific_list. */ + +static void +add_strip_symbol (name) + const char *name; +{ + struct symlist *tmp_list; + + tmp_list = (struct symlist *) xmalloc (sizeof (struct symlist)); + tmp_list->name = name; + tmp_list->next = strip_specific_list; + strip_specific_list = tmp_list; +} + +/* See whether a symbol should be stripped or kept based on + strip_specific_list and keep_symbols. */ + +static boolean +is_strip_symbol (name) + const char *name; +{ + struct symlist *tmp_list; + + for (tmp_list = strip_specific_list; tmp_list; tmp_list = tmp_list->next) + { + if (strcmp (name, tmp_list->name) == 0) + return keep_symbols ? false : true; + } + return keep_symbols; +} + +/* 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; + 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' + || (bfd_asymbol_name (sym)[0] + == bfd_get_symbol_leading_char (abfd)))) + { + if (bfd_get_symbol_leading_char (obfd) == '\0') + bfd_asymbol_name (sym) = bfd_asymbol_name (sym) + 1; + else + { + char *n; + + n = xmalloc (strlen (bfd_asymbol_name (sym)) + 2); + n[0] = bfd_get_symbol_leading_char (obfd); + if (bfd_get_symbol_leading_char (abfd) == '\0') + strcpy (n + 1, bfd_asymbol_name (sym)); + else + strcpy (n + 1, bfd_asymbol_name (sym) + 1); + 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))) + && bfd_asymbol_name (sym)[0] == bfd_get_symbol_leading_char (abfd)) + bfd_asymbol_name (sym) = bfd_asymbol_name (sym) + 1; + + if ((flags & BSF_KEEP) != 0) /* Used in relocation. */ + 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_strip_symbol (bfd_asymbol_name (sym))) + keep = 0; + if (keep && is_strip_section (abfd, bfd_get_section (sym))) + keep = 0; + + if (keep && weaken && (flags & BSF_GLOBAL) != 0) + { + sym->flags &=~ BSF_GLOBAL; + sym->flags |= BSF_WEAK; + } + + 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; + *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; + + if (!bfd_set_format (obfd, bfd_get_format (ibfd))) + { + 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 += adjust_start; + + if (!bfd_set_start_address (obfd, start) + || !bfd_set_file_flags (obfd, + (bfd_get_file_flags (ibfd) + & bfd_applicable_file_flags (obfd)))) + { + 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))) + { + fprintf (stderr, + "Warning: Output file cannot represent architecture %s\n", + bfd_printable_arch_mach (bfd_get_arch (ibfd), + bfd_get_mach (ibfd))); + } + if (!bfd_set_format (obfd, bfd_get_format (ibfd))) + { + 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) + { + fprintf (stderr, "%s: can't create section `%s': %s\n", + program_name, padd->name, + bfd_errmsg (bfd_get_error ())); + status = 1; + return; + } + else + { + flagword flags; + + if (! bfd_set_section_size (obfd, padd->section, padd->size)) + 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)) + nonfatal (bfd_get_filename (obfd)); + + if (pset != NULL + && (pset->adjust == adjust_vma + || pset->adjust == set_vma)) + { + if (! bfd_set_section_vma (obfd, padd->section, pset->val)) + 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_vma); + + 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_vma (obfd, osections[i]) + size; + gap_stop = bfd_section_vma (obfd, osections[i + 1]); + if (gap_start < gap_stop) + { + if (! bfd_set_section_size (obfd, osections[i], + size + (gap_stop - gap_start))) + { + fprintf (stderr, "%s: Can't fill gap after %s: %s\n", + program_name, + 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 vma; + bfd_size_type size; + + vma = bfd_section_vma (obfd, osections[c - 1]); + size = bfd_section_size (obfd, osections[c - 1]); + if (vma + size < pad_to) + { + if (! bfd_set_section_size (obfd, osections[c - 1], + pad_to - vma)) + { + fprintf (stderr, "%s: Can't add padding to %s: %s\n", + program_name, + bfd_get_section_name (obfd, osections[c - 1]), + bfd_errmsg (bfd_get_error ())); + status = 1; + } + else + { + gaps[c - 1] = pad_to - (vma + size); + if (max_gap < pad_to - (vma + size)) + max_gap = pad_to - (vma + size); + } + } + } + } + + /* Symbol filtering must happen after the output sections have + been created, but before their contents are set. */ + if (strip_symbols == strip_all) + { + osympp = isympp = NULL; + symcount = 0; + } + else + { + long symsize; + PTR dhandle = NULL; + + symsize = bfd_get_symtab_upper_bound (ibfd); + if (symsize < 0) + { + nonfatal (bfd_get_filename (ibfd)); + } + + osympp = isympp = (asymbol **) xmalloc (symsize); + symcount = bfd_canonicalize_symtab (ibfd, isympp); + if (symcount < 0) + { + nonfatal (bfd_get_filename (ibfd)); + } + + if (convert_debugging) + dhandle = read_debugging_info (ibfd, isympp, symcount); + + if (strip_symbols == strip_debug + || strip_symbols == strip_unneeded + || discard_locals != locals_undef + || strip_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. */ + 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)) + 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)) + { + 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)) + { + fprintf (stderr, "%s: %s: error copying private BFD data: %s\n", + program_name, 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 (mkdir (dir, 0700) != 0) + { + 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 (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) + { + nonfatal (output_name); + } + if (!bfd_set_format (obfd, bfd_get_format (ibfd))) + { + nonfatal (bfd_get_filename (obfd)); + } + + if (bfd_check_format (this_element, bfd_object) == true) + { + copy_object (this_element, output_bfd); + } + + bfd_close (output_bfd); + + /* 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)) + { + nonfatal (bfd_get_filename (obfd)); + } + + if (!bfd_close (ibfd)) + { + 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) + { + 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) + { + 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) + { + nonfatal (output_filename); + } + + copy_object (ibfd, obfd); + + if (!bfd_close (obfd)) + { + nonfatal (output_filename); + } + + if (!bfd_close (ibfd)) + { + 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_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; + } + + if (!bfd_set_section_size (obfd, + osection, + bfd_section_size (ibfd, isection))) + { + err = "size"; + goto loser; + } + + vma = bfd_section_vma (ibfd, isection); + if (p != NULL && p->adjust == adjust_vma) + vma += p->val; + else if (p != NULL && p->adjust == set_vma) + vma = p->val; + else + vma += adjust_section_vma; + if (! bfd_set_section_vma (obfd, osection, vma)) + { + err = "vma"; + goto loser; + } + + lma = isection->lma; + if (p != NULL && p->adjust == adjust_vma) + lma += p->val; + else if (p != NULL && p->adjust == set_vma) + lma = p->val; + else + lma += adjust_section_vma; + osection->lma = lma; + + 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: + fprintf (stderr, "%s: %s: section `%s': error in %s: %s\n", + program_name, + 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; + + 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; + + if (strip_symbols == strip_all) + bfd_set_reloc (obfd, osection, (arelent **) NULL, 0); + else + { + long relsize; + + relsize = bfd_get_reloc_upper_bound (ibfd, isection); + if (relsize < 0) + { + 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) + { + nonfatal (bfd_get_filename (ibfd)); + } + bfd_set_reloc (obfd, osection, 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)) + { + nonfatal (bfd_get_filename (ibfd)); + } + + if (copy_byte >= 0) + { + filter_bytes (memhunk, &size); + /* The section has gotten smaller. */ + if (!bfd_set_section_size (obfd, osection, size)) + nonfatal (bfd_get_filename (obfd)); + } + + if (!bfd_set_section_contents (obfd, osection, memhunk, (file_ptr) 0, + size)) + { + 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_vma (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 VMA. */ + if ((*sec1)->vma > (*sec2)->vma) + return 1; + else if ((*sec1)->vma < (*sec2)->vma) + return -1; + + /* Sort sections with the same VMA 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))) + { + fprintf (stderr, "%s: can't create debugging section: %s\n", + 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)) + { + fprintf (stderr, "%s: can't set debugging section contents: %s\n", + bfd_get_filename (obfd), bfd_errmsg (bfd_get_error ())); + return false; + } + + return true; + } + + fprintf (stderr, + "%s: don't know how to write debugging information for %s\n", + bfd_get_filename (obfd), bfd_get_target (obfd)); + return false; +} + +/* 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; +} + +#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. + Assumes that TO already exists, because FROM is a temp file. + Return 0 if ok, -1 if error. */ + +static int +smart_rename (from, to) + const char *from; + const char *to; +{ + struct stat s; + int ret = 0; + + if (lstat (to, &s)) + return -1; + + /* Use rename only if TO is not a symbolic link and has + only one hard link. */ + if (!S_ISLNK (s.st_mode) && s.st_nlink == 1) + { + ret = rename (from, to); + if (ret == 0) + { + /* 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. */ + int saved = errno; + fprintf (stderr, "%s: %s: ", program_name, to); + errno = saved; + perror ("rename"); + unlink (from); + } + } + else + { + ret = simple_copy (from, to); + if (ret != 0) + { + int saved = errno; + fprintf (stderr, "%s: %s: ", program_name, to); + errno = saved; + perror ("simple_copy"); + } + unlink (from); + } + return ret; +} + +/* Set the date of the file DESTINATION to be the same as the date of + the file SOURCE. */ + +static void +make_same_dates (source, destination) + const char *source; + const char *destination; +{ + struct stat statbuf; + int result; + + if (stat (source, &statbuf) < 0) + { + fprintf (stderr, "%s: ", source); + perror ("cannot stat"); + return; + } + + { +#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) + { + fprintf (stderr, "%s: ", destination); + perror ("can not set time"); + } +} + +static int +strip_main (argc, argv) + int argc; + char *argv[]; +{ + char *input_target = NULL, *output_target = NULL; + boolean show_version = false; + boolean preserve_dates = 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': + if (! keep_symbols && strip_specific_list != NULL) + { + fprintf (stderr, "%s: Can not specify both -K and -N\n", + program_name); + strip_usage (stderr, 1); + } + keep_symbols = true; + add_strip_symbol (optarg); + break; + case 'N': + if (keep_symbols) + { + fprintf (stderr, "%s: Can not specify both -K and -N\n", + program_name); + strip_usage (stderr, 1); + } + add_strip_symbol (optarg); + 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; + char *tmpname; + + 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) + make_same_dates (argv[i], tmpname); + if (output_file == NULL) + smart_rename (tmpname, argv[i]); + 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 adjust_warn = true; + boolean preserve_dates = false; + int c; + struct section_list *p; + + while ((c = getopt_long (argc, argv, "b:i:I:K:N:s:O:d:F:R:SpgxXVv", + copy_options, (int *) 0)) != EOF) + { + switch (c) + { + case 'b': + copy_byte = atoi(optarg); + if (copy_byte < 0) + { + fprintf (stderr, "%s: byte number must be non-negative\n", + program_name); + exit (1); + } + break; + case 'i': + interleave = atoi(optarg); + if (interleave < 1) + { + fprintf(stderr, "%s: interleave must be positive\n", + program_name); + exit (1); + } + 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': + if (! keep_symbols && strip_specific_list != NULL) + { + fprintf (stderr, "%s: Can not specify both -K and -N\n", + program_name); + strip_usage (stderr, 1); + } + keep_symbols = true; + add_strip_symbol (optarg); + break; + case 'N': + if (keep_symbols) + { + fprintf (stderr, "%s: Can not specify both -K and -N\n", + program_name); + strip_usage (stderr, 1); + } + add_strip_symbol (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 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) + { + fprintf (stderr, + "%s: bad format for --add-section NAME=FILENAME\n", + program_name); + exit (1); + } + + if (stat (s + 1, &st) < 0) + { + fprintf (stderr, "%s: ", program_name); + perror (s + 1); + exit (1); + } + + 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) + { + fprintf (stderr, "%s: ", program_name); + perror (pa->filename); + exit (1); + } + if (fread (pa->contents, 1, pa->size, f) == 0 + || ferror (f)) + { + fprintf (stderr, "%s: %s: fread failed\n", + program_name, pa->filename); + exit (1); + } + fclose (f); + + pa->next = add_sections; + add_sections = pa; + } + break; + case OPTION_ADJUST_START: + adjust_start = parse_vma (optarg, "--adjust-start"); + break; + case OPTION_ADJUST_SECTION_VMA: + { + const char *s; + int len; + char *name; + + s = strchr (optarg, '='); + if (s == NULL) + { + s = strchr (optarg, '+'); + if (s == NULL) + { + s = strchr (optarg, '-'); + if (s == NULL) + { + fprintf (stderr, + "%s: bad format for --adjust-section-vma\n", + program_name); + exit (1); + } + } + } + + len = s - optarg; + name = (char *) xmalloc (len + 1); + strncpy (name, optarg, len); + name[len] = '\0'; + + p = find_section_list (name, true); + + p->val = parse_vma (s + 1, "--adjust-section-vma"); + + if (*s == '=') + p->adjust = set_vma; + else + { + p->adjust = adjust_vma; + if (*s == '-') + p->val = - p->val; + } + } + break; + case OPTION_ADJUST_VMA: + adjust_section_vma = parse_vma (optarg, "--adjust-vma"); + adjust_start = adjust_section_vma; + break; + case OPTION_ADJUST_WARNINGS: + adjust_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) + { + fprintf (stderr, "%s: warning: truncating gap-fill from 0x", + program_name); + fprintf_vma (stderr, gap_fill_vma); + fprintf (stderr, "to 0x%x\n", (unsigned int) gap_fill); + } + gap_fill_set = true; + } + break; + case OPTION_NO_ADJUST_WARNINGS: + adjust_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) + { + fprintf (stderr, "%s: bad format for --set-section-flags\n", + program_name); + exit (1); + } + + 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) + { + fprintf (stderr, "%s: byte number must be less than interleave\n", + program_name); + exit (1); + } + + 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 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) + make_same_dates (input_filename, tmpname); + smart_rename (tmpname, input_filename); + } + else + unlink (tmpname); + } + else + { + copy_file (input_filename, output_filename, input_target, output_target); + if (status == 0 && preserve_dates) + make_same_dates (input_filename, output_filename); + } + + if (adjust_warn) + { + for (p = adjust_sections; p != NULL; p = p->next) + { + if (! p->used && p->adjust != ignore_vma) + { + fprintf (stderr, "%s: warning: --adjust-section-vma %s%c0x", + program_name, p->name, + p->adjust == set_vma ? '=' : '+'); + fprintf_vma (stderr, p->val); + fprintf (stderr, " never used\n"); + } + } + } + + return 0; +} + +int +main (argc, argv) + int argc; + char *argv[]; +{ + 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/gnu/dist/binutils/objdump.1 b/gnu/dist/binutils/objdump.1 new file mode 100644 index 00000000000..6c155310bd6 --- /dev/null +++ b/gnu/dist/binutils/objdump.1 @@ -0,0 +1,402 @@ +.\" Copyright (c) 1991, 1996, 1997 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 "[\|" \-\-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 disasembling 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 \-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 +\-\-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/gnu/dist/binutils/objdump.c b/gnu/dist/binutils/objdump.c new file mode 100644 index 00000000000..2ae400205fb --- /dev/null +++ b/gnu/dist/binutils/objdump.c @@ -0,0 +1,2740 @@ +/* objdump.c -- dump information about an object file. + Copyright 1990, 91, 92, 93, 94, 95, 96, 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, 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 *, long, long, 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@prep.ai.mit.edu\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)) + { + printf ("No symbols in \"%s\".\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: %s: No symbols\n", + program_name, 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, "-"); + objdump_print_value (secaddr - vma, info, true); + } + else if (vma > secaddr) + { + (*info->fprintf_func) (info->stream, "+"); + 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, "-"); + objdump_print_value (bfd_asymbol_value (sym) - vma, info, true); + } + else if (vma > bfd_asymbol_value (sym)) + { + (*info->fprintf_func) (info->stream, "+"); + 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) + { + 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); +} + +/* 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; + char *current; +} SFILE; + +/* sprintf to a "stream" */ + +#ifdef ANSI_PROTOTYPES +static int +objdump_sprintf (SFILE *f, const char *format, ...) +{ + int n; + va_list args; + + va_start (args, format); + vsprintf (f->current, format, args); + f->current += n = strlen (f->current); + va_end (args); + return n; +} +#else +static int +objdump_sprintf (va_alist) + va_dcl +{ + int n; + SFILE *f; + const char *format; + va_list args; + + va_start (args); + f = va_arg (args, SFILE *); + format = va_arg (args, const char *); + vsprintf (f->current, format, args); + f->current += n = strlen (f->current); + va_end (args); + return n; +} +#endif + +/* 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; + long start; + long stop; + arelent ***relppp; + arelent **relppend; +{ + struct objdump_disasm_info *aux; + asection *section; + int bytes_per_line; + boolean done_dot; + int skip_addr_chars; + long 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) + { + long z; + int bytes; + 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[1000]; + SFILE sfile; + int bpc, 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.buffer = sfile.current = buf; + info->fprintf_func = (fprintf_ftype) objdump_sprintf; + info->stream = (FILE *) &sfile; + info->bytes_per_line = 0; + info->bytes_per_chunk = 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 (" "); + } + + printf ("%s", buf); + + 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; + + 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; + + 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; + } + } + + 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; + } + + if (prefix_addresses) + disassemble_bytes (&disasm_info, disassemble_fn, true, data, i, stop, + &relpp, relppend); + else + { + asymbol *sym; + long place; + + sym = find_symbol_for_address (abfd, section, section->vma + i, + true, &place); + ++place; + while (i < stop) + { + asymbol *nextsym; + long nextstop; + boolean insns; + + if (sym != NULL && bfd_asymbol_value (sym) <= section->vma + i) + disasm_info.symbol = sym; + else + disasm_info.symbol = NULL; + + 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 + && (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. Ie: we want either an exact match or a a section followed by + a number. */ + if (strncmp (stabsect_name, s->name, len) == 0 + && (s->name[len] == '\000' || isdigit (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; + + 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/gnu/dist/binutils/prdbg.c b/gnu/dist/binutils/prdbg.c new file mode 100644 index 00000000000..958cbd2c6bf --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/ranlib.1 b/gnu/dist/binutils/ranlib.1 new file mode 100644 index 00000000000..7efb5c8e850 --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/ranlib.sh b/gnu/dist/binutils/ranlib.sh new file mode 100644 index 00000000000..2b6fbc479c6 --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/rdcoff.c b/gnu/dist/binutils/rdcoff.c new file mode 100644 index 00000000000..287b3cc4b1f --- /dev/null +++ b/gnu/dist/binutils/rdcoff.c @@ -0,0 +1,889 @@ +/* stabs.c -- Parse COFF debugging information + Copyright (C) 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 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/gnu/dist/binutils/rddbg.c b/gnu/dist/binutils/rddbg.c new file mode 100644 index 00000000000..c9ee3a8af75 --- /dev/null +++ b/gnu/dist/binutils/rddbg.c @@ -0,0 +1,448 @@ +/* rddbg.c -- Read debugging information into a generic form. + Copyright (C) 1995, 96, 1997 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/gnu/dist/binutils/sanity.sh b/gnu/dist/binutils/sanity.sh new file mode 100644 index 00000000000..942cabf9ac0 --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/size.1 b/gnu/dist/binutils/size.1 new file mode 100644 index 00000000000..3b19bd25930 --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/size.c b/gnu/dist/binutils/size.c new file mode 100644 index 00000000000..b928a814ed1 --- /dev/null +++ b/gnu/dist/binutils/size.c @@ -0,0 +1,438 @@ +/* size.c -- report size of various sections of an executable file. + Copyright 1991, 92, 93, 94, 95, 96, 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. */ + +/* 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; + +/* IMPORTS */ +extern char *target; + +/* 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 void lprint_number PARAMS ((int, bfd_size_type)); +static void rprint_number PARAMS ((int, bfd_size_type)); +static void print_berkeley_format PARAMS ((bfd *)); +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@prep.ai.mit.edu\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; + + 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 void +lprint_number (width, num) + int width; + bfd_size_type num; +{ + printf ((radix == decimal ? "%-*lu\t" : + ((radix == octal) ? "%-*lo\t" : "%-*lx\t")), + width, (unsigned long) num); +} + +static void +rprint_number (width, num) + int width; + bfd_size_type num; +{ + printf ((radix == decimal ? "%*lu\t" : + ((radix == octal) ? "%*lo\t" : "%*lx\t")), + width, (unsigned long) num); +} + +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\tdata\tbss/stk\toct\thex\tfilename" : + "text\tdata\tbss/stk\tdec\thex\tfilename"); +#else + puts ((radix == octal) ? "text\tdata\tbss\toct\thex\tfilename" : + "text\tdata\tbss\tdec\thex\tfilename"); +#endif + + total = textsize + datasize + bsssize; + + lprint_number (7, textsize); + lprint_number (7, datasize); + lprint_number (7, bsssize); + printf (((radix == octal) ? "%-7lo\t%-7lx\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; + +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 ("%-12s", bfd_section_name (file, sec)); + rprint_number (8, size); + printf (" "); + rprint_number (8, bfd_section_vma (file, sec)); + printf ("\n"); + } +} + +static void +print_sysv_format (file) + bfd *file; +{ + svi_total = 0; + + printf ("%s ", bfd_get_filename (file)); + if (bfd_my_archive (file)) + printf (" (ex %s)", bfd_get_filename (bfd_my_archive (file))); + + puts (":\nsection\t\tsize\t addr"); + bfd_map_over_sections (file, sysv_internal_printer, (PTR) NULL); + + printf ("Total "); + rprint_number (8, 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/gnu/dist/binutils/srconv.c b/gnu/dist/binutils/srconv.c new file mode 100644 index 00000000000..f378edab75a --- /dev/null +++ b/gnu/dist/binutils/srconv.c @@ -0,0 +1,2028 @@ +/* srconv.c -- Sysroff conversion program + Copyright (C) 1994 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 sh; +static int h8300; +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; + +char * +xcalloc (a, b) + int a; + int b; +{ + char *r = xmalloc (a * b); + memset (r, 0, a * b); + return r; +} + +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) + { + if (sh) + size = 4; + else if (h8300) + size = 2; + } + 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 (abfd->flags & 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++; + } + } + if (sh) + un.tool = "C_SH"; + else if (h8300) + un.tool = "C_H8/300H"; + 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 (abfd->flags & 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 (abfd->arch_info->arch) + { + case bfd_arch_h8300: + hd.au = 8; + hd.si = 0; + hd.afl = 2; + hd.spcsz = 32; + hd.segsz = 0; + hd.segsh = 0; + hd.cpu = "H8300H"; + h8300 = 1; + 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"; + sh = 1; + break; + default: + abort (); + } + + if (!abfd->flags & 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 (abfd->filename); + + + 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; +{ + int 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 (abfd->flags & 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 < section->size) + { + struct IT_ob ob; + int todo = 200; /* Copy in 200 byte lumps */ + ob.spare = 0; + if (i + todo > 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; + + dsy.spare2 = 0; + 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) + { + if (sh) + dsy.reg = rname_sh[symbol->where->offset]; + else if (h8300) + dsy.reg = rname_h8300[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 = abfd->flags & 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] = abfd->flags & 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 = !(abfd->flags & EXEC_P); + sc.addr = 0; + sc.length = 0; + name = info[i].sec->name; + } + else + { + if (abfd->flags & 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; + 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/gnu/dist/binutils/stabs.c b/gnu/dist/binutils/stabs.c new file mode 100644 index 00000000000..db2df7a081e --- /dev/null +++ b/gnu/dist/binutils/stabs.c @@ -0,0 +1,5082 @@ +/* stabs.c -- Parse stabs 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 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" + +/* 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; +}; + +/* 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) + 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 '/', 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 == '/') + 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; + 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; + + 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. */ + { + 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; + + /* 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; + } + } + + 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); + /* -1 is used for the upper bound of (4 byte) "unsigned int" + and "unsigned long", and we already checked for that, so + don't need to test for it here. */ + } + else if (n3 == 0 + && n2 < 0 + && (self_subrange || n2 == -8)) + return debug_make_int_type (dhandle, - n2, true); + else if (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); + } + } + + /* 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') + { + 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 **)); +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) + || ! 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') + { + /* FIXME: I don't know how to handle the ptype != NULL case + here. */ + if (! stab_demangle_template (minfo, pp)) + 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. */ + +static boolean +stab_demangle_template (minfo, pp) + struct stab_demangle_info *minfo; + const char **pp; +{ + 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; + } + } + } + + 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); + 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); + } + free (name); + } + } + break; + + case 't': + if (! stab_demangle_template (minfo, pp)) + return false; + if (ptype != NULL) + { + debug_type t; + + /* FIXME: I really don't know how a template should be + represented in the current type system. Perhaps the + template should be demangled into a string, and the type + should be represented as a named type. However, I don't + know what the base type of the named type should be. */ + t = debug_make_void_type (minfo->dhandle); + t = debug_make_pointer_type (minfo->dhandle, t); + t = debug_name_type (minfo->dhandle, "TEMPLATE", t); + *ptype = t; + } + 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/gnu/dist/binutils/strings.1 b/gnu/dist/binutils/strings.1 new file mode 100644 index 00000000000..408de29400b --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/strings.c b/gnu/dist/binutils/strings.c new file mode 100644 index 00000000000..a5780dfd3ca --- /dev/null +++ b/gnu/dist/binutils/strings.c @@ -0,0 +1,508 @@ +/* strings -- print the strings of printable characters in files + Copyright (C) 1993, 94, 95, 96, 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. */ + +/* 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; + + 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@prep.ai.mit.edu\n"); + exit (status); +} diff --git a/gnu/dist/binutils/strip.1 b/gnu/dist/binutils/strip.1 new file mode 100644 index 00000000000..7974612194a --- /dev/null +++ b/gnu/dist/binutils/strip.1 @@ -0,0 +1,185 @@ +.\" Copyright (c) 1991, 92, 93, 94, 95, 96, 1997 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/gnu/dist/binutils/sysdump.c b/gnu/dist/binutils/sysdump.c new file mode 100644 index 00000000000..5f158e9b99e --- /dev/null +++ b/gnu/dist/binutils/sysdump.c @@ -0,0 +1,765 @@ +/* Sysroff object format dumper. + Copyright (C) 1994 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 h8300; +static int sh; +static int dump = 1; +static int segmented_p; +static int code; +static FILE *file; + +static char * +xcalloc (a, b) + int a; + int b; +{ + char *r = xmalloc (a * b); + memset (r, 0, a * b); + return r; +} + +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 = 4; + 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) + char *ptr; + int *idx; + int size; +{ + int byte = *idx / 8; + int bit = *idx % 8; + + *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); + 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); +} + +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)) + ; + } +} + +static void +object_body_list () +{ + while (getone (IT_sh_CODE)) + { + while (getone (IT_ob_CODE)) + ; + while (getone (IT_rl_CODE)) + ; + } +} + +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, ""); +} + +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, ""); +} + +static void +debug_list () +{ + tab (1, "DEBUG LIST"); + + must (IT_du_CODE); + opt (IT_dus_CODE); + program_structure (); + must (IT_dln_CODE); + + tab (-1, ""); +} + +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} + }; + + 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/gnu/dist/binutils/sysinfo.c b/gnu/dist/binutils/sysinfo.c new file mode 100644 index 00000000000..ae97bf6ffb6 --- /dev/null +++ b/gnu/dist/binutils/sysinfo.c @@ -0,0 +1,1249 @@ + +/* A Bison parser, made from ./sysinfo.y with Bison version GNU Bison version 1.24 + */ + +#define YYBISON 1 /* Identify Bison output. */ + +#define COND 258 +#define REPEAT 259 +#define TYPE 260 +#define NAME 261 +#define NUMBER 262 +#define UNIT 263 + +#line 1 "./sysinfo.y" + +#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[]= {"","*","**"}; + +#line 24 "./sysinfo.y" +typedef union { + int i; + char *s; +} YYSTYPE; + +#ifndef YYLTYPE +typedef + struct yyltype + { + int timestamp; + int first_line; + int first_column; + int last_line; + int last_column; + char *text; + } + yyltype; + +#define YYLTYPE yyltype +#endif + +#ifndef YYDEBUG +#define YYDEBUG 1 +#endif + +#include <stdio.h> + +#ifndef __cplusplus +#ifndef __STDC__ +#define const +#endif +#endif + + + +#define YYFINAL 55 +#define YYFLAG -32768 +#define YYNTBASE 11 + +#define YYTRANSLATE(x) ((unsigned)(x) <= 263 ? yytranslate[x] : 29) + +static const char yytranslate[] = { 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, + 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 2, 3, 4, 7, + 8, 9, 10 +}; + +#if YYDEBUG != 0 +static const short yyprhs[] = { 0, + 0, 1, 4, 7, 8, 9, 16, 19, 22, 25, + 26, 27, 34, 35, 42, 43, 54, 56, 57, 61, + 64, 68, 69, 70, 74, 75 +}; + +static const short yyrhs[] = { -1, + 12, 13, 0, 14, 13, 0, 0, 0, 5, 8, + 9, 15, 16, 6, 0, 21, 16, 0, 19, 16, + 0, 17, 16, 0, 0, 0, 5, 4, 8, 18, + 16, 6, 0, 0, 5, 3, 8, 20, 16, 6, + 0, 0, 5, 24, 5, 23, 25, 6, 26, 22, + 27, 6, 0, 7, 0, 0, 5, 8, 6, 0, + 9, 10, 0, 5, 8, 6, 0, 0, 0, 5, + 28, 6, 0, 0, 28, 5, 8, 8, 6, 0 +}; + +#endif + +#if YYDEBUG != 0 +static const short yyrline[] = { 0, + 38, 59, 75, 76, 79, 130, 150, 152, 153, 154, + 157, 186, 204, 217, 230, 233, 338, 340, 343, 348, + 354, 356, 359, 360, 362, 363 +}; + +static const char * const yytname[] = { "$","error","$undefined.","COND","REPEAT", +"'('","')'","TYPE","NAME","NUMBER","UNIT","top","@1","it_list","it","@2","it_field_list", +"repeat_it_field","@3","cond_it_field","@4","it_field","@5","attr_type","attr_desc", +"attr_size","attr_id","enums","enum_list","" +}; +#endif + +static const short yyr1[] = { 0, + 12, 11, 13, 13, 15, 14, 16, 16, 16, 16, + 18, 17, 20, 19, 22, 21, 23, 23, 24, 25, + 26, 26, 27, 27, 28, 28 +}; + +static const short yyr2[] = { 0, + 0, 2, 2, 0, 0, 6, 2, 2, 2, 0, + 0, 6, 0, 6, 0, 10, 1, 0, 3, 2, + 3, 0, 0, 3, 0, 5 +}; + +static const short yydefact[] = { 1, + 4, 0, 2, 4, 0, 3, 5, 10, 0, 0, + 10, 10, 10, 0, 0, 0, 0, 6, 9, 8, + 7, 13, 11, 0, 18, 10, 10, 19, 17, 0, + 0, 0, 0, 0, 14, 12, 20, 22, 0, 15, + 0, 23, 21, 25, 0, 0, 16, 0, 24, 0, + 0, 26, 0, 0, 0 +}; + +static const short yydefgoto[] = { 53, + 1, 3, 4, 8, 10, 11, 27, 12, 26, 13, + 42, 30, 17, 34, 40, 45, 46 +}; + +static const short yypact[] = {-32768, + 3, 2,-32768, 3, 4,-32768,-32768, 6, 0, 8, + 6, 6, 6, 9, 10, 11, 7,-32768,-32768,-32768, +-32768,-32768,-32768, 14, 15, 6, 6,-32768,-32768, 12, + 17, 18, -1, 19,-32768,-32768,-32768, 21, 20,-32768, + 23, 22,-32768,-32768, 24, 1,-32768, 25,-32768, 26, + 29,-32768, 31, 32,-32768 +}; + +static const short yypgoto[] = {-32768, +-32768, 33,-32768,-32768, -11,-32768,-32768,-32768,-32768,-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768 +}; + + +#define YYLAST 37 + + +static const short yytable[] = { 19, + 20, 21, 14, 15, 16, 48, 49, 2, 37, 5, + 9, 25, 7, 18, 31, 32, 22, 23, 24, 28, + 33, 29, 35, 36, 38, 39, 44, 41, 43, 47, + 54, 55, 50, 51, 52, 0, 6 +}; + +static const short yycheck[] = { 11, + 12, 13, 3, 4, 5, 5, 6, 5, 10, 8, + 5, 5, 9, 6, 26, 27, 8, 8, 8, 6, + 9, 7, 6, 6, 6, 5, 5, 8, 6, 6, + 0, 0, 8, 8, 6, -1, 4 +}; +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ +#line 3 "/usr/unsupported/share/bison.simple" + +/* Skeleton output parser for bison, + Copyright (C) 1984, 1989, 1990 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +#ifndef alloca +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not GNU C. */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) +#include <alloca.h> +#else /* not sparc */ +#if defined (MSDOS) && !defined (__TURBOC__) +#include <malloc.h> +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +#include <malloc.h> + #pragma alloca +#else /* not MSDOS, __TURBOC__, or _AIX */ +#ifdef __hpux +#ifdef __cplusplus +extern "C" { +void *alloca (unsigned int); +}; +#else /* not __cplusplus */ +void *alloca (); +#endif /* not __cplusplus */ +#endif /* __hpux */ +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc. */ +#endif /* not GNU C. */ +#endif /* alloca not defined. */ + +/* This is the parser code that is written into each bison parser + when the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +/* Note: there must be only one dollar sign in this file. + It is replaced by the list of actions, each action + as one case of the switch. */ + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT return(0) +#define YYABORT return(1) +#define YYERROR goto yyerrlab1 +/* Like YYERROR except do call yyerror. + This remains here temporarily to ease the + transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ +#define YYFAIL goto yyerrlab +#define YYRECOVERING() (!!yyerrstatus) +#define YYBACKUP(token, value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { yychar = (token), yylval = (value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { yyerror ("syntax error: cannot back up"); YYERROR; } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +#ifndef YYPURE +#define YYLEX yylex() +#endif + +#ifdef YYPURE +#ifdef YYLSP_NEEDED +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval, &yylloc) +#endif +#else /* not YYLSP_NEEDED */ +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval) +#endif +#endif /* not YYLSP_NEEDED */ +#endif + +/* If nonreentrant, generate the variables here */ + +#ifndef YYPURE + +int yychar; /* the lookahead symbol */ +YYSTYPE yylval; /* the semantic value of the */ + /* lookahead symbol */ + +#ifdef YYLSP_NEEDED +YYLTYPE yylloc; /* location data for the lookahead */ + /* symbol */ +#endif + +int yynerrs; /* number of parse errors so far */ +#endif /* not YYPURE */ + +#if YYDEBUG != 0 +int yydebug; /* nonzero means print parse trace */ +/* Since this is uninitialized, it does not stop multiple parsers + from coexisting. */ +#endif + +/* YYINITDEPTH indicates the initial size of the parser's stacks */ + +#ifndef YYINITDEPTH +#define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH is the maximum size the stacks can grow to + (effective only if the built-in stack extension method is used). */ + +#if YYMAXDEPTH == 0 +#undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 10000 +#endif + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +int yyparse (void); +#endif + +#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ +#define __yy_memcpy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT) +#else /* not GNU C or C++ */ +#ifndef __cplusplus + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (from, to, count) + char *from; + char *to; + int count; +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#else /* __cplusplus */ + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (char *from, char *to, int count) +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#endif +#endif + +#line 192 "/usr/unsupported/share/bison.simple" + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +#else +#define YYPARSE_PARAM +#define YYPARSE_PARAM_DECL +#endif + +int +yyparse(YYPARSE_PARAM) + YYPARSE_PARAM_DECL +{ + register int yystate; + register int yyn; + register short *yyssp; + register YYSTYPE *yyvsp; + int yyerrstatus; /* number of tokens to shift before error messages enabled */ + int yychar1 = 0; /* lookahead token as an internal (translated) token number */ + + short yyssa[YYINITDEPTH]; /* the state stack */ + YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ + + short *yyss = yyssa; /* refer to the stacks thru separate pointers */ + YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ + +#ifdef YYLSP_NEEDED + YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; + +#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else +#define YYPOPSTACK (yyvsp--, yyssp--) +#endif + + int yystacksize = YYINITDEPTH; + +#ifdef YYPURE + int yychar; + YYSTYPE yylval; + int yynerrs; +#ifdef YYLSP_NEEDED + YYLTYPE yylloc; +#endif +#endif + + YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ + + int yylen; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Starting parse\n"); +#endif + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss - 1; + yyvsp = yyvs; +#ifdef YYLSP_NEEDED + yylsp = yyls; +#endif + +/* Push a new state, which is found in yystate . */ +/* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. */ +yynewstate: + + *++yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Give user a chance to reallocate the stack */ + /* Use copies of these so that the &'s don't force the real ones into memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; +#ifdef YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; +#endif + + /* Get the current used size of the three stacks, in elements. */ + int size = yyssp - yyss + 1; + +#ifdef yyoverflow + /* Each stack pointer address is followed by the size of + the data in use in that stack, in bytes. */ +#ifdef YYLSP_NEEDED + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yyls1, size * sizeof (*yylsp), + &yystacksize); +#else + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yystacksize); +#endif + + yyss = yyss1; yyvs = yyvs1; +#ifdef YYLSP_NEEDED + yyls = yyls1; +#endif +#else /* no yyoverflow */ + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + { + yyerror("parser stack overflow"); + return 2; + } + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; + yyss = (short *) alloca (yystacksize * sizeof (*yyssp)); + __yy_memcpy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp)); + yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp)); + __yy_memcpy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp)); +#ifdef YYLSP_NEEDED + yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp)); + __yy_memcpy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp)); +#endif +#endif /* no yyoverflow */ + + yyssp = yyss + size - 1; + yyvsp = yyvs + size - 1; +#ifdef YYLSP_NEEDED + yylsp = yyls + size - 1; +#endif + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Stack size increased to %d\n", yystacksize); +#endif + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Entering state %d\n", yystate); +#endif + + goto yybackup; + yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Reading a token: "); +#endif + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Now at end of input.\n"); +#endif + } + else + { + yychar1 = YYTRANSLATE(yychar); + +#if YYDEBUG != 0 + if (yydebug) + { + fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise meaning + of a token, for further debugging info. */ +#ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +#endif + fprintf (stderr, ")\n"); + } +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); +#endif + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* count tokens shifted since error; after three, turn off error status. */ + if (yyerrstatus) yyerrstatus--; + + yystate = yyn; + goto yynewstate; + +/* Do the default action for the current state. */ +yydefault: + + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + +/* Do a reduction. yyn is the number of a rule to reduce with. */ +yyreduce: + yylen = yyr2[yyn]; + if (yylen > 0) + yyval = yyvsp[1-yylen]; /* implement default value of the action */ + +#if YYDEBUG != 0 + if (yydebug) + { + int i; + + fprintf (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) + fprintf (stderr, "%s ", yytname[yyrhs[i]]); + fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + + + switch (yyn) { + +case 1: +#line 38 "./sysinfo.y" +{ + 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; + } + ; + break;} +case 2: +#line 59 "./sysinfo.y" +{ + switch (writecode) { + case 'i': + case 'p': + case 'g': + case 'c': + printf("#endif\n"); + break; + case 'd': + break; + } +; + break;} +case 5: +#line 81 "./sysinfo.y" +{ + it = yyvsp[-1].s; code = yyvsp[0].i; + 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",yyvsp[-1].s); + 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",yyvsp[-1].s); + 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",yyvsp[-1].s); + 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",yyvsp[-1].s); + printf("struct IT_%s *ptr;\n", it); + printf("{\n"); + printf("itheader(\"%s\", IT_%s_CODE);\n",yyvsp[-1].s,yyvsp[-1].s); + break; + + case 't': + break; + } + + ; + break;} +case 6: +#line 131 "./sysinfo.y" +{ + 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"); + } +; + break;} +case 11: +#line 158 "./sysinfo.y" +{ + rdepth++; + switch (writecode) + { + case 'c': + if (rdepth==1) + printf("\tprintf(\"repeat %%d\\n\", %s);\n",yyvsp[0].s); + if (rdepth==2) + printf("\tprintf(\"repeat %%d\\n\", %s[n]);\n",yyvsp[0].s); + case 'i': + case 'g': + case 'o': + + if (rdepth==1) + { + printf("\t{ int n; for (n = 0; n < %s; n++) {\n", yyvsp[0].s); + } + if (rdepth == 2) { + printf("\t{ int m; for (m = 0; m < %s[n]; m++) {\n", yyvsp[0].s); + } + + break; + } + + oldrepeat = repeat; + repeat = yyvsp[0].s; + ; + break;} +case 12: +#line 188 "./sysinfo.y" +{ + repeat = oldrepeat; + oldrepeat =0; + rdepth--; + switch (writecode) + { + case 'i': + case 'g': + case 'o': + case 'c': + printf("\t}}\n"); + } + ; + break;} +case 13: +#line 205 "./sysinfo.y" +{ + switch (writecode) + { + case 'i': + case 'g': + case 'o': + case 'c': + printf("\tif (%s) {\n", yyvsp[0].s); + break; + } + ; + break;} +case 14: +#line 218 "./sysinfo.y" +{ + switch (writecode) + { + case 'i': + case 'g': + case 'o': + case 'c': + printf("\t}\n"); + } + ; + break;} +case 15: +#line 232 "./sysinfo.y" +{name = yyvsp[0].s; ; + break;} +case 16: +#line 234 "./sysinfo.y" +{ + char *desc = yyvsp[-8].s; + char *type = yyvsp[-6].s; + int size = yyvsp[-5].i; + char *id = yyvsp[-3].s; +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; + } + ; + break;} +case 17: +#line 339 "./sysinfo.y" +{ yyval.s = yyvsp[0].s; ; + break;} +case 18: +#line 340 "./sysinfo.y" +{ yyval.s = "INT";; + break;} +case 19: +#line 345 "./sysinfo.y" +{ yyval.s = yyvsp[-1].s; ; + break;} +case 20: +#line 350 "./sysinfo.y" +{ yyval.i = yyvsp[-1].i * yyvsp[0].i; ; + break;} +case 21: +#line 355 "./sysinfo.y" +{ yyval.s = yyvsp[-1].s; ; + break;} +case 22: +#line 356 "./sysinfo.y" +{ yyval.s = "dummy";; + break;} +case 26: +#line 364 "./sysinfo.y" +{ + switch (writecode) + { + case 'd': + printf("#define %s %s\n", yyvsp[-2].s,yyvsp[-1].s); + break; + case 'c': + printf("if (ptr->%s%s == %s) { tabout(); printf(\"%s\\n\");}\n", name, names[rdepth],yyvsp[-1].s,yyvsp[-2].s); + } + ; + break;} +} + /* the action file gets copied in in place of this dollarsign */ +#line 487 "/usr/unsupported/share/bison.simple" + + yyvsp -= yylen; + yyssp -= yylen; +#ifdef YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + +#ifdef YYLSP_NEEDED + yylsp++; + if (yylen == 0) + { + yylsp->first_line = yylloc.first_line; + yylsp->first_column = yylloc.first_column; + yylsp->last_line = (yylsp-1)->last_line; + yylsp->last_column = (yylsp-1)->last_column; + yylsp->text = 0; + } + else + { + yylsp->last_line = (yylsp+yylen-1)->last_line; + yylsp->last_column = (yylsp+yylen-1)->last_column; + } +#endif + + /* Now "shift" the result of the reduction. + Determine what state that goes to, + based on the state we popped back to + and the rule number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + +yyerrlab: /* here on detecting error */ + + if (! yyerrstatus) + /* If not already recovering from an error, report this error. */ + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + int size = 0; + char *msg; + int x, count; + + count = 0; + /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + size += strlen(yytname[x]) + 15, count++; + msg = (char *) malloc(size + 15); + if (msg != 0) + { + strcpy(msg, "parse error"); + + if (count < 5) + { + count = 0; + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + { + strcat(msg, count == 0 ? ", expecting `" : " or `"); + strcat(msg, yytname[x]); + strcat(msg, "'"); + count++; + } + } + yyerror(msg); + free(msg); + } + else + yyerror ("parse error; also virtual memory exceeded"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror("parse error"); + } + + goto yyerrlab1; +yyerrlab1: /* here on error raised explicitly by an action */ + + if (yyerrstatus == 3) + { + /* if just tried and failed to reuse lookahead token after an error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); +#endif + + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token + after shifting the error token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + +yyerrdefault: /* current state does not do anything special for the error token. */ + +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ + if (yyn) goto yydefault; +#endif + +yyerrpop: /* pop the current state because it cannot handle the error token */ + + if (yyssp == yyss) YYABORT; + yyvsp--; + yystate = *--yyssp; +#ifdef YYLSP_NEEDED + yylsp--; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "Error: state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + +yyerrhandle: + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting error token, "); +#endif + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; +} +#line 379 "./sysinfo.y" + +/* 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); +} diff --git a/gnu/dist/binutils/sysinfo.h b/gnu/dist/binutils/sysinfo.h new file mode 100644 index 00000000000..e8e2d25765e --- /dev/null +++ b/gnu/dist/binutils/sysinfo.h @@ -0,0 +1,13 @@ +typedef union { + int i; + char *s; +} YYSTYPE; +#define COND 258 +#define REPEAT 259 +#define TYPE 260 +#define NAME 261 +#define NUMBER 262 +#define UNIT 263 + + +extern YYSTYPE yylval; diff --git a/gnu/dist/binutils/sysinfo.y b/gnu/dist/binutils/sysinfo.y new file mode 100644 index 00000000000..0e0141aff0f --- /dev/null +++ b/gnu/dist/binutils/sysinfo.y @@ -0,0 +1,413 @@ +%{ +#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); +} diff --git a/gnu/dist/binutils/syslex.c b/gnu/dist/binutils/syslex.c new file mode 100644 index 00000000000..a32ff2f44a3 --- /dev/null +++ b/gnu/dist/binutils/syslex.c @@ -0,0 +1,1651 @@ +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header: /cvsroot/src/gnu/dist/binutils/Attic/syslex.c,v 1.1.1.1 1997/09/24 15:39:32 gwr Exp $ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include <stdio.h> + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include <stdlib.h> +#include <unistd.h> + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include <io.h> +#include <stdlib.h> +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 25 +#define YY_END_OF_BUFFER 26 +static yyconst short int yy_accept[81] = + { 0, + 0, 0, 26, 25, 7, 8, 5, 25, 1, 2, + 11, 11, 6, 3, 4, 25, 25, 25, 25, 25, + 25, 25, 0, 9, 11, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, + 13, 0, 0, 0, 0, 16, 0, 0, 0, 0, + 0, 12, 15, 0, 23, 0, 0, 0, 0, 0, + 0, 14, 18, 0, 0, 0, 0, 0, 17, 0, + 24, 0, 0, 0, 20, 22, 0, 21, 19, 0 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 4, 1, 5, 1, 1, 1, 1, 1, 6, + 7, 1, 1, 1, 1, 1, 1, 8, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 1, 10, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 11, 1, 12, 1, 1, 1, 13, 14, 15, 16, + + 17, 18, 19, 20, 21, 1, 1, 22, 1, 23, + 24, 25, 1, 26, 27, 28, 29, 30, 1, 31, + 32, 33, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[34] = + { 0, + 1, 1, 2, 1, 1, 1, 1, 3, 3, 1, + 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1 + } ; + +static yyconst short int yy_base[84] = + { 0, + 0, 0, 100, 101, 101, 101, 101, 94, 101, 101, + 26, 28, 0, 101, 101, 82, 26, 18, 74, 79, + 78, 81, 88, 101, 32, 0, 0, 76, 65, 62, + 61, 75, 20, 59, 61, 66, 58, 0, 57, 56, + 54, 63, 53, 62, 54, 101, 59, 48, 53, 46, + 59, 101, 44, 43, 101, 41, 55, 46, 53, 44, + 31, 101, 101, 39, 27, 21, 39, 19, 101, 35, + 101, 33, 26, 29, 101, 101, 28, 101, 101, 101, + 58, 61, 41 + } ; + +static yyconst short int yy_def[84] = + { 0, + 80, 1, 80, 80, 80, 80, 80, 81, 80, 80, + 80, 80, 82, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 81, 80, 80, 83, 82, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 83, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 0, + 80, 80, 80 + } ; + +static yyconst short int yy_nxt[135] = + { 0, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 4, 4, 4, 4, 4, + 19, 4, 4, 4, 4, 20, 21, 4, 4, 22, + 4, 4, 4, 25, 25, 25, 25, 32, 29, 25, + 25, 33, 44, 38, 79, 78, 30, 77, 45, 76, + 75, 74, 73, 72, 71, 70, 26, 31, 23, 23, + 23, 27, 69, 27, 68, 67, 66, 65, 64, 63, + 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, + 52, 51, 50, 49, 48, 47, 46, 43, 42, 41, + 40, 39, 24, 37, 36, 35, 34, 28, 24, 80, + + 3, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80 + } ; + +static yyconst short int yy_chk[135] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 11, 11, 12, 12, 18, 17, 25, + 25, 18, 33, 83, 77, 74, 17, 73, 33, 72, + 70, 68, 67, 66, 65, 64, 11, 17, 81, 81, + 81, 82, 61, 82, 60, 59, 58, 57, 56, 54, + 53, 51, 50, 49, 48, 47, 45, 44, 43, 42, + 41, 40, 39, 37, 36, 35, 34, 32, 31, 30, + 29, 28, 23, 22, 21, 20, 19, 16, 8, 3, + + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +char *yytext; +#line 1 "./syslex.l" +#define INITIAL 0 +#line 2 "./syslex.l" +#include "sysinfo.h" +char *word; +int number; +int unit; + +#ifndef yywrap +static int yywrap () { return 1; } +#endif +#line 424 "lex.yy.c" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include <stdlib.h> +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 11 "./syslex.l" + +#line 573 "lex.yy.c" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 81 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 101 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 12 "./syslex.l" +{ return '(';} + YY_BREAK +case 2: +YY_RULE_SETUP +#line 13 "./syslex.l" +{ return ')';} + YY_BREAK +case 3: +YY_RULE_SETUP +#line 14 "./syslex.l" +{ return '[';} + YY_BREAK +case 4: +YY_RULE_SETUP +#line 15 "./syslex.l" +{ return ']';} + YY_BREAK +case 5: +YY_RULE_SETUP +#line 16 "./syslex.l" +{ ; } + YY_BREAK +case 6: +YY_RULE_SETUP +#line 17 "./syslex.l" +{ ; } + YY_BREAK +case 7: +YY_RULE_SETUP +#line 18 "./syslex.l" +{ ; } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 19 "./syslex.l" +{ ; } + YY_BREAK +case 9: +YY_RULE_SETUP +#line 20 "./syslex.l" +{ +yylval.s = malloc(strlen (yytext)); +strcpy(yylval.s, yytext+1); +yylval.s[strlen(yylval.s)-1] = 0; + return NAME; + } + YY_BREAK +case 10: +YY_RULE_SETUP +#line 27 "./syslex.l" +{ + yylval.i = strtol(yytext,0,16); + return NUMBER; + } + YY_BREAK +case 11: +YY_RULE_SETUP +#line 32 "./syslex.l" +{ + yylval.i = atoi(yytext); + return NUMBER; + } + YY_BREAK +case 12: +YY_RULE_SETUP +#line 38 "./syslex.l" +{ yylval.i =1 ;return UNIT;} + YY_BREAK +case 13: +YY_RULE_SETUP +#line 39 "./syslex.l" +{ yylval.i = 1; return UNIT;} + YY_BREAK +case 14: +YY_RULE_SETUP +#line 40 "./syslex.l" +{ yylval.i= 8; return UNIT;} + YY_BREAK +case 15: +YY_RULE_SETUP +#line 41 "./syslex.l" +{ yylval.i = 8; return UNIT;} + YY_BREAK +case 16: +YY_RULE_SETUP +#line 43 "./syslex.l" +{ yylval.s = "INT"; return TYPE;} + YY_BREAK +case 17: +YY_RULE_SETUP +#line 44 "./syslex.l" +{ yylval.s = "BARRAY"; return TYPE;} + YY_BREAK +case 18: +YY_RULE_SETUP +#line 45 "./syslex.l" +{ yylval.s = "CHARS"; return TYPE;} + YY_BREAK +case 19: +YY_RULE_SETUP +#line 46 "./syslex.l" +{ yylval.i = 0; return NUMBER;} + YY_BREAK +case 20: +YY_RULE_SETUP +#line 47 "./syslex.l" +{ yylval.i = -4; return NUMBER;} + YY_BREAK +case 21: +YY_RULE_SETUP +#line 48 "./syslex.l" +{ yylval.i = -2; return NUMBER; } + YY_BREAK +case 22: +YY_RULE_SETUP +#line 49 "./syslex.l" +{ yylval.i = -1; return NUMBER; } + YY_BREAK +case 23: +YY_RULE_SETUP +#line 50 "./syslex.l" +{ return COND;} + YY_BREAK +case 24: +YY_RULE_SETUP +#line 51 "./syslex.l" +{ return REPEAT;} + YY_BREAK +case 25: +YY_RULE_SETUP +#line 52 "./syslex.l" +ECHO; + YY_BREAK +#line 792 "lex.yy.c" +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a singled characater, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 81 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 81 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 80); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + yytext_ptr = yy_c_buf_p; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + { + yy_c_buf_p = + yytext_ptr + YY_MORE_ADJ; + return EOF; + } + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + break; + + case EOB_ACT_LAST_MATCH: +#ifdef __cplusplus + YY_FATAL_ERROR( + "unexpected last match in yyinput()" ); +#else + YY_FATAL_ERROR( + "unexpected last match in input()" ); +#endif + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + + return c; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +extern int isatty YY_PROTO(( int )); +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *str ) +#else +YY_BUFFER_STATE yy_scan_string( str ) +yyconst char *str; +#endif + { + int len; + for ( len = 0; str[len]; ++len ) + ; + + return yy_scan_bytes( str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n - YY_MORE_ADJ; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 52 "./syslex.l" diff --git a/gnu/dist/binutils/syslex.l b/gnu/dist/binutils/syslex.l new file mode 100644 index 00000000000..a39484287a7 --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/sysroff.info b/gnu/dist/binutils/sysroff.info new file mode 100644 index 00000000000..3af001a1016 --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/testsuite/ChangeLog b/gnu/dist/binutils/testsuite/ChangeLog new file mode 100644 index 00000000000..510d0fbec1e --- /dev/null +++ b/gnu/dist/binutils/testsuite/ChangeLog @@ -0,0 +1,436 @@ +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/gnu/dist/binutils/testsuite/binutils-all/ar.exp b/gnu/dist/binutils/testsuite/binutils-all/ar.exp new file mode 100644 index 00000000000..b4f3013bdf1 --- /dev/null +++ b/gnu/dist/binutils/testsuite/binutils-all/ar.exp @@ -0,0 +1,171 @@ +# 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 {[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" + + binutils_remove tmpdir/$n1 + 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 + + binutils_remove tmpdir/$n2 + 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 + + # Some file systems truncate file names at 14 characters, which + # makes it impossible to run this test. Check for that now. + 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 + } + + binutils_remove tmpdir/artest.a + set got [binutils_run $AR "rc tmpdir/artest.a tmpdir/$n1 tmpdir/$n2"] + if ![string match "" $got] { + fail $testname + return + } + + binutils_remove tmpdir/$n1 + binutils_remove tmpdir/$n2 + + set got [binutils_run $AR "t tmpdir/artest.a"] + if ![string match "$n1*$n2" $got] { + fail $testname + return + } + + verbose -log "cd tmpdir; $AR x artest.a" + catch "exec /bin/sh -c \"cd tmpdir; $AR x artest.a\"" exec_output + set exec_output [prune_warnings $exec_output] + if ![string match "" $exec_output] { + verbose -log $exec_output + fail $testname + return + } + + if ![file exists tmpdir/$n1] { + verbose -log "tmpdir/$n1 does not exist" + fail $testname + return + } + if ![file exists tmpdir/$n2] { + verbose -log "tmpdir/$n2 does not exist" + fail $testname + return + } + + set f [open tmpdir/$n1 r] + if { [gets $f line] == -1 || $line != "first" } { + verbose -log "tmpdir/$n1 contents:" + verbose -log "$line" + close $f + fail $testname + return + } + close $f + + set f [open tmpdir/$n2 r] + if { [gets $f line] == -1 || $line != "second" } { + verbose -log "tmpdir/$n2 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 $AS $srcdir/$subdir/bintest.s tmpdir/bintest.o] { + unresolved $testname + return + } + + binutils_remove tmpdir/artest.a + + set got [binutils_run $AR "rc tmpdir/artest.a tmpdir/bintest.o"] + if ![string match "" $got] { + fail $testname + return + } + + set got [binutils_run $NM "--print-armap tmpdir/artest.a"] + 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/gnu/dist/binutils/testsuite/binutils-all/bintest.s b/gnu/dist/binutils/testsuite/binutils-all/bintest.s new file mode 100644 index 00000000000..9e006502219 --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/testsuite/binutils-all/hppa/addendbug.s b/gnu/dist/binutils/testsuite/binutils-all/hppa/addendbug.s new file mode 100644 index 00000000000..659306f0741 --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/testsuite/binutils-all/hppa/objdump.exp b/gnu/dist/binutils/testsuite/binutils-all/hppa/objdump.exp new file mode 100644 index 00000000000..e381f40998c --- /dev/null +++ b/gnu/dist/binutils/testsuite/binutils-all/hppa/objdump.exp @@ -0,0 +1,53 @@ +# 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 $AS $srcdir/$subdir/addendbug.s tmpdir/addendbug.o]} then { + return +} + +# Make sure the SOM BFD code sign extends constants in R_DATA_OVERRIDE fixups. + +set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -r tmpdir/addendbug.o"] + +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/gnu/dist/binutils/testsuite/binutils-all/nm.exp b/gnu/dist/binutils/testsuite/binutils-all/nm.exp new file mode 100644 index 00000000000..8d392e651ea --- /dev/null +++ b/gnu/dist/binutils/testsuite/binutils-all/nm.exp @@ -0,0 +1,115 @@ +# 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 {[which $NM] == 0} then { + perror "$NM does not exist" + return +} + +send_user "Version [binutil_version $NM]" + + +if {![binutils_assemble $AS $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then { + return +} + +# 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 tmpdir/bintest.o"] + +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 tmpdir/bintest.o"] + +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 tmpdir/bintest.o"] + +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/gnu/dist/binutils/testsuite/binutils-all/objcopy.exp b/gnu/dist/binutils/testsuite/binutils-all/objcopy.exp new file mode 100644 index 00000000000..168079a3ee2 --- /dev/null +++ b/gnu/dist/binutils/testsuite/binutils-all/objcopy.exp @@ -0,0 +1,420 @@ +# Copyright (C) 1994, 1995, 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 + +# Written by Ian Lance Taylor <ian@cygnus.com> + +if {[which $OBJCOPY] == 0} then { + perror "$OBJCOPY does not exist" + return +} + +send_user "Version [binutil_version $OBJCOPY]" + +if {![binutils_assemble $AS $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then { + unresolved "objcopy (simple copy)" + return +} + +# Test that objcopy does not modify a file when copying it. + +set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS tmpdir/bintest.o tmpdir/copy.o"] + +if ![string match "" $got] then { + fail "objcopy (simple copy)" +} else { + send_log "cmp tmpdir/bintest.o tmpdir/copy.o\n" + verbose "cmp tmpdir/bintest.o tmpdir/copy.o" + catch "exec cmp tmpdir/bintest.o tmpdir/copy.o" exec_output + 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 "arm-*-pe" + 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. + +set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS -O srec tmpdir/bintest.o tmpdir/copy.srec"] + +if ![string match "" $got] then { + fail "objcopy -O srec" +} else { + set file [open tmpdir/copy.srec r] + + # The first S record is fixed by the file name we are using. + gets $file line + send_log "$line\n" + verbose $line + if ![string match "S0130000746D706469722F636F70792E7372656397*" $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 tmpdir/copy.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 tmpdir/bintest.o"] +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 tmpdir/bintest.o tmpdir/copy.srec --set-start 0x7654"] + if ![string match "" $got] then { + fail "objcopy --set-start" + } else { + set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -f tmpdir/copy.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 tmpdir/bintest.o tmpdir/copy.srec --adjust-start 0x123"] + if ![string match "" $got] then { + fail "objcopy --adjust-start" + } else { + set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -f tmpdir/copy.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 tmpdir/bintest.o"] + +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 tmpdir/bintest.o tmpdir/copy.srec --adjust-vma 0x123"] + if ![string match "" $got] then { + fail "objcopy --adjust-vma" + } else { + set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -fh tmpdir/copy.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 tmpdir/bintest.o tmpdir/copy.srec $arg"] + if ![string match "" $got] then { + fail "objcopy --adjust-section-vma +" + } else { + set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -h tmpdir/copy.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 tmpdir/bintest.o tmpdir/copy.srec $argeq"] + if ![string match "" $got] then { + fail "objcopy --adjust-section-vma =" + } else { + set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -h tmpdir/copy.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 { [which $CC] == 0 } { + untested $test + return + } + + if ![binutils_compile $CC "-g -c" $srcdir/$subdir/testprog.c tmpdir/testprog.o] { + unresolved $test + return + } + + set exec_output [binutils_run $STRIP "$STRIPFLAGS tmpdir/testprog.o"] + if ![string match "" $exec_output] { + fail $test + return + } + + set exec_output [binutils_run $NM "-a $NMFLAGS tmpdir/testprog.o"] + if ![string match "No symbols in *" $exec_output] { + fail $test + return + } + + pass $test +} + +strip_test + +# Build a final executable. + +proc copy_setup { } { + global CC + global srcdir + global subdir + + if ![isnative] { + return 1 + } + + if { [which $CC] == 0 } { + return 2 + } + + if ![binutils_compile $CC "-g" $srcdir/$subdir/testprog.c tmpdir/testprog] { + return 3 + } + + set exec_output [binutils_run tmpdir/testprog ""] + if ![string match "ok" $exec_output] { + return 3 + } + + return 0 +} + +# Test copying an executable. + +proc copy_executable { prog flags test1 test2 } { + + set exec_output [binutils_run $prog "$flags tmpdir/testprog tmpdir/copyprog"] + if ![string match "" $exec_output] { + fail $test1 + fail $test2 + return + } + + set exec_output [binutils_run "cmp" "tmpdir/testprog tmpdir/copyprog"] + + 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 the system 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. + setup_xfail "*-*-*" + fail $test1 + } + + set exec_output [binutils_run tmpdir/copyprog ""] + if ![string match "ok" $exec_output] { + fail $test2 + } else { + pass $test2 + } +} + +# Test stripping an executable + +proc strip_executable { prog flags test } { + + set exec_output [binutils_run $prog "$flags tmpdir/copyprog"] + if ![string match "" $exec_output] { + fail $test + return + } + + set exec_output [binutils_run tmpdir/copyprog ""] + if ![string match "ok" $exec_output] { + fail $test + } else { + pass $test + } +} + +set test1 "simple objcopy of executable" +set test2 "run objcopy of executable" +set test3 "run stripped executable" + +switch [copy_setup] { + "1" { + # do nothing + } + "2" { + untested $test1 + untested $test2 + untested $test3 + } + "3" { + unresolved $test1 + unresolved $test2 + unresolved $test3 + } + "0" { + copy_executable "$OBJCOPY" "$OBJCOPYFLAGS" "$test1" "$test2" + strip_executable "$STRIP" "$STRIPFLAGS" "$test3" + } +} diff --git a/gnu/dist/binutils/testsuite/binutils-all/objdump.exp b/gnu/dist/binutils/testsuite/binutils-all/objdump.exp new file mode 100644 index 00000000000..0fe21db8385 --- /dev/null +++ b/gnu/dist/binutils/testsuite/binutils-all/objdump.exp @@ -0,0 +1,128 @@ +# 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 {[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|arm|convex|d10v|h8|hppa|i386|i860|i960|m32r|m68k|m88k|mips|mn10200|mn10300|ns32k|powerpc|pyramid|romp|rs6000|sh|sparc|tahoe|vax|we32k|z8k|z8001|z8002)" + +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 $AS $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then { + return +} + +# Test objdump -f + +set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -f tmpdir/bintest.o"] + +set want "tmpdir/bintest.o:\[ \]*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 tmpdir/bintest.o"] + +set want "tmpdir/bintest.o:\[ \]*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 tmpdir/bintest.o"] + +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 tmpdir/bintest.o"] + +set want "tmpdir/bintest.o:\[ \]*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 tmpdir/bintest.o"] + +set want "tmpdir/bintest.o:\[ \]*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/gnu/dist/binutils/testsuite/binutils-all/size.exp b/gnu/dist/binutils/testsuite/binutils-all/size.exp new file mode 100644 index 00000000000..5c31cce18aa --- /dev/null +++ b/gnu/dist/binutils/testsuite/binutils-all/size.exp @@ -0,0 +1,70 @@ +# 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 {[which $SIZE] == 0} then { + perror "$SIZE does not exist" + return +} + +send_user "Version [binutil_version $SIZE]" + + +if {![binutils_assemble $AS $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then { + return +} + +set dec "\[0-9\]+" +set hex "\[0-9a-fA-F\]+" + +# Test size with no arguments + +set got [binutils_run $SIZE "$SIZEFLAGS tmpdir/bintest.o"] + +set want "($dec)\[ \]+($dec)\[ \]+($dec)\[ \]+($dec)\[ \]+($hex)\[ \]+tmpdir/bintest.o" + +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 tmpdir/bintest.o"] + +set want "tmpdir/bintest.o.*(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/gnu/dist/binutils/testsuite/binutils-all/testprog.c b/gnu/dist/binutils/testsuite/binutils-all/testprog.c new file mode 100644 index 00000000000..210656b4487 --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/testsuite/config/default.exp b/gnu/dist/binutils/testsuite/config/default.exp new file mode 100644 index 00000000000..b6485568d8c --- /dev/null +++ b/gnu/dist/binutils/testsuite/config/default.exp @@ -0,0 +1,113 @@ +# 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 AS] then { + set AS [findfile $base_dir/../gas/as.new $base_dir/../gas/as.new [transform as]] +} +if ![info exists ASFLAGS] then { + set ASFLAGS "" +} + +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 ![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 { as source object } { + default_binutils_assemble $as $source $object +} + +# +# binutils_compile +# compile a file +# +proc binutils_compile { cc flags source object } { + default_binutils_compile $cc $flags $source $object +} + +# +# binutils_remove +# remove a file +# +proc binutils_remove { file } { + default_binutils_remove $file +} + +# +# add some basic error trapping. These mostly catch programming error's +# within the tests themselves +# +expect_before { + buffer_full { perror "internal buffer is full." } + "can't open '*'" { perror "Can't open test file." } +} diff --git a/gnu/dist/binutils/testsuite/config/hppa.sed b/gnu/dist/binutils/testsuite/config/hppa.sed new file mode 100644 index 00000000000..d8607d85d0c --- /dev/null +++ b/gnu/dist/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/gnu/dist/binutils/testsuite/lib/utils-lib.exp b/gnu/dist/binutils/testsuite/lib/utils-lib.exp new file mode 100644 index 00000000000..e3aa5359822 --- /dev/null +++ b/gnu/dist/binutils/testsuite/lib/utils-lib.exp @@ -0,0 +1,189 @@ +# 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 {[which $prog] == 0} then { + perror "$prog can't be run, file not found." + return "" + } + catch "exec $prog --version" tmp + # 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 "[which $prog] (no version number)\n" + } + return "[which $prog] $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 {[which $prog] == 0} then { + perror "$prog does not exist" + set binutils_run_failed 1 + return "" + } + + send_log "$prog $progargs\n" + verbose "$prog $progargs" + + # This used to be + # catch "exec $prog $progargs" exec_output + # but that would evaluate $progargs twice, which would fail if + # any arguments started with `$'. This is a dismal hack to avoid + # this problem. I tried using + # catch { exec $prog $progargs } exec_output + # but that failed because $progargs was not split into words by + # exec. I don't know if this operation can be done correctly. No + # matter how hard I try, I can not convince myself that TCL is a + # language. + regsub -all "\\$" $progargs "\\$" progq + catch "exec $prog $progq" exec_output + set exec_output [prune_warnings $exec_output] + 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 { as source object } { + global ASFLAGS + global srcdir + global host_triplet + + if {[which $as] == 0} then { + perror "$as does not exist" + return 0 + } + + if ![info exists ASFLAGS] { set ASFLAGS "" } + + # 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 | $as $ASFLAGS -o $object\n" + verbose "sed -f $srcdir/config/hppa.sed < $source | $as $ASFLAGS -o $object" + catch "exec sed -f $srcdir/config/hppa.sed < $source | $as $ASFLAGS -o $object" exec_output + } else { + send_log "$as $ASFLAGS -o $object $source\n" + verbose "$as $ASFLAGS -o $object $source" + catch "exec $as $ASFLAGS -o $object $source" exec_output + } + + set exec_output [prune_warnings $exec_output] + + if [string match "" $exec_output] then { + return 1 + } else { + send_log "$exec_output\n" + verbose "$exec_output" + perror "$source: assembly failed" + return 0 + } +} + +# +# default_binutils_compile +# compile a file +# +proc default_binutils_compile { cc flags source object } { + global CFLAGS + global srcdir + global host_triplet + + if {[which $cc] == 0} then { + perror "$cc does not exist" + return 0 + } + + if ![info exists CFLAGS] { set CFLAGS "" } + + send_log "$cc $flags $CFLAGS -o $object $source\n" + verbose "$cc $flags $CFLAGS -o $object $source" + catch "exec $cc $flags $CFLAGS -o $object $source" exec_output + + set exec_output [prune_warnings $exec_output] + + if [string match "" $exec_output] then { + return 1 + } else { + send_log "$exec_output\n" + verbose "$exec_output" + perror "$source: compilation failed" + return 0 + } +} + +# +# default_binutils_remove +# remove a file +# +proc default_binutils_remove { file } { + catch "exec rm -f $file" exec_output +} + +# This definition is taken from an unreleased version of DejaGnu. Once +# that version gets released, and has been out in the world for a few +# months at least, it may be safe to delete this copy. +if ![string length [info proc prune_warnings]] { + # + # prune_warnings -- delete various system verbosities from TEXT + # + # An example is: + # ld.so: warning: /usr/lib/libc.so.1.8.1 has older revision than expected 9 + # + # Sites with particular verbose os's may wish to override this in site.exp. + # + proc prune_warnings { text } { + # This is from sun4's. Do it for all machines for now. + # The "\\1" is to try to preserve a "\n" but only if necessary. + regsub -all "(^|\n)(ld.so: warning:\[^\n\]*\n?)+" $text "\\1" text + + # This happens when compiling on Alpha OSF/1 with cc -g -O. + regsub -all "(^|\n)(\n*uopt: Warning: file not optimized; use -g3 if both optimization and debug wanted\n?)+" $text "\\1" text + + # This happens on SunOS with cc -g -O. + regsub -all "(^|\n)(cc: Warning: -O conflicts with -g. -O turned off.\n?)+" $text "\\1" text + + # It might be tempting to get carried away and delete blank lines, etc. + # Just delete *exactly* what we're ask to, and that's it. + return $text + } +} diff --git a/gnu/dist/binutils/version.c b/gnu/dist/binutils/version.c new file mode 100644 index 00000000000..ab6b8190a31 --- /dev/null +++ b/gnu/dist/binutils/version.c @@ -0,0 +1,43 @@ +/* version.c -- binutils version information + Copyright 1991, 1996 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. */ + printf ("GNU %s %s\n", name, program_version); + printf ("Copyright 1997 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/gnu/dist/binutils/wrstabs.c b/gnu/dist/binutils/wrstabs.c new file mode 100644 index 00000000000..b771ab587a7 --- /dev/null +++ b/gnu/dist/binutils/wrstabs.c @@ -0,0 +1,2416 @@ +/* wrstabs.c -- Output stabs debugging information + Copyright (C) 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 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 (p, h->root.string); + p += strlen (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 (targindex >= *cache_alloc) + { + size_t alloc; + + alloc = *cache_alloc; + if (alloc == 0) + alloc = 10; + while (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; + 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 (*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); +} |
